Page 1 of 1

SOLVED : centering a dialog in an app

Posted: Sun Oct 15, 2023 3:06 pm
by Blue
A Windows question.

When an app displays a message in a dialog box, the OS Windows outputs the resulting dialog box in the centre of the screen.
But i'd really like to have that dialog box centered in my app, whatever its position.

Is there a PB or an API parameter or a method that will allow me to do that ?

Code: Select all

; A simple example
; Blue — October 15 2023

OpenWindow(0, 140, 140, 300, 300, "Some Windows app", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)

ButtonGadget(0, 20,20,120,24,"I have a request...")
Procedure Display_message()
  Protected.s msg = "I'd like to be centered" + Chr(10) + "in my app..." 
  MessageRequester("Information", msg, 0)
EndProcedure 

Repeat
  event = WaitWindowEvent()
  Select event
    Case #PB_Event_CloseWindow : Break
    Case #PB_Event_Gadget : Display_message()
  EndSelect
ForEver
End
Thanks in advance...

Re: How can I force Windows to center a dialog in my app ?

Posted: Sun Oct 15, 2023 4:14 pm
by firace
One way, using a callback (original code by netmaestro) - Use as a starting point

Code: Select all



Procedure MsgCallback(hWnd, Message, wParam, lParam)   
  Protected msgwin
  Select message
    Case #WM_WINDOWPOSCHANGING
      msgwin=FindWindow_("#32770", "Confirmation required") 
      If msgwin
        SetWindowPos_(msgwin,0,windowX(0)+40,windowY(0)+80,0,0,#SWP_NOSIZE|#SWP_NOZORDER)
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


OpenWindow(0, 100, 100, 540, 380, "")

SetWindowCallback(@MsgCallBack())


MessageRequester("Confirmation required", "Are you sure?", #PB_MessageRequester_YesNo)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 

Re: How can I force Windows to center a dialog in my app ?

Posted: Sun Oct 15, 2023 5:24 pm
by Blue
Thank you Firace.
That's certainly a very promising step in the right direction.
Using NetMaestro's method, it becomes possible to position the dialog box very precisely.

If I may be so curious, how did you come across this code by NetMaestro ? I spent over a good hour searching the forum, and i found nothing even approaching this. Could you provide a link to NetMaestro's original code ?

The method he uses is what i was trying to implement; but try as I may, I just couldn't figure out the correct way to apply my calculated coordinates to the dialog box BEFORE it was displayed by the system. It was quite frustrating...

So, again, a big thank you.

addendum : ————————————————————————————————
Using MsgCallback as a search word, I found everything required, and more.
original code : viewtopic.php?p=136950&hilit=MsgCallback#p136950


.

Re: SOLVED : centering a dialog in an app

Posted: Sun Oct 15, 2023 9:46 pm
by Blue
The annoying thing with the method suggested by NetMaestro is that all the dialog boxes in a given app have to use the exact same title to identify themselves. Otherwise, the Callback function won't find them and, therefore, won't be able to apply the repositioning hack.

Re: SOLVED : centering a dialog in an app

Posted: Sun Oct 15, 2023 10:14 pm
by AZJIO
Blue
I wrote the following code on AutoIt3, or rather there were two of them, one created a window in the visible area, the other centered it in the program and at the same time made it in the visible area, but apparently I did one code and not the second. When the dialog is centered, a problem arises if the window is partially moved off the screen, then the child window may appear off the screen and the user will not have access to it. You don’t see what is written there, it is possible to remove the disk from the OS, and the question is “Yes or No”, you press Enter expecting the worst consequences. You can't pull out the parent window because the child denies access to it until the child is closed, checkmate.

Try dragging the window off the screen and clicking the button

Code: Select all

EnableExplicit

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

;- Enumeration
Enumeration
	#Win0
	#Win_About
EndEnumeration

#w0_btn = 0

Global About$, ProgName$

Declare Win_About(ProgName$, Width = 270, Height = 170, WinID = -1)

ProgName$ = "ProgName"
About$ = "About"

;- GUI
OpenWindow(#Win0, 0, 0, 420, 300, "Win", #PB_Window_SizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)

ButtonGadget(#w0_btn, 10, 10, 110, 30, About$)

;- Loop
Repeat
	Select WaitWindowEvent()
		Case #PB_Event_Gadget
			Select EventGadget()
				Case #w0_btn
					Win_About(ProgName$, 300, 220, #Win0)
			EndSelect
		Case #PB_Event_CloseWindow
			CloseWindow(#Win0)
			End
	EndSelect
ForEver


Procedure ChildCoor(*gp.Rect2, nWnd, w, h, c=0, d=0)
	Protected DX, DY
	*gp\w = WindowWidth(nWnd)
	*gp\h = WindowHeight(nWnd)
	*gp\x = WindowX(nWnd)
	*gp\y = WindowY(nWnd)
	ExamineDesktops()
	DX=DesktopWidth(0)
	DY=DesktopHeight(0)
	If c = 0
		*gp\x=*gp\x+(*gp\w-w)/2
		*gp\y=*gp\y+(*gp\h-h)/2
	EndIf
	If *gp\x+w+d>DX
		*gp\x=DX-w-10-d
	EndIf
	If *gp\y+h+60+d>DY
		*gp\y=DY-h-70-d
	EndIf
	If *gp\x<=d
		*gp\x=d
	EndIf
	If *gp\y<=d
		*gp\y=d
	EndIf
	*gp\w=w
	*gp\h=h
EndProcedure


Procedure Win_About(ProgName$, Width = 270, Height = 170, WinID = -1)
	Protected hWnd
	Protected gp.Rect2
	If WinID > -1
		hWnd = WindowID(WinID)
		DisableWindow(WinID, #True)
	Else
		hWnd = 0
	EndIf
	
	ChildCoor(@gp, #Win0, Width, Height, 0, 30)

	If OpenWindow(#Win_About, gp\x, gp\y, gp\w, gp\h, About$, #PB_Window_SystemMenu | #PB_Window_TitleBar, WindowID(#Win0))

		Repeat
		Until WaitWindowEvent() = #PB_Event_CloseWindow

		If hWnd
			DisableWindow(WinID, #False)
		EndIf
		CloseWindow(#Win_About)
		ProcedureReturn 0
	EndIf
EndProcedure

Re: SOLVED : centering a dialog in an app

Posted: Mon Oct 16, 2023 8:02 am
by firace
Blue wrote: Sun Oct 15, 2023 9:46 pm The annoying thing with the method suggested by NetMaestro is that all the dialog boxes in a given app have to use the exact same title to identify themselves. Otherwise, the Callback function won't find them and, therefore, won't be able to apply the repositioning hack.

Adapted to support multiple captions - hope this helps!

Code: Select all

Procedure MsgCallback(hWnd, Message, wParam, lParam)   
  Protected msgwin
  Select message
    Case #WM_WINDOWPOSCHANGING
      captions.s = "Confirmation required::Prompt::Please confirm"  ;; match all these captions - "::" is the separator
      
      for a = 1 to CountString(captions, "::") + 1
        msgwin=FindWindow_("#32770", StringField(captions, a, "::"))
        if msgwin
          break
        endif 
      next 
           
      If msgwin
        SetWindowPos_(msgwin,0,windowX(0)+40,windowY(0)+80,0,0,#SWP_NOSIZE|#SWP_NOZORDER)
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


OpenWindow(0, 100, 100, 540, 380, "")

SetWindowCallback(@MsgCallBack())


MessageRequester("Confirmation required", "Are you sure?", #PB_MessageRequester_YesNo)
MessageRequester("Please confirm", "Are you sure?", #PB_MessageRequester_YesNo)
MessageRequester("Not this one", "Are you sure?", #PB_MessageRequester_YesNo)
MessageRequester("Prompt", "Are you sure?", #PB_MessageRequester_YesNo)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 

Re: SOLVED : centering a dialog in an app

Posted: Mon Oct 16, 2023 8:59 am
by Shardik
Thread MessageRequester centered with your main window from Juli 2009 with examples from flaith and netmaestro.

Re: SOLVED : centering a dialog in an app

Posted: Mon Oct 16, 2023 3:13 pm
by Blue
You've been hard at work, firace...
firace wrote: Mon Oct 16, 2023 8:02 am [...]
Adapted to support multiple captions - hope this helps!

Code: Select all

[...]
Procedure MsgCallback(hWnd, Message, wParam, lParam)
 {etc}   
EndProcedure
[...]
Great minds definitely think alike !
I did exactly what you're suggesting here.

And, as you've already been able to verify, it works nicely.

Thanks firace

Re: SOLVED : centering a dialog in an app

Posted: Mon Oct 16, 2023 6:53 pm
by Sicro
This is how I did it in an old program of mine.

If the window #Window_Main was moved partially out of the screen, it does not work. Then the message requester is in the middle of the screen again.

Code: Select all

Enumeration Window
  #Window_Main
EndEnumeration

Enumeration Gadget
  #Button_Show_MsgBox
EndEnumeration

Global.RECT screenRect
Global resetWorkAreaTimer

Procedure ResetWorkArea(hWnd, uMsg, wParam, lParam)
  ; Reset the work area size
  SystemParametersInfo_(#SPI_SETWORKAREA, 0, @screenRect, 0)
  KillTimer_(0, resetWorkAreaTimer)
EndProcedure

Procedure ShowMsgBox()
  Protected.RECT windowRect
  Protected result = #False
  
  ; Reduce work area to the size of #Window_Main
  If SystemParametersInfo_(#SPI_GETWORKAREA, 0, @screenRect, 0) And
     GetWindowRect_(WindowID(#Window_Main), @windowRect)
    result = SystemParametersInfo_(#SPI_SETWORKAREA, 0, @windowRect, 0)
  EndIf
  
  If result
    resetWorkAreaTimer = SetTimer_(0, 0, 1, @ResetWorkArea())
  EndIf
    
  MessageRequester("Example", "This is a centered message box.")
EndProcedure

OpenWindow(#Window_Main, 300, 300, 800, 800, "Test", #PB_Window_SystemMenu)
ButtonGadget(#Button_Show_MsgBox, 800/2 - 100/2, 800/2 - 20/2, 100, 20, "Show MsgBox")

Repeat
  event = WaitWindowEvent()
  If event = #PB_Event_Gadget
    ShowMsgBox()
  EndIf
Until event = #PB_Event_CloseWindow

Re: SOLVED : centering a dialog in an app

Posted: Mon Oct 16, 2023 7:14 pm
by AZJIO
I'd like to illustrate my thesis with an example.

Code: Select all

Global DsktpWidth
ExamineDesktops()
DsktpWidth = DesktopWidth(0)


Procedure MsgCallback(hWnd, Message, wParam, lParam)   
  Protected msgwin
  Select message
    Case #WM_WINDOWPOSCHANGING
      captions.s = "Format the hard drive"  ;; match all these captions - "::" is the separator
      
      For a = 1 To CountString(captions, "::") + 1
        msgwin=FindWindow_("#32770", StringField(captions, a, "::"))
        If msgwin
          Break
        EndIf 
      Next 
           
      If msgwin
        SetWindowPos_(msgwin,0,WindowX(0)+40,WindowY(0)+80,0,0,#SWP_NOSIZE|#SWP_NOZORDER)
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

; While the backup was in progress, we moved the window to the side
OpenWindow(0, DsktpWidth - 40, 100, 540, 380, "Press Enter/Esc if you don’t know what to do, maybe you’ll get lucky")

SetWindowCallback(@MsgCallBack())


If MessageRequester("Format the hard drive", "Unable to create a data backup. Format a hard disk without a backup?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
	Debug "Thank you for agreeing to format your hard drive."
EndIf

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow