关于钩子程序和屏幕取词的一些资料

关于钩子程序和屏幕取词的一些资料
关于钩子程序和屏幕取词的一些资料

关于钩子程序和屏幕取词的一些资料

屏幕抓词(或者叫动态翻译)是指随着鼠标的移动,软件能够随时获知屏幕上鼠标位置的单词或汉字,并翻译出来提示用户。它对於上网浏览、在线阅读外文文章等很有帮助作用,因此许多词典软件都提供了屏幕抓词功能。

屏幕抓词的关键是如何获得鼠标位置的字符串,Windows的动态链接和消息响应机制为之提供了实现途径。概括地说,主要通过下面的几个步骤来取得屏幕上鼠标位置的字符串:

符串:

. 代码拦截:Windows以DLL方式提供系统服务,可以方便地获取Windows字符输出API的地址,修改其入口代码,拦截应用程序对它们的调用。

. 鼠标HOOK:安装WH-MOUSEPROC类型的全局鼠标HOOK过程,监视鼠标在整个屏幕上的移动。

. 屏幕刷新:使鼠标周围一块区域无效,并强制鼠标位置的窗口刷新屏幕输出。窗口过程响应WM-NCPAINT和WM-PAINT消息,调用ExtTextOut/TextOut等字符输出API更新无效区域里面的字符串。这些调用被我们截获,从堆栈里取得窗口过程传给字符API的参数,如字符串地址、长度、输出坐标、HDC、裁剪区等信息。

2Windows 95/98的字符输出方法

Windows95/98不是一个纯32位的操作系统,它从16位操作系统发展而来,为了保持兼容,其内部仍然是32位和16位代码的混合体。系统通过gdi.exe 、user.exe和krnl386.exe提供16位API,供16位程序调用;通过gdi32.dll、user32.dll和kernel32.dll 提归结如下:

图1Windows 95/98的字符输出机制

. 16位程序通过16位gdi.exe的ExtTextOut/TextOut函数输出字符;

. 32位程序通过gdi32.dll的ExtTextOutA/TextOutA输出ANSI格式的字符,通过ExtTextOutW/TextOutW输出UNICODE格式的字符;

. 32位的ExtTextOutA/TextOutA转换到16位的ExtTextOut/TextOut,完成ANSI 格式字符的输出;

. 32位的ExtTextOutW/TextOutW转换到16位gdi.exe的两个未公开API,完成UNICODE格式字符的输出。为方便叙述,本文对这两个未公开API称为ExtTextOut16W 和TextOut16W。

t16W。

因此,只要拦截四个16位函数:TextOut、ExtTextOut、TextOut16W和ExtTextOut16W,就能截获32位和16位应用程序的所有字符串输出。

3拦截字符输出API

3.1代码拦截的基本思路

为了实现对ExtTextOut/TextOut等API的拦截,需要在函数入口放入一条动态生成的"JMP<替代函数>"指令,JMP 的操作数是我们提供的一个拦截替代函数的地址。当该API 被调用时,JMP指令首先执行,跳转到替代函数。替代函数负责从堆栈中获取参数,计算字符串坐标,分出鼠标位置的单词等工作。执行完成后,替代函数再调用原来的被拦截函数,完成正常的字符输出,然后返回。图2表明了应用程序对TextOut的正常调用流程和TextOut被拦截后的流程。

a)

①程序调用TextOut;

②从TextOut返回程序。

①程序调用TextOut(其入口已经被修改);

②转入拦截替代函数myTextOut;

③从myTextOut调用原来的TextOut;

④从TextOut返回myTextOut;

⑤从myTextOut返回程序。

图2对TextOut的正常调用流程

和TextOut被拦截后的流程

3.2提供拦截替代函数

拦截替代函数插入被拦截API的流程中执行,需要有相同的参数和返回值原型。以对拦截替代函数插入被拦截API的流程中执行,需要有相同的参数和返回值原型。以对TextOut 的拦截为例,下面是替代函数myTextOut的伪代码:

BOOL myTextOut(HDC hdc,int x,int y,LPSTR lpstr,int cbstr)

{

DoSpy(hDC,x ,y,lpstr,cbstr);

//保存参数,作抓词的所有工作

RestoreCode();//恢复TextOut入口原来的指令

TextOut(hDC,x,y,lpstr,cbstr);//调用原来的API

SpyCode();//再次放入JMP指令

return TRUE;

}

函数首先调用DoSpy()来作抓词的具体工作,然后RestoreCode()函数恢复被拦截函数入口的代码,再调用TextOut()执行正常的字符输出,接下来SpyCode()在被拦截函数入口再次放入JMP指令,最后返回调用进程。

3.3获取被拦截API的动态链接地址

TextOut和ExtTextOut的地址可以通过GetProcAddress取得,而TextOut16W和ExtTextOut16W既未公开于文档,也没有用字符串或序号从gdi.exe中引出,无法使用GetProcAddress取得它们的地址。下面讨论如何解决这个问题。

第一种方法:用softICE可以跟踪发现,ExtTextOut16W位于公开函数GetTextMetrics 入口的偏移20H处,TextOut16W位于GetTextMetrics的偏移7CH处。所以可以先取得GetTextMetrics的地址,再分别在加上20H和7CH,就是ExtTextOutW 和TextOutW的地址。

第二种方法:从指令里面析出地址。

第二种方法:从指令里面析出地址。

Windows 95/98维持一个DWORD类型的数组,称为32位-16位替换表,表中每个元素存

放了一个Win32 API对应的16位API的段:偏移地址。需要转入16位运行的Win32API 使用

不同的索引来从该表格里面取目的地址。ExtTextOutW和TextOutW分别使用索引B2H 和30

H,取表中相应元素作为ExtTextOut16W和TextOut16W的地址。取得这个数组的起始位置

,根据索引号即可找到16位函数的地址。由于这个数组是一个重定位项,在内存的地址

不固定,所以需要从指令流里面动态析出它的地址。

3.4动态生成JMP指令

动态生成的JMP指令占用5个字节,保存在一个数组里面。以生成跳转到TextOut 的替

代函数myTextOut的JMP指令为例:

BYTE ins[5]; //保存JMP指令

ins[0]= 0xea; //操作码:1 byte

*(WORD *)(ins+1) = FP-OFF(myTextOut);

//操作数:2byte的偏移

*(WORD *)(ins+3) = FP-SEG(myTextOut);

//操作数:2byte的段

3.5修改被拦截函数的入口

Windows运行在保护模式下,16位进程采用了段保护机制,代码段描述符的属性被标记为只读。如果直接向被拦截函数的入口写入JMP指令,会引起CPU保护错误,因此在修改代码前要采用下面的方法绕过段保护机制:

. 获取GDI代码段的基地址和界限;

. 用当前DS复制一个新的段选择子,该选择子的描述符具有可读写的属性;

. 将复制得到的选择子的基地址和界限设置为GDI代码段的基地址和界限;

. 将复制得到的选择子的基地址和界限设置为GDI代码段的基地址和界限;

. 用新的选择子作为段,同被拦截API的偏移组合成一个新的地址。

这样就获得了一个指向被拦截代码的可写指针。先保存5字节内容,再将数组ins[

]复制到该地址,即完成对TextOut等API的拦截修改。

4使用HOOK监视鼠标移动

安装一个WH-MOUSEPROC类型的全局HOOK可以监视鼠标在全屏幕的移动。每当有鼠标事件产生,HOOK过程被调用,它判断出鼠标移动了后,就向主窗口发送消息,通知主窗口鼠标位置发生了变化。

主窗口收到消息后,设置定时器,监视鼠标在某一位置停留时间的长短。如果鼠标停留超过设定的时间,才启动抓词功能,否则抓词功能保持禁止状态。这样可以减少代码拦截对系统性能的影响。

