摘要:利用Delphi6自己开发的后台程序,在官方提供的SetPoint V2.40驱动程序以及笔者自行编写的扩展补丁V1.0、V2.0的基础上,再一次自定义扩展了鼠标上的众多功能键,连滚轮的功能也扩展了。并且使用了配置文件,更加通用。关键字:Delphi、Windows API、消息、钩子、四向(横向)滚轮、灵貂(多媒体)、LX5、罗技Logz、热键、剪贴板、配置文件。
██████████ 注意
请使用Fixedsys、Courier New等“中英文等间距”的字体浏览本文!
██████████ 前传
[Delphi]罗技无限灵貂Logz,驱动程序补丁─实现真正的多媒体遥控器!附QQ图标,标题栏伪装程序(Patch2)
http://blog.youkuaiyun.com/ACDSeeQ/archive/2005/12.aspx
██████████ 前言
05年8月买完灵貂,并且自定义扩展了鼠标功能键的功能后,使用到现在,用着真TMD爽。而且不少网友买完灵貂后纷纷向我索要扩展补丁,令我十分欣喜,可以和别人共同分享我的“小聪明”,呵呵。但新的问题又有了,于是又开始有了新的需求。
公司除了为我们软件部每人配台Notebook之外,在办公室每人又配了台PC,而且显示器是17"液晶的。平常我在办公室更喜欢用PC,写了一个映射驱动器的批处理文件,一点击之后,就可以把Notebook当成服务器用了,充分发挥17"液晶的价值。因此灵貂就要在不停地在两台电脑之间切换,有的时候笔记本用灵貂的时候,PC也要临时用下鼠标,只好插上一个小光电鼠标对付一下,但用着很不爽。突然想起了白云大妈的一句名言——程序员对自己下手就要狠一点!于是痛下决心,再去买一个Logz无线鼠标。
本来05年初的时候买过一个Logz无线鼠标——旋貂极光版(我的第一个无线鼠标,从此拉开了我的‘无线&伸缩’时代,呵呵),可到了8月突然坏了(后文交代处理结果)。已经用惯了无线,并且打算升级,因此也就懒得去修理,直接买的灵貂。这次就不用再买个灵貂了,太TMD贵了!主要是为了PC临时用的,所以买个便宜点的就够了,上网又收集了一下资料并且打电话到上一次的教化专卖店,最终以190的价格又捧回了一个LX5,虽然没有灵貂那么多的多媒体功能键,但滚轮是四向的,可以横向滚动,就是下按的时候手感有些硬,不过用胜于无么。(比较了一下,LX5的中键手感不如罗技的其它产品,旋貂都比它强!不推荐大家买LX5,我是买了就没办法了。)
拿回来用以后,无论是在PC上临时用,还是在笔记本上临时用,少了很多灵貂的扩展功能,觉得相当不习惯。于是琢磨着,怎么把灵貂的扩展功能做的更通用一些,让LX5也能用上呢?LX5除了左右键,有三个可以自定义的功能键——中键(即滚轮下按)、左滚右滚(横向滚轮)。仔细一想,其实横向滚轮用的机会不是很多,真要是有用到的时候,多费点事,左键按住滚动条滚动就可以了。打个比方,汽车都会把喇叭、转向指示灯和方向盘做在一起,决不会把调整收音机的音量、播放CD这些东西放在方向盘上,放上了也是鸡肋,除了显得技术含量高,实用价值不大(但有些中高档车的确已经做到了)。于是决定埫横滚作为两个鼠标共享扩展功能的接口。又经过在官方程序中可以利用的功能中的一番挑选,并考虑到笔者本人编程实力有限,决定为横滚指定快捷键(即组合键、热键)来作为共享扩展功能的接口。如此一来,天下所有滚轮可以四向滚动的鼠标都可以使用我的驱动补丁了,只要鼠标自带的驱动可以为横滚指定按键组合。——此为v2.0
此外,在同事的强烈建议之下,决定将扩展功能写到配置文件中,这样一来,可以更加通用,不会仅仅局限在笔者本人最常使用的软件的范围内,让每个横向滚轮鼠标的用户都能发挥他们手中的鼠标的强大功能!欲使新的配置生效,只需重新注销、登录(如果是灵貂,只需按Shift+Alt+PP *^-^* )。——此为v3.0
██████████ 术语约定
官方驱动:SetPoint V2.40
扩展补丁、自定义补丁:Logz V3.0
普通鼠标——
中键:滚轮下按
四向鼠标——
左滚:滚轮向左掰
右滚:滚轮向右掰
横滚:左滚or右滚
灵貂——
UU:向上浏览
DD:向下浏览
PP:Play/Pause >||
FF:Forward >>
BB:Backward <<
██████████ 笔者的 SetPoint 设置
版本——
2.40(
2.47
、
2.60
不好使,鸡肋)
灵貂、LX5——
中键:Close
左滚[LogzHotKey0]:Shift+Alt+0 (先按0,再按Shift+Alt)
右滚[LogzHotKey1]:Shift+Alt+1 (这两个按键组合不要被系统中已有的应用软件占用)
灵貂——
Media:Ctrl+F4
UU:向上浏览(缺省)
DD:向下浏览(缺省)
██████████ 驱动补丁嵌入的扩展功能明细
◎◎◎◎ 关闭补丁程序=Ctrl+Shift+Alt+PP
◎◎◎◎ 重新加载配置=Shift+Alt+PP(for 灵貂 only)
◎◎◎ ACD SYSTEMS
⊙⊙ ACDSee 5.0 Viewer
左滚:* (缩小至全屏查看)
右滚:/ (放大至实际大小)
(看起图片来,真TMD方便!)
⊙⊙ ACD FotoCanvas
⊙ Resize
左滚:36% (缩小图片至36%并回车确定,为了和FotoCanvas的左滚保持一致)
右滚:[待定]
⊙ Edit Description
左滚:Alt+A、回车
右滚:[待定]
◎◎◎ Delphi6
左滚:Ctrl+F9 (编译)
右滚:F9 (编译并运行)
PP:F12 (查看窗体)
FF:Ctrl+F2 (终止编译程序的运行)
BB:F11 (对象观察器)
Ctrl+PP:Ctrl+F12 (查看单元)
Ctrl+BB:Ctrl+F11 (打开工程)
◎◎◎ MPC
UU:前进10秒
DD:倒退10秒
◎◎◎ 影音传送带
⊙⊙ 主界面
⊙ 选择要下载的URL
UU、DD:只勾择 .JPG 文件,并模拟点击‘确定’
⊙ 添加新的下载任务
UU:勾选‘手工开始’单选框,并模拟点击‘确定’
DD:勾选‘立即开始’单选框,并模拟点击‘确定’
Ctrl+UU:如果操作系统剪贴板的内容是一段文字,将其填补到‘目录’编辑框中,勾选‘手工开始’单选框,并模拟点击‘确定’
Ctrl+DD:如果操作系统剪贴板的内容是一段文字,将其填补到‘目录’编辑框中,勾选‘立即开始’单选框,并模拟点击‘确定’
██████████ 后话
那个后买的LX5,由于中键手感不如我的灵貂和另两个同事的罗技鼠标,拿到代理那儿去换,换了之后还是一个德行,本想算了。不过给我拿出来的新LX5颜色和我的灵貂差不多,于是强词夺理地又要求换了,哈哈。
新版补丁把大量扩展操作转移到了横滚上,因此对罗技无线鼠标的滚轮的机械品质绝对是个考验,希望罗技的制作工艺不会令我失望。
刚买第一个LX5的时候,他们给我的名片上又多了罗技维修处的地址和电话,我一瞧,和我单位离得很近,于是有天午饭后把那个坏了的旋貂拿去了。维修处真TM破呀,和废品收购站差不多。初步断定是接收器坏了,由于旋貂已经停产了,可能会给我换个新的。过了不到十天,我打电话询问进展,说让我过去拿换的新的。去了以后,给我换了个工包的(把一套键鼠套装中的无线旋貂换给我了)。
后来有人告诉我网上罗技最新的驱动是2.47、2.60……等等,于是我升级了驱动,但并未发现有何新颖的创新,界面稍有些改观。不过我的补丁程序不好使了,最后只好把新的驱动卸载,重新安装了2.40版的驱动,补丁又重新好使了,并且继续发挥强大的功能了。看来2.40应该是罗技最稳定的驱动了,hoho。
本人酷爱数码摄影,每次用松下FZ30拍回来的图片,利用ACDSee FotoCanvas 2.0对图片进行PS。如果没有旋转、裁剪这些操作,在驱动补丁的辅助下,PS一张原始的数码图片,连5秒钟都用不了,对于我来说,那-真-是--相当方便了!
我个人在很多自己经常使用的对话框中,将左滚设定为回车键,现在,左滚基本上就相当于半个回车键了,快捷方便!
██████████ 图片及下载
如果您手中的鼠标也带有横向滚轮,或者恰巧是罗技的产品,甚至就是罗技无限灵貂,而且对该补丁感兴趣,可以致信作者。
另外,补丁程序将Delphi IDE中的很多资源设为动态链接,因此产生了一个优点和一个缺点。
优点是:文件体积非常小。所有文件加在一起连200k都不到,其中嵌入到程序中的两个美观的图标就占了50k,哈哈。
缺点是:在没有安装Delphi开发环境的计算机中使用,可能会报错说某些文件找不到,那么用户可以自行到网上下载或者给笔者来信索要。目前得到的信息是,这些缺失的文件应当包括——
Name Size Date
--------------------------- -------- ---------------
adortl60.bpl 146 KB 2002-2-15 14:02
dbrtl60.bpl 249 KB 2002-2-15 14:02
indy60.bpl 502 KB 2001-5-22 14:00
qtintf.dll 4,046 KB 2002-2-15 14:02
rtl60.bpl 669 KB 2003-3-20 6:04
vcl60.bpl 1,295 KB 2002-2-15 14:02
visualclx60.bpl 1,035 KB 2002-2-15 14:02
笔者的鼠标实物、官方驱动、自定义补丁的设置放在了163相册里(http://photo.163.com/photos/logzmouse/),仅供参考。
如要应用补丁,官方驱动的版本以及设置务必与笔者保持一致!
██████████ 作者联系方式
如果您有什么改进的建议或者不解的疑问,或是提供更好的编程技巧,或是索要补丁程序,欢迎与作者联系。
╱╲
╔═══════════════╦══════════════╱㊣╱
║Logz ║ V3.0 ╱ ╱
╟───────────────╫────────────╱ ╱╢
║ 木 小 折 ║ ◣╱ ║
╟───────────────╫───────────────╢
║ 子 兀 口 ║ LogzMouse ║
╟───────────────╫───────────────╢
║ Erngy Lee ║ @163.com ║
╟───────────────╫───────────────╢
║ 2006年║5月 ║
╚═══════════════╩═══════════════╝
██████████ URL
http://blog.youkuaiyun.com/ACDSeeQ/
██████████ Delphi Source Dode
//▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ Logz.dpr
{ 罗技无限灵貂Logz,驱动程序扩展补丁
V3.0
且适用于所有罗技四向滚轮鼠标
作者:Lgz
日期:2006年5月
┏━━┳━━━━━━┳━━━━┳━━━━━━┓
┃罗技┃ P/N ┃ M/N ┃ S/N or PID ┃
┣━━╋━━━━━━╋━━━━╋━━━━━━┫
┃灵貂┃852213-0000 ┃M-RAM99 ┃LZB50154923 ┃
┣━━╋━━━━━━╋━━━━╋━━━━━━┫
┃LX5 ┃831192-3000 ┃C-BN4 ┃LZ547AU ┃
┗━━┻━━━━━━┻━━━━┻━━━━━━┛
}
program Logz;
uses
Forms,
SysUtils,
Windows,
DlgDebug_U,
FrmMediaPlayer_U in 'FrmMediaPlayer_U.pas' {frmMediaPlayer},
Shared_U in '../../../Delphi/[Public]/Shared_U.pas';
{$R *.res}
begin
Application.Initialize;
//启动调试
SD_Debug_Show(findCmdLineSwitch('debug', ['/', '-'], true));
Application.ShowMainForm := False; //隐藏
Application.CreateForm(TfrmMediaPlayer, frmMediaPlayer);
ShowWindow(Application.Handle, SW_HIDE);//隐藏
Application.Run;
end.
//▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ FrmMediaPlayer_U.pas
{ 主界面(后台隐形运行)
主要利用WndProc以及热键(WMHotKey)捕捉消息并进行处理
2006年5月
}
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
unit FrmMediaPlayer_U; interface
uses Windows, Messages, Forms, CommCtrl, Classes, Controls, StdCtrls, IniFiles,
ExtCtrls, SysUtils, Dialogs, DlgDebug_U, Clipbrd, Shared_U, Qt, Const_U,
StrUtils;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
const
LOGITECH = $0319;//利用VC的Spy捕捉到的
PLAY_PAUSE = $E0000;
PLAY_LEFT = $C0000;
PLAY_RIGHT = $B0000;
LOGZHOTKEYWORD0= 'LogzHotKeyword0';
LOGZHOTKEYWORD1= 'LogzHotKeyword1';
ItemNo = 36;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
type
TLogzItem = record
//欲应用补丁的窗体(对话框)的信息,在本程序中,定义为“项目”。详情请参考配置文件
Onn: Boolean;
ItemIndex,//[Item01]
ExecSQL,
Description,
Keywords,
HotGun0,
HotGun1,
UU,
DD,
PP,
BB,
FF,
Ctrl_HotGun0,
Ctrl_HotGun1,
Alt_PP,
Alt_BB,
Alt_FF,
Ctrl_PP,
Ctrl_BB,
Ctrl_FF,
Shift_PP,
Shift_BB,
Shift_FF
: string;
end;
TfrmMediaPlayer = class(TForm)
le: TLabeledEdit;
Nemo: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure WndProc(var Mssg: TMessage); override;
private
{ Private declarations }
hwLogz: HWND;//Window
tlLogz, clsName: string;//Title, Class
Buf: array[0..1024] of Char;
dwnCtrl, dwnShift, dwnAlt: Boolean;//Down
LogzHotID : array [0..1] of Integer;//热键标识ID
LogzHotKey: array [0..1] of Boolean;//触发了哪个热键
Items: array [1..ItemNo] of TLogzItem;//窗体(对话框)信息
ExecKeys: array [0..2] of byte;//转换后的组合键
procedure WMLogzHotKey (var Mssg: TWMHotKey); message WM_HotKey ;
procedure WMDrawClipBoard(var Mssg: TMessage ); message WM_DRAWCLIPBOARD;
procedure LoadConfiguration;
procedure GetForeWindowInfo;
function TitleKeyword(theKeyword: string): Boolean;
function ClassKeyword(theKeyword: string): Boolean;
function TitleIS(theKeyword: string): Boolean;
function ClassIS(theKeyword: string): Boolean;
function KeywordsMatchTitle(const theKeywords: string): Boolean;
procedure ExecuseMe(theExecSQL: string);
public
{ Public declarations }
NextClipHwnd: HWND;//剪贴板观察链中下一个窗口句柄
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
var frmMediaPlayer: TfrmMediaPlayer;
implementation
uses MisCtrls_U;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
//罗技无限灵貂
procedure EnableWheelHook ; stdcall; external 'LogzHook.dll';
procedure DisableWheelHook; stdcall; external 'LogzHook.dll';
procedure Key1(VK1 : byte); external 'LogzHook.dll';
procedure Key2(VK1, VK2 : byte); external 'LogzHook.dll';
procedure Key3(VK1, VK2, VK3: byte); external 'LogzHook.dll';
procedure KeyStr(const theStr: string);external 'LogzHook.dll';
procedure Down(VK: byte); external 'LogzHook.dll';
procedure UP (VK: byte); external 'LogzHook.dll';
function StrToVK(theKeyStr: string): byte; external 'LogzHook.dll';
function VKToStr(theVisKey: byte): string; external 'LogzHook.dll';
procedure LoadVisualKeys; external 'LogzHook.dll';
{$R *.dfm}
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.FormCreate(Sender: TObject);
//界面初始化
var i: integer;
begin
FormStyle := fsStayOnTop;
//复制粘贴要用的
le.Width := 50000;
Nemo.Width := le.Width;
EnableWheelHook;//罗技灵貂蓝色侧键,WM_MouseWheel 消息钩子
Lgf := 'LogzClip.txt';//剪贴板要用的
NextClipHwnd:=SetClipBoardViewer(Handle);//获得观察链中下一个窗口句柄
//配置文件
Cnf := './Logz.conf';
Conf:= TIniFile.Create(cnf);
LoadConfiguration;
LoadVisualKeys;
//注册全局热键 Shift+Alt+0/1
if (GlobalFindAtom(LOGZHOTKEYWORD0)=0)and(GlobalFindAtom(LOGZHOTKEYWORD1)=0) then begin
LogzHotID[0] := GlobalAddAtom(LOGZHOTKEYWORD0);
LogzHotID[1] := GlobalAddAtom(LOGZHOTKEYWORD1);
RegisterHotKey(Handle, LogzHotID[0], MOD_SHIFT or MOD_Alt, Key_0);
RegisterHotKey(Handle, LogzHotID[1], MOD_SHIFT or MOD_Alt, Key_1);
end else halt;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.FormClose(Sender: TObject; var Action: TCloseAction);
//程序退出
begin
//从观察链中删除本观察窗口
ChangeClipboardChain(Handle, NextClipHwnd);
//将WM_DRAWCLIPBOARD消息传递到下一个观察链中的窗口
SendMessage(NextClipHwnd, WM_CHANGECBCHAIN, Handle, NextClipHwnd);
UnRegisterHotKey(Handle, LogzHotID[0]); GlobalDeleteAtom(LogzHotID[0]);
UnRegisterHotKey(Handle, LogzHotID[1]); GlobalDeleteAtom(LogzHotID[1]);
DisableWheelHook;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.WndProc(var Mssg: TMessage);
//无限灵貂中右侧三个键
var i: integer;
begin with Mssg do begin
inherited;
//如果不是多媒体键区的中右侧三个键按下,则退出
IF NOT( (Msg=LOGITECH) AND ((lParam=PLAY_PAUSE)OR(lParam=PLAY_LEFT)OR(lParam=PLAY_RIGHT)) ) THEN exit;
GetForeWindowInfo;
//是否刷新配置
if dwnShift and dwnAlt and (lParam=PLAY_PAUSE) then LoadConfiguration;
//Close
if dwnShift and dwnAlt and (lParam=PLAY_PAUSE) and dwnCtrl then Close;
//以下是一些嵌入代码:为个人定制
//ACDSee5
if TitleKeyword('ACDSee') and TitleKeyword('5.0') then begin
if dwnCtrl then begin//按下了Ctrl键
Up(VK_Control);
case lParam of
PLAY_PAUSE: ;//enumChildWindows(hwLogz, @EnumAseChildWndProc_Less10K, 0);
end;
end else if dwnAlt then begin//按下了Alt键
Up(VK_Menu);
case lParam of
//PLAY_PAUSE: enumChildWindows(hwLogz, @EnumAseChildWndProc_Less10K, 0);
PLAY_LEFT : begin Key2(VK_Menu, VK_Left); Key1(VK_F3); Key2(VK_Menu, ord('S')); end;
//PLAY_RIGHT: Key1(VK_DIVIDE );// /
end;
end;
//exit;//不能exit,配置文件里还有ACDSee的信息
end;
//Delphi6
if pos('T', clsName)=1 then begin
if dwnCtrl then begin
Up(VK_Control);
case lParam of
PLAY_PAUSE: Key2(VK_Control, VK_F12);//Ctrl+F12
PLAY_LEFT : Key2(VK_Control, VK_F11);//Ctrl+F11, Open Project
end;
end else begin
case lParam of
PLAY_PAUSE: Key1(VK_F12);//F12
PLAY_LEFT : Key1(VK_F11);//F11
PLAY_RIGHT: Key2(VK_Control, VK_F2);//Ctrl+F2
end;
end;
exit;
end;
//根据配置文件轮循处理:为大众通用
for i := 1 to ItemNo do begin
if not Items[i].Onn then continue;
if not KeywordsMatchTitle(Items[i].Keywords) then continue;
if dwnAlt then begin
Up(VK_Menu);
case lParam of
PLAY_PAUSE: Items[i].ExecSQL := Items[i].Alt_PP;
PLAY_LEFT : Items[i].ExecSQL := Items[i].Alt_BB;
PLAY_RIGHT: Items[i].ExecSQL := Items[i].Alt_FF;
end;
end else if dwnCtrl then begin
Up(VK_Control);
case lParam of
PLAY_PAUSE: Items[i].ExecSQL := Items[i].Ctrl_PP;
PLAY_LEFT : Items[i].ExecSQL := Items[i].Ctrl_BB;
PLAY_RIGHT: Items[i].ExecSQL := Items[i].Ctrl_FF;
end;
end else if dwnShift then begin
Up(VK_Shift);
case lParam of
PLAY_PAUSE: Items[i].ExecSQL := Items[i].Shift_PP;
PLAY_LEFT : Items[i].ExecSQL := Items[i].Shift_BB;
PLAY_RIGHT: Items[i].ExecSQL := Items[i].Shift_FF;
end;
end else begin
case lParam of
PLAY_PAUSE: Items[i].ExecSQL := Items[i].PP;
PLAY_LEFT : Items[i].ExecSQL := Items[i].BB;
PLAY_RIGHT: Items[i].ExecSQL := Items[i].FF;
end;
end;
ExecuseMe(Items[i].ExecSQL);
break;
end;
end; end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.WMDrawClipBoard(var Mssg: TMessage);
//监视剪贴板
begin
//将WM_DRAWCLIPBOARD消息传递到下一个观察链中的窗口
SendMessage(NextClipHwnd, Mssg.Msg, Mssg.WParam, Mssg.LParam);
//查询剪贴板中特定格式的数据内容
if (Clipboard.HasFormat(CF_TEXT) or Clipboard.HasFormat(CF_OEMTEXT))
and(pos('Outlook Express', tlLogz)>0) and(pos('@', ClipBoard.AsText)>0) then begin
//处理剪贴板中内容
sLg_(Lgf, trim(Clipboard.AsText));
Clipboard.Clear;
end;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.WMLogzHotKey(var Mssg: TWMHotKey);
//捕获并处理横滚触发的热键
var i, j: integer;
begin
if (Mssg.HotKey<>LogzHotID[0])and(Mssg.HotKey<>LogzHotID[1]) then exit;
LogzHotKey[0] := Mssg.HotKey=LogzHotID[0];
LogzHotKey[1] := Mssg.HotKey=LogzHotID[1];
UP(VK_Shift); UP(VK_Menu); UP(Key_0); UP(Key_1);
GetForeWindowInfo;
//deb(tlLogz);
//以下是一些嵌入代码:为个人定制
//ACDSee5
if ClassIS('ImageViewWndClass')
or (ClassIS('Afx:400000:8')and TitleKeyword('ACDSee')and TitleKeyword('5.0')) then begin
if LogzHotKey[0] then Key1(VK_MULTIPLY) else Key1(VK_DIVIDE );// * or /
Key1(VK_F5);
exit;
end;
if (ClassIS('Afx:400000:0')and TitleKeyword('ACDSee')and TitleKeyword('5.0')) then begin
if LogzHotKey[0] then Key2(VK_Control, ord('E')) else Key1(VK_F4);
//exit;//这里不能用exit,否则如果在配置文件中为LogzHotKey0指定了按键组合,就会失效
end;
if TitleIS('Resize') then begin//For Panasonic-FZ30 only
if LogzHotKey[0] then
begin Key1(VK_NumPad3); Key1(VK_NumPad6); Key1(VK_Return); end;//36(%)+Return
exit;
end;
if TitleIS('Edit Description') then begin
if LogzHotKey[0] then
begin Key2(VK_Menu, ord('A')); Key1(VK_Return); end;
exit;
end;
//Delphi6
if (pos('T', clsName)=1) then begin
if LogzHotKey[0] then Key2(VK_Control, VK_F9)//Ctrl+F9 , Compile
else Key1(VK_F9);//F9=Run
exit;
end;
//影音传送带
if TitleIS('选择要下载的URL') then begin
PostMessage(hwLogz, WM_MouseWheel, $03C00000, $007E0104);//照着SPY程序写的
exit;
end else if TitleIS('添加新的下载任务') then begin
if dwnCtrl then begin
Up(VK_CONTROL);
Key2(VK_Menu, ord('D')); Key1(VK_End); Key2(VK_CONTROL, ord('V'));
end;
if LogzHotKey[0] then Key2(VK_Menu, ord('M')) else Key2(VK_Menu, ord('I'));//手工or立即
Key2(VK_Menu, ord('D'));
Key1(VK_Return);
exit;
end;
//根据配置文件轮循处理:为大众通用
for i := 1 to ItemNo do begin
if not Items[i].Onn then continue;
//[为pcAnywhere定制:for 孙总 only
if (pos('pcAnywhere', Items[i].Description)>0)and TitleIS(Items[i].Keywords) then begin
j := pos('^', Items[i].HotGun0);
if TitleIS('Credentials') then begin
Key2(VK_Menu, ord('D'));//&Domain/UserName
KeyStr(copy(Items[i].HotGun0, 1, j-1));
Key2(VK_Menu, ord('P'));//&Password
KeyStr(copy(Items[i].HotGun0, j+1, length(Items[i].HotGun0)-j));
Key1(VK_Return);
end;
if TitleIS('Symantec pcAnywhere - Host Login') then begin
Key2(VK_Menu, ord('U'));//&User Name
KeyStr(copy(Items[i].HotGun0, 1, j-1));
Key2(VK_Menu, ord('P'));//&Password
KeyStr(copy(Items[i].HotGun0, j+1, length(Items[i].HotGun0)-j));
Key1(VK_Return);
end;
break;
end;
//为pcAnywhere定制]
if not KeywordsMatchTitle(Items[i].Keywords) then continue;
if dwnCtrl then begin
Up(VK_Control);
if LogzHotKey[0] then Items[i].ExecSQL := Items[i].Ctrl_HotGun0
else Items[i].ExecSQL := Items[i].Ctrl_HotGun1;
end else begin
if LogzHotKey[0] then Items[i].ExecSQL := Items[i].HotGun0
else Items[i].ExecSQL := Items[i].HotGun1;
end;
ExecuseMe(Items[i].ExecSQL);
break;
end;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.GetForeWindowInfo;
//得到顶层窗体(对话框)的信息
begin
hwLogz := GetForegroundWindow;
GetWindowText(hwLogz, buf, 1024); tlLogz := string(buf);
GetClassName (hwLogz, buf, 1024); clsName := string(buf);
dwnCtrl := GetKeyState(VK_Control)<0;
dwnShift:= GetKeyState(VK_Shift )<0;
dwnAlt := GetKeyState(VK_Menu )<0;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function TfrmMediaPlayer.TitleKeyword(theKeyword: string): Boolean;
begin Result := pos(theKeyword, tlLogz)>0 end;
function TfrmMediaPlayer.ClassKeyword(theKeyword: string): Boolean;
begin Result := pos(theKeyword, clsName)>0 end;
function TfrmMediaPlayer.TitleIS(theKeyword: string): Boolean;
begin Result := theKeyword=tlLogz; end;
function TfrmMediaPlayer.ClassIS(theKeyword: string): Boolean;
begin Result := theKeyword=clsName; end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function TfrmMediaPlayer.KeywordsMatchTitle(const theKeywords: string): Boolean;
//判断顶层窗体(对话框)的标题栏是否与关键字组合相吻合
var j: byte;
sKw: string;
begin
sKw := theKeywords;
if isEmpty(theKeywords) then begin Result := false; exit; end
else Result := true;
repeat begin
j := pos('^', sKw);
if j=0 then begin
Result := Result and (pos(sKw, tlLogz)>0);
sKw := '';
end else begin
Result := Result and (pos(leftStr(sKw, j-1), tlLogz)>0);
sKw := rightStr(sKw, length(sKw)-j);
end;
end until not (Result and notEmpty(sKw));
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.ExecuseMe(theExecSQL: string);
//执行指定的按键组合
var i, j: integer;
s: string;
begin
i := 1;
j := pos('^', theExecSQL);
if j>0 then begin
inc(i);
ExecKeys[0] := strToVK(leftStr(theExecSQL, j-1));
s := rightStr(theExecSQL, length(theExecSQL)-j);
j := pos('^', s);
if j>0 then begin
inc(i);
ExecKeys[1] := strToVK(leftStr(s, j-1));
s := rightStr(s, length(s)-j);
ExecKeys[2] := strToVK(s);
end else ExecKeys[1] := strToVK(s);
end else begin
ExecKeys[0] := strToVK(theExecSQL);
end;
case i of
1: Key1(ExecKeys[0]);
2: Key2(ExecKeys[0], ExecKeys[1]);
3: Key3(ExecKeys[0], ExecKeys[1], ExecKeys[2]);
end;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure TfrmMediaPlayer.LoadConfiguration;
//读入配置文件信息内容
var i: byte;
begin with Conf do for i := 1 to ItemNo do begin
fmtStr(Items[i].ItemIndex, 'Item%s', [intToStr0(i, 2)]);
Items[i].Onn := ReadBool(Items[i].ItemIndex, 'On', false);
Items[i].Description := ReadString(Items[i].ItemIndex, 'Description','');
Items[i].Keywords:= ReadString(Items[i].ItemIndex, 'Keywords','');
Items[i].HotGun0 := ReadString(Items[i].ItemIndex, 'HotGun0', '');
Items[i].HotGun1 := ReadString(Items[i].ItemIndex, 'HotGun1', '');
Items[i].UU := ReadString(Items[i].ItemIndex, 'UU', '');
Items[i].DD := ReadString(Items[i].ItemIndex, 'DD', '');
Items[i].PP := ReadString(Items[i].ItemIndex, 'PP', '');
Items[i].BB := ReadString(Items[i].ItemIndex, 'BB', '');
Items[i].FF := ReadString(Items[i].ItemIndex, 'FF', '');
Items[i].Ctrl_HotGun0 := ReadString(Items[i].ItemIndex, 'Ctrl_HotGun0', '');
Items[i].Ctrl_HotGun1 := ReadString(Items[i].ItemIndex, 'Ctrl_HotGun1', '');
Items[i].Alt_PP := ReadString(Items[i].ItemIndex, 'Alt_PP', '');
Items[i].Alt_BB := ReadString(Items[i].ItemIndex, 'Alt_BB', '');
Items[i].Alt_FF := ReadString(Items[i].ItemIndex, 'Alt_FF', '');
Items[i].Ctrl_PP := ReadString(Items[i].ItemIndex, 'Ctrl_PP', '');
Items[i].Ctrl_BB := ReadString(Items[i].ItemIndex, 'Ctrl_BB', '');
Items[i].Ctrl_FF := ReadString(Items[i].ItemIndex, 'Ctrl_FF', '');
Items[i].Shift_PP := ReadString(Items[i].ItemIndex, 'Shift_PP', '');
Items[i].Shift_BB := ReadString(Items[i].ItemIndex, 'Shift_BB', '');
Items[i].Shift_FF := ReadString(Items[i].ItemIndex, 'Shift_FF', '');
end; end;
end.
//▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ LogzHook.dpr
{ 罗技无限灵貂Logz,驱动程序扩展补丁
V3.0
作者:Lgz
日期:2006年5月
捕捉灵貂‘向上浏览、向下浏览’键发出的消息
}
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
library LogzHook;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
uses
SysUtils,
Classes,
LogzHook_U in 'LogzHook_U.pas';
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
exports
EnableWheelHook, DisableWheelHook,
Key1, Key2, Key3, KeyStr, Down, Up,
StrToVK, VKToStr, LoadVisualKeys;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
begin
hkLogzWheel := 0;
hkQQChat := 0;
end.
//▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ LogzHook_U.pas
{ 主要利用WheelHookProc以及TitleHookProc处理捕捉到的灵貂‘向上、下浏览’键发出的
消息,并修改QQ聊天窗口的标题。
此外,放入一些主窗体程序用到的一些过程和函数。
}
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
unit LogzHook_U; interface
uses Windows, Messages, Classes, SysUtils, Dialogs, CommCtrl, MisCtrls_U;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
var hkLogzWheel, hkQQChat: HHOOK;//钩子的句柄值
hwLogzWheel, hwQQChat: HWnd ;
tlLogzWheel, tlQQChat: string;
dwnCtrl, dwnShift, dwnAlt: Boolean;//Down
clsName: string;
buf: array [0..1024] of char;
iC: byte;
zDelta: short;//上下浏览的速度
rc: TRect;//QQ聊天窗口的特征信息
wid, hei: integer;
VisualKeys: TStringList;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
const
csQQ = '#32770';//利用VC的Spy捕捉到的
csRoom= 'Afx:400000:b:0:';
csMSN = 'IMWindowClass';
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function WheelHookProc(Code: Integer; WParam, Msg: Longint): LRESULT; stdcall;
function TitleHookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
function EnumWindowsTitleFunc(Handle: THandle; lParam: LPARAM): boolean ; stdcall;
function EnableWheelHook : Boolean; stdcall; export;
function DisableWheelHook: Boolean; stdcall; export;
procedure Down(VK: byte);
procedure UP (VK: byte);
procedure Key1(VK1 : byte);
procedure Key2(VK1, VK2 : byte);
procedure Key3(VK1, VK2, VK3: byte);
procedure KeyStr(const theStr: string);
function TitleKeyword(theKeyword: string): Boolean;
function ClassKeyword(theKeyword: string): Boolean;
function TitleIS(theKeyword: string): Boolean;
function ClassIS(theKeyword: string): Boolean;
procedure GetForeWindowInfo;
procedure LoadVisualKeys;
function StrToVK(theKeyStr: string): byte;
function VKToStr(theVisKey: byte): string;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
implementation
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function EnumNtChildWndProc_JPEG(AhWnd: LongInt; AlParam: lParam): Boolean; StdCall;
//令影音传送带专门下载 .JPG
var WndClassName, WndCaption, pszText1, pszText2: array[0..254] of Char;
pszStr1: string;
i: integer;
begin
GetClassName (AhWnd, wndClassName, 254);
GetWindowText(AhWnd, WndCaption , 254);
//所有的链接,只选中JPG文件,其它的全勾掉
if (wndClassName='SysListView32') and (WndCaption='List1') then
for i := 0 to ListView_GetItemCount(AhWnd)-1 do begin
ListView_GetItemText(AhWnd, i, 1, pszText1, 100);
ListView_GetItemText(AhWnd, i, 2, pszText2, 100);
pszStr1 := lowerCase(string(pszText1));
//正常情况下
ListView_SetCheckState(AhWnd, i,
( ( (pszStr1='.jpg')or(pszStr1='.jpeg')or(pszStr1='.bmp') )
and ( pos('small', pszText2)=0 )
and ( pos('xinsiludcfs', pszText2)=0 )
and ( pos('bannerr02', pszText2)=0 )
and ( pos('www.beautyleg.com', pszText2)=0 )
)
or
( ( pos('http://www.beautyleg.com/', pszText2)>0 )
and ( pos('attachment', pszText2)>0 )
)
);
end;
//因为‘取消’是最后一个控件,这个时候再模拟点击‘确定’,否则先点‘确定’关闭对话框
//也许代码找不到下一个控件了
if (wndClassName='Button') and (pos('取消', WndCaption)>0) then
Key2(VK_Menu, ord('O'));
result:=true;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function WheelHookProc(Code: Integer; WParam, Msg:Longint): LRESULT; stdcall;
//处理无限灵貂上下浏览键的Wheel钩子
begin
zDelta := short(HiWord(PMsg(Msg)^.wParam));
if (Code=HC_ACTION) and (PMsg(Msg)^.Message=WM_MOUSEWHEEL) and (abs(zDelta)>200) then begin
GetForeWindowInfo;
if TitleKeyword('mplayerc')or TitleKeyword('Media Player Classic') then begin
inc(iC);
//按一次蓝色侧键产生两条消息,二合一处理的话相当于快进1次,即5秒,
//都处理的话相当于快进2次,即10秒
//if (iC mod 2)=0 then begin
Down(VK_Control);
if zDelta>200 then Key1(VK_Right) else Key1(VK_Left);
Up(VK_Control);//CTRL Up
//end;
PMsg(Msg)^.Message := 0;//因为侧键消息已经本地处理过了,不必再交给其它线程处理
end else if TitleIS('选择要下载的URL') then begin//影音传送带
enumChildWindows(hwLogzWheel, @EnumNtChildWndProc_JPEG, 0);
end
else Result := CallNextHookEx(hkLogzWheel, Code, WParam, Longint(@Msg));//如果不是MPC或者影音传送带,则向下传递
end else Result := CallNextHookEx(hkLogzWheel, Code, WParam, Longint(@Msg));//如果不是两个蓝色侧键则向下传递
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function TitleHookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
//处理QQ聊天对话框的Title钩子
begin
Result := 0;
if Code<0 then begin
Result := CallNextHookEx(hkQQChat, Code, wParam, lParam);
Exit;
end else if Code=HCBT_ACTIVATE then begin
hwQQChat := HWND(wParam);
GetClassName(hwQQChat, buf, 1024);
clsName := string(buf);
if clsName=csQQ then begin//QQ聊天对话框
GetWindowRect(hwQQChat, rc);
with rc do begin
wid := right -left;
hei := bottom-top ;
end;
//478,323 or 470,467
if (wid>400)and(hei>300) then begin
//inc(ic);
//if (ic mod 2)=0 then begin
EnumWindows(@EnumWindowsTitleFunc, hwQQChat);
//end;
end;
end else if (pos(csRoom, clsName)>0)or(clsName=csMSN) then begin//QQ聊天室orMSN
EnumWindows(@EnumWindowsTitleFunc, hwQQChat);
end;
end;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function EnumWindowsTitleFunc(Handle: THandle; lParam: LPARAM): boolean ; stdcall;
//伪装聊天窗口的标题栏
begin
Result := false;
if (Handle=lParam) and boolean(GetWindowText(Handle, buf, 256)) then begin
tlQQChat := string(buf);
//QQ
if ((pos('与', tlQQChat)>0) and (pos('聊天中', tlQQChat)>0)) then begin
tlQQChat := StringReplace(tlQQChat, '与' , '我的文档', []);
tlQQChat := StringReplace(tlQQChat, '聊天中', '' , []);
SetWindowText(Handle, pchar(tlQQChat));
Result := true;
exit;
end;
if ((pos('群 -', tlQQChat)>0) or (pos('高级群 -', tlQQChat)>0)) then begin
tlQQChat := StringReplace(tlQQChat, '群 -', '我的信件', []);
tlQQChat := StringReplace(tlQQChat, '高级' , '' , []);
SetWindowText(Handle, pchar(tlQQChat));
Result := true;
exit;
end;
//聊天室
if pos('QQ 聊天室', tlQQChat)>0 then begin
tlQQChat := 'Microsoft Visual C++ 6.2';
SetWindowText(Handle, pchar(tlQQChat));
Result := true;
exit;
end;
//MSN
if pos(' - 对话', tlQQChat)>0 then begin
tlQQChat := replacing(tlQQChat, ' - 对话' , '工作文档');
SetWindowText(Handle, pchar(tlQQChat));
Result := true;
exit;
end;
end;
Result := true;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function EnableWheelHook: Boolean; stdcall; export;
//加载钩子
begin
//罗技鼠标
if hkLogzWheel=0 then begin
hkLogzWheel := SetWindowsHookEx(WH_GETMESSAGE, @WheelHookProc, Hinstance, 0);
Result := True;
end else Result := False;
//QQ聊天对话框
if hkQQChat=0 then begin
hkQQChat := SetWindowsHookEx(WH_CBT, @TitleHookProc, Hinstance, 0);
Result := True;
end else Result := False;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function DisableWheelHook: Boolean; stdcall; export;
//卸载钩子
begin
//罗技鼠标
if hkLogzWheel<>0 then begin
UnHookWindowsHookEx(hkLogzWheel);
hkLogzWheel := 0;
Result := True;
end else Result := False;
//QQ聊天对话框
if hkQQChat<>0 then begin
UnHookWindowsHookEx(hkQQChat);
hkQQChat := 0;
Result := True;
end else Result := False;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
//模拟按键
procedure Down(VK: byte); begin keybd_event(VK, MapVirtualKey(VK, 0), 0, 0); end;
procedure UP (VK: byte); begin keybd_event(VK, MapVirtualKey(VK, 0), KEYEVENTF_KEYUp, 0); end;
procedure Key1(VK1: byte); begin
Down(VK1);
Up (VK1);
end;
procedure Key2(VK1, VK2: byte); begin
Down(VK1);
Down(VK2);
Up (VK2);
Up (VK1);
end;
procedure Key3(VK1, VK2, VK3: byte); begin
Down(VK1);
Down(VK2);
Down(VK3);
Up (VK3);
Up (VK2);
Up (VK1);
end;
procedure KeyStr(const theStr: string);
var i: byte;
begin
for i := 1 to length(theStr) do Key1(StrToVK(UpperCase('VK_'+theStr[i])));
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
procedure GetForeWindowInfo;
//得到顶层窗体(对话框)的信息
begin
hwLogzWheel := GetForegroundWindow;
GetWindowText(hwLogzWheel, buf, 1024); tlLogzWheel := string(buf);
GetClassName (hwLogzWheel, buf, 1024); clsName := string(buf);
dwnCtrl := GetKeyState(VK_Control)<0;
dwnShift:= GetKeyState(VK_Shift )<0;
dwnAlt := GetKeyState(VK_Menu )<0;
end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function TitleKeyword(theKeyword: string): Boolean;
begin Result := pos(theKeyword, tlLogzWheel)>0 end;
function ClassKeyword(theKeyword: string): Boolean;
begin Result := pos(theKeyword, clsName)>0 end;
function TitleIS(theKeyword: string): Boolean;
begin Result := theKeyword=tlLogzWheel; end;
function ClassIS(theKeyword: string): Boolean;
begin Result := theKeyword=clsName; end;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function StrToVK(theKeyStr: string): byte;
begin
if isEmpty(theKeyStr) then begin Result := 0; exit; end;
Result := VisualKeys.IndexOf(theKeyStr);
end;
function VKToStr(theVisKey: byte): string;
begin
Result := VisualKeys[theVisKey];
end;
procedure LoadVisualKeys;
procedure AddEmptyVK; overload;
begin
VisualKeys.Add('VK_CANCEL');
end;
procedure AddEmptyVK(a, b: byte); overload;
var i: byte;
begin
for i := a to b do VisualKeys.Add('VK_CANCEL');
end;
var i: byte;
begin
VisualKeys := TStringList.Create;
VisualKeys.Add('VK_CANCEL'); //0
VisualKeys.Add('VK_LBUTTON'); //1
VisualKeys.Add('VK_RBUTTON'); //2
VisualKeys.Add('VK_CANCEL'); //3
VisualKeys.Add('VK_MBUTTON'); //4
AddEmptyVK(5, 7); //=====
VisualKeys.Add('VK_BACK'); //8
VisualKeys.Add('VK_TAB'); //9
AddEmptyVK(10, 11); //=====
VisualKeys.Add('VK_CLEAR'); //12
VisualKeys.Add('VK_RETURN'); //13
AddEmptyVK(14, 15); //=====
VisualKeys.Add('VK_SHIFT'); //$10
VisualKeys.Add('VK_CONTROL'); //17
VisualKeys.Add('VK_MENU'); //18
VisualKeys.Add('VK_PAUSE'); //19
VisualKeys.Add('VK_CAPITAL'); //20
VisualKeys.Add('VK_KANA'); //21 or VK_HANGUL = 21 too
VisualKeys.Add('VK_HANGUL'); //21 or VK_HANGUL = 21 too
VisualKeys.Add('VK_JUNJA'); //23
VisualKeys.Add('VK_FINAL'); //24
VisualKeys.Add('VK_HANJA'); //25 or VK_KANJI = 25 too
VisualKeys.Add('VK_KANJI'); //25 or VK_KANJI = 25 too
VisualKeys.Add('VK_ESCAPE'); //27
VisualKeys.Add('VK_CONVERT'); //28
VisualKeys.Add('VK_NONCONVERT');//29
VisualKeys.Add('VK_ACCEPT'); //30
VisualKeys.Add('VK_MODECHANGE');//31
VisualKeys.Add('VK_SPACE'); //$20
VisualKeys.Add('VK_PRIOR'); //33
VisualKeys.Add('VK_NEXT'); //34
VisualKeys.Add('VK_END'); //35
VisualKeys.Add('VK_HOME'); //36
VisualKeys.Add('VK_LEFT'); //37
VisualKeys.Add('VK_UP'); //38
VisualKeys.Add('VK_RIGHT'); //39
VisualKeys.Add('VK_DOWN'); //40
VisualKeys.Add('VK_SELECT'); //41
VisualKeys.Add('VK_PRINT'); //42
VisualKeys.Add('VK_EXECUTE'); //43
VisualKeys.Add('VK_SNAPSHOT'); //44
VisualKeys.Add('VK_INSERT'); //45
VisualKeys.Add('VK_DELETE'); //46
VisualKeys.Add('VK_HELP'); //47
VisualKeys.Add('VK_0'); //$30
VisualKeys.Add('VK_1'); //$31
VisualKeys.Add('VK_2'); //$32
VisualKeys.Add('VK_3'); //$33
VisualKeys.Add('VK_4'); //$34
VisualKeys.Add('VK_5'); //$35
VisualKeys.Add('VK_6'); //$36
VisualKeys.Add('VK_7'); //$37
VisualKeys.Add('VK_8'); //$38
VisualKeys.Add('VK_9'); //$39
AddEmptyVK($3A,$40);//=====
VisualKeys.Add('VK_A'); //$41
VisualKeys.Add('VK_B'); //$42
VisualKeys.Add('VK_C'); //$43
VisualKeys.Add('VK_D'); //$44
VisualKeys.Add('VK_E'); //$45
VisualKeys.Add('VK_F'); //$46
VisualKeys.Add('VK_G'); //$47
VisualKeys.Add('VK_H'); //$48
VisualKeys.Add('VK_I'); //$49
VisualKeys.Add('VK_J'); //$4A
VisualKeys.Add('VK_K'); //$4B
VisualKeys.Add('VK_L'); //$4C
VisualKeys.Add('VK_M'); //$4D
VisualKeys.Add('VK_N'); //$4E
VisualKeys.Add('VK_O'); //$4F
VisualKeys.Add('VK_P'); //$50
VisualKeys.Add('VK_Q'); //$51
VisualKeys.Add('VK_R'); //$52
VisualKeys.Add('VK_S'); //$53
VisualKeys.Add('VK_T'); //$54
VisualKeys.Add('VK_U'); //$55
VisualKeys.Add('VK_V'); //$56
VisualKeys.Add('VK_W'); //$57
VisualKeys.Add('VK_X'); //$58
VisualKeys.Add('VK_Y'); //$59
VisualKeys.Add('VK_Z'); //$5A
VisualKeys.Add('VK_LWIN'); //91
VisualKeys.Add('VK_RWIN'); //92
VisualKeys.Add('VK_APPS'); //93
AddEmptyVK(94, 95); //=====
VisualKeys.Add('VK_NUMPAD0'); //96
VisualKeys.Add('VK_NUMPAD1'); //97
VisualKeys.Add('VK_NUMPAD2'); //98
VisualKeys.Add('VK_NUMPAD3'); //99
VisualKeys.Add('VK_NUMPAD4'); //100
VisualKeys.Add('VK_NUMPAD5'); //101
VisualKeys.Add('VK_NUMPAD6'); //102
VisualKeys.Add('VK_NUMPAD7'); //103
VisualKeys.Add('VK_NUMPAD8'); //104
VisualKeys.Add('VK_NUMPAD9'); //105
VisualKeys.Add('VK_MULTIPLY'); //106
VisualKeys.Add('VK_VisualKeys.Add'); //107
VisualKeys.Add('VK_SEPARATOR');//108
VisualKeys.Add('VK_SUBTRACT'); //109
VisualKeys.Add('VK_DECIMAL'); //110
VisualKeys.Add('VK_DIVIDE'); //111
VisualKeys.Add('VK_F1'); //112
VisualKeys.Add('VK_F2'); //113
VisualKeys.Add('VK_F3'); //114
VisualKeys.Add('VK_F4'); //115
VisualKeys.Add('VK_F5'); //116
VisualKeys.Add('VK_F6'); //117
VisualKeys.Add('VK_F7'); //118
VisualKeys.Add('VK_F8'); //119
VisualKeys.Add('VK_F9'); //120
VisualKeys.Add('VK_F10'); //121
VisualKeys.Add('VK_F11'); //122
VisualKeys.Add('VK_F12'); //123
VisualKeys.Add('VK_F13'); //124
VisualKeys.Add('VK_F14'); //125
VisualKeys.Add('VK_F15'); //126
VisualKeys.Add('VK_F16'); //127
VisualKeys.Add('VK_F17'); //128
VisualKeys.Add('VK_F18'); //129
VisualKeys.Add('VK_F19'); //130
VisualKeys.Add('VK_F20'); //131
VisualKeys.Add('VK_F21'); //132
VisualKeys.Add('VK_F22'); //133
VisualKeys.Add('VK_F23'); //134
VisualKeys.Add('VK_F24'); //135
AddEmptyVK(136,143);//=====
VisualKeys.Add('VK_NUMLOCK'); //144
VisualKeys.Add('VK_SCROLL'); //145
AddEmptyVK(146,159);//=====
VisualKeys.Add('VK_LSHIFT'); //160
VisualKeys.Add('VK_RSHIFT'); //161
VisualKeys.Add('VK_LCONTROL'); //162
VisualKeys.Add('VK_RCONTROL'); //163
VisualKeys.Add('VK_LMENU'); //164
VisualKeys.Add('VK_RMENU'); //165
AddEmptyVK(166,228);//=====
VisualKeys.Add('VK_PROCESSKEY');//229
AddEmptyVK(230,245);//=====
VisualKeys.Add('VK_ATTN'); //246
VisualKeys.Add('VK_CRSEL'); //247
VisualKeys.Add('VK_EXSEL'); //248
VisualKeys.Add('VK_EREOF'); //249
VisualKeys.Add('VK_PLAY'); //250
VisualKeys.Add('VK_ZOOM'); //251
VisualKeys.Add('VK_NONAME'); //252
VisualKeys.Add('VK_PA1'); //253
VisualKeys.Add('VK_OEM_CLEAR');//254
end;
end.