int MakeKeyLparam(int VirtualKey, int flag) { UINT sCode; //Firstbyte ; lparam 参数的 24-31位 UINT Firstbyte; switch (flag) { case WM_KEYDOWN: Firstbyte = 0; break; case WM_KEYUP: Firstbyte = 0xC0;break; case WM_CHAR: Firstbyte = 0x20;break; case WM_SYSKEYDOWN: Firstbyte = 0x20;break; case WM_SYSKEYUP: Firstbyte = 0xE0;break; case WM_SYSCHAR: Firstbyte = 0xE0;break; } // 键的扫描码; lparam 参数 的 16-23位 UINT iKey = MapVirtualKey(VirtualKey, 0); // 1为 lparam 参数的 0-15位,即发送次数 sCode = (Firstbyte << 24) + (iKey << 16) + 1; return sCode; }
int MakeKeyLparam(int VirtualKey, int flag) { UINT sCode; //Firstbyte ; lparam 参数的 24-31位 UINT Firstbyte; switch (flag) {// 24 Specifies whether the key is an extended key, // 25–28 Reserved; do not use // 29 Specifies the context code. // The value is 1 if the ALT key is down while the key is pressed; // it is 0 if the WM_SYSKEYDOWN message is posted to the active window // because no window has the keyboard focus.
如果键盘键入的是“Ctrl+D”,则应该选择WM_KEYDOWN,因为WM_KEYDOWN既包含字母也包含特殊字符。
WM_CHAR是由WM_KEYDOWN消息Translate()之后产生的,然后再发送给窗口过程。例如按下“D”键,产生WM_KEYDOWN消息,此消息经过Translate()处理后变成了WM_KEYDOW、WM_CHAR两个消息传递给窗口过程。
而WM_SYSKEYDOWN是接受快捷键或系统命令按键的,像Alt键就是。所以捕获Alt键时,在WM_KEYDOWN下是无效的,要在WM_SYSKEYDOWN中。Ctrl和shift不属于WM_SYSKEYDOWN。"
我发的消息是用SPY++查来的,看了你的回答,有点迷糊
倒底给后台记事本发Alt+E应该用什么?
我是用的WM_SYSKEYDOWN呀?
PostMessage(m_hWnd, WM_SYSCHAR, 'E', MakeKeyLparam('E', WM_SYSCHAR));
看
PostMessage(m_hWnd, WM_SYSKEYDOWN, VK_MENU, MakeKeyLparam(VK_MENU, WM_SYSKEYDOWN));
PostMessage(m_hWnd, WM_SYSKEYDOWN, 'E', MakeKeyLparam('E', WM_SYSKEYDOWN));
PostMessage(m_hWnd, WM_CHAR, 'E', MakeKeyLparam('E', WM_CHAR));
PostMessage(m_hWnd, WM_SYSKEYUP, 'E', MakeKeyLparam('E', WM_SYSKEYUP));
PostMessage(m_hWnd, WM_KEYUP, VK_MENU, MakeKeyLparam(VK_MENU, WM_KEYUP));
一样没效果,如果把记事本程序放在前台就能成功
MakeKeyLparam
是 VB 的 吧 ?
{
unsigned int sCode;
AnsiString strLp, Firstbyte, Secondbyte;
switch (flag)
{
case WM_KEYDOWN: Firstbyte = "00";
break;
case WM_KEYUP: Firstbyte = "C0";
break;
case WM_CHAR: Firstbyte = "20";
break;
case WM_SYSKEYDOWN: Firstbyte = "20";
break;
case WM_SYSKEYUP: Firstbyte = "E0";
break;
case WM_SYSCHAR: Firstbyte = "E0";
break;
}
int iKey = MapVirtualKey(VirtualKey, 0);
Secondbyte = IntToHex(iKey, 2);
strLp = "0x" + Firstbyte + Secondbyte + "0001";
sCode = strLp.ToInt();
return sCode;
}
if( hwnd)
{
::BringWindowToTop(hwnd);
keybd_event(VK_MENU,0,0,0);
keybd_event('F',0,0,0);
keybd_event('F',0,KEYEVENTF_KEYUP,0);
keybd_event(VK_MENU,0,KEYEVENTF_KEYUP,0);
}
AttachThreadInput
AttachThreadInput(GetWindowThreadProcessId(A, NULL), GetWindowThreadProcessId(B, NULL), true)
挂上后,给B发消息(就是原来那些),B没反应,A的Edit菜单出来了(为了试验也给A加了EDIT菜单) 其实从前面函数PostMessage的返回值和发送单键能成功看到效果上看得出来,目标程序(记事本)是能接到我们发的消息的,但不知道为什么没反应
::BringWindowToTop(hwnd); 还是 去不掉。
AttachThreadInput(GetWindowThreadProcessId(B, NULL), GetWindowThreadProcessId(A, NULL), true)
{
UINT sCode;
//Firstbyte ; lparam 参数的 24-31位
UINT Firstbyte;
switch (flag)
{
case WM_KEYDOWN: Firstbyte = 0; break;
case WM_KEYUP: Firstbyte = 0xC0;break;
case WM_CHAR: Firstbyte = 0x20;break;
case WM_SYSKEYDOWN: Firstbyte = 0x20;break;
case WM_SYSKEYUP: Firstbyte = 0xE0;break;
case WM_SYSCHAR: Firstbyte = 0xE0;break;
}
// 键的扫描码; lparam 参数 的 16-23位
UINT iKey = MapVirtualKey(VirtualKey, 0);
// 1为 lparam 参数的 0-15位,即发送次数
sCode = (Firstbyte << 24) + (iKey << 16) + 1;
return sCode;
}
{
UINT sCode;
//Firstbyte ; lparam 参数的 24-31位
UINT Firstbyte;
switch (flag)
{// 24 Specifies whether the key is an extended key,
// 25–28 Reserved; do not use
// 29 Specifies the context code.
// The value is 1 if the ALT key is down while the key is pressed;
// it is 0 if the WM_SYSKEYDOWN message is posted to the active window
// because no window has the keyboard focus.
WM_SYSKEYDOWN 改 WM_KEYDOWN
不过 不明白 为什么 不能 ::BringWindowToTop(hwnd);
做一个程序,设置好参数及方案,自动处理图形及相关计算,但这个过程想在后台进行,不想影响前台的工作(计算机不多呀,嘿嘿)