編寫輸入法類應用,需獲取當前系統輸入焦點所在控件的屏幕坐標(插入符閃爍位置),而非鼠標坐標。
GetForegroundWindow() (user32.dll)。GetFocus() 或 GetGUIThreadInfo (更可靠,可跨進程獲取焦點 hwnd)。GetClientRect(hwnd, out RECT)。EM_GETSEL 獲取選區起始,再用 EM_POSFROMCHAR 轉坐標。EM_GETSCROLLPOS + 字符索引計算。System.Windows.Automation) 獲取 TextPattern 的 CaretPosition。ClientToScreen(hwnd, ref POINT)。
[DllImport("user32.dll")] static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")] static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui);
// ... 定義結構體 GUITHREADINFO, RECT, POINT ...
public Point GetCaretScreenPos()
{
GUITHREADINFO gti = new GUITHREADINFO { cbSize = Marshal.SizeOf(typeof(GUITHREADINFO)) };
GetGUIThreadInfo(0, ref gti);
IntPtr hwndFocus = gti.hwndFocus;
if (hwndFocus == IntPtr.Zero) return Point.Empty;
// 這裡以標準 Edit 為例
int selStart = SendMessage(hwndFocus, EM_GETSEL, IntPtr.Zero, IntPtr.Zero).ToInt32() & 0xFFFF;
Point ptClient = new Point();
SendMessage(hwndFocus, EM_POSFROMCHAR, ref ptClient, (IntPtr)selStart);
ClientToScreen(hwndFocus, ref ptClient);
return ptClient;
}
不同類型控件 (Edit, RichEdit, Chrome RenderWidget, WPF TextBox) 獲取插入符位置 API 不同,UI Automation 是最通用但性能稍差的方案。