Page 1 of 1

Control Position And Size of Requesters [Windows]

Posted: Wed Sep 08, 2010 5:50 pm
by RASHAD
Control Position And Size of Requesters [Windows]
RASHAD 08/09/2010

The Default behavior is the left top corner of the parent window
This code is for control the position And size w/o any parent window

1 : Using Watching Thread
1-1 OpenFileRequester

Code: Select all

Global hwnd,ReqText$,x,y,w,h,flag

Procedure Center(parameter)
  Repeat
    hwnd = FindWindow_(0,ReqText$)
    r.RECT
    GetWindowRect_(hwnd,r)
    ExamineDesktops()
    If w =0 Or h = 0 Or OSVersion() <= #PB_OS_Windows_XP
       w = r\right - r\left
       h = r\bottom - r\top
    EndIf    
    If hwnd And flag = 0
      MoveWindow_(hwnd,x,y,w,h,1)
      InvalidateRect_(hwnd,0,1)
    ElseIf hwnd And flag = 1
      x = (DesktopWidth(0) - w)/2
      y = (DesktopHeight(0) - h)/2      
      MoveWindow_(hwnd,x,y,w,h,1)
      InvalidateRect_(hwnd,0,1)
    EndIf
    run = run + 1
  Until run = 1000
EndProcedure

;ClassName$ = "#32770"   ;"InputRequester"

ReqText$ = "Please choose file to load"                ;For OpenFileRequester or Any Text else
x = 100
y = 100
w = 900            ; 0 = OS Default Width & Height            
h = 600            ; 0 = OS Default Width & Height
flag = 1           ; 1 = Center   0 = At x,y Position

Thread = CreateThread(@Center(),100) 


  StandardFile$ = "C:\autoexec.bat"   ; set initial file+path to display
  ; With next string we will set the search patterns ("|" as separator) for file displaying:
  ;  1st: "Text (*.txt)" as name, ".txt" and ".bat" as allowed extension
  ;  2nd: "PureBasic (*.pb)" as name, ".pb" as allowed extension
  ;  3rd: "All files (*.*) as name, "*.*" as allowed extension, valid for all files
  Pattern$ = "Text (*.txt)|*.txt;*.bat|PureBasic (*.pb)|*.pb|All files (*.*)|*.*"
  Pattern = 0    ; use the first of the three possible patterns as standard
  File$ = OpenFileRequester("Please choose file to load", StandardFile$, Pattern$, Pattern)
  If File$
    MessageRequester("Information", "You have selected following file:" + Chr(10) + File$, 0)
  Else
    MessageRequester("Information", "The requester was canceled.", 0) 
  EndIf  
  
  If IsThread(Thread)
    KillThread(Thread)
  EndIf
1-2 FontRequester

Code: Select all


  Global hwnd,ReqText$,x,y,w,h,flag

Procedure Center(parameter)
  Repeat
    hwnd = FindWindow_(0,ReqText$)
        r.RECT
        GetWindowRect_(hwnd,r)
        ExamineDesktops()
        If w =0 Or h = 0
           w = r\right - r\left
           h = r\bottom - r\top
        EndIf    
        If hwnd And flag = 0
          MoveWindow_(hwnd,x,y,w,h,1)
        ElseIf hwnd And flag = 1
          x = (DesktopWidth(0) - w)/2
          y = (DesktopHeight(0) - h)/2      
          MoveWindow_(hwnd,x,y,w,h,1)
        EndIf
        run = run + 1
  Until run = 1000
EndProcedure

ReqText$ = "Font"           ;For FontRequester
x = 100                     ;Upper Corner Left Pos
y = 100                     ;Upper Corner Top Pos
flag = 1                    ;1 = Center   0 = At x,y Position