全局HOOK过程需要放入DLL里面。

5刷新屏幕输出

预先创建一个小的工具窗口,当鼠标停留在某个位置超过设定时间后,使工具窗口在鼠标位置上显示一下,然后隐含掉,这样就会在目标窗口--鼠标位置的窗口产生无效区域。然后调用UpdateWindow强制目标窗口刷新屏幕输出。在响应WM-PAINT /WM-N CPAINT中,目标窗口对字符输出API的调用将被我们截获和处理,完成一次抓词过程。6其它

本文所介绍的Windows 95/98环境下屏幕抓词的原理和取得鼠标位置字符串的实现方法。对于进一步的探索,笔者提出下面的几点看法:

. 只有通过响应WM-PAINT /WM-NCPAINT消息输出的字符串才会被捕捉

到;

. 有些软件(例如Internet Explorer)在刷新屏幕时,为了消除闪烁,不直接把字符串输出到屏幕DC,而是创建一个兼容的内存DC,先将字符串写到内存DC,再复制到效区域。然后调用UpdateWindow强制目标窗口刷新屏幕输出。在响应

WM-PAINT /WM-N屏幕上去。由于内存DC坐标和屏幕DC坐标的不同,不能直接依赖内存DC的坐标来计算字符串的屏幕位置;

. 本文讨论的方法不适用于Windows NT下的抓词。Windows NT的系统功能完全由32位代码提供,NT下的抓词需要拦截Win32 API。其实现机制同在Windows 95/98下也不一样。在NT里,KERNEL、USER、GDI模块位於进程的私有地址空间内,所以需要使用HOOK来将拦截替代函数动态映射到不同的被拦截进程的地址空间里面。而且由于控制台窗口禁止大多数HOOK,还需要创建远程线程来获取控制台窗口的字符输出。

=======================================屏幕上的文字大都是由gdi32.dll的以下几个函数显示的:TextOutA、TextOutW、ExtTextOutA、ExtTextOutW。实现屏幕抓词的关键就是截获对这些函数的调用,得到程序发给它们的参数。

我的方法有以下三个步骤:

一、得到鼠标的当前位置

通过SetWindowsHookEx实现。

二、向鼠标下的窗口发重画消息,让它调用系统函数重画

通过WindowFromPoint,ScreenToClient,InvalidateRect 实现。

三、截获对系统函数的调用,取得参数(以TextOutA为例)

1.仿照TextOutA作成自己的函数MyTextOutA,与TextOutA有相同参数和返回值,放在系统钩子所在的DLL里。

SysFunc1=(DWORD)GetProcAddress(GetModuleHandle("gdi32.dll"),"TextOutA");

BOOL WINAPI MyTextOutA(HDC hdc, int nXStart, int nYStart, L PCSTR lpszString,int cbString)

{ //输出lpszString的处理

return ((FARPROC)SysFunc1)(hdc,nXStart,nYStart,lpszString,cbString);}

2.由于系统鼠标钩子已经完成注入其它GUI进程的工作,我们不需要为注入再做工作。

如果你知道所有系统钩子的函数必须要在动态库里,就不会对"注入"感到奇怪。当进程隐式或显式调用一个动态库里的函数时,系统都要把这个动态库映射到这个进程的虚拟地址空间里(以下简称"地址空间")。这使得DLL成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈(见图1)。

图1 DLL映射到虚拟地址空间中

对系统钩子来说,系统自动将包含"钩子回调函数"的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程。

3.当包含钩子的DLL注入其它进程后,寻找映射到这个进程虚拟内存里的各个模块(EXE和DLL)的基地址。EXE和DLL被映射到虚拟内存空间的什么地方是由它们的基地址决定的。它们的基地址是在链接时由链接器决定的。当你新建一个Win32工程时,VC ++链接器使用缺省的基地址0x00400000。可以通过链接器的BASE选项改变模块的基地址。EXE通常被映射到虚拟内存的0x00400000处,DLL也随之有不同的基地址,通常被映射到不同进程的相同的虚拟地址空间处。

如何知道EXE和DLL被映射到哪里了呢?

在Win32中,HMODULE和HINSTANCE是相同的。它们就是相应模块被装入进程的虚拟内存空间的基地址。比如:

HMODULE hmodule=GetModuleHandle(〃gdi32.dll〃);

返回的模块句柄强制转换为指针后,就是gdi32.dll被装入的基地址。

关于如何找到虚拟内存空间映射了哪些DLL?我用如下方式实现:

while(VirtualQuery (base, &mbi, sizeof (mbi))〉0)

{ if(mbi.Type==MEM-IMAGE)

ChangeFuncEntry((DWORD)mbi.BaseAddress,1);

base=(DWORD)mbi.BaseAddress+mbi.RegionSize; }

4.得到模块的基地址后,根据PE文件的格式穷举这个模块的

IMAGE-IMPORT-DESCRIPTOR数组,看是否引入了gdi32.dll。如是,则穷举

IMAGE-THUNK-DATA数组,看是否引入了TextOutA函数。

5.如果找到,将其替换为相应的自己的函数。

系统将EXE和DLL原封不动映射到虚拟内存空间中,它们在内存中的结构与磁盘上的静态文件结构是一样的。即PE (Portable Executable) 文件格式。

所有对给定API函数的调用总是通过可执行文件的同一个地方转移。那就是一个模块(可以是EXE或DLL)的输入地址表(import address table)。那里有所有本模块调用的其它DLL的函数名及地址。对其它DLL的函数调用实际上只是跳转到输入地址表,由输入地址表再跳转到DLL真正的函数入口。例如:

图2 对MessageBox()的调用跳转到输入地址表,从输入地址表再跳转到MessageBox函数

IMAGE-IMPORT-DESCRIPTOR和IMAGE-THUNK-DATA分别对应于DLL和函数。它们是PE文件的输入地址表的格式(数据结构参见winnt.h)。

BOOL ChangeFuncEntry(HMODULE hmodule)

{ PIMAGE-DOS-HEADER pDOSHeader;

PIMAGE-NT-HEADERS pNTHeader;

PIMAGE-IMPORT-DESCRIPTOR pImportDesc;

/ get system functions and my functions′entry /

pSysFunc1=(DWORD)GetProcAddress(GetModuleHandle(〃gdi32.dll〃),〃TextOutA〃);

pMyFunc1= (DWORD)GetProcAddress(GetModuleHandle(〃hookdll.dll〃),〃MyTextOutA〃);

pDOSHeader=(PIMAGE-DOS-HEADER)hmodule;

if (IsBadReadPtr(hmodule, sizeof(PIMAGE-NT-HEADERS)))

return FALSE;

if (pDOSHeader-〉e-magic != IMAGE-DOS-SIGNATURE)

return FALSE;

pNTHeader=(PIMAGE-NT-HEADERS)((DWORD)pDOSHeader+(DWORD)pDOSH eader-〉e-lfanew);

if (pNTHeader-〉Signature != IMAGE-NT-SIGNATURE)

return FALSE;

pImportDesc = (PIMAGE-IMPORT-DESCRIPTOR)((DWORD)hmodule+(DWORD)pNTHeader-〉OptionalHeader.DataDirectory

[IMAGE-DIRECTORY-ENTRY-IMPORT].VirtualAddress);

if (pImportDesc == (PIMAGE-IMPORT-DESCRIPTOR)pNTHeader)

return FALSE;

while (pImportDesc-〉Name)

{ PIMAGE-THUNK-DATA pThunk;

strcpy(buffer,(char )((DWORD)hmodule+(DWORD)pImportDesc-〉Name)); CharLower(buffer);

if(strcmp(buffer,"gdi32.dll"))

{ pImportDesc++;

continue;

}else

{ pThunk=(PIMAGE-THUNK-DATA)((DWORD)hmodule+(DWORD)pImportDesc-〉FirstThunk);

while (pThunk-〉u1.Function)

{ if ((pThunk-〉u1.Function) == pSysFunc1)

{ VirtualProtect((LPVOID)(&pThunk-〉u1.Function),

sizeof(DWORD),PAGE-EXECUTE-READWRITE,&dwProtect);

(pThunk-〉u1.Function)=pMyFunc1;

VirtualProtect((LPVOID)(&pThunk-〉

u1.Function), sizeof(DWORD),dwProtect,&temp); }

pThunk++; } return 1;}}}

