Positioning of MessageRequester

Just starting out? Need help? Post your questions and find answers here.
Klonk
Enthusiast
Enthusiast
Posts: 173
Joined: Tue Jul 13, 2004 2:17 pm

Positioning of MessageRequester

Post by Klonk »

Is there a way to position MessageRequester? By default they are ScreenCentered.

Any ideas?
Bye Karl
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Positioning of MessageRequester

Post by PB »

I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

In the case of a message requester, the requester is coming out at a location unrelated to any windows you have opened. So you have to set the position of the requester using MoveWindow_() or similar based on its handle. Easy enough, right? Except that the MessageRequester will hold up processing while it waits for input. Bummer. So - you play a little trick on it. Call the positioning procedure as a thread instead of normally:

Code: Select all

Procedure SetMessagePos(pos) 
  Protected x,y,t,hWnd 
  x = pos>>16 : y = pos & $FFFF 
  hWnd=0 : t=GetTickCount_() 
  While hWnd=0 
    hWnd = FindWindow_(#Null,"Notice") 
    If GetTickCount_()-t > 500 : Break : EndIf 
    Delay(1)
  Wend 
  If hWnd : SetWindowPos_(hWnd,0,x,y,0,0,#SWP_NOSIZE|#SWP_NOZORDER) : EndIf
EndProcedure 

OpenWindow(0,0,0,320,240,"Test Window",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
CreateGadgetList(WindowID(0)) 
ButtonGadget(0,80,180,150,22,"Show Message") 
Repeat 
  EventID = WaitWindowEvent(1) 
  Select EventID 
    Case #PB_Event_Gadget 
      x=20 : y=20 : pos=x<<16+y 
      CreateThread(@SetMessagePos(),pos) 
      MessageRequester("Notice","This isn't the center!") 
  EndSelect 
Until EventID = #PB_Event_CloseWindow
You can only pass the thread one long as parameter. So here I'm packing the x and y position into the high- and low- order words of a long and sending it that way. You could just as easily use global vars or something if bit-shifting isn't your thing. The proc will only try to find the MessageRequester window for 500 milliseconds before giving up. If it hasn't found it in that time, it isn't going to. Actual performance is the window is found on the very first loop.
Last edited by netmaestro on Fri Apr 21, 2006 2:51 am, edited 12 times in total.
BERESHEIT
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

Thank you netmaestro, I will be trying this tonight. :)
@}--`--,-- A rose by any other name ..
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

The way I showed you above should work well, but it has the weakness that if it takes a few loops to find the window, it could flash the messagebox in the center of the screen briefly before repositioning it. To ensure that doesn't happen, we can use a different approach which will catch the window on creation and position it before it gets shown:

Code: Select all

Procedure MsgCallback(hWnd, Message, wParam, lParam)
  Select message
    Case #WM_WINDOWPOSCHANGING
      msgwin=FindWindow_("#32770", #Null) ;No need to loop, we know it's there
      If msgwin
        SetWindowPos_(msgwin,0,20,20,0,0,#SWP_NOSIZE|#SWP_NOZORDER)
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

OpenWindow(0,0,0,320,240,"Test Window",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(0))
ButtonGadget(0,80,200,150,22,"Show Message")
SetWindowCallback(@MsgCallBack())
Repeat
  EventID = WaitWindowEvent(1)
  Select EventID
    Case #PB_Event_Gadget
      MessageRequester("Notice","This isn't in the center")
  EndSelect
Until EventID = #PB_Event_CloseWindow
BERESHEIT
Post Reply