Snap a window to all 4 corners of a screen

Just starting out? Need help? Post your questions and find answers here.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4792
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Snap a window to all 4 corners of a screen

Post by Fangbeast »

Is there an easy way to snap an application window to all 4 corners of a screen with a user defined snap region?

I've been playing with the math but it got a little complex for me after a few hours.

The below is as far as I got. Part of it workd, the rest is bbeing converted to shorter variables. But I need help.

Code: Select all

;============================================================================================================================
; Snap the main form to any of the current window borders
;============================================================================================================================

Procedure SnapWindowToBorder(Window.l)
  If ExamineDesktops()                              ; < Less than,  > Greater than
    CurrentScreenWidth.l  = DesktopWidth(0)         ; The current desktop width, can change dynamically!!
    CurrentScreenheight.l = DesktopHeight(0)        ; The current desktop height, can change dynamically!!
    WindowHeight.l        = WindowHeight(Window.l)  ; The passed window height, can change dynamically!!
    WindowWidth.l         = WindowWidth(Window.l)   ; The passed window width, can change dynamically!!
    CurrentXPos.l         = WindowX(Window.l)       ; Current top left x position of the window
    CurrentYPos.l         = WindowY(Window.l)       ; Current top left x position of the window
    If CurrentXPos.l < 20
      If CurrentYPos.l < 0
        ResizeWindow(Window.l, 0, #PB_Ignore, #PB_Ignore, #PB_Ignore)
      Else
        ResizeWindow(Window.l, 0, 0, #PB_Ignore, #PB_Ignore)
      EndIf  
    ElseIf CurrentYPos.l < 20
      If CurrentXPos.l > 0
        ResizeWindow(Window.l, #PB_Ignore, 0, #PB_Ignore, #PB_Ignore)
      Else
        ResizeWindow(Window.l, 0, 0, #PB_Ignore, #PB_Ignore)
      EndIf
    ElseIf CurrentXPos.l < 20 And CurrentYPos.l < 20
      ResizeWindow(Window.l, 0, 0, #PB_Ignore, #PB_Ignore)
    EndIf
    If CurrentXPos.l + WindowWidth.l > CurrentScreenWidth.l - 30  ; Is form beyond right x position?
      If CurrentYPos.l + CurrentScreenheight.l > CurrentScreenheight.l - 30
        ResizeWindow(Window.l, CurrentScreenWidth.l - WindowWidth.l - 7, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ElseIf CurrentXPos.l + WindowWidth.l > CurrentScreenWidth.l - 30 And CurrentYPos.l > 
      ResizeWindow(Window.l, CurrentScreenWidth.l - WindowWidth.l - 7, #PB_Ignore, #PB_Ignore, #PB_Ignore)
    ElseIf CurrentYPos.l + WindowHeight.l > CurrentScreenheight.l - 30
      ResizeWindow(Window.l, #PB_Ignore, CurrentScreenheight.l - WindowHeight.l - 26, #PB_Ignore, #PB_Ignore)
    ElseIf CurrentXPos.l + WindowWidth.l > CurrentScreenWidth.l - 30 And CurrentYPos.l + WindowHeight.l > CurrentScreenheight.l - 30
      ResizeWindow(Window.l, CurrentScreenWidth.l - WindowWidth.l - 7, CurrentScreenheight.l - WindowHeight.l - 26, #PB_Ignore, #PB_Ignore)
    EndIf
  EndIf
EndProcedure
  

  
  

User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

See if this has anything of interest:

Code: Select all

;======================================
; Program:    Window Snap Demo
; Author:     netmaestro
; Date:       October 23, 2006
;======================================

Global screenW, screenH, SnapD = 50, AutoSnap=#True

SystemParametersInfo_(#SPI_GETWORKAREA,0,@wa.RECT,0) ; Client area of the desktop
ScreenW = wa\right
screenH = wa\bottom

Procedure Snap(hwnd, corner)
  Protected w,h
  GetWindowRect_(hwnd, @view.RECT)
  w = view\right - view\left
  h = view\bottom - view\top
  Select corner
    Case 1
      MoveWindow_(hwnd, 0, 0, w, h, #True)
    Case 2
      MoveWindow_(hwnd, screenw-w,0,w,h,#True)
    Case 3
      MoveWindow_(hwnd,0, screenH-h,w,h,#True)   
    Case 4
     MoveWindow_(hwnd, screenW-w,screenH-h,w,h,#True)
  EndSelect
EndProcedure

Procedure CallBack(hwnd, msg, wParam, lParam)

  Static snapped1,snapped2,snapped3,snapped4
  result = #PB_ProcessPureBasicEvents

  If msg = #WM_MOVING
    *view.RECT = lparam
    curwidth = *view\right - *view\left
    curheight = *view\bottom - *view\top
    
    ;==============================
    ;  AutoSnap Section
    ;==============================
    If AutoSnap
      If *view\left<SnapD And *view\top<SnapD
        If Not Snapped1
          *view\left=0: *view\top=0 : *view\right = curwidth : *view\bottom = curheight
          snapped1=#True
          result=#True
        EndIf
      Else
        snapped1=#False
      EndIf
      If *view\right > screenw-SnapD And *view\top < SnapD
        If Not Snapped2
          *view\left=ScreenW-curwidth : *view\top=0 : *view\right=screenW : *view\bottom = curheight
          snapped2=#True
          result=#True
        EndIf
      Else
          snapped2=#False
      EndIf
      If *view\right > screenw-SnapD And *view\bottom > screenH-SnapD
        If Not Snapped3
          *view\left=ScreenW-curwidth : *view\top=screenH-curheight : *view\right=screenW : *view\bottom = screenH
          snapped3=#True
          result=#True
        EndIf
      Else
          snapped3=#False
      EndIf      
      If *view\left < SnapD And *view\bottom > screenH-SnapD
        If Not Snapped4
          *view\left=0 : *view\top=screenH-curheight : *view\right=curwidth : *view\bottom = screenH
          snapped4=#True
          result=#True
        EndIf
      Else
          snapped4=#False
      EndIf      
    EndIf

    ;==============================
    ;  Inside Desktop Section
    ;==============================
    If *view\top < 0 : *view\top=0 : *view\bottom = curheight : EndIf
    If *view\left < 0: *view\left=0 : *view\right = curwidth : EndIf
    If *view\right > screenW : *view\right = screenW : *view\left = *view\right-curwidth : EndIf
    If *view\bottom > screenH: *view\bottom = screenH : *view\top = *view\bottom-curheight : EndIf
    MoveWindow_(hwnd,*view\left,*view\top,*view\right-*view\left,*view\bottom-*view\top,#True)
    result = #True

  EndIf
  ProcedureReturn result
EndProcedure

OpenWindow(0,0,0,320,240,"The Dapper Snapper",$CF0001)
CreateGadgetList(WindowID(0))
ButtonGadget(1,120,80,40,20,"Snap")
ButtonGadget(2,160,80,40,20,"Snap")
ButtonGadget(3,120,100,40,20,"Snap")
ButtonGadget(4,160,100,40,20,"Snap")
ButtonGadget(5,100,160,120,20,"AutoSnap On/Off")
TextGadget(6,120,210,120,20,"AutoSnap is ON")

SetWindowCallback(@Callback())
Repeat
  EventID = WaitWindowEvent()
  If EventID = #PB_Event_Gadget
    Select EventGadget()
      Case 1
        Snap(WindowID(0), 1)
      Case 2
        Snap(WindowID(0), 2)
      Case 3
        Snap(WindowID(0), 3)
      Case 4
        Snap(WindowID(0), 4)
      Case 5
        AutoSnap = 1-AutoSnap
        SetGadgetText(6, "AutoSnap is "+StringField("OFF|ON",AutoSnap+1,"|"))
   EndSelect
 EndIf
 
Until EventID = #WM_CLOSE
If AutoSnap is on and the user moves the window to within SnapD pixels of any corner, the window will snap to that corner. The snap buttons perform a 'hard snap' and don't have an on/off state. They always work.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4792
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Post by Fangbeast »

Thank you for that. Give me a while for my lesser intellect to absorb it (grin).

:):):)

One last question..Is it easy to extend the snapping to the sides as well?

Noooo, put down that sheep!!
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Believe it or not, adding snapping to the sides to what's already there makes for simpler code. This version will snap to all four corners and all four sides:

Code: Select all

;====================================== 
; Program:    Window Snap Demo 
; Author:     netmaestro 
; Date:       October 23, 2006 
;====================================== 

Global screenW, screenH, SnapD = 50, AutoSnap=#True 

SystemParametersInfo_(#SPI_GETWORKAREA,0,@wa.RECT,0) ; Client area of the desktop 
ScreenW = wa\right 
screenH = wa\bottom 

Procedure Snap(hwnd, corner) 
  Protected w,h 
  GetWindowRect_(hwnd, @view.RECT) 
  w = view\right - view\left 
  h = view\bottom - view\top 
  Select corner 
    Case 1 
      MoveWindow_(hwnd, 0, 0, w, h, #True) 
    Case 2 
      MoveWindow_(hwnd, screenw-w,0,w,h,#True) 
    Case 3 
      MoveWindow_(hwnd,0, screenH-h,w,h,#True)    
    Case 4 
     MoveWindow_(hwnd, screenW-w,screenH-h,w,h,#True) 
  EndSelect 
EndProcedure 

Procedure CallBack(hwnd, msg, wParam, lParam) 

  Static snapped1,snapped2,snapped3,snapped4 
  result = #PB_ProcessPureBasicEvents 

  If msg = #WM_MOVING 
    *view.RECT = lparam 
    curwidth = *view\right - *view\left 
    curheight = *view\bottom - *view\top 
    
    ;============================== 
    ;  AutoSnap Section 
    ;============================== 
    If AutoSnap 
      If *view\left<SnapD 
        If Not Snapped1 
          *view\left=0: *view\right = curwidth 
          snapped1=#True 
          result=#True 
        EndIf 
      Else 
        snapped1=#False 
      EndIf 

      If *view\top < SnapD 
        If Not Snapped2 
          *view\top=0 : *view\bottom = curheight 
          snapped2=#True 
          result=#True 
        EndIf 
      Else 
          snapped2=#False 
      EndIf 
      
      If *view\right > screenw-SnapD 
        If Not Snapped3 
          *view\left=ScreenW-curwidth : *view\right=screenW 
          snapped3=#True 
          result=#True 
        EndIf 
      Else 
          snapped3=#False 
      EndIf      
      If *view\bottom > screenH-SnapD 
        If Not Snapped4 
           *view\top=screenH-curheight : *view\bottom = screenH 
          snapped4=#True 
          result=#True 
        EndIf 
      Else 
          snapped4=#False 
      EndIf      
    EndIf 

    ;============================== 
    ;  Inside Desktop Section 
    ;============================== 
    If *view\top < 0 : *view\top=0 : *view\bottom = curheight : EndIf 
    If *view\left < 0: *view\left=0 : *view\right = curwidth : EndIf 
    If *view\right > screenW : *view\right = screenW : *view\left = *view\right-curwidth : EndIf 
    If *view\bottom > screenH: *view\bottom = screenH : *view\top = *view\bottom-curheight : EndIf 
    MoveWindow_(hwnd,*view\left,*view\top,*view\right-*view\left,*view\bottom-*view\top,#True) 
    result = #True 

  EndIf 
  ProcedureReturn result 
EndProcedure 

OpenWindow(0,0,0,320,240,"The Dapper Snapper",$CF0001) 
CreateGadgetList(WindowID(0)) 
ButtonGadget(1,120,80,40,20,"Snap") 
ButtonGadget(2,160,80,40,20,"Snap") 
ButtonGadget(3,120,100,40,20,"Snap") 
ButtonGadget(4,160,100,40,20,"Snap") 
ButtonGadget(5,100,160,120,20,"AutoSnap On/Off") 
TextGadget(6,120,210,120,20,"AutoSnap is ON") 

SetWindowCallback(@Callback()) 
Repeat 
  EventID = WaitWindowEvent() 
  If EventID = #PB_Event_Gadget 
    Select EventGadget() 
      Case 1 
        Snap(WindowID(0), 1) 
      Case 2 
        Snap(WindowID(0), 2) 
      Case 3 
        Snap(WindowID(0), 3) 
      Case 4 
        Snap(WindowID(0), 4) 
      Case 5 
        AutoSnap = 1-AutoSnap 
        SetGadgetText(6, "AutoSnap is "+StringField("OFF|ON",AutoSnap+1,"|")) 
   EndSelect 
 EndIf 
  
Until EventID = #WM_CLOSE 
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4792
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Post by Fangbeast »

When may I sell my daughter to pay you money for this???? This is a seriously great bit of code and help
Post Reply