LKP Posted February 6 Share Posted February 6 (edited) Hi, everyone. My topic is inpired by this question. The question is simple, the answer is more then fulfilling, but I am here for fun 🙂, so I desided to reinvent a wheel and imitate z-order/clipping manually. Here is where it got me: Spoiler I know it does unnesesary redrawing, just tryed to simplify the code this time and cut off everything outside the question. I know that "child" windows should coinsider Every window and not get clipped if the parent is hidden. Let's assume it is a feature not a bug. expandcollapse popup#include <GDIPlus.au3> #include <WinAPIProc.au3> #include <SendMessage.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars', 1) OnAutoItExitRegister('_Exxit') Global $idButt = -3 ;$GUI_EVENT_CLOSE ;"Child" windows get "parent" hwnd as a parametr Global $hGui = GUICreate(($CmdLine[0] = False) ? 'OnTop' : 'Clipped', 255, 255) If $CmdLine[0] Then GUISetBkColor(Random(0, 0xFFFFFF)) Else $idButt = GUICtrlCreateButton('Add Auto IT Child', 42,126, 171) EndIf GUICtrlCreateLabel('Left Mouse button to move', 42, 42, 172) GUICtrlCreateLabel('ESC to Exit', 42, 84, 172) _GDIPlus_Startup() Global $X, $Y ; to store mouse pos GUIRegisterMsg($WM_MOVE, '_WM_MOVE') GUIRegisterMsg($WM_MOVING, '_WM_MOVING') GUIRegisterMsg($WM_MOUSEMOVE, '_WM_MOUSEMOVE') Global Const $nMargin = 3 _UpdateRegion() GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $idButt _AddAChild() EndSwitch _UpdateRegion() WEnd ; =============================================================================================================================== Func _Exxit() _GDIPlus_Shutdown() Exit EndFunc ; =============================================================================================================================== Func _WM_MOVE($hWndGUI, $MsgID, $WParam, $LParam) WinMove($hGui, '', $X, $Y) EndFunc ; =============================================================================================================================== Func _WM_MOVING($hWndGUI, $MsgID, $WParam, $LParam) Local Const $tagRectSTRUCT = 'LONG left; LONG top; LONG right; LONG bottom' Local $tRECT = DllStructCreate($tagRectSTRUCT, $LParam) $X = DllStructGetData($tRECT, 'left') $Y = DllStructGetData($tRECT, 'top') _UpdateRegion() EndFunc ; =============================================================================================================================== Func _WM_MOUSEMOVE($hWndGUI, $MsgID, $WParam, $LParam) Local Const $MK_LBUTTON = 0x0001 Local Const $SC_MOVE = 0xF010 + 13 ; I dont really know why 13 If BitAND($MK_LBUTTON, $WParam) Then _SendMessage($hGui, $WM_SYSCOMMAND, $SC_MOVE) EndIf EndFunc ; =============================================================================================================================== Func _UpdateRegion() If Not $CmdLine[0] Then Return Local $aPPos = WinGetPos(HWnd($CmdLine[1])) Local $aCPos = WinGetPos($hGui) If Not IsArray($aPPos) Then Exit Local $hRegionInf = _GDIPlus_RegionCreate() Local $hRegion = _GDIPlus_RegionCreateFromRect( _ $aPPos[0] - $aCPos[0] - $nMargin, _ $aPPos[1] - $aCPos[1] - $nMargin, _ $aPPos[2] + $nMargin * 2, _ $aPPos[3] + $nMargin * 2) _GDIPlus_RegionCombineRegion($hRegion, $hRegionInf, 3) Local $hRGN = _GDIPlus_RegionGetHRgn($hRegion, 0) _WinAPI_SetWindowRgn($hGui, $hRGN) _WinAPI_DeleteObject($hRGN) _GDIPlus_RegionDispose($hRegion) _GDIPlus_RegionDispose($hRegionInf) EndFunc ; =============================================================================================================================== Func _AddAChild() Switch @Compiled Case True Run(@ScriptFullPath & " " & $hGui) Case Else ShellExecute(@AutoItExe, @ScriptFullPath & ' ' & $hGui) EndSwitch EndFunc ; =============================================================================================================================== While coding this ↑ I've encountered problems would need community help with: Why does _WinAPI_SetWindowRgn change window style? After the func is applied window caption switches to some prehistoric version. Why? I've tryed checking UDF source, but it does nothing, just sends data to win func. I've tryed checking microsoft.learn for more info, but couldnt find anything there either. How do I change it back, change it to something else? It is probably GUISetStyle I should use, but none of style configs I applied worked. Func works fine, but there are no $WS_REJECTTRADITION / $WS_EMBRACEMODERNITY styles. Basic functions code is not included, but I could google SetWindowLongA whitch, holding GUI Control Styles and Extended Style table, looks very similar to GUISetStyle. However, those style tables are the exact copy of Appendix Reference, so it is kinda useless. How do I get ExExStyle table? Is there some kind of FullWinAPI.chm someone could share? Are there any other hidden win styles? Why don't reference constanst work? Lines 57-61 I send a SC_MOVE massage to a window. Judging by SC_MOVE page. everything is OK. But cursor changes to EveryDirPos and win does not move. On the same time adding some value (like +13), results in a moving window without changing the cursor There is a remark saying Quote In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator. And I don't understand it. Bit AND for styleData and wParam behaves weirdly. Could someone explain that in simple english or give working examples? Edited February 6 by LKP Link to comment Share on other sites More sharing options...
Andreik Posted February 6 Share Posted February 6 3 hours ago, LKP said: Why does _WinAPI_SetWindowRgn change window style? This is nonesense. If you debug the _UpdateRegion() you will see that the style of the window is never changed inside the function, so it has nothing to do with _WinAPI_SetWindowRgn(). The only time when the style of the window is changed it's when you show the window and WS_VISIBLE is added as style. Since you call _UpdateRegion() once before calling GUISetState() it's normal to see a change in window style. 3 hours ago, LKP said: How do I change it back, change it to something else? Hide the window. To change the style to something else you can use GUISetStyle() or _WinAPI_SetWindowLong(). 3 hours ago, LKP said: Why don't reference constanst work? I don't have any clue what are you talking about here. Link to comment Share on other sites More sharing options...
LKP Posted February 7 Author Share Posted February 7 (edited) @Andreik, thank you very much for your answer. However, some things remain unclear for me. 17 hours ago, Andreik said: This is nonesense. If you debug the _UpdateRegion() you will see that the style of the window is never changed inside the function, so it has nothing to do with _WinAPI_SetWindowRgn(). The only time when the style of the window is changed it's when you show the window and WS_VISIBLE is added as style. Since you call _UpdateRegion() once before calling GUISetState() it's normal to see a change in window style. It sounds like nonesense to me either, but I can see the changes and can't find the solution. The problem, by the way, also affects Autoit UDF examples. In _GDIPlus_RegionCombinePath example window caption looks like one from Win 98 too. I've deleted every call of _UpdateRegion() in cycles, so that it could only be launched by button, added a MsgBox before and after the _WinAPI_SetWindowRgn. And it definitely changes. I've tested it at home and on two laptops at work. Win 7, Win 10, Win 11 give the same result. But it could be that my AutoIt zip is somehow broken, so I will attach a screenshot with two types of styles. There the top purple window has win 98 style caption. It is blue and the buttons are smaller. I cant see why that happens and would like to know how to switch it. 17 hours ago, Andreik said: I don't have any clue what are you talking about here. Yesterday I was not in the condition to write using the second language.😀 I will try to express myself in a more clear way this time. So, I want to learn how to use _SendMessage AutoItHelp files were not that helpful with that, so I tried to get the information I needed on learn.microsoft. For testing I decided to send WM_SYSCOMMAND, which would move my window. learn.microsoft says that the message uses only the wParam parameter, which is supposed to be SC_MOVE (0xF010) to move a window. But when I post WM_SYSCOMMAND with the 0xF010 parameter to my window, the cusor moves and changes to an arrow pointing in every direction (like $MCID_SIZEALL) Eventually, I made WM_SYSCOMMAND move the window by adding 13 to 0xF010, but I don't know why. I dont know what I miss. The only guess is the remark WM_SYSCOMMAND learn.microsoft page that says: Quote In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator. But I can't understand it propely. Updated code with manual, interrupted _UpdateRegion() and two options of WM_SYSCOMMAND: expandcollapse popup#include <GDIPlus.au3> #include <WinAPIProc.au3> #include <SendMessage.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars', 1) OnAutoItExitRegister('_Exxit') Global $idButt = -3 ;$GUI_EVENT_CLOSE ;"Child" windows get "parent" hwnd as a parametr Global $hGui = GUICreate(($CmdLine[0] = False) ? 'OnTop' : 'Clipped', 255, 255) If $CmdLine[0] Then GUISetBkColor(Random(0, 0xFFFFFF)) Else EndIf $idButt = GUICtrlCreateButton(($CmdLine[0] = False) ? 'Add Auto IT Child' : 'Update Region', 42,126, 171) GUICtrlCreateLabel('Left Mouse button to move (SC_MOVE+13)' & @CRLF & _ 'Right mouse button doesn''t work (SC_MOVE)', 42, 42, 192, 88) GUICtrlCreateLabel('ESC to Exit', 42, 104, 172) _GDIPlus_Startup() Global $X, $Y ; to store mouse pos GUIRegisterMsg($WM_MOVE, '_WM_MOVE') GUIRegisterMsg($WM_MOVING, '_WM_MOVING') GUIRegisterMsg($WM_MOUSEMOVE, '_WM_MOUSEMOVE') Global Const $nMargin = 3 ; _UpdateRegion() GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $idButt If $CmdLine[0] = False Then _AddAChild() Else _UpdateRegion() EndIf EndSwitch ; _UpdateRegion() WEnd ; =============================================================================================================================== Func _Exxit() _GDIPlus_Shutdown() Exit EndFunc ; =============================================================================================================================== Func _WM_MOVE($hWndGUI, $MsgID, $WParam, $LParam) WinMove($hGui, '', $X, $Y) EndFunc ; =============================================================================================================================== Func _WM_MOVING($hWndGUI, $MsgID, $WParam, $LParam) Local Const $tagRectSTRUCT = 'LONG left; LONG top; LONG right; LONG bottom' Local $tRECT = DllStructCreate($tagRectSTRUCT, $LParam) $X = DllStructGetData($tRECT, 'left') $Y = DllStructGetData($tRECT, 'top') ; _UpdateRegion() EndFunc ; =============================================================================================================================== Func _WM_MOUSEMOVE($hWndGUI, $MsgID, $WParam, $LParam) Local Const $MK_LBUTTON = 0x0001 Local Const $MK_RBUTTON = 0x0002 Local Const $SC_MOVE = 0xF010 If BitAND($MK_LBUTTON, $WParam) Then _SendMessage($hGui, $WM_SYSCOMMAND, $SC_MOVE + 13) ; I dont really know why 13 ElseIf BitAND($MK_RBUTTON, $WParam) Then _SendMessage($hGui, $WM_SYSCOMMAND, $SC_MOVE) EndIf EndFunc ; =============================================================================================================================== Func _UpdateRegion() If Not $CmdLine[0] Then Return Local $aPPos = WinGetPos(HWnd($CmdLine[1])) Local $aCPos = WinGetPos($hGui) If Not IsArray($aPPos) Then Exit Local $hRegionInf = _GDIPlus_RegionCreate() Local $hRegion = _GDIPlus_RegionCreateFromRect( _ $aPPos[0] - $aCPos[0] - $nMargin, _ $aPPos[1] - $aCPos[1] - $nMargin, _ $aPPos[2] + $nMargin * 2, _ $aPPos[3] + $nMargin * 2) _GDIPlus_RegionCombineRegion($hRegion, $hRegionInf, 3) Local $hRGN = _GDIPlus_RegionGetHRgn($hRegion, 0) MsgBox(0, '', 'Before') _WinAPI_SetWindowRgn($hGui, $hRGN) MsgBox(0, '', 'After') _WinAPI_DeleteObject($hRGN) _GDIPlus_RegionDispose($hRegion) _GDIPlus_RegionDispose($hRegionInf) EndFunc ; =============================================================================================================================== Func _AddAChild() Switch @Compiled Case True Run(@ScriptFullPath & " " & $hGui) Case Else ShellExecute(@AutoItExe, @ScriptFullPath & ' ' & $hGui) EndSwitch EndFunc ; =============================================================================================================================== Edited February 7 by LKP Link to comment Share on other sites More sharing options...
Solution argumentum Posted February 7 Solution Share Posted February 7 The above code crashes maybe _WinAPI_SetThemeAppProperties() can help ? Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
LKP Posted February 7 Author Share Posted February 7 (edited) Hi, @argumentum. Did not expect spaces in FileName. Is it the crash reason? Gone reading _WinAPI_SetThemeAppProperties() 🙂 Fixed Code: expandcollapse popup#include <GDIPlus.au3> #include <WinAPIProc.au3> #include <SendMessage.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars', 1) OnAutoItExitRegister('_Exxit') Global $idButt = -3 ;$GUI_EVENT_CLOSE ;"Child" windows get "parent" hwnd as a parametr Global $hGui = GUICreate(($CmdLine[0] = False) ? 'OnTop' : 'Clipped', 255, 255) If $CmdLine[0] Then GUISetBkColor(Random(0, 0xFFFFFF)) Else EndIf $idButt = GUICtrlCreateButton(($CmdLine[0] = False) ? 'Add Auto IT Child' : 'Update Region', 42,126, 171) GUICtrlCreateLabel('Left Mouse button to move (SC_MOVE+13)' & @CRLF & _ 'Right mouse button doesn''t work (SC_MOVE)', 42, 42, 192, 88) GUICtrlCreateLabel('ESC to Exit', 42, 104, 172) _GDIPlus_Startup() Global $X, $Y ; to store mouse pos GUIRegisterMsg($WM_MOVE, '_WM_MOVE') GUIRegisterMsg($WM_MOVING, '_WM_MOVING') GUIRegisterMsg($WM_MOUSEMOVE, '_WM_MOUSEMOVE') Global Const $nMargin = 3 ; _UpdateRegion() GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $idButt If $CmdLine[0] = False Then _AddAChild() Else _UpdateRegion() EndIf EndSwitch ; _UpdateRegion() WEnd ; =============================================================================================================================== Func _Exxit() _GDIPlus_Shutdown() Exit EndFunc ; =============================================================================================================================== Func _WM_MOVE($hWndGUI, $MsgID, $WParam, $LParam) WinMove($hGui, '', $X, $Y) EndFunc ; =============================================================================================================================== Func _WM_MOVING($hWndGUI, $MsgID, $WParam, $LParam) Local Const $tagRectSTRUCT = 'LONG left; LONG top; LONG right; LONG bottom' Local $tRECT = DllStructCreate($tagRectSTRUCT, $LParam) $X = DllStructGetData($tRECT, 'left') $Y = DllStructGetData($tRECT, 'top') ; _UpdateRegion() EndFunc ; =============================================================================================================================== Func _WM_MOUSEMOVE($hWndGUI, $MsgID, $WParam, $LParam) Local Const $MK_LBUTTON = 0x0001 Local Const $MK_RBUTTON = 0x0002 Local Const $SC_MOVE = 0xF010 If BitAND($MK_LBUTTON, $WParam) Then _SendMessage($hGui, $WM_SYSCOMMAND, $SC_MOVE + 13) ; I dont really know why 13 ElseIf BitAND($MK_RBUTTON, $WParam) Then _SendMessage($hGui, $WM_SYSCOMMAND, $SC_MOVE) EndIf EndFunc ; =============================================================================================================================== Func _UpdateRegion() If Not $CmdLine[0] Then Return Local $aPPos = WinGetPos(HWnd($CmdLine[1])) Local $aCPos = WinGetPos($hGui) If Not IsArray($aPPos) Then Exit Local $hRegionInf = _GDIPlus_RegionCreate() Local $hRegion = _GDIPlus_RegionCreateFromRect( _ $aPPos[0] - $aCPos[0] - $nMargin, _ $aPPos[1] - $aCPos[1] - $nMargin, _ $aPPos[2] + $nMargin * 2, _ $aPPos[3] + $nMargin * 2) _GDIPlus_RegionCombineRegion($hRegion, $hRegionInf, 3) Local $hRGN = _GDIPlus_RegionGetHRgn($hRegion, 0) MsgBox(0, '', 'Before') _WinAPI_SetWindowRgn($hGui, $hRGN) MsgBox(0, '', 'After') _WinAPI_DeleteObject($hRGN) _GDIPlus_RegionDispose($hRegion) _GDIPlus_RegionDispose($hRegionInf) EndFunc ; =============================================================================================================================== Func _AddAChild() Switch @Compiled Case True Run(@ScriptFullPath & " " & $hGui) Case Else ShellExecute(@AutoItExe, FileGetShortName(@ScriptFullPath) & ' ' & $hGui) EndSwitch EndFunc ; =============================================================================================================================== Edited February 7 by LKP Link to comment Share on other sites More sharing options...
argumentum Posted February 7 Share Posted February 7 19 minutes ago, LKP said: Did not expect spaces in FileName. Is it the crash reason? No is not, I fixed the spaces. Is in _UpdateRegion() Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
argumentum Posted February 7 Share Posted February 7 7 minutes ago, argumentum said: No is not, I fixed the spaces. Is in _UpdateRegion() ..as luck may have it, I had previous parameters in "Shift + F8". There's nothing wrong with the code. LKP 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
argumentum Posted February 7 Share Posted February 7 and, testing on WinXP, when this was coded, works as expected. Welcome to Win10/11 ? Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
LKP Posted February 7 Author Share Posted February 7 Well, I hoped it is not the reason. 😕 Still hope some genius could provide a way to apply this win 98 style on any other AutoIt window & switch it back. If backward compatibility exists there has to be a way to use it. If none does that, or helps me with SendMessage within a week, I will mark your reply as a solution. P.s. Feels strange to know someone uses XP today, it was great, but it was so long ago. Everyone laughed at me when I bought win 7 CD to have operational OS, if Vista2 happens, but today none of computers around me even have a CD-Drive. P.p.s. Your About me looks perfect😉 argumentum 1 Link to comment Share on other sites More sharing options...
Andreik Posted February 7 Share Posted February 7 (edited) 5 hours ago, LKP said: I've deleted every call of _UpdateRegion() in cycles, so that it could only be launched by button, added a MsgBox before and after the _WinAPI_SetWindowRgn. And it definitely changes. As I said before, it doesn't. The style of the window is not affected, what it changes it's the theme but it's not a bug, it's the windows way to make your application compatible with earlier versions. You can read here more about when visual styles are not applied. One more thing. Don't delete the handle of the region after you successfully used _WinAPI_SetWindowRgn() because the system owns the region and the system deletes the region handle when it no longer needed. Edited February 7 by Andreik Link to comment Share on other sites More sharing options...
ioa747 Posted February 8 Share Posted February 8 (edited) strange indeed how to return the window to its original state? expandcollapse popup#include <WinAPIGdi.au3> #include <ButtonConstants.au3> #include <WindowsConstants.au3> Local $hGUI, $idBtnTest, $hRgn, $aPos $hGUI = GUICreate(StringTrimRight(@ScriptName, 4), 300, 100) GUISetBkColor(0xCAC6B3) $idBtnTest1 = GUICtrlCreateButton("Default", 10, 60, 70, 30) $idBtnTest2 = GUICtrlCreateButton("Toolwindow", 90, 60, 70, 30) $idBtnTest3 = GUICtrlCreateButton("Test 3", 220, 60, 70, 30) GUISetState(@SW_SHOW) GUICtrlSendMsg($idBtnTest3, $BM_CLICK, 0, 0) GUICtrlSendMsg($idBtnTest2, $BM_CLICK, 0, 0) GUICtrlSendMsg($idBtnTest3, $BM_CLICK, 0, 0) ;********************************** While 1 Switch GUIGetMsg() Case -3 ExitLoop Case $idBtnTest1 GUISetStyle(BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU), 0) Case $idBtnTest2 GUISetStyle(BitOR($WS_CAPTION, $WS_POPUPWINDOW, $WS_THICKFRAME), BitOR($WS_EX_CLIENTEDGE, $WS_EX_TOOLWINDOW)) Case $idBtnTest3 $aPos = WinGetPos($hGUI) $hRgn = _WinAPI_CreateRectRgn(0, 0, $aPos[2], $aPos[3]) _WinAPI_SetWindowRgn($hGUI, $hRgn) EndSwitch Sleep(10) WEnd ;********************************** Edited February 8 by ioa747 I know that I know nothing Link to comment Share on other sites More sharing options...
argumentum Posted February 8 Share Posted February 8 (edited) Let me steal this thread for a moment. Since we're at it. What about making a sh*t load of examples for: Func _WinAPI_DwmSetWindowAttribute($hWnd, $iAttribute, $iData) ;Switch $iAttribute ; https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute ; Case 2, 3, 4, 6, 7, 8, 10, 11, 12 ; Case Else ; Return SetError(1, 0, 0) ;EndSwitch Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute I just opened a trac to change it to the above. Given that the more modern examples would not have worked with the $iAttribute filtering of the era. Examples are few and far between: https://www.autoitscript.com/forum/topic/101358-remove-a-window-from-aero-peek-in-windows-7/ ( aero stuff ) https://www.autoitscript.com/forum/topic/211196-gui-title-bar-dark-theme-an-elegant-solution-using-dwmapi/#comment-1527581 ( Win 10/11 stuff ) ...and who knows ( not me ), one of those may aid this thread. Spoiler ( https://www.purebasic.fr/english/viewtopic.php?t=78732 ) Edited February 8 by argumentum more Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
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