keybd_event 模拟 键盘Ctr+A Ctr+C 组合实现复制粘贴到剪贴板失败!

zlxi 2018-11-02 11:31:42
Ctr+A Ctr+C 有时候成功,有时候失败,求大神指教




SetForegroundWindow(topHwnd); //在视屏可视

/*设置最大化*/
WINDOWPLACEMENT placement;
placement.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(topHwnd, &placement);
placement.flags = WPF_RESTORETOMAXIMIZED;
placement.showCmd = SW_MAXIMIZE;
SetWindowPlacement(topHwnd, &placement);

/*移动到编辑区域*/
SetCursorPos(222, 85);
//按下鼠标左键
mouse_event(MOUSEEVENTF_LEFTDOWN| MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

//模拟Ctrl+A 全选
keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event(_T('A'),0, 0, 0);
keybd_event(_T('A'), 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
Sleep(1000);

//模拟Ctrl+C 复制
keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event(_T('C'), 0, 0, 0);
keybd_event(_T('C'), 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);

Sleep(1000);

if (OpenClipboard(NULL))//首先打开一个剪切板
{
if (IsClipboardFormatAvailable(CF_UNICODETEXT))//检查此时剪切板中数据是否为CF_UNICODETEXT,可以设置成别的!
{
HANDLE hClip; //声明一个句柄
LPTSTR pBuf;
hClip = GetClipboardData(CF_UNICODETEXT);//得到剪切板的句柄
pBuf = (LPTSTR)GlobalLock(hClip);//得到指向这块内存的指针
GlobalUnlock(hClip);//解除内存锁定


if (pBuf)
tcout << pBuf << std::endl;
else
tcout << _T("空复制") << std::endl;

}
else
tcout << _T("IsClipboardFormatAvailable") << std::endl;

EmptyClipboard(); //清空剪贴板
CloseClipboard(); //关闭此剪切板
}

...全文
862 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
clever101 2020-06-01
  • 打赏
  • 举报
回复
clever101 2020-06-01
  • 打赏
  • 举报
回复

#include <iostream>
#include "windows.h"
 
int main(int argc, char** argv) {
    HWND h=FindWindow("Notepad",NULL);
    if(h!=NULL)
    {
        daoSetActiveWindow(h);
        SetForegroundWindow(h);
        SetFocus(h);
        keybd_event(65,0,0,0);  // 输出字符A
        keybd_event(65,0,KEYEVENTF_KEYUP,0);
    }
    else
    {
        printf("no find");
    }
    return 0;
}
schlafenhamster 2018-11-03
  • 打赏
  • 举报
回复 1
https://blog.csdn.net/friendan/article/details/7537066
赵4老师 2018-11-02
  • 打赏
  • 举报
回复
schlafenhamster 2018-11-02
  • 打赏
  • 举报
回复
窗口 可能 不接受 焦点 !(disable 的 窗口 !)
zgl7903 2018-11-02
  • 打赏
  • 举报
回复
先 SetFocus 设置焦点, 否则一般的窗口都接收键盘消息
Jacky_Qiu2018 2018-11-02
  • 打赏
  • 举报
回复
* 窗口焦点问题:
你用鼠标模拟拖动窗口后,文本区域的焦点是否失去了,考虑SetFocus or SetForegroundWindow ,来激活窗口

* 你先把代码里的关于 模拟 ctrl +a ctrl+V 的部分不要。 然后这行前面 模拟拖动窗口 的代码,再手动 ctrl +a ctrl+V , 看是否获得文本。 这样可以排除是否 ctrl +a ctrl+V的代码出问题了。

* ctrl +a 和 ctrl+v 中间是否考虑 延长一点时间

以下代码仅供参考:

/****************************************************************************
获取剪贴板文本
****************************************************************************/
static
bool GetClipBoardText(string & ClipBoardText , HWND hWnd=NULL)
{
//判断剪贴板的数据格式是否可以处理。
#ifdef _UNICODE
if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
#else
if (!IsClipboardFormatAvailable(CF_TEXT))
#endif
return false;

//打开剪贴板。
if (!::OpenClipboard(hWnd))
return false;

#ifdef _UNICODE
HGLOBAL hMem = GetClipboardData(CF_UNICODETEXT);
#else
HGLOBAL hMem = GetClipboardData(CF_TEXT);
#endif
if (hMem != NULL)
{
//获取字符串。
LPTSTR lpStr = (LPTSTR)GlobalLock(hMem);
if (lpStr != NULL)
{
ClipBoardText=lpStr;

//释放锁内存
GlobalUnlock(hMem);
}
}

//关闭剪贴板
CloseClipboard();

return true;
}




/****************************************************************************
//should check this code with autohotkey "waitclip"
* in some application, should use sleep after execute ctrl+a (such as wiz)
* most of the time ,it should be used in new thread because sleep which is used in function will block the app
****************************************************************************/
static
bool CopySelectedText(string & SelText, string * pPreClipboardText=NULL)
{
//保存现在剪贴板的文本内容
if (pPreClipboardText)
GetClipBoardText(*pPreClipboardText);

::OpenClipboard(NULL);
EmptyClipboard();
CloseClipboard();

keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event('C', 0, 0, 0);
keybd_event('C', 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);

int TryTime = 40;
while (Sleep(50), --TryTime) //指定时间内不停判断
{
if (IsClipboardFormatAvailable(CF_TEXT))
break;
}
if (TryTime == 0) { MessageBoxS(_T("超过预定最大时间,can not get clipboard text")); return false; }

return GetClipBoardText(SelText);
}




有时候,模拟按键 再某些窗口会出问题,用
keybd_event(bVk,MapVirtualKey(bVk,MAPVK_VK_TO_VSC),0,0); 可能可以解决。
以下代码仅供参考:


void SimulateKeyDown(HWND hWnd,UINT nChar)
{
UINT ScanCode= MapVirtualKey( nChar , MAPVK_VK_TO_VSC);
LPARAM KeyDownLPARAM= (ScanCode<<16) | 0x00000001 ;
::PostMessage(hWnd,WM_KEYDOWN,nChar,KeyDownLPARAM);
}

void SimulatekeyUp(HWND hWnd,UINT nChar)
{
UINT ScanCode= MapVirtualKey( nChar , MAPVK_VK_TO_VSC);
LPARAM KeyUpLPARAM = (ScanCode<<16) | 0xC0000001 ;
::PostMessage(hWnd,WM_KEYUP,nChar,KeyUpLPARAM);
}


void Simulate_CombinateKey( BYTE bVk , UINT nChar , HWND hWnd )
{
keybd_event(bVk,MapVirtualKey(bVk,MAPVK_VK_TO_VSC),0,0);
SimulateKeyDown( hWnd ,nChar);
Sleep(100);
SimulatekeyUp ( hWnd ,nChar);
keybd_event(bVk,MapVirtualKey(bVk,MAPVK_VK_TO_VSC),KEYEVENTF_KEYUP,0);
}


void Simulate_Ctrl_ ( UINT nChar , HWND hWnd ) { Simulate_CombinateKey( VK_CONTROL , nChar , hWnd ) ; }
void Simulate_Shift_( UINT nChar , HWND hWnd ) { Simulate_CombinateKey( VK_SHIFT , nChar , hWnd ) ; }
void Simulate_Alt_ ( UINT nChar , HWND hWnd ) { Simulate_CombinateKey( VK_MENU , nChar , hWnd ) ; }

void Simulate_Ctrl_Shift_( UINT nChar , HWND hWnd )
{
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,MAPVK_VK_TO_VSC),0,0);
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,MAPVK_VK_TO_VSC),0,0);
SimulateKeyDown( hWnd ,nChar);
Sleep(100);
SimulatekeyUp ( hWnd ,nChar);
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,MAPVK_VK_TO_VSC),KEYEVENTF_KEYUP,0);
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,MAPVK_VK_TO_VSC),KEYEVENTF_KEYUP,0);
}


