Window resize event only after mouse release?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2071
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Window resize event only after mouse release?

Post by Andre »

Using the #PB_Event_SizeWindow event I'm currently getting resize events after every single pixel change in width/height of the window. So an event is triggered already while the user has the mouse cursor still pressed...

This can be useful of course, but as I'm having very complex GUIs / dialogs (containing a lot of gadgets, charts, filled listicons which content need to be recalculated after a size change, etc.) I can't and don't want to react to every window width/height change (for only 1 pixel) while the user is still resizing the window.

So I'm searching for a solution, where the GUI/dialog resize function is only called, when the mouse cursor was released and the user's resizing action is finished.

The only releated thread I found is this one: http://www.purebasic.fr/english/viewtop ... vent+mouse

What was called a bug here, is my wanted behaviour 8)
(probably even a feature-request for a new #PB_Event_SizeWindowFinished or similar... :mrgreen:)

Currently I have only the idea of a workaround: save the old window size (before resize was started) and don't react to every pixel change, but to every +/- 10 pixel or more...

Anyone has a code example, which works on Windows and MacOS?

Thank you very much! :D
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
wombats
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Dec 29, 2011 5:03 pm

Re: Window resize event only after mouse release?

Post by wombats »

Unless I'm missing something, this seems to do what you want:

Code: Select all

If OpenWindow(0, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)

  Repeat
    Event = WaitWindowEvent()

    If Event = #PB_Event_CloseWindow
      Quit = 1
    EndIf
    
    If Event = #PB_Event_SizeWindow
      Debug "Window resized"
    EndIf

  Until Quit = 1
  
EndIf

End
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Window resize event only after mouse release?

Post by mk-soft »

Works fine with MacOS, Window 7 and windows 10

Code: Select all

Procedure UpdateWindow()
  Debug "Update Window"
EndProcedure


Procedure SizeWindowHandler()
  Static dx, dy, old_dx, old_dy
  Protected delta_dx, delta_dy
  dx = WindowWidth(0)
  dy = WindowHeight(0)
  delta_dx = old_dx - dx
  delta_dy = old_dy - dy
  If delta_dx < -5 Or delta_dx > 5 Or delta_dy < -5 Or delta_dy > 5
    old_dx = dx
    old_dy = dy
    UpdateWindow()
  EndIf
EndProcedure

If OpenWindow(0, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
  
  BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())
  
  Repeat
    Event = WaitWindowEvent()

    If Event = #PB_Event_CloseWindow
      Quit = 1
    EndIf
    
    If Event = #PB_Event_SizeWindow
      UpdateWindow()
      Debug "Finished Size Window"
    EndIf

  Until Quit = 1
  
EndIf

End
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4664
Joined: Sun Apr 12, 2009 6:27 am

Re: Window resize event only after mouse release?

Post by RASHAD »

Workaround

Code: Select all

Procedure SizeCB()
  HideWindow(1,1)
EndProcedure

Procedure MoveCB()
  ResizeWindow(0,WindowX(1),WindowY(1), #PB_Ignore, #PB_Ignore)
EndProcedure

OpenWindow(0,0,0,800,600,"",#PB_Window_BorderLess |#PB_Window_SizeGadget|#PB_Window_ScreenCentered  &~ #PB_Window_TitleBar)
OpenWindow(1,0,0,800,578,"Main window",#PB_Window_SystemMenu |#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered| #PB_Window_Invisible,WindowID(0))
StickyWindow(0,1)

BindEvent(#PB_Event_MoveWindow ,@MoveCB())
BindEvent(#PB_Event_SizeWindow ,@SizeCB())

HideWindow(1,0)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1      
      
    Case #PB_Event_MaximizeWindow
      flag = 1
     
    Case #PB_Event_SizeWindow
      If flag = 0
        ResizeWindow(1,WindowX(0),WindowY(0), WindowWidth(0),WindowHeight(0)-22)
      EndIf
      If flag = 1
        flag = 0
      EndIf
      HideWindow(1,0)       
       
  EndSelect
Until Quit = 1
Egypt my love
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2071
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: Window resize event only after mouse release?

Post by Andre »

Thank you for your suggestions, friends! :D

@wombats: This "normal behaviour" is what I want to avoid, because in this case every change of the window size will be recognized and my "UpdateSize" procedure need to react already during resizing of the window by the user. My goal is to react (at least for some parts of my GUI, see first post) only when the user has finished the resizing (= released the mouse).

@mk-soft: seems to work fine, at least here on Win10 (need to be tested on MacOS too).

@RASHAD: during resizing the hiding/displaying of the second window leads to a mostly hidden titlebar of the main window during resizing. So this workaround would be visible for the user...

Currenty the solution of mk-soft seems the way to go.

With my question I initially hoped, that there isn't needed any workaround, if there would be some additional OS events on Windows/MacOS (not natively supported by PB), which could be used instead of #PB_Event_SizeWindow and which are only fired if the mouse was released by the user (= resizing finished).

So any more ideas are welcome! :D
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Window resize event only after mouse release?

Post by JHPJHP »

Hi Andre,

Someone might post script for OSX, so here is a Windows only option:

Code: Select all

Global lpPrevWndFunc

Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
  Select uMsg
    Case #WM_ENTERSIZEMOVE : Debug "Start Resize"
    Case #WM_EXITSIZEMOVE : Debug "End Resize"
  EndSelect
  ProcedureReturn CallWindowProc_(lpPrevWndFunc, hWnd, uMsg, wParam, lParam)
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Resize Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  lpPrevWndFunc = SetWindowLongPtr_(WindowID(0), #GWL_WNDPROC, @WindowCallback())
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Window resize event only after mouse release?

Post by mk-soft »

For all OS and without API (Update)

Code: Select all

;- Top

#TimerSizeWindow = 999

Enumeration #PB_Event_FirstCustomValue
  #PB_Event_SizeWindowFinished
EndEnumeration

Procedure UpdateWindow(window, dx, dy)
  Debug "Update (window=" + window + ", dx=" + dx + ", dy=" + dy + ")"
EndProcedure


Procedure SizeWindowHandler()
  Static old_dx, old_dy, timer, time_dx, time_dy
  Protected window, dx, dy, delta_dx, delta_dy
  
  window = EventWindow()
  dx = WindowWidth(window)
  dy = WindowHeight(window)
  
  Select Event()
    Case #PB_Event_SizeWindow
      If Not timer
        Debug "Add Timer"
        timer = #True
        AddWindowTimer(window, #TimerSizeWindow, 200)
      EndIf
      delta_dx = old_dx - dx
      delta_dy = old_dy - dy
      If delta_dx < -5 Or delta_dx > 5 Or delta_dy < -5 Or delta_dy > 5
        old_dx = dx
        old_dy = dy
        UpdateWindow(window, dx, dy)
      EndIf
    Case #PB_Event_Timer
      If EventTimer() = #TimerSizeWindow
        delta_dx = time_dx - dx
        delta_dy = time_dy - dy
        time_dx = dx
        time_dy = dy
        If delta_dx = 0 And delta_dy = 0
          UpdateWindow(window, dx, dy)
          Debug "Remove Timer"
          timer = #False
          RemoveWindowTimer(window, #TimerSizeWindow)
          PostEvent(#PB_Event_SizeWindowFinished, window, 0)
        EndIf
      EndIf
  EndSelect
  
EndProcedure

If OpenWindow(1, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
  
  BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())
  BindEvent(#PB_Event_Timer, @SizeWindowHandler())
  
  Repeat
    Event = WaitWindowEvent()

    If Event = #PB_Event_CloseWindow
      Quit = 1
    EndIf
    
    If Event = #PB_Event_SizeWindowFinished
      Debug "Finished SizeWindow"
    EndIf
    
  Until Quit = 1
  
EndIf

End
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
wombats
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Dec 29, 2011 5:03 pm

Re: Window resize event only after mouse release?

Post by wombats »

Andre wrote: @wombats: This "normal behaviour" is what I want to avoid, because in this case every change of the window size will be recognized and my "UpdateSize" procedure need to react already during resizing of the window by the user. My goal is to react (at least for some parts of my GUI, see first post) only when the user has finished the resizing (= released the mouse).
Oh...maybe I'm misunderstanding what you are trying to achieve, then. On my laptop (Windows 10), the debug message in my code is only sent when the mouse is released. Maybe it's different on OS X and Linux...I don't remember. Regardless, that's why I use BindEvent() in my program, as it allows for live resizing.

There is this code by Shardik.
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2071
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: Window resize event only after mouse release?

Post by Andre »

Thank you, guys! :mrgreen:

@wombats: I'm also on Win10 here (beside my MacBook). As I'm getting the resize event also during resizing, I came to this question... Thank you anyway for the link to the code example on german PB forum.

@mk-soft: As I'm prefering a solution without API / native PB commands I tried your latest example (on Win10) and it works very well. Thank you very much! :D

Here this solution again with some small modifications - now there is a Debug output only when the window resizing is finished.

Code: Select all

; http://www.purebasic.fr/english/viewtopic.php?f=13&t=68481
; by mk-soft, small changes by André

;- Top

#TimerSizeWindow = 999

Enumeration #PB_Event_FirstCustomValue
  #PB_Event_SizeWindowFinished
EndEnumeration

Procedure UpdateWindow(window, dx, dy)
  Debug "Update (window=" + window + ", dx=" + dx + ", dy=" + dy + ")"
EndProcedure


Procedure SizeWindowHandler()
  Static old_dx, old_dy, timer, time_dx, time_dy
  Protected window, dx, dy, delta_dx, delta_dy
 
  window = EventWindow()
  dx = WindowWidth(window)
  dy = WindowHeight(window)
 
  Select Event()
    Case #PB_Event_SizeWindow
      If Not timer
        ;Debug "Add Timer"
        timer = #True
        AddWindowTimer(window, #TimerSizeWindow, 200)
      EndIf
      delta_dx = old_dx - dx
      delta_dy = old_dy - dy
      If delta_dx < -5 Or delta_dx > 5 Or delta_dy < -5 Or delta_dy > 5
        old_dx = dx
        old_dy = dy
        ;UpdateWindow(window, dx, dy)
      EndIf
    Case #PB_Event_Timer
      If EventTimer() = #TimerSizeWindow
        delta_dx = time_dx - dx
        delta_dy = time_dy - dy
        time_dx = dx
        time_dy = dy
        If delta_dx = 0 And delta_dy = 0
          ;UpdateWindow(window, dx, dy)
          ;Debug "Remove Timer"
          timer = #False
          RemoveWindowTimer(window, #TimerSizeWindow)
          PostEvent(#PB_Event_SizeWindowFinished, window, 0)
        EndIf
      EndIf
  EndSelect
 
EndProcedure

If OpenWindow(1, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
 
  BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())
  BindEvent(#PB_Event_Timer, @SizeWindowHandler())
 
  Repeat
    Event = WaitWindowEvent()

    If Event = #PB_Event_CloseWindow
      Quit = 1
    EndIf
   
    If Event = #PB_Event_SizeWindowFinished
      Debug "Finished SizeWindow"
      Debug "...new window size: " + WindowWidth(1) + "x" + WindowHeight(1)
    EndIf
   
  Until Quit = 1
 
EndIf

End
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2071
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: Window resize event only after mouse release?

Post by Andre »

Just to check, if/how several windows can be handled and own window-specific callback functions work, I extended the example of mk-soft a bit further... here is the result, based on this I will try to include it in my project now 8)

Code: Select all

; http://www.purebasic.fr/english/viewtopic.php?f=13&t=68481
; by mk-soft, small changes by André

;- Top

#TimerSizeWindow = 999

Enumeration #PB_Event_FirstCustomValue
  #PB_Event_SizeWindowFinished
EndEnumeration

Procedure UpdateWindow(window, dx, dy)
  Debug "Update (window=" + window + ", dx=" + dx + ", dy=" + dy + ")"
EndProcedure


Procedure SizeWindowHandler()
  Static old_dx, old_dy, timer, time_dx, time_dy
  Protected window, dx, dy, delta_dx, delta_dy
 
  window = EventWindow()
  dx = WindowWidth(window)
  dy = WindowHeight(window)
 
  Select Event()
    Case #PB_Event_SizeWindow
      If Not timer
        ;Debug "Add Timer"
        timer = #True
        AddWindowTimer(window, #TimerSizeWindow, 200)
      EndIf
      delta_dx = old_dx - dx
      delta_dy = old_dy - dy
      If delta_dx < -5 Or delta_dx > 5 Or delta_dy < -5 Or delta_dy > 5
        old_dx = dx
        old_dy = dy
        ;UpdateWindow(window, dx, dy)
      EndIf
    Case #PB_Event_Timer
      If EventTimer() = #TimerSizeWindow
        delta_dx = time_dx - dx
        delta_dy = time_dy - dy
        time_dx = dx
        time_dy = dy
        If delta_dx = 0 And delta_dy = 0
          ;UpdateWindow(window, dx, dy)
          ;Debug "Remove Timer"
          timer = #False
          RemoveWindowTimer(window, #TimerSizeWindow)
          PostEvent(#PB_Event_SizeWindowFinished, window, 0)
        EndIf
      EndIf
  EndSelect
 
EndProcedure

Procedure UpdateSize_1stWindow()
  Debug "UpdateSize_1stWindow() function reached.... here further action on this specific window can be going on :-)"
  Debug "  new pos+size: " + WindowX(1) + "," + WindowY(1) + " with " + WindowWidth(1) + "x" + WindowHeight(1)
EndProcedure

Procedure UpdateSize_2ndWindow()
  Debug "UpdateSize_2ndWindow() function reached.... here further action on this specific window can be going on :-)"
  Debug "  new pos+size: " + WindowX(2) + "," + WindowY(2) + " with " + WindowWidth(2) + "x" + WindowHeight(2)
EndProcedure


If OpenWindow(1, 50, 100, 400, 200, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
  OpenWindow(2, 470, 300, 400, 200, "PureBasic 2nd Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
  
  BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())
  BindEvent(#PB_Event_Timer, @SizeWindowHandler())
  
  BindEvent(#PB_Event_SizeWindowFinished, @UpdateSize_1stWindow(), 1)
  BindEvent(#PB_Event_SizeWindowFinished, @UpdateSize_2ndWindow(), 2)
  
  Repeat
    Event = WaitWindowEvent()
    EventWindow = EventWindow()

    If Event = #PB_Event_CloseWindow
      Quit = 1
    EndIf
    
    ; Note: Following code isn't needed, as it's fully covered by the BindEvent() functions!
    ;If Event = #PB_Event_SizeWindowFinished
    ;  Debug "Finished SizeWindow of window: " + GetWindowTitle(EventWindow)
    ;  Debug "...new window size: " + WindowWidth(EventWindow) + "x" + WindowHeight(EventWindow)
    ;EndIf
   
  Until Quit = 1
 
EndIf

End
Edit 18th June 2017: bug-fix + now there specific BindEvent() resize functions for the 2 windows :)
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
Post Reply