Keep a window at a certain aspect ratio

Just starting out? Need help? Post your questions and find answers here.
BarryG
Addict
Addict
Posts: 4266
Joined: Thu Apr 18, 2019 8:17 am

Re: Keep a window at a certain aspect ratio

Post by BarryG »

@Idle, your version also suffers the problem of the whole window moving away from its X/Y position when sizing from other edges - it's like it's being dragged by the title bar. Please test resizing on all four window sides, and not from just the bottom-right corner.
Last edited by BarryG on Tue Apr 04, 2023 9:56 pm, edited 3 times in total.
User avatar
jacdelad
Addict
Addict
Posts: 2044
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Keep a window at a certain aspect ratio

Post by jacdelad »

You're right, it doesn't flicker, but (and I may be blind not to see the solution) how do I write the desired height/width back so it keeps the aspect ratio?
Edit: Ah, I just tried the diagonal resizing. Horizontal/vertical works fine.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
idle
Always Here
Always Here
Posts: 6091
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Keep a window at a certain aspect ratio

Post by idle »

Aspect ratio stays the same you're given the memory pointer to the rect so all you have to do is change it but
it's complicated as special attention needs to be applied for top and left resize.

see here
https://learn.microsoft.com/en-us/windo ... /wm-sizing
User avatar
idle
Always Here
Always Here
Posts: 6091
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Keep a window at a certain aspect ratio

Post by idle »

This seems to be ok now with the corners

Code: Select all

EnableExplicit 

Procedure WinManCallBack(hwnd,msg,wparam,lparam);
  Protected *rc.rect,w,h  
  Select msg 
    Case #WM_SIZING  
      *rc = lparam 
      w = *rc\right - *rc\left 
      h = *rc\bottom - *rc\top 
      Select wparam 
        Case 1                       ;left  
          *rc\bottom = *rc\top + w            
        Case 2                       ;right  
          *rc\bottom = *rc\top + w 
        Case 3,4,7                   ;top / top Left / bottom left 
          *rc\left = *rc\right - h 
        Case 5,6,8                   ;top right / bottom / bottom right  
          *rc\right = *rc\left + h
      EndSelect       
      
  EndSelect 
  
  ProcedureReturn #PB_ProcessPureBasicEvents
  
EndProcedure