void Simulate_Ctrl_Alt_( UINT nChar , HWND hWnd )
{
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,MAPVK_VK_TO_VSC),0,0);
keybd_event(VK_MENU,MapVirtualKey(VK_MENU,MAPVK_VK_TO_VSC),0,0);
SimulateKeyDown( hWnd ,nChar);
Sleep(100);
SimulatekeyUp ( hWnd ,nChar);
keybd_event(VK_MENU,MapVirtualKey(VK_MENU,MAPVK_VK_TO_VSC),KEYEVENTF_KEYUP,0);
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,MAPVK_VK_TO_VSC),KEYEVENTF_KEYUP,0);
}
weixin_42882709 2021-10-05
  • 举报
回复
@Jacky_Qiu2018 no good
赵4老师 2018-11-02
  • 打赏
  • 举报
回复
autohotkey的ImageSearch了解一下。
schlafenhamster 2018-11-02
  • 打赏
  • 举报
回复
EnableWindow
The EnableWindow function enables or disables mouse and keyboard input to the specified window or control. When input is disabled, the window does not receive input such as mouse clicks and key presses. When input is enabled, the window receives all input.

BOOL EnableWindow(
HWND hWnd, // handle to window
BOOL bEnable // flag for enabling or disabling input
);

Parameters
hWnd
Handle to the window to be enabled or disabled.
bEnable
Specifies whether to enable or disable the window. If this parameter is TRUE, the window is enabled. If the parameter is FALSE, the window is disabled.
Return Values
If the window was previously disabled, the return value is nonzero.

If the window was not previously disabled, the return value is zero. To get extended error information, callGetLastError.

Remarks
If the enabled state of a window is changing, a WM_ENABLE message is sent before the EnableWindow function returns. If a window is already disabled, all its child windows are implicitly disabled, although they are not sent a WM_ENABLE message.

