Page 1 of 1

GetDesktopWindow() on dual monitor system.

Posted: Wed Sep 25, 2024 6:46 pm
by byron.hopp
When I ask for the desktop windows on my dual monitor system I get the main monitor by GetWndRect( GetDesktopWindows() ). Is there a way to the the second or n monitors as well. I am trying to display multiple dialogs across the screens for a scheduling app and need to know how far I can go to the right.

Re: GetDesktopWindow() on dual monitor system.

Posted: Thu Sep 26, 2024 3:05 am
by Antonio Linares
Dear Byron,

monitors.prg

Code: Select all | Expand

#include "FiveWin.ch"

function Main()

   EnumDisplayMonitors( { | nMonitor, hMonitor, hdcMonitor, lPrimary, aMonitorRect, aMonitorRectInfo, aWorkRect | ;
                          XBrowser( { "nMonitor" => nMonitor,;
                                      "hMonitor" => hMonitor,;
                                      "hdcMonitor" => hdcMonitor,;
                                      "lPrimary" => lPrimary,;
                                      "aMonitorRect" => aMonitorRect,;
                                      "aMonitorRectInfo" => aMonitorRectInfo,;  
                                      "aWorkRect" => aWorkRect } ), .T. } )  // .T. continue to next monitor
return nil 

#pragma BEGINDUMP

#include <windows.h>
#include <hbapi.h>
#include <hbapiitm.h>

static int iMonitorCount;

static BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData )
{
    MONITORINFOEX mi;

    if( iMonitorCount >= MAX_MONITORS ) 
    {
       return FALSE;  // Stop enumeration if we've reached the maximum
    }

    mi.cbSize = sizeof( MONITORINFOEX );
    
    if( GetMonitorInfo( hMonitor, ( LPMONITORINFO ) &mi ) )
    {
       PHB_ITEM pMonitorCount   = hb_itemPutNL( NULL, ++iMonitorCount );
       PHB_ITEM pHandleMonitor  = hb_itemPutPtr( NULL, hMonitor );
       PHB_ITEM phdcMonitor     = hb_itemPutPtr( NULL, hdcMonitor );
       PHB_ITEM prctMonitor     = hb_itemArrayNew( 4 );
       PHB_ITEM pIsPrimary      = hb_itemPutL( NULL, ( mi.dwFlags & MONITORINFOF_PRIMARY) != 0 );
       PHB_ITEM prctMonitorInfo = hb_itemArrayNew( 4 );
       PHB_ITEM prctWork        = hb_itemArrayNew( 4 );

       PHB_ITEM pMonitorLeft    = hb_itemPutNL( NULL, lprcMonitor->left );
       PHB_ITEM pMonitorTop     = hb_itemPutNL( NULL, lprcMonitor->top );
       PHB_ITEM pMonitorBottom  = hb_itemPutNL( NULL, lprcMonitor->bottom );
       PHB_ITEM pMonitorRight   = hb_itemPutNL( NULL, lprcMonitor->right );

       PHB_ITEM pMonitorInfoLeft   = hb_itemPutNL( NULL, mi.rcMonitor.left );
       PHB_ITEM pMonitorInfoTop    = hb_itemPutNL( NULL, mi.rcMonitor.top );
       PHB_ITEM pMonitorInfoBottom = hb_itemPutNL( NULL, mi.rcMonitor.bottom );
       PHB_ITEM pMonitorInfoRight  = hb_itemPutNL( NULL, mi.rcMonitor.right );

       PHB_ITEM pWorkLeft   = hb_itemPutNL( NULL, mi.rcWork.left );
       PHB_ITEM pWorkTop    = hb_itemPutNL( NULL, mi.rcWork.top );
       PHB_ITEM pWorkBottom = hb_itemPutNL( NULL, mi.rcWork.bottom );
       PHB_ITEM pWorkRight  = hb_itemPutNL( NULL, mi.rcWork.right );

       hb_itemArrayPut( prctMonitor, 1, pMonitorLeft );
       hb_itemArrayPut( prctMonitor, 2, pMonitorTop );
       hb_itemArrayPut( prctMonitor, 3, pMonitorBottom );
       hb_itemArrayPut( prctMonitor, 4, pMonitorRight );

       hb_itemArrayPut( prctMonitorInfo, 1, pMonitorInfoLeft );
       hb_itemArrayPut( prctMonitorInfo, 2, pMonitorInfoTop );
       hb_itemArrayPut( prctMonitorInfo, 3, pMonitorInfoBottom );
       hb_itemArrayPut( prctMonitorInfo, 4, pMonitorInfoRight );

       hb_itemArrayPut( prctWork, 1, pWorkLeft );
       hb_itemArrayPut( prctWork, 2, pWorkTop );
       hb_itemArrayPut( prctWork, 3, pWorkBottom );
       hb_itemArrayPut( prctWork, 4, pWorkRight );

       hb_evalBlock( ( PHB_ITEM ) dwData, pMonitorCount, pHandleMonitor, phdcMonitor, pIsPrimary, prctMonitor, 
                     prctMonitorInfo, prctWork, NULL );

       hb_itemRelease( pMonitorLeft );
       hb_itemRelease( pMonitorTop );
       hb_itemRelease( pMonitorBottom );
       hb_itemRelease( pMonitorRight );

       hb_itemRelease( pMonitorInfoLeft );
       hb_itemRelease( pMonitorInfoTop );
       hb_itemRelease( pMonitorInfoBottom );
       hb_itemRelease( pMonitorInfoRight );

       hb_itemRelease( pWorkLeft );
       hb_itemRelease( pWorkTop );
       hb_itemRelease( pWorkBottom );
       hb_itemRelease( pWorkRight );

       hb_itemRelease( prctWork );
       hb_itemRelease( prctMonitorInfo );
       hb_itemRelease( prctMonitor );
       hb_itemRelease( pIsPrimary );
       hb_itemRelease( phdcMonitor );
       hb_itemRelease( pHandleMonitor );
       hb_itemRelease( pMonitorCount );
    }
    
    return hb_parl( -1 );  // .T. continue enumeration
}

