首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# 獲取屏幕輸入焦點控件坐標(光標位置)的實現方案

     編輯:程式設計綜合問答

需求

編寫輸入法類應用,需獲取當前系統輸入焦點所在控件的屏幕坐標(插入符閃爍位置),而非鼠標坐標。

核心思路

  1. 獲取前台窗口句柄: GetForegroundWindow() (user32.dll)。
  2. 獲取焦點控件句柄: GetFocus() 或 GetGUIThreadInfo (更可靠,可跨進程獲取焦點 hwnd)。
  3. 獲取控件客戶區矩形: GetClientRect(hwnd, out RECT)。
  4. 獲取插入符位置 (相對客戶區):
    • 標準編輯框:發送 EM_GETSEL 獲取選區起始,再用 EM_POSFROMCHAR 轉坐標。
    • RichEdit:EM_GETSCROLLPOS + 字符索引計算。
    • 通用方案:UI Automation (System.Windows.Automation) 獲取 TextPattern 的 CaretPosition。
  5. 客戶區坐標轉屏幕坐標: 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 是最通用但性能稍差的方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved