Hi, I am trying to find the fastest way to move a window to the center of the users display.
Modal windows automatically are centered on the screen, so I know that JMP is somehow able to tell where to put a window, but I have only found some relatively slow workarounds to doing this with non-modal windows. Below is the jsl script I am currently using to determine the screen size and center a new window.
Is there a faster way? Thanks!
win2 = NewWindow("Test Window");
winSize = win2 << GetWindowSize();
win2 << ShowWindow(0);
testwin = NewWindow("test", << ShowWindow(0));
testwin << Maximize Window(1);
dispsize = testwin << Get Window Size;
testwin << CloseWindow();
win2 << MoveWindow(dispsize[1]/2 - winsize[1]/2, dispsize[2]/2 - winsize[2]/2);
win2 << ShowWindow(1);
In my experience the <<Get Window Size method is not reliable. The issue is that <<Get Window Size does not return physical pixels but logical pixels (affected by Windows display scaling), while <<Move Window( x, y ) uses physical pixels. Also, JMP in general and <<Get Window Size in specific does not update when the Windows display scaling changes (if a user starts JMP on a laptop and later hooks up a monitor, for instance).
I run the following PowerShell script from JMP to get the actual screen resolution and use this info to place windows as appropriate (you'll have to launch powershell with -ExecutionPolicy Bypass:
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class PInvoke {
[DllImport("user32.dll")] public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll")] public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
}
"@
$hdc = [PInvoke]::GetDC([IntPtr]::Zero)
[PInvoke]::GetDeviceCaps($hdc, 118) # width
[PInvoke]::GetDeviceCaps($hdc, 117) # height
Your method is the method I normally use.
In my experience the <<Get Window Size method is not reliable. The issue is that <<Get Window Size does not return physical pixels but logical pixels (affected by Windows display scaling), while <<Move Window( x, y ) uses physical pixels. Also, JMP in general and <<Get Window Size in specific does not update when the Windows display scaling changes (if a user starts JMP on a laptop and later hooks up a monitor, for instance).
I run the following PowerShell script from JMP to get the actual screen resolution and use this info to place windows as appropriate (you'll have to launch powershell with -ExecutionPolicy Bypass:
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class PInvoke {
[DllImport("user32.dll")] public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll")] public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
}
"@
$hdc = [PInvoke]::GetDC([IntPtr]::Zero)
[PInvoke]::GetDeviceCaps($hdc, 118) # width
[PInvoke]::GetDeviceCaps($hdc, 117) # height
This is the kind of hocus pocus I was looking for haha. Thanks Jim and Jordan! I will try out both options and see which is faster and/or more reliable
Hello,
Thank you very much for your tip ! It's been years, but it's still relevant: how do you transfer this information from PowerShell to JMP (about screen size) using Run Program?
you can use text as Read function() and split the string by using words()
powershell_code ="
Add-Type -AssemblyName System.Windows.Forms
$primary = [System.Windows.Forms.Screen]::PrimaryScreen
Write-Output $primary.Bounds.Width
Write-Output $primary.Bounds.Height
";
result = Run Program(
Executable( "powershell.exe" ),
Options( {"-Command", powershell_code} ),
Read Function( "text" )
);
{w, h} = Transform Each( {str}, Words( result, "\!n\!r" ), Num( str ) );