HB_FUNC( ENUMDISPLAYMONITORS )
{
   iMonitorCount = 0;
   hb_retl( EnumDisplayMonitors( NULL, NULL, MonitorEnumProc, ( LPARAM ) hb_param( 1, HB_IT_BLOCK ) ) );    
}

#pragma ENDDUMP

Re: GetDesktopWindow() on dual monitor system.

Posted: Thu Sep 26, 2024 3:30 am
by byron.hopp
Mr. Rao told me to try FW_VirtualScreen(), but I don't know if it works for more than two screens (I only have 2) . However I cannot successfully link my app with EnumDisplayMonitors() the linker can't find it. I did find several mentions of this function when googling the WinAPI for multiple monitors.

Re: GetDesktopWindow() on dual monitor system.

Posted: Thu Sep 26, 2024 4:11 am
by Antonio Linares
I have edited my previous answer with an example to test, thanks

Re: GetDesktopWindow() on dual monitor system.

Posted: Thu Sep 26, 2024 4:17 am
by Antonio Linares
Minor editing again on the example code

Re: GetDesktopWindow() on dual monitor system.

Posted: Thu Sep 26, 2024 4:19 am
by Antonio Linares
Final minor editing :-)

Re: GetDesktopWindow() on dual monitor system.

Posted: Thu Sep 26, 2024 4:22 am
by Antonio Linares
Please let me know if it helps you or if you need something else.

Re: GetDesktopWindow() on dual monitor system.

Posted: Thu Sep 26, 2024 5:26 pm
by byron.hopp
Works perfectly. Do you know the difference between aWorkRect vs (aMonitorRectInfo or aMonitorRect), this is more like what I saw on line I just had no idea how to implement the code. Thanks,

Re: GetDesktopWindow() on dual monitor system.

Posted: Mon Jan 06, 2025 10:27 pm
by byron.hopp
I have this example of monitor information, but I don't know how to use it. Currently it displays and xbrowse window, how do I just get the information in an array so I can utilize it later. Don't need the xbrowse dialog.

Function Antonio()
EnumDisplayMonitors( { | nMonitor, hMonitor, hdcMonitor, lPrimary, aMonitorRect, aMonitorRectInfo, aWorkRect | XBrowser(
{ "nMonitor" => nMonitor,;
"hMonitor" => hMonitor,;
"hdcMonitor" => hdcMonitor,;
"lPrimary" => lPrimary,;
"aMonitorRect" => aMonitorRect,;
"aMonitorRectInfo" => aMonitorRectInfo,;
"aWorkRect" => aWorkRect } ), .T. } ) // .T. continue to next monitor
return nil

Re: GetDesktopWindow() on dual monitor system.

Posted: Tue Jan 07, 2025 12:10 am
by byron.hopp
I think I got it, I needed to refer to the hash variables h["nMonitor"] instead of h:nMonitor. Now I got my numbers. And life is good again.
Thanks again Antonio.

Re: GetDesktopWindow() on dual monitor system.

Posted: Tue Jan 07, 2025 6:38 am
by Antonio Linares
very good :)