; A DLL to subclass a window to prevent resizing. ; Compile as Shared DLL, x86 (PB 4.6+) ANSI ;- Constants - Window Property names. #WND_SIZE_PREVENT_PROPNAME = "WndSizePreventOldProc" #WND_SIZE_PREVENT_HADMAX = "WndSizePreventHadMax" #WND_SIZE_PREVENT_WIDTH = "WndSizePreventWidth" #WND_SIZE_PREVENT_HEIGHT = "WndSizePreventHeight" ; Window dimension helpers. Procedure.i GetWindowWidth(hWnd.i) Protected rect.RECT If(GetWindowRect_(hWnd, @rect)) ProcedureReturn (rect\right - rect\left) EndIf EndProcedure Procedure.i GetWindowHeight(hWnd.i) Protected rect.RECT If(GetWindowRect_(hWnd, @rect)) ProcedureReturn (rect\bottom - rect\top) EndIf EndProcedure ; Procedure that clears out all properties on a window and restores original style/callback. Procedure.i WndSizePreventClear(hWnd.i) ; Restore original callback function. SetWindowLong_(hWnd, #GWL_WNDPROC, GetProp_(hWnd, #WND_SIZE_PREVENT_PROPNAME)) ; If the window had a maximize box, restore it. If(GetProp_(hWnd, #WND_SIZE_PREVENT_HADMAX)) SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE) | #WS_MAXIMIZEBOX) EndIf ; Remove all props from hWnd, preventing unwanted behaviour. RemoveProp_(hWnd, #WND_SIZE_PREVENT_PROPNAME) RemoveProp_(hWnd, #WND_SIZE_PREVENT_WIDTH) RemoveProp_(hWnd, #WND_SIZE_PREVENT_HEIGHT) RemoveProp_(hWnd, #WND_SIZE_PREVENT_HADMAX) EndProcedure ; Subclass callback procedure catching events for resizing. Procedure.i WndSizePreventProc(hWnd.i, uMsg.i, wParam.l, lParam.l) Protected dwOldProc.l = GetProp_(hWnd, #WND_SIZE_PREVENT_PROPNAME) Select uMsg Case #WM_NCHITTEST ; Call the original callback function to see the result of the NC hit test. Protected procRes.i = CallWindowProc_(dwOldProc, hWnd, uMsg, wParam, lParam) Select procRes ; Catch hit tests on borders and return 0, causing Windows to forget about handling a resize-cursor. Case #HTBORDER, #HTBOTTOM, #HTBOTTOMLEFT, #HTBOTTOMRIGHT, #HTTOP, #HTTOPLEFT, #HTTOPRIGHT, #HTLEFT, #HTRIGHT ProcedureReturn 0 EndSelect ; Set a minimum and maximum size for the window to its original size, preventing resizing. Case #WM_GETMINMAXINFO Protected *MM.MINMAXINFO = lParam With *MM Protected x = GetProp_(hWnd, #WND_SIZE_PREVENT_WIDTH) Protected y = GetProp_(hWnd, #WND_SIZE_PREVENT_HEIGHT) \ptMaxSize\x = x \ptMaxSize\y = y \ptMaxTrackSize\x = x \ptMaxTrackSize\y = y \ptMinTrackSize\x = x \ptMinTrackSize\y = y EndWith ProcedureReturn 0 ; Don't forget to remove all the props etc. if the window is closed. Case #WM_DESTROY WndSizePreventClear(hWnd) EndSelect ; If nothing else was prevented / catched and returned, call the original callback procedure to handle other events. ProcedureReturn CallWindowProc_(dwOldProc, hWnd, uMsg, wParam, lParam) EndProcedure Procedure.i PreventWindowSizing(hWnd.i, State.i) Protected oldProc.i = GetProp_(hWnd, #WND_SIZE_PREVENT_PROPNAME) Protected oldStyle.l = 0 If(State) ; If this window already has the state set to 1, return. If(oldProc) ProcedureReturn #True EndIf ; Set a new callback function for our window and prepare all the props containing important information. oldProc = SetWindowLong_(hWnd, #GWL_WNDPROC, @WndSizePreventProc()) SetProp_(hWnd, #WND_SIZE_PREVENT_PROPNAME, oldProc) SetProp_(hWnd, #WND_SIZE_PREVENT_WIDTH, GetWindowWidth(hWnd)) SetProp_(hWnd, #WND_SIZE_PREVENT_HEIGHT, GetWindowHeight(hWnd)) SetProp_(hWnd, #WND_SIZE_PREVENT_HADMAX, 0) ; If the window has a maximize box, we want to disable it. Remove it from the GWL_STYLE long. oldStyle = GetWindowLong_(hWnd, #GWL_STYLE) If(oldStyle & #WS_MAXIMIZEBOX) SetProp_(hWnd, #WND_SIZE_PREVENT_HADMAX, 1) SetWindowLong_(hWnd, #GWL_STYLE, oldStyle & ~#WS_MAXIMIZEBOX) EndIf ProcedureReturn #True Else If(oldProc) ; Don't forget to remove all the props etc. if the state is set to 0. Same as WM_DESTROY's steps. WndSizePreventClear(hWnd) ProcedureReturn #True EndIf EndIf EndProcedure ProcedureDLL.i IsValidWindow(hWnd.i) ; A DLL wrapper for IsWindow, so we won't have to load another DLL in AMS. ProcedureReturn IsWindow_(hWnd) EndProcedure ProcedureDLL.i DisableWindowResizing(hWnd.i, intDisabledState.i = 0) ; A DLL wrapper for PreventWindowSizing. ProcedureReturn PreventWindowSizing(hWnd, intDisabledState) EndProcedure ;- Example PureBasic implementation. Uncomment the next line to enable it. ;#WND_SIZE_PREVENT_EXAMPLE = 1 CompilerIf Defined(WND_SIZE_PREVENT_EXAMPLE, #PB_Constant) = 1 Global SizeableState = 0 If(OpenWindow(0, 0, 0, 450, 350, "Size test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)) ButtonGadget(0, 5, 5, 100, 22, "Toggle Sizeability") Repeat ; Have PureBasic's internal WinProc catch all other events. Event = WaitWindowEvent() E_GID = EventGadget() Select Event Case #PB_Event_CloseWindow Quit = 1 Case #PB_Event_Gadget Select E_GID Case 0 SizeableState ! 1 ; If SizeableState = 0, XOR to 1, if SizeableState = 1, XOR to 0. PreventWindowSizing(WindowID(0), SizeableState) EndSelect EndSelect Until Quit EndIf CompilerEndIf