Я пытаюсь получить каре позицию, используя GetWindowRect()
(и GetGUIThreadInfo()
):Почему GetWindowRect включает строку заголовка в моем окне WPF?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Runtime.InteropServices;
namespace WpfApplication1
{
public class CaretInfo
{
public double Width { get; private set; }
public double Height { get; private set; }
public double Left { get; private set; }
public double Top { get; private set; }
public CaretInfo(double width, double height, double left, double top)
{
Width = width;
Height = height;
Left = left;
Top = top;
}
}
public class CaretHelper
{
public static CaretInfo GetCaretPosition()
{
// Get GUI info containing caret poisition
var guiInfo = new GUITHREADINFO();
guiInfo.cbSize = (uint)Marshal.SizeOf(guiInfo);
GetGUIThreadInfo(0, out guiInfo);
// Get width/height
double width = guiInfo.rcCaret.right - guiInfo.rcCaret.left;
double height = guiInfo.rcCaret.bottom - guiInfo.rcCaret.top;
// Get left/top relative to screen
RECT rect;
GetWindowRect(guiInfo.hwndFocus, out rect);
double left = guiInfo.rcCaret.left + rect.left + 2;
double top = guiInfo.rcCaret.top + rect.top + 2;
int capacity = GetWindowTextLength(guiInfo.hwndFocus) * 2;
StringBuilder stringBuilder = new StringBuilder(capacity);
GetWindowText(guiInfo.hwndFocus, stringBuilder, stringBuilder.Capacity);
Console.WriteLine("Window: " + stringBuilder);
Console.WriteLine("Caret: " + guiInfo.rcCaret.left + ", " + guiInfo.rcCaret.top);
Console.WriteLine("Rect : " + rect.left + ", " + rect.top);
return new CaretInfo(width, height, left, top);
}
[DllImport("user32.dll", EntryPoint = "GetGUIThreadInfo")]
public static extern bool GetGUIThreadInfo(uint tId, out GUITHREADINFO threadInfo);
[DllImport("user32.dll")]
public static extern bool ClientToScreen(IntPtr hWnd, out Point position);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr handle, out RECT lpRect);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetClientRect(IntPtr hWnd, ref Rect rect);
[StructLayout(LayoutKind.Sequential)]
public struct GUITHREADINFO
{
public uint cbSize;
public uint flags;
public IntPtr hwndActive;
public IntPtr hwndFocus;
public IntPtr hwndCapture;
public IntPtr hwndMenuOwner;
public IntPtr hwndMoveSize;
public IntPtr hwndCaret;
public RECT rcCaret;
};
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowTextLe
Блокнота и почти нигде координаты являются правильно неправдоподобным:
В моем WPF (и любой другой WPF), однако GetWindowRect()
решает включить строку заголовка и компенсировать верхнее положение каретки на высоту строки заголовка:
Любая идея, почему?
Я также попытался использовать DwmGetWindowAttribute()
, но он получает те же координаты для окна WPF, что и GetWindowRect()
.
Edit:
С ответом от Brian Reichle я смог определить способ получить координаты клиентской области:
[DllImport("user32.dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref System.Drawing.Point lpPoint);
System.Drawing.Point point = new System.Drawing.Point(0, 0);
ClientToScreen(guiInfo.hwndFocus, ref point)
0,0
является верхняя левая координата клиентская область окна, указанная guiInfo.hwndFocus
, и это всегда 0,0
, потому что это касается клиентской области окна. ClientToScreen()
преобразует координаты относительно относительно экрана (должно быть System.Drawing.Point
, System.Windows.Point
не будет работать).
Строка заголовка включена, потому что ее часть окна, если вы не хотите неклиентскую область, тогда вам нужно запросить область клиента rect (GetClientRect). Путаница из блокнота, вероятно, связана с тем, что вы используете дескриптор окна текстового поля, а не самого окна. Помните, что WPF использует единый дескриптор для общего окна, в то время как win32 часто (но не всегда) использует отдельный дескриптор для каждого элемента управления в окне. –
'GetClientRect()' возвращает 0,0, но я думаю, что вы правильно относитесь к дескрипторам окон - по крайней мере, я могу подтвердить с помощью Spy ++, поэтому, если вы хотите отказаться от этого в качестве ответа, я могу его принять. – Woodgnome