替换了输入地址表中TextOutA的入口为MyTextOutA后,截获系统函数调用的主要部分已经完成,当一个被注入进程调用TextOutA 时,其实调用的是MyTextOutA,只需在MyTextOutA中显示传进来的字符串,再交给TextOutA处理即可。

========================================

金山词霸抓词机理-- HOOK消息功能的使用

Win32全局钩子在VC5中的实现

Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子的种类很多,每种钩子可以截获并处理相应的消息,如键盘钩子可以截获键盘消息,外壳钩子可以截取、启动和关闭应用程序的消息等。本文在VC5编程环境下实现了一个简单的鼠标钩子程序,并对Win32全局钩子的运行机制、Win32 DLL的特点、VC5环境下的MFC DLL以及共享数据等相关知识进行了简单的阐述。

一.Win32全局钩子的运行机制

钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。对每种类型的钩子由系统来维护一个钩子链,最近安装的钩子放在链的开始,而最先安装的钩子放在最后,也就是后加入的先获得控制权。要实现Win32的系统钩子,必须调用SDK中的API函数SetWindowsHookEx来安装这个钩子函数,这个函数的原型是HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);,其中,第一个参数是钩子的类型;第二个参数是钩子函数的地址;第三个参数是包含钩子函数的模块句柄;第四个参数指定监视的线程。如果指定确定的线程,即为线程专用钩子;如果指定为空,即为全局钩子。其中,全局钩子函数必须包含在DLL(动态链接库)中,而线程专用钩子还可以包含在可执行文件中。得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx来传递它。钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。

二.Win32 DLL的特点

Win32 DLL与Win16 DLL有很大的区别,这主要是由操作系统的设计思想决定的。一方面,在Win16 DLL中程序入口点函数和出口点函数(LibMain和WEP)是分别实现的;而在Win32 DLL中却由同一函数DLLMain来实现。无论何时,当一个进程或线程载入和卸载DLL时,都要调用该函数,它的原型是BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved);,其中,第一个参数表示DLL的实例句柄;第三个参数系统保留;这里主要介绍一下第二个参数,它有四个可能的值:

DLL_PROCESS_ATTACH(进程载入),DLL_THREAD_ATTACH(线程载入),DLL_THREAD_DETACH (线程卸载),DLL_PROCESS_DETACH(进程卸载),在DLLMain函数中可以对传递进来的这个参数的值进行判别,并根据不同的参数值对DLL进行必要的初始化或清理工作。举个例子来说,当有一个进程载入一个DLL时,系统分派给DLL的第二个参数为DLL_PROCESS_ATTACH,这时,你可以根据这个参数初始化特定的数据。另一方面,在Win16环境下,所有应用程序都在同一地址空间;而在Win32环境下,所有应用程序都有自己的私有空间,每个进程的空间都是相互独立的,这减少了应用程序间的相互影响,但同时也增加了编程的难度。大家知道,在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同的;而在Win32环境中,情况却发生了变化,当进程在载入DLL时,系统自动把DLL地址映射到该进程的私有空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间,也就是说每个进程所拥有的相同的DLL的全局数据其值却并不一定是相同的。因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。亦即把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的属性设置为共享。

三.VC5中MFC DLL的分类及特点

在VC5中有三种形式的MFC DLL(在该DLL中可以使用和继承已有的MFC类)可供选择,即Regular statically linked to MFC DLL(标准静态链接MFC DLL)和Regular using the shared MFC DLL(标准动态链接MFC DLL)以及Extension MFC DLL(扩展MFC DLL)。第一种DLL的特点是,在编译时把使用

的MFC代码加入到DLL中,因此,在使用该程序时不需要其他MFC动态链接类库的存在,但占用磁盘空间比较大;第二种DLL的特点是,在运行时,动态链接到MFC类库,因此减少了空间的占用,但是在运行时却依赖于MFC动态链接类库;这两种DLL既可以被MFC程序使用也可以被Win32程序使用。第三种DLL的特点类似于第二种,做为MFC类库的扩展,只能被MFC程序使用。

四.在VC5中全局共享数据的实现

在主文件中,用#pragma data_seg建立一个新的数据段并定义共享数据,其具体格式为:

#pragma data_seg ("shareddata")

HWND sharedwnd=NULL;//共享数据

#pragma data_seg()

仅定义一个数据段还不能达到共享数据的目的,还要告诉编译器该段的属性,有两种方法可以实现该目的(其效果是相同的),一种方法是在.DEF文件中加入如下语句:

SETCTIONS

shareddata READ WRITE SHARED

另一种方法是在项目设置链接选项中加入如下语句:

/SECTION:shareddata,rws

五.具体实现步骤

由于全局钩子函数必须包含在动态链接库中,所以本例由两个程序体来实现。

1.建立钩子Mousehook.DLL

(1)选择MFC AppWizard(DLL)创建项目Mousehook;

(2)选择MFC Extension DLL(共享MFC拷贝)类型;

(3)由于VC5没有现成的钩子类,所以要在项目目录中创建Mousehook.h文件,在其中建立钩子类:

class AFX_EXT_CLASS Cmousehook:public CObject

{

public:

Cmousehook();

//钩子类的构造函数

~Cmousehook();

//钩子类的析构函数

BOOL starthook(HWND hWnd);

//安装钩子函数

BOOL stophook();

卸载钩子函数

};

(4)在Mousehook.app文件的顶部加入#include"Mousehook.h"语句;

(5)加入全局共享数据变量:

#pragma data_seg("mydata")

HWND glhPrevTarWnd=NULL;

//上次鼠标所指的窗口句柄

HWND glhDisplayWnd=NULL;

//显示目标窗口标题编辑框的句柄

HHOOK glhHook=NULL;

//安装的鼠标勾子句柄

HINSTANCE glhInstance=NULL;

//DLL实例句柄

#pragma data_seg()

(6)在DEF文件中定义段属性:

SECTIONS

mydata READ WRITE SHARED

(7)在主文件Mousehook.cpp的DllMain函数中加入保存DLL实例句柄的语句:DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {

//如果使用lpReserved参数则删除下面这行

UNREFERENCED_PARAMETER(lpReserved);

if (dwReason == DLL_PROCESS_ATTACH)

{

TRACE0("MOUSEHOOK.DLL Initializing!/n");

//扩展DLL仅初始化一次

if (!AfxInitExtensionModule(MousehookDLL, hInstance))

return 0;

new CDynLinkLibrary(MousehookDLL);

//把DLL加入动态MFC类库中

glhInstance=hInstance;

//插入保存DLL实例句柄

}

else if (dwReason == DLL_PROCESS_DETACH)

{

TRACE0("MOUSEHOOK.DLL Terminating!/n");

//终止这个链接库前调用它

AfxTermExtensionModule(MousehookDLL);

}

return 1;

}

(8)类Cmousehook的成员函数的具体实现:

Cmousehook::Cmousehook()

//类构造函数

{

}

Cmousehook::~Cmousehook()

//类析构函数

{

stophook();

}

BOOL Cmousehook::starthook(HWND hWnd)

