Page 1 of 1

Positioning of MessageRequester

Posted: Sun Apr 02, 2006 8:41 pm
by Klonk
Is there a way to position MessageRequester? By default they are ScreenCentered.

Any ideas?

Re: Positioning of MessageRequester

Posted: Sun Apr 02, 2006 10:02 pm
by PB

Posted: Mon Apr 03, 2006 4:37 am
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.

Posted: Mon Apr 03, 2006 5:58 am
by Dare2
Thank you netmaestro, I will be trying this tonight. :)

Posted: Mon Apr 03, 2006 10:49 am
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