gpt4 book ai didi

c - 如何使用 native Win32 API 从聚焦窗口中获取选定的文本?

转载 作者:可可西里 更新时间:2023-11-01 12:18:37 36 4
gpt4 key购买 nike

我的应用程序。将在系统上运行尝试监视热键;当用户在任何窗口中选择一些文本并按下热键时,当我收到 WM_HOTKEY 消息时,如何获取所选文本?

为了将文本捕获到剪贴板上,我尝试使用 keybd_event()SendInput()Ctrl + C 发送到事件窗口 (GetActiveWindow()) 和前景窗口 (GetForegroundWindow());尝试了其中的组合;一切都是徒劳。我可以使用纯 Win32 系统 API 在 Windows 中获取焦点窗口的选定文本吗?

最佳答案

TL;DR:是的,有一种方法可以使用普通的 win32 系统 API 来执行此操作,但很难正确实现。

WM_COPY 和 WM_GETTEXT 可能有效,但并非在所有情况下都有效。它们依赖于正确处理请求的接收窗口——在许多情况下它不会。让我介绍一种可能的方法。它可能不像您希望的那么简单,但是在充满冒险的 win32 编程世界中有什么?准备好?好的。我们走吧。

首先我们需要获取目标窗口的HWND id。有很多方法可以做到这一点。一种这样的方法就是您在上面提到的方法:获取前景窗口,然后获取焦点窗口等。但是,有一个巨大陷阱,很多人都忘记了。获得前景窗口后,您必须 AttachThreadInput 以获得焦点窗口。否则 GetFocus() 将简单地返回 NULL

有一个更简单的方法。只需(错过)使用 GUITREADINFO 函数。它更安全,因为它避免了将输入线程与另一个程序相关联的所有隐患。

LPGUITHREADINFO lpgui = NULL;
HWND target_window = NULL;

if( GetGUIThreadInfo( NULL, lpgui ) )
target_window = lpgui->hwndFocus;
else
{
// You can get more information on why the function failed by calling
// the win32 function, GetLastError().
}

发送击键来复制文本有点复杂......

我们将使用 SendInput 而不是 keybd_event,因为它更快,而且最重要的是,不会被并发用户输入或其他模拟击键的程序搞乱。

这确实意味着该程序将需要在 Windows XP 或更高版本上运行,但是,如果您运行的是 98,抱歉!

// We're sending two keys CONTROL and 'V'. Since keydown and keyup are two
// seperate messages, we multiply that number by two.
int key_count = 4;

INPUT* input = new INPUT[key_count];
for( int i = 0; i < key_count; i++ )
{
input[i].dwFlags = 0;
input[i].type = INPUT_KEYBOARD;
}

input[0].wVK = VK_CONTROL;
input[0].wScan = MapVirtualKey( VK_CONTROL, MAPVK_VK_TO_VSC );
input[1].wVK = 0x56 // Virtual key code for 'v'
input[1].wScan = MapVirtualKey( 0x56, MAPVK_VK_TO_VSC );
input[2].dwFlags = KEYEVENTF_KEYUP;
input[2].wVK = input[0].wVK;
input[2].wScan = input[0].wScan;
input[3].dwFlags = KEYEVENTF_KEYUP;
input[3].wVK = input[1].wVK;
input[3].wScan = input[1].wScan;

if( !SendInput( key_count, (LPINPUT)input, sizeof(INPUT) ) )
{
// You can get more information on why this function failed by calling
// the win32 function, GetLastError().
}

那里。那还不错,不是吗?

现在我们只需看一下剪贴板中的内容。这并不像您最初想象的那么简单。 “剪贴板”实际上可以保存同一事物的多个表示形式。当您复制到剪贴板时处于事件状态的应用程序可以控制将什么内容准确地放入剪贴板。

例如,当您从 Microsoft Office 复制文本时,它会将 RTF 数据与同一文本的纯文本表示一起放入剪贴板。这样你就可以将它粘贴到写字板和记事本中。写字板将使用富文本格式,而记事本将使用纯文本格式。

不过,对于这个简单的示例,我们假设我们只对纯文本感兴趣。

if( OpenClipboard(NULL) )
{
// Optionally you may want to change CF_TEXT below to CF_UNICODE.
// Play around with it, and check out all the standard formats at:
// http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx
HGLOBAL hglb = GetClipboardData( CF_TEXT );
LPSTR lpstr = GlobalLock(hglb);

// Copy lpstr, then do whatever you want with the copy.

GlobalUnlock(hglb);
CloseClipboard();
}
else
{
// You know the drill by now. Check GetLastError() to find out what
// went wrong. :)
}

就是这样!只需确保将 lpstr 复制到您要使用的某个变量,不要直接使用 lpstr,因为我们必须在关闭剪贴板之前放弃对剪贴板内容的控制。

Win32 编程一开始可能会让人望而生畏,但过一段时间后……还是让人望而生畏。

干杯!

关于c - 如何使用 native Win32 API 从聚焦窗口中获取选定的文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2251578/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com