Woo*_*ome 1 c# wpf pinvoke caret
我正在尝试使用GetWindowRect()(和GetGUIThreadInfo())获得插入符号位置:
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
Run Code Online (Sandbox Code Playgroud)
对于记事本和几乎其他任何地方,都可以正确获取坐标:
然而,在我的 WPF(和任何其他 WPF)窗口中,GetWindowRect()决定包含标题栏并将插入符号顶部位置偏移标题栏的高度:
知道为什么吗?
我也尝试使用DwmGetWindowAttribute(),但它获得的 WPF 窗口坐标与GetWindowRect().
编辑:
通过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)
Run Code Online (Sandbox Code Playgroud)
0,0是由 指定的窗口客户区的左上角坐标,guiInfo.hwndFocus它总是0,0因为它相对于窗口的客户区。ClientToScreen()将坐标转换为相对于屏幕的坐标(必须是System.Drawing.Point,System.Windows.Point不起作用)。
包含标题栏是因为它是窗口的一部分,如果您不想要非客户区,则需要请求客户区 rect ( GetClientRect)。
记事本的混淆可能是因为您使用的是文本框的窗口句柄而不是窗口本身。请记住,WPF 对整个窗口使用单个句柄,而 win32 经常(但不总是)为窗口中的每个控件使用单独的句柄。
在您提到GetClientRect'returned'的评论中,0,0您是否检查过它返回的是 true(成功)还是 false(失败)?如果返回 false,您是否检查了GetLastError()?
| 归档时间: |
|
| 查看次数: |
1275 次 |
| 最近记录: |