Frankly after doing the tests you'll find here I'm not sure of what should be changed if any.
Please read on.
What I see which looks probably wrong are the returned values for these:
Code: Select all
Define x=WindowX(30,#PB_Window_FrameCoordinate)
Define y=WindowY(30,#PB_Window_FrameCoordinate)
Define w=WindowWidth(30,#PB_Window_FrameCoordinate)
Define h=WindowHeight(30,#PB_Window_FrameCoordinate)
They are not always the real values, and using DwmGetWindowAttribute() the values are correct.
If you are asking for these metrics I think the commands should always return the real on-screen values.
So probably this should be addressed.
Now, let's put this aside for now ... and look this.
I've tried an API only test:
Code: Select all
Enumeration
#DWMWA_NCRENDERING_ENABLED = 1
#DWMWA_NCRENDERING_POLICY
#DWMWA_TRANSITIONS_FORCEDISABLED
#DWMWA_ALLOW_NCPAINT
#DWMWA_CAPTION_BUTTON_BOUNDS
#DWMWA_NONCLIENT_RTL_LAYOUT
#DWMWA_FORCE_ICONIC_REPRESENTATION
#DWMWA_FLIP3D_POLICY
#DWMWA_EXTENDED_FRAME_BOUNDS
#DWMWA_HAS_ICONIC_BITMAP
#DWMWA_DISALLOW_PEEK
#DWMWA_EXCLUDED_FROM_PEEK
#DWMWA_LAST
EndEnumeration
Procedure GetWindowRectEx (hWnd, *tRECT.RECT)
Protected hDll, iDwmUsed
Protected *DwmGetWindowAttribute
Protected tRECT.RECT
If OSVersion() >= #PB_OS_Windows_Vista
hDll = OpenLibrary(#PB_Any, "dwmapi.dll")
If hDll
*DwmGetWindowAttribute = GetFunction(hDll, "DwmGetWindowAttribute")
If *DwmGetWindowAttribute
If CallFunctionFast(*DwmGetWindowAttribute, hWnd, #DWMWA_EXTENDED_FRAME_BOUNDS, *tRECT, SizeOf(RECT)) = #S_OK
iDwmUsed = 1
EndIf
EndIf
CloseLibrary(hDLL)
EndIf
EndIf
If iDwmUsed = 0 ; fallback
GetWindowRect_(hWnd, *tRECT)
EndIf
EndProcedure
Structure RECT2
x.i
y.i
w.i
h.i
EndStructure
Procedure CalcDecoratedWindowSize (Style, StyleEx, *rect.RECT2)
Protected r.RECT
r\left = 0
r\top = 0
r\right = *Rect\w
r\bottom = *Rect\h
AdjustWindowRectEx_(@r, Style, 0, StyleEx)
*Rect\w = r\right - r\left
*Rect\h = r\bottom - r\top
EndProcedure
Global hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_WINDOW))
; window procedure
Procedure WinProc (hWnd, Msg, wParam, lParam)
Select Msg
Case #WM_CLOSE
DestroyWindow_(hWnd)
Case #WM_NCDESTROY
DeleteObject_(hBrush)
PostQuitMessage_(0)
ProcedureReturn 0
EndSelect
ProcedureReturn DefWindowProc_(hWnd, Msg, wParam, lParam)
EndProcedure
; window class
Classname$ = "MyApiWindow"
With wClass.WNDCLASSEX
\cbsize = SizeOf(WNDCLASSEX)
\lpfnWndProc = @WinProc()
\hCursor = LoadCursor_(0, #IDC_ARROW)
\hbrBackground = hBrush
\lpszClassName = @classname$
EndWith
RegisterClassEx_(@wClass)
; create window and process messages
StyleEx = 0
Define rect.RECT2
Define r.RECT
rect\x = 10
rect\y = 150
rect\w = 280
rect\h = 70
Style = #WS_VISIBLE | #WS_SYSMENU | #WS_CAPTION
CalcDecoratedWindowSize(Style, StyleEx, @rect)
Debug "requested = " + rect\x
Debug "requested = " + rect\y
Debug "requested = " + rect\w
Debug "requested = " + rect\h
hWnd1 = CreateWindowEx_(StyleEx, Classname$, "without #WS_SIZEBOX (bad)", Style, rect\x, rect\y, rect\w, rect\h, 0, 0, 0, 0)
ShowWindow_(hWnd1, #SW_SHOWDEFAULT)
GetWindowRectEx (hwnd1, @r)
Debug "actual = " + r\left
Debug "actual = " + r\top
Debug "actual = " + Str(r\right - r\left)
Debug "actual = " + Str(r\bottom - r\top)
rect\x = 10
rect\y = 300
rect\w = 280
rect\h = 70
Style = #WS_VISIBLE | #WS_SYSMENU | #WS_CAPTION | #WS_SIZEBOX
CalcDecoratedWindowSize(Style, StyleEx, @rect)
Debug "requested = " + rect\x
Debug "requested = " + rect\y
Debug "requested = " + rect\w
Debug "requested = " + rect\h
hWnd2 = CreateWindowEx_(StyleEx, Classname$, "with #WS_SIZEBOX (good)", Style, rect\x, rect\y, rect\w, rect\h, 0, 0, 0, 0)
ShowWindow_(hWnd2, #SW_SHOWDEFAULT)
GetWindowRectEx (hwnd2, @r)
Debug "actual = " + r\left
Debug "actual = " + r\top
Debug "actual = " + Str(r\right - r\left)
Debug "actual = " + Str(r\bottom - r\top)
While GetMessage_(msg.MSG, 0, 0, 0 )
TranslateMessage_(msg)
DispatchMessage_(msg)
Wend
UnregisterClass_(Classname$, GetModuleHandle_(#Null))
Code: Select all
[23:34:46] requested = 10
[23:34:46] requested = 150
[23:34:46] requested = 286
[23:34:46] requested = 95
[23:34:46] actual = 5
[23:34:46] actual = 145
[23:34:46] actual = 296
[23:34:46] actual = 105
[23:34:46] requested = 10
[23:34:46] requested = 300
[23:34:46] requested = 296
[23:34:46] requested = 105
[23:34:46] actual = 10
[23:34:46] actual = 300
[23:34:46] actual = 296
[23:34:46] actual = 105
For some reason the upper left corner of the window is not what specified in the CreateWindowEx_() call for the first window, and it's correct for the second one. The difference is the second one has the #WS_SIZEBOX style.
Looks like is the missing #WS_SIZEBOX the cause, and not the presence of #PB_Window_SystemMenu.
Adding or removing the #WS_SYSMENU style in the API example does not seem to have an effect. The positioning is correct in both cases.
Why this happens I don't know. But PB should be using the same API I believe and if the code above is correct (is it ? to me looks ok) then the result cannot be different.
In fact if you put that style in the PB window using #PB_Window_SizeGadget (which should be the #WS_SIZEBOX equivalent), all works ok.
Code: Select all
; BAD
OpenWindow(0, 10, 150, 280, 70, "30",#PB_Window_SystemMenu)
SetWindowColor(0,$F650F1)
OpenWindow(1, 0, 0, 280, 70, "30",#PB_Window_SystemMenu)
SetWindowColor(1,$0050F1)
x=WindowX(0,#PB_Window_FrameCoordinate)
y=WindowY(0,#PB_Window_FrameCoordinate)
w=WindowWidth(0,#PB_Window_FrameCoordinate)
h=WindowHeight(0,#PB_Window_FrameCoordinate)
ResizeWindow(1,(x+w),y, #PB_Ignore, #PB_Ignore)
; GOOD
OpenWindow(2, 10, 350, 280, 70, "30",#PB_Window_SystemMenu | #PB_Window_SizeGadget)
SetWindowColor(2,$F650F1)
OpenWindow(3, 0, 0, 280, 70, "30",#PB_Window_SystemMenu | #PB_Window_SizeGadget)
SetWindowColor(3,$0050F1)
x=WindowX(2,#PB_Window_FrameCoordinate)
y=WindowY(2,#PB_Window_FrameCoordinate)
w=WindowWidth(2,#PB_Window_FrameCoordinate)
h=WindowHeight(2,#PB_Window_FrameCoordinate)
ResizeWindow(3,(x+w),y, #PB_Ignore, #PB_Ignore)
While WaitWindowEvent() ! #PB_Event_CloseWindow :Wend
Using plain API return the same results.
If you know how to fix the API example, then probably the same thing can be applied to PB.
I would say I'm missing something but at the moment I don't see why the missing #WS_SIZEBOX should influence the correct positioning of the upper left corner of the window created.
EDIT: updated the API code with both the "requested" and the "actual" dimensions of the two windows.