A window must be enabled before it can be activated. For example, if an application is displaying a modeless dialog box and has disabled its main window, the application must enable the main window before destroying the dialog box. Otherwise, another window will receive the keyboard focus and be activated. If a child window is disabled, it is ignored when the system tries to determine which window should receive mouse messages.

By default, a window is enabled when it is created. To create a window that is initially disabled, an application can specify the WS_DISABLED style in the CreateWindow or CreateWindowEx function. After a window has been created, an application can use EnableWindow to enable or disable the window.

An application can use this function to enable or disable a control in a dialog box. A disabled control cannot receive the keyboard focus, nor can a user gain access to it.

zlxi 2018-11-02
  • 打赏
  • 举报
回复
引用 7 楼 zgl7903 的回复:
取的什么窗口的数据?


实体键盘能够使用 Ctrl+A Ctrl+C 复制的内容!!!!希望都能做到!!



换了一种方式好像可以了! 帮忙看一下还是否有误区!



SetForegroundWindow(topHwnd);
WINDOWPLACEMENT placement;
placement.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(topHwnd, &placement);
placement.flags = WPF_RESTORETOMAXIMIZED;
placement.showCmd = SW_MAXIMIZE;

SetWindowPlacement(topHwnd, &placement);



/*让鼠标在活动区,拖拉一段距离,然后再模拟按键盘*/
SetCursorPos(222, 85);
Sleep(10);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(222 + 1, 85 + 5);
Sleep(10);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP, 222 + 1, 85 + 5, 0, 0);


/*使用 SendInput 实现按键方法*/

INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;

ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

// Press the "V" key
ip.ki.wVk = 'A';
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

// Release the "V" key
ip.ki.wVk = 'A';
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));

// Release the "Ctrl" key
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));

Sleep(1000);


ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

// Press the "V" key
ip.ki.wVk = 'C';
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

// Release the "V" key
ip.ki.wVk = 'C';
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));

// Release the "Ctrl" key
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
Sleep(500);


if (OpenClipboard(topHwnd))//首先打开一个剪切板
{
if (IsClipboardFormatAvailable(CF_UNICODETEXT))//检查此时剪切板中数据是否为TEXT,可以设置成别的!
{
HANDLE hClip; //声明一个句柄
LPTSTR pBuf;
hClip = GetClipboardData(CF_UNICODETEXT);//得到剪切板的句柄
pBuf = (LPTSTR)GlobalLock(hClip);//得到指向这块内存的指针
GlobalUnlock(hClip);//解除内存锁定


if (pBuf)
tcout << pBuf << std::endl;
else
tcout << _T("空复制") << std::endl;
//SetDlgItemText(IDC_EDIT2, pBuf);//将他设置给一个文本框显示

}
else
tcout << _T("IsClipboardFormatAvailable") << std::endl;

EmptyClipboard();
CloseClipboard();//关闭此剪切板
}


zlxi 2018-11-02
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
http://www.autohotkey.com



引用 8 楼 zgl7903 的回复:
编辑框的话可以发消息


HWND hNotePad = ::FindWindow(_T("Notepad"), NULL);
if(hNotePad)
{
HWND hEdit = ::FindWindowEx(hNotePad, NULL, _T("Edit"), NULL);
if(hEdit)
{
::SendMessage(hEdit, EM_SETSEL, 0, -1);
::SendMessage(hEdit, WM_COPY, 0, 0);

}
}


有些是找不到 Edit控件的! 不如java awt,就找不到!!




zgl7903 2018-11-02
  • 打赏
  • 举报
回复
编辑框的话可以发消息


HWND hNotePad = ::FindWindow(_T("Notepad"), NULL);
if(hNotePad)
{
HWND hEdit = ::FindWindowEx(hNotePad, NULL, _T("Edit"), NULL);
if(hEdit)
{
::SendMessage(hEdit, EM_SETSEL, 0, -1);
::SendMessage(hEdit, WM_COPY, 0, 0);

}
}
zgl7903 2018-11-02
  • 打赏
  • 举报
回复
取的什么窗口的数据?
zlxi 2018-11-02
  • 打赏
  • 举报
回复
引用 2 楼 schlafenhamster 的回复:
窗口 可能 不接受 焦点 !(disable 的 窗口 !)


setForce也不行,但程序重新编译,就可以获取一次!
zlxi 2018-11-02
  • 打赏
  • 举报
回复
引用 4 楼 zgl7903 的回复:
上面漏了一个字
先 SetFocus 设置焦点, 否则一般的窗口都接收键盘消息



我把程序,重新编译一次,就可以获取到数据! 好奇怪!
zgl7903 2018-11-02
  • 打赏
  • 举报
回复
上面漏了一个字
先 SetFocus 设置焦点, 否则一般的窗口都接收键盘消息

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