//安装钩子并设定接收显示窗口句柄

{

BOOL bResult=FALSE;

glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0); if(glhHook!=NULL)

bResult=TRUE;

glhDisplayWnd=hWnd;

//设置显示目标窗口标题编辑框的句柄

return bResult;

}

BOOL Cmousehook::stophook()

//卸载钩子

{

BOOL bResult=FALSE;

if(glhHook)

{

bResult= UnhookWindowsHookEx(glhHook); if(bResult)

{

glhPrevTarWnd=NULL;

glhDisplayWnd=NULL;//清变量

glhHook=NULL;

}

}

return bResult;

}

(9)钩子函数的实现:

LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)

{

LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam; if (nCode>=0)

{

HWND glhTargetWnd=pMouseHook->hwnd;

//取目标窗口句柄

HWND ParentWnd=glhTargetWnd;

while (ParentWnd !=NULL)

{

glhTargetWnd=ParentWnd;

ParentWnd=GetParent(glhTargetWnd);

//取应用程序主窗口句柄

}

if(glhTargetWnd!=glhPrevTarWnd)

{

char szCaption[100];

GetWindowText(glhTargetWnd,szCaption,100);

//取目标窗口标题

if(IsWindow(glhDisplayWnd))

SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption); glhPrevTarWnd=glhTargetWnd;

//保存目标窗口

}

}

return CallNextHookEx(glhHook,nCode,wparam,lparam);

//继续传递消息

}

(10)编译项目生成mousehook.dll。

2.创建钩子可执行程序

(1)用MFC的AppWizard(EXE)创建项目Mouse;

(2)选择“基于对话应用”并按下“完成”键;

(3)编辑对话框,删除其中原有的两个按钮,加入静态文本框和编辑框,用鼠标右键点击静态文本框,在弹出的菜单中选择“属性”,设置其标题为“鼠标所在的窗口标题”;

(4)在Mouse.h中加入对Mousehook.h的包含语句#Include"../Mousehook/Mousehook.h";

(5)在CMouseDlg.h的CMouseDlg类定义中添加私有数据成员:

CMouseHook m_hook;//加入钩子类作为数据成员

(6)修改CmouseDlg::OnInitDialog()函数:

BOOL CMouseDlg::OnInitDialog()

{

CDialog::OnInitDialog();

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

SetIcon(m_hIcon, TRUE);//Set big icon

SetIcon(m_hIcon, FALSE);//Set small icon

//TODO: Add extra initialization here

CWnd * pwnd=GetDlgItem(IDC_EDIT1);

//取得编辑框的类指针

m_hook.starthook(pwnd->GetSafeHwnd());

//取得编辑框的窗口句柄并安装钩子

return TRUE;

//return TRUE unless you set the focus to a control

}

(7)链接DLL库,即把../Mousehook/debug/Mousehook.lib加入到项目设置链接标签中;

(8)编译项目生成可执行文件;

(9)把Mousehook.DLL拷贝到../mouse/debug目录中;

(10)先运行几个可执行程序,然后运行Mouse.exe程序,把鼠标在不同窗口中移动,在Mouse.exe 程序窗口中的编辑框内将显示出鼠标所在的应用程序主窗口的标题。

==========================================

消息钩子函数入门篇

消息钩子函数入门篇

Windows 系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子可以监视系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理。这样,我们就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。可见,利用钩子可以实现许多特殊而有用的功能。因此,对于高级编程人员来说,掌握钩子的编程方法是很有必要的。

钩子的类型

一.按事件分类,有如下的几种常用类型

(1)键盘钩子和低级键盘钩子可以监视各种键盘消息。

(2)鼠标钩子和低级鼠标钩子可以监视各种鼠标消息。

(3)外壳钩子可以监视各种Shell事件消息。比如启动和关闭应用程序。

(4)日志钩子可以记录从系统消息队列中取出的各种事件消息。

(5)窗口过程钩子监视所有从系统消息队列发往目标窗口的消息。

此外,还有一些特定事件的钩子提供给我们使用,不一一列举。

下面描述常用的Hook类型:

1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPRO

c#钩子实例

C#键盘勾子(Hook)拦截器,屏蔽键盘活动 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。 运行机制 1、钩子链表和钩子子程: 每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程序定义的,被Hook 子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Ho ok类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。

Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Ho ok链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。 钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。 钩子子程必须按照以下的语法: LRESULT CALLBACK HookProc ( int nCode, WPARAM wParam, LPARAM lParam ); HookProc是应用程序定义的名字。 nCode参数是Hook代码,Hook子程使用这个参数来确定任务。这个参数的值依赖于Hook类型,每一种Hook都有自己的Hook代码特征字符集。

VB-条件语句-循环语句练习题

VB条件语句和循环语句 测试习题(满分100分) 班级姓名 一、根据程序写运行结果 1.写出下列程序的运行结果。(5分) Private sub command1_click X=VAL(text1.text) IF X<0 THEN Y=ABS(X) ELSE Y= -X END IF PRINT "Y=";Y End sub 运行结果: (1)在text1中输入99 输出 (2)在text1中输入-23 输出 2. 写出下列程序的运行结果。(5分) Private sub command1_click N=1 FOR X=3 TO 10 STEP 3 N=N*2 NEXT X PRINT "N=";N End sub 运行结果: 3.写出下列程序的运行结果。(5分) Private sub command1_click S=0 FOR X=10 TO 1 STEP 4 S=S+X NEXT X PRINT " S=";S End sub(5分) 运行结果: 4.写出下列程序运行结果。 (5分) Private sub command1_click FOR I= 1 TO 5 step 2 PRINT I, NEXT I End sub 运行结果: 5. 写出下列程序的运行结果。(5分) Private sub command1_click X=VAL(text1.text) IF X/2=Int(X/2) THEN S=X+1 ELSE S=X-1 END IF PRINT "S=";S End sub 若在text1中输入以下数字,运行结果: (1)99 (2)98 二、根据题意,完善下列程序。(每空5分) 1.请设计一个程序,将从键盘上任意输入的两个数中最大的那个选出来。 Private sub command1_click A=VAL(text1.text) B=VAL(text2.text) IF A>B THEN MAX=________ ELSE MAX= ENDIF PRINT "MAX=";MAX End sub 2.求和S=1+3+5+7+…+99 Private sub command1_click S=0 FOR I=1 TO 99 STEP S=________ NEXT I PRINT “S=”;S End sub 3.完善下列程序,使其能求出 2+4+6+……+100之和。 Private sub command1_click FOR I =____ TO 100 STEP _____ S= S+I ______ I PRINT S End sub

C语言for循环语句教学设计

C语言for循环语句教学设计 摘要:for循环语句是C语言三种循环语句中使用频率最高,最为灵活的一种循环。掌握for循环语句对学生编程技能的提高具有重要意义。本文从教学背景、微课件特色、教学目标,教学内容等方面着眼,对C语言之for循环语句,进行教学设计。希望学生能够较好的掌握for循环语句的相关知识,在实际应用中游刃有余。 关键词:程序设计基础;for语句;循环 循环结构是C程序的三大结构之一,是程序设计的基础。其循环包括whie 循环、dowhile循环和for循环,三种循环之间可以互相转换。其中for循环语句使用最为灵活,不仅可以用于循环次数可以确定的情况,而且可以用于循环次数不确定,只给出循环结束条件的情况,它完全可以代替while语句。学生只有熟练掌握了循环语句的语句格式,理解循环执行过程,才能在实际应用中游刃有余。 1教学背景 循环结构是C程序的三大结构之一,是程序设计的基础。C语言提供了三种循环控制语句(不考虑goto/if构成的循环),构成了三种基本的循环结构。(1)while语句构成的循环结构(“当型循环”)(2)do-while语句构成的循环结构(“直到型循环”)(3)for语句构成的循环结构(“当型循环”)我们本次教学是学生在学习了while语句构成的循环结构(“当型循环”)和do-while语句构成的循环结构(“直到型循环”)之后进行开展的。并在课前做了相关的微课视频,让学生提前预习。 2微课件特色 (1)视频中采用循环导航按钮,改变了以往视频从头放到尾的翻页模式。在微课视频使用过程中,可以跳跃访问到任何一个节点,查看需要学习的内容。(2)课件基于工作过程为导向的设计理念,以任务为载体,以课程技能要求为目标,以实施过程为核心。在实施过程中,考虑到学生个体差异,又进行分层教学,既提供了高基础高水平的实施项目的思路、方法,又提供了零基础学生实施项目的思路、方法和步骤操作。所以该课件既适合任课老师上课教学使用,也适

