`
javasogo
  • 浏览: 1845299 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

钩子及其应用(三)

阅读更多

unit wdMacro;

{*******************************************

* brief: 日志钩子实现宏功能

* autor: linzhenqun

* date: <chsdate w:st="on" isrocdate="False" islunardate="False" day="11" month="9" year="2005">2005-9-11</chsdate>

* email: linzhengqun@163.com

* blog: http://blog.csdn.net/linzhengqun

********************************************}

interface

uses

Windows, Messages, Classes, SysUtils;

type

{回放可以调速度的哦!}

TPlaySpeed = (psFastest, psFaseter, psNormal, psSlower, psSlowest);

{录制和回放完毕的回调函数}

TSimpleProc = procedure;

{开始记录事件}

function StartRecord: Boolean;

{停止刻录事件}

function StopRecord: Boolean;

{开始回放事件}

function StartPlayBack(PlaySpeed: TPlaySpeed): Boolean;

{停止回放事件}

function StopPlayBack: Boolean;

{保存事件}

function SaveEventList(FileName: string): Boolean;

{打开事件列表}

function OpenEventList(FileName: string): Boolean;

{系统动作使得钩子停止}

procedure HookStopBySystem(Msg: LongWord);

var

RecordStop: TSimpleProc;

PlayStop: TSimpleProc;

implementation

uses

Math, XMLDoc, xmldom;

const

Max_EventNum = 1000000; //一百万个消息足矣

type

{管理事件结构指针,负责销毁它们}

TEventList = class(TList)

public

{覆盖该方法,释放指针的内存}

procedure Notify(Ptr: Pointer; Action: TListNotification); override;

end;

var

EventList: TEventList; //事件结构列表

HRecord: THandle; //记录钩子的句柄

HPlay: THandle; //回放钩子的句柄

Recording: Boolean; //标识是否正在记录

Playing: Boolean; //标识是否在回放

EventIndex: Integer; //当前回放的事件索引

IsReady: Boolean; //准备好拷贝了吗。

Speed: Integer; //回放速度,小于0表示正确速度

{ TEventList }

procedure TEventList.Notify(Ptr: Pointer; Action: TListNotification);

begin

inherited;

if (Action = lnDeleted) and (Ptr <> nil) then

Dispose(Ptr);

end;

{internal procedure}

function GetPlaySpeed(PlaySpeed: TPlaySpeed): Integer;

begin

case PlaySpeed of

psFastest: Result := 0;

psFaseter: Result := 5;

psNormal: Result := -1;

psSlower: Result := 50;

else Result := 80;

end;

end;

{ Hook proc }

function RecordProc(nCode: integer; wParam: WPARAM;

lParam: LPARAM): LRESULT; stdcall;

var

PEvent: PEventMsg;

begin

case nCode of

HC_ACTION:

begin

if EventList.Count >= Max_EventNum then

StopRecord

else begin

new(PEvent);

Move(PEventMsg(lParam)^, PEvent^, SizeOf(TEventMsg));

EventList.Add(PEvent);

end;

end;

end;

Result := CallNextHookEx(HRecord, nCode, wParam, lParam);

end;

function PlayBackProc(nCode: integer; wParam: WPARAM;

lParam: LPARAM): LRESULT; stdcall;

begin

Result := 0;

case nCode of

HC_SKIP:

begin

Inc(EventIndex);

if EventIndex >= EventList.Count then

begin

StopPlayBack;

IsReady := False;

end

else

IsReady := True;

end;

HC_GETNEXT:

begin

if IsReady then

begin

IsReady := False;

if Speed < 0 then

Result := PEventMsg(EventList.Items[EventIndex])^.time -

PEventMsg(EventList.Items[EventIndex - 1])^.time

else

Result:= Speed;

end

else

Result := 0;

PEventMsg(lParam)^ := TEventMsg(EventList.Items[EventIndex]^);

end;

else

Result := CallNextHookEx(HPlay, nCode, wParam, lParam);

end;

end;

{ save event to xml}

//将事件结构列表保存到XML文件中

function SaveEventListToXML(AEventList: TEventList; AXMLDoc: TXMLDocument): Boolean;

var

i: Integer;

RootNode, ParenNode: IDOMNode;

temStr: string;

{初始化XML文档}

procedure InitXMLDoc;

begin

AXMLDoc.XML.Text := '';

AXMLDoc.Active := True;

AXMLDoc.Encoding := 'utf-8';

end;

{在一个父结点下增加一个子结点}

function ApendNode(PNode: IDOMNode; tagName, Value: WideString): IDOMNode;

var

CNode: IDOMNode;

TextNode: IDOMText;

begin

with AXMLDoc.DOMDocument do

begin

CNode := createElement(tagName);

if Value <> '' then

begin

TextNode := createTextNode(Value);

CNode.appendChild(TextNode);

end;

Result := PNode.appendChild(CNode);

end;

end;

begin

Result := False;

if AEventList.Count = 0 then

Exit;

try

InitXMLDoc;

RootNode := AXMLDoc.DOMDocument.createElement('EventList');

AXMLDoc.DOMDocument.documentElement := IDOMElement(RootNode);

for i := 0 to AEventList.Count - 1 do

begin

ParenNode := ApendNode(RootNode, 'EventMsg', '');

temStr := IntToStr(TEventMsg(EventList.Items[i]^).message);

ApendNode(ParenNode, 'Message', temStr);

temStr := IntToStr(TEventMsg(EventList.Items[i]^).paramL);

ApendNode(ParenNode, 'ParamL', temStr);

temStr := IntToStr(TEventMsg(EventList.Items[i]^).paramH);

ApendNode(ParenNode, 'ParamH', temStr);

temStr := IntToStr(TEventMsg(EventList.Items[i]^).time);

ApendNode(ParenNode, 'Time', temStr);

temStr := IntToStr(TEventMsg(EventList.Items[i]^).hwnd);

ApendNode(ParenNode, 'Hwnd', temStr);

end;

Result := True;

except

//什么也不做

end;

end;

//XML文件中加载事件结构列表

function GetEventListFromXML(AEventList: TEventList; AXMLDoc: TXMLDocument): Boolean;

var

i: Integer;

PE: PEventMsg;

function GetNodeValue(ANode: IDOMNode): Integer;

begin

Result := StrToInt(ANode.firstChild.nodeValue);

end;

begin

Result := False;

try

with AXMLDoc.DOMDocument.documentElement do

for i := 0 to childNodes.length - 1 do

begin

new(PE);

PE^.message := GetNodeValue(childNodes[i].childNodes[0]);

PE^.paramL := GetNodeValue(childNodes[i].childNodes[1]);

PE^.paramH := GetNodeValue(childNodes[i].childNodes[2]);

PE^.time := GetNodeValue(childNodes[i].childNodes[3]);

PE^.hwnd := GetNodeValue(childNodes[i].childNodes[4]);

EventList.Add(PE);

end;

Result := True;

except

end;

end;

{ macro API }

function OpenEventList(FileName: string): Boolean;

var

XMLDoc: TXMLDocument;

begin

Result := False;

XMLDoc := TXMLDocument.Create(nil);

try

EventList.Clear;

XMLDoc.LoadFromFile(FileName);

if GetEventListFromXML(EventList, XMLDoc) then

Result := True;

finally

XMLDoc.Free;

end;

end;

function SaveEventList(FileName: string): Boolean;

var

XMLDoc: TXMLDocument;

begin

Result := False;

XMLDoc := TXMLDocument.Create(nil);

try

if SaveEventListToXML(EventList, XMLDoc) then

begin

XMLDoc.SaveToFile(FileName);

Result := True;

end;

finally

XMLDoc.Free;

end;

end;

function StartPlayBack(PlaySpeed: TPlaySpeed): Boolean;

begin

Result := False;

if Recording or Playing then

Exit;

if EventList.Count = 0 then

Exit;

EventIndex := 0;

Speed := GetPlaySpeed(PlaySpeed);

HPlay := SetWindowsHookEx(WH_JOURNALPLAYBACK, @PlayBackProc, HInstance, 0);

Result := HPlay <> 0;

Playing := Result;

end;

function StartRecord: Boolean;

begin

Result := False;

if Playing or Recording then

Exit;

EventList.Clear;

HRecord := SetWindowsHookEx(WH_JOURNALRECORD, @RecordProc, HInstance, 0);

Result := HRecord <> 0;

Recording := Result;

end;

function StopPlayBack: Boolean;

begin

Result := False;

if not Playing or Recording then

Exit;

Result := UnhookWindowsHookEx(HPlay);

if Result then

begin

if Assigned(PlayStop) then

PlayStop();

Playing := False;

end;

end;

function StopRecord: Boolean;

begin

Result := False;

if not Recording or Playing then

Exit;

Result := UnhookWindowsHookEx(HRecord);

if Result then

begin

Recording := False;

//通知外部,记录已经停止

if Assigned(RecordStop) then

RecordStop();

end;

end;

procedure HookStopBySystem(Msg: LongWord);

begin

if Msg = WM_CANCELJOURNAL then

begin

if Playing then

begin

Playing := False;

if Assigned(PlayStop) then

PlayStop();

end

else if Recording then

begin

Recording := False;

if Assigned(RecordStop) then

RecordStop();

end;

end;

end;

initialization

<spa

分享到:
评论

相关推荐

    钩子源码钩子源码

    以下是对钩子机制及其应用的详细解释: 一、钩子的基本概念: 钩子是Windows操作系统提供的一种机制,允许开发者注册函数来接收并处理特定的消息或事件。当特定的事件发生时,如键盘输入、窗口消息、系统事件等,...

    键盘钩子hook键盘钩子

    本地钩子仅在安装它的进程上下文中运行,只能捕获该进程及其子进程中的键盘事件。而全局钩子则更为强大,可以在整个系统范围内工作,监听所有进程中发生的键盘事件。 实现键盘钩子通常涉及以下步骤: 1. 定义钩子...

    Hook钩子\钩子程序.pdf

    下面将详细介绍几种常用的钩子类型及其应用场景: ##### 1. 键盘钩子与低级键盘钩子 **键盘钩子**(Keyboard Hook)用于监控所有键盘消息,包括按键按下与释放等事件。通过这种钩子,开发者可以实现对用户键盘输入...

    键盘钩子、鼠标钩子应用组件示例及 源码

    在IT领域,尤其是在Windows应用程序开发中,"键盘钩子"和"鼠标钩子"是用于监控和处理系统级输入事件的重要技术。这些技术通常涉及到低级别编程,特别是使用C#语言时,EventHook库提供了方便的接口来实现这一功能。本...

    hook_钩子程序-delphi

    总结起来,"hook_钩子程序-delphi"的主题涵盖了一个广泛的Delphi编程领域,涉及到Windows系统中的Hook技术及其在Delphi中的实现,这对于任何希望增强其应用程序功能或进行系统监控的开发者来说都是极其宝贵的资源。...

    完整版键盘钩子.rar

    在这个“完整版键盘钩子.rar”压缩包中,我们将会深入探讨键盘钩子的核心原理、实现方式及其在实际应用中的具体运用。 键盘钩子,简单来说,是一种操作系统级别的机制,允许程序拦截并处理键盘输入事件。这一技术...

    古老的钩子艺术-详细讲解钩子的教程

    本文重点介绍用户空间钩子的技术细节及其应用场景。 #### 三、用户空间钩子(User Space Hook) 用户空间钩子是在用户态下实现的一种Hook技术,主要用于拦截和修改应用程序的行为。这种技术通常不涉及对操作系统核心...

    VC++钩子函数

    ### 钩子函数在VC++中的应用 #### 一、引言 在软件开发过程中,特别是对于Windows应用程序而言,钩子(Hook)技术是一种非常有用的工具,...希望本文能够帮助初学者更好地理解和掌握钩子函数的基本原理及其应用场景。

    简单的钩子函数

    这种实践可以帮助理解钩子的工作原理及其在实际项目中的应用。 在文件"钩子函数"中,可能包含了创建和使用钩子函数的代码示例。通过阅读和分析这些代码,你可以更深入地了解如何在实际编程中设置和管理钩子,以及...

    一个 钩子程序DLL和用来调用的控制台

    【标题】:深入理解钩子程序DLL及其在控制台中的应用 在Windows操作系统中,钩子(Hook)是一种系统机制,允许程序员监控特定事件的发生,例如键盘输入、鼠标操作等。钩子程序通常是一个动态链接库(DLL),它包含...

    钩子资料整理,个人感觉不错

    2. **应用程序级钩子**:局部钩子,只对创建它的进程及其子进程有效。 3. **线程级钩子**:针对特定线程的钩子,只会在指定线程中被调用。 二、钩子工作原理 当一个事件发生时,如键盘输入、鼠标点击,Windows会...

    c#系统钩子(c#源码)

    系统钩子主要有三种类型: 1. **全局系统钩子**:这种钩子在整个系统范围内生效,可以捕获所有进程中发生的特定事件。 2. **本地系统钩子**:只对创建它的进程及其子进程有效。 3. **线程系统钩子**:针对特定线程的...

    用VC_c全局钩子.pdf

    #### 一、全局钩子的概念及其重要性 在Windows操作系统中,全局钩子是一种强大的工具,它允许开发者在系统范围内捕获和处理各种消息。这对于创建诸如自动演示程序、程序日志、辅助调试工具等特殊功能极为有用。此外...

    消息钩子代码实现

    本篇文章将深入探讨消息钩子的实现及其在拦截`WM_COMMAND`消息中的应用。 首先,我们需要理解什么是`WM_COMMAND`消息。`WM_COMMAND`是Windows消息的一种,它在用户与菜单、快捷键、控件交互时产生,传递控制ID和...

    全局键盘钩子获取扫描枪输入

    全局键盘钩子是Windows操作系统提供的一种机制,允许应用程序在系统层面捕获键盘事件,即使焦点不在该应用程序上。这种技术通常用于实现系统级...通过分析和学习这段代码,可以加深对全局键盘钩子及其实现细节的理解。

    系统钩子示例程序.rar

    全局钩子在所有当前运行于同一台计算机上的线程间共享,而本地钩子只对创建它的进程及其子进程有效。此外,还有WH_JOURNALPLAYBACK、WH_JOURNALRECORD、WH_KEYBOARD_LL、WH_MOUSE_LL等不同类型的钩子,它们分别针对...

    MFC --进程中的钩子

    本文将详细探讨MFC中的进程钩子及其使用方法。 首先,让我们理解什么是进程钩子。进程钩子是安装在特定进程中的,当该进程中发生特定事件时,钩子函数会被调用。这使得开发者可以在事件发生时进行干预,实现自定义...

    详解Vue3生命周期及其 Composition API 钩子应用与对比

    内容概要:本文介绍了 Vue3 的生命周期各个阶段以及各周期钩子的功能与调用时机,并详细讲解了这些生命周期的变化情况及与Vue2的区别,特别是对新增Composition API形式的生命周期做了细致解析和示例代码说明。...

    钩子函数中文版,翻译的很详细

    钩子函数在Windows编程中是一种强大的机制,它允许开发者插入自定义代码到系统或应用程序的特定事件处理流程中,以实现对特定事件的监控或控制。在中文环境中,理解钩子函数的概念和使用方法对于Windows应用程序开发...

    鼠标键盘钩子截获密码的代码

    ### 鼠标键盘钩子技术详解及其应用 #### 一、钩子技术概述 钩子(Hook)技术是Windows操作系统提供的一种高级编程接口,它允许开发者捕获、拦截或修改系统中的各种消息和事件。通过钩子技术,开发者可以实现一些...

Global site tag (gtag.js) - Google Analytics