如果模拟键盘按下ALT + 字符键(如ALT + D )

coolbobo 2009-07-30 02:19:31
用了这个方法,PostMessage(CBHwnd,WM_KEYDOWN, VK_LMENU + VK_D, 0)
一直调试不通过,也就是没有起到作用。

不能用keybd_event,因为可能发送的消息窗体不是当前活动的窗体。谢谢
...全文
864 46 打赏 收藏 转发到动态 举报
写回复
用AI写文章
46 条回复
切换为时间正序
请发表友善的回复…
发表回复
twoods 2012-08-29
  • 打赏
  • 举报
回复
&H44是D的虚拟码
twoods 2012-08-29
  • 打赏
  • 举报
回复
Call SendMessage(Hwnd, &H104, &H11, &H20380001) '按下alt
Call SendMessage(Hwnd, &H104, &H44, &H20210001) 'WM_SYSKEYDOWN = &H104 ‘按下字母
Call SendMessage(Hwnd, &H106, &H44, &H20210001) 'WM_SYSCHAR = &H106 '发送字母
Call SendMessage(Hwnd, &H105, &H11, &HC0380001) '抬起alt
tjj5203 2009-08-03
  • 打赏
  • 举报
回复
学习!
coolbobo 2009-08-03
  • 打赏
  • 举报
回复
CaiBirdy,我已经按照你的方法实现了。
感觉感谢您的支持,希望我们交个朋友,您的邮箱是多少,有空Mail 您
black_killer 2009-08-01
  • 打赏
  • 举报
回复
PostMessage(WinHandle,WM_KEYUP,Ord('D'),MakeKeyLparam(Ord('D'),WM_KEYUP));
PostMessage(WinHandle,WM_KEYDOWN,VK_LMENU,MMakeKeyLparam(VK_LMENU,WM_KEYUP));
coolbobo 2009-07-31
  • 打赏
  • 举报
回复
//重贴代码,仍然不起作用。
procedure TfrmSimulation.ShowArchive(CBHwnd: HWND);
function MakeSysKeyDownFirstByte(VirtualKeyType:LONGINT):string;
begin
// VirtualKeyType : 0 - alt ;1 - ctrl 2- shift
case VirtualKeyType of
0: result:='21';// 00100001
1: result:='01';// 00000001
2: result:='01';// 00000001
end;
end;
function MakeKeyLparam(VirtualKey:LONGINT; flag :LONGINT):LONGINT;
var
s:String;
Firstbyte:String; // lparam参数的24-31位
Scancode:LONGINT;
Secondbyte:string; //lparam参数的16-23位,即虚拟键扫描码
begin
if flag = WM_KEYDOWN then
Firstbyte :='00'
else
Firstbyte := 'C0';

if flag = WM_SYSKEYDOWN then
begin
case VirtualKey of
VK_MENU,VK_LMENU,VK_RMENU: Firstbyte:=MakeSysKeyDownFirstByte(0);
VK_SHIFT: Firstbyte:=MakeSysKeyDownFirstByte(2);
VK_CONTROL: Firstbyte:=MakeSysKeyDownFirstByte(1);
end;
end;
//获得键的扫描码
Scancode := MapVirtualKey(VirtualKey, 0);
Secondbyte := IntToHex(Scancode, 2);
s :='$'+Firstbyte + Secondbyte + '0001';
result := strtoint(s);
end;
begin
//CTRL+D被按下
PostMessage(CBHwnd,WM_KEYDOWN,ord('D'), MakeKeyLparam(VK_MENU,WM_SYSKEYDOWN));
Sleep(500);
PostMessage(CBHwnd, WM_KEYDOWN, VK_RETURN, 0);
PostMessage(CBHwnd,WM_KEYUP,ord('D'),MakeKeyLparam(VK_MENU,WM_KEYUP));
end;
coolbobo 2009-07-31
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 caibirdy 的回复:]
用25楼的代码替换吧,应该没问题的
[/Quote]