鼠标键盘钩子截获密码

利用鼠标键盘钩子截获密码。 源码示例:https://www.360docs.net/doc/af5454046.html,/soft/GetPass_Src.rar 钩子能截获系统并得理发送给其它应用程序的消息,能完成一般程序无法完成的功能。掌握钩子的编程方法是很有必要的 钩子分类: 1、WH_CALLWNDPROC和WH_CALLWNDPROCRET:使你可以监视发送到窗口过程的消息 3、WH_DEBUG 调试钩子 4、WH_FOREGROUNDIDLE 当当应用程序的前台线程大概要变成空闲状态时,系统就会调用 WH_FOREGROUNDIDL 5、WH_JOURNALRECORD 监视和记录输入事件 6、WH_JOURNALPLAYBACK 回放用WH_JOURNALRECORD记录事件 7、WH_KEYBOARD 键盘钩子 9、WH_KEYBOARD_LL 低层键盘钩子 10、WH_MOUSE 鼠标钩子 11、WH_MOUSE_LL 底层鼠标钩子 12、WH_SHELL 外壳钩子 13、WH_MSGFILTER 和WH_SYSMSGFILTER 使我们可以监视菜单,滚动条,消息框等 安装钩子: 调用函数SetWindowsHookEx安装钩子。其函数原型为: HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId ) idHook表示钩子类型,它是和钩子函数类型一一对应的。如,

WH_KEYBOARD,WH_MOUSE。 Lpfn是钩子函数的地址。 HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。(系统钩子必须在DLL中) dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。 SetWindowsHookEx返回所安装的钩子句柄。 卸载钩子 调用函数BOOL UnhookWindowsHookEx( HHOOK hhk)卸载钩子 定义钩子函数 钩子函数是一种特殊的回调函数。钩子监视的特定事件发生后,系统会调用钩子函数进行处理。一般为下: LRESULT WINAPI MyHookProc(int nCode ,WPARAM wParam,LPARAM lParam) 参数wParam和lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode 包含有关消息本身的信,比如是否从消息队列中移出。 实例: 下面我们通过安装鼠标钩子。和键盘钩子还截获输入的密码,并可查看*密码为例,来说明何何使用钩子。 1,进入向导,新建MFC AppWizard(dll) 取名为GetPass,选择MFC Extension DLL,完成。 2,新建一个CGetPassHook 类,基类:CObject,并加入StartHook,StopHook,函数,如下:class AFX_EXT_CLASS CGetPassHook : public CObject { public: BOOL StopHook();

编写钩子程序实例

编写钩子程序的步骤分为三步:定义钩子函数、安装钩子和卸载钩子。 1.定义钩子函数 钩子函数是一种特殊的回调函数。钩子监视的特定事件发生后,系统会调用钩子函数进行处理。不同事件的钩子函数的形式是各不相同的。下面以鼠标钩子函数举例说明钩子函数的原型: LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam) 参数wParam和lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信息,比如是否从消息队列中移出。 我们先在钩子函数中实现自定义的功能,然后调用函数CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。CallNextHookEx.的原型如下: LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam ) 参数hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。 当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。 2.安装钩子 在程序初始化的时候,调用函数SetWindowsHookEx安装钩子。其函数原型为:HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId ) 参数idHook表示钩子类型,它是和钩子函数类型一一对应的。比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。 Lpfn是钩子函数的地址。 HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。 dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。 SetWindowsHookEx返回所安装的钩子句柄。 3.卸载钩子 当不再使用钩子时,必须及时卸载。简单地调用函数BOOL UnhookWindowsHookEx( HHOOK hhk)即可。 值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。线程钩子一般在当前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。 线程钩子的编程实例: 按照上面介绍的方法实现一个线程级的鼠标钩子。钩子跟踪当前窗口鼠标移动的位置变化信息。并输出到窗口。 (1)在VC++6.0中利用MFC APPWizard(EXE)生成一个不使用文档/视结构的单文档应用mousehook。打开childview.cpp 文件,加入全局变量: HHOOK hHook;//鼠标钩子句柄 CPoint point;//鼠标位置信息 CChildView *pV iew; // 鼠标钩子函数用到的输出窗口指针 在CChildView::OnPaint()添加如下代码: CPaintDC dc(this);

条件语句、循环语句

1.2.2-1.2.3条件语句和循环语句(第二、三课时) 教学目标: 知识与技能 (1)正确理解条件语句和循环语句的概念,并掌握其结构的区别与联系。 (2)会应用条件语句和循环语句编写程序。 过程与方法 经历对现实生活情境的探究,认识到应用计算机解决数学问题方便简捷,促进发展学生逻辑思维能力 情感态度与价值观 了解条件语句在程序中起判断转折作用,在解决实际问题中起决定作用。深刻体会到循环语句在解决大量重复问题中起重要作用。减少大量繁琐的计算。通过本小节内容的学习,有益于我们养成严谨的数学思维以及正确处理问题的能力。 重点与难点 重点:条件语句和循环语句的步骤、结构及功能。 难点:会编写程序中的条件语句和循环语句。 学法与教学用具 计算机、图形计算器 教学设想 【创设情境】 试求自然数1+2+3+……+99+100的和。

显然大家都能准确地口算出它的答案:5050。而能不能将这项计算工作交给计算机来完成呢?而要编程,以我们前面所学的输入、输出语句和赋值语句还不能满足“我们日益增长的物质需要”,因此,还需要进一步学习基本算法语句中的另外两种:条件语句和循环语句。 【探究新知】 (一)条件语句 算法中的条件结构是由条件语句来表达的,是处理条件分支逻辑结构的算法语句。它的一般格式是:(IF -THEN -ELSE 格式) 当计算机执行上述语句时,首先对IF 后的条件进行判断,如果条件符合,就执行THEN 后的语句1,否则执行ELSE 后的

语句2。其对应的程序框图为:(如上右图) 在某些情况下,也可以只使用IF -THEN 语句:(即 IF -THEN 格式) 计算机执行这种形式的条件语句时,也是首先对IF 后的条件进行判断,如果条件符合,就执行THEN 后的语句,如果条件不符合,则直接结束该条件语句,转而执行其他语句。其对应的程序框图为:(如上右图) 条件语句的作用:在程序执行过程中,根据判断是否满足约定的条件而决定是否需要转换到何处去。需要计算机按条件进行分析、比较、判断,并按判断后的不同情况进行不同的处理。 【例题精析】 〖例1〗:编写程序,输入一元二次方程20ax bx c ++=的系数,输 IF 条件 THEN 语句 END IF

C语言for循环语句教案

