用户在输入过程中,光标的位置在不停变化,如何得到这个位置来进行一些操作呢?似乎很简单,GetCaretPos,这个函数能得到光标的位置。
看看MSDN上如何说的:
See Also
SetCaretPos | POINT | Carets Functions
Requirements
OS Versions: Windows CE 1.0 and later.
Header: Winuser.h.
Link Library: Caret.lib.
This function copies the caret's position, in client coordinates, to the specified POINT structure.
BOOL GetCaretPos(
LPPOINT lpPoint
);
Parameters
lpPoint
[out] Long pointer to the POINT structure that is to receive the client coordinates of the caret.
Return Values
Nonzero indicates success. Zero indicates failure. To get extended error information, call GetLastError.
Remarks
The caret position is always given in the client coordinates of the window that contains the caret.
If an application calls GetCaretPos from a thread that does not own the caret, GetCaretPos fails with an error value of ERROR_ACCESS_DENIED.
很遗憾,实际的结果,此函数对于本进程是有效的,对于别的进程缺无能为力,真的会得到错误值ERROR_ACCESS_DENIED。
看看windows上有什么好方法吧。
网上找找,通用的大概有两种方法:1)使用AttachThreadInput将本进程注入到输入焦点窗口进程(当然要先找到焦点窗口),这样就能使用GetCaretPos了;2)使用GetGUIThreadInfo可以获得位置信息。
还是很遗憾,wince对于这两个函数都不支持。
在绝望地摸索了一段时间后,通过曲线救国的方式,事情似乎有了转机。
微软提供了两个函数GetWindowLong和SetWindowLong,这个函数可以得到和设置指定窗口的一些信息,包括窗口进程的地址。
先准备一些料,包饺子用的,后面会用到:
static WNDPROC g_pOldWndProc = NULL;
static WNDPROC g_pOldEditProc = NULL;
static UINT g_uGetFocusMessage = RegisterWindowMessage(_T("GetFocusMessage"));
static UINT g_uGetCaretMessage = RegisterWindowMessage(_T("GetCaretMessage"));
static UINT g_uGetRectMessage = RegisterWindowMessage(_T("GetRectMessage"));
static POINT g_ptCaret;
static RECT g_rcEdit;
static LRESULT WINAPI GetFocusWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if(uMsg == g_uGetFocusMessage)
{
return (LRESULT)GetFocus();
}
else
{
return CallWindowProc(g_pOldWndProc, hWnd, uMsg, wParam, lParam);
}
}
static LRESULT WINAPI GetCaretPosWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if(uMsg == g_uGetCaretMessage)
{
return (LRESULT)GetCaretPos(&g_ptCaret);
}
else if(uMsg == g_uGetRectMessage)
{
return (LRESULT)GetWindowRect(hWnd, &g_rcEdit);
}
else
{
return CallWindowProc(g_pOldEditProc, hWnd, uMsg, wParam, lParam);
}
}
现在假设一上层窗口,拥有输入Edit,我们用下面的方法可以得到输入光标的坐标:
HWND hWnd = GetForegroundWindow();
if(hWnd)
{
g_pOldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
//设置一个新的窗口进程
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)GetFocusWindowProc);
HWND hEdit = (HWND)SendMessage(hWnd, g_uGetFocusMessage, 0, 0);
if(hEdit)
{
g_pOldEditProc = (WNDPROC)GetWindowLong(hEdit, GWL_WNDPROC);
SetWindowLong(hEdit, GWL_WNDPROC, (LONG)GetCaretPosWindowProc);
SendMessage(hEdit, g_uGetRectMessage, 0, 0);
BOOL b = (BOOL)SendMessage(hEdit, g_uGetCaretMessage, 0, 0);
if(b)
{
//此处利用g_rcEdit和g_ptCaret就可以得到光标相对于屏幕的位置
}
SetWindowLong(hEdit, GWL_WNDPROC, (LONG)g_pOldEditProc);
g_pOldEditProc = NULL;
}
//用完了,要恢复
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)g_pOldWndProc);
g_pOldWndProc = NULL;
}