Thread = CreateThread(@Center(),100)
  
  FontName$ = "Arial"   ; set initial font  (could also be blank)
  FontSize  = 14        ; set initial size  (could also be null)
  Result = FontRequester(FontName$, FontSize, #PB_FontRequester_Effects)
  If Result
    Message$ = "You have selected following font:"  + #LF$ 
    Message$ + "Name:  " + SelectedFontName()       + #LF$
    Message$ + "Size:  " + Str(SelectedFontSize())  + #LF$
    Message$ + "Color: " + Str(SelectedFontColor()) + #LF$
    If SelectedFontStyle() & #PB_Font_Bold
      Message$ + "Bold" + #LF$
    EndIf
    If SelectedFontStyle() & #PB_Font_StrikeOut
      Message$ + "StrikeOut" + #LF$
    EndIf
    If SelectedFontStyle() & #PB_Font_Underline
      Message$ + "Underline" + #LF$
    EndIf
  Else 
    Message$ = "The requester was canceled."
  EndIf
  
  MessageRequester("FontRequester", Message$, #PB_MessageRequester_Ok)
  
  If IsThread(Thread)
    KillThread(Thread)
  EndIf
2 : Hooking CBT

2-1 OpenFileRequester

Code: Select all

  Global hwnd,ReqText$

Procedure HookCB ( uMsg , wParam , lParam)
   
   Select uMsg
     Case #HCBT_SETFOCUS
       For i = 1 To 10
          hwnd = FindWindow_(0,ReqText$)
          r.RECT
          GetWindowRect_(hwnd,r)
          ExamineDesktops()
          w = r\right - r\left
          h = r\bottom - r\top
          x = (DesktopWidth(0) - w)/2
          y = (DesktopHeight(0) - h)/2
          MoveWindow_(hwnd,x,y,w,h,1)
        Next

   EndSelect
   
   ProcedureReturn #False
EndProcedure


Hook = SetWindowsHookEx_ ( #WH_CBT , @ HookCB () , GetModuleHandle_ (0) , GetCurrentThreadId_ () )


ReqText$ = "test"
OpenFileRequester ( "test" , "*.*" , "*.*" , 0 )

UnhookWindowsHookEx_( Hook )

I hope it worth it

Re: Control Position And Size of Requesters [Windows]

Posted: Thu Sep 09, 2010 8:21 pm
by blueznl
The user Eddy produced something similar ages :-) ago. I've posted it below for reference. At first glance it seems to be a different approach but I'm no expert in these things...

Code: Select all


Procedure.i x_requesterposition_callback(window.i,message.i,wparam.i,lparam.i)               ; used for x_setrequesterposition()
  Protected result.i
  ; Global x_requesterposition_x.i, x_requesterposition_y.i, x_requesterposition_callback.i
  ; Global x_requesterposition_hook.i, x_requesterposition_window.i
  ;
  Select message
  Case #WM_DESTROY
    SetWindowLong_(window,#GWL_WNDPROC,x_requesterposition_callback)
  Case #WM_CREATE                            ; update requester position (special case for InputRequester)
    SetWindowPos_(window,#HWND_TOPMOST,x_requesterposition_x,x_requesterposition_y,0,0,#SWP_NOSIZE|#SWP_NOACTIVATE)
  Case #WM_INITDIALOG                        ; update requester position
    SetWindowPos_(Window,#HWND_TOPMOST,x_requesterposition_x,x_requesterposition_y,0,0,#SWP_NOSIZE|#SWP_NOACTIVATE)
    result = CallWindowProc_(x_requesterposition_callback,window,message,wparam,lparam)
    SetWindowPos_(Window,#HWND_TOPMOST,x_requesterposition_x,x_requesterposition_y,0,0,#SWP_NOSIZE|#SWP_NOACTIVATE)
    ProcedureReturn result                                      
  EndSelect
  ProcedureReturn CallWindowProc_(x_requesterposition_callback,window,message,wparam,lparam)
EndProcedure

Procedure.i x_requesterposition_hook(idhook.i,wparam.i,lparam.i)                             ; used for x_setrequesterposition()
  Protected *x_requesterposition_cwp.CWPSTRUCT, windowclass.s, result.i, message.i, window.i
  ; Global x_requesterposition_x.i, x_requesterposition_y.i, x_requesterposition_callback.i
  ; Global x_requesterposition_hook.i, x_requesterposition_window.i
  ;
  *x_requesterposition_cwp.CWPSTRUCT = lParam
  message = *x_requesterposition_cwp\Message
  window = *x_requesterposition_cwp\hwnd
  ;
  ; special case for InputRequester
  ;
  windowClass = Space(255)
  GetClassName_(window,@windowclass,255)
  If LCase(windowclass)="inputrequester"
    message = #WM_INITDIALOG
  EndIf
  ;
  Select message
  Case #WM_INITDIALOG                            ; modify Requester callback
    x_requesterposition_callback = SetWindowLong_(window,#GWL_WNDPROC,@x_requesterposition_callback())
    result = CallNextHookEx_(x_requesterposition_hook, idHook,wParam,lParam)
    UnhookWindowsHookEx_(x_requesterposition_hook)
    x_requesterposition_hook = 0
  Default
    result = CallNextHookEx_(x_requesterposition_hook,idhook,wparam,lparam)
  EndSelect
  ;
  ProcedureReturn result                                      
EndProcedure

Procedure x_setrequesterposition(x.i,y.i,windownr.i)                                         ; set x/y position of the next purebasic requester
  ; Global x_requesterposition_x.i, x_requesterposition_y.i, x_requesterposition_callback.i
  ; Global x_requesterposition_hook.i, x_requesterposition_window.i
  ;
  ; *** set x/y position of the next purebasic requester
  ;
  ; in:        x.l       - horizontal position
  ;            y.l       - vertical position
  ;            windownr  - number of parentwindow
  ; retval:    none
  ; out:       none
  ;
  ; from the purebasic forum, by eddy, dunno how it works, or even if it works properly... :-)
  ;
  ; note: only call this with a window open! otherwise it may cause all sorts of unpredictable errors, if neccessary open
  ;       an invisible window with x_requesterposition_window = OpenWindow(#PB_Any,x,y,0,0,#PB_Window_Invisible,"")
  ;
  x_requesterposition_x = x
  x_requesterposition_y = y
  x_requesterposition_window = windownr
  ;
  ; modify parent hook
  ;
  x_requesterposition_hook = SetWindowsHookEx_(#WH_CALLWNDPROC,@x_requesterposition_hook(),GetModuleHandle_(0),GetWindowThreadProcessId_(WindowID(x_requesterposition_window),0))
  ;
EndProcedure

Re: Control Position And Size of Requesters [Windows]

Posted: Thu Sep 09, 2010 9:10 pm
by RASHAD
@blueznl Hi
What do you think ? I am the first one :lol:
When I have any problem I go google saying to myself I am not the only stupid
And yes sir I found at least 1000 having the same problem
But may be my code is less difficulty
Ok see the next code may be you will like it
It is using Timed Hook

And thank you I just copied eddy code to my archive

Code: Select all


Global hwnd,ReqText$,x,y,w,h,flag,Hook

Procedure HookTimer(hwnd, uMsg, Event, Time)
    UnhookWindowsHookEx_( Hook )
EndProcedure

Procedure HookCB ( uMsg , wParam , lParam)
   
   Select uMsg
     Case #HC_ACTION
          hwnd = FindWindow_(0,ReqText$)
          r.RECT
          GetWindowRect_(hwnd,r)
          ExamineDesktops()
          If w =0 Or h = 0
             w = r\right - r\left
             h = r\bottom - r\top
          EndIf   
          If hwnd And flag = 0
            MoveWindow_(hwnd,x,y,w,h,1)
          ElseIf hwnd And flag = 1
            x = (DesktopWidth(0) - w)/2
            y = (DesktopHeight(0) - h)/2     
            MoveWindow_(hwnd,x,y,w,h,1)
          EndIf
 
   EndSelect
   
   ProcedureReturn #False
EndProcedure

Timer = SetTimer_(#Null, 0, 1000, @HookTimer())
Hook = SetWindowsHookEx_ ( #WH_FOREGROUNDIDLE, @ HookCB () , 0, GetCurrentThreadId_ ())


ReqText$ = "test"
x = 100 
y = 100 
w = 800                   ; 0 = OS Default Width & Height
h = 500                   ; 0 = OS Default Width & Height
flag = 1

OpenFileRequester ( "test" , "*.*" , "*.*" , 0 )

KillTimer_(#Null, Timer)
have a good day sir

Edit : A quick look at Eddy code it seems to me he is using Window which I am avoiding in my code
It is totally different

Re: Control Position And Size of Requesters [Windows]

Posted: Fri Sep 10, 2010 8:21 am
by blueznl
In my eyes you are the first one! :-)

I found your solution interesting, and matched it against Eddy's. In my eyes anyone who tackles a problem him / herself is 'a first', it's all too easy to throw yet another library at something.

Though, to be honest, it's a fine line... when does it makes sense to use 'external' stuff, and when not... I've pretty much choosen to stick to 'core' PureBasic and WinApi and not rely on user libraries, but I must say I have deployed a few DLL's in the past :-) Shame on me 8)

Re: Control Position And Size of Requesters [Windows]

Posted: Fri Sep 10, 2010 7:34 pm
by Michael Vogel
Good code (also copying them to my "finest examples" collection) :P

What I did in the past is (far) not as good as all examples above, anyhow I post it for the sake of completeness:

Code: Select all

OpenWindow(1,GetSystemMetrics_(#SM_CXSCREEN)>>2,GetSystemMetrics_(#SM_CYSCREEN)>>2,0,0,"",#PB_Window_BorderLess)
Requester.s=OpenFileRequester(" Programm zum Kompaktieren auswählen...","","Ausführbare Programme (*.dll,*.exe)|*.exe;*.dll|Alle Dateien (*.*)|*.*",0,#PB_Requester_MultiSelection)
CloseWindow(1)

Re: Control Position And Size of Requesters [Windows]

Posted: Sun Sep 12, 2010 9:24 am
by Baldrick
@RASHAD, I have only tried the 1 snippet of your code which is the OpenFileRequester() snippet & have found a bit of a problem you might wish to have a bit of a look at.
What happens here is if you run the code & drag the requester to any part of the screen, when you either select a file followed by clicking the Open or cancel buttons the requester instead of closing instead jumps back to it's original screen centered position.
Same result here on PB 4.40 & 4.50. WinXp Sp3, 32 bit

Re: Control Position And Size of Requesters [Windows]

Posted: Sun Sep 12, 2010 10:11 am
by RASHAD
@blueznl
Thank you very much for your kind words You are a gentelman as usual
I am late to thank you but that is because some guys makes me hate to see my name on the net so I have to be conservative

@Michael
Thank you mate for your support
Lately you added to my archive The TextGadget and the ampersand snippet
Then The enforced overwright for the EditorGadet then this one
BTW:I liked much your Sport Programme Interface (It has the Pro touch indeed)

@Baldrick
Yes you are right this is the third snippet from the first post with windows 7
I decided to leave it that way and worked with a much better Timed Hook the second post

Thank you mate for your comment and have not a good day but at least a good year

Thank you boys I needed that to keep going

Re: Control Position And Size of Requesters [Windows]

Posted: Mon Jun 01, 2015 1:14 am
by ozzie
Thank you, Forum users and especially RASHAD, for saving the day yet again! In my program I've started using a 3rd-party library for handling video playback, but this library seems to create new windows of its own - on the secondary monitor, and then I find my MessageRequester() dialogs get displayed in the middle of this secondary monitor, not on the primary monitor. After much searching I came across RASHAD's solution in this thread that uses the timed hook, and after adapting that slightly for my requirements it appears to have solved the problem perfectly when used with MessageRequester(). :D

Re: Control Position And Size of Requesters [Windows]

Posted: Fri Dec 16, 2016 4:52 pm
by Dreamland Fantasy
RASHAD wrote:

Code: Select all


Global hwnd,ReqText$,x,y,w,h,flag,Hook

Procedure HookTimer(hwnd, uMsg, Event, Time)
    UnhookWindowsHookEx_( Hook )
EndProcedure

Procedure HookCB ( uMsg , wParam , lParam)
   
   Select uMsg
     Case #HC_ACTION
          hwnd = FindWindow_(0,ReqText$)
          r.RECT
          GetWindowRect_(hwnd,r)
          ExamineDesktops()
          If w =0 Or h = 0
             w = r\right - r\left
             h = r\bottom - r\top
          EndIf   
          If hwnd And flag = 0
            MoveWindow_(hwnd,x,y,w,h,1)
          ElseIf hwnd And flag = 1
            x = (DesktopWidth(0) - w)/2
            y = (DesktopHeight(0) - h)/2     
            MoveWindow_(hwnd,x,y,w,h,1)
          EndIf
 
   EndSelect
   
   ProcedureReturn #False
EndProcedure

Timer = SetTimer_(#Null, 0, 1000, @HookTimer())
Hook = SetWindowsHookEx_ ( #WH_FOREGROUNDIDLE, @ HookCB () , 0, GetCurrentThreadId_ ())


ReqText$ = "test"
x = 100 
y = 100 
w = 800                   ; 0 = OS Default Width & Height
h = 500                   ; 0 = OS Default Width & Height
flag = 1

OpenFileRequester ( "test" , "*.*" , "*.*" , 0 )

KillTimer_(#Null, Timer)
I've just given this code a try and noticed a bug. If I run the code and then maximise the window by double-clicking on the titlebar, close it and then re-run the code, I am no longer able to move the window about the screen.

I guess that Windows thinks that the window is still maximised so will not allow you to move it. If I double-click on the titlebar again the window moves to the top left of the screen and can now be moved.

Kind regards,

Francis