for循环结构程序设计教案 课程名称:C语言程序设计 本课内容:循环结构程序设计——for 语句 一、教学目标 1、领会程序设计中构成循环的方法 2 、掌握for 语句的用法 二、教学重点 1、for 语句的一般格式 2、for语句的执行过程 三、教学难点 for 语句的综合利用 四、教学方法 1、课堂讲授,给出主要内容。 2、讲解其基本格式。 3、应用示例,结合相应的知识讲解。 4、执行过程用流程图和例题用(演示法和讲解法)进行详细说明。 五、教学过程 (一)导入 1、复习前两节课我们学习的两种循环语句——while语句和do~while 语句的基本格式和执行过程和特征。 2、给出例子如下:

main( ) {int x=1; (表达式1) s=0; while(x<=100) (表达式2) {s=s+x; x=x+1; (表达式3) } printf(“%d”,s); } 分析用while语句来完成的程序,主要完成1到100的累加和,对一个循环程序来说最关键的三个部分:循环变量的赋初值、控制循环条件、循环控制变量的更新。 (二)教学过程 1、写出本节课要介绍的for语句的一般格式 for(表达式1;表达式2;表达式3) 循环体; 2、掌握:基本格式和各个表达式的功能和特征 强调:for语句中的所有表达式和while语句中的表达式所完成的功能是相同的。 表达式1:循环变量的初始化(初始值) 表达式2:循环条件(终止值) 表达式3:循环变量自增 3、for语句的执行过程 for ( int i = 0 ; i < 10 ; i++) { printf("我最棒"); }

VB 钩子详解

Windows钩子函数的概念和实现方法 首先我们必须大致了解Windows的基本运作机理,Windows作为一个多任务操作系统,它是分有层次概念的,运行在最底下的称为Ring 0层,在这一层里基本上都是一些硬件驱动程序和Windows的总内核,一般的应用程序极少极少运行在这层,当然也有例外,例如调试软件SoftICE(不过基本上这个软件的作用是Crack软件而不是调试)、还原精灵还有分区魔法大师,就是运行在Ring 0层的,另外就是著名的CIH病毒。运行在Ring 0级的程序能够对所有硬件进行直接地址级访问,所受到的限制也最小。 消息(Message)传递是Windows独有的一种机制,因为Windows规定运行在Ring 0以上的程序是没有权利知道究竟硬件发生了怎样的中断变化的,Windows统一将这些中断变化封装成一系列的消息(黑箱作业,也就是常说的Black Box),比如鼠标移动,系统产生一个OnMouseMove消息(但这条消息从何而来,相关的硬件中断向量是什么,程序无从得知),OnMouseMove这条消息最后送达每一个窗口程序以供处理。在更高层次的地方,比如说控件级,所有的消息还被封装成一系列“事件”,比如TextBox控件有KeyPress事件,实际上,这些事件都是林林种种的消息映射。事件的概念使得程序员能够更加傻瓜化地进行编程,但是从另一个角度来说,这种黑箱作业也使得程序员过分依赖系统的安排,限制了程序员的思维,举个例子,Windows为按钮控件封装了大部分常用的属性和事件,完成一般的常规妈作是没有问题的,但是很遗憾,或许是Windows的疏忽,按钮控件的字体颜色永远默认是黑色,而且Windows没有为此提供一个专门的接口来修改,碰到这种情况,程序员就会非常头疼。 钩子函数(Hook Function),就像一把钩子,它的作用是将消息在抵达窗口程序之前先钩到一个地方以便程序员进行分析,这个地方称为挂接函数链,消息在这里先被一系列的函数处理然后由程序员决定是否交还给Windows系统,在这里,你可以“吞噬”(Lickup)一些你不希望发生的消息,比如说你吞掉所有的键盘消息而不交还给系统,那么键盘将会失灵。当然,经过了这道周折,系统效率将会有极其微小的降低,但是,由于Windows规定所有不运行在Ring 0层的程序都不能直接访问硬件中断,因此作为一种中断驱动程序的补充,钩子函数在很多场合下是非常有用的,有时候甚至是唯一的方法。 下面就以键盘拦截为例讲述钩子函数的使用方法: 首先定义以下API: Public Declare Function SetWindowsHookEx Lib "user32" _ Alias "SetWindowsHookExA" (ByVal idHook As Long, _ ByVal lpfn As Long, _ ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long SetWindowsHookEx,这个函数是一切钩子函数的根本,其作用是通知Windows进行钩子妈作并定义钩子函数。 参数1,idHook为定义需要进行的拦截类型,是键盘拦截?鼠标拦截?还是别的。如 WH_KEYBOARD捕捉键盘消息,而WH_MOUSE捕捉鼠标消息。

6、条件语句和循环语句

6、条件语句和循环语句 学习目标 1.正确理解条件语句和循环语句的概念,并掌握其结构的区别与联系。 2.会应用条件语句和循环语句编写程序。 3.培养学生形成严谨的数学思维以及正确处理问题的能力。 学习过程 一、课前准备 复习:回顾三种基本算法语句。 引入:顺序结构的框图可以用输入语句,输出语句,赋值语句来表示,条件结构、循环结构的语句要转化成计算机理解的语言,我们必须学习条件语句、循环语句. 二、新课导学 探究:条件语句和循环语句 (一)条件语句 条件语句的一般格式是: . 当计算机执行上述语句时,首先对IF 后的条件进行判断,如果条件符合,就执行THEN 后的语句1,否则执行ELSE 后的语句2。 在某些情况下,也可以只使用 IF-THEN 语句:(即 ) 计算机执行这种形式的条件语句时,也是首先对IF 后的条件进行判断,如果条件符合,就执行THEN 后的语句,如果条件不符合,则直接结束该条件语句,转而执行其他语句。 (二)循环语句 满足条件? 语句1 语句2 是 否 IF 条件 THEN 语句1 ELSE 语句2 END IF IF 条件 THEN 语句 END IF

算法中的循环结构是由循环语句来实现的。对应于程序框图中的两种循环结构,一般程序设计语言中也有 和 两种语句结构。即WHILE 语句和UNTIL 语句。 (1)WHILE 语句的一般格式是: (2)UNTIL 语句的一般格式是: 思考:你觉得WHILE 型语句与UNTIL 型语句之间有什么区别呢? 三、典型例题 例1 编写程序,输入一元二次方程2 0ax bx c ++=的系数,输出它的实数根。 例2 编写程序,计算自然数1+2+3+……+99+100的和。 WHILE 条件 循环体 WEND 满足条件? 循环体 是 否 DO 循环体 LOOP UNTIL 条件

循环语句的教学设计

循环语句的教学设计 这是一篇由网络搜集整理的关于循环语句的教学设计的文档,希望对你能有帮助。 1、进一步熟悉循环语句的一般格式和执行流程。 2、学会多角度分析问题,并找出对问题较为便捷适当的解决方法。 2、了解计数循环和条件循环两种循环语句的适用环境。 3、经历将具体问题转化,进而编写出程序的过程,提高逻辑思维能力。 教学重点:循环语句的两种形式的适用环境 教学难点:计数循环和条件循环的灵活应用,将具体问题转化过程。 课型:新授课 教学过程: 一.创设情境 同学们前面,我们已经学习了循环语句,哪位同学能够回忆一下,我们一共学习了几种循环语句呢?(意图:让学生思维中再现循环语句的得来过程和一般形式巩固了旧知识。能用联系的观点看问题) 请三位同学分别在黑板上写出各循环语句的'基本格式 教师点评和小结。 我们学习了,3种循环,那么在具体解决问题时,我们应该选择哪种循环呢?今天我们就来探讨这个问题。 二.师生探究 上次课后,老师布置了一道作业题,但是老师发现同学们给出了不同的答

案,下面我们就一起来研究研究这道题目 问题1:计算1+3+5+……+99的和。 分析:这是一个累加问题,请学生说一说你是怎么分析这道题目的呢? A:发现1,3,5,…99都是奇数,并且到99结束,那么我用一个程序从1一直循环到99,判断是奇数的就加起来。 I=1 S=0 DO IF I MOD 2 0 THEN S=S+I I=I+1 LOOP UNTIL I>99 PRINT S END B:发现相加的数列中后一个数就等于前一个数加上2 I=1 S=0 DO S=S+I I=I+2 LOOP UNTIL I>99

hook的使用实例

在网上找了好久都没有找到消息hook的实例,下面是我的例子给大家分享一下 下面是dll中的代码: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //我的经验,编译的时候会提示DllMain,已在DllMain.cpp中定义,把DllMain.cpp从源文件里删掉就好了 #include "stdafx.h" #include HHOOK hkey=NULL; HINSTANCE h_dll; #pragma data_seg(".MySec") //定义字段,段名.MySec HWND h_wnd=NULL; #pragma data_seg() #pragma comment(linker,"/section:.MySec,RWS") BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { h_dll=hinstDLL; // MessageBox(0,"运行dllman","",MB_OK); return TRUE; } LRESULT CALLBACK my_test(int nCode,WPARAM wParam,LPARAM iParam)// { /* if(nCode==HC_ACTION) { MessageBox(0,"成功!!","标题",MB_OK); } else { MessageBox(0,"失败!!","标题",MB_OK); } */ MessageBox(0,"被截取","",MB_OK); UnhookWindowsHookEx(hkey); return 1; } void SetHook(HWND hwnd) { h_wnd = hwnd; // MessageBox(0,"运行sethook","",MB_OK); hkey=SetWindowsHookEx(WH_KEYBOARD,my_test,h_dll,0); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 下面是EXE的代码:有很多头文件是没用上的,我个人习惯都带着- -,虽然这不是好习惯

5条件语句和循环语句

第二、三课时 1.2.2-1.2.3条件语句和循环语句 教学目标: 知识与技能 (1)正确理解条件语句和循环语句的概念,并掌握其结构的区别与联系。 (2)会应用条件语句和循环语句编写程序。 过程与方法 经历对现实生活情境的探究,认识到应用计算机解决数学问题方便简捷,促进发展学生逻辑思维能力 情感态度与价值观 了解条件语句在程序中起判断转折作用,在解决实际问题中起决定作用。深刻体会到循环语句在解决大量重复问题中起重要作用。减少大量繁琐的计算。通过本小节内容的学习,有益于我们养成严谨的数学思维以及正确处理问题的能力。 重点与难点 重点:条件语句和循环语句的步骤、结构及功能。 难点:会编写程序中的条件语句和循环语句。 学法与教学用具 计算机、图形计算器 教学设想

【创设情境】 试求自然数1+2+3+……+99+100的和。 显然大家都能准确地口算出它的答案:5050。而能不能将这项计算工作交给计算机来完成呢?而要编程,以我们前面所学的输入、输出语句和赋值语句还不能满足“我们日益增长的物质需要”,因此,还需要进一步学习基本算法语句中的另外两种:条件语句和循环语句(板出课题) 【探究新知】 (一)条件语句 算法中的条件结构是由条件语句来表达的,是处理条件分支逻辑结构的算法语句。它的一般格式是:(IF-THEN-ELSE 格式) 当计算机执行上述语句时,首先对IF 后的条件进行判断,如果条件符合,就执行THEN 后的语句1,否则执行ELSE 后的语句2。其对应的程序框图为:(如上右图)

在某些情况下,也可以只使用IF-THEN 语句:(即IF-THEN 格式) 计算机执行这种形式的条件语句时,也是首先对IF 后的条件进行判断,如果条件符合,就执行THEN 后的语句,如果条件不符合,则直接结束该条件语句,转而执行其他语句。其对应的程序框图为:(如上右图) 条件语句的作用:在程序执行过程中,根据判断是否满足约定的条件而决定是否需要转换到何处去。需要计算机按条件进行分析、比较、判断,并按判断后的不同情况进行不同的处理。 【例题精析】 〖例1〗:编写程序,输入一元二次方程20ax bx c ++=的系数,输出它的实数根。 分析:先把解决问题的思路用程序框图表示出来,然后再根据程序框图给 出的算法步骤,逐步把算法用对应的程序语句表达出来。 IF 条件 THEN 语句

FOR循环语句教学设计

FOR循环语句 一、教材分析:本节是《算法与程序设计》(选修)第二章第四节“程序的循环结构”中的内容。这一节的前面是顺序结构和选择结构,紧接FOR语句后面是DO语句和循环嵌套。本节课是FOR语句的初次学习,着重介绍FOR 语句的基础知识:格式和执行过程,不涉及双重循环等较难的运用。循环结构是程序设计的三种基本结构之一,是程序设计的基础。 二、学情分析:在学习本课之前,学生已掌握VB程序的顺序结构和选择结构的程序执行流程,对条件语句有了较深的理解,并具有一定的算法基础和比较、归纳能力。 三、教学目标 1、知识与技能:: 1)掌握FOR循环语句的基本格式; 2)理解FOR循环语句的执行过程; 3)能用for循环结构编写简单的程序。 2、过程与方法: 1)培养学生分析问题,解决问题的能力。 2)能进一步理解用计算机解决问题的过程和方法。 3、情感态度与价值观:激发学生学习热情,培养学生学习的积极性。 四、教学重点、难点及确立依据: 教学重点:1、掌握FOR循环语句的基本格式; 2、理解FOR循环语句的执行过程; 教学难点:解决实际问题,编写简单程序。 五、教学方法:讲授法、任务驱动法 六、教学环境:机房 六、教学过程: 1、导入新课: 由故事引出本节课内容: 阿基米德与国王下棋,国王输了,国王问阿基米德要什么奖赏?阿基米德对国王说:我只要在棋盘上第一格放一粒米,第二格放二粒,第三格放四粒,第四格放八粒………按这个比例放满整个棋盘64个格子就行。国王以为要不了多少粮食,可一个粮仓的米还摆不完一半的棋格子,全部摆满后,你知道排满棋盘全部格子有多少米吗?请根据你所学的数学知识列出式子。 学生回答:2^0+2^1+2^2+……2^64 那用vb程序怎样进行计算呢?引出循环结构。 2、新课讲授: 在实际问题中会遇到具体规律性的重复运算问题,反映在程序中就是将完成特定任务的一组语句重复执行多次。重复执行的一组语句称为循环体,每重复一次循环体,都必须做出继续或者停止循环的判断,其依据就是判断一个特定的条件,成立与否,决定继续还是退出循环。

