Announcement

Collapse
No announcement yet.

Two monitors

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Two monitors

    I use two monitors. My program should be displayed on the monitor each time it is called up, where it was last executed.

    Which APIs can I use here? Is there a sample program?

  • #2
    I am not sure where this code came from but it looks like Gary's style

    Frank
    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "Win32API.inc"
    
    GLOBAL hDlg AS DWORD
    
    FUNCTION PBMAIN() AS LONG
      DIALOG NEW PIXELS, 0, "Test Code",300,300,200,200, %WS_OVERLAPPEDWINDOW TO hDlg
      CONTROL ADD LABEL, hDlg, 100,"Move/resize, then close the window. When restarted, it will reopen to the saved size/position.", 40,10,150,60
      DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    
    CALLBACK FUNCTION DlgProc() AS LONG
      SELECT CASE CB.MSG
      CASE %WM_INITDIALOG
        Settings_INI "get"
      CASE %WM_DESTROY
        Settings_INI "save"
      END SELECT
    END FUNCTION
    
    SUB Settings_INI(Task$)
      LOCAL x AS LONG, y AS LONG, iResult&
      LOCAL xResult AS ASCIIZ*%MAX_PATH, yResult AS ASCIIZ*%MAX_PATH
      LOCAL temp AS ASCIIZ*%MAX_PATH, INIFileName AS ASCIIZ*%MAX_PATH
    
      'defines file name (any file name will work)
      INIFileName = EXE.PATH$ + "myapp.ini"
    
      IF Task$ = "get" THEN
        'get dialog top/left from INI file and use to set Dialog location
        GetPrivateProfileString "All", "Left", "300", xResult, %MAX_PATH, INIFileName
        GetPrivateProfileString "All", "Top", "300", yResult, %MAX_PATH, INIFileName
        DIALOG SET LOC hDlg, VAL(xResult$), VAL(yResult$)   'left/top
    
        'get dialog width/height from INI file and use to set Dialog size
        GetPrivateProfileString "All", "Width", "300", xResult, %MAX_PATH, INIFileName
        GetPrivateProfileString "All", "Height", "300", yResult, %MAX_PATH, INIFileName
        DIALOG SET SIZE hDlg,VAL(xResult$), VAL(yResult$)   'width/height
      END IF
    
      IF Task$ = "save" THEN
        'save dialog size/location unless minimized or maximized
        IF ISFALSE(IsIconic(hDlg) OR IsZoomed(hDlg)) THEN
          DIALOG GET LOC hDlg TO x,y
          WritePrivateProfileString "All", "Left", STR$(x), INIFileName
          WritePrivateProfileString "All", "Top", STR$(y), INIFileName
          DIALOG GET SIZE hDlg TO x,y
          WritePrivateProfileString "All", "Width", STR$(x), INIFileName
          WritePrivateProfileString "All", "Height", STR$(y), INIFileName
        END IF
      END IF
    END SUB

    Comment


    • #3
      > INIFileName = EXE.PATH$ + "myapp.ini"

      It's not a good idea to put writable files etc in the executable directory unless you are working with a "portable" application that doesn't reside in "Program Files"

      It's better practice generally to either use a directory off Appdata or the Registry.

      Comment


      • #4
        Frank, it is a nice solution.

        But when the second monitor is unplugged, the program starts in the invisible area.
        Therefore, I suspect that the display ID plays a role. I have no approach to display management.

        Comment


        • #5
          Use GetSystemmetrics(%SM_CMONITORS), returns number of connected monitors.
          Of course only works if monitor physically is unplugged, not if you only switch it off...
          Regards,
          Peter

          Comment


          • #6
            Originally posted by Bernhard Fomm View Post
            Frank, it is a nice solution.

            But when the second monitor is unplugged, the program starts in the invisible area.
            Therefore, I suspect that the display ID plays a role. I have no approach to display management.
            That's to be expected. You told it to start at co-ordinates outside of the first monitor.

            Comment


            • #7
              Originally posted by Peter Lameijn View Post
              Use GetSystemmetrics(%SM_CMONITORS), returns number of connected monitors.
              Of course only works if monitor physically is unplugged, not if you only switch it off...
              And it will only help if you are using the second monitor as an extended desktop, not a a clone

              It would be better to test whether the stored values fall within the bounds of
              x between GetSystemMetrics(%SM_XVIRTUALSCREEN) and GetSystemMetrics(%SM_XVIRTUALSCREEN + (GetSystemMetrics(%SM_CXVIRTUALSCREEN)
              and
              y between GetSystemMetrics(%SM_YVIRTUALSCREEN) and GetSystemMetrics(%SM_YVIRTUALSCREEN+ GetSystemMetrics((%SM_CYVIRTUALSCREEN)

              (Of course, that still does not guaranteed that the application is visible because those numbers give the bounding coordinates of the attached monitors extended desktop. Whether any particular co-ordinates are visible depends on how the monitors are configured relative to each other)
              Last edited by Stuart McLachlan; 16 Jul 2020, 06:06 PM. Reason: Edited to clarify x/y cordinates

              Comment


              • #8
                Then i know how many monitors are available.
                But how do I switch my program to the different monitors?
                I must to collect all monitor IDs first? Then the PB program must be displayed on the desired monitor.

                Comment


                • #9
                  Maybe this?
                  https://docs.microsoft.com/en-us/win...tors-functions

                  Comment


                  • #10
                    With:
                    Code:
                    X = GetSystemmetrics(%SM_CXVIRTUALSCREEN)
                    y = GetSystemmetrics(%SM_CYVIRTUALSCREEN)
                    you can get the virtual screen size. If the stored position is outside that, it obviously won't show.
                    Regards,
                    Peter

                    Comment


                    • #11
                      It should also work with three monitors.

                      Comment


                      • #12
                        I think I already use the GetSystemmetrics() to display a menu in the system tray.

                        I try it. Thanks in advance!

                        Comment


                        • #13
                          It does. If position is not valid, switch to primary display
                          Regards,
                          Peter

                          Comment


                          • #14
                            Originally posted by Bernhard Fomm View Post
                            It should also work with three monitors.
                            %SM_CXVIRTUALSCREEN etc will work with any number of monitors, including where %SM_XVIRTUALSCREEN is less than 0 (i.e. where the central monitor is the primary)

                            Comment


                            • #15
                              I have an idea of what was said. But I feel very helpless right now.

                              Let's see what my brain makes of it overnight.

                              Comment


                              • #16
                                Originally posted by Peter Lameijn View Post
                                With:
                                Code:
                                X = GetSystemmetrics(%SM_CXVIRTUALSCREEN)
                                y = GetSystemmetrics(%SM_CYVIRTUALSCREEN)
                                you can get the virtual screen size. If the stored position is outside that, it obviously won't show.
                                Note that that does not give you the co-ordinates of the virtual screen, just its width/height. The origin may not be (0,0).
                                See Post #7 (edited)

                                Comment


                                • #17
                                  Something like:

                                  Code:
                                  If XPos < GetSystemmetrics(%SM_CXVIRTUALSCREEN) And YPos < GetSystemmetrics(%SM_CYVIRTUALSCREEN) Then
                                    Dialog New, %HWND_DESKTOP, "Test",Xpos,YPos,500,200, %WS_OverlappedWindow To hDlg
                                  Else
                                    Dialog New, %HWND_DESKTOP, "Test",Xpos,YPos,,, %WS_OverlappedWindow To hDlg   'Center on main screen
                                  End If
                                  Where XPos/YPos is the saved previous position
                                  Only true if monitors are neatly aligned from left to right. If not, there is some more work to be done...
                                  Regards,
                                  Peter

                                  Comment


                                  • #18
                                    From AfxWin.inc in my include files:

                                    Code:
                                    ' ========================================================================================
                                    ' If you use dual (or even triple/quad) displays then you have undoubtedly encountered the
                                    ' following situation: You change the physical order of your displays, or otherwise
                                    ' reconfigure the logical ordering using your display software. This sometimes has the
                                    ' side-effect of changing your desktop coordinates from zero-based to negative starting
                                    ' coordinates (i.e. the top-left coordinate of your desktop changes from 0,0 to -1024,-768).
                                    ' This effects many Windows programs which restore their last on-screen position whenever
                                    ' they are started. Should the user reorder their display configuration this can sometimes
                                    ' result in a Windows program subsequently starting in an off-screen position (i.e. at a
                                    ' location that used to be visible) - and is now effectively invisible, preventing the
                                    ' user from closing it down or otherwise moving it back on-screen.
                                    ' The ForceVisibleDisplay function can be called at program start-time right after the
                                    ' main window has been created and positioned 'on-screen'. Should the window be positioned
                                    ' in an off-screen position, it is forced back onto the nearest display to its last
                                    ' position. The user will be unaware this is happening and won't even realise to thank you
                                    ' for keeping their user-interface visible, even though they changed their display
                                    ' settings.
                                    ' Source: http://www.catch22.net/tuts/tips2
                                    ' ========================================================================================
                                    SUB AfxForceVisibleDisplay (BYVAL hwnd AS DWORD)
                                    
                                       ' // Check if the specified window-recrangle is visible on any display
                                       LOCAL rc AS RECT
                                       GetWindowRect(hwnd, rc)
                                       IF MonitorFromRect(rc, %MONITOR_DEFAULTTONULL) <> %NULL THEN EXIT SUB
                                    
                                       LOCAL hMonitor AS DWORD
                                       LOCAL mi AS MONITORINFO
                                       mi.cbSize = SIZEOF(mi)
                                       ' // Find the nearest display to the rectangle
                                       hMonitor = MonitorFromRect(rc, %MONITOR_DEFAULTTONEAREST)
                                       GetMonitorInfo(hMonitor, mi)
                                       ' // Center window rectangle
                                       rc.left = mi.rcWork.left + ((mi.rcWork.right - mi.rcWork.left) - (rc.right-rc.left)) \ 2
                                       rc.top = mi.rcWork.top + ((mi.rcWork.bottom - mi.rcWork.top) - (rc.bottom-rc.top)) \ 2
                                       SetWindowPos(hwnd, 0, rc.left, rc.top, 0, 0, %SWP_NOACTIVATE OR %SWP_NOZORDER OR %SWP_NOSIZE)
                                    
                                    END SUB
                                    ' ========================================================================================
                                    Forum: http://www.jose.it-berater.org/smfforum/index.php

                                    Comment


                                    • #19
                                      Originally posted by José Roca View Post
                                      New URL for the above:
                                      http://www.catch22.net/tuts/win32/ti...tricks-part-2#


                                      Comment


                                      • #20
                                        Great!

                                        Comment

                                        Working...
                                        X