Announcement

Collapse
No announcement yet.

DOSBOX location control from PBWIN

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

  • BOB MECHLER
    replied
    Thanks Pierre!

    Bob Mechler

    Leave a comment:


  • Pierre Bellisle
    replied
    Both previous program are updated
    to react corectly even if second monitor
    is made the main monitor via Windows monitor property options.

    Pierre

    Leave a comment:


  • Pierre Bellisle
    replied
    Create a centered dialog on second monitor

    Also,

    For the fun of it, following code will create a dialog that will
    start centered on the second monitor, if any.

    Pierre

    Code:
    #COMPILE EXE '#Win 8.03#
    #DIM ALL
    #INCLUDE "Win32Api.inc" '#2005-01-27#
     
    %Label1       = 201
     
    GLOBAL hDlg AS DWORD
     
    %DISPLAY_DEVICE_MODESPRUNED = &h8000000
    %DISPLAY_DEVICE_REMOVABLE   = &h20
     
    TYPE MonitorInfoAddr
      ArrayAddress AS DWORD
      MonitorCount AS DWORD
    END TYPE
     
    TYPE MonitorInfoData
      hMonitor   AS DWORD
      hdcMonitor AS DWORD
      Clip       AS RECT
    END TYPE
     
    TYPE DISPLAY_DEVICE_EX 'Old DISPLAY_DEVICE in Win32api
      cb           AS DWORD
      DeviceName   AS ASCIIZ * 32
      DeviceString AS ASCIIZ * 128
      StateFlags   AS DWORD
      DeviceID     AS ASCIIZ * 128
      DeviceKey    AS ASCIIZ * 128
    END TYPE
    '______________________________________________________________________________
     
    FUNCTION MonInfoEnumProc(BYVAL hMonitor AS DWORD, BYVAL hdcMonitor AS DWORD, _
                             BYREF Clip AS RECT, BYVAL dwData AS DWORD) AS LONG
     LOCAL  pMonitorDataAddr AS MonitorInfoAddr POINTER
     LOCAL  Looper           AS LONG
     STATIC LastMonitor      AS DWORD
     
     REDIM PRESERVE MonitorData(0 TO LastMonitor) AS STATIC MonitorInfoData
     
     'This FOR/NEXT is needed to reset data only if EnumDisplayMonitors is called more than once
     FOR Looper = 0 TO LastMonitor
       IF MonitorData(Looper).hMonitor = hMonitor THEN
         LastMonitor = 0
         REDIM PRESERVE MonitorData(0 TO LastMonitor) AS STATIC MonitorInfoData
         EXIT FOR
       END IF
     NEXT
     
     MonitorData(LastMonitor).hMonitor = hMonitor
     MonitorData(LastMonitor).hdcMonitor = hdcMonitor
     MonitorData(LastMonitor).Clip = Clip
     
     pMonitorDataAddr = dwData
     @pMonitorDataAddr.MonitorCount = LastMonitor + 1
     @pMonitorDataAddr.ArrayAddress = VARPTR(MonitorData(0))
     
     INCR LastMonitor
     
     FUNCTION = %TRUE
     
    END FUNCTION
    '______________________________________________________________________________
     
    CALLBACK FUNCTION DlgProc
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION PBMAIN()
     LOCAL MonitorDataAddr  AS MonitorInfoAddr
     LOCAL MonitorData      AS MONITORINFOEX
     LOCAL DisplayDevice    AS DISPLAY_DEVICE_EX
     LOCAL SecondaryMonitor AS LONG
     LOCAL Looper           AS LONG
     LOCAL Buffer           AS STRING
     LOCAL MainRect         AS RECT
     LOCAL MainSizeX        AS LONG
     LOCAL MainSizeY        AS LONG
     
     EnumDisplayMonitors(BYVAL %NULL, BYVAL %NULL, BYVAL CODEPTR(MonInfoEnumProc), VARPTR(MonitorDataAddr))
     
     DIM MonitorData(0 TO MonitorDataAddr.MonitorCount - 1) AS MonitorInfoData AT MonitorDataAddr.ArrayAddress
     Buffer = ""
     FOR Looper = 0 TO MonitorDataAddr.MonitorCount - 1
       Buffer = Buffer & _
       "Monitor " & STR$(Looper)                                    & $CRLF & _
       "Monitor handle is" & STR$(MonitorData(Looper).hMonitor)     & $CRLF & _
       "Monitor hdc is"    & STR$(MonitorData(Looper).hdcMonitor)   & $CRLF & _
       "Left:"             & STR$(MonitorData(Looper).Clip.nLeft)   & $CRLF & _
       "Top:"              & STR$(MonitorData(Looper).Clip.nTop)    & $CRLF & _
       "Right:"            & STR$(MonitorData(Looper).Clip.nRight)  & $CRLF & _
       "Bottom:"           & STR$(MonitorData(Looper).Clip.nBottom) & $CRLF & $CRLF
     NEXT
     
     FOR Looper = 0 TO MonitorDataAddr.MonitorCount - 1
       MonitorData.cbSize = SIZEOF(MonitorData) 'Ask for MONITORINFOEX
       GetMonitorInfo BYVAL MonitorData(Looper).hMonitor, BYVAL VARPTR(MonitorData)
       IF (MonitorData.dwFlags AND %MONITORINFOF_PRIMARY) = 0 THEN
         SecondaryMonitor = Looper
         EXIT FOR
       END IF
     NEXT
     
     DIALOG NEW %HWND_DESKTOP ,"Centered on secondary monitor !", , , 210, 150, _  '200 150
                %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, %NULL TO hDlg
     
     SetClassLong hDlg, %GCL_HICON, LoadIcon(BYVAL %NULL, BYVAL %IDI_INFORMATION)
     
     CONTROL ADD LABEL, hDlg, %Label1, Buffer, 15, 10, 170, 130
     
     IF MonitorDataAddr.MonitorCount = 2 THEN
       GetWindowRect hDlg, MainRect 'Get dialog position and size
     
       MainSizeX = MainRect.nRight - MainRect.nLeft
       MainRect.nLeft = MonitorData(SecondaryMonitor).Clip.nLeft + _
                        ((MonitorData(SecondaryMonitor).Clip.nRight - _
                        MonitorData(SecondaryMonitor).Clip.nLeft) / 2) - _
                        MainSizeX / 2
       MainRect.nRight = MainRect.nLeft + MainSizeX
     
       MainSizeY = MainRect.nBottom - MainRect.nTop
       MainRect.nTop = MonitorData(SecondaryMonitor).Clip.nTop + _
                       ((MonitorData(SecondaryMonitor).Clip.nBottom - _
                       MonitorData(SecondaryMonitor).Clip.nTop) / 2) - _
                       MainSizeY / 2
       MainRect.nBottom = MainRect.nTop + MainSizeY
     
       SetWindowPos hDlg, %HWND_TOP, MainRect.nLeft, MainRect.nTop, 0, 0, _
                    %SWP_NOSIZE OR %SWP_NOZORDER OR %SWP_SHOWWINDOW
     END IF
     
     DIALOG SHOW MODAL hDlg CALL DlgProc
     
     '--------------------------------------------------------------------- EnumDisplayDevices
     
     Buffer = ""
     FOR Looper = 0 TO MonitorDataAddr.MonitorCount - 1
       DisplayDevice.cb = SIZEOF(DisplayDevice)
       EnumDisplayDevices(BYVAL %NULL, Looper, BYVAL VARPTR(DisplayDevice), BYVAL %NULL) 'Nonzero if succees
       Buffer = Buffer & _
       "DeviceName: "   & DisplayDevice.DeviceName       & $CRLF & _
       "DeviceString: " & DisplayDevice.DeviceString     & $CRLF & _
       "DeviceID: "     & DisplayDevice.DeviceID         & $CRLF & _
       "DeviceKey: "    & DisplayDevice.DeviceKey        & $CRLF & _
       "StateFlags: "   & HEX$(DisplayDevice.StateFlags) & $CRLF
       IF (DisplayDevice.StateFlags AND %DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) THEN
         Buffer = Buffer & "DISPLAY_DEVICE_ATTACHED_TO_DESKTOP" & $CRLF
       END IF
       IF (DisplayDevice.StateFlags AND %DISPLAY_DEVICE_PRIMARY_DEVICE) THEN
         Buffer = Buffer & "DISPLAY_DEVICE_PRIMARY_DEVICE" & $CRLF
       END IF
       IF (DisplayDevice.StateFlags AND %DISPLAY_DEVICE_MIRRORING_DRIVER) THEN
         Buffer = Buffer & "DISPLAY_DEVICE_MIRRORING_DRIVER" & $CRLF
       END IF
       IF (DisplayDevice.StateFlags AND %DISPLAY_DEVICE_MODESPRUNED) THEN
         Buffer = Buffer & "DISPLAY_DEVICE_MODESPRUNED" & $CRLF
       END IF
       IF (DisplayDevice.StateFlags AND %DISPLAY_DEVICE_REMOVABLE) THEN
         Buffer = Buffer & "DISPLAY_DEVICE_REMOVABLE" & $CRLF
       END IF
       IF (DisplayDevice.StateFlags AND %DISPLAY_DEVICE_VGA_COMPATIBLE) THEN
         Buffer = Buffer & "DISPLAY_DEVICE_VGA_COMPATIBLE" & $CRLF
       END IF
       Buffer = Buffer & $CRLF
     NEXT
     MSGBOX Buffer,, "EnumDisplayDevices on primary monitor"
     
    END FUNCTION
    '______________________________________________________________________________
    Last edited by Pierre Bellisle; 12 Sep 2007, 12:42 PM. Reason: Updated for swapped primary/secondary monitor

    Leave a comment:


  • Pierre Bellisle
    replied
    Code updated for multi monitor

    Bob,

    If you feel like cheating,
    I updated above code to work in a multi monitors environnement...

    Pierre

    Leave a comment:


  • BOB MECHLER
    replied
    Pierre,

    Works fine with a single display but hugs right corner of monitor 1 if I move
    the program to the second monitor. Looks promising though. I'll play with the return values of the dialog position and see what I can do.

    Bob Mechler

    Leave a comment:


  • Pierre Bellisle
    replied
    Center SHELLed dialog, multi monitor aware

    Bob,

    You may also try the following...

    Pierre

    Code:
    #COMPILE EXE '#Win 8.03#
    #DIM ALL
    #INCLUDE "Win32Api.inc" '#2005-01-27#
     
    GLOBAL hDlg   AS DWORD
    GLOBAL hShell AS DWORD
     
    %ButtonShell  = 101
    %Label1       = 201
    %Label2       = 202
    '______________________________________________________________________________
     
    FUNCTION EnumWindowProc(BYVAL hTry AS LONG, BYVAL ProcessId AS DWORD) AS LONG
     LOCAL zCaption     AS ASCIIZ * %Max_Path
     LOCAL zClass       AS ASCIIZ * %Max_Path
     LOCAL LenClass     AS LONG
     LOCAL LenCaption   AS LONG
     LOCAL ProcessIdTry AS DWORD
     
     hShell = 0
     
     'LenCaption = GetWindowText(hTry, zCaption, %MAX_PATH) 'Get the caption of the dialog
     'IF UCASE$(zCaption) = "MYCAPTION" THEN
     '  hShell = hTry
     'ELSE
     '  FUNCTION = %TRUE
     'END IF
     
     'LenClass = GetClassName(hTry, zClass, %MAX_PATH) 'Get the class of the dialog
     'IF UCASE$(zClass) = "MYCLASS" THEN
     '  hShell = hTry
     'ELSE
     '  FUNCTION = %TRUE
     'END IF
     
     GetWindowThreadProcessId hTry, ProcessIdTry 'Get ProcessId of try window
     IF ProcessId = ProcessIdTry THEN 'Found our process id ?
       hShell = hTry
     ELSE
       FUNCTION = %TRUE 'True, so Function will recall itself until last window found
     END IF
     
     
    END FUNCTION
    '______________________________________________________________________________
     
    CALLBACK FUNCTION DlgProc
     LOCAL ProcessId    AS DWORD
     LOCAL Looper       AS LONG
     LOCAL DesktopRect  AS RECT
     LOCAL MainRect     AS RECT
     LOCAL ShellRect    AS RECT
     LOCAL ShellSizeX   AS LONG
     LOCAL ShellSizeY   AS LONG
     LOCAL hMonitor     AS DWORD
     LOCAL MonitorData  AS MONITORINFOEX
     LOCAL sBuffer      AS STRING
     
     SELECT CASE CBMSG
     
       CASE %WM_INITDIALOG
     
       CASE %WM_COMMAND
         SELECT CASE LOWRD(CBWPARAM)
           CASE %ButtonShell
             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
               ProcessId = SHELL(HANDLES, "Notepad.exe", %SW_HIDE) 'Change to valid stuff...
               'Since it will take some time for Windows to create the SHELLed dialog,
               'the use of this FOR/NEXT loop will wait up to 10 seconds.
               FOR Looper = 1 TO 100 'Try for 10 seconds (100 * 0.1 second)
                 EnumWindows CODEPTR(EnumWindowProc), ProcessId
                 IF hShell THEN EXIT FOR
                 SLEEP 100 'Give Windows time to create dialog, 0.1 second delay
               NEXT
     
               IF hShell THEN
                 'SystemParametersInfo could be used on single monitor system
                 'SystemParametersInfo %SPI_GETWORKAREA, 0, BYVAL VARPTR(DesktopRect), 0 'Get desktop size
     
                 'Multi monitor...
                 'Get handle of the monitor where our dialog is
     
                 hMonitor = MonitorFromWindow(BYVAL hDlg, BYVAL %MONITOR_DEFAULTTONEAREST) '%MONITOR_DEFAULTTOPRIMARY %MONITOR_DEFAULTTONEAREST
                 sBuffer = "Monitor handle is" & STR$(hMonitor)
                 'Get monitor info
                 MonitorData.cbSize = SIZEOF(MonitorData) 'Ask for MONITORINFOEX
                 GetMonitorInfo BYVAL hMonitor, BYVAL VARPTR(MonitorData)
                 IF MonitorData.dwFlags = %MONITORINFOF_PRIMARY THEN
                   sBuffer = sBuffer & ", it is the primary monitor"
                 ELSE
                   sBuffer = sBuffer & ", it is the secondary monitor"
                 END IF
                 sBuffer = sBuffer & $CRLF & "Device name is " & MonitorData.szDevice
                 CONTROL SET TEXT CBHNDL, %Label1, sBuffer
                 sBuffer = "Size is - " & _
                           "Left:" & STR$(MonitorData.rcWork.nLeft)    & _
                           ", Top:" & STR$(MonitorData.rcWork.nTop)   & _
                           ", Right:" & STR$(MonitorData.rcWork.nRight) & _
                           ", Bottom:" & STR$(MonitorData.rcWork.nBottom)
                 CONTROL SET TEXT CBHNDL, %Label2, sBuffer
     
                 DesktopRect = MonitorData.rcWork
     
                 GetWindowRect hDlg, MainRect 'Get main dialog position and size
                 GetWindowRect hShell, ShellRect 'Get shelled dialog position and size
     
                 'Calculate new shelled dialog position...
                 ShellSizeX = ShellRect.nRight - ShellRect.nLeft
                 ShellRect.nLeft =(MainRect.nLeft + (MainRect.nRight - MainRect.nLeft) / 2) - _
                                  (ShellSizeX / 2)
                 ShellRect.nRight = ShellRect.nLeft + ShellSizeX
     
                 ShellSizeY = ShellRect.nBottom - ShellRect.nTop
                 ShellRect.nTop =(MainRect.nTop + (MainRect.nBottom - MainRect.nTop) / 2) - _
                                 (ShellSizeY / 2)
                 ShellRect.nBottom = ShellRect.nTop + ShellSizeY
     
                 'Make sure right side of dialog is visible...
                 IF ShellRect.nRight > DesktopRect.nRight THEN
                   ShellRect.nLeft = DesktopRect.nRight - (ShellRect.nRight - ShellRect.nLeft)
                   ShellRect.nRight = ShellRect.nLeft + ShellSizeX
                 END IF
                 'Make sure bottom side of dialog is visible...
                 IF ShellRect.nBottom > DesktopRect.nBottom THEN
                   ShellRect.nTop = DesktopRect.nBottom - (ShellRect.nBottom - ShellRect.nTop)
                   ShellRect.nBottom = ShellRect.nTop + ShellSizeY
                 END IF
                 'Make sure left side of dialog is visible...
                 IF ShellRect.nLeft < DesktopRect.nLeft THEN
                   ShellRect.nLeft = DesktopRect.nLeft               
                   ShellRect.nRight = ShellSizeX
                 END IF
                 'Make sure top side of dialog is visible...
                 IF ShellRect.nTop < DesktopRect.nTop THEN             
                   ShellRect.nTop = DesktopRect.nTop               
                   ShellRect.nBottom = ShellSizeY
                 END IF
     
                 'Set new shelled dialog position
                 SetWindowPos hShell, %HWND_TOP, ShellRect.nLeft, ShellRect.nTop, 0, 0, _ 'ShellSizeX, ShellSizeY, _
                              %SWP_NOSIZE OR %SWP_NOZORDER OR %SWP_SHOWWINDOW
     
                 ShowWindow hShell, %SW_SHOWNORMAL
     
               END IF
             END IF
         END SELECT
     
      END SELECT
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION PBMAIN()
     
     DIALOG NEW %HWND_DESKTOP ,"Center shelled program", , , 200, 100, _
                %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, %NULL TO hDlg
     
     SetClassLong hDlg, %GCL_HICON, LoadIcon(BYVAL %NULL, BYVAL %IDI_INFORMATION)
     
     CONTROL ADD LABEL, hDlg, %Label1, "Center shelled program.", 10, 10, 180, 18
     CONTROL ADD LABEL, hDlg, %Label2, "Single and multi monitor version.", 10, 30, 180, 18
     
     CONTROL ADD BUTTON, hDlg, %ButtonShell, "Shell program", 70, 50, 60, 20
     
     DIALOG SHOW MODAL hDlg CALL DlgProc
     
    END FUNCTION
    '______________________________________________________________________________
    Last edited by Pierre Bellisle; 12 Sep 2007, 12:44 PM. Reason: Added multi monitor capability, update for swapped primary/secondary monitor

    Leave a comment:


  • BOB MECHLER
    replied
    Eric,

    I've downloaded the shareware version of DosBox and will evaluate.

    We are starting to heavily use SQL Tools professional and find it an excellent, excellent tool that will allow us to move to SQL with our procedural style programs.

    Thanks,

    Bob Mechler

    Leave a comment:


  • Eric Pearson
    replied
    Bob --

    It's possible that my company's "DOSBox Tools" product would solve your problems...

    -- Eric Pearson

    Leave a comment:


  • Michael Mattias
    replied
    ... If I shell to a dos window from a PBwin program, how do I center that dos window over the program that shelled to it?
    If you shell the DOS program with by means of the CreateProcess WinAPI function, I think you can specify the starting position and size of the command prompt in the STARTUPINFO structure.

    I know this works for "GUI" child processes, but I'm not sure it works for console processes, or if CMD.EXE actually obeys when it is the child.

    Leave a comment:


  • BOB MECHLER
    started a topic DOSBOX location control from PBWIN

    DOSBOX location control from PBWIN

    Some of our customers have Dos custom programs that they have not seen fit to upgrade to PBWIN. We are implementing sticky window positioning so that when a dialog is move to a second screen or any position other than center screen, the next PBWIN program called from a menu will appear in the same position. Also while that program is open any popup program that returns values to the underlying maintenance screen will center itself in the larger parent screen. I'm not use MDI but have gotten all the screens in PBWin to work this way by capturing the Windows position with WM_MOVE and then passing it to the next program called. If the target program has a smaller footprint, I do a little math and center the top left so that it will be centered in the calling program.
    The Dos programs that are called from a custom menu, I don't know how to control their position from a PBwin program. If only Dos programs are running they retain their position in a multiple monitor scenario on their own.

    A long explanation to ask this question. If I shell to a dos window from a PBwin program, how do I center that dos window over the program that shelled to it?

    BOB MECHLER
Working...
X