当我使用ClientToScreen()时,我得到客户端窗口的坐标,但它不包括文件菜单栏。当窗口具有文件菜单栏时,这对我来说只是一个问题。 Windows计算器。
public Point createPoint(IntPtr handle)
{
Point myPoint = new Point(0, 0);
Point myPointClient = new Point(0, 0);
RECT myRectWindow;
if (radioButtonEntireWindow.Checked) // Green cross
{
// Result: (0, 0)
}
else if (radioButtonClientWindowFileMenu.Checked) // Red cross
{
// This works for windows 7, but probably not for windows 10:
myPoint = new Point(8, 30);
// Result: (8, 30)
}
else if (radioButtonClientWindow.Checked) // Purple cross
{
GetWindowRect(handle, out myRectWindow);
ClientToScreen(handle, ref myPointClient);
myPoint = new Point(myPointClient.X - myRectWindow.Location.X, myPointClient.Y - myRectWindow.Location.Y);
// Result: (8, 50)
}
return myPoint;
}
如何在不明确使用(8,30)的情况下获得红叉坐标?使用GetWindowRect()和GetClientRect()来获取标题栏高度不起作用,因为它不包括文件菜单栏,就像ClientToScreen()一样。
答案 0 :(得分:0)
您可以使用System.Windows.SystemParameters的属性来获取各种元素的大小,例如它具有MenuBarHeight和CaptionBarHeight属性。
答案 1 :(得分:0)
本机菜单栏位于HWNDs客户区之外。有些窗口也使用自定义菜单栏,在这些情况下所有赌注都关闭,它可能位于客户区内部或外部。
您可以通过调用GetMenu
来检测窗口是否具有本机菜单栏。
您无法真正使用系统指标(HTMENU
等)来查找它的大小,因为:
如果您只是想知道屏幕上的某个点是否是菜单栏,您可以发送WM_NCHITTEST
消息并将返回值与HWND hCalc = FindWindow(TEXT("CalcFrame"), NULL);
HMENU hMenu = hCalc ? GetMenu(hCalc) : NULL;
MENUBARINFO mbi;
printf("Menu of %p is %p\n", hCalc, hMenu);
mbi.cbSize = sizeof(MENUBARINFO);
if (GetMenuBarInfo(hCalc, OBJID_MENU, 0, &mbi))
{
printf("GetMenuBarInfo: pos:%dx%d size:%dx%d\n", mbi.rcBar.left, mbi.rcBar.top, mbi.rcBar.right - mbi.rcBar.left, mbi.rcBar.bottom - mbi.rcBar.top);
}
进行比较。
要获得原生菜单栏的大小,您可以执行以下操作(在简单C中发帖,抱歉):
OleInitialize(0);
HWND hCalc = FindWindow(TEXT("CalcFrame"), NULL);
IAccessible*pAcc;
HRESULT hr;
hr = AccessibleObjectFromWindow(hCalc, OBJID_MENU, IID_IAccessible, (void**) &pAcc);
if (SUCCEEDED(hr))
{
long x, y, w, h;
VARIANT v;
V_VT(&v) = VT_I4;
V_I4(&v) = CHILDID_SELF;
if (SUCCEEDED(pAcc->accLocation(&x, &y, &w, &h, v)))
{
printf("pos: %dx%d size: %dx%d\n", x, y, w, h);
}
pAcc->Release();
}
但我建议您使用MSAA或UI自动化,因为它也适用于具有自定义菜单栏的应用程序:
using System;
using System.Runtime.InteropServices;
using Accessibility;
namespace Test
{
class TestApp
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, IntPtr zero);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), DllImport("oleacc.dll", ExactSpelling = true, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
static extern object AccessibleObjectFromWindow(IntPtr hwnd, uint dwObjectID, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
static Guid IID_IAccessible = new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");
enum OBJID : uint { WINDOW = 0x00000000, SYSMENU = 0xFFFFFFFF, TITLEBAR = 0xFFFFFFFE, MENU = 0xFFFFFFFD, CLIENT = 0xFFFFFFFC, }
static void Main()
{
IntPtr hCalc = FindWindow("CalcFrame", IntPtr.Zero);
Console.WriteLine("Calc HWND is "+hCalc);
if (hCalc == IntPtr.Zero) return ;
try
{
IAccessible acc = (IAccessible) AccessibleObjectFromWindow(hCalc, (uint)OBJID.CLIENT, IID_IAccessible);
int x, y, w, h;
acc.accLocation(out x, out y, out w, out h, null);
Console.WriteLine(string.Format("pos: {0}x{1} size:{2}x{3}", x, y, w, h));
}
catch (System.Runtime.InteropServices.COMException)
{
}
}
}
}
与PInvoke调用相同:
{{1}}