获取鼠标信息
鼠标基本设置
鼠标操作在实际中的应用
1
第
章
鼠标操作控制
1.1 获取鼠标信息
鼠标是计算机的一个重要组成部分,它有很多默认的设置,如双击时间间隔、闪烁频率、移动速度等。本 实例使用 C#实现了获取鼠标双击时间间隔的功能,实例运行效果如图 1.1 所示。
图 1.1 获取鼠标双击时间间隔
本实例实现时主要用到了 API 函数 GetDoubleClickTime,下面对其进行详细介绍。
GetDoubleClickTime 函数主要用来判断连续两次鼠标单击之间会被处理成双击事件的间隔时间,其声明语 法如下:
[DllImport("user32.dll", EntryPoint = "GetDoubleClickTime")]
public extern static int GetDoubleClickTime(); //重写 API 函数
参数说明
返回值:int 类型,表示以毫秒表示的双击时间。
说明:程序中使用系统 API 函数时,首先需要在命名空间区域添加 System.Runtime.InteropServices 命名空间,下面遇到类似的情况时将不再提示。
(1) 打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 GetMouseTimeSpan。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 Label 控件,用来显示鼠标双 击的时间间隔。
(3)程序主要代码如下:
[DllImport("user32.dll", EntryPoint = "GetDoubleClickTime")]
public extern static int GetDoubleClickTime(); //重写 API 函数 private void Frm_Main_Load(object sender, EventArgs e)
{
label2.Text = GetDoubleClickTime()+"毫秒"; //显示双击鼠标的时间间隔 }
心法领悟 001:使用 OpenWrite 方法打开现有文件并进行写入。
使用 OpenWrite 方法打开现有文件并进行写入时,首先需要生成 FileStream 类的一个对象,用来记录要打 开的文件路径及名称,然后定义一个 Byte 类型的数组,存储以 Default 方式编码的要写入文件的内容,最后调用 FileStream 对象的 Write 方法向指定文件中写入内容。使用 OpenWrite 方法打开现有文件并进行写入的代码如下:
FileStream FStream = File.OpenWrite(textBox1.Text);
Byte[] info =Encoding.Default.GetBytes(textBox2.Text);
FStream.Write(info, 0, info.Length);
本实例使用 C#实现了获取光标闪烁频率的功能,实例运行效果如图 1.2 所示。
图 1.2 获取光标闪烁的频率
本实例实现时主要用到了 API 函数 GetCaretBlinkTime,下面对其进行详细介绍。
GetCaretBlinkTime 函数主要用来判断插入符光标的闪烁频率,其声明语法如下:
[DllImport("user32", EntryPoint = "GetCaretBlinkTime")]
public extern static int GetCaretBlinkTime(); //重写 API 函数
参数说明
返回值:int 类型,表示插入符连续两次闪烁间隔的时间,以毫秒为单位,零表示函数调用失败。
(1) 打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 GetMouseFrequency。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 Label 控件,用来显示光标闪 烁的频率。
(3)程序主要代码如下:
[DllImport("user32", EntryPoint = "GetCaretBlinkTime")]
public extern static int GetCaretBlinkTime(); //重写 API 函数 private void Frm_Main_Load(object sender, EventArgs e)
{
label2.Text = GetCaretBlinkTime() + "毫秒"; //显示光标闪烁频率 }
心法领悟 002:如何读取文件中的第一行数据?
读取文件中第一行数据时,首先需要生成 StreamReader 类的一个对象,以指定要读取的文件,然后调用 StreamReader 对象的 ReadLine 方法将指定文件中的第一行数据读取出来。读取文件中第一行数据的代码如下:
openFileDialog1.Filter = "文本文件(*.txt)|*.txt";
openFileDialog1.ShowDialog();
textBox1.Text = openFileDialog1.FileName;
StreamReader SReader=new StreamReader(textBox1.Text,Encoding.Default);
textBox2.Text = SReader.ReadLine();
鼠标有多种样式,如有的只有左右两个键、有的带滑轮等,不同样式的鼠标,按键数目是不一样的。本实
例使用 C#实现了获取鼠标键数的功能,实例运行效果如图 1.3 所示。
图 1.3 获取鼠标键数
本实例实现时主要用到了 API 函数 GetSystemMetrics,下面对其进行详细介绍。
GetSystemMetrics 函数主要用来返回与 Windows 环境有关的信息,其声明语法如下:
[DllImport("user32",EntryPoint="GetSystemMetrics")]
public static extern int GetSystemMetrics(int intcount); //重写 API 函数
参数说明
intcount:指定欲获取的信息。
返回值:取决于具体的常数索引。
说明:本实例在使用 GetSystemMetrics 函数时,为其 intcount 参数定义了 SM_CMOUSEBUTTONS 常量值,该值的常量值为 43,表示鼠标按钮(按键)的数量,如没有鼠标,则为 0。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 GetMouseNumbers。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 Label 控件,用来显示鼠标的 按键数目。
(3)程序主要代码如下:
public const int SM_CMOUSEBUTTONS=43; //定义一个常量值
[DllImport("user32",EntryPoint="GetSystemMetrics")]
public static extern int GetSystemMetrics(int intcoutn); //重写 API 函数 private void Form1_Load(object sender, EventArgs e)
{
int intCon = GetSystemMetrics(SM_CMOUSEBUTTONS); //获取鼠标键数
label2.Text = intCon + "个"; //显示在 Label 控件中
}
心法领悟 003:如何向文件中写入数据?
向文件中写入数据时,首先要生成 StreamWriter 类的一个对象,以指定要写入数据的文件,然后调用该对 象的 Write 方法向指定文件中写入数据。向文件中写入数据的代码如下:
StreamWriter SWriter = new StreamWriter(textBox1.Text);
SWriter.Write(textBox2.Text);
SWriter.Close();
在不同的操作状态,鼠标会显示不同的外观,如人们熟知的鼠标的正常选择状态、精确选择状态和帮助选 择状态等,那么如何手动设置鼠标处于不同的状态呢?本实例使用 C#实现了使鼠标处于等待状态的功能,实例 运行效果如图 1.4 所示。
图 1.4 显示鼠标的等待光标
本实例实现时主要用到了 Form 类的 Cursor 属性,下面对其进行详细介绍。
Form 类的 Cursor 属性用来获取或设置当鼠标指针位于窗体上时显示的光标,其语法格式如下:
public virtual Cursor Cursor { get; set; }
参数说明
属性值:一个 Cursor,表示当鼠标指针位于窗体上时显示的光标。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 ShowWaitMouse。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main。
(3)程序主要代码如下:
private void Frm_Main_Load(object sender, EventArgs e) {
this.Cursor = Cursors.WaitCursor; //将当前窗体的光标样式修改为等待光标
}
心法领悟 004:如何读取文件中的所有数据?
读取文件中的所有数据时,首先需要生成 StreamReader 类的一个对象,以指定要读取的文件,然后调用 StreamReader 对象的 ReadToEnd 方法将指定文件中的所有数据读取出来。读取文件中所有数据的代码如下:
StreamReader SReader = new StreamReader(textBox1.Text, Encoding.Default);
textBox2.Text = SReader.ReadToEnd();
在开发精确度比较高的程序(如电子地图程序、屏幕抓图程序等)时,通常都需要准确定位鼠标的位置,
那么如何实现该功能呢?本实例解决了这一问题。运行本实例,在窗体的任意位置单击鼠标,程序会适时将鼠 标的当前位置显示在窗体上。实例运行效果如图 1.5 所示。
图 1.5 获得鼠标在窗体上的位置
本实例实现时主要用到了 MouseEventArgs 类的 X 属性和 Y 属性,下面分别对它们进行详细介绍。
(1)MouseEventArgs 类的 X 属性
MouseEventArgs 类用来为 MouseUp、MouseDown 和 MouseMove 事件提供数据,其 X 属性用来获取鼠标在 产生鼠标事件时的 X 坐标,其语法格式如下:
public int X { get; }
参数说明
属性值:鼠标的 X 坐标(以像素为单位)。
(2)MouseEventArgs 类的 Y 属性
该属性用来获取鼠标在产生鼠标事件时的 Y 坐标,其语法格式如下:
public int Y { get; }
参数说明
属性值:鼠标的 Y 坐标(以像素为单位)。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 GetMousePosition。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加两个 Label 控件,分别用来显示鼠 标当前位置的 X 坐标和 Y 坐标。
(3)程序主要代码如下:
private void Form1_MouseDown(object sender, MouseEventArgs e) {
this.labX.Text = e.X.ToString(); //显示 X 坐标
this.labY.Text = e.Y.ToString(); //显示 Y 坐标
}
心法领悟 005:如何创建临时文件?
在 C#中创建一个临时文件的代码如下:
textBox1.Text = Path.GetTempFileName();
FileInfo fin = new FileInfo(textBox1.Text);
StreamWriter sw = fin.AppendText();
sw.Write(textBox2.Text);
sw.Close();
在 Windows 操作系统中,按下鼠标右键时,会弹出快捷菜单,而按下鼠标左键时,可以拖动窗口,那么操 作系统是如何区分用户按下的是鼠标右键还是左键呢?本实例将通过 C#程序解决该问题。运行本实例,当用户 对鼠标进行操作时,程序会自动记录并显示鼠标的操作行为。实例运行效果如图 1.6 所示。
图 1.6 记录鼠标行为
本实例实现时主要用到了 MouseEventArgs 类的 Button 属性,下面对其进行详细介绍。
MouseEventArgs 类的 Button 属性用来获取曾按下的是哪个鼠标按键,其语法格式如下:
public MouseButtons Button { get; }
参数说明
属性值:MouseButtons 枚举值之一。MouseButtons 枚举值及说明如表 1.1 所示。
表 1.1 MouseButtons 枚举值及说明
枚 举 值 说 明 枚 举 值 说 明
Left 鼠标左键曾按下 Middle 鼠标中间键曾按下
None 未曾按下鼠标按键 XButton1 第一个 XButton 曾按下
Right 鼠标右键曾按下 XButton2 第二个 XButton 曾按下
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 RecordMouse。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 TextBox 控件,用来显示鼠标 按键的行为。
(3)程序主要代码如下:
private void textBox1_MouseDown(object sender, MouseEventArgs e) {
string str = textBox1.Text; //记录文本框中的内容
if (e.Button == MouseButtons.Right) //如果按下鼠标右键
{
str += "鼠标右键按下 "; //记录鼠标右键按下
}
if (e.Button == MouseButtons.Left) //如果按下鼠标左键
{
str += "鼠标左键按下 "; //记录鼠标左键按下
}
if (e.Button == MouseButtons.Middle) //如果按下鼠标中间键
{
str += "鼠标中间键按下 "; //记录鼠标中间键按下
}
textBox1.Text = str; //显示鼠标按键行为
}
心法领悟 006:如何实现文件替换?
用 File.Create 方法创建文件时,如果在用户的机器上已经存在该文件,则新文件会自动替换掉原来的文件。
实现文件替换功能的代码如下:
File.Create(textBox1.Text);
程序开发中,有效地截取系统消息有时会起到事半功倍的效果,如开发人员可以通过截取系统消息获取鼠 标操作或者键盘操作等。本实例通过截取系统消息实现了获取鼠标单击键的功能,实例运行效果如图 1.7 所示。
图 1.7 通过截取系统消息判断鼠标的单击键
本实例实现的关键是如何截取系统消息,下面对如何在 C#中截取系统消息进行详细讲解。
在 C#中截取系统消息时,主要有以下两种方案:
第一种方案,通过在 Form 中重写 Control 类的虚方法 WndProc 来截取 Windows 消息。
第二种方案,通过实现 IMessageFilter 接口来创建消息筛选器,从而截取 Windows 消息。
下面对这两种方案中用到的关键技术进行详细讲解。
(1)WndProc 方法
WndProc 方法主要用来处理 Windows 消息,该方法为虚方法,其语法格式如下:
protected virtual void WndProc(ref Message m)
参数说明
m:Message 结构,表示要处理的 Windows 消息。Message 结构的属性及说明如表 1.2 所示。
表 1.2 Message 结构的属性及说明
属 性 说 明
HWnd 获取或设置消息的窗口句柄
LParam 指定消息的 LParam 字段
Msg 获取或设置消息的 ID 号
Result 指定为响应消息处理而向 Windows 返回的值
WParam 获取或设置消息的 WParam 字段
(2)IMessageFilter 接口
IMessageFilter 接口用来定义消息筛选器接口,该接口的 PreFilterMessage 方法用来在调度消息之前将其筛 选出来,其语法格式如下:
bool PreFilterMessage(ref Message m)
参数说明
m:要调度的消息,无法修改此消息。
返回值:如果筛选消息并禁止消息被调度,则为 true;如果允许消息继续到达下一个筛选器或控件,则 为 false。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 SysInfo。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 Label 控件,用来显示操作程 序的提示信息。
(3)程序主要代码如下:
private void Frm_Main_Load(object sender, EventArgs e) //窗体加载消息筛选器 {
Application.AddMessageFilter(mf); //添加消息筛选器,以便在向目标传送 Windows 消息时监视这些消息
}
private void Frm_Main_FormClosing(object sender, FormClosingEventArgs e)//从窗体中移除一个消息筛选器 {
Application.RemoveMessageFilter(mf); //从应用程序的消息泵移除一个消息筛选器
}
protected override void WndProc(ref Message m) //方法一,重写 WndProc 虚方法,与方法二不可同时存在 {
switch (m.Msg) //判断系统消息的 ID 号
{
case 513:
MessageBox.Show("单击了鼠标左键!", "系统信息");
m.Result = (IntPtr)0; //为了响应消息处理而向 Windows 返回的值
break;
case 516:
MessageBox.Show("单击了鼠标右键!", "系统信息");
m.Result = (IntPtr)0; //为了响应消息处理而向 Windows 返回的值
break;
default:
base.WndProc(ref m);
break;
} }
//方法二,实现 IMessageFilter 接口,从而获得 Windows 消息,与方法一不可同时存在 public class MessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message message) //实现 PreFilterMessage 方法 {
switch (message.Msg) //判断系统消息的 ID 号
{
case 513:
MessageBox.Show("单击了鼠标左键!", "系统信息");
return true;
case 516:
MessageBox.Show("单击了鼠标右键!", "系统信息");
return true;
default:
return false;
} } }
心法领悟 007:如何使用递归法删除文件夹中所有文件?
使用递归法删除文件夹中所有文件时,首先需要生成 DirectoryInfo 类的一个对象,以指定文件夹,然后生 成一个 FileSystemInfo 类型的数组,用来记录指定文件夹中的所有目录及子目录,最后,循环访问 FileSystemInfo 类型数组中的文件,并调用 FileInfo 对象的 Delete 方法将其一一删除。
1.2 鼠标基本设置
鼠标的指针形状有很多种,如人们经常看到的“小箭头”形状、单击超链接 时的“小手”形状等,那么如何在程序中自定义鼠标的指针形状呢?本实例实现 了该功能。运行本实例,将鼠标移动到“鼠标放在这”文本框上方,鼠标指针会 呈现“小手”形状。实例运行效果如图 1.8 所示。
本实例实现时主要用到了 Label 控件的 Cursor 属性,下面对其进行详细介绍。
Label 控件的 Cursor 属性用来获取或设置当鼠标指针位于控件上时显示的光标,其语法格式如下:
public virtual Cursor Cursor { get; set; }
参数说明
属性值:一个 Cursor,表示当鼠标指针位于控件上时显示的光标。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 SetMouseShape。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 Label 控件,用来在其上方改 图 1.8 定义鼠标指针形状
变鼠标的指针形状。
(3)程序主要代码如下:
private void Form1_Load(object sender, EventArgs e) {
this.labCur .Cursor =Cursors.Hand; //定义鼠标形状
}
心法领悟 008:如何更改文件扩展名?
更改文件扩展名时,首先需要生成 FileInfo 类的一个对象,以指定要更改的文件,然后调用该对象的 MoveTo 方法实现文件扩展名的更改操作。更改文件扩展名的代码如下:
FileInfo FInfo = new FileInfo(textBox1.Text);
string strPath = textBox1.Text.Substring(0,textBox1.Text.LastIndexOf(".")+1)+textBox3.Text.Trim();
FInfo.MoveTo(strPath);
用户在使用鼠标时,为了使鼠标更加美观,可以自定义鼠标的图片,本实例 将介绍如何使用 C#实现自定义鼠标图片的功能。运行本实例,单击“Click Me 改变鼠标图片”按钮,即可将鼠标图片设置为指定的图片。实例运行效果如图 1.9 所示。
本实例实现时主要用到了 Form 类的 Cursor 属性,下面对其进行详细介绍。
Form 类的 Cursor 属性用来获取或设置当鼠标指针位于窗体上时显示的光标,其语法格式如下:
public virtual Cursor Cursor { get; set; }
参数说明
属性值:一个 Cursor,表示当鼠标指针位于窗体上时显示的光标。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 SetMouseImage。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 Button 控件,用来执行自定义 鼠标图片操作。
(3)程序主要代码如下:
private void btnClickMe_Click(object sender, EventArgs e) {
this.Cursor = new Cursor("pen_il.cur"); //改变鼠标图片 }
心法领悟 009:如何实现复制文件?
复制文件时,首先需要生成 FileInfo 类的一个对象,以指定要复制的文件,然后调用该对象的 MoveTo 方法 将指定文件复制到指定路径下。实现复制文件的代码如下:
FileInfo FInfo = new FileInfo(textBox1.Text);
if (FInfo.Exists) {
FInfo.MoveTo(textBox2.Text + textBox1.Text.Substring(textBox1.Text.LastIndexOf("\\") + 1, (textBox1.Text.Length - textBox1.Text.LastIndexOf 图 1.9 自定义鼠标的图片
("\\") - 1)));
}
人们在电脑中使用的鼠标样式,一般都是系统默认的,为了使自己的电脑更具 有特色,用户可以自己设置鼠标样式。本实例将对改变 C#窗体和系统鼠标样式进 行详细讲解,实例运行效果如图 1.10 所示。
本实例实现时,主要使用 API 函数 LoadCursorFromFile、IntLoadCursorFromFile
和 SetSystemCursor 来改变系统的鼠标样式。下面对本实例中用到的关键技术进行详细讲解。
(1)API 函数 LoadCursorFromFile
该函数是在一个指针文件或一个动画指针文件(扩展名分别是.cur 和.ani)的基础上创建一个指针,其声明 语法如下:
[DllImport("user32.dll")]
public static extern IntPtr LoadCursorFromFile(string fileName);
参数说明
fileName:string 类型,包含指针的文件的名字。
(2)API 函数 IntLoadCursorFromFile
该函数将要修改的鼠标图片存入到指定目录下,其声明语法如下:
[DllImport("user32", EntryPoint = "LoadCursorFromFile")]
public static extern int IntLoadCursorFromFile(string lpFileName);
参数说明
lpFileName:文件路径。
(3)API 函数 SetSystemCursor
该函数用于改变任何一个标准系统指针,其声明语法如下:
[DllImport("user32", EntryPoint = "SetSystemCursor")]
public static extern void SetSystemCursor(int hcur, int id);
参数说明
hcur:光标的句柄,该函数 hcur 标识的光标的内容代替 id 定义的系统光标内容。系统通过调用 DestroyCursor 函数销毁 hcur,因此 hcur 不能是由 LoadCursor 函数载入的光标。要指定一个从资源载入的光标,先用 CopyCursor 函数复制该光标,然后把该副本传送给 SetSystemCursor 函数。
id:指定由 hcur 的内容替换系统光标,常用的系统光标标识符及说明如表 1.3 所示。
表 1.3 常用的系统光标标识符及说明
标 识 符 值 说 明
OCR_APPSTARTING 32650 标准箭头和小的沙漏
OCR_NORAAC 32512 标准箭头
OCR_CROSS 32515 交叉十字线光标
OCR_HAND 32649 手的形状(Windows NT 5.0 和以后版本)
OCR_IBEAM 32513 Ⅰ形
OCR_NO 32648 斜的圆
OCR_SIZEALL 32646 4 个方位的箭头分别指向北、南、东、西
图 1.10 自定义动画鼠标
续表
标 识 符 值 说 明
OCR_SIZENS 32645 双箭头,分别指向北和南
OCR_SIZENWSE 32642 双箭头,分别指向西北和东南
OCR_SIZEWE 32644 双箭头,分别指向西和东
OCR_UP 32516 垂直箭头
OCR_WAIT 32514 沙漏
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 SetAnimateMouse。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 MenuStrip 控件,用来作为窗 体的菜单栏。
(3)程序主要代码如下。
在 ToolS_From 项的 Click 事件中,设置当前鼠标指针位于窗体时显示自定义的鼠标图标,代码如下:
private void ToolS_From_Click(object sender, EventArgs e) {
Cursor myCursor = new Cursor(Cursor.Current.Handle); //创建 Cursor 类 IntPtr colorCursorHandle = LoadCursorFromFile("0081.ani"); //鼠标图标路径
myCursor.GetType().InvokeMember("handle", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null,
myCursor, new object[] { colorCursorHandle }); //获取鼠标
this.Cursor = myCursor; //设置当前鼠标指针位于窗体时显示的光标
}
在 ToolS_FromRevert 项的 Click 事件中,恢复当前鼠标指针位于窗体时的鼠标图标,代码如下:
private void ToolS_FromRevert_Click(object sender, EventArgs e) {
this.Cursor = Cursors.Default;
}
在 ToolS_System 项的 Click 事件中,用自定义鼠标图标设置系统鼠标的正常选择鼠标、移动鼠标、不可用 鼠标和超链接鼠标,代码如下:
private void ToolS_System_Click(object sender, EventArgs e) {
int cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\01.cur"); //设置正常选择鼠标 SetSystemCursor(cur, OCR_NORAAC);
cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\03.cur"); //设置移动鼠标 SetSystemCursor(cur, OCR_SIZEALL);
cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\04.cur"); //设置不可用鼠标 SetSystemCursor(cur, OCR_NO);
cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\06.cur"); //设置超链接鼠标 SetSystemCursor(cur, OCR_HAND);
}
注意:当用自定义鼠标图标设置鼠标时,应将其图标放置在系统盘的 WINDOWS\Cursors 目录下,否则 API 函数 IntLoadCursorFromFile 无法在指定文件的基础上创建一个指针。在 ToolS_SystemRevert 项的 Click 事件中,恢复系统鼠标的正常选择鼠标、移动鼠标、不可用鼠标和超链 接鼠标,代码如下:
private void ToolS_SystemRevert_Click(object sender, EventArgs e) {
int cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\arrow_m.cur"); //恢复正常选择鼠标 SetSystemCursor(cur, OCR_NORAAC);
cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\move_r.cur"); //恢复移动鼠标 SetSystemCursor(cur, OCR_SIZEALL);
cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\no_r.cur"); //恢复不可用鼠标 SetSystemCursor(cur, OCR_NO);
cur = IntLoadCursorFromFile(@"C:\WINDOWS\Cursors\hand.cur"); //恢复超链接鼠标 SetSystemCursor(cur, OCR_HAND);
}
心法领悟 010:如何修改文件名?
修改文件名称时,需要调用 FileInfo 类的 MoveTo 方法实现,代码如下:
FileInfo FInfo = new FileInfo(textBox1.Text);
string strPath = textBox1.Text.Substring(0, textBox1.Text.LastIndexOf("\\") + 1) + textBox2.Text + "." + textBox3.Text;
FInfo.MoveTo(strPath);
当用户双击“控制面板”/“鼠标”时,会弹出“鼠标属性”对话框,在该 对话框中可以对鼠标进行相关设置。本实例将根据“鼠标属性”对话框开发一 个程序,用来控制鼠标左右键的切换,实例运行效果如图 1.11 所示。
本实例实现时主要用到了 API 函数 SwapMouseButton,下面对其进行详细介绍。
SwapMouseButton 函数主要用来决定是否互换鼠标左右键的功能,其声明语法如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SwapMouseButton")]
public extern static int SwapMouseButton(int bSwap); //重写 API 函数
参数说明
bSwap:如果为非零,则互换两个鼠标按键的功能,否则恢复正常状态。
返回值:非零表示鼠标按键的功能在调用该函数之前已经互换,否则返回零。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 ChangeRLKey。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加两个 Button 控件,分别用来执行交 换鼠标左右键和恢复鼠标默认设置操作。
(3)程序主要代码如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SwapMouseButton")]
public extern static int SwapMouseButton(int bSwap); //重写 API 函数 public void DefaultRightButton()
{
SwapMouseButton(1); //鼠标右键
}
public void DefaultLeftButton() {
SwapMouseButton(0); //鼠标左键
}
private void btnChange_Click(object sender, EventArgs e) {
this.DefaultRightButton(); //交换鼠标左右键
}
private void btnReset_Click(object sender, EventArgs e) {
this.DefaultLeftButton(); //恢复默认设置
}
心法领悟 011:如何删除文件?
删除文件时,需要用到 FileInfo 类的 Delete 方法,该方法用来永久删除文件。删除文件的代码如下:
图 1.11 交换鼠标左右键功能
FileInfo FInfo = new FileInfo(textBox1.Text);
FInfo.Delete();
鼠标是一个用于操作计算机的外部输入设备,在屏幕中,用一个具有 特殊形状的图标来表示当前鼠标。鼠标的移动范围是整个屏幕,用它可以 向任意窗口发送指令,但是一些恶意软件故意改变鼠标移动的区域,将它 固定在某个范围内,而这项技术也可以应用在普通的应用软件中。本实例 使用 C#实现了一个限制鼠标活动区域的功能,实例运行效果如图 1.12 所示。
本实例实现限制鼠标在某一区域工作的功能时,主要用到了 Cursor 类中的相关属性。下面对 Cursor 类进行 详细介绍。
Cursor 类表示用于绘制鼠标指针的图像,该类的常用属性及说明如表 1.4 所示。
表 1.4 Cursor 类的常用属性及说明
属 性 说 明
Clip 获取或设置表示光标的剪辑矩形的边界
Current 获取或设置代表鼠标光标的光标对象
Handle 获取光标句柄
Position 获取或设置光标位置
Size 获取光标对象的大小
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 ControlMouseRange。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加两个 Button 控件,分别用来执行限 制和解除鼠标活动区域的操作。
(3)程序主要代码如下:
private void button1_Click(object sender, EventArgs e) //限制鼠标活动区域 {
this.Cursor = new Cursor(Cursor.Current.Handle); //创建 Cursor 对象 Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y); //设置鼠标位置 Cursor.Clip = new Rectangle(this.Location, this.Size); //设置鼠标的活动区域 }
private void button2_Click(object sender, EventArgs e) //解除对鼠标活动区域的限制 {
Screen[] screens = Screen.AllScreens; //获取显示的数组
this.Cursor = new Cursor(Cursor.Current.Handle); //创建 Cursor 对象
Cursor.Clip = screens[0].Bounds; //解除对鼠标活动区域的限制
}
心法领悟 012:如何拖放文件?
将所选的文件拖放到窗体中的实现代码如下:
private void Form1_Load(object sender, EventArgs e) {
图 1.12 限制鼠标在某一区域工作
this.AllowDrop = true; //设置窗体为允许拖放 }
private void Form1_DragEnter(object sender, DragEventArgs e) {
if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
for (int i = 0; i < files.Length; i++) //将拖放入窗体的文件的文件名加入 ListBox {
listBox1.Items.Add(files[i]);
} } }
当平时上网遇到好的帖子并对其进行复制操作时,往往会出现单击鼠 标右键无效的情况,这样将直接导致无法进行复制,这种做法虽然限制浏 览者的权限,但它保护了文章作者的合法权益,因此被广泛采纳。本实例 将详细讲解如何屏蔽鼠标按键,实例运行效果如图 1.13 所示。
本实例实现时主要用到了钩子的安装及释放技术、系统热键的解除屏 蔽技术,下面对本实例中用到的关键技术进行详细讲解。
(1)钩子的安装及释放技术
Hook(钩子)函数是 Windows 提供的一种消息处理机制,是指在程序正常运行过程中接收信息之前预先启 动的函数,它主要用来检查和修改传递给本程序的 Windows 消息,钩子实际上是一个处理消息的程序段。通过 系统调用,将其挂入系统,每当发出特定消息时,在没有到达窗口前,钩子程序就先捕获该消息,对截获的消 息进行处理,还可以强制结束消息的传递。
钩子的安装用到 API 函数 SetWindowsHookEx,其语法格式如下:
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int SetWindowsHookEx(int HookType, HOOKPROCEDURE methodAddress, IntPtr handler, int dwThreadId);
SetWindowsHookEx 函数中的参数及说明如表 1.5 所示。
表 1.5 SetWindowsHookEx 函数中的参数及说明
参 数 说 明
HookType 表示钩子类型,钩子与消息类型相对应
methodAddress 表示钩子函数入口地址
handler 表示钩子所在实例的句柄
dwThreadId 表示钩子监视的线程号
钩子的释放用到 API 函数 UnhookWindowsHookEx,其语法格式如下:
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr idHook);
参数说明
idHook:表示将要卸载的句柄。
本实例中为了实现对鼠标按键的屏蔽,需要进行钩子的安装,代码如下:
public bool StartHook() //自定义安装钩子方法
{
图 1.13 屏蔽鼠标按键
IntPtr InstallHook = (IntPtr)(4194304); //定义安装钩子的句柄
if (this.mouseHandler == IntPtr.Zero) //判断 mouseHandler 的值是否为 0
{
this.m_MouseHookProcedure = new HOOKPROCEDURE(MouseHookProcedure); //创建钩子函数地址 //安装钩子函数
this.mouseHandler = (IntPtr)SetWindowsHookEx(WH_MOUSE_LL, m_MouseHookProcedure, InstallHook, 0);
if (this.mouseHandler == IntPtr.Zero) //判断 mouseHandler 的值是否为 0
{
this.UnInstallHook(); //释放钩子
return false; //创建失败
} }
return true; //创建成功
}
钩子使用完毕,需要对它进行释放,否则,将造成不必要的麻烦,代码如下:
public bool UnInstallHook() //自定义卸载钩子函数方法
{
bool Result = true; //定义一个 bool 型的标识变量
if (this.mouseHandler != IntPtr.Zero) //当 mouseHandler 的值不为 0 时
{
Result = (UnhookWindowsHookEx(this.mouseHandler) && Result); //获取是否进行卸载
this.mouseHandler = IntPtr.Zero; //重新定义 mouseHandler
}
return Result; //返回该标识变量
}
(2)系统热键的解除屏蔽技术
与钩子类似,系统热键的使用也需要安装和卸载。安装时用到 API 函数 RegisterHotKey,其语法格式如下:
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(IntPtr Hwnd, int Id, KeyModifiers keyModifiers, Keys key);
RegisterHotKey 函数中的参数及说明如表 1.6 所示。
表 1.6 RegisterHotKey 函数中的参数及说明
参 数 说 明
Hwnd 表示要定义热键窗口的句柄
Id 表示所定义热键的 ID
keyModifiers 表示热键是否在按下所定义的按键之后才会生效
key 表示定义热键的内容
卸载时用到 API 函数 UnregisterHotKey,其语法格式如下:
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr Hwnd, int Id);
参数说明
Hwnd:表示将要释放的热键的句柄。
Id:表示将要释放的热键的 ID。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 NullificationMouse。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 TextBox 控件,用来显示解除 屏蔽操作快捷键的提示;添加 3 个 CheckBox 控件,分别用来标识是否屏蔽左键、右键和滑轮;添加一个 Button 控件,用来执行屏蔽鼠标按键操作。
(3)程序主要代码如下。
本实例用到自定义类 MouseHook,在自定义类内部首先定义程序中要使用的全局对象及变量,代码如下:
public const int WH_MOUSE_LL = 14; //定义鼠标左键的键值
public const int WM_MOUSEMOVE = 0x200; //定义鼠标移动对应的键值
public const int WM_LBUTTONDOWN = 0x201; //定义按下鼠标左键对应的键值
public const int WM_RBUTTONDOWN = 0x204; //定义按下鼠标右键对应的键值
public const int WM_MBUTTONDOWN = 0x207; //定义按下鼠标滑轮对应的键值
public const int WM_LBUTTONUP = 0x202; //定义松开鼠标左键对应的键值
public const int WM_RBUTTONUP = 0x205; //定义松开鼠标右键对应的键值
public const int WM_MBUTTONUP = 0x208; //定义松开鼠标滑轮对应的键值
public const int WM_LBUTTONDBLCLK = 0x203; //定义双击鼠标左键对应的键值
public const int WM_RBUTTONDBLCLK = 0x206; //定义双击鼠标右键对应的键值
public const int WM_MBUTTONDBLCLK = 0x209; //定义双击鼠标滑轮对应的键值
public const int WM_MOUSEWHEEL = 0x020A; //定义鼠标滑轮对应的键值
public IntPtr mouseHandler = IntPtr.Zero; //定义处理鼠标事件的句柄
public event MouseEventHandler MouseDown; //定义鼠标按下事件
public static int flag = 0; //该变量标识屏蔽项
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
//声明一个钩子函数
public static extern int SetWindowsHookEx(int HookType, HOOKPROCEDURE methodAddress, IntPtr handler, int dwThreadId);
//释放钩子函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr idHook);
//声明钩子函数地址
public delegate int HOOKPROCEDURE(int nCode, Int32 wParam, IntPtr IParam);
private HOOKPROCEDURE m_MouseHookProcedure;
//定义使用户可以控制类或结构的数据字段的物理布局 [StructLayout(LayoutKind.Sequential)]
protected class MouseHookStruct {
public POINT pt;
public int mouseData;
public int flags;
public int time;
public int dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
protected class POINT {
public int x;
public int y;
}
当钩子捕获消息后,要对消息进行处理,需调用 MouseHookProcedure 方法,代码如下:
//自定义的消息处理函数
private int MouseHookProcedure(int nCode, Int32 wParam, IntPtr IParam) {
if (nCode >= 0 && MouseDown != null) //判断是否处理该消息以及是否有鼠标按键被按下
{
//定义一个结构体实例
MouseHookStruct mouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(IParam, typeof(MouseHookStruct));
MouseButtons button = GetButton(wParam); //获取鼠标的按键类型
short mouseDelta = 0; //定义一个标识滑轮转动次数的变量
switch (wParam) //判断消息类型
{
//当按下的是鼠标左键时 case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONUP:button = MouseButtons.Left;
if (Form1.flagL == true) //判断屏蔽类型中“左键”是否被选中
flag = 1; //屏蔽鼠标左键
else
flag = 0; //不进行屏蔽
break;
//当按下的是鼠标右键时 case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK :
case WM_RBUTTONUP: button = MouseButtons.Right;
if (Form1.flagR == true) //判断屏蔽类型中“右键”是否被选中
flag = 1; //屏蔽鼠标右键
else
flag = 0; //不进行屏蔽
break;
//当按下的是鼠标滑轮时
case WM_MOUSEWHEEL: mouseDelta = (short)((mouseHookStruct.mouseData >> 16) & 0xffff);
if (Form1.flagM == true) //判断屏蔽类型中“滑轮”是否被选中
flag = 1; //屏蔽鼠标滑轮
else
flag = 0; //不进行屏蔽
break;
case WM_MOUSEMOVE: flag = 0; //当鼠标处于移动状态时
break;
}
int clickCount = 0; //定义一个标识鼠标单击次数的整型变量
//判断传递消息表示的鼠标单击次数
if (wParam == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDBLCLK)
clickCount = 2; //表示双击
else
clickCount = 1; //表示单击
//定义一个为鼠标事件提供数据的实例
System.Windows.Forms.MouseEventArgs e = new System.Windows.Forms.MouseEventArgs(button ,clickCount ,mouseHookStruct.pt.x , mouseHookStruct.pt.y ,mouseDelta );
MouseDown (this, e); //触发该事件
}
return flag; //返回屏蔽标识
}
鼠标按键被按下后,钩子都要判断按键类型,需要用到 GetButton 方法,代码如下:
private MouseButtons GetButton(Int32 wParam) //自定义判断鼠标按键类型方法
{
switch (wParam) //判断消息类型
{
case WM_LBUTTONDBLCLK: //双击鼠标左键
case WM_LBUTTONDOWN: //按下鼠标左键
case WM_LBUTTONUP: //松开鼠标左键
return MouseButtons.Left; //返回按下的键是鼠标左键
case WM_RBUTTONDBLCLK: //双击鼠标右键
case WM_RBUTTONDOWN: //按下鼠标右键
case WM_RBUTTONUP: //松开鼠标右键
return MouseButtons.Right; //返回按下的键是鼠标右键
case WM_MBUTTONDBLCLK: //双击鼠标滑轮
case WM_MBUTTONDOWN: //按下鼠标滑轮
case WM_MBUTTONUP: //松开鼠标滑轮
return MouseButtons.Middle; //返回按下的键是鼠标中键
default:
return MouseButtons.None; //默认情况无按键被按下
} }
前面详细描述了自定义类的内容,下面将进入 Form1 窗体。首先,声明本实例所需要的变量,代码如下:
MouseHook mouseHook = new MouseHook(); //定义自定义类的实例
[DllImport("user32.dll", SetLastError = true)] //设置系统热键用到的声明
public static extern bool RegisterHotKey(IntPtr Hwnd, int Id, KeyModifiers keyModifiers, Keys key); //启动系统热键 [DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr Hwnd, int Id); //释放系统热键 [Flags()]
public enum KeyModifiers //定义一个位域保存一些按键的键值
{
None = 0, Alt = 1, Control = 2, }
public static bool flagL = false; //鼠标左键的屏蔽标识
public static bool flagR = false; //鼠标右键的屏蔽标识
public static bool flagM = false; //鼠标滑轮的屏蔽标识
选中“屏蔽类型”栏中的复选框后,单击“确定”按钮进行屏蔽,代码如下:
private void button1_Click(object sender, EventArgs e) {
mouseHook.StartHook(); //启动钩子
mouseHook.MouseDown += new MouseEventHandler(Mouse_Down); //调用钩子后获取鼠标的按下事件 }
在进行屏蔽操作时,传递鼠标的按键消息,用到 Mouse_Down 方法和 AddMouseValueEvent 方法,代码如下:
void Mouse_Down(object sender, MouseEventArgs e) {
AddMouseValueEvent(e.Button.ToString()); //添加鼠标事件
}
public void AddMouseValueEvent(string MouseValue) {
//此方法仅作传递,没有方法体 }
设置系统热键时,在 Form1_Load 事件中开启热键,代码如下:
private void Form1_Load(object sender, EventArgs e) {
Clipboard.Clear(); //清空剪贴板中的内容
RegisterHotKey(Handle, 100, 0, Keys.F10); //启动系统热键
flagL = false;
flagR = false;
flagM = false;
}
系统热键使用完成后,在 Form1_FormClosing 事件中关闭热键,代码如下:
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
UnregisterHotKey(Handle, 100); //卸载系统热键
}
系统热键开启后,需要对操作进行处理,该处理函数为 WndProc,代码如下:
protected override void WndProc(ref Message m) {
const int WM_Key = 0x312; //初始化热键对应的键值
switch (m.Msg) //判断消息类型
{
case WM_Key: //当按下设置的热键时
mouseHook.UnInstallHook(); //释放钩子
break;
}
base.WndProc(ref m);
}
通过 CheckBox 控件的状态决定屏蔽鼠标按键类型,当 CheckBox 处于选定状态时,通过标识将选定的信息 传递给钩子处理函数,由钩子的处理函数决定是否进行屏蔽。代码如下:
private void checkBox1_Click(object sender, EventArgs e) {
if (checkBox1.Checked == false) //当“左键”复选框未被选中时
flagL = false ; //标识屏蔽左键的变量为假
else
flagL = true; //标识屏蔽左键的变量为真
}
private void checkBox3_Click(object sender, EventArgs e) {
if (checkBox3.Checked == false) //当“右键”复选框未被选中时
flagR = false; //标识屏蔽右键的变量为假
else
flagR = true; //标识屏蔽右键的变量为真
}
private void checkBox2_Click(object sender, EventArgs e) {
if (checkBox2.Checked == false) //当“滑轮”复选框未被选中时
flagM = false; //标识屏蔽滑轮的变量为假
else
flagM = true; //标识屏蔽滑轮的变量为真
}
心法领悟 013:如何创建文件夹?
创建文件夹时,需要用到 DirectoryInfo 类的 Create 方法,代码如下:
DirectoryInfo DInfo = new DirectoryInfo(textBox1.Text+textBox2.Text);
DInfo.Create();
当用户双击“控制面板”/“鼠标”时,会弹出“鼠标属性”对话框,
在该对话框中可以对鼠标进行相关设置。本实例将根据“鼠标属性”对话 框制作一个鼠标设置器,它可以对鼠标左右键的切换、鼠标的双击速度和 移动速度进行显示或设置,实例运行效果如图 1.14 所示。
本实例主要是用 API 函数 SwapMouseButton、SystemParametersInfo、
GetSystemMetrics、SetDoubleClickTime 和 GetDoubleClickTime 对鼠标的 属性进行设置,下面对其进行详细说明。
(1)API 函数 SwapMouseButton
该函数用于决定是否互换鼠标左右键,其声明语法如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SwapMouseButton")]
public extern static int SwapMouseButton(int bSwap);
参数说明
bSwap:如果为 true(非零),则互换两个鼠标按键的功能;否则,恢复正常状态。
返回值:true(非零)表示鼠标按键的功能在调用该函数之前已经互换,否则返回零。
(2)API 函数 SystemParametersInfo
该函数用于获取和设置数量众多的 Windows 系统参数,其声明语法如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref int pvParam, uint fWinIni);
参数说明
uiAction:指定要设置的参数,其常用常数及说明如表 1.7 所示。
表 1.7 uiAction 参数的常用常数及说明
常 数 值 说 明
SPI_GETMOUSESPEED 112 检索当前鼠标速度。该变量接收 1(最慢)~20(最快)之间的数值。默认值为 10 SPI_SETMOUSE 4 是一个三元素整数数组的头一个条目,其中包含了鼠标设置
uiParam:如果安装了 Windows Extenson,那么该函数返回 true(非零),否则为 false(零)。
pvParam:按引用调用的 int、long 和数据结构。
fWinIni:取决于不同的参数及操作系统,随同这个函数设置的用户配置参数保存在 win.ini 或注册表中,
或同时保存在这两个地方。该参数规定,在设置系统参数时是否应更新用户设置参数。可以是零(禁止更新),
或者应用表 1.8 中的常数。
表 1.8 fWinIni 参数的常数及说明
常 数 值 说 明
SPIF_SENDWININICHANGE 0x0002 若设置 SPIF_UPDATEINIFILE,将一条 WM_WININICHANGE 消息发给所有 应用程序;否则,没有作用。该消息告诉应用程序已经改变用户配置设置 SPIF_UPDATEINIFILE 0x0001 用于更新 win.ini 和(或)注册表中的用户配置文件
图 1.14 鼠标设置器
返回值:int 类型,非零表示成功,零表示失败。
(3)API 函数 GetSystemMetrics
该函数主要用来返回与 Windows 环境有关的信息,其声明语法如下:
[System.Runtime.InteropServices.DllImport("user32.dll")]
public extern static int GetSystemMetrics(int nIndes);
参数说明
nIndes:int 类型,常数,指定欲获取的信息,其常数及说明如表 1.9 所示。
返回值:int 类型,取决于具体的常数索引。
表 1.9 nIndes 参数的常数及说明
常 数 值 说 明
SM_SWAPBUTTON 23 如果左右鼠标键已经交换,则为 true
SM_CXCURSOR 36 标准指针大小
SM_MOUSEPRESENT 19 如安装鼠标则为 true
SM_MOUSEWHEELPRESENT 75 如安装带轮鼠标则为 true,只适用于 nt 4.0
(4)API 函数 SetDoubleClickTime
该函数用于设置连续两次鼠标单击之间能使系统认为是双击事件的间隔时间,其声明语法如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetDoubleClickTime")]
public extern static int SetDoubleClickTime(int wCount);
参数说明
wCount:int 类型,新的 DoubleClick 间隔时间,以毫秒为单位。
返回值:int 类型,非零表示成功,零表示失败。
(5)API 函数 GetDoubleClickTime
该函数用于获取判断连续两次鼠标单击之间会被处理成双击事件的间隔时间,其声明语法如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "GetDoubleClickTime")]
public extern static int GetDoubleClickTime();
参数说明
返回值:int 类型,以毫秒表示的双击时间。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 SetMouse。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 CheckBox 控件,用来对鼠标 左右键的切换进行设置;添加两个 TrackBar 控件,分别用来显示并设置鼠标的双击速度和移动速度。
(3)程序主要代码如下。
在 Frm_Main 窗体的“代码编辑”窗口中定义常数,代码如下:
const int SM_SWAPBUTTON = 23; //如左右鼠标键已经交换,则为 true
const int SPI_SETMOUSE = 4; //设置鼠标的移动速度
const int SPI_GETMOUSESPEED = 112; //检索当前鼠标速度
const uint SPIF_UPDATEINIFILE = 0x0001; //更新 win.ini 和(或)注册表中的用户配置文件
const uint SPIF_SENDWININICHANGE = 0x0002; //该消息告诉应用程序已经改变了用户配置设置
在 Frm_Main 窗体的加载事件中,获取鼠标左右键哪个是主键,以及鼠标的双击速度和移动速度,并对其 进行显示。代码如下:
private void Form1_Load(object sender, EventArgs e) {
if (GetSystemMetrics(SM_SWAPBUTTON) == 0) //如果鼠标的左右键没有切换
{
pictureBox1.Image = null; //清空图片
pictureBox1.Image = Properties.Resources.鼠标左键; //显示图片
checkBox1.Checked = false; //设置复选框为未选中状态
}
else //如果鼠标左右切换 {
pictureBox1.Image = null; //清空图片
pictureBox1.Image = Properties.Resources.鼠标右键; //显示图片
checkBox1.Checked = true; //设置复选框为选中状态
}
int tem_n = 0;
switch (Convert.ToInt32(DoubleClickTime_Get())) //获取鼠标的双击速度
{
case 900: tem_n = 0; break;
case 830: tem_n = 1; break;
case 760: tem_n = 2; break;
case 690: tem_n = 3; break;
case 620: tem_n = 4; break;
case 550: tem_n = 5; break;
case 480: tem_n = 6; break;
case 410: tem_n = 7; break;
case 340: tem_n = 8; break;
case 270: tem_n = 9; break;
case 200: tem_n = 10; break;
}
trackBar1.Value = tem_n; //显示鼠标的双击速度
SystemParametersInfo(SPI_GETMOUSESPEED, 0, ref aMouseinfo, 0); //获取当前鼠标的移动速度
trackBar2.Value = aMouseinfo; //显示当前鼠标的移动速度
}
自定义方法 DoubleClickTime_Get 用于获取鼠标当前的双击速度,代码如下:
public string DoubleClickTime_Get() {
return GetDoubleClickTime().ToString(); //获取鼠标的双击速度
}
在 checkBox1 控件的 MouseUp 事件中,设置鼠标的左右键切换,当该控件处于选中状态时,设置右键为主 键;否则,设置左键为主键。代码如下:
private void checkBox1_MouseUp(object sender, MouseEventArgs e) {
if (((CheckBox)sender).Checked == true) //如果为选中状态
{
pictureBox1.Image = null; //清空图片
pictureBox1.Image = Properties.Resources.鼠标右键; //显示图片
SwapMouseButton(1); //切换鼠标左右键
}
else //如果为未选中状态
{
if (((CheckBox)sender).Checked == false) {
pictureBox1.Image = null; //清空图片
pictureBox1.Image = Properties.Resources.鼠标左键; //显示图片
SwapMouseButton(0); //恢复,设置左键为主键
} } }
trackBar1 控件的 Scroll 事件,主要是在移动滑块时,根据滑块的当前位置设置鼠标的双击速度。代码如下:
private void trackBar1_Scroll(object sender, EventArgs e) {
int tem_n = 0;
switch (((TrackBar)sender).Value) //记录鼠标的双击速度
{
case 0: tem_n = 900; break;
case 1: tem_n = 830; break;
case 2: tem_n = 760; break;
case 3: tem_n = 690; break;
case 4: tem_n = 620; break;
case 5: tem_n = 550; break;
case 6: tem_n = 480; break;
case 7: tem_n = 410; break;
case 8: tem_n = 340; break;
case 9: tem_n = 270; break;
case 10: tem_n = 200; break;
}
DoubleClickTime_Set(tem_n); //设置鼠标的双击速度
}
自定义方法 DoubleClickTime_Set 主要用于设置鼠标的双击速度,代码如下:
public void DoubleClickTime_Set(int MouseDoubleClickTime) {
SetDoubleClickTime(MouseDoubleClickTime); //设置鼠标的双击速度
}
trackBar2 控件的 Scroll 事件,主要是在移动滑块时,根据滑块的当前位置设置鼠标的移动速度。代码如下:
private void trackBar2_Scroll(object sender, EventArgs e) {
aMouseinfo = trackBar2.Value; //记录鼠标的移动速度
SystemParametersInfo(SPI_SETMOUSE, 0, ref aMouseinfo, SPIF_UPDATEINIFILE); //设置鼠标的移动速度 }
心法领悟 014:如何移动文件夹?
移动文件夹时,需要用到 DirectoryInfo 类的 MoveTo 方法,代码如下:
DirectoryInfo DInfo = new DirectoryInfo(textBox1.Text);
string strPath = textBox2.Text + textBox1.Text.Substring(textBox1.Text.LastIndexOf("\\") + 1, textBox1.Text.Length - textBox1. Text.LastIndexOf("\\") - 1);
DInfo.MoveTo(strPath);
1.3 鼠标操作在实际中的应用
本实例使用 C#实现了隐藏和显示鼠标的功能。运行本实例,单击“隐藏鼠 标”按钮,即可将当前鼠标隐藏;通过 Tab 键将鼠标焦点移动到“显示鼠标”按 钮上,按下 Enter 键,即可将隐藏的鼠标显示出来。实例运行效果如图 1.15 所示。
本实例实现时主要用到了 API 函数 ShowCursor,下面对其进行详细介绍。
ShowCursor 函数主要用来控制鼠标指针的可视性,其声明语法如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "ShowCursor")]
public extern static bool ShowCursor(bool bShow); //重写 API 函数
参数说明
bShow:如果为 true,显示指针;如果为 false,则隐藏指针。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 HideMouse。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加两个 Button 控件,分别用来执行隐藏 鼠标和显示鼠标操作。
(3)程序主要代码如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "ShowCursor")]
public extern static bool ShowCursor(bool bShow); //重写 API 函数
图 1.15 隐藏和显示鼠标
private void btnHide_Click(object sender, EventArgs e) {
ShowCursor(false); //鼠标隐藏
}
private void btnShow_Click(object sender, EventArgs e) {
ShowCursor(true); //鼠标显示
}
心法领悟 015:如何修改文件夹名称?
修改文件夹名称时,需要调用 DirectoryInfo 类的 MoveTo 方法实现,代码如下:
DirectoryInfo DInfo = new DirectoryInfo(textBox1.Text);
DInfo.MoveTo(textBox1.Text.Substring(0, textBox1.Text.LastIndexOf("\\") + 1) + textBox2.Text);
开发登录窗体或者其他一些输入数据的窗体时,在一个文本框中输入内 容后,通常都需要按 Tab 键切换鼠标焦点,那么通过双击窗体能否实现类似 Tab 键的功能呢?答案是肯定的。本实例使用 C#实现了通过鼠标双击窗体时 模拟键盘 Tab 键操作的功能,实例运行效果如图 1.16 所示。
本实例实现时主要用到了 SendKeys 类的 Send 方法,下面对其进行详细 介绍。
SendKeys 类用来提供将击键发送到应用程序的方法,其 Send 方法用来向活动应用程序发送击键,该方法 的语法格式如下:
public static void Send(string keys)
参数说明
keys:要发送的击键字符串。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 MouseDoubleToTab。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加两个 TextBox 控件,分别用来通过 双击窗体在其中切换鼠标焦点。
(3)程序主要代码如下:
private void Form1_DoubleClick(object sender, EventArgs e) {
SendKeys.Send("{Tab}"); //转换为 Tab 键
}
心法领悟 016:如何遍历文件夹?
遍历文件夹时,首先要生成 DirectoryInfo 类的一个对象,以指定文件夹,然后生成一个 FileSystemInfo 类型 的数组,用来记录指定文件夹中的所有目录及子目录,最后,循环访问 FileSystemInfo 类型数组中的文件,并将 文件显示在 richTextBox 文本框中。
图 1.16 鼠标双击窗体时模拟 键盘 Tab 键操作
现在的很多软件都有一个通用的功能:使用鼠标拖放复制文本,该 功能使用户的输入更加方便快捷,那么该功能是如何实现的呢?本实例 将对使用鼠标拖放复制文本功能的实现过程进行详细讲解,实例运行效 果如图 1.17 所示。
本实例实现时主要用到了 TextBox 控件的 DoDragDrop 方法、DragEventArgs 类的 Data 属性和 Effect 属性以 及 DataObject 类的 GetData 方法,下面分别对它们进行详细讲解。
(1)TextBox 控件的 DoDragDrop 方法 该方法用来开始拖放操作,其语法格式如下:
public DragDropEffects DoDragDrop(Object data,DragDropEffects allowedEffects)
参数说明
data:要拖动的数据。
allowedEffects:DragDropEffects 枚举值之一。DragDropEffects 枚举值及说明如表 1.10 所示。
返回值:DragDropEffects 枚举的值,它表示在拖放操作期间执行的最终效果。
表 1.10 DragDropEffects 枚举值及说明
枚 举 值 说 明
None 放置目标不接收该数据
Copy 将数据复制到放置目标
Move 将拖动源中的数据移动到放置目标
Link 将拖动源中的数据链接到放置目标
Scroll 即将在放置目标中开始滚动,或当前正在滚动
All 从拖动源复制、移除数据,并将其滚动到放置目标中
(2)DragEventArgs 类的 Data 属性
DragEventArgs 类包含与所有拖放事件(DragEnter、DragLeave、DragOver 和 Drop)相关的参数,其 Data 属性用来获取一个数据对象,该对象包含与对应拖动事件关联的数据。Data 属性的语法格式如下:
public IDataObject Data { get; }
参数说明
属性值:一个数据对象,该对象包含与对应拖动事件关联的数据。
(3)DragEventArgs 类的 Effect 属性
该属性用来获取或设置目标拖放操作,其语法格式如下:
public DragDropEffects Effects { get; set; }
参数说明
属性值:DragDropEffects 枚举值之一,指定目标拖放操作。DragDropEffects 枚举值及说明如表 1.10 所示。
(4)DataObject 类的 GetData 方法
DataObject 类的 GetData 方法用来返回与所指定数据格式关联的数据,它有 3 种重载形式,本实例中用到的 重载形式如下:
public virtual Object GetData(string format)
图 1.17 使用鼠标拖放复制文本
参数说明
format:要检索的数据的格式。
返回值:与指定格式关联的数据,或为 NULL。
(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 MouseDragTxt。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加两个 TextBox 控件,分别用来输入 信息和显示拖放的信息。
(3)程序主要代码如下:
private void txt1_MouseMove(object sender, MouseEventArgs e) {
if ((e.Button & MouseButtons.Left) == MouseButtons.Left) //判断是否按下鼠标左键 {
this.Cursor = new Cursor("arrow_l.cur"); //设置鼠标样式 //拖放文本
DragDropEffects dropEffect = this.txt1.DoDragDrop(this.txt1.Text, DragDropEffects.Copy | DragDropEffects.Link);
} }
private void txt2_DragDrop(object sender, DragEventArgs e) {
txt2.Text = e.Data.GetData(DataFormats.Text).ToString(); //显示拖放文本 }
private void txt2_DragEnter(object sender, DragEventArgs e) {p
e.Effect = DragDropEffects.Copy; //设置复制操作
}
心法领悟 017:如何删除文件夹?
删除文件夹时,需要用到 DirectoryInfo 类的 Delete 方法。使用 Delete 方法删除文件夹时,首先判断文件夹 是否为空,如果为空,则删除;否则将引发 IOExecption 异常。删除文件夹的代码如下:
DirectoryInfo DInfo = new DirectoryInfo(textBox1.Text);
DInfo.Delete();
在常用的画图软件中,用户一般都可以通过鼠标在其中绘图,那么该功能 是如何实现的呢?本实例将讲解如何使用 C#实现通过拖动鼠标在窗体上绘图 的功能,实例运行效果如图 1.18 所示。
本实例实现时主要用到了 Graphics 类的 DrawLine 方法和 MouseEventArgs 类的 X 属性、Y 属性,下面分别对它们进行详细介绍。
Graphics 类中的 DrawLine 方法主要用来绘制直线,该方法为可重载方法,本 实例中用到的重载形式如下:
public void DrawLine (Pen pen,Point pt1,Point pt2)
参数说明
pen:Pen 对象,它确定线条的颜色、宽度和样式。
图 1.18 利用鼠标绘图
pt1:Point 结构,它表示要连接的第一个点。
pt2:Point 结构,它表示要连接的第二个点。
说明:关于 MouseEventArgs 类的 X 属性和 Y 属性的详细讲解,请参见实例 005 中的关键技术。(1)打开 Visual Studio 2008 开发环境,新建一个 Windows 窗体应用程序,并将其命名为 MouseToDraw。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main。
(3)程序主要代码如下:
private void Form1_MouseMove(object sender, MouseEventArgs e) {
if (lastPoint.Equals(Point.Empty)) //判断绘图开始点是否为空
{
lastPoint = new Point(e.X, e.Y); //记录鼠标当前位置
}
if (G_OnMouseDown) //开始绘图
{
Point cruuPoint = new Point(e.X, e.Y); //获取鼠标当前位置
graphics.DrawLine(pen, cruuPoint, lastPoint); //绘图 }
lastPoint = new Point(e.X, e.Y); //记录鼠标当前位置
}
private void Form1_MouseUp(object sender, MouseEventArgs e) {
G_OnMouseDown = false; //开始绘图标识设置为 false
}
private void Form1_MouseDown(object sender, MouseEventArgs e) {
G_OnMouseDown = true; //开始绘图标识设置为 true
}
心法领悟 018:如何读写内存数据流?
对内存数据流进行操作时,需要使用 MemoryStream 类。MemoryStream 类创建的流以内存作为数据存储区,
而不是磁盘或网络连接。MemoryStream 类封装以无符号字节数组形式存储的数据,该数组在创建 MemoryStream 对象时被初始化,或者创建为空数组。用户可在内存中直接访问 MemoryStream 类中封装的数据。
本实例主要使用 C#实现模拟鼠标操作的功能。运行本实例,单击“单击后鼠标将自动上移”按钮,模拟鼠 标的单击操作,使鼠标位置自动上移,并弹出信息提示框。实例运行效果如图 1.19 所示。
图 1.19 模拟鼠标操作
本实例实现时主要用到了 API 函数 mouse_event,下面对其进行详细介绍。
mouse_event 函数用于模拟鼠标的事件,其声明语法如下:
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, Int32 dwExtraInfo);
mouse_event 函数中的参数及说明如表 1.11 所示。
表 1.11 mouse_event 函数中的参数及说明
参 数 说 明
dwFlags 指定单击按钮和鼠标动作的多种情况,其相关常数如表 1.12 所示
dx
指定鼠标沿 x 轴的绝对位置或者从上次鼠标事件产生以来移动的数量,依赖于 MOOSEEVENTF_
ABSOLOTE 的设置。给出的绝对数据作为鼠标的实际 x 坐标;给出的相对数据作为移动的 mickeys 数。
一个 mickey 表示鼠标移动的数量,表明鼠标已经移动
dy 指定鼠标沿 y 轴的绝对位置或者从上次鼠标事件产生以来移动的数量,依赖于 MOOSEEVENTF_
ABSOLVTE 的设置。给出的绝对数据作为鼠标的实际 y 坐标;给出的相对数据作为移动的 mickeys 数 dwData 如果 dwFlags 为 MOOSEEVENTF_WHEEL,则 dwData 指定鼠标滑轮移动的数量。正值表明鼠标滑轮
向前转动,即远离用户的方向;负值表明鼠标滑轮向后转动,即朝向用户
dwExtraInfo 指定与鼠标事件相关的附加 32 位值。应用程序调用函数 GetMessgeExtraInfo 来获得此附加信息 表 1.12 dwFlags 参数的常数及说明
常 数 值 说 明
MOOSEEVENTF_ABSOLOTE 0x8000 表明参数 dx、dy 含有规范化的绝对坐标。如果不设置此处,参数含有相 对数据(相对于上次位置的改动位置)
MOOSEEVENTF_MOVE 0x0001 表明发生移动 M00SEEVENTF_LEFTDOWN 0x0002 表明按下鼠标左键 M00SEEVENTF_LEFTUP 0x0004 表明松开鼠标左键 MOOSEEVENTF_RIGHTDOWN 0x0008 表明按下鼠标右键 MOOSEEVENTF_RIGHTUP 0x0010 表明松开鼠标右键 MOOSEEVENTF_MIDDLEDOWN 0x0020 表明按下鼠标中键 MOOSEEVENTF_MIDDLEUP 0x0040 表明松开鼠标中键
MOOSEEVENTF_WHEEL 0x0800 在 Windows NT 中如果鼠标有一个轮,表明鼠标轮被移动,移动的数量由 dwData 给出
(1) 打开 Visual Studio 2008 开发环境,新建一个Windows 窗体应用程序,并将其命名为 SimulateOperateMouse。
(2)更改默认窗体 Form1 的 Name 属性为 Frm_Main,在该窗体中添加一个 Button 控件,用来在单击该控 件之后使鼠标自动上移。
(3)程序主要代码如下:
[DllImport("user32.dll")]
private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); //引入 API 函数 mouse_event
const int MOUSEEVENTF_MOVE = 0x0001; //表示鼠标移动
const int MOUSEEVENTF_LEFTDOWN = 0x0002; //表示鼠标左键按下
const int MOUSEEVENTF_LEFTUP = 0x0004; //表示鼠标左键松开
private void button1_Click(object sender, EventArgs e) {
mouse_event(MOUSEEVENTF_MOVE, -20, -20, 0, 0); //模拟移动鼠标
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); //第一次鼠标左键按下
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //第一次鼠标左键松开
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); //第二次鼠标左键按下
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //第二次鼠标左键松开
}