Tasp
Full Member
Posts: 215
|
Post by Tasp on Aug 31, 2020 6:25:40 GMT -5
I have 3 monitors, am I am trying to open a different window on each monitor. I have done this before but I'm unable to find the code to do this. I was hoping the simple solution was just going to be moving the UpperLeftX 0-1920 for mon 1, 1921-3840 for mon 2 and 3841-5760 for mon 3. But it's not that simple.... There's also the question, as like me, for some reason I have my monitors setup as 2 - 1 - 3 so those positions would potentially be different. But if the user places the window at a position I can save that position and reopen it next time in the same one. I have tried this, just collecting the screen position. But it shows at between 1 and 1920, doesn't show on which monitor.
Is there a way to identify which monitor the window is currently sat upon?
I think Janet helped with this last time, but this was on the old forum.
On a side note, has anyone seen Janet or John recently? I don't see those guys here anymore?
TIA
|
|
|
Post by Chris Iverson on Sept 1, 2020 12:06:45 GMT -5
For collecting the screen position, I suspect you're using GetWindowRect(), which is explicitly documented as returning screen co-ordinates. That is, they return the position relative to the top-left of the current screen.
I don't know if there's an actual one-step way to convert this to virtual-screen co-ordinates. You can use the MonitorFromWindow API to get a handle to the current monitor, and then GetMonitorInfo to get the workspace or full screen coordinates of the monitor, and do the math to get the co-ordinates.
If all you want is to save the current positioning of the window to restore it later, though, you may be better off using GetWindowPlacement and SetWindowPlacement.
Use GetWindowPlacement, and save all the info it gives you. You can then use SetWindowPlacement to restore it all at once.
Here's a sample I made for myself a while ago that combines all of these, when I was playing with going full-screen no matter what monitor I was on. Click "Fullscreen", and it should go full screen on whatever monitor it's currently on. Click "Windowed" to change it back, and try moving it to a different monitor.
gosub [structdef]
WindowWidth = 300 WindowHeight = 300 UpperLeftX = 300 UpperLeftY = 300
'Set defaults for Window Rect WINDOWRECT.left.struct = UpperLeftX WINDOWRECT.top.struct = UpperLeftY WINDOWRECT.right.struct = UpperLeftX + WindowWidth WINDOWRECT.bottom.struct = UpperLeftY + WindowHeight stylebits #m.g, 0, _WS_BORDER, 0, 0 graphicbox #m.g, 0, 0, 300, 300 button #m.b, "Fullscreen", [fsclick], UL, 100, 100, 100, 25 stylebits #m, 0, 0, _WS_EX_TOPMOST, 0 open "Hello" for window as #m #m, "trapclose [quit]" #m, "resizehandler [resize]"
#m.g, "color black" #m.g, "down;fill black"
hWnd = hwnd(#m) hButton = hwnd(#m.b)
wait
[quit] close #m end
[resize] #m.g, "locate 0 0 ";WindowWidth;" ";WindowHeight #m, "refresh" #m.g, "down;fill black" wait
[fsclick] winStyle = GetWindowLong(hWnd, _GWL_STYLE)
'WS_OVERLAPPEDWINDOW corresponds to a combination of OVERLAPPED, SYSMENU, 'THICKFRAME, CAPTION, MINIMIZEBOX, MAXIMIZEBOX. 'Turning it off will produce a window with no system menu/buttons and no border. ' 'This is important for one reason: if the window manager detects such a window that is 'filling up the monitor it is on, it will automatically hide the taskbar on that monitor. If winStyle AND _WS_OVERLAPPEDWINDOW Then 'Get the position of the monitor we're on 'Default to the primary monitor if it can't be determined hMonitor = MonitorFromWindow(hWnd, MONITOR.DEFAULTTOPRIMARY)
'If we can't get the monitor info or the window's current position, we don't do anything If (GetMonitorInfo(hMonitor) AND GetWindowPlacement(hWnd)) then
winStyle = winStyle XOR _WS_OVERLAPPEDWINDOW
'NOOWNERZORDER prevents the window from changing position in the z-order, 'FRAMECHANGED notifies the window manager that there's been a change and to recheck uFlags = _SWP_NOOWNERZORDER or _SWP_FRAMECHANGED
a = SetWindowLong(hWnd, _GWL_STYLE, winStyle) a = SetWindowPos(hWnd, _HWND_TOP, MONITORINFO.rcMonitorLeft.struct, MONITORINFO.rcMonitorTop.struct,_ (MONITORINFO.rcMonitorRight.struct - MONITORINFO.rcMonitorLeft.struct),_ (MONITORINFO.rcMonitorBottom.struct - MONITORINFO.rcMonitorTop.struct), uFlags)
'a = SetWindowText(hButton, "Windowed") #m.b "Windowed" End If Else winStyle = winStyle OR _WS_OVERLAPPEDWINDOW
'NOZORDER tells SetWindowPos to ignore the hWndInsertAfter parameter 'NOSIZE and NOMOVE tell SetWindowPos to ignore the size and position parameters. 'The SetWindowPos call is only used to tell Windows that the Window styles have changed, and force it 'to update. uFlags = _SWP_NOOWNERZORDER or _SWP_FRAMECHANGED or _SWP_NOZORDER or _SWP_NOSIZE or _SWP_NOMOVE
a = SetWindowLong(hWnd, _GWL_STYLE, winStyle) a = SetWindowPlacement(hWnd) a = SetWindowPos(hWnd, _NULL, 0, 0, 0, 0, uFlags)
'a = SetWindowText(hButton, "Fullscreen") #m.b "Fullscreen" End If wait
Function GetLastError() CallDLL #kernel32, "GetLastError",_ GetLastError as long End Function
Function GetWindowLong(hWnd, nIndex) CallDLL #user32, "GetWindowLongA",_ hWnd as ulong,_ nIndex as long,_ GetWindowLong as long End Function
Function SetWindowLong(hWnd, nIndex, newLong) CallDLL #user32, "SetWindowLongA",_ hWnd as ulong,_ nIndex as long,_ newLong as long,_ SetWindowLong as long End Function
Function SetWindowPos(hWnd, hWInsertAfter, X, Y, cx, cy, uFlags) CallDLL #user32, "SetWindowPos",_ hWnd as ulong,_ hWInsertAfter as ulong,_ X as long,_ Y as long,_ cx as long,_ cy as long,_ uFlags as long,_ SetWindowPos as long End Function
Function SetWindowText(hWnd, text$) CallDLL #user32, "SetWindowTextA",_ hWnd as ulong,_ text$ as ptr,_ SetWindowText as long End Function
Function MonitorFromWindow(hWnd, dwFlags) CallDLL #user32, "MonitorFromWindow",_ hWnd as ulong,_ dwFlags as long,_ MonitorFromWindow as ulong End Function
Function GetMonitorInfo(hMonitor) CallDLL #user32, "GetMonitorInfoA",_ hMonitor as ulong,_ MONITORINFO as struct,_ GetMonitorInfo as long End Function
Function GetWindowPlacement(hWnd) CallDLL #user32, "GetWindowPlacement",_ hWnd as ulong,_ WINDOWPLACEMENT as struct,_ GetWindowPlacement as long End Function
Function GetWindowRect(hWnd) CallDLL #user32, "GetWindowRect",_ hWnd as ulong,_ WINDOWRECT as struct,_ GetWindowRect as long End Function
Function SetWindowPlacement(hWnd) CallDLL #user32, "SetWindowPlacement",_ hWnd as ulong,_ WINDOWPLACEMENT as struct,_ SetWindowPlacement as long End Function
[structdef]
struct MONITORINFO,_ cbSize as long,_ rcMonitorLeft as long,_ rcMonitorTop as long,_ rcMonitorRight as long,_ rcMonitorBottom as long,_ rcWorkLeft as long,_ rcWorkTop as long,_ rcWorkRight as long,_ rcWorkBottom as long,_ dwFlags as long
MONITORINFO.cbSize.struct = len(MONITORINFO.struct)
struct WINDOWPLACEMENT,_ length as ulong,_ flags as long,_ showCmd as long,_ ptMinPositionX as long,_ ptMinPositionY as long,_ ptMaxPositionX as long,_ ptMaxPositionY as long,_ rcNormalPositionLeft as long,_ rcNormalPositionTop as long,_ rcNormalPositionRight as long,_ rcNormalPositionBottom as long
WINDOWPLACEMENT.length.struct = len(WINDOWPLACEMENT.struct)
struct WINDOWRECT,_ left as long,_ top as long,_ right as long,_ bottom as long
global MONITOR.DEFAULTTONEAREST, MONITOR.DEFAULTTONULL, MONITOR.DEFAULTTOPRIMARY
MONITOR.DEFAULTTONULL = 0 MONITOR.DEFAULTTOPRIMARY = 1 MONITOR.DEFAULTTONEAREST = 2
return
|
|
|
Post by Carl Gundel on Sept 1, 2020 12:32:43 GMT -5
For collecting the screen position, I suspect you're using GetWindowRect(), which is explicitly documented as returning screen co-ordinates. That is, they return the position relative to the top-left of the current screen. For LB5 I will try to support multiple displays. I believe that VisualWorks Smalltalk has support for this in the virtual machine in a way that I can capitalize on.
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Sept 27, 2020 12:42:13 GMT -5
Chris, Thanks for this, it's not exactly what I was looking for but actually does exactly what I need (I was looking at this wrongly).
It's took me a while to get my head around the basics, and I've actually learnt more about interacting with structs and API calls along the way. Whether I will remember any info is another matter.
Here's the snippet I needed, maybe this cut down version will help someone else.
gosub [structdef]
UpperLeftX = 500 : UpperLeftY = 500 button #m.1, "position",[getpos], UL, 100,100 button #m.2, "move", [move], UL, 100, 150 button #m.3, "text", [changetext],UL, 100, 200
OPEN "window" FOR window AS #m #m, "trapclose [quit]" hWnd = hwnd(#m) WAIT
[changetext] 'Change window title a = SetWindowText(hWnd, "text") WAIT
[getpos] 'Get cureent window position on any monitor a = GetWindowPlacement(hWnd) print "Window Position" print "ULX "; WINDOWPLACEMENT.rcNormalPositionLeft.struct print "ULY "; WINDOWPLACEMENT.rcNormalPositionTop.struct
WAIT
[move] 'Move window 'Must fill struct first as I think it will contains window type info etc. a = GetWindowPlacement(hWnd) 'UpperLeftX WINDOWPLACEMENT.rcNormalPositionLeft.struct = -200 'UpperLeftY WINDOWPLACEMENT.rcNormalPositionTop.struct = 200 'Bottom Right corner position WINDOWPLACEMENT.rcNormalPositionRight.struct = 1000 'Bottom position WINDOWPLACEMENT.rcNormalPositionBottom.struct = 1000
a = SetWindowPlacement(hWnd)
WAIT
[quit] CLOSE #m END
Function GetWindowPlacement(hWnd) CallDLL #user32, "GetWindowPlacement", hWnd as ulong, WINDOWPLACEMENT as struct, GetWindowPlacement as long End Function
Function SetWindowPlacement(hWnd) CallDLL #user32, "SetWindowPlacement", hWnd as ulong, WINDOWPLACEMENT as struct, SetWindowPlacement as long End Function
Function SetWindowText(hWnd, text$) CallDLL #user32, "SetWindowTextA", hWnd as ulong, text$ as ptr, SetWindowText as long End Function
[structdef] struct WINDOWPLACEMENT, length as ulong, flags as long, showCmd as long, ptMinPositionX as long, ptMinPositionY as long, ptMaxPositionX as long, ptMaxPositionY as long, rcNormalPositionLeft as long, rcNormalPositionTop as long, rcNormalPositionRight as long, rcNormalPositionBottom as long WINDOWPLACEMENT.length.struct = len(WINDOWPLACEMENT.struct)
global MONITOR.DEFAULTTONEAREST, MONITOR.DEFAULTTONULL, MONITOR.DEFAULTTOPRIMARY
return
|
|