Resizing third-party window that has a minimum

Just starting out? Need help? Post your questions and find answers here.
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Resizing third-party window that has a minimum

Post by MachineCode »

I'm trying to resize a third-party app's window with SetWindowPos_(), basically to just its title bar, but it won't let me set it that small. It's obviously got some minimum size restriction. Can that be overridden with some API call? I've searched but cannot find. Thanks for any tips.
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Resizing third-party window that has a minimum

Post by RASHAD »

I am not sure if it works with your case
But it works with Calculator

Code: Select all

RunProgram("Calc.exe")

Repeat
hWnd = FindWindow_(0,"Calculator")
Until hWnd

SetWindowLongPtr_(hWnd, #GWL_STYLE, GetWindowLongPtr_(hWnd, #GWL_STYLE) |#WS_SIZEBOX)
Delay(200)
MoveWindow_(hWnd,10,10,300,50,1)

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

Re: Resizing third-party window that has a minimum

Post by netmaestro »

In PureBasic we have the WindowBounds() command which sets limits on the window size. If a PB programmer set window bounds on a window I doubt that a third party program could size it outside those limits, as it will refuse even a native ResizeWindow() that is out of bounds. That being the case, the window you are trying to resize may be using the same technique for enforcing size limits and if it is I don't think there's going to be a way to overcome it.
BERESHEIT
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Resizing third-party window that has a minimum

Post by Danilo »

PB program with WindowBounds():

Code: Select all

If OpenWindow(0, 0, 0, 300, 300, "Resize me !", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
    WindowBounds(0, 200, 200, 400, 400)
    StickyWindow(0,1)
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Resizing program:

Code: Select all

Repeat
    hWnd = FindWindow_(0,"Resize me !")
Until hWnd

GetWindowRect_(hWnd,@r.RECT)
SetWindowPos_(hWnd,0,r\left,r\top,r\right-r\left,35,#SWP_NOSENDCHANGING|#SWP_NOACTIVATE)

MessageRequester("INFO","OK")
Works here. The target window does not know it got resized with #SWP_NOSENDCHANGING.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Resizing third-party window that has a minimum

Post by RASHAD »

@Danilo Fantastic
It works even with

Code: Select all

Global wr.RECT

Procedure WinProc(hwnd, msg, wparam, lparam)
  result=#PB_ProcessPureBasicEvents
  Select msg
    Case #WM_WINDOWPOSCHANGING
      *wp.WINDOWPOS = lparam
      With *wp
        \x=wr\left
        \y=wr\top
        \cx = wr\right-wr\left
        \cy = wr\bottom-wr\top
      EndWith
      result=0
  EndSelect
  ProcedureReturn result
EndProcedure

OpenWindow(0,400,400,320,240,"TEST",#PB_Window_SizeGadget|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget)
SetWindowCallback(@WinProc())
GetWindowRect_(WindowID(0), wr)

Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow 

Egypt my love
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Resizing third-party window that has a minimum

Post by ts-soft »

Windows Bounds is more like this API:

Code: Select all

EnableExplicit

Procedure wincb(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected mm.MINMAXINFO
  
  Select uMsg
    Case #WM_GETMINMAXINFO
      mm\ptMinTrackSize\x = 100
      mm\ptMinTrackSize\y = 100
      mm\ptMaxTrackSize\x = 700
      mm\ptMaxTrackSize\y = 500
      CopyMemory(@mm, lParam, SizeOf(MINMAXINFO))
      Result = 0
  EndSelect
  
  ProcedureReturn Result
EndProcedure

OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "Resize me !", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
SetWindowCallback(@wincb())
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver
Resizing works a bit.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: Resizing third-party window that has a minimum

Post by MachineCode »

Rashad, your code doesn't work with an app called "Star Downloader", but Danilo's does, do Danilo wins! :) Thanks, Dan. (I also prefer Danilo's because it doesn't alter the style of the target window).
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Resizing third-party window that has a minimum

Post by Danilo »

MachineCode wrote:Rashad, your code doesn't work with an app called "Star Downloader", but Danilo's does, do Danilo wins! :) Thanks, Dan. (I also prefer Danilo's because it doesn't alter the style of the target window).
Thank you very much! :)

Just wanted to say something about the window height. I had hard-coded it to height 35,
because GetSystemMetrics_(#SM_CYCAPTION) did not return the correct height for WinXP styled windows.
It may be better to calculate the size from the window rectangle and the window client rectangle:

Code: Select all

GetWindowRect_(hWnd,@r.RECT)  ; get window outer rectangle/bounds
GetClientRect_(hWnd,@cr.RECT) ; get size of window client area (inner width, where the 'gadgets' are located)
SetWindowPos_(hWnd,0,r\left,r\top,r\right-r\left,r\bottom-r\top-cr\bottom+MenuHeight(),#SWP_NOSENDCHANGING|#SWP_NOACTIVATE)
Remove "+MenuHeight()" (it is just an example) and you should get a window that is always the size of the border and titlebar only (XP style enabled or disabled, all Windows versions).
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: Resizing third-party window that has a minimum

Post by MachineCode »

Danilo wrote:GetSystemMetrics_(#SM_CYCAPTION) did not return the correct height for WinXP styled windows
What about GetSystemMetrics_(#SM_CYMIN) instead? Seems to work fine on Win 7, but I can't test on XP. It's what I'm using now.
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
SharkyEXE
User
User
Posts: 35
Joined: Sat Feb 26, 2022 6:33 pm

Re: Resizing third-party window that has a minimum

Post by SharkyEXE »

Hello

Please, help me, how resize this window?

Code: Select all

Define dir.BROWSEINFO
dir\ulFlags = #BIF_EDITBOX
SHBrowseForFolder_(@dir)
Thank You!
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Resizing third-party window that has a minimum

Post by breeze4me »

SharkyEXE wrote: Sun Apr 03, 2022 11:00 am Hello

Please, help me, how resize this window?

Code: Select all

Define dir.BROWSEINFO
dir\ulFlags = #BIF_EDITBOX
SHBrowseForFolder_(@dir)
Thank You!
This is a simple example of using a thread. Alternatively, you may use message hook.

Code: Select all

Structure FolderNewPos
  x.l
  y.l
  w.l
  h.l
EndStructure

Procedure ResizeFolderWnd(*pos.FolderNewPos)
  Protected hWnd, i
  
  If *pos
    For i = 1 To 2000
      hWnd = FindWindow_("#32770", 0)
      If hWnd
        If GetForegroundWindow_() = hWnd
          MoveWindow_(hWnd, *pos\x, *pos\y, *pos\w, *pos\h, 1)
          ;SetWindowPos_(hWnd, 0, *pos\x, *pos\y, *pos\w, *pos\h, #SWP_NOZORDER | #SWP_FRAMECHANGED)
          Break
        EndIf
      EndIf
      Delay(1)
    Next
  EndIf
EndProcedure

Define newpos.FolderNewPos
newpos\x = 10
newpos\y = 10
newpos\w = 500
newpos\h = 700

CreateThread(@ResizeFolderWnd(), newpos)

Define dir.BROWSEINFO

dir\ulFlags = #BIF_EDITBOX | #BIF_NEWDIALOGSTYLE   ; #BIF_NEWDIALOGSTYLE flag is essential. Without the flag, child controls cannot be rearranged.
SHBrowseForFolder_(@dir)
SharkyEXE
User
User
Posts: 35
Joined: Sat Feb 26, 2022 6:33 pm

Re: Resizing third-party window that has a minimum

Post by SharkyEXE »

breeze4me wrote: Mon Apr 04, 2022 10:17 pm
Hello

Your script if i click on folder - expand tree

I do not have, if i click on folder - expand tree

I my exapmle
Define dir.BROWSEINFO
dir\ulFlags = #BIF_EDITBOX
SHBrowseForFolder_(@dir)
if i click on folder - NOT expand tree

Please, write, how make in your script, if i click on folder - NOT expand tree
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Resizing third-party window that has a minimum

Post by breeze4me »

SharkyEXE wrote: Tue Apr 05, 2022 8:13 pm
Hello

Your script if i click on folder - expand tree

I do not have, if i click on folder - expand tree

I my exapmle
Define dir.BROWSEINFO
dir\ulFlags = #BIF_EDITBOX
SHBrowseForFolder_(@dir)
if i click on folder - NOT expand tree

Please, write, how make in your script, if i click on folder - NOT expand tree
Try this.

Code: Select all

#BFFM_INITIALIZED = 1

Structure FolderNewPos
  hMutex.i
  hWnd.i
  x.l
  y.l
  w.l
  h.l
EndStructure

Procedure ResizeFolderWnd(*pos.FolderNewPos)
  Protected i
  For i = 0 To 1000
    If TryLockMutex(*pos\hMutex)
      FreeMutex(*pos\hMutex)
      If *pos\hWnd
        SetWindowPos_(*pos\hWnd, 0, *pos\x, *pos\y, *pos\w, *pos\h, #SWP_NOZORDER | #SWP_NOOWNERZORDER | #SWP_FRAMECHANGED | #SWP_SHOWWINDOW)
      EndIf
      Break
    EndIf
    Delay(50)
  Next
EndProcedure

; Procedure EnumChildProc(hwnd, lParam)
;   Protected Buffer.s{64}
;   
;   If GetClassName_(hwnd, @Buffer, 63)
;     If FindString(Buffer, "treeview", 1, #PB_String_NoCase)
;       SetWindowLong_(hwnd, #GWL_STYLE, GetWindowLong_(hwnd, #GWL_STYLE) & ~#TVS_SINGLEEXPAND)
;       ProcedureReturn 0
;     EndIf
;   EndIf
;   
;   ProcedureReturn 1
; EndProcedure

Procedure BrowseCallbackProc(hwnd, uMsg, lParam, *lpData.FolderNewPos)
  Protected Buffer.s, hShell, hTree
  
  If uMsg = #BFFM_INITIALIZED
    SetWindowPos_(hWnd, 0, -30000, -30000, 0, 0, #SWP_NOZORDER | #SWP_NOOWNERZORDER | #SWP_NOSIZE | #SWP_HIDEWINDOW)
    Repeat
      hShell = GetDlgItem_(hwnd, 0)
      If hShell
        hTree = GetDlgItem_(hShell, 100)
        If hTree
          Buffer = Space(64)
          If GetClassName_(hTree, @Buffer, 63)
            If FindString(Buffer, "treeview", 1, #PB_String_NoCase)
              SetWindowLong_(hTree, #GWL_STYLE, GetWindowLong_(hTree, #GWL_STYLE) & ~#TVS_SINGLEEXPAND)
              Break
            EndIf
          EndIf
        EndIf
      EndIf
      
      ;EnumChildWindows_(hwnd, @EnumChildProc(), 0)   ;If the above attempt fails, try again here.
      Break
    ForEver
    
    ;;MoveWindow_(hwnd, *lpData\x, *lpData\y, *lpData\w, *lpData\h, 1)  ;It does not work properly, so do the following.
    
    *lpData\hWnd = hwnd
    UnlockMutex(*lpData\hMutex)
  EndIf
  
  ProcedureReturn 0
EndProcedure


Define newpos.FolderNewPos
newpos\x = 50
newpos\y = 50
newpos\w = 400
newpos\h = 500
newpos\hMutex = CreateMutex()

If newpos\hMutex
  LockMutex(newpos\hMutex)
  CreateThread(@ResizeFolderWnd(), newpos)
  
  Define dir.BROWSEINFO
  dir\lpfn = @BrowseCallbackProc()
  dir\lParam = @newpos
  dir\ulFlags = #BIF_EDITBOX | #BIF_NEWDIALOGSTYLE   ; #BIF_NEWDIALOGSTYLE flag is essential. Without the flag, child controls cannot be rearranged.
  SHBrowseForFolder_(@dir)
EndIf

A better way.

Code: Select all

#BFFM_INITIALIZED = 1

Structure FolderNewPos
  x.l
  y.l
  w.l
  h.l
EndStructure

#App_WndProcString = "AppOldWndProc"

Global newpos.FolderNewPos

Procedure FolderWndProc(hWnd, Message, wParam, lParam)
  Protected old = GetProp_(hWnd, #App_WndProcString)
  
  If Message = #WM_ACTIVATE
    SetWindowPos_(hWnd, 0, newpos\x, newpos\y, newpos\w, newpos\h, #SWP_NOZORDER | #SWP_NOOWNERZORDER | #SWP_FRAMECHANGED)
    SetWindowLongPtr_(hWnd, #GWLP_WNDPROC, old)
    RemoveProp_(hWnd, #App_WndProcString)
  EndIf
  
  ProcedureReturn CallWindowProc_(old, hWnd, Message, wParam, lParam)
EndProcedure

; Procedure EnumChildProc(hwnd, lParam)
;   Protected Buffer.s{64}
;   
;   If GetClassName_(hwnd, @Buffer, 63)
;     If FindString(Buffer, "treeview", 1, #PB_String_NoCase)
;       SetWindowLong_(hwnd, #GWL_STYLE, GetWindowLong_(hwnd, #GWL_STYLE) & ~#TVS_SINGLEEXPAND)
;       ProcedureReturn 0
;     EndIf
;   EndIf
;   
;   ProcedureReturn 1
; EndProcedure

Procedure BrowseCallbackProc(hwnd, uMsg, lParam, lpData)
  Protected Buffer.s, hShell, hTree, old
  
  If uMsg = #BFFM_INITIALIZED
    Repeat
      hShell = GetDlgItem_(hwnd, 0)
      If hShell
        hTree = GetDlgItem_(hShell, 100)
        If hTree
          Buffer = Space(64)
          If GetClassName_(hTree, @Buffer, 63)
            If FindString(Buffer, "treeview", 1, #PB_String_NoCase)
              SetWindowLong_(hTree, #GWL_STYLE, GetWindowLong_(hTree, #GWL_STYLE) & ~#TVS_SINGLEEXPAND)
              Break
            EndIf
          EndIf
        EndIf
      EndIf
      
      ;EnumChildWindows_(hwnd, @EnumChildProc(), 0)   ;If the above attempt fails, try again here.
      Break
    ForEver
    
    old = SetWindowLongPtr_(hwnd, #GWLP_WNDPROC, @FolderWndProc())
    SetProp_(hwnd, #App_WndProcString, old)
  EndIf
  
  ProcedureReturn 0
EndProcedure


newpos\x = 50
newpos\y = 50
newpos\w = 400
newpos\h = 500

Define dir.BROWSEINFO
dir\lpfn = @BrowseCallbackProc()
dir\ulFlags = #BIF_EDITBOX | #BIF_NEWDIALOGSTYLE   ; #BIF_NEWDIALOGSTYLE flag is essential. Without the flag, child controls cannot be rearranged.
SHBrowseForFolder_(@dir)
SharkyEXE
User
User
Posts: 35
Joined: Sat Feb 26, 2022 6:33 pm

Re: Resizing third-party window that has a minimum

Post by SharkyEXE »

breeze4me

Hello

Very-very thank You!

Your 2 code work perfectly - if i click on folder - NOT expand tree

Little question - what different on two code, whats code is better or in work two code work 100 percent identically or not?
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Resizing third-party window that has a minimum

Post by breeze4me »

SharkyEXE wrote: Wed Apr 06, 2022 3:09 pm breeze4me

Hello

Very-very thank You!

Your 2 code work perfectly - if i click on folder - NOT expand tree

Little question - what different on two code, whats code is better or in work two code work 100 percent identically or not?
Both do the same thing, but the second code is lighter and more efficient. The first one is somewhat inefficient because it uses a mutex and a thread.
So I recommend the second one.
Post Reply