兄弟,根据您的意见,我修改了,还是不起作用,请帮忙看下。多谢啦。。。。。
procedure TfrmSimulation.ShowArchive(CBHwnd: HWND);
function MakeSysKeyDownFirstByte(VirtualKeyType:LONGINT):string;
begin
// VirtualKeyType : 0 - alt ;1 - ctrl 2- shift
case VirtualKeyType of
0: result:='21';// 00100001
1: result:='01';// 00000001
2: result:='01';// 00000001
end;
end;
function MakeKeyLparam(VirtualKey:LONGINT; flag :LONGINT):LONGINT;
var
s:String;
Firstbyte:String; // lparam参数的24-31位
Scancode:LONGINT;
Secondbyte:string; //lparam参数的16-23位,即虚拟键扫描码
begin
if flag = WM_KEYDOWN then
Firstbyte :='00'
else
Firstbyte := 'C0';

if flag = WM_SYSKEYDOWN then
begin
case VirtualKey of
VK_MENU,VK_LMENU,VK_RMENU: Firstbyte:=MakeSysKeyDownFirstByte(0);
VK_SHIFT: Firstbyte:=MakeSysKeyDownFirstByte(2);
VK_CONTROL: Firstbyte:=MakeSysKeyDownFirstByte(1);
end;
end;
//获得键的扫描码
Scancode := MapVirtualKey(VirtualKey, 0);
Secondbyte := IntToHex(Scancode, 2);
s :='$'+Firstbyte + Secondbyte + '0001';
result := strtoint(s);
end;
begin

//CTRL+D被按下
PostMessage(CBHwnd, WM_KEYDOWN, VK_MENU, MakeKeyLparam(VK_MENU, WM_SYSKEYDOWN));
PostMessage(CBHwnd, WM_KEYDOWN, Ord('D'),MakeKeyLparam(Ord('D'), WM_SYSKEYDOWN));
//回车键被按下
PostMessage(CBHwnd, WM_KEYDOWN, VK_RETURN, 0);
//CTRL+D被弹出
PostMessage(CBHwnd, WM_KEYUP, Ord('D'),MakeKeyLparam(Ord('D'), WM_KEYUP));
PostMessage(CBHwnd, WM_KEYUP, VK_MENU, MakeKeyLparam(VK_MENU, WM_KEYUP));
{
//模拟键盘ALT+D键被按下
keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
keybd_event(VK_D, MapVirtualKey(VK_D, 0), 0, 0);
keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), 0, 0);
//模拟键盘ALT+D键被弹出
keybd_event(VK_D, MapVirtualKey(VK_D, 0), KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0);
}
end;
CaiBirdy 2009-07-31
  • 打赏
  • 举报
回复
用25楼的代码替换吧,应该没问题的
coolbobo 2009-07-31
  • 打赏
  • 举报
回复
而且好像用了keybd_event后,发送消息SendMessage()都不管用的。
coolbobo 2009-07-31
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 caibirdy 的回复:]
alt用VK_MENU吧,我试了VK_LMENU确实是无法触发,VK_MENU才可以
[/Quote]

你试过用吗?
我怎么试了就没有用了。用keybd_event事件才有用的:
//模拟键盘ALT+D键被按下
keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
keybd_event(VK_D, MapVirtualKey(VK_D, 0), 0, 0);
keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), 0, 0);
//模拟键盘ALT+D键被弹出
keybd_event(VK_D, MapVirtualKey(VK_D, 0), KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0);
CaiBirdy 2009-07-31
  • 打赏
  • 举报
回复
应该是这样最后才是真正释放alt,刚才写错了
PostMessage(WinHandle,WM_KEYDOWN,ord('D'),MakeKeyLparam(VK_MENU,WM_SYSKEYDOWN));
Sleep(50);
PostMessage(WinHandle,WM_KEYUP,ord('D'),MakeKeyLparam(VK_MENU,WM_KEYUP));
CaiBirdy 2009-07-31
  • 打赏
  • 举报
回复
function MakeSysKeyDownFirstByte(VirtualKeyType:LONGINT):string;
begin
// VirtualKeyType : 0 - alt ;1 - ctrl 2- shift
case VirtualKeyType of
0: result:='21';// 00100001
1: result:='01';// 00000001
2: result:='01';// 00000001
end;
end;

Function MakeKeyLparam(VirtualKey:LONGINT; flag :LONGINT):LONGINT;
var
s:String;
Firstbyte:String;
Scancode:LONGINT;
Secondbyte:string;
begin
If flag = WM_KEYDOWN Then
Firstbyte :='00';
If flag = WM_KEYUP Then
Firstbyte := 'C0';