OpenWindow(0,0,0,400,400,"Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_SizeGadget)
SetWindowCallback(@WinManCallBack())

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow


User avatar
jacdelad
Addict
Addict
Posts: 2044
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Keep a window at a certain aspect ratio

Post by jacdelad »

Ah yes, this is great! Thanks!!!
There are still some minor flaws within it: The rect includes the title bar size and of course I don't only want rectangular windows). I'm on it.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
idle
Always Here
Always Here
Posts: 6091
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Keep a window at a certain aspect ratio

Post by idle »

jacdelad wrote: Tue Apr 04, 2023 10:46 pm Ah yes, this is great! Thanks!!!
There are still some minor flaws within it: The rect includes the title bar size and of course I don't only want rectangular windows). I'm on it.
just set the callback with the window number
I'm sure you can work out the title bar thing :)

Code: Select all

SetWindowCallback(@WinManCallBack(),0)
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5012
Joined: Sun Apr 12, 2009 6:27 am

Re: Keep a window at a certain aspect ratio

Post by RASHAD »

It maybe Cross Platform too
Full control with Width & Height
Using Mouse Wheel
# 1:

Code: Select all


OpenWindow(0,0,0,400,400,"Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
TH = WindowY(0,#PB_Window_InnerCoordinate)-WindowY(0,#PB_Window_FrameCoordinate)
ResizeWindow(0,#PB_Ignore,#PB_Ignore,400,400-TH)
CanvasGadget(0,0,0,400,400-th,#PB_Canvas_Keyboard |#PB_Canvas_Container)
  TextGadget(10,10,10,100,24,"Width = 400")
CloseGadgetList()
Repeat
  Select WaitWindowEvent()
  Case #PB_Event_CloseWindow
    Quit = 1
    
  Case #PB_Event_Gadget
    Select EventGadget()
      Case 0
        Select EventType()
          Case #PB_EventType_MouseWheel
            value = GetGadgetAttribute(0,#PB_Canvas_WheelDelta )
            If value > 0
              w = WindowWidth(0)+5
              h = w-TH
              ResizeWindow(0,#PB_Ignore,#PB_Ignore ,w,h)
              ResizeGadget(0,0,0,w,h)
              SetGadgetText(10,"Width = "+Str(w))
            Else
              w = WindowWidth(0)-5
              h = w-TH
              ResizeWindow(0,#PB_Ignore,#PB_Ignore ,w,h)
              ResizeGadget(0,0,0,w,h)
              SetGadgetText(10,"Width = "+Str(w))
            EndIf
            If w > 1080
              w = 1920
            ElseIf w < 300
              w=300
            EndIf         
        EndSelect
    EndSelect
  EndSelect 
Until Quit = 1

# 2:
It maybe Cross Platform too
Resize take effect after release Mouse Capture

Code: Select all

Procedure SizeCB()
  HideWindow(0,1)
EndProcedure

Procedure MoveCB()
If OSVersion() >= #PB_OS_Windows_10
  ResizeWindow(1,WindowX(0),WindowY(0)-3, WindowWidth(0),WindowWidth(0))
Else
  ResizeWindow(1,WindowX(0),WindowY(0), WindowWidth(0),WindowWidth(0))
EndIf
EndProcedure

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

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

HideWindow(0,0)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1      
      
    Case #PB_Event_MaximizeWindow
      flag = 1
     
    Case #PB_Event_SizeWindow
      If flag = 0
        ResizeWindow(0,WindowX(1),WindowY(1), WindowWidth(1),WindowHeight(1)-22)
      EndIf
      If flag = 1
        flag = 0
      EndIf
      HideWindow(0,0)       
       
  EndSelect
Until Quit = 1
Egypt my love
AZJIO
Addict
Addict
Posts: 2241
Joined: Sun May 14, 2017 1:48 am

Re: Keep a window at a certain aspect ratio

Post by AZJIO »

RASHAD
We need behavior, if we increase one of the sides, then we want to increase the window. Sometimes the window size reverts to its original state, instead of increasing the window. If we use corner points to resize the window, then here we can also make an assessment of which sides are resized in percentage terms. If one side increased by 10%, and the other side decreased by 5%, then we take 10% as the criterion, since this is a larger indicator. Then we will have the behavior of the window as the user expected. If 10% increase and 10% decrease, then do nothing +-2%.
You also need to change the window from the center in different directions at the same time. We pull to the right, and the left side also moves to the left.
You can add AddWindowTimer() to recalculate the window after the mouse is released.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5012
Joined: Sun Apr 12, 2009 6:27 am

Re: Keep a window at a certain aspect ratio

Post by RASHAD »

Why don't you do that to see how good you are Mr.X :wink:
No more Bla ..Bla
Egypt my love
User avatar
jacdelad
Addict
Addict
Posts: 2044
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Keep a window at a certain aspect ratio

Post by jacdelad »

idle wrote: Wed Apr 05, 2023 2:17 am
jacdelad wrote: Tue Apr 04, 2023 10:46 pm Ah yes, this is great! Thanks!!!
There are still some minor flaws within it: The rect includes the title bar size and of course I don't only want rectangular windows). I'm on it.
just set the callback with the window number
I'm sure you can work out the title bar thing :)

Code: Select all

SetWindowCallback(@WinManCallBack(),0)
I have 8 hours of nothing do to ahead, I'm on it. :D
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
idle
Always Here
Always Here
Posts: 6091
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Keep a window at a certain aspect ratio

Post by idle »

jacdelad wrote: Wed Apr 05, 2023 8:54 pm
idle wrote: Wed Apr 05, 2023 2:17 am
jacdelad wrote: Tue Apr 04, 2023 10:46 pm Ah yes, this is great! Thanks!!!
There are still some minor flaws within it: The rect includes the title bar size and of course I don't only want rectangular windows). I'm on it.
just set the callback with the window number
I'm sure you can work out the title bar thing :)

Code: Select all

SetWindowCallback(@WinManCallBack(),0)
I have 8 hours of nothing do to ahead, I'm on it. :D
for the title bar height you can use this in the call back

Code: Select all

Procedure WinManCallBack(hwnd,msg,wparam,lparam);
  Protected *rc.rect,*rc1.rect,rcc.rect,w,h 
  Static tbsize  
  
  If Not tbsize 
    tbsize = GetSystemMetrics_(#SM_CYMIN)
  EndIf 
    
  Select msg 
    Case #WM_SIZING  
      *rc = lparam 
      w = *rc\right - *rc\left 
      h = *rc\bottom - *rc\top 
      Select wparam 
        Case 1                       ;left  
          *rc\bottom = *rc\top + w           
        Case 2                       ;right  
          *rc\bottom = *rc\top + w 
        Case 3,4,7                   ;top / top Left / bottom left 
          *rc\left = *rc\right - (h-tbsize) 
        Case 5,6,8                   ;top right / bottom / bottom right  
          *rc\right = *rc\left + (h-tbsize)
      EndSelect       
      Debug Str(w) + "," + Str(h) 
  EndSelect 
  
  ProcedureReturn #PB_ProcessPureBasicEvents
  
EndProcedure

OpenWindow(0,0,0,400,400,"Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_SizeGadget)
SetWindowCallback(@WinManCallBack())

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
User avatar
jacdelad
Addict
Addict
Posts: 2044
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Keep a window at a certain aspect ratio

Post by jacdelad »

Thanks idle, but I think this can cause problem, because GetWindowRect_() has different behavious since Windows Vista (it includes the shadow) and may change again.

However, I'm done. This is what I created from your template:

Code: Select all

;EnableExplicit 
Structure _AR
  Window.i
  Ratio.f
  dx.l
  dy.l
EndStructure
Global NewMap AspectRatioMap._AR()
Procedure WinManCallBack(hwnd,msg,wparam,lparam);
  Protected *rc.rect,w,h  
  Select msg 
    Case #WM_SIZING  
      If FindMapElement(AspectRatioMap(),Str(hwnd))
        *rc = lparam 
        w = *rc\right - *rc\left - AspectRatioMap(Str(hwnd))\dx
        h = *rc\bottom - *rc\top - AspectRatioMap(Str(hwnd))\dy
        Select wparam 
          Case 1,2;Left,right
            *rc\bottom = *rc\top + w/AspectRatioMap(Str(hwnd))\Ratio + AspectRatioMap(Str(hwnd))\dy
          Case 3,6;Top,Bottom
            *rc\right = *rc\left + h*AspectRatioMap(Str(hwnd))\Ratio + AspectRatioMap(Str(hwnd))\dx
          Case 4;Top Left
            If w/AspectRatioMap(Str(hwnd))\Ratio<h
              *rc\top = *rc\bottom - w/AspectRatioMap(Str(hwnd))\Ratio - AspectRatioMap(Str(hwnd))\dy
            Else
              *rc\left = *rc\right - h*AspectRatioMap(Str(hwnd))\Ratio - AspectRatioMap(Str(hwnd))\dx
            EndIf
          Case 7;Bottom Left 
            If w/AspectRatioMap(Str(hwnd))\Ratio<h
              *rc\bottom = *rc\top + w/AspectRatioMap(Str(hwnd))\Ratio + AspectRatioMap(Str(hwnd))\dy
            Else
              *rc\left = *rc\right - h*AspectRatioMap(Str(hwnd))\Ratio - AspectRatioMap(Str(hwnd))\dx
            EndIf
          Case 5;Top Right
            If w/AspectRatioMap(Str(hwnd))\Ratio<h
              *rc\top = *rc\bottom - w/AspectRatioMap(Str(hwnd))\Ratio - AspectRatioMap(Str(hwnd))\dy
            Else
              *rc\right = *rc\left + h*AspectRatioMap(Str(hwnd))\Ratio + AspectRatioMap(Str(hwnd))\dx
            EndIf
          Case 8;Bottom Right  
            If w/AspectRatioMap(Str(hwnd))\Ratio<h
              *rc\bottom = *rc\top + w/AspectRatioMap(Str(hwnd))\Ratio + AspectRatioMap(Str(hwnd))\dy
            Else
              *rc\right = *rc\left + h*AspectRatioMap(Str(hwnd))\Ratio + AspectRatioMap(Str(hwnd))\dx
            EndIf
        EndSelect       
      EndIf
  EndSelect 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure SetWindowAspectRatio(Window.i,Enable=#True)
  Protected rect.rect,WindowID.i=WindowID(Window)
  If Enable
    GetWindowRect_(WindowID(Window),rect)
    AspectRatioMap(Str(WindowID))\Window=Window
    AspectRatioMap(Str(WindowID))\Ratio=WindowWidth(Window,#PB_Window_InnerCoordinate)/WindowHeight(Window,#PB_Window_InnerCoordinate)
    AspectRatioMap(Str(WindowID))\dy=rect\bottom-rect\top-WindowHeight(Window,#PB_Window_InnerCoordinate)
    AspectRatioMap(Str(WindowID))\dx=rect\right-rect\left-WindowWidth(Window,#PB_Window_InnerCoordinate)
    SetWindowCallback(@WinManCallBack(),Window)
  Else
    If FindMapElement(AspectRatioMap(),Str(WindowID))
      SetWindowCallback(0,AspectRatioMap(Str(WindowID))\Window)
      DeleteMapElement(AspectRatioMap(),Str(WindowID))
    EndIf
  EndIf
EndProcedure

CompilerIf #PB_Compiler_IsMainFile
  OpenWindow(0,0,0,550,175,"Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_SizeGadget)
  SetWindowAspectRatio(0,1)
  
  Repeat
  Until WaitWindowEvent()=#PB_Event_CloseWindow
CompilerEndIf
...and it's working exactly as I wanted to have it!
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
idle
Always Here
Always Here
Posts: 6091
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Keep a window at a certain aspect ratio

Post by idle »

Nice that seems to work well!
User avatar
jacdelad
Addict
Addict
Posts: 2044
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Keep a window at a certain aspect ratio

Post by jacdelad »

Thanks and yeah, it's great. I just need to add some code to make it work with WindowBounds(). This doesn't work yet.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
idle
Always Here
Always Here
Posts: 6091
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Keep a window at a certain aspect ratio

Post by idle »

jacdelad wrote: Thu Apr 06, 2023 12:02 am Thanks and yeah, it's great. I just need to add some code to make it work with WindowBounds(). This doesn't work yet.
I tried that too and wasn't sure what was going on with the windowbounds function but you can do it in the callback adding the min and max parameters to your structure and then do the fiddling in the cases if result > min or result > max
Post Reply