C#键盘钩子拦截键盘按键

C#键盘钩子,本文以C#语言为例,演示拦截键盘按键。首先打开VS创建一个窗体应用程序。如图: 需要引入以下两个命名空间。 using System.Runtime.InteropServices; using System.Diagnostics; 以下是全部源码: using System; using System.Collections.Generic; using https://www.360docs.net/doc/af5454046.html,ponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices;

using System.Diagnostics; namespace WindowsForms5107 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //定¨义?一?个?结á构1 public struct HookStruck { public int vkCode; public int scanCode; public int time; } public delegate int FunctionAddr(int ncode,IntPtr wParam,IntPtr iparam); [DllImport("user32.dll")] //参?数簓介é绍Θ?:阰hookID表括?示?参?数簓类え?型í,?有瓺鼠酣?标括?钩3子哩?,?键ü盘ì钩3子哩?等台?类え?型í,?callfunction:阰回?调獭?函ˉ数簓地?址·,?即′你?要癮转羇而?执′行D的?程ì序?地?址·。£ //hInstance:钩3子哩?程ì序?的?实害??柄括?。£threadID线?程ìId,你?要癮监à视酣?的?程ì序?的?iD,当獭纈d=0时骸?,?为a系μ统?钩3子哩?,?监à控?整?个?系μ统?

