xoru icon

dwr.pb

xoru | PRO | 11/13/12 04:42:35 PM UTC | 0 ⭐ | 7110 👁️ | Never ⏰ | []
PureBasic |

5.6 KB

|

None

|

0 👍

/

0 👎

; 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

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