if flag = WM_SYSKEYDOWN then
begin
case VirtualKey of
VK_MENU,VK_LMENU,VK_RMENU:
Firstbyte:=MakeSysKeyDownFirstByte(0);
VK_SHIFT :Firstbyte:=MakeSysKeyDownFirstByte(2);
VK_CONTROL:Firstbyte:=MakeSysKeyDownFirstByte(1);
end;
end;

//获得键的扫描码
Scancode := MapVirtualKey(VirtualKey, 0);
Secondbyte := Strctrls.FormatIntToHexStr(Scancode,2,'0');
s :='$'+Firstbyte + Secondbyte + '0001';
result := strtoint(s);
end;

=================
帮你修改了,这次可以了
PostMessage(WinHandle,WM_KEYDOWN,ord('D'),MakeKeyLparam(VK_MENU,WM_SYSKEYDOWN));
Sleep(50);
PostMessage(WinHandle,WM_KEYUP,ord('D'),MakeKeyLparam(VK_MENU,WM_SYSKEYDOWN));
CaiBirdy 2009-07-31
  • 打赏
  • 举报
回复
alt用VK_MENU吧,我试了VK_LMENU确实是无法触发,VK_MENU才可以
米的向日葵 2009-07-31
  • 打赏
  • 举报
回复
mark
coolbobo 2009-07-31
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 dinoalex 的回复:]
Delphi(Pascal) code
postmessage(CBHwnd,WM_KEYDOWN,VK_D,$20000000);
[/Quote]

实现不了,奇怪。
coolbobo 2009-07-31
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 de410 的回复:]
Delphi(Pascal) codeSendMessage(hwnd, 0x0104, 0x11, 0x20380001);
SendMessage(hwnd, 0x0104, (int)'D', 0x20210001);
SendMessage(hwnd, 0x0106, (int)'D', 0x20210001);
SendMessage(hwnd, 0x0105, 0x11,0xC038¡­
[/Quote]
这里编译不通过,谢谢支持。
CaiBirdy 2009-07-31
  • 打赏
  • 举报
回复
好像不用激活,
PostMessage(WinHandle,WM_SYSCHAR,ord('D'),MakeKeyLparam(VK_MENU,WM_SYSKEYDOWN));// '按下Alt+D键
Sleep(50);
PostMessage(WinHandle,WM_KEYUP,ord('D'),MakeKeyLparam(VK_MENU,WM_KEYUP));// '释放Alt+D键
Sleep(50);
PostMessage(WinHandle, WM_KEYDOWN, VK_RETURN, 0);
=========================
直接用这个执行,其他不用改,不过又好像跟系统反应速度有关,90%以上可以把菜单执行出来,前面会需要执行两次应该是窗口焦点变来变去,就是说实际上菜单已经被呼叫出来了,但由于焦点变回我在测试的那个窗体,所以导致菜单一闪而过,我刚还以为是没出来菜单呢,呵呵。。。。
CaiBirdy 2009-07-31
  • 打赏
  • 举报
回复
建议还是先激活吧,39楼的代码需要重复两次才能呼出菜单,第一次会把窗口激活,第二次才能呼出菜单。。所以还是建议先把窗口激活,再执行39楼的代码。就可以一次呼出菜单。再执行PostMessage(CBHwnd, WM_KEYDOWN, VK_RETURN, 0); 。。

。。。。
。。。。。。。。。。。
改成这个 :
// '按下Alt+D键
PostMessage(WinHandle,WM_SYSCHAR,ord('D'),MakeKeyLparaM(VK_MENU,WM_SYSKEYDOWN));
Sleep(50);
// '释放Alt+D键
PostMessage(WinHandle,WM_KEYUP,ord('D'),MakeKeyLparam(VK_MENU,WM_KEYUP));
Sleep(50);
PostMessage(WinHandle, WM_KEYDOWN, VK_RETURN, 0); 。。
CaiBirdy 2009-07-31
  • 打赏
  • 举报
回复
改成这个
// '按下Alt+D键
PostMessage(WinHandle,WM_SYSCHAR,ord('D'),MakeKeyLparaM(VK_MENU,WM_SYSKEYDOWN));
Sleep(50);
// '释放Alt+D键
PostMessage(WinHandle,WM_KEYUP,ord('D'),MakeKeyLparam(VK_MENU,WM_KEYUP));
coolbobo 2009-07-31
  • 打赏
  • 举报
回复
与窗体激活没有关系的。你可以试下用你的方法触发菜单点击,这种方法不行。但是用KeyBD的方法是可以的
加载更多回复(26)

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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