钩子函数捕捉键盘消息

利用钩子函数来捕捉键盘响应的windows应用程序一:引言: 你也许一直对金山词霸的屏幕抓词的实现原理感到困惑,你也许希望将你的键盘,鼠标的活动适时的记录下来,甚至你想知道木马在windows操作系统是怎样进行木马dll的加载的…..其实这些都是用到了windows的钩子函数。因此本文将对钩子函数的相关知识进行阐述。当然,本文的目的并不是想通过此程序让读者去窃取别人的密码,只是由于钩子函数在windows系统中是一个非常重要的系统接口函数,所以想和大家共同的探讨,当然本文也对怎样建立动态连结库(DLL)作了一些简单的描述。(本文的程序为vc6.0的开发环境,语言是:C和win32 api)。 二:钩子概述: 微软的windowsX操作系统是建立在事件驱动的机制上的,也就是通过消息传递来实现。而钩子在windows操作系统中,是一种能在事件(比如:消息、鼠标激活、键盘响应)到达应用程序前中途接获事件的机制。而且,钩子函数还可以通过修改、丢弃等手段来对事件起作用。 Windows 有两种钩子,一种是特定线程钩子(Thread specific hooks),一种是全局系统钩子(Systemwide hooks)。特定线程钩子只是监视指定的线程,而全局系统钩子则可以监视系统中所有的线程。无论是特定线程钩子,还是全局系统钩子,都是通过SetWindowsHookEx ()来设置钩子的。对于特定线程钩子,钩子的函数既可以是包含在一个.exe也可以是一个.dll。但是对于一个全局系统钩子,钩子函数必须包含在独立的dll中,因此,当我们要捕捉键盘响应时,我们必须创建一个动态链接库。但是当钩子函数在得到了控制权,并对相关的事件处理完后,如果想要该消息得以继续的传递,那么则必须调用另一个函数:CallNextHookEx。由于系统必须对每个消息处理,钩子程序因此增加了处理的负担,因此也降低了系统的性能。鉴于这一点,在windows ce中对钩子程序并不支持。所以当程序完成并退出时,应当释放钩子,调用函数:UnhookWindowsHookEx。 下面我们将举一个例子(捕捉键盘)来详细的讲解钩子函数的程序设计。 三:程序的设计: I:设置钩子 设置钩子是通过SetWindowsHookEx ()的API函数. 原形: HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId) idhook:装入钩子的类型. lpfn: 钩子进程的入口地址 hMod: 应用程序的事件句柄 dwThreadId: 装入钩子的线程标示 参数: idHook: 这个参数可以是以下值: WH_CALLWNDPROC、WH_CALLWNDPROCRET、WH_CBT、WH_DEBUG、WH_FOREGROUNDIDLE、 WH_GETMESSAGE、WH_JOURNALPLAYBACK、WH_JOURNALRECORD、WH_KEYBOARD、WH_KEYBOARD_LL、

《基本算法语句——循环语句》教学设计

《基本算法语句——循环语句》教学设计 教学目标 (1)正确理解循环语句的概念,并掌握其结构; (2)会应用循环语句编写程序. 教学重点 两种循环语句的表示方法、结构和用法,用循环语句表示算法. 教学难点 理解循环语句的表示方法、结构和用法,会编写程序中的循环语句. 教学过程 一、问题情境 1.问题1:设计计算135799?????的一个算法,并画出流程图. 二、学生活动 解决问题1的算法是: 对于以上算法过程,我们可以用循环语句来实现. 三、建构数学 1.循环语句:循环语句一般有种:“For 循环”、“While 循环”和“Do 循环”(由于该种循环变化较多,教材中暂不介绍). (1)“For 循环”是在循环次数已知时使用的循环, 其一般形式为: 例如:问题1中算法可用“For 循环”语句表示为: 1S ← Print S End S1 S ←1 S2 I ←3 S3 S ←S ×I S4 I ←I+2 S5 若I ≤99,则返回S3 S6 输出S 结束 开始 流程图: For I from “初值”to “终值”step “步长” … End for For I From 1 To 99 Step 2 S S I ←? End For

说明:①上面“For ”和“End For ”之间缩进的步骤称为循环体; ②如果省略“Step 2”,默认的“步长”为1,即循环时,I 的值每次增加1(步长也可以为负,例如,以上“For 循环”第1行可写成:For I From 99 To 1 Step -2); ③“For 循环”是直到型循环结构,即先执行后判断. (2)“While 循环”的一般形式为: 其中A 为判断执行循环的条件. 例如:问题1中的算法可“While 循环”语句表示为: 1S ← 3I ← Print S End 说明:①上面“While ”和“End While ”之间缩进的步骤称为循环体; ②“While 循环”是当型循环结构,其特点是“前测试”,即先判断,后执行.若初始条件不成立,则一次也不执行循环体中的内容; ③任何一种需要重复处理的问题都可以用这种前测试循环来实现. 四、数学运用 1.例题: 例1.编写程序,计算自然数1+2+3+……+99+100的和。 解:用“For 循环”表示如下: 用“While 循环”表示如下: 例2.试用算法语句表示:寻找满足1357_____10000?????>的最小整数的算法. 解:本例中循环的次数不定,因此可用“While 循环”语句,具体描述如下: While A … End while While I ≤99 S S I ←? 2I I =+ End While 1S ← For I From 1 To 100 Step 1 S S I ←+ End For Print S End 1S ← While I ≤100 S S I ←+ 1I I =+ End While Print S End 1S ← 1I ← While S ≤10000 2I I =+ *S S I ← End While Print I End

C#键盘钩子实现全局快捷键

C#键盘钩子实现全局快捷键 本文介绍如何使用Win32Api创建键盘钩子,并编写一个使用全局快捷键的实例。 工具/原料 Visual Studio(本文使用VS2013,其他版本亦可)。 基础知识 1 使用钩子之前,需要使用SetWindowsHookEx()函数创建钩子,使用完毕之后要UnhookWindowsHookEx()函数卸载钩子,“钩”到消息后操作系统会自动调用在创建钩子时注册的回调函数来处理消息,处理完后调用CallNextHookEx()函数等待或处理下一条消息。有关钩子的详细信息请见参考--C#鼠标钩子,其中已介绍。 2 对于键盘钩子,钩子类型为WH_KEYBOARD_LL=13,只需要设置SetWindowsHookEx的idHook 参数为13即可“钩”到键盘消息。关于钩子类型的资料见参考资料--钩子类型。 END 键盘钩子实例 启动VS,新建C# WinForm项目,命名为“Cs键盘钩子”,如下: 对主窗口布局,如下: 添加Win32Api引用,代码如下: using System; using System.Collections.Generic; using System.Linq;

using System.Text; using System.Runtime.InteropServices; using System.Reflection; using System.Threading; using System.Windows.Forms; using System.Diagnostics; public class Win32Api { #region常数和结构 public const int WM_KEYDOWN = 0x100; public const int WM_KEYUP = 0x101; public const int WM_SYSKEYDOWN = 0x104; public const int WM_SYSKEYUP = 0x105; public const int WH_KEYBOARD_LL = 13; [StructLayout(LayoutKind.Sequential)] //声明键盘钩子的封送结构类型public class KeyboardHookStruct { public int vkCode; //表示一个在1到254间的虚似键盘码 public int scanCode; //表示硬件扫描码 public int flags; public int time; public int dwExtraInfo; } #endregion #region Api public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); //安装钩子的函数 [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); //卸下钩子的函数 [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern bool UnhookWindowsHookEx(int idHook); //下一个钩挂的函数 [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int CallNextHookEx(int idHook, int nCode, Int32wParam, IntPtr lParam); [DllImport("user32")] public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);

相关文档
最新文档