Page 1 of 3

Resizing third-party window that has a minimum

Posted: Mon Feb 11, 2013 4:16 pm
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.

Re: Resizing third-party window that has a minimum

Posted: Mon Feb 11, 2013 6:52 pm
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)


Re: Resizing third-party window that has a minimum

Posted: Mon Feb 11, 2013 7:51 pm
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.

Re: Resizing third-party window that has a minimum

Posted: Mon Feb 11, 2013 8:43 pm
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.

Re: Resizing third-party window that has a minimum

Posted: Mon Feb 11, 2013 9:09 pm
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 


Re: Resizing third-party window that has a minimum

Posted: Mon Feb 11, 2013 9:13 pm
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.

Re: Resizing third-party window that has a minimum

Posted: Tue Feb 12, 2013 9:02 am
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).

Re: Resizing third-party window that has a minimum

Posted: Tue Feb 12, 2013 9:31 am
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).

Re: Resizing third-party window that has a minimum

Posted: Tue Feb 12, 2013 11:40 am
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.

Re: Resizing third-party window that has a minimum

Posted: Sun Apr 03, 2022 11:00 am
by SharkyEXE
Hello

Please, help me, how resize this window?

Code: Select all

Define dir.BROWSEINFO
dir\ulFlags = #BIF_EDITBOX
SHBrowseForFolder_(@dir)
Thank You!

Re: Resizing third-party window that has a minimum

Posted: Mon Apr 04, 2022 10:17 pm
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)

Re: Resizing third-party window that has a minimum

Posted: Tue Apr 05, 2022 8:13 pm
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

Re: Resizing third-party window that has a minimum

Posted: Tue Apr 05, 2022 11:24 pm
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)

Re: Resizing third-party window that has a minimum

Posted: Wed Apr 06, 2022 3:09 pm
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?

Re: Resizing third-party window that has a minimum

Posted: Wed Apr 06, 2022 5:52 pm
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.