WildByDesign Posted Thursday at 02:09 PM Posted Thursday at 02:09 PM I know that this is somewhat unusual. I also understand that MDI (WS_EX_MDICHILD) windows are intended to move with the parent GUI window, not a child window (WS_CHILD). However, for the sake of learning and trying unusual things, here we are... From the example, you will notice that if you move the GUI around the screen, the pink-ish square (MDI window) stays in the middle and does not move with the GUI. That is because I have associated it with the white square which is a child window (WS_CHILD). The first part of what I want to achieve is to synchronize the movement of the MDI window with the movement of the white child window, specifically. The second part of what I would like to achieve would be to also synchronize the sizing of MDI window. I am still very much a rookie when it comes to WM_SIZE and WM_MOVE which I am assuming would be required here. Anyway, if anyone has a moment and is willing to assist with this, I would appreciate it very much. Thank you. #include <WindowsStylesConstants.au3> #include <GUIConstantsEx.au3> Example() Func Example() ; Create a GUI with various controls. Local $hGUI = GUICreate("Example", 400, 400) GUISetBkColor(0x202020) ; Display the GUI. GUISetState(@SW_SHOW, $hGUI) $hChild = GUICreate("ChildWindow", 200, 200, 100, 100, 0x40000000, -1, $hGUI) GUISetBkColor(0xffffff) GUISetState(@SW_SHOW, $hChild) $hChildMDI = GUICreate("", 100, 100, 5, 5, $WS_POPUP, $WS_EX_MDICHILD, $hChild) GUISetBkColor(0xff00ff) GUISetState(@SW_SHOW, $hChildMDI) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Delete the previous GUI and all controls. GUIDelete($hGUI) EndFunc ;==>Example
Nine Posted Thursday at 07:36 PM Posted Thursday at 07:36 PM Unless there is a specific reason to mix $WS_CHILD and $WS_EX_MDICHILD, you shouldn't do that. All you will get out of it is useless complexity. Now if you want to adapt the child windows to the size of its parent, here one easy way : expandcollapse popup; From Nine #include <GUIConstants.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", True) Global $hChild1, $hChild2, $aPosGUI Example() Func Example() Local $hGUI = GUICreate("Example", 400, 400, Default, Default, $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED) GUISetBkColor(0x202020) GUISetState() $hChild1 = GUICreate("", 200, 200, 100, 100, $WS_POPUP, $WS_EX_MDICHILD, $hGUI) GUISetBkColor(0xFFFFFF) GUISetState() $hChild2 = GUICreate("", 100, 100, 5, 5, $WS_POPUP, $WS_EX_MDICHILD, $hChild1) GUISetBkColor(0xFF00FF) GUISetState() GUIRegisterMsg($WM_SIZE, WM_SIZE) $aPosGUI = WinGetPos($hGUI) While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd EndFunc ;==>Example Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) Local $aPos = WinGetPos($hWnd), $aChild1 = WinGetPos($hChild1), $aChild2 = WinGetPos($hChild2) WinMove($hChild1, "", $aChild1[0], $aChild1[1], $aChild1[2] + $aPos[2] - $aPosGUI[2], $aChild1[3] + $aPos[3] - $aPosGUI[3]) WinMove($hChild2, "", $aChild2[0], $aChild2[1], $aChild2[2] + $aPos[2] - $aPosGUI[2], $aChild2[3] + $aPos[3] - $aPosGUI[3]) $aPosGUI = $aPos EndFunc ;==>WM_SIZE WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
pixelsearch Posted 15 hours ago Posted 15 hours ago (edited) On 11/27/2025 at 3:09 PM, WildByDesign said: The first part of what I want to achieve is to synchronize the movement of the MDI window with the movement of the white child window, specifically. I tried it like this, in the following script. Please note that you can move separately the pink MDI window by dragging it with the mouse (I applied to it the "AutoIt special" Exstyle $WS_EX_CONTROLPARENT) In this script, we don't need (for now) 2 separate functions WM_EXITSIZEMOVE() and WM_MOVE() as their content would duplicate the code found in functions WM_ENTERSIZEMOVE() and WM_SIZE() . This could change in case you'll have to work later on separate functions WM_SIZE() and WM_MOVE() expandcollapse popup#include <WindowsConstants.au3> #include <GUIConstantsEx.au3> Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Global $g_hGUI, $g_hChild, $g_hChildMDI, $g_aPosChild, $g_iDeltaX, $g_iDeltaY Example() Func Example() $g_hGUI = GUICreate("Example", 400, 400, -1, -1, $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED) GUISetBkColor(0x202020) GUISetState(@SW_SHOW, $g_hGUI) $g_hChild = GUICreate("ChildWindow", 200, 200, 100, 100, $WS_CHILD, -1, $g_hGUI) GUISetBkColor(0xffffff) GUISetState(@SW_SHOW, $g_hChild) $g_hChildMDI = GUICreate("", 100, 100, 5, 5, $WS_POPUP, BitOr($WS_EX_MDICHILD, $WS_EX_CONTROLPARENT), $g_hChild) GUISetBkColor(0xff00ff) GUISetState(@SW_SHOW, $g_hChildMDI) _CalcPosAndDelta() GUIRegisterMsg($WM_ENTERSIZEMOVE, "WM_ENTERSIZEMOVE") GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_ENTERSIZEMOVE") GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUIRegisterMsg($WM_MOVE, "WM_SIZE") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete($g_hChildMDI) GUIDelete($g_hChild) GUIDelete($g_hGUI) EndFunc ;==>Example Func _CalcPosAndDelta() Local $aPosChildMDI = WinGetPos($g_hChildMDI) $g_aPosChild = WinGetPos($g_hChild) $g_iDeltaX = $g_aPosChild[0] - $aPosChildMDI[0] $g_iDeltaY = $g_aPosChild[1] - $aPosChildMDI[1] EndFunc ;==>_CalcPosAndDelta Func WM_ENTERSIZEMOVE($hWnd, $iMsg, $wParam, $lParam) _CalcPosAndDelta() EndFunc ;==>WM_ENTERSIZEMOVE Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) If $hWnd = $g_hGUI Then $g_aPosChild = WinGetPos($g_hChild) WinMove($g_hChildMDI, "", $g_aPosChild[0] - $g_iDeltaX, $g_aPosChild[1] - $g_iDeltaY) EndIf EndFunc ;==>WM_SIZE Edited 13 hours ago by pixelsearch typo WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted 13 hours ago Author Posted 13 hours ago Here is a quick addition of the ListView with LVS_EX_DOUBLEBUFFER. By the way, @pixelsearch, I see that you just edited your example. My ListView addition is based on your example that was originally posted. I still have to check your updated example. expandcollapse popup#include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> ; DPI DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -2) Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Global $g_hGUI, $g_hChild, $g_hChildMDI, $g_aPosChild, $g_iDeltaX, $g_iDeltaY Example() Func Example() $g_hGUI = GUICreate("Example", 400, 400, -1, -1, $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED) GUISetBkColor(0x202020) GUISetState(@SW_SHOW, $g_hGUI) $g_hChild = GUICreate("ChildWindow", 320, 320, 40, 40, 0x40000000, -1, $g_hGUI) GUISetBkColor(0x606060) GUISetState(@SW_SHOW, $g_hChild) $g_hChildMDI = GUICreate("", 280, 280, 20, 20, $WS_POPUP, BitOr($WS_EX_MDICHILD, $WS_EX_CONTROLPARENT), $g_hChild) GUISetBkColor(0xff00ff) ; add listview Local $idListview = GUICtrlCreateListView("Column1|Column2", 20, 20, 240, 240, -1, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_CHECKBOXES)) Local $idLVi_Item1 = GUICtrlCreateListViewItem("1|1", $idListview) Local $idLVi_Item2 = GUICtrlCreateListViewItem("2|2", $idListview) Local $idLVi_Item3 = GUICtrlCreateListViewItem("3|3", $idListview) ; get rid of selection rectangle on listview GUICtrlSendMsg($idListview, $WM_CHANGEUISTATE, 65537, 0) GUISetState(@SW_SHOW, $g_hChildMDI) _CalcPosAndDelta() GUIRegisterMsg($WM_ENTERSIZEMOVE, "WM_ENTERSIZEMOVE") GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_ENTERSIZEMOVE") GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUIRegisterMsg($WM_MOVE, "WM_SIZE") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete($g_hChildMDI) GUIDelete($g_hChild) GUIDelete($g_hGUI) EndFunc ;==>Example Func _CalcPosAndDelta() Local $aPosChildMDI = WinGetPos($g_hChildMDI) $g_aPosChild = WinGetPos($g_hChild) $g_iDeltaX = $g_aPosChild[0] - $aPosChildMDI[0] $g_iDeltaY = $g_aPosChild[1] - $aPosChildMDI[1] EndFunc ;==>_CalcPosAndDelta Func WM_ENTERSIZEMOVE($hWnd, $iMsg, $wParam, $lParam) _CalcPosAndDelta() EndFunc ;==>WM_ENTERSIZEMOVE Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) If $hWnd = $g_hGUI Then $g_aPosChild = WinGetPos($g_hChild) WinMove($g_hChildMDI, "", $g_aPosChild[0] - $g_iDeltaX, $g_aPosChild[1] - $g_iDeltaY) EndIf EndFunc ;==>WM_SIZE pixelsearch 1
pixelsearch Posted 13 hours ago Posted 13 hours ago (edited) 47 minutes ago, WildByDesign said: I see that you just edited your example. No big deal, I simply replaced the constant 0x40000000 with its more comprehensive variable name $WS_CHILD, no more no less As you can see in my script, it's very easy to synchronize a MDI (WS_EX_MDICHILD) window with a Child Window (WS_CHILD) . It also works if you minimize / maximize / restore the GUI. I like the fact that the 2 registered functions WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE are called only 1 time per moving/sizing loop (I added a counter during tests and it's true). This is what MSDN stipulates about them : WM_ENTERSIZEMOVE : Sent one time to a window after it enters the moving or sizing modal loop WM_EXITSIZEMOVE : Sent one time to a window, after it has exited the moving or sizing modal loop. So they are "light" messages that don't require a lot of CPU at all and you can (re)initialize variables inside the functions, very useful ! According to trancexx at the very end of an old interesting thread... wait, let me paste the post and the link to the thread : On 3/25/2010 at 8:10 AM, trancexx said: On 3/25/2010 at 7:48 AM, 'martin said: I notice there is a listview extended style $LVS_EX_DOUBLEBUFFER which I thought might be a better solution than using $WS_EX_COMPOSITED for the window. I tried it but it doesn't reduce the flicker for me. It's not supposed to. That style reduces flicker when you resize columns, not the whole listview. Edited 13 hours ago by pixelsearch typo "I think you are searching a bug where there is no bug... don't listen to bad advice."
pixelsearch Posted 12 hours ago Posted 12 hours ago @WildByDesign great result with the listview inside the MDI window So $WS_EX_COMPOSITED is now applied to the GUI (less flicker when resizing the GUI) and doesn't interfere with the "$LVS_EX_DOUBLEBUFFER listview" which is a control of an external MDI window, bravo ! WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted 12 hours ago Author Posted 12 hours ago 16 minutes ago, pixelsearch said: I like the fact that the 2 registered functions WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE are called only 1 time per moving/sizing loop (I added a counter during tests and it's true). This is what MSDN stipulates about them : That is fantastic. Very efficient. By the way, this is all really quite genius. 17 minutes ago, pixelsearch said: According to trancexx at the very end of an old interesting thread... wait, let me paste the post and the link to the thread : What a coincidence, I was actually reading this same thread earlier in the morning. Sometimes I spend a good amount of time reading older threads here in the forum because it's literally a gold mine worth of information. Anyways, your technique is working. I've got it working with WS_EX_COMPOSITE and a perfectly working ListView thanks to the MDI GUI trick. I'll post the screenshot and more details in another comment because I just ran out of quota again... pixelsearch 1
WildByDesign Posted 12 hours ago Author Posted 12 hours ago This is what I have working so far. I'll have to open up a thread soon so that anyone can help if they want. I've got lots of ideas already for adding menubar, toolbar, statusbar, etc. The only thing that I need to figure out still is resizing the MDI GUI when the child GUI resizes.
Solution pixelsearch Posted 1 hour ago Solution Posted 1 hour ago 11 hours ago, WildByDesign said: The only thing that I need to figure out still is resizing the MDI GUI when the child GUI resizes. Fingers crossed expandcollapse popup#include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> ; DPI DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -2) Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Global $g_hGUI, $g_hChild, $g_hChildMDI, $g_aPosChild, $g_aDelta[4], $g_nRatio[4] Example() Func Example() Local $iParentW = 400, $iParentH = 400 Local $iChildW = 320, $iChildH = 320, $iChildX = 40, $iChildY = 40 $g_hGUI = GUICreate("Example", $iParentW, $iParentH, -1, -1, $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED) GUISetBkColor(0x202020) GUISetState(@SW_SHOW, $g_hGUI) $g_hChild = GUICreate("ChildWindow", $iChildW, $iChildH, $iChildX, $iChildY, $WS_CHILD, -1, $g_hGUI) GUISetBkColor(0x606060) Local $idLabel = GUICtrlCreateLabel("", 0, 0, $iChildW, $iChildH) GUICtrlSetState(-1, $GUI_DISABLE) GUISetState(@SW_SHOW, $g_hChild) $g_hChildMDI = GUICreate("", 280, 280, 20, 20, $WS_POPUP, BitOr($WS_EX_MDICHILD, $WS_EX_CONTROLPARENT), $g_hChild) GUISetBkColor(0xff00ff) ; add listview Local $idListview = GUICtrlCreateListView("Column1|Column2", 20, 20, 240, 240, -1, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_CHECKBOXES)) Local $idLVi_Item1 = GUICtrlCreateListViewItem("1|1", $idListview) Local $idLVi_Item2 = GUICtrlCreateListViewItem("2|2", $idListview) Local $idLVi_Item3 = GUICtrlCreateListViewItem("3|3", $idListview) ; get rid of selection rectangle on listview GUICtrlSendMsg($idListview, $WM_CHANGEUISTATE, 65537, 0) GUISetState(@SW_SHOW, $g_hChildMDI) $g_nRatio[0] = $iChildX / $iParentW $g_nRatio[1] = $iChildY / $iParentH $g_nRatio[2] = $iChildW / $iParentW $g_nRatio[3] = $iChildH / $iParentH _CalcPosAndDelta() GUIRegisterMsg($WM_ENTERSIZEMOVE, "WM_ENTERSIZEMOVE") GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_ENTERSIZEMOVE") GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUIRegisterMsg($WM_MOVE, "WM_MOVE") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete($g_hChildMDI) GUIDelete($g_hChild) GUIDelete($g_hGUI) EndFunc ;==>Example Func _CalcPosAndDelta() Local $aPosChildMDI = WinGetPos($g_hChildMDI) $g_aPosChild = WinGetPos($g_hChild) For $i = 0 To 3 $g_aDelta[$i] = $g_aPosChild[$i] - $aPosChildMDI[$i] Next EndFunc ;==>_CalcPosAndDelta Func WM_ENTERSIZEMOVE($hWnd, $iMsg, $wParam, $lParam) _CalcPosAndDelta() EndFunc ;==>WM_ENTERSIZEMOVE Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) If $hWnd = $g_hGUI Then Local $iParentNewCliW = BitAND($lParam, 0xFFFF) ; low word Local $iParentNewCliH = BitShift($lParam, 16) ; high word WinMove($g_hChild, "", $iParentNewCliW * $g_nRatio[0], $iParentNewCliH * $g_nRatio[1], _ $iParentNewCliW * $g_nRatio[2], $iParentNewCliH * $g_nRatio[3]) ; WinMove will use Int coords $g_aPosChild = WinGetPos($g_hChild) WinMove($g_hChildMDI, "", $g_aPosChild[0] - $g_aDelta[0], $g_aPosChild[1] - $g_aDelta[1] , _ $g_aPosChild[2] - $g_aDelta[2], $g_aPosChild[3] - $g_aDelta[3]) EndIf EndFunc ;==>WM_SIZE Func WM_MOVE($hWnd, $iMsg, $wParam, $lParam) If $hWnd = $g_hGUI Then $g_aPosChild = WinGetPos($g_hChild) WinMove($g_hChildMDI, "", $g_aPosChild[0] - $g_aDelta[0], $g_aPosChild[1] - $g_aDelta[1]) EndIf EndFunc ;==>WM_MOVE "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted 1 hour ago Author Posted 1 hour ago 19 minutes ago, pixelsearch said: Fingers crossed This is absolute perfection! Thank you so much. 🍷 I know it may seem like a lot of "extra" here, for anyone else that may be following along or reading later. I really enjoy smooth GUI movement (flicker-free) with WS_EX_COMPOSITED, particularly combined with the GUIFrame UDF in this case. But at the same time, I am a huge fan of ListViews and use many of them in most of my bigger projects. I love ListViews. So this MDI window trick was a blessing.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now