能不能捕捉系统光标所在的位置 比如打开一个任意的文档光标都会在一闪一闪的,能不能捕捉到它,然后再在它后面加我想要的内容就好比,一打开新的记事本就不是空的记事本,而是有内容的(这个内容是我在程序内附给它的)能不能啊,请各位路过的大侠来看看哦,非常感谢!!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 <script type="text/javascript">function mousePosition(ev){if(ev.pageX || ev.pageY){return {x:ev.pageX, y:ev.pageY};}return {x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,y:ev.clientY +document.body.scrollTop - document.body.clientTop};} 鼠标屏幕取词技术的原理和实现减小字体 增大字体 作者:不详 来源:本站整理 发布时间:2005-7-29 20:49:57 “鼠标屏幕取词”技术是在电子字典中得到广泛地应用的,如四通利方和金山词霸等软件,这个技术看似简单,其实在windows系统中实现却是非常复杂的,总的来说有两种实现方式: 第一种:采用截获对部分gdi的api调用来实现,如textout,textouta等。 第二种:对每个设备上下文(dc)做一分copy,并跟踪所有修改上下文(dc)的操作。 第二种方法更强大,但兼容性不好,而第一种方法使用的截获windowsapi的调用,这项技术的强大可能远远超出了您的想象,毫不夸张的说,利用windowsapi拦截技术,你可以改造整个操作系统,事实上很多外挂式windows中文平台就是这么实现的!而这项技术也正是这篇文章的主题。 截windowsapi的调用,具体的说来也可以分为两种方法: 第一种方法通过直接改写winapi 在内存中的映像,嵌入汇编代码,使之被调用时跳转到指定的地址运行来截获;第二种方法则改写iat(import address table输入地址表),重定向winapi函数的调用来实现对winapi的截获。 第一种方法的实现较为繁琐,而且在win95、98下面更有难度,这是因为虽然微软说win16的api只是为了兼容性才保留下来,程序员应该尽可能地调用32位的api,实际上根本就不是这样!win 9x内部的大部分32位api经过变换调用了同名的16位api,也就是说我们需要在拦截的函数中嵌入16位汇编代码! 我们将要介绍的是第二种拦截方法,这种方法在win95、98和nt下面运行都比较稳定,兼容性较好。由于需要用到关于windows虚拟内存的管理、打破进程边界墙、向应用程序的进程空间中注入代码、pe(portable executable)文件格式和iat(输入地址表)等较底层的知识,所以我们先对涉及到的这些知识大概地做一个介绍,最后会给出拦截部分的关键代码。 先说windows虚拟内存的管理。windows9x给每一个进程分配了4gb的地址空间,对于nt来说,这个数字是2gb,系统保留了2gb到 4gb之间的地址空间禁止进程访问,而在win9x中,2gb到4gb这部分虚拟地址空间实际上是由所有的win32进程所共享的,这部分地址空间加载了共享win32 dll、内存映射文件和vxd、内存管理器和文件系统码,win9x中这部分对于每一个进程都是可见的,这也是win9x操作系统不够健壮的原因。win9x中为16位操作系统保留了0到4mb的地址空间,而在4mb到2gb之间也就是win32进程私有的地址空间,由于 每个进程的地址空间都是相对独立的,也就是说,如果程序想截获其它进程中的api调用,就必须打破进程边界墙,向其它的进程中注入截获api调用的代码,这项工作我们交给钩子函数(setwindowshookex)来完成,关于如何创建一个包含系统钩子的动态链接库,《电脑高手杂志》在第?期已经有过专题介绍了,这里就不赘述了。所有系统钩子的函数必须要在动态库里,这样的话,当进程隐式或显式调用一个动态库里的函数时,系统会把这个动态库映射到这个进程的虚拟地址空间里,这使得dll成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈,也就是说动态链接库中的代码被钩子函数注入了其它gui进程的地址空间(非gui进程,钩子函数就无能为力了),当包含钩子的dll注入其它进程后,就可以取得映射到这个进程虚拟内存里的各个模块(exe和dll)的基地址,如:hmodule hmodule=getmodulehandle(“mypro.exe”);在mfc程序中,我们可以用afxgetinstancehandle()函数来得到模块的基地址。exe和dll被映射到虚拟内存空间的什么地方是由它们的基地址决定的。它们的基地址是在链接时由链接器决定的。当你新建一个win32工程时,vc++链接器使用缺省的基地址0x00400000。可以通过链接器的base选项改变模块的基地址。exe通常被映射到虚拟内存的0x00400000处,dll也随之有不同的基地址,通常被映射到不同进程的相同的虚拟地址空间处。 系统将exe和dll原封不动映射到虚拟内存空间中,它们在内存中的结构与磁盘上的静态文件结构是一样的。即pe (portable executable) 文件格式。我们得到了进程模块的基地址以后,就可以根据pe文件的格式穷举这个模块的image_import_descriptor数组,看看进程空间中是否引入了我们需要截获的函数所在的动态链接库,比如需要截获“textouta”,就必须检查“gdi32.dll”是否被引入了。说到这里,我们有必要介绍一下pe文件的格式,如右图,这是pe文件格式的大致框图,最前面是文件头,我们不必理会,从pe file optional header后面开始,就是文件中各个段的说明,说明后面才是真正的段数据,而实际上我们关心的只有一个段,那就是“.idata”段,这个段中包含了所有的引入函数信息,还有iat(import address table)的rva(relative virtual address)地址。 说到这里,截获windowsapi的整个原理就要真相大白了。实际上所有进程对给定的api函数的调用总是通过pe文件的一个地方来转移的,这就是一个该模块(可以是exe或dll)的“.idata”段中的iat输入地址表(import address table)。在那里有所有本模块调用的其它dll的函数名及地址。对其它dll的函数调用实际上只是跳转到输入地址表,由输入地址表再跳转到dll真正的函数入口。 具体来说,我们将通过image_import_descriptor数组来访问“.idata”段中引入的dll的信息,然后通过image_thunk_data数组来针对一个被引入的dll访问该dll中被引入的每个函数的信息,找到我们需要截获的函数的跳转地址,然后改成我们自己的函数的地址……具体的做法在后面的关键代码中会有详细的讲解。 讲了这么多原理,现在让我们回到“鼠标屏幕取词”的专题上来。除了api函数的截获,要实现“鼠标屏幕取词”,还需要做一些其它的工作,简单的说来,可以把一个完整的取词过程归纳成以下几个步骤:1. 安装鼠标钩子,通过钩子函数获得鼠标消息。 使用到的api函数:setwindowshookex2. 得到鼠标的当前位置,向鼠标下的窗口发重画消息,让它调用系统函数重画窗口。 使用到的api函数:windowfrompoint,screentoclient,invalidaterect using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Threading;namespace ShuBiao{ public partial class Form1 : Form { #region Window Api [DllImport("user32.dll")] static extern bool SetCursorPos(int x, int y); [DllImport("user32.dll")] static extern void mouse_event(uint mouseEvent, int dx, int dy, uint data, int extrainfo); #endregion #region Mouse Event public static readonly uint MOUSEEVENTF_LEFTDOWN = 2; public static readonly uint MOUSEEVENTF_LEFTUP = 4; public static readonly uint MOUSEEVENTF_RIGHTDOWN = 8; public static readonly uint MOUSEEVENTF_RIGHTUP = 16; # endregion public Form1() { InitializeComponent(); WindowState = FormWindowState.Minimized; //设置多长时间点鼠标 Thread.Sleep(6000); } private void Form1_Load(object sender, EventArgs e) { DateTime dt=DateTime .Now; string day; day = dt.DayOfWeek.ToString(); if (day == "Sunday" || day =="Saturday") ShutDown(); else MouseEvent(); } /// <summary> /// 鼠标事件 /// </summary> private void MouseEvent() { //启动officeIM System.Diagnostics.Process.Start(@"F:\陈想\软件\OfficeIM网络智能办公客户端\OfficeIM.exe"); //随机选取,在一定时间点击 Random rd=new Random(); int time=rd.Next(1,5); Thread .Sleep (time*60000); //点击升级以后再说 SetCursorPos(561, 467); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); SetCursorPos(561, 467); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击考勤工作日志 Thread.Sleep(10000); SetCursorPos(88, 168); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); SetCursorPos(88, 168); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击考勤登记 Thread.Sleep(5000); SetCursorPos(376, 84); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); SetCursorPos(376, 84); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击登记(早晨) Thread.Sleep(5000); SetCursorPos(677, 315); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); SetCursorPos(677, 315); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击退出 Thread.Sleep(5000); SetCursorPos(681, 547); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); SetCursorPos(681, 547); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击关闭 Thread.Sleep(5000); SetCursorPos(1014, 10); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); SetCursorPos(1014, 10); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); SetCursorPos(1014, 10); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); SetCursorPos(1014, 10); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); Application.Exit(); } /// <summary> /// 周末的时候自动关机 /// </summary> private void ShutDown() { //60秒后自动关机 System.Diagnostics.Process.Start("shutdown", "-s -f -t 60"); } }}//前几天写的程序。实现自动登录系统。(考勤系统)希望对你有所帮助。 Global System Hooks in .NET http://www.codeproject.com/KB/system/globalsystemhook.aspx ------------------------------------------------------------ Processing Global Mouse and Keyboard Hooks in C# http://www.codeproject.com/csharp/globalhook.asp 请问这两个VS2008的版本号 哪个是最新的? 怎样向打印机传ASCII的数据啊! 怎样快速定位到我用XML注释的函数 大家帮忙看看这个怎么解决 怎样创建、修改、删除NTFS文件流 thread.Abort()与 thread.Suspend()的区别???? 急,查询3张表,去掉某张表的字段不重复,怎么查询 *******50分只求一个正则表达式如何写???或别的方法查打字符串***** 我装了VS.NET 2005以后,出些VS.NET 2003不能调试! 怎么把WORD的文字显示区域镶嵌在我的窗体中? 如何把C#控制台程序生成一个.exe可执行文件。步骤如何? .net分布式解决方案
<script type="text/javascript">
function mousePosition(ev)
{if(ev.pageX || ev.pageY){return {x:ev.pageX, y:ev.pageY};}
return {
x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
y:ev.clientY +document.body.scrollTop - document.body.clientTop};
}
减小字体 增大字体 作者:不详 来源:本站整理 发布时间:2005-7-29 20:49:57 “鼠标屏幕取词”技术是在电子字典中得到广泛地应用的,如四通利方和金山词霸等软件,这个技术看似简单,其实在windows系统中实现却是非常复杂的,总的来说有两种实现方式:
第一种:采用截获对部分gdi的api调用来实现,如textout,textouta等。
第二种:对每个设备上下文(dc)做一分copy,并跟踪所有修改上下文(dc)的操作。
第二种方法更强大,但兼容性不好,而第一种方法使用的截获windowsapi的调用,这项技术的强大可能远远超出了您的想象,毫不夸张的说,利用windowsapi拦截技术,你可以改造整个操作系统,事实上很多外挂式windows中文平台就是这么实现的!而这项技术也正是这篇文章的主题。
截windowsapi的调用,具体的说来也可以分为两种方法:
第一种方法通过直接改写winapi 在内存中的映像,嵌入汇编代码,使之被调用时跳转到指定的地址运行来截获;第二种方法则改写iat(import address table输入地址表),重定向winapi函数的调用来实现对winapi的截获。
第一种方法的实现较为繁琐,而且在win95、98下面更有难度,这是因为虽然微软说win16的api只是为了兼容性才保留下来,程序员应该尽可能地调用32位的api,实际上根本就不是这样!win 9x内部的大部分32位api经过变换调用了同名的16位api,也就是说我们需要在拦截的函数中嵌入16位汇编代码!
我们将要介绍的是第二种拦截方法,这种方法在win95、98和nt下面运行都比较稳定,兼容性较好。由于需要用到关于windows虚拟内存的管理、打破进程边界墙、向应用程序的进程空间中注入代码、pe(portable executable)文件格式和iat(输入地址表)等较底层的知识,所以我们先对涉及到的这些知识大概地做一个介绍,最后会给出拦截部分的关键代码。
先说windows虚拟内存的管理。windows9x给每一个进程分配了4gb的地址空间,对于nt来说,这个数字是2gb,系统保留了2gb到 4gb之间的地址空间禁止进程访问,而在win9x中,2gb到4gb这部分虚拟地址空间实际上是由所有的win32进程所共享的,这部分地址空间加载了共享win32 dll、内存映射文件和vxd、内存管理器和文件系统码,win9x中这部分对于每一个进程都是可见的,这也是win9x操作系统不够健壮的原因。win9x中为16位操作系统保留了0到4mb的地址空间,而在4mb到2gb之间也就是win32进程私有的地址空间,由于 每个进程的地址空间都是相对独立的,也就是说,如果程序想截获其它进程中的api调用,就必须打破进程边界墙,向其它的进程中注入截获api调用的代码,这项工作我们交给钩子函数(setwindowshookex)来完成,关于如何创建一个包含系统钩子的动态链接库,《电脑高手杂志》在第?期已经有过专题介绍了,这里就不赘述了。所有系统钩子的函数必须要在动态库里,这样的话,当进程隐式或显式调用一个动态库里的函数时,系统会把这个动态库映射到这个进程的虚拟地址空间里,这使得dll成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈,也就是说动态链接库中的代码被钩子函数注入了其它gui进程的地址空间(非gui进程,钩子函数就无能为力了),当包含钩子的dll注入其它进程后,就可以取得映射到这个进程虚拟内存里的各个模块(exe和dll)的基地址,如:hmodule hmodule=getmodulehandle(“mypro.exe”);在mfc程序中,我们可以用afxgetinstancehandle()函数来得到模块的基地址。exe和dll被映射到虚拟内存空间的什么地方是由它们的基地址决定的。它们的基地址是在链接时由链接器决定的。当你新建一个win32工程时,vc++链接器使用缺省的基地址0x00400000。可以通过链接器的base选项改变模块的基地址。exe通常被映射到虚拟内存的0x00400000处,dll也随之有不同的基地址,通常被映射到不同进程的相同的虚拟地址空间处。
系统将exe和dll原封不动映射到虚拟内存空间中,它们在内存中的结构与磁盘上的静态文件结构是一样的。即pe (portable executable) 文件格式。我们得到了进程模块的基地址以后,就可以根据pe文件的格式穷举这个模块的image_import_descriptor数组,看看进程空间中是否引入了我们需要截获的函数所在的动态链接库,比如需要截获“textouta”,就必须检查“gdi32.dll”是否被引入了。说到这里,我们有必要介绍一下pe文件的格式,如右图,这是pe文件格式的大致框图,最前面是文件头,我们不必理会,从pe file optional header后面开始,就是文件中各个段的说明,说明后面才是真正的段数据,而实际上我们关心的只有一个段,那就是“.idata”段,这个段中包含了所有的引入函数信息,还有iat(import address table)的rva(relative virtual address)地址。
说到这里,截获windowsapi的整个原理就要真相大白了。实际上所有进程对给定的api函数的调用总是通过pe文件的一个地方来转移的,这就是一个该模块(可以是exe或dll)的“.idata”段中的iat输入地址表(import address table)。在那里有所有本模块调用的其它dll的函数名及地址。对其它dll的函数调用实际上只是跳转到输入地址表,由输入地址表再跳转到dll真正的函数入口。 具体来说,我们将通过image_import_descriptor数组来访问“.idata”段中引入的dll的信息,然后通过image_thunk_data数组来针对一个被引入的dll访问该dll中被引入的每个函数的信息,找到我们需要截获的函数的跳转地址,然后改成我们自己的函数的地址……具体的做法在后面的关键代码中会有详细的讲解。
讲了这么多原理,现在让我们回到“鼠标屏幕取词”的专题上来。除了api函数的截获,要实现“鼠标屏幕取词”,还需要做一些其它的工作,简单的说来,可以把一个完整的取词过程归纳成以下几个步骤:
1. 安装鼠标钩子,通过钩子函数获得鼠标消息。
使用到的api函数:setwindowshookex
2. 得到鼠标的当前位置,向鼠标下的窗口发重画消息,让它调用系统函数重画窗口。
使用到的api函数:windowfrompoint,screentoclient,invalidaterect
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;using System.Runtime.InteropServices;
using System.Threading;namespace ShuBiao
{
public partial class Form1 : Form
{
#region Window Api
[DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y); [DllImport("user32.dll")]
static extern void mouse_event(uint mouseEvent, int dx, int dy, uint data, int extrainfo);
#endregion #region Mouse Event
public static readonly uint MOUSEEVENTF_LEFTDOWN = 2;
public static readonly uint MOUSEEVENTF_LEFTUP = 4;
public static readonly uint MOUSEEVENTF_RIGHTDOWN = 8;
public static readonly uint MOUSEEVENTF_RIGHTUP = 16;
# endregion public Form1()
{
InitializeComponent();
WindowState = FormWindowState.Minimized; //设置多长时间点鼠标
Thread.Sleep(6000);
} private void Form1_Load(object sender, EventArgs e)
{
DateTime dt=DateTime .Now;
string day;
day = dt.DayOfWeek.ToString();
if (day == "Sunday" || day =="Saturday")
ShutDown();
else
MouseEvent();
} /// <summary>
/// 鼠标事件
/// </summary>
private void MouseEvent()
{
//启动officeIM
System.Diagnostics.Process.Start(@"F:\陈想\软件\OfficeIM网络智能办公客户端\OfficeIM.exe");
//随机选取,在一定时间点击
Random rd=new Random();
int time=rd.Next(1,5);
Thread .Sleep (time*60000); //点击升级以后再说
SetCursorPos(561, 467);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(561, 467);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
//点击考勤工作日志
Thread.Sleep(10000);
SetCursorPos(88, 168);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(88, 168);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击考勤登记
Thread.Sleep(5000);
SetCursorPos(376, 84);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(376, 84);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
//点击登记(早晨)
Thread.Sleep(5000);
SetCursorPos(677, 315);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(677, 315);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击退出
Thread.Sleep(5000);
SetCursorPos(681, 547);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(681, 547);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //点击关闭
Thread.Sleep(5000);
SetCursorPos(1014, 10);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(1014, 10);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); SetCursorPos(1014, 10);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
SetCursorPos(1014, 10);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); Application.Exit();
} /// <summary>
/// 周末的时候自动关机
/// </summary>
private void ShutDown()
{
//60秒后自动关机
System.Diagnostics.Process.Start("shutdown", "-s -f -t 60");
}
}
}//前几天写的程序。实现自动登录系统。(考勤系统)希望对你有所帮助。
http://www.codeproject.com/KB/system/globalsystemhook.aspx
------------------------------------------------------------
Processing Global Mouse and Keyboard Hooks in C#
http://www.codeproject.com/csharp/globalhook.asp