Show box on top, keep dialog onscreen

Started by User_McUser, January 26, 2026, 09:53:16 AM

Previous topic - Next topic

User_McUser

I have a custom dialog and I want it to stay visible on-screen while the script runs. The script takes a while to run so I want a place to show progress updates to the user while they wait. A box seems like an easy way to do this but the box always appears *behind* (z-order) the dialog. I tried calling "WinActivate" using the box's caption but that did not work.

What mojo is needed to move the Box to be above (z-order) the dialog?

Thanks! 😀

td

Not sure that it will work, but have you tried the WindowOnTop function?

WindowOnTop
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

User_McUser

Thank you for the suggestion; unfortunately this did not work. 🙁

The overall script is used to query user profiles on a PC so we can reclaim disk space. The subroutine with the Box calls is below in case I made an obvious mistake. It is invoked from the @dePbPush callback for the main dialog.

#DefineSubRoutine getComputerInfo(getSize)

	theFolders = Arrayize(DirItemize("%theBasePath%*.*"), @TAB)
	theLength = ArrInfo(theFolders, 1) - 1
	
	if theLength < 0 then
		Message("ERROR", "Could not get folder list from %theBasePath%%@CRLF%%@CRLF%Make sure you have Admin permissions on the target device.")
		return 0
	endif
	
	profileCount = 0
	profileList = ""
	
	for i = 0 to theLength
		username = theFolders[i]
		if StrCmp(StrLower(username), "administrator") == 0 then next
		if StrCmp(StrLower(username), "defaultapppool") == 0 then next
		if StrCmp(StrLower(username), "public") == 0 then next
		if StrCmp(StrLower(username), "default") == 0 then next
		if StrCmp(StrLower(username), "defaultuser0") == 0 then next
		if StrCmp(StrLower(username), "all users") == 0 then next
		profileCount += 1
		profileList = ItemInsert(username, -1, profileList, @TAB)
	endfor
	
	tempArray = Arrayize(profileList, @TAB)
	profileArray = ArrDimension(profileCount+1,6)

	if profileCount == 0 then
		Message("No Profiles Found", "Something went terribly wrong - didn't find any folders in %theBasePath%")
		exit
	endif

	profileArray[0,0] = "Checkbox"
	profileArray[0,1] = "Username"
	profileArray[0,2] = "Account AD Status"
	profileArray[0,3] = "Profile Size (GB)"
	profileArray[0,4] = "Last Login"
	profileArray[0,5] = "Profile Path"

	if getSize == @TRUE then
		BoxeNew(1, "0,0,200,200", 2)
		BoxCaption(1, "Calculating Profile Sizes")
		BoxDataTag(1, "theDataTag")
		BoxesUp("400,400,600,600", @normal)
		WinActivate("Calculating Profile Sizes")
	endif

	tempVar = ArrInfo(tempArray, 1) - 1
	tempCount = tempVar + 1

	for i = 0 to tempVar
		k = i + 1
		tempName = tempArray[i]
		if getSize == @TRUE then
			BoxDataClear(1, "theDataTag")
			BoxDrawText(1, "0,50,1000,150", "Calculating profile sizes, please wait.", @TRUE, 1)
			BoxDrawText(1, "0,200,1000,500", "Processing profile %k% of %tempCount% - Please wait.", @TRUE, 5)
			BoxDrawText(1, "0,500,1000,1000", StrCat(theBasePath, tempName), @TRUE, 1)
		endif
		tempArray2 =  getProfileInfo(theBasePath, tempName, theDC, getSize)
		for j = 0 to 5
			profileArray[k,j] = tempArray2[j]
		endfor
	endfor

	if getSize == @TRUE then
		WinActivate("Calculating Profile Sizes") ;Without this line, the BoxDestroy below does NOT remove the box.
		BoxDestroy(1)
	endif

#EndSubRoutine

td

As a side note, you may need to use DialogProcOptions @dpoDisable option." If you have code that may take a long time to execute in a callback, you may need to temporarily disable the dialog. Don't forget to enable after the process is complete."

More towards your immediate issue, why not use a control on your dialog to display the status as you process?
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

User_McUser

Yeah, that is an option (using a control on the dialog.) Honestly? I like the aesthetics of the pop-over box more than embedding it into the dialog but that might be how I need to go. 🤷 Or maybe I will use a second custom dialog - the box routines seemed quicker at the time. I'll figure something out.

I flirted with using WinPlaceSet to move the box on the y-axis to be just above or below the main dialog but I don't like the way that looks. (Aside: Could we eventually get a WB function similar to WinPlaceSet but for z-order? Admittedly, I don't know much about how Windows does z-order other than there is one so maybe this is more of an ask than I realize. 🤔)

BTW - @dpoDisable did not change the behavior but I appreciate the suggestion; not something I was thinking about.

Thanks as always! 😀

td

WindowOnTop places a window on the top of the z-order and you need to use @dpoDisable to have the dialog still receive window messages if your callback is doing length processing. If you don't, the OS will think the process is hung.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

To add context, the WinBatch main window owns WIL dialog windows. I won't go into the details, but it is why you shouldn't use WinBatch boxes in WIL dialog procedures in the same process.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

SMF spam blocked by CleanTalk