cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Did you get called away in the middle of writing a post? Don't worry you can find your unfinished post later in the Drafts section of your profile page. X

centering a non-modal XUI dialog

jsulak
1-Newbie

centering a non-modal XUI dialog

Hello Adepters,



When I create a modal XUI dialog, Arbortext automatically centers it on
the screen. However, if I create the identical dialog with @modal =
false, Arbortext places it on the edge of the screen. Is there a way to
position a non-modal dialog in the center of the screen?



I can use the window interface's .moveTo method to position the dialog,
but without knowing the resolution of the user's screen, it's impossible
to precisely center it. So alternatively, if I could determine the
users' screen resolution, I could center the dialog manually using
.moveTo.



Thanks,



-James



5 REPLIES 5
bibach
1-Newbie
(To:jsulak)

Hey, James...

Unfortunately, Editor doesn't seem to offer any direct methods of
getting the screen resolution. So, here's just enough black magic to
get the information from the Windows API via ACL.

####################
# Get dimensions of monitor containing the window with the given ID.
# Get just the working area (minus taskbar) by passing
# a non-zero value for the optional "workarea" argument.
# Returns a string of the form "WxH+X+Y" (window geometry)
# or a message starting with "Error " on failure.
function getScreenSize(window, workarea=0)
{
# Get a handle to the Windows User32 library
local dll = dl_load("user32");
if (!dll) { return "Error loading library"; }

# Get a handle to the MonitorFromWindow function
local MonitorFromWindow = dl_find(dll, "MonitorFromWindow");
if (!MonitorFromWindow)
{
dl_unload(dll);
return "Error getting monitor lookup function";
}

# Get a handle to the GetMonitorInfo function
local GetMonitorInfo = dl_find(dll, "GetMonitorInfoW");
if (!GetMonitorInfo)
{
dl_unload(dll);
return "Error getting monitor info function";
}

# Get a handle to the monitor that the window is on
local hwnd = window_xid(window);
# 0, 1, 2 = MONITOR_DEFAULTTO{NULL,PRIMARY,NEAREST}
local monitor = dl_call(MonitorFromWindow, hwnd, 2);

# Get the geometry of the monitor
local rect[];
# struct RECT { long left; long top; long right; long bottom; }
# struct MONITORINFO { DWORD cbSize; RECT rcMonitor;
# RECT rcWork; DWORD dwFlags; }
local geom = pack("ll4l4l", 40, 0, 0, 0, 0, 0, 0, 0, 0, 0);
local ret = dl_call(GetMonitorInfo, monitor, geom);
if (ret == 0)
{
dl_unload(dll);
return "Error getting monitor info";
}
# Unpack just the RECT we're interested in, skipping the rest
ret = "x" . (workarea != 0 ? 20 : 4) . "l4";
unpack(ret, geom, rect);
geom = " . (rect[3] - rect[1]) . "x" . (rect[4] - rect[2]);
geom = geom . "+" . rect[1] . "+" . rect[2];

dl_unload(dll);
return geom;
}
####################

Use with caution. 😉

-Brandon 🙂

Brandon Ibach
Developer, Single-Sourcing Solutions, Inc.

Hi James--

I'll never be able to match Brandon's prowess at Win32 API programming,
but at least in this case I think I can beat him in sneaky thinking. 🙂

It turns out that you can get the screen dimensions by creating the
window and setting its geometry to some egregiously large value--which
Arbortext will very helpfully cap at the max screen resolution. Then,
you simply read the dimensions of the window, and you have your screen
size. You can do all this *before* you display the window, so you don't
have to worry about annoying the user with windows resizing and jumping
around before their eyes.

So, getting the screen size is as simple as this:

//Javascript:
dlg = Application.createDialogFromFile("jstester.xml");
dlgwin = dlg.dialogView.window;
dlgwin.setSize(10000,10000);
Application.alert("screen is " + dlgwin.height + " x " + dlgwin.width);

#ACL:
$xuidoc = doc_open("myXuiDialog.xml",1);
$win = window_create("xui",0x10,$xuidoc);
window_set($win,"geometry","10000x10000+0+0");
$screengeom = window_get($win,"geometry");

Apart from being shorter, this approach also has the advantage that it
is probably less likely to induce a Windows BSOD. 🙂

Once you've got the screen size, calculating where to position the
window to center it is pretty straightforward.

--Clay
bibach
1-Newbie
(To:jsulak)

Hey, Clay...

Nicely done. 🙂 I thought about trying to get Editor to do the dirty
work with something like that, but didn't spot a means. Believe me,
resorting to Win32 calls is always a last resort!

However, hypothetical BSOD aside (come now, that was a low blow!), how
would your approach work with a multiple monitor system, increasingly
popular as they are?

-Brandon 🙂

Hi Brandon--

It seems to work just fine with multiple monitors. When I run the test
code from an editor window, it reports the size of whichever screen
contains that editor window.

Multiple monitors do somewhat complicate the centering algorithm though,
because if you have your monitors set up for extended desktop (so you
can have different things showing on each monitor, the usual setup),
then you have to take that into account when positioning the dialog. You
can figure out where the current monitor is relative to the extended
desktop by looking at the +x+y part of the geometry after expanding the
window.

For example, I have two monitors, both set to 1680x1050, side by side.
If my Editor window is on monitor 2 and I do this trick, the geometry
string I get back is "1680x1022+1680+28". The "+1680" part tells me I'm
on screen 2 instead of screen 1. (The 1022 instead of 1050 and the +28
are to leave room for the task bar.) So you have to incorporate that
into your calculations when figuring out where to position the dialog to
have it centered. Unless I'm mistaken, the formula for each dimension
would be:

centered value = (expanded value/2) - (original value/2) + (expanded
offset)

Oh, and as for the BSOD comment, it really just betrays my inherent
anxiety and anything to do with the Win32 API. I've done a little .NET
programming when I've been forced to, but I'll do just about anything to
avoid mucking around in the guts of the OS. Black magic indeed! Give me
a nice safe Java VM or scripting engine and I'm happy. 🙂

--Clay
jsulak
1-Newbie
(To:jsulak)

Very nice! I knew I could count on Adepters. I can confirm that both
of these methods work, are both very fast, and that they both work on a
multi-monitor set-up. Thanks guys. I was banging my head against my
monitor trying to figure that one out.

-James

Top Tags