When looking for how to position a adding window using Visual Studio Tools for Dynamics GP - I came across Dave's blog: specifically the blog post But I wasn't able to find much more than that.
Sure that I could find the position of a GP window, I tried building something - and this appears to work:
Usage:
That would center the form according to the "Sales Payment Entry" window - if it was open, and the screen if it's not open.
Here is the helper classes
I hope others find this useful.
Sure that I could find the position of a GP window, I tried building something - and this appears to work:
Usage:
Code:
WindowHelper.PositionForm(this, "Sales Payment Entry"); // From within the Form Load event
Here is the helper classes
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using Microsoft.Dexterity.Shell;
using System.Runtime.InteropServices;
namespace OurNamespace.Utilities
{
public class ApiWindow
{
public string MainWindowTitle = "";
public IntPtr hWnd;
}
public class WindowHelper
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
public static IntPtr GetGPWindow(string name)
{
if (name == null || name == string.Empty || name.Trim().Length < 1) return IntPtr.Zero;
Process[] procs = Process.GetProcessesByName("Dynamics");
Process p = null;
if (procs.Length == 1) p = procs[0];
if (p == null) return IntPtr.Zero;
WindowsEnumerator we = new WindowsEnumerator();
List<ApiWindow> gpWindows = we.GetProcessWindows(p);
IntPtr ret = IntPtr.Zero;
foreach (ApiWindow win in gpWindows)
{
if (win.MainWindowTitle.ToLower().Contains(name.ToLower()))
{
ret = win.hWnd;
break;
}
}
return ret;
}
public static System.Drawing.Rectangle GetGPWindowBounds(string name)
{
IntPtr window = GetGPWindow(name);
if (window == IntPtr.Zero) return Screen.PrimaryScreen.Bounds;
RECT rct;
if (!GetWindowRect(window, out rct)) return Screen.PrimaryScreen.Bounds;
return new System.Drawing.Rectangle(rct.Left, rct.Top, rct.Right - rct.Left + 1, rct.Bottom - rct.Top + 1);
}
public static void PositionForm(DexUIForm form)
{
PositionForm(form, string.Empty);
}
public static void PositionForm(DexUIForm form, string basedOn)
{
System.Drawing.Rectangle rect = GetGPWindowBounds(basedOn);
int x = (int)Math.Round((double)((rect.Width / 2) - (form.Width / 2)), 0) + rect.X;
int y = (int)Math.Round((double)((rect.Height / 2) - (form.Height / 2)), 0) + rect.Y;
form.SetBounds(x, y, form.Width, form.Height);
}
}
public class WindowsEnumerator
{
private delegate bool EnumCallBackDelegate(IntPtr hwnd, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetShellWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern UInt32 GetWindowThreadProcessId(IntPtr hWnd, out UInt32 lpdwProcessId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool EnumWindows(EnumCallBackDelegate callback, int lParam);
private IntPtr hShellWindow = GetShellWindow();
private List<ApiWindow> _windows = new List<ApiWindow>();
public List<ApiWindow> GetProcessWindows(Process p)
{
_windows = new List<ApiWindow>();
EnumWindows(EnumWindowProc, p.Id);
return _windows;
}
private bool EnumWindowProc(IntPtr hwnd, int lParam)
{
if (hwnd != hShellWindow)
{
if (!IsWindowVisible(hwnd)) return true;
int length = GetWindowTextLength(hwnd);
if (length == 0) return true;
UInt32 windowPid;
GetWindowThreadProcessId(hwnd, out windowPid);
if (windowPid != lParam) return true;
StringBuilder title = new StringBuilder(length);
GetWindowText(hwnd, title, (length + 1));
ApiWindow window = new ApiWindow();
window.hWnd = hwnd;
window.MainWindowTitle = title.ToString();
_windows.Add(window);
}
return true;
}
}
}
I hope others find this useful.