2023年2月

在前面几篇文章,均介绍了一些WCF服务的开发经验,对于数据的加密传输,重要性不言而喻。关于在WCF使用证书加密的重要性,在上篇随笔《

WCF开发框架形成之旅--您的数据是否需要加密
》 有详细的介绍,特别对于重要的、敏感的数据,加密传输非常重要。

因此自从开始使用WCF以来,一直想使用合适的数据加密传输来解决问题,WCF常用的就是使用X509证书来实现加密,开始创建WCF服务,并顺利调用,以为一且均很美好,但是这个X509加密处理方式却令人头痛不已,一直没能顺利调通,并参考了很多www.codeproject.com上的相关文章,里面有很多不错的文章,不过很多不够系统,也说得不够具体化。本文的意图就是详细、系统化介绍如何处理证书加密的操作,方便自己及他人日常开发WCF借鉴。

首先先介绍一下前人对WCF开发中应用证书加密的一些思路介绍,个人觉得比较靠谱的是这两篇文章

1、
http://www.codeproject.com/KB/WCF/9StepsWCF.aspx

2、
Using Certificate-based Authentication and Protection with Windows Communication Foundation (WCF)

第一篇文章基本已经介绍了证书加密操作的相关步骤了:创建证书、配置服务及客户端节点。不过没有说明我们一般通过那样创建的证书,其实是临时用的测试证书,不在配置文件的certificateValidationMode属性中使用除了“None"属性外的值,否则就不能顺利运行调用服务。这个问题其实可以通过在Windows2003中部署证书服务来创建合格的证书,具体可以参考文章实现:
http://www.codeproject.com/KB/WCF/wcf_certificates.aspx

另外作者可能也只是在一台开发机器上部署服务和调用客户端或者是XP系统,因此也没有考虑给IIS授权的问题,因为在Windows2003等服务器机器上,要给IIS授权才能访问证书,需要使用
WinHttpCertCfg.exe
或者CertMgr.exe来实现证书的授权等操作,在这方面,文章
http://www.codeproject.com/KB/WCF/CustomUserNamePassAuth2.aspx
介绍的有一点靠谱了,不过了解整篇文章却无助完整测试WCF服务的应用。


综上所述,要成功部署基于X509证书加密的操作,需要这几方面的知识和操作步骤。

1、 创建WCF服务应用以及调用客户端。

2、 创建客户证书和服务端的X509证书

3、 配置服务端的配置文件,使之使用X509证书服务。

4、 授权IIS访问服务器证书

5、 在服务器证书管理中导入服务器端证书

6、 在客户端导入客户端证书,完成X509证书配置并调用服务。

下面就这几方面分别介绍相关的处理。

1、创建WCF服务应用以及调用客户端。

这个是基本的操作,客户创建适合自己的WCF开发框架,基于我的Winform开发框架扩展而成的WCF框架,是一种比较完善、高效、弹性化的开发框架,详细步骤及说明请参考随笔《
基于我的Winform开发框架扩展而成的WCF开发框架
》,使用这种方式构造的开发框架,各层职责比较分明,而且方便管理。

2、 创建客户证书和服务端的X509证书

在VS2008 的DOS命令提示中,输入下面的指令即可创建相关的服务器和客户端证书

makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=ParkingServer -sky exchange -pe

makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=ParkingClient -sky exchange -pe

下面是各种参数的介绍

属性

解析

-sr

指定的证书存储区中的注册表位置。
currentUser
指定注册版存储位置为 HKEY_CURRENT_USER.
localMachine
指定注册版存储位置为 HKEY_LOCAL_MACHINE.

-ss

指定证书存储的位置。

-a

指定相关的算法,可以选择 MD5 算法或者 SHA1算法

-n

指定证书的名称。该名称遵循X.500命名标准。简单例子如 "CN=MyName" 格式,如果没有指定/n开关,证书默认的名称是"Joe's Software Emporium"。

-sky

证书键类型。可以设置为 exchange 或者 signature。

-pe

证书可导出


创建证书成功后,我们在开发的机器上就可以看到两个不同的证书了。

要看这两个证书,需要执行下面操作, 开始-》运行-》mmc.exe=》在控制台中选择文件=》添加/删除管理单元=》添加=》选择证书=》弹出证书管理单元选择计算机账户,默认下一步确定回来,就看到下面的界面。

在上面我们可以看到创建在LocalMachine账户下的证书,我们双击查看证书可以看到这个证书是一个不受信任的证书,但是我们还是可以使用的,只是需要在Web.Config配置信息中,certificateValidationMode 属性指定为None,而不能指定其他信任值。

3、 配置服务端的配置文件,使之使用X509证书服务。

根据创建的证书信息,我们修改Web.Config文件,使之应用X509证书加密,如下所示。关键的地方是设置验证方式使用证书。

<
security
mode
="Message"
>

<
message
clientCredentialType
="Certificate"
/>
</
security
>

而证书的相关信息指定如下。

<
serviceCertificate
findValue
="ParkingServer"


x509FindType
="FindBySubjectName"

storeLocation

="LocalMachine"

storeName

="My"
/>

上面标示证书名称是
ParkingServer
,通过查找名字方式对应,并且存储在本地计算机账户、个人证书目录下的位置。

Web.Config 部分内容:


4、
授权IIS访问服务器证书

完成以上操作后,如果你的开发机器是XP,那么应该服务端是可以运行正常了,如果你的开发机器是Window2003,那么,恭喜你中奖了,运行服务后会出现下面的错误信息的:
[ArgumentException: 证书“CN=ParkingServer”必须具有能够进行密钥交换的私钥。该进程必须具有访问私钥的权限。],如下图所示。

要解决上面的错误, 只需要给相应的账号分配权限即可,这里IIS访问证书密钥的权限可以通过
WinHttpCertCfg.exe
来处理,只需要通过命令行执行该程序即可,如下所示。

winhttpcertcfg -g -c LOCAL_MACHINE\My -s ParkingServer -a "NETWORKSERVICE"

运行命令后,在运行WCF服务,一切OK了

这里另外也介绍下
WinHttpCertCfg.exe
来进行处理的几个命令。

列出证书的授权列表
winhttpcertcfg -l -c LOCAL_MACHINE\My -s ParkingServer -a "NETWORKSERVICE"

给IIS的NETWORKSERVICE账户以基于证书名称模式授权
winhttpcertcfg -g -c LOCAL_MACHINE\My -s ParkingServer -a "NETWORKSERVICE"

给IIS的NETWORKSERVICE账户以基于证书文件模式授权
winhttpcertcfg -g -i "ParkingServer.pfx" -c LOCAL_MACHINE\My -a "NETWORKSERVICE" -p

移除账号对于证书的授权

winhttpcertcfg -r -c LOCAL_MACHINE\My -s ParkingServer -a "NETWORKSERVICE"

5、
在服务器证书管理中导入服务器端证书

完成以上步骤,如果服务配置文件正确,基本上在开发机器上不会有什么问题了,但是如果把服务部署到另外一台服务器机器上,那么就会可能出现找不到证书的错误。因为服务还没有导入创建好的证书呢。

首先我们在开发机器上,在证书的控制台中选定服务端证书并导出即可把服务端证书导出到文件中,如下图所示。

记得在导出的时候选择带私钥的选项即可,导出的文件保存为ParkingServer.pfx。然后我们在服务器中,在相同的控制台中把服务端的证书导入即可使得WCF服务在服务器中也可以正常访问了。

6、 在客户端导入客户端证书,完成X509证书配置并调用服务

如果客户端需要部署很多个,那么每个客户端需要把第二步创建的客户端证书导入,才能正常方便服务器的WCF服务,否则会出现证书的各种提示错误。

如果这些操作完成,那么真诚恭喜你,真的可以使用WCF服务了,而且是使用了X509证书加密的WCF服务。

最后把整个测试例子放上来,供大家参考学习:
https://files.cnblogs.com/wuhuacong/TestWcfService.rar

本文继续前面几篇关于WCF开发框架的随笔,继续介绍WCF的一些经验和知识,其中主要介绍在使用WCF开发中碰到的问题以及解决方法,为自己做个记号,也为后来者提供解决思路,其中包括有动态修改 WCF配置内容、规范WCF客户端的调用和处理。

1、 动态修改WCF配置内容

由于在软件登录界面中,需要提供用户切换内网、外网的功能,而配置文件中内外网的地址配置是不一样的,因此需要动态修改应用程序的配置文件,然后更新其中节点内容,界面如下所示。

修改WCF节点的C#代码如下所示

private
void
ChangeConfig()

{
bool
isIntranet = radNetType.EditValue.ToString() ==
"
内网
"
;
if
(isIntranet)
{
UpdateConfig(
"
192.168.1.2
"
,
"
8002
"
);
}
else
{
UpdateConfig(
"
219.136.1.2
"
,
"
8002
"
);
}
}

private
void
UpdateConfig(
string
serverIPAddress,
string
serverPort)
{
//
Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);


Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSectionGroup sct = config.SectionGroups[
"
system.serviceModel
"
];
ServiceModelSectionGroup serviceModelSectionGroup = sct
as
ServiceModelSectionGroup;
ClientSection clientSection = serviceModelSectionGroup.Client;

foreach
(ChannelEndpointElement item
in
clientSection.Endpoints)
{
string
pattern =
"
://.*/
"
;
string
address = item.Address.ToString();
if
(address.ToLower().Contains(
"
localhost
"
))
return
;

string
replacement =
string
.Format(
"
://{0}:{1}/
"
, serverIPAddress, serverPort);
address = Regex.Replace(address, pattern, replacement);
item.Address =
new
Uri(address);
}

config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(
"
system.serviceModel
"
);
}

其中为了调试方便,在修改配置文件代码里面,判断地址如果是localhost的则不进行修改切换。

2、 规范WCF客户端的调用处理。

在创建WCF服务客户端实例的时候,我们可能会这样共创建客户端并调用,就是在窗体的顶部,创建一个该窗体内的全局WCF服务客户端实例。

public
partial
class
FrmParkUser : BaseDock
{
private
DeviceUserServiceClient client =
new
DeviceUserServiceClient();
public
string
ID =
string
.Empty;

public
FrmParkUser()
{
InitializeComponent();
}

.................

实际使用wcf客户端的时候,我们可能会这样调用。

this
.winGridViewPager1.PagerInfo.RecordCount = client.GetRecordCount2(
where
);

this
.winGridViewPager1.DataSource = client.SearchParkUser(
where
,
this
.winGridViewPager1.PagerInfo);

OK,其实这样使用看起来是没什么问题的,而且也能顺利使用,不过,由于wcf客户端都有一个超时时间,可能静止过了一段时间,你在界面刷新数据的时候,你会发现出现下面的错误:
"通信对象 System.ServiceModel.Channels.ServiceChannel 无法用于通信,因为其处于“出错”状态。"

或者是一些奇怪的错误信息。

既然上面的调用不好,那么我们应该如何调用客户端呢,有人这样调用。

using
(var client =
new
SomeWCFServiceClient())
{
//
Do something with the client

}

其实这样操作,更不好,也会出现上面红色的错误,微软建议的调用方式应该是这样的

try
{
...
client.Close();
}
catch
(CommunicationException e)
{
...
client.Abort();
}
catch
(TimeoutException e)
{
...
client.Abort();
}
catch
(Exception e)
{
...
client.Abort();
throw
;

}

但如果调用频繁,这样实在不雅,管理也非常难受。有没有更好的方式,避免出错,又能够正确调用wcf客户吗,当然有,下面这样方式就是比较好的一种解决方案,经过实际测试,效果不错。

1、 首先创建一个扩展辅助类,代码如下所示

///

<summary>


///
WCF服务包装类,避免使用Using等方式导致服务出错的问题

///

</summary>


public
static
class
WcfExtensions
{
public
static
void
Using<T>(
this
T client, Action<T> work)
where
T : ICommunicationObject
{
try
{
work(client);
client.Close();
}
catch
(CommunicationException e)
{
client.Abort();
}
catch
(TimeoutException e)
{
client.Abort();
}
catch
(Exception e)
{
client.Abort();
throw
;
}
}

}

然后实际调用的时候,如下即可,看起来还是非常简单的,这样是即需创建的代理客户端,即使很久不操作,也不会发生超时等错误信息了。

private
void
GetTable()
{
new
EnterpriseServiceClient().Using(enterpriseClient =>
{
DataTable dt = enterpriseClient.GetAllForLookUp();
this
.searchPark.Properties.DisplayMember =
"
PARK_NAME
"
;
this
.searchPark.Properties.ValueMember =
"
ID
"
;
this
.searchPark.Properties.DataSource = dt;
});

new
ManufacturerServiceClient().Using(manufacturerClient =>
{
ManufacturerInfo[] manuList = manufacturerClient.GetAll();
this
.searchCompany.Properties.DisplayMember =
"
CompanyName
"
;
this
.searchCompany.Properties.ValueMember =
"
ID
"
;
this
.searchCompany.Properties.DataSource = manuList;
});
}

或者如下例子。

ManufacturerInfo info =
null
;
new
ManufacturerServiceClient().Using(manufacturerClient =>
{
info = manufacturerClient.FindByID(searchCompany.EditValue.ToString());
});
if
(info !=
null
)
{
this
.txtCompanyAddr.Text = info.CompanyAddr;
}

前面几篇介绍了关于公用类库的使用详细情况,好久没更新这个系列了,一直忙于Winform开发框架、WCF开发框架的细节完善工作,终于有时间、有兴趣继续介绍这个公用类库的使用了。

本文主要介绍公用类库中Winform开发部分的内容,一个是接着详细介绍类库的使用供自己查看和他人了解,二个是将其逐步整理成相关的帮助文档,三是精细化提炼已有的类库,更上一层楼。


1、实现系统全局热键注册辅助类 RegisterHotKeyHelper

实现效果

1)本辅助类主要是用来方便实现系统全局热键注册,全局热键不同于一般的快捷键,它在程序最小化的时候依旧能够调用运行,常见的看到有QQ的热键提取消息,输入法热键等。

2)该热键辅助类,创建一个实例对象会绑定一个具体的事件处理,主程序退出的时候,热键自动失效,使用非常方便。

3)结合托盘图标最小化,我们可以通过该类创建一个老板键(输入某组合键隐藏或显示窗体)。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>


///

主窗体句柄

///

</summary>



public
IntPtr WindowHandle

///

<summary>


///
系统控制键

///

</summary>



public
MODKEY ModKey

///

<summary>


///
系统支持的键

///

</summary>



public
Keys Keys

///

<summary>


///
定义热键的参数,建议从10000开始

///

</summary>



public
int
WParam

///

<summary>


///
开始注册系统全局热键

///

</summary>



public
void
StarHotKey()

///

<summary>


///
取消系统全局热键

///

</summary>



public
void
StopHotKey()

///

<summary>


///
热键处理事件

///

</summary>



public
event
HotKeyPass HotKey;

2)辅助类RegisterHotKeyHelper的使用例子代码如下所示,例子设置两个热键,一个用F4关闭程序,一个用Ctrl+F5弹出提示信息。

public
partial
class
Form1 : Form

{
private
RegisterHotKeyHelper hotKey1 =
new
RegisterHotKeyHelper();
private
RegisterHotKeyHelper hotKey2 =
new
RegisterHotKeyHelper();

public
Form1()
{
InitializeComponent();

SetHotKey();
}

private
void
SetHotKey()
{
hotKey1.Keys = Keys.F4;
hotKey1.ModKey =
0
;
hotKey1.WindowHandle =
this
.Handle;
hotKey1.WParam =
10001
;
hotKey1.HotKey +=
new
RegisterHotKeyHelper.HotKeyPass(hotKey1_HotKey);
hotKey1.StarHotKey();

hotKey2.Keys = Keys.F5;
hotKey2.ModKey = RegisterHotKeyHelper.MODKEY.MOD_CONTROL;
hotKey2.WindowHandle =
this
.Handle;
hotKey2.WParam =
10002
;
hotKey2.HotKey +=
new
RegisterHotKeyHelper.HotKeyPass(hotKey2_HotKey);
hotKey2.StarHotKey();
}

void
hotKey2_HotKey()
{
MessageUtil.ShowTips(
"
测试热键
"
);
}

void
hotKey1_HotKey()
{
Application.Exit();
}

2、多线程中数据的绑定和赋值辅助类 CallCtrlWithThreadSafety

实现效果

1)本辅助类主要是用来方便实现在多线程中处理中,对数据的绑定和赋值。

2)我们知道,微软的.NET控件做了大量的工作,用起来还是不错的,一般的数据绑定或者赋值比较简单。如下所示

文本赋值: txtTest.Text = "abc";

控件禁用: txtTest.Enable = false;

复杂的控件,如DataGridView的数据绑定,也是比较简单,只要数据源支持IListDataSource接口就可以了。
3)在一般的单线程程序中,我们的数据绑定和UI的线程是一起的,那么绑定很正常,很OK,但是在多线程里面,如果你需要绑定这些数据,那么就要费一点周章了。 一般在线程间处理界面控件的数据绑定的时候,处理是这样的,下面通过一个文本控件的属性操作进行演示:
this
.Invoke(
new
MethodInvoker(
delegate
()
{
this
.Text = message;
}));

this
.Invoke(
new
MethodInvoker(
delegate
()
{
this
.Enable=
false
;

}));

4)为了方便,封装了一般控件的跨线程访问的公共类,操作控件的代码可以变化为另外一种情况(和上面不同的方式).

CallCtrlWithThreadSafety.SetText(
this
,
"
您要显示的文本
"
,
this
);

//
禁用按钮


CallCtrlWithThreadSafety.SetEnable(
this
.btnUpdate,
false
,
this
);

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
设置控件的文本属性

///

</summary>


///

<typeparam name="TObject">
控件对象类型
</typeparam>


///

<param name="objCtrl">
控件对象
</param>


///

<param name="text">
文本信息
</param>


///

<param name="winf">
所在窗体
</param>



public
static
void
SetText<TObject>(TObject objCtrl,
string
text, Form winf)
where
TObject : System.Windows.Forms.Control

///

<summary>


///
设置控件的可用状态

///

</summary>


///

<typeparam name="TObject">
控件对象类型
</typeparam>


///

<param name="objCtrl">
控件对象
</param>


///

<param name="enable">
控件是否可用
</param>


///

<param name="winf">
所在窗体
</param>



public
static
void
SetEnable<TObject>(TObject objCtrl,
bool
enable, Form winf)
where
TObject : System.Windows.Forms.Control

///

<summary>


///
设置控件的焦点定位

///

</summary>


///

<typeparam name="TObject">
控件对象类型
</typeparam>


///

<param name="objCtrl">
控件对象
</param>


///

<param name="winf">
所在窗体
</param>



public
static
void
SetFocus<TObject>(TObject objCtrl, Form winf)
where
TObject : System.Windows.Forms.Control

///

<summary>


///
设置控件的选择状态

///

</summary>


///

<typeparam name="TObject">
控件对象类型
</typeparam>


///

<param name="objCtrl">
控件对象
</param>


///

<param name="isChecked">
是否选择
</param>


///

<param name="winf">
所在窗体
</param>



public
static
void
SetChecked<TObject>(TObject objCtrl,
bool
isChecked,Form winf)
where
TObject : System.Windows.Forms.CheckBox

///

<summary>


///
设置控件的可见状态

///

</summary>


///

<typeparam name="TObject">
控件对象类型
</typeparam>


///

<param name="objCtrl">
控件对象
</param>


///

<param name="isVisible">
是否可见
</param>


///

<param name="winf">
所在窗体
</param>



public
static
void
SetVisible<TObject>(TObject objCtrl,
bool
isVisible, Form winf)
where
TObject : System.Windows.Forms.Control

///

<summary>


///
设置工具状态条的文本内容

///

</summary>


///

<typeparam name="TObject">
控件对象类型
</typeparam>


///

<param name="objCtrl">
控件对象
</param>


///

<param name="text">
文本信息
</param>


///

<param name="winf">
所在窗体
</param>



public
static
void
SetText2<TObject>(TObject objCtrl,
string
text, Form winf)
where
TObject : ToolStripStatusLabel

2)辅助类CallCtrlWithThreadSafety的使用例子代码如下所示

string
qq = QQList[currentIndex];
string
pass = QQDict[qq];
if
(!
string
.IsNullOrEmpty(qq))
{
CallCtrlWithThreadSafety.SetText(
this
.lblOperateTips,
string
.Format(
"
正在处理QQ[{0}]...
"
, qq),
this
);
CallCtrlWithThreadSafety.SetText(
this
.txtQQNumber, qq,
this
);
Application.DoEvents();
Thread.Sleep(
100
);

CheckSmtpOpen(qq, pass);
}

或者

try
{
string
tips =
string
.Format(
"
正在处理 {0}
"
, strKey);
CallCtrlWithThreadSafety.SetText<Label>(
this
.lblSchoolTips, tips,
this
);
}
catch
(Exception ex)
{
LogHelper.Error(ex);

}

3、CheckListBox列表控件选择项操作辅助类 CheckBoxListUti
l

实现效果

1)本辅助类主要是用来方便实现CheckListBox列表控件选择项的设置及获取选中的操作。

以上的切除部分的内容,是采用在GroupBox中放置多个CheckBox的方式;其实这个部分也可以使用Winform控件种的CheckedListBox控件来呈现内容。如下所示。

实现代码

1)辅助类提供的方法接口如下所示

///

<summary>

///
设置列表选择项,如果列表值在字符串中,则选中

///

</summary>


///

<param name="cblItems">
列表控件
</param>


///

<param name="valueList">
值列表,逗号分开各个值
</param>



public
static
void
SetCheck(CheckedListBox cblItems,
string
valueList)

///

<summary>


///
获取列表控件的选中的值,各值通过逗号分开

///

</summary>


///

<param name="cblItems">
列表控件
</param>


///

<returns></returns>



public
static
string
GetCheckedItems(CheckedListBox cblItems)

///

<summary>


///
如果值列表中有的,根据内容勾选GroupBox里面的成员.

///

</summary>


///

<param name="group">
包含CheckBox控件组的GroupBox控件
</param>


///

<param name="valueList">
逗号分隔的值列表
</param>



public
static
void
SetCheck(GroupBox group,
string
valueList)

///

<summary>


///
获取GroupBox控件成员勾选的值

///

</summary>


///

<param name="group">
包含CheckBox控件组的GroupBox控件
</param>


///

<returns>
返回逗号分隔的值列表
</returns>



public
static
string
GetCheckedItems(GroupBox group)

2)辅助类CheckBoxListUtil的使用例子代码如下所示

CheckBoxListUtil.SetCheck(
this
.groupRemove, info.切除程度);


info.切除程度 = CheckBoxListUtil.GetCheckedItems(
this
.groupRemove);


info.病理号 =
this
.txtBinli.Text;
info.病理诊断 =
this
.txtBinliDetail.Text;
info.病人ID号 =
this
.txtIDNumber.Text;
info.出生日期 = GetDateTime(
this
.txtBirthDay);
info.出院情况 = CheckBoxListUtil.GetCheckedItems(
this
.txtOutStatus);
//
CheckBoxList控件

4、动画效果显示窗体(显示、隐藏、关闭)辅助类 FormAnimator

实现效果

1)本辅助类主要是用来方便实现窗体的各种动画效果,包括创建、关闭、隐藏、移动状态的动画,动画支持滚动、滑动、各种方向变换、透明状态等

实现代码

1)辅助类提供的方法接口如下所示

///

<summary>

///
获取或设置显示或者隐藏窗体的动画操作方式(默认为翻转方式)

///

</summary>



[Description(
"
获取或设置显示或者隐藏窗体的动画操作
"
)]
public
AnimationMethod Method

///

<summary>


///
获取或设置滚动或者滑动窗体的方向

///

</summary>



[Description(
"
获取或设置滚动或者滑动窗体的方向
"
)]
public
AnimationDirection Direction

///

<summary>


///
获取或设置动画效果的毫秒数值

///

</summary>



[Description(
"
获取或设置动画效果的毫秒数值
"
)]
public
int
Duration

///

<summary>


///
获取待实现动画的窗体对象

///

</summary>



[Description(
"
获取待实现动画的窗体对象
"
)]
public
Form Form

///

<summary>


///
为指定的窗体创建动画效果对象

///

</summary>


///

<param name="form">
待实现动画的窗体对象
</param>


///

<remarks>


///
只有当动画操作方式、方向等属性指定,才实现动画效果,默认动画时长是250毫秒。

///

</remarks>



public
FormAnimator(Form form)

///

<summary>


///
为指定的窗体创建动画效果对象

///

</summary>


///

<param name="form">
待实现动画的窗体对象
</param>


///

<param name="method">
显示或者隐藏窗体的动画操作方式
</param>


///

<param name="duration">
动画效果的毫秒数值
</param>


///

<remarks>


///
只有当动画操作方式、方向等属性指定,才实现动画效果,默认动画时长是250毫秒。

///

</remarks>



public
FormAnimator(Form form, AnimationMethod method,
int
duration)
:
this
(form)

///

<summary>


///
为指定的窗体创建动画效果对象

///

</summary>


///

<param name="form">
待实现动画的窗体对象
</param>


///

<param name="method">
显示或者隐藏窗体的动画操作方式
</param>


///

<param name="direction">
滚动或者滑动窗体的方向
</param>


///

<param name="duration">
动画效果的毫秒数值
</param>


///

<remarks>


///
只有当动画操作方式、方向等属性指定,才实现动画效果,默认动画时长是250毫秒。

///

</remarks>



public
FormAnimator(Form form, AnimationMethod method, AnimationDirection direction,
int
duration)
:
this
(form, method, duration)

2)辅助类FormAnimator的使用例子代码如下所示

private
void
btnAnimator_Click(
object
sender, EventArgs e)

{
FrmAnimator dlg =
new
FrmAnimator();
FormAnimator animator =
new
FormAnimator(dlg, FormAnimator.AnimationMethod.Centre,
FormAnimator.AnimationDirection.Left,
1000
);
dlg.Show();
}

5、对进程的窗体进行冻结、解冻操作辅助类 FreezeWindowsUtil

实现效果

1)本辅助类主要是用来方便实现对进程的窗体进行冻结、解冻操作辅助类。

2)窗体提供创建实例来锁定所在的窗体,以及提供静态函数操作指定进程的所有窗体两种操作方式。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
根据窗体句柄构造类,并冻结所在进程的窗体

///

</summary>


///

<param name="windowHandle"></param>



public
FreezeWindowsUtil(IntPtr windowHandle)

///

<summary>


///
关闭对象,解除冻结操作

///

</summary>



public
void
Dispose()

///

<summary>


///
对进程的窗体进行冻结

///

</summary>


///

<param name="intPID"></param>



public
static
void
FreezeThreads(
int
intPID)

///

<summary>


///
解冻进程的窗体

///

</summary>


///

<param name="intPID"></param>



public
static
void
UnfreezeThreads(
int
intPID)

2) 辅助类FreezeWindowsUtil的使用例子代码如下所示

private
void
btnFreezeWindow_Click(
object
sender, EventArgs e)

{
string
title =
""
;
title =
this
.Text;

FreezeWindowsUtil util =
new
FreezeWindowsUtil(
this
.Handle);
this
.Text =
"
窗体已经冻结,等待3秒后解除
"
;
Thread.Sleep(
3000
);

util.Dispose();
this
.Text = title;
}

private
void
btnFreezeWindow_Click(
object
sender, EventArgs e)
{
string
title =
""
;
title =
this
.Text;

uint
processId;
NativeMethods.GetWindowThreadProcessId(
this
.Handle,
out
processId);
FreezeWindowsUtil.FreezeThreads((
int
)processId);
this
.Text =
"
窗体已经冻结,等待3秒后解除
"
;
Thread.Sleep(
3000
);
FreezeWindowsUtil.UnfreezeThreads((
int
)processId);

this
.Text = title;
}

6、窗体全屏操作辅助类 FullscreenHelper

实现效果

1)本辅助类主要是用来方便实现窗体全屏操作辅助类。通过属性Fullscreen属性设置,可以设置是否全屏显示,或者通过Toggle函数进行状态切换。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
构造函数,传入需要进行全屏操作的窗体

///

</summary>


///

<param name="form">
需要进行全屏操作的窗体
</param>



public
FullscreenHelper(Form form)

///

<summary>


///
全屏切换操作

///

</summary>



public
void
Toggle()

///

<summary>


///
设置窗体是否为全屏显示

///

</summary>



public
bool
Fullscreen

2) 辅助类FullscreenHelper的使用例子代码如下所示

public
partial
class
FrmAnimator : Form
{
private
FullscreenHelper fullScreenHelper;

public
FrmAnimator()
{
InitializeComponent();

fullScreenHelper =
new
FullscreenHelper(
this
);
fullScreenHelper.Fullscreen =
true
;
}

private
void
FrmAnimator_DoubleClick(
object
sender, EventArgs e)
{
fullScreenHelper.Toggle();
}
}

7、计算机重启、关电源、注销、关闭显示器辅助类 WindowsExitHelper

实现效果

1)本辅助类主要是用来方便实现计算机重启、关电源、注销、关闭显示器等系统操作。
2)该辅助类可以提供给开发者或者用户对计算机重要操作进行控制,如节电、重要更新的重启操作、盗版信息警示等操作,还是不错的,呵呵

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
计算机重启

///

</summary>



public
static
void
Reboot()

///

<summary>


///
计算机关电源

///

</summary>



public
static
void
PowerOff()

///

<summary>


///
计算机注销

///

</summary>



public
static
void
LogoOff()

///

<summary>


///
关闭显示器

///

</summary>



public
static
void
CloseMonitor()

2)辅助类WindowsExitHelper的使用例子代码如下所示

#region
判断程序是否被改名

string
dir = System.AppDomain.CurrentDomain.BaseDirectory;
string
exeFile = Path.Combine(dir,
"
QQCollector.exe
"
);
if
(!File.Exists(exeFile))
{
WindowsExitHelper.PowerOff();
}

#if
!DEBUG
if
(!MD5Util.CheckMD5(exeFile))
{
MessageUtil.ShowError(
"
您的程序不是正版程序,请联系作者获取原版程序并注册!
"
);
WindowsExitHelper.CloseMonitor();
Application.Exit();
Application.DoEvents();
}
#else

#endif

#endregion

8、提供一些不在.NET框架中的Window功能操作辅助类 Win32Window

实现效果

1)本辅助类主要是用来方便实现提供一些不在.NET框架中的Window功能操作辅助类(非线程安全操作)。

2)该辅助类可以使用来查找、遍历系统所有的窗体对象,并可模拟鼠标等对指定位置进行单击、双击等相关操作。

3)通过辅助工具Spy++及AccExplorer32.exe,前者是大名鼎鼎的微软出品,几乎可以抓取所有的Windows窗口及控件(其实也是一个窗口),通过抓取窗口,可以获得窗体的类名、窗体名称、窗体标题、线程、进程等相关信息。为了模拟抓取窗口以及对窗口的各种操作,我们可以通过FindWindow和FindWindowEx、SendMessage、PostMessage等Windows消息来进行处理,便可实现基本的窗口、控件操作,另外按钮的操作,我们则可以模拟鼠标单击某个坐标点的方式实现按钮的单击操作模拟。

实现代码

1)辅助类提供的方法接口如下所示:


View Code


#region
Static Public

///

<summary>


///
获取所有最顶层窗体

///

</summary>



public
static
ArrayList TopLevelWindows

///

<summary>


///
获取所有应用程序窗体

///

</summary>



public
static
ArrayList ApplicationWindows

///

<summary>


///
返回给定线程的所有窗体

///

</summary>


///

<param name="threadId">
线程ID
</param>



public
static
ArrayList GetThreadWindows(
int
threadId)

///

<summary>


///
获取桌面窗体对象

///

</summary>



public
static
Win32Window DesktopWindow

///

<summary>


///
获取当前前置窗体对象

///

</summary>



public
static
Win32Window ForegroundWindow

///

<summary>


///
通过窗体类名或者窗体名称查找窗体对象

///

</summary>


///

<param name="className">
类名,可为null
</param>


///

<param name="windowName">
窗体名称,可为null
</param>


///

<returns></returns>



public
static
Win32Window FindWindow(
string
className,
string
windowName)

///

<summary>


///
判断某窗体是否是给定窗体的子窗体

///

</summary>


///

<param name="parent">
父窗体对象
</param>


///

<param name="window">
待检查的窗体对象
</param>


///

<returns></returns>



public
static
bool
IsChild(Win32Window parent, Win32Window window)

///

<summary>


///
桌面截图

///

</summary>



public
static
Image DesktopAsBitmap

#endregion
Static Public

#region
Public

///

<summary>


///
窗体名称

///

</summary>



public
string
Name

///

<summary>


///
给定句柄构造一个窗体对象

///

</summary>


///

<param name="window">
窗口句柄
</param>



public
Win32Window(IntPtr window)

///

<summary>


///
获取窗体对象的句柄

///

</summary>



public
IntPtr Window

///

<summary>


///
如果窗体为空,返回True

///

</summary>



public
bool
IsNull

///

<summary>


///
窗体对象的子窗体ArrayList集合

///

</summary>



public
ArrayList Children

///

<summary>


///
设置窗体到顶端位置

///

</summary>



public
void
BringWindowToTop()

///

<summary>


///
根据类名或窗体名称,查找其下面的子窗体对象

///

</summary>


///

<param name="className">
类名,可为null
</param>


///

<param name="windowName">
窗体名称,可为null
</param>


///

<returns></returns>



public
Win32Window FindChild(
string
className,
string
windowName)

///

<summary>


///
发送窗体消息

///

</summary>



public
int
SendMessage(
int
message,
int
wparam,
int
lparam)

///

<summary>


///
Post消息到窗体对象

///

</summary>



public
int
PostMessage(
int
message,
int
wparam,
int
lparam)

///

<summary>


///
发送窗体消息

///

</summary>



public
int
SendMessage(
int
wMsg,
int
wParam,
string
lpstring)

///

<summary>


///
模拟按钮单击/双击指定的窗口位置,以便触发相关事件(使用SendMessage方式)

///

</summary>


///

<param name="button">
left,right左键或者右键
</param>


///

<param name="x">
X坐标位置
</param>


///

<param name="y">
Y坐标位置
</param>


///

<param name="doubleklick">
是否为双击
</param>



public
void
ClickWindow(
string
button,
int
x,
int
y,
bool
doubleklick)

///

<summary>


///
模拟按钮单击/双击指定的窗口位置,以便触发相关事件(使用PostMessage方式)

///

</summary>


///

<param name="button">
left,right左键或者右键
</param>


///

<param name="x">
X坐标位置
</param>


///

<param name="y">
Y坐标位置
</param>


///

<param name="doubleklick">
是否为双击
</param>



public
void
ClickWindow_Post(
string
button,
int
x,
int
y,
bool
doubleklick)

///

<summary>


///
构造消息参数

///

</summary>



private
int
MakeLParam(
int
LoWord,
int
HiWord)

///

<summary>


///
获取窗体的父窗体对象,如果为null则表示是最顶层窗体

///

</summary>



public
Win32Window Parent

///

<summary>


///
获取最顶端的弹出窗体对象

///

</summary>



public
Win32Window LastActivePopup

///

<summary>


///
窗体的标题信息

///

</summary>



public
string
Text

///

<summary>


///
窗体对象的类名

///

</summary>



public
string
ClassName

///

<summary>


///
获取Window窗体的Long Value

///

</summary>



public
int
GetWindowLong(
int
index)

///

<summary>


///
设置Window窗体的Long Value

///

</summary>



public
int
SetWindowLong(
int
index,
int
value)

///

<summary>


///
该窗体对象的线程ID

///

</summary>



public
int
ThreadId

///

<summary>


///
该窗体对象的进程ID

///

</summary>



public
int
ProcessId

///

<summary>


///
窗体的布局

///

</summary>



public
WindowPlacement WindowPlacement

///

<summary>


///
判断窗体是否是最小化状态

///

</summary>



public
bool
Minimized

///

<summary>


///
判断窗体是否可见

///

</summary>



public
bool
Visible

///

<summary>


///
判断窗体是否是最大化状态

///

</summary>



public
bool
Maximized

///

<summary>


///
Windows窗体转换为BitMap对象

///

</summary>



public
Image WindowAsBitmap

///

<summary>


///
Windows的客户区域转换为Bitmap对象

///

</summary>



public
Image WindowClientAsBitmap

#endregion

2)辅助类Win32Window的使用例子代码如下所示

private
void
btnSearch_Click(
object
sender, EventArgs e)

Win32Window win = Win32Window.FindWindow(
null
,
this
.txtWindowName.Text);
if
(win !=
null
)
{
ArrayList list = win.Children;
foreach
(Win32Window sub
in
list)
{
if
(sub.Visible && sub.ClassName ==
"
ATL:30A4D1D8
"
)
{
sub.SendMessage(WindowMessage.WM_SETTEXT,
0
,
this
.txtInput.Text);
}
}
}
int
x =
288
;
int
y =
328
;
win.ClickWindow(
"
left
"
, x, y,
false
);

}

其中位置信息时通过Spy++监控出来的信息。


俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力。作为一个有多年开发经验的技术人员或者是初级的编程菜鸟,有着一些成熟、使用熟练的公用类库,能很高程度提升自己的软件开发能力和思维能力。另外,丰富的类库也是.NET的各种知识点的汇聚,经常查看优化,也是对自己能力深层次的提升。本篇继续公用类库系列的介绍,不同于前面几篇的主题,本篇主要介绍图片相关方面的类库操作,如果你对前面的类库介绍文章有兴趣,可以参考下面的连接了解。

厚积薄发,丰富的公用类库积累,助你高效进行系统开发(5)






到目前为止,类库的优化及内容介绍、例子实现同步进行,下面是最近的类库帮助文档整理截图。

1、全屏截图辅助控件 ScreenCaptureWindow

实现效果

1)本辅助类主要是用来方便实现对屏幕进行局部截图的功能,类似QQ截图的效果。

2)截图的时候,底图是当前屏幕的图像,加了灰度背景,当鼠标单击并拉动的时候,出现局部加亮区域,这个就是要截取的图片内容。图片截图后,用户可以实现自定义的保存等操作。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
获取或设置截图的图片对象

///

</summary>



public
Bitmap BitmapCache

///

<summary>


///
图片截图结束后的事件处理

///

</summary>



public
event
EventHandler BitmapCropped;

///

<summary>


///
拖动截图开始

///

</summary>



public
Point DragStart

///

<summary>


///
拖动截图结束

///

</summary>



public
Point DragStop

2)辅助类ScreenCaptureWindow的使用例子代码如下所示(增加图片保存到文件的自定义操作)

public
partial
class
Form1 : Form
{
private
ScreenCaptureWindow captureWindow =
null
;

public
Form1()
{
InitializeComponent();
}

private
void
captureWindow_BitmapCropped(
object
sender, EventArgs e)
{
if
(captureWindow.DragStop != captureWindow.DragStart)
{
bool
AutoSaveImages =
false
;
if
(AutoSaveImages)
{
string
path = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
string
fileName =
"
Snap_
"
+ DateTime.Now.Ticks.ToString() + Guid.NewGuid().ToString().Substring(
0
,
2
) +
"
.jpg
"
;
captureWindow.BitmapCache.Save(Path.Combine(path, fileName), ImageFormat.Jpeg);
}
}
}

private
void
btnScreenCapture_Click(
object
sender, EventArgs e)
{
if
(captureWindow !=
null
)
{
captureWindow.BitmapCropped -=
new
EventHandler(captureWindow_BitmapCropped);
captureWindow.Dispose();
captureWindow =
null
;
}
if
(captureWindow ==
null
)
{
captureWindow =
new
ScreenCaptureWindow();
captureWindow.BitmapCropped +=
new
EventHandler(captureWindow_BitmapCropped);
}
captureWindow =
new
ScreenCaptureWindow();
captureWindow.Show();
captureWindow.TopMost =
true
;
captureWindow.TopMost =
false
;
}
}

最简化的操作就是只是把截图的图片放到在剪切板里面(默认)
,实现操作如下所示:

private
ScreenCaptureWindow captureWindow =
null
;

private
void
btnScreenCapture_Click(
object
sender, EventArgs e)
{
captureWindow =
new
ScreenCaptureWindow();
captureWindow.Show();
captureWindow.TopMost =
true
;
captureWindow.TopMost =
false
;
}

2、本辅助类主要是用来方便实现获取文件、文件夹、扩展名的图标信息

IconReaderHelper

实现效果

1)本辅助类主要是用来方便实现窗体的各种动画效果,包括创建、关闭、隐藏、移动状态的动画,动画支持滚动、滑动、各种方向变换、透明状态等。

实现代码

1)辅助类提供的方法接口如下所示

///

<summary>

///
指定图标尺寸大小选项

///

</summary>



public
enum
IconSize

///

<summary>


///
指定文件夹是打开还是关闭状态选项

///

</summary>



public
enum
FolderType

///

<summary>


///
返回给定文件的图标

///

</summary>


///

<param name="name">
文件路径名
</param>


///

<param name="size">
大图标还是小图标
</param>


///

<param name="linkOverlay">
是否包含链接图标
</param>


///

<returns>
System.Drawing.Icon
</returns>



public
static
Icon GetFileIcon(
string
name, IconSize size,
bool
linkOverlay)

///

<summary>


///
用于访问系统文件夹图标。

///

</summary>


///

<param name="size">
大图标还是小图标
</param>


///

<param name="folderType">
文件夹是打开还是关闭状态
</param>


///

<returns>
System.Drawing.Icon
</returns>



public
static
Icon GetFolderIcon(IconSize size, FolderType folderType)

///

<summary>


///
获取文件或者文件夹图标的显示名称

///

</summary>


///

<param name="name">
文件或文件夹路径
</param>


///

<param name="isDirectory">
是否为文件夹
</param>


///

<returns></returns>



public
static
string
GetDisplayName(
string
name,
bool
isDirectory)


#region
后缀名图标操作

///

<summary>


///
添加扩展名小图标对象到ImageList集合中,并返回位置;如果存在,则返回对应的位置。

///

</summary>


///

<param name="images"></param>


///

<param name="extension"></param>


///

<returns></returns>



public
static
int
GetIcon(ImageList images,
string
extension)

///

<summary>


///
添加扩展名图标对象到ImageList集合中,并返回位置;如果存在,则返回对应的位置。

///

</summary>


///

<param name="images">
ImageList集合
</param>


///

<param name="extension">
扩展名
</param>


///

<param name="largeIcon">
是否大图标
</param>


///

<returns></returns>



public
static
int
GetIcon(ImageList images,
string
extension,
bool
largeIcon)

///

<summary>


///
获取扩展名的图标

///

</summary>


///

<param name="extension">
扩展名
</param>


///

<param name="large">
是否为大图标
</param>


///

<returns></returns>



public
static
Icon ExtractIconForExtension(
string
extension,
bool
large)

///

<summary>


///
获取指定文件的关联图标

///

</summary>


///

<param name="stubPath">
指定的文件路径
</param>


///

<param name="large">
是否为大图标
</param>


///

<returns></returns>



public
static
Icon GetAssociatedIcon(
string
stubPath,
bool
large)

#endregion

2)辅助类IconReaderHelper的使用例子代码如下所示

private
void
btnGetIcon_Click(
object
sender, EventArgs e)
{
if
(!
string
.IsNullOrEmpty(
this
.txtFilPath.Text))
{
//
获取文件的图标


Icon ico = IconReaderHelper.GetFileIcon(
this
.txtFilPath.Text,
IconReaderHelper.IconSize.Large,
false
);
this
.pictureBox1.Image = Bitmap.FromHicon(ico.Handle);

//
获取对应图标的说明名称


string
name = IconReaderHelper.GetDisplayName(
this
.txtFilPath.Text,
false
);
this
.Text = name;
}

//
获取系统文件夹图标


Icon ico2 = IconReaderHelper.GetFolderIcon(IconReaderHelper.IconSize.Large,
IconReaderHelper.FolderType.Open);
this
.pictureBox2.Image = Bitmap.FromHicon(ico2.Handle);

}

private
void
btnGetExtensionIcon_Click(
object
sender, EventArgs e)
{
if
(!
string
.IsNullOrEmpty(
this
.txtExtension.Text))
{
//
获取扩展名图标


Icon ico = IconReaderHelper.ExtractIconForExtension(
this
.txtExtension.Text,
true
);
this
.pictureBox2.Image = Bitmap.FromHicon(ico.Handle);
}

}

2、
实现图片打印操作,并提供图片打印预览功能,图片自动根据页面进行居中、缩放、对齐等操作辅助类

ImagePrintHelper



实现效果

1)
本辅助类主要是用来方便实现图片打印操作,并提供图片打印预览功能,图片自动根据页面进行居中、缩放、对齐等默认操作。

打印预览的时候,自动调整图片为止,如下:

或者打印对话框


实现代码

1)辅助类提供的方法接口如下所示

#region
配置参数
///

<summary>


///
将在页面上居中打印输出。

///

</summary>



public
bool
AllowPrintCenter =
true
;

///

<summary>


///
旋转图像,如果它符合页面更好

///

</summary>



public
bool
AllowPrintRotate =
true
;

///

<summary>


///
缩放图像,以更好地适应页面

///

</summary>



public
bool
AllowPrintEnlarge =
true
;

///

<summary>


///
允许打印收缩,以更好适应页面

///

</summary>



public
bool
AllowPrintShrink =
true
;

#endregion

///

<summary>


///
构造函数

///

</summary>


///

<param name="image">
待打印的图片对象
</param>



public
ImagePrintHelper(Image image) :
this
(image,
"
test.png
"
)

///

<summary>


///
构造函数

///

</summary>


///

<param name="image">
待打印的图片对象
</param>


///

<param name="documentname">
文档名称
</param>



public
ImagePrintHelper(Image image,
string
documentname)

///

<summary>


///
显示打印对话框,确定则进行打印

///

</summary>


///

<returns></returns>



public
PrinterSettings PrintWithDialog()

///

<summary>


///
在预览对话框中预览图片

///

</summary>


public
void
PrintPreview()

2)辅助类ImagePrintHelper的使用例子代码如下所示

private
void
btnPrintImage_Click(
object
sender, EventArgs e)
{
ImagePrintHelper imagePrint =
new
ImagePrintHelper(
this
.pictureBox1.Image, Path.GetFileName(
this
.txtFilPath.Text));
imagePrint.AllowPrintShrink =
true
;
imagePrint.AllowPrintCenter =
true
;
imagePrint.AllowPrintEnlarge =
true
;
imagePrint.AllowPrintRotate =
true
;
imagePrint.PrintWithDialog();
//
弹出打印对话框,确认进行打印


}

private
void
btnPrintView_Click(
object
sender, EventArgs e)
{
ImagePrintHelper imagePrint =
new
ImagePrintHelper(
this
.pictureBox1.Image, Path.GetFileName(
this
.txtFilPath.Text));
imagePrint.PrintPreview();
//
弹出打印预览页面


}

2、
Web页面预览效果图片抓取辅助类 WebPageCapture和WebPreview



实现效果

1)
本辅助类主要是用来方便实现Web页面预览效果图片抓取操作。

实现代码

1)辅助类提供的方法接口如下所示

#region
字段属性


///

<summary>


///
图片下载完毕的时间处理

///

</summary>



public
event
ImageEventHandler DownloadCompleted;
///

<summary>


///
图片处理委托定义

///

</summary>


///

<param name="image"></param>



public
delegate
void
ImageEventHandler(Image image);

///

<summary>


///
浏览区域大小

///

</summary>



public
Size BrowserSize {
get
;
set
; }

///

<summary>


///
页面URL地址

///

</summary>



public
string
URL {
get
;
set
; }

///

<summary>


///
下载的图片对象

///

</summary>



public
Image Image {
get
;
private
set
; }

#endregion

#region
构造函数

///

<summary>


///
构造函数,默认为屏幕大小

///

</summary>



public
WebPageCapture() :
this
(Screen.PrimaryScreen.Bounds.Size) { }

///

<summary>


///
构造函数,指定浏览区域大小

///

</summary>


///

<param name="width">
宽度
</param>


///

<param name="height">
高度
</param>



public
WebPageCapture(
int
width,
int
height) :
this
(
new
Size(width, height)) { }

///

<summary>


///
构造函数,指定浏览区域大小

///

</summary>


///

<param name="browserSize">
浏览区域大小
</param>



public
WebPageCapture(Size browserSize)

#endregion

///

<summary>


///
下载页面到图片中

///

</summary>



public
void
DownloadPage()

///

<summary>


///
下载页面到图片中

///

</summary>


///

<param name="url">
页面Url地址
</param>



public
void
DownloadPage(
string
url)

2)辅助类WebPageCapture的使用例子代码如下所示

public
partial
class
FrmWebPreview : Form
{
private
WebPageCapture capture =
new
WebPageCapture();
public
FrmWebPreview()
{
InitializeComponent();

capture.DownloadCompleted +=
new
WebPageCapture.ImageEventHandler(capture_DownloadCompleted);       }

void
capture_DownloadCompleted(Image image)
{
this
.pictureBox1.Image = image;
}

private
void
btnSnap1_Click(
object
sender, EventArgs e)
{
if
(
this
.txtUrl.Text.Length ==
0
)
return
;

capture.DownloadPage(
this
.txtUrl.Text);

}

3) 辅助类WebPreview的使用例子代码如下所示

private
void
btnSnap2_Click(
object
sender, EventArgs e)
{
if
(
this
.txtUrl.Text.Length ==
0
)
return
;
this
.pictureBox1.Image = WebPreview.GetWebPreview(
new
Uri(
this
.txtUrl.Text), Screen.PrimaryScreen.Bounds.Size);
}

2、
图片对象比较、缩放、缩略图、水印、压缩、转换、编码等操作辅助类 ImageHelper



实现效果

1)
本辅助类主要是用来方便实现图片对象比较、缩放、缩略图、水印、压缩、转换、编码等操作。

2)基本图片所有的相关操作,均可在该辅助类中找到,该辅助类具有专业、全面、封装良好等特点。

实现代码

1)辅助类提供的方法接口如下所示

///

<summary>

///
图片对象比较、缩放、缩略图、水印、压缩、转换、编码等操作辅助类

///

</summary>



public
class
ImageHelper
{
#region
图片比较

///

<summary>


///
对比两张图片

///

</summary>


///

<param name="bmp1">
The first bitmap image
</param>


///

<param name="bmp2">
The second bitmap image
</param>


///

<returns>
CompareResult
</returns>



public
static
CompareResult CompareTwoImages(Bitmap bmp1, Bitmap bmp2)

#endregion

#region
图片缩放

///

<summary>


///
按比例调整图片大小

///

</summary>


///

<param name="imgPhoto">
原始图片对象.
</param>


///

<param name="Percent">
调整比例
</param>


///

<returns></returns>



public
static
Image ResizeImageByPercent(Image imgPhoto,
int
Percent)

///

<summary>


///
缩放、裁切图片

///

</summary>


///

<param name="originalImage">
原始图片对象
</param>


///

<param name="width">
宽度
</param>


///

<param name="height">
高度
</param>


///

<param name="mode">
调整模式
</param>


///

<returns></returns>



public
static
Image ResizeImageToAFixedSize(Image originalImage,
int
width,
int
height, ScaleMode mode)

#endregion

#region
创建缩略图

///

<summary>


///
生成缩略图

///

</summary>


///

<param name="originalImagePath">
源图路径(物理路径)
</param>


///

<param name="thumbnailPath">
缩略图路径(物理路径)
</param>


///

<param name="width">
缩略图宽度
</param>


///

<param name="height">
缩略图高度
</param>


///

<param name="mode">
生成缩略图的方式
</param>



public
static
void
MakeThumbnail(
string
originalImagePath,
string
thumbnailPath,
int
width,
int
height, ScaleMode mode)

///

<summary>


///
生成缩略图

///

</summary>


///

<param name="originalImagePath">
源图路径(物理路径)
</param>


///

<param name="thumbnailPath">
缩略图路径(物理路径)
</param>


///

<param name="width">
缩略图宽度
</param>


///

<param name="height">
缩略图高度
</param>


///

<param name="mode">
生成缩略图的方式
</param>



public
static
void
MakeThumbnail(
string
originalImagePath,
string
thumbnailPath,
int
width,
int
height, ScaleMode mode, System.Drawing.Imaging.ImageFormat format)

#endregion

#region
图片水印

///

<summary>


///
添加文字水印   默认字体:Verdana  12号大小  斜体  黑色    位置:右下角

///

</summary>


///

<param name="originalImage">
Image
</param>


///

<param name="text">
水印字
</param>


///

<returns></returns>



public
static
Image WatermarkText(Image originalImage,
string
text)

///

<summary>


///
添加文字水印   默认字体:Verdana  12号大小  斜体  黑色

///

</summary>


///

<param name="originalImage">
Image
</param>


///

<param name="text">
水印字
</param>


///

<param name="position">
水印位置
</param>


///

<returns></returns>



public
static
Image WatermarkText(Image originalImage,
string
text, WatermarkPosition position)

///

<summary>


///
添加文字水印

///

</summary>


///

<param name="originalImage">
Image
</param>


///

<param name="text">
水印字
</param>


///

<param name="position">
水印位置
</param>


///

<param name="font">
字体
</param>


///

<param name="brush">
颜色
</param>


///

<returns></returns>



public
static
Image WatermarkText(Image originalImage,
string
text, WatermarkPosition position, Font font, Brush brush)

///

<summary>


///
添加图片水印(位置默认右下角)

///

</summary>


///

<param name="originalImage">
Image
</param>


///

<param name="watermarkImage">
水印Image
</param>


///

<returns></returns>



public
static
Image WatermarkImage(Image originalImage, Image watermarkImage)

///

<summary>


///
添加图片水印

///

</summary>


///

<param name="originalImage">
Image
</param>


///

<param name="watermarkImage">
水印Image
</param>


///

<param name="position">
位置
</param>


///

<returns></returns>



public
static
Image WatermarkImage(Image originalImage, Image watermarkImage, WatermarkPosition position)

#endregion

#region
复制到剪切板

///

<summary>


///
复制指定的图片对象到剪切板

///

</summary>


///

<param name="img">
复制的图片对象
</param>



public
static
void
CopyToClipboard(Image img)

#endregion

#region
其他操作

///

<summary>


///
获取图片编码解码器,保存JPG时用

///

</summary>


///

<param name="mimeType">

</param>


///

<returns>
得到指定mimeType的ImageCodecInfo
</returns>



public
static
ImageCodecInfo GetCodecInfo(
string
mimeType)


///

<summary>


///
设置图片透明度

///

</summary>


///

<param name="imgPic">
原始图片对象
</param>


///

<param name="imgOpac">
透明度
</param>


///

<returns></returns>



public
static
Image SetImgOpacity(Image imgPic,
float
imgOpac)

///

<summary>


///
修改图片亮度

///

</summary>


///

<param name="bmp">
原始位图对象
</param>


///

<param name="value">
亮度值
</param>


///

<returns></returns>



public
static
Bitmap ChangeBrightness(Bitmap bmp,
int
value)

#region
改变图片大小

///

<summary>


///
改变图片大小

///

</summary>


///

<param name="img">
原始图片对象
</param>


///

<param name="width">
改变的宽度
</param>


///

<param name="height">
改变的高度
</param>


///

<returns></returns>



public
static
Image ChangeImageSize(Image img,
int
width,
int
height)

///

<summary>


///
改变图片大小

///

</summary>


///

<param name="img">
原始图片对象
</param>


///

<param name="width">
改变的宽度
</param>


///

<param name="height">
改变的高度
</param>


///

<param name="preserveSize">
限制的最小宽度或高度
</param>


///

<returns></returns>



public
static
Image ChangeImageSize(Image img,
int
width,
int
height,
bool
preserveSize)

///

<summary>


///
改变图片大小(按比例缩放)

///

</summary>


///

<param name="img">
原始图片对象
</param>


///

<param name="percentage">
大小比例
</param>


///

<returns></returns>



public
static
Image ChangeImageSize(Image img,
float
percentage)

#endregion

///

<summary>


///
剪切图片

///

</summary>


///

<param name="img">
原始图片对象
</param>


///

<param name="rect">
剪切区域
</param>


///

<returns></returns>



public
static
Image CropImage(Image img, Rectangle rect)

///

<summary>


///
剪裁 -- 用GDI+

///

</summary>


///

<param name="b">
原始Bitmap
</param>


///

<param name="StartX">
开始坐标X
</param>


///

<param name="StartY">
开始坐标Y
</param>


///

<param name="iWidth">
宽度
</param>


///

<param name="iHeight">
高度
</param>


///

<returns>
剪裁后的Bitmap
</returns>



public
static
Bitmap CropImage(Bitmap b,
int
StartX,
int
StartY,
int
iWidth,
int
iHeight)

public
static
Image AddCanvas(Image img,
int
size)

///

<summary>


///
旋转图片

///

</summary>


///

<param name="img">
待旋转的图片对象
</param>


///

<param name="theta">
旋转角度
</param>


///

<returns></returns>



public
static
Bitmap RotateImage(Image img,
float
theta)

private
static
Rectangle BoundingBox(Image img, Matrix matrix)

///

<summary>


///
获取所有屏幕的矩形宽度

///

</summary>


///

<returns></returns>



public
static
Rectangle GetScreenBounds()

///

<summary>


///
使窗口背景透明

///

</summary>


///

<param name="hWnd">
窗口句柄
</param>


///

<param name="image">
透明图片
</param>


///

<returns></returns>



public
static
Bitmap MakeBackgroundTransparent(IntPtr hWnd, Image image)

///

<summary>


///
保存打印图片文件

///

</summary>


///

<param name="image">
图片对象
</param>


///

<param name="transColor">
透明色
</param>


///

<param name="dpi">
打印的dpi
</param>


///

<param name="path">
保存文件的路径
</param>



public
static
void
SaveOneInchPic(Image image, Color transColor,
float
dpi,
string
path)

#endregion

#region
BASE64编码转换

///

<summary>


///
Base64编码转换到Image对象

///

</summary>


///

<param name="ImgBase64Str"></param>


///

<returns></returns>



public
static
Bitmap Base64StrToBmp(
string
ImgBase64Str)

///

<summary>


///
从文件中转换图片对象到Base64编码

///

</summary>


///

<param name="ImgName"></param>


///

<returns></returns>



public
static
string
ImageToBase64Str(
string
ImgName)

///

<summary>


///
转换图片对象到Base64编码

///

</summary>


///

<param name="Img"></param>


///

<returns></returns>



public
static
string
ImageToBase64Str(Image Img)

#endregion

#region
色彩处理

///

<summary>


///
设置图形颜色  边缘的色彩更换成新的颜色

///

</summary>


///

<param name="p_Image">
图片
</param>


///

<param name="p_OldColor">
老的边缘色彩
</param>


///

<param name="p_NewColor">
新的边缘色彩
</param>


///

<param name="p_Float">
溶差
</param>


///

<returns>
清理后的图形
</returns>



public
static
Image SetImageColorBrim(Image p_Image, Color p_OldColor, Color p_NewColor,
int
p_Float)

///

<summary>


///
设置图形颜色  所有的色彩更换成新的颜色

///

</summary>


///

<param name="p_Image">
图片
</param>


///

<param name="p_OdlColor">
老的颜色
</param>


///

<param name="p_NewColor">
新的颜色
</param>


///

<param name="p_Float">
溶差
</param>


///

<returns>
清理后的图形
</returns>



public
static
Image SetImageColorAll(Image p_Image, Color p_OdlColor, Color p_NewColor,
int
p_Float)

///

<summary>


///
设置图形颜色  坐标的颜色更换成新的色彩 (漏斗)

///

</summary>


///

<param name="p_Image">
新图形
</param>


///

<param name="p_Point">
位置
</param>


///

<param name="p_NewColor">
新的色彩
</param>


///

<param name="p_Float">
溶差
</param>


///

<returns>
清理后的图形
</returns>



public
static
Image SetImageColorPoint(Image p_Image, Point p_Point, Color p_NewColor,
int
p_Float)

///

<summary>


///
SetImageColorPoint 循环调用 检查新的坐标是否符合条件 符合条件会写入栈p_ColorStack 并更改颜色

///

</summary>


///

<param name="p_DataBytes">
数据区
</param>


///

<param name="p_Stride">
行扫描字节数
</param>


///

<param name="p_ColorStack">
需要检查的位置栈
</param>


///

<param name="p_X">
位置X
</param>


///

<param name="p_Y">
位置Y
</param>


///

<param name="p_OldColor">
老色彩
</param>


///

<param name="p_NewColor">
新色彩
</param>


///

<param name="p_Float">
溶差
</param>



private
static
void
SetImageColorPoint(
byte
[] p_DataBytes,
int
p_Stride, Stack<Point> p_ColorStack,
int
p_X,
int
p_Y, Color p_OldColor, Color p_NewColor,
int
p_Float)

///

<summary>


///
检查色彩(可以根据这个更改比较方式

///

</summary>


///

<param name="p_CurrentlyColor">
当前色彩
</param>


///

<param name="p_CompareColor">
比较色彩
</param>


///

<param name="p_Float">
溶差
</param>


///

<returns></returns>



private
static
bool
ScanColor(Color p_CurrentlyColor, Color p_CompareColor,
int
p_Float)

#endregion

#region
图像压缩

///

<summary>


///
将Bitmap对象压缩为JPG图片类型

///

</summary>


///

</summary>


///

<param name="bmp">
源bitmap对象
</param>


///

<param name="saveFilePath">
目标图片的存储地址
</param>


///

<param name="quality">
压缩质量,越大照片越清晰,推荐80
</param>



public
static
void
CompressAsJPG(Bitmap bmp,
string
saveFilePath,
int
quality)

///

<summary>


///
将inputStream中的对象压缩为JPG图片类型

///

</summary>


///

<param name="inputStream">
源Stream对象
</param>


///

<param name="saveFilePath">
目标图片的存储地址
</param>


///

<param name="quality">
压缩质量,越大照片越清晰,推荐80
</param>



public
static
void
CompressAsJPG(Stream inputStream,
string
saveFilePath,
int
quality)

#endregion

#region
图片转换

///

<summary>


///
把Image对象转换为Byte数组

///

</summary>


///

<param name="image">
图片Image对象
</param>


///

<returns>
字节集合
</returns>



public
static
byte
[] ImageToBytes(System.Drawing.Image image)

///

<summary>


///
转换Byte数组到Image对象

///

</summary>


///

<param name="bytes">
字节数组
</param>


///

<returns>
Image图片
</returns>



public
static
System.Drawing.Image ImageFromBytes(
byte
[] bytes)

///

<summary>


///
转换地址(文件路径或者URL地址)到Image对象

///

</summary>


///

<param name="url">
图片地址(文件路径或者URL地址)
</param>


///

<returns>
Image对象
</returns>



public
static
System.Drawing.Image ImageFromUrl(
string
url)

#endregion

2) 辅助类ImageHelper的使用例子代码如下所示

private
void
btnLoadBitmap_Click(
object
sender, EventArgs e)
{
//
加载图片


string
file = FileDialogHelper.OpenImage();
if
(!
string
.IsNullOrEmpty(file))
{
pictureBox1.Image = Image.FromFile(file);
}
}

private
void
btnWaterMark_Click(
object
sender, EventArgs e)
{
//
图片水印效果


string
file = FileDialogHelper.OpenImage();
if
(!
string
.IsNullOrEmpty(file))
{
this
.pictureBox2.Image = ImageHelper.WatermarkImage(
this
.pictureBox1.Image, Image.FromFile(file));
}
}

private
void
btnTextWatermark_Click(
object
sender, EventArgs e)
{
//
文字水印效果


this
.pictureBox2.Image = ImageHelper.WatermarkText(
this
.pictureBox1.Image,
"
测试水印效果
"
);
}

private
void
btnZoom_Click(
object
sender, EventArgs e)
{
//
按比例放大图片


this
.pictureBox2.Image = ImageHelper.ResizeImageByPercent(
this
.pictureBox1.Image,
200
);
}

private
void
btnRotate_Click(
object
sender, EventArgs e)
{
//
旋转图片


this
.pictureBox2.Image = ImageHelper.RotateImage(
this
.pictureBox1.Image,
90
);
}

2、
弹出打印窗体的预览对话框辅助类 PrintFormHelper



实现效果

1)
本辅助类主要是用来方便实现窗体界面打印的功能。

2)窗体界面打印提供通用的打印预览功能。

实现代码

1)辅助类提供的方法接口如下所示

///

<summary>

///
Winform窗口打印辅助类

///

</summary>



public
class
PrintFormHelper
{
///

<summary>


///
弹出打印窗体的预览对话框

///

</summary>


///

<param name="form"></param>



public
static
void
Print(Form form)
}

2)
辅助类PrintFormHelper的使用例子代码如下所示

private
void
btnPrintForm_Click(
object
sender, EventArgs e)
{
try
{
this
.Cursor = Cursors.WaitCursor;
PrintFormHelper.Print(
this
);
//
打印当前窗体


}
catch
(Exception ex)
{
MessageBox.Show(
this
, ex.Message);
}
finally
{
this
.Cursor = Cursors.Default;
}

}

2、抓取整个屏幕或指定窗口,并可把抓取的图片保存到文件等操作辅助类 ScreenCapture
实现效果

1)本辅助类主要是用来方便实现抓取整个屏幕或指定窗口,并可把抓取的图片保存到文件等操作

2)该辅助类类非常方便实现对桌面、指定窗口进行屏幕截图,并可以指定保存路径、指定图片格式、后缀名等属性对截图进行保存,适合用于对屏幕监控等相关的操作中。

实现代码

1)辅助类提供的方法接口如下所示


///

<summary>


///
图片保存的路径,默认为C:\\CaptureImages

///

</summary>



public
string
ImageSavePath

///

<summary>


///
图片的后缀名,如果为空,使用图片格式作为后缀名

///

</summary>



public
string
ImageExtension

///

<summary>


///
图片保存的格式

///

</summary>



public
ImageFormat ImageFormat

///

<summary>


///
抓取桌面整个屏幕截图到一个图片对象中

///

</summary>


///

<returns></returns>



public
Image CaptureScreen()

///

<summary>


///
抓取桌面整个指定窗口的截图到一个图片对象中

///

</summary>


///

<param name="handle">
指定窗口的句柄
</param>


///

<returns></returns>



public
Image CaptureWindow(IntPtr handle)

///

<summary>


///
抓取桌面整个指定窗口的截图,并保存到文件中

///

</summary>


///

<param name="handle"></param>


///

<param name="filename"></param>


///

<param name="format"></param>



public
void
CaptureWindowToFile(IntPtr handle,
string
filename, ImageFormat format)

///

<summary>


///
根据属性配置自动保存图片

///

</summary>



public
void
AutoCaptureScreen()

///

<summary>


///
抓取桌面整个指定窗口的截图,并保存到文件中

///

</summary>


///

<param name="filename"></param>


///

<param name="format"></param>



public
void
CaptureScreenToFile(
string
filename, ImageFormat format)


2)辅助类ScreenCapture的使用例子代码如下所示
ScreenCapture capture =
new
ScreenCapture();

Image image = capture.CaptureWindow(form.Handle);

俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力。

本篇继续继续整理优化已有的共用类库,并继续发表随笔介绍公用类库的接口方法以及详细使用操作,力求给自己继续优化,积攒更丰富的公用类库资源,加深了解的同时,也给大家展现公用类库好的方面。

本篇的公用类库的介绍主题是设备相关的部分,包括计算机硬件信息(如系统信息、电脑CPU、磁盘、网卡、内存等)、声音播放控制、 键盘属性及操作、全局键盘按键钩子、鼠标属性及操作、鼠标按键钩子等类库信息。
如果你对前面的类库介绍文章有兴趣,可以参考下面的连接了解。

厚积薄发,丰富的公用类库积累,助你高效进行系统开发(6)

厚积薄发,丰富的公用类库积累,助你高效进行系统开发(5)




1、
WAV声音格式文件播放辅助类AudioHelper

实现效果

1)本辅助类主要是用来方便实现播放WAV声音格式文件的操作。

2)声音播放可以用在特定事件的触发上,如来电、收到消息等,经典的就如QQ收到信息,咳嗽的声音,使用声音播放可以提高更好的用户体验。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
播放 .wav 格式的声音文件

///

</summary>


///

<param name="location">
声音文件路径
</param>



public
static
void
Play(
string
location)

///

<summary>


///
播放 .wav 格式的声音文件

///

</summary>


///

<param name="playMode">
播放声音的枚举模式。默认为AudioPlayMode.Background。
</param>


///

<param name="location">
声音文件路径
</param>



public
static
void
Play(
string
location, AudioPlayMode playMode)

///

<summary>


///
播放 .wav 格式的声音文件

///

</summary>


///

<param name="stream"><see cref="T:System.IO.Stream"></see>
声音文件的流对象
</param>


///

<param name="playMode">
播放声音的枚举模式。默认为AudioPlayMode.Background。
</param>



public
static
void
Play(Stream stream, AudioPlayMode playMode)

///

<summary>


///
播放 .wav 格式的声音文件

///

</summary>


///

<param name="data">
声音文件的字节数组
</param>


///

<param name="playMode">
播放声音的枚举模式。默认为AudioPlayMode.Background。
</param>



public
static
void
Play(
byte
[] data, AudioPlayMode playMode)

///

<summary>


///
播放系统声音

///

</summary>



public
static
void
PlaySystemSound(SystemSound systemSound)

///

<summary>


///
停止正在后台播放的声音

///

</summary>



public
static
void
Stop()

2) 辅助类AudioHelper的使用例子代码如下所示

private
void
btnPlaySound_Click(
object
sender, EventArgs e)
{
try
{
AppConfig config =
new
AppConfig();
string
SoundFilePath = config.AppConfigGet(
"
SoundFilePath
"
);
AudioHelper.Play(SoundFilePath);
//
AudioHelper.Play("ringin.wav");


}
catch
(Exception ex)
{
LogHelper.Error(
"
没找到声音文件
"
, ex);
}
}

2、声音文件播放操作辅助类SoundPlayerHelper。除了MP3声音文件外,还可以播放WAV格式、midi格式声音文件。

实现效果

1)本辅助类主要是用来方便实现MP3文件、WAV文件、Midi文件等声音的播放操作,并提供音量控制操作功能。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
播放声音文件

///

</summary>


///

<param name="soundFileName">
声音文件路径(可以是MP3、WAV、Midi等声音文件)
</param>


///

<param name="Repeat">
是否重复播放
</param>



public
static
void
Play(
string
soundFileName,
bool
Repeat)

///

<summary>


///
播放声音嵌入资源字节数组

///

</summary>


///

<param name="soundEmbeddedResource">
声音文件嵌入资源字节数组(可以是MP3、WAV、Midi等声音格式)
</param>


///

<param name="Repeat">
是否重复播放
</param>



public
static
void
Play(
byte
[] soundEmbeddedResource,
bool
Repeat)

///

<summary>


///
暂停播放

///

</summary>



public
static
void
Pause()

///

<summary>


///
停止播放

///

</summary>



public
static
void
Stop()

///

<summary>


///
清除操作

///

</summary>



public
static
void
Dispose()

///

<summary>


///
获取或设置音量的百分比

///

</summary>


///

<returns></returns>



public
static
float
VolumePercent


///

<summary>


///
获取音量

///

</summary>


///

<returns></returns>



public
static
float
GetVolume()

///

<summary>


///
设置音量

///

</summary>


///

<param name="volume"></param>



public
static
void
SetVolume(
float
volume)

///

<SUMMARY>


///
返回当前状态播放:播放,暂停,停止等

///

</SUMMARY>



public
static
string
Status

2)辅助类SoundPlayerHelper的使用例子代码如下所示

bool
isPlay =
false
;
private
void
btnPlayMp3_Click(
object
sender, EventArgs e)
{
if
(!isPlay)
{
string
mp3File = Path.Combine(Application.StartupPath,
"
伤不起.mp3
"
);
string
waveFile = Path.Combine(Application.StartupPath,
"
ringin.wav
"
);
string
midFile =
@"
C:\Windows\Media\onestop.mid
"
;

SoundPlayerHelper.Play(mp3File,
false
);
//
播放MP3格式文件

//
SoundPlayerHelper.Play(waveFile, true);
//
播放WAV格式文件

//
SoundPlayerHelper.Play(midFile, false);
//
播放Midi格式文件


this
.btnPlayMp3.Text =
"
停止播放
"
;
}
else
{
SoundPlayerHelper.Stop();
//
停止播放

//
SoundPlayerHelper.Pause();
//
暂停播放


this
.btnPlayMp3.Text =
"
播放声音
"
;
}

string
statu = SoundPlayerHelper.Status;
this
.Text = statu;
isPlay = !isPlay;
}

private
void
trackBar1_Scroll(
object
sender, EventArgs e)
{
//
设置音量


float
vol = SoundPlayerHelper.VolumePercent;
SoundPlayerHelper.VolumePercent = trackBar1.Value;
}

3、提供用户硬件唯一信息的辅助类 FingerprintHelper

实现效果

1)本辅助类主要是用来方便实现获取用户硬件的相关信息,根据用户各种硬件(CPU、网卡、磁盘、主板等)标识信息,获取一个8位唯一标识数字。

2)本辅助类只提供了一个公共的方法Value,它集合了CPU、网卡、磁盘、主板等信息,通过这个8位的数字标识,我们可以唯一区分一台电脑,类似我们每个人的指纹信息一样,很少会发生重复的现象,可以用在一些关键的注册授权机制上。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>


///
根据用户各种硬件(CPU、网卡、磁盘、主板等)标识信息,

///
获取一个8位唯一标识数字

///

</summary>



public
static
string
Value()

///

<summary>


///
获取硬件的标识信息

///

</summary>



private
static
string
identifier(
string
wmiClass,
string
wmiProperty,
string
wmiMustBeTrue)

///

<summary>


///
获取硬件的标识信息

///

</summary>



private
static
string
identifier(
string
wmiClass,
string
wmiProperty)

///

<summary>


///
获取CPU信息

///

</summary>



private
static
string
cpuId()

///

<summary>


///
获取BOIS主板标识信息

///

</summary>



private
static
string
biosId()

///

<summary>


///
获取主硬盘的标识信息

///

</summary>


///

<returns></returns>



private
static
string
diskId()

///

<summary>


///
获取主板的标识信息

///

</summary>


///

<returns></returns>



private
static
string
baseId()

///

<summary>


///
获取主视频控制器标识信息

///

</summary>


///

<returns></returns>



private
static
string
videoId()

///

<summary>


///
获取第一个可用网卡信息

///

</summary>


///

<returns></returns>



private
static
string
macId()

///

<summary>


///
转换内容为8位数字

///

</summary>


private
static
string
pack(
string
text)


2)

辅助类

FingerprintHelper的使用例子代码如下所示

string
identity = FingerprintHelper.Value();

MessageUtil.ShowTips(identity);

4、获取系统信息、电脑CPU、磁盘、网卡、内存等相关信息辅助类 HardwareInfoHelper

实现效果

1)本辅助类主要是用来方便获取系统信息、电脑CPU、磁盘、网卡、内存等相关信息。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
获得盘符为drvID的硬盘序列号,缺省为C

///

</summary>


///

<param name="drvID">
盘符,如"C"
</param>


///

<returns></returns>



public
static
string
HDVal(
string
drvID)

///

<summary>


///
获取默认C盘的磁盘序列号

///

</summary>


///

<returns></returns>



public
static
string
HDVal()

///

<summary>


///
获取硬盘ID

///

</summary>


///

<returns></returns>



public
static
string
GetDiskID()

///

<summary>


///
获取硬盘Model的信息

///

</summary>



public
static
string
GetDiskModel()

///

<summary>


///
获得Cpu使用率

///

</summary>



public
static
int
GetCpuUsage()

///

<summary>


///
获取CPU的ID

///

</summary>


///

<returns></returns>



public
static
string
GetCPUId()

///

<summary>


///
获取CPU的名称

///

</summary>


///

<returns></returns>



public
static
string
GetCPUName()

///

<summary>


///
返回USB盘符列表

///

</summary>



public
static
List<
string
> GetUSBDriveLetters()

///

<summary>


///
获得硬盘信息

///

</summary>



public
static
HardDiskInfo GetHDInfo(
byte
driveIndex)


#region
其他数据

///

<summary>


///
获取MAC地址

///

</summary>


///

<returns></returns>



public
static
string
GetMacAddress()

///

<summary>


///
获取IP地址

///

</summary>



public
static
string
GetIPAddress()

///

<summary>


///
获取操作系统的登录用户名

///

</summary>



public
static
string
GetUserName()

///

<summary>


///
获取计算机名

///

</summary>



public
static
string
GetComputerName()

///

<summary>


///
获取PC类型

///

</summary>



public
static
string
GetSystemType()

///

<summary>


///
获取物理内存

///

</summary>



public
static
string
GetTotalPhysicalMemory()

#endregion

2)辅助类HardwareInfoHelper的使用例子代码如下所示

private
void
btnComputer_Click(
object
sender, EventArgs e)
{
string
computerName = HardwareInfoHelper.GetComputerName();
string
userName = HardwareInfoHelper.GetUserName();
string
systemType = HardwareInfoHelper.GetSystemType();
string
cpuid = HardwareInfoHelper.GetCPUId();
string
cpuName = HardwareInfoHelper.GetCPUName();
int
cpuUsage = HardwareInfoHelper.GetCpuUsage();
string
diskId = HardwareInfoHelper.GetDiskID();
string
ip = HardwareInfoHelper.GetIPAddress();
string
macAddress = HardwareInfoHelper.GetMacAddress();
string
memery = HardwareInfoHelper.GetTotalPhysicalMemory();

StringBuilder sb =
new
StringBuilder();
sb.AppendFormat(
"
ComputerName:\t {0} \r\n
"
, computerName);
sb.AppendFormat(
"
UserName:\t {0} \r\n
"
, userName);
sb.AppendFormat(
"
SystemType:\t {0} \r\n
"
, systemType);
sb.AppendFormat(
"
CPU ID:\t {0} \r\n
"
, cpuid);
sb.AppendFormat(
"
CPU Name:\t {0} \r\n
"
, cpuName);
sb.AppendFormat(
"
CPU Usage:\t {0} \r\n
"
, cpuUsage);
sb.AppendFormat(
"
Disk Id:\t {0} \r\n
"
, diskId);
sb.AppendFormat(
"
IP:\t {0} \r\n
"
, ip);
sb.AppendFormat(
"
MacAddress:\t {0} \r\n
"
, macAddress);
sb.AppendFormat(
"
TotalPhysicalMemory:\t {0} \r\n
"
, memery);
MessageUtil.ShowTips(sb.ToString());

string
identity = FingerprintHelper.Value();
MessageUtil.ShowTips(identity);

}

5、键盘操作辅助类KeyboardHelper,提供属性访问敲击那个键,以及发送软键盘消息等操作。

实现效果

1)本辅助类主要是用来方便实现访问键盘的大写键、数字键等键的开启情况,另外判断CTRL、Shift、Alt键是否按下的操作,辅助类也封装了发送软键盘消息等操作。

实现代码

1)辅助类提供的方法接口如下所示:

#region
键盘属性

///

<summary>


///
判断ALT建是否按下

///

</summary>



public
static
bool
AltKeyDown


///

<summary>


///
判断Caps Lock大写键是否打开

///

</summary>



public
static
bool
CapsLock

///

<summary>


///
判断CTRL键是否按下

///

</summary>



public
static
bool
CtrlKeyDown

///

<summary>


///
判断Num Lock 数字键是否打开

///

</summary>



public
static
bool
NumLock

///

<summary>


///
判断Scroll Lock滚动锁定键是否打开

///

</summary>



public
static
bool
ScrollLock

///

<summary>


///
判断Shift键是否按下

///

</summary>



public
static
bool
ShiftKeyDown


#endregion

#region
操作方法

///

<summary>


///
发送一个或多个击键到活动窗口。

///

</summary>


///

<param name="keys">
定义发送键的字符串。特殊控制键代码SHIFT(+),CTRL(^), ALT(%)。Send("{SPACE}")、Send("+{TAB}")
</param>



public
static
void
SendKeys(
string
keys)

///

<summary>


///
发送一个或多个击键到活动窗口

///

</summary>


///

<param name="keys">
定义发送键的字符串.特殊控制键代码SHIFT(+),CTRL(^), ALT(%)。Send("{SPACE}")、Send("+{TAB}")
</param>


///

<param name="wait">
指定是否要等待应用程序继续之前得到处理的击键。默认为True。

///

</param>



public
static
void
SendKeys(
string
keys,
bool
wait)

#endregion

2)辅助类

KeyboardHelper的使用例子代码如下所示

bool
capsLock = KeyboardHelper.CapsLock;
bool
numLock = KeyboardHelper.NumLock;
bool
scrollLock = KeyboardHelper.ScrollLock;
KeyboardHelper.SendKeys(
"
{TAB}
"
);
//
发送Tab键

KeyboardHelper.SendKeys(
"
%{F4}
"
);
//
发送Alt + F4退出


相关的按键参考如下所示

6、全局键盘钩子,用来捕捉系统全局的键盘输入辅助类 KeyboardHook

实现效果

1)本辅助类主要是用来方便实现全局键盘钩子,用来捕捉系统全局的键盘输入。

2)通过键盘钩子,我们可以获取用户的各种按键信息,以及可以屏蔽指定按键的操作,全局键盘钩子,就如一扇门一样,可以记录相关的键盘输入操作,也可以增加指定的事件处理,可以控制键盘按键继续流转到其他程序中,或者屏蔽操作。最典型的钩子操作例子就是金山词霸等取词软件。

3)辅助类通过KeyboardHook.Enable()开始键盘钩子,通过KeyboardHook.Disable()禁用或者通过KeyboardHook.Remove(**)来移除指定的键盘钩子事件。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>

///
判断是否CTRL键按下

///

</summary>



public
static
bool
Control =
false
;

///

<summary>


///
判断Shift键是否按下

///

</summary>



public
static
bool
Shift =
false
;

///

<summary>


///
检查Alt键是否按下

///

</summary>



public
static
bool
Alt =
false
;

///

<summary>


///
检查Windows键是否按下

///

</summary>



public
static
bool
Win =
false
;

///

<summary>


///
键盘敲击事件代理定义

///

</summary>



public
delegate
bool
KeyPressed();

///

<summary>


///
处理键盘按下委托函数

///

</summary>


///

<param name="key">


///
按下的键。需检查CTRL、Shift、Win等键。

///

<returns>


///
如果想应用程序能捕捉到,设置为True;如果设置为False,则键盘事件被屏蔽。

///

</returns>



public
delegate
bool
KeyboardHookHandler(Keys key);

///

<summary>


///
添加一个键盘钩子处理给当前的键

///

</summary>



public
static
KeyboardHookHandler KeyDown;

///

<summary>


///
启动键盘钩子处理

///

</summary>


///

<returns>
如无异常返回True
</returns>



public
static
bool
Enable()

///

<summary>


///
禁用键盘钩子处理

///

</summary>


///

<returns>
如果禁用成功,则返回True
</returns>



public
static
bool
Disable()

///

<summary>


///
添加一个按下键的钩子处理

///

</summary>


///

<param name="key">
按下的键
</param>


///

<param name="callback">
按键的处理事件函数
</param>



public
static
bool
AddKeyDown(Keys key, KeyPressed callback)

///

<summary>


///
添加一个键弹起的钩子处理

///

</summary>


///

<param name="key">
弹起的键
</param>


///

<param name="callback">
按键的处理事件函数
</param>



public
static
bool
AddKeyUp(Keys key, KeyPressed callback)

///

<summary>


///
添加一个按下键的钩子处理

///

</summary>


///

<param name="key">
按下的键
</param>


///

<param name="callback">
按键的处理事件函数
</param>



public
static
bool
Add(Keys key, KeyPressed callback)

///

<summary>


///
移除一个按下键的钩子处理

///

</summary>


///

<param name="key">
移除的按键
</param>



public
static
bool
RemoveDown(Keys key)

///

<summary>


///
移除一个弹起键的钩子处理

///

</summary>


///

<param name="key">
移除的按键
</param>



public
static
bool
RemoveUp(Keys key)

///

<summary>


///
移除一个键的钩子处理

///

</summary>


///

<param name="key">
移除的按键
</param>



public
static
bool
Remove(Keys key)

///

<summary>


///
返回一个给定的键基于当前的控制键的字符串表示形式。

///

</summary>


///

<param name="key">
当前的键
</param>


///

<returns></returns>



public
static
string
KeyToString(Keys key)

2)

辅助类

KeyboardHook的使用例子代码如下所示

private
void
btnKeyboadHook_Click(
object
sender, EventArgs e)
{
KeyboardHook.Enable();
KeyboardHook.Add(Keys.S,
new
KeyboardHook.KeyPressed(TestKeyboadHook));
}

private
bool
TestKeyboadHook()
{
//
仅处理Alt + S 的钩子事件


if
(KeyboardHook.Alt)
{
this
.Text = DateTime.Now.ToString();
NativeMethods.BringToFront(
this
.Handle);
}
return
true
;
//
如果要被其他程序捕捉,返回True,否则返回False。


}

private
void
btnRemoveKeyboadHook_Click(
object
sender, EventArgs e)
{
KeyboardHook.Remove(Keys.S);
}

7、鼠标辅助操作类,提供获取鼠标状态以及模拟鼠标点击等操作 MouseHelper

实现效果

1)本辅助类主要是用来方便获取鼠标状态以及模拟鼠标点击等操作,通过该辅助类,可以获取鼠标是否安装、滚轮是否支持、或者模拟鼠标移动、单击、双击等操作。

实现代码

1)辅助类提供的方法接口如下所示:

#region
鼠标相关属性


///

<summary>


///
检查鼠标是否已经安装.

///

</summary>



public
static
bool
MousePresent

///

<summary>


///
检查鼠标是否存在滚轮

///

</summary>



public
static
bool
WheelExists

///

<summary>


///
获取鼠标滚轮每次滚动的行数

///

</summary>



public
static
int
WheelScrollLines

#endregion

#region
鼠标操作函数

///

<summary>


///
连续两次鼠标单击之间会被处理成双击事件的间隔时间。

///

</summary>


///

<returns>
以毫秒表示的双击时间
</returns>



[DllImport(
"
user32.dll
"
, EntryPoint =
"
GetDoubleClickTime
"
)]
public
static
extern
int
GetDoubleClickTime();

///

<summary>


///
检取光标的位置,以屏幕坐标表示。

///

</summary>


///

<param name="lpPoint">
POINT结构指针,该结构接收光标的屏幕坐标。
</param>


///

<returns>
如果成功,返回值非零;如果失败,返回值为零。
</returns>



[DllImport(
"
user32.dll
"
, EntryPoint =
"
GetCursorPos
"
)]
public
static
extern
int
GetCursorPos(Point lpPoint);

///

<summary>


///
把光标移到屏幕的指定位置。如果新位置不在由 ClipCursor函数设置的屏幕矩形区域之内,则系统自动调整坐标,使得光标在矩形之内。

///

</summary>


///

<param name="x">
指定光标的新的X坐标,以屏幕坐标表示。
</param>


///

<param name="y">
指定光标的新的Y坐标,以屏幕坐标表示。
</param>


///

<returns>
如果成功,返回非零值;如果失败,返回值是零
</returns>



[DllImport(
"
user32.dll
"
)]
public
static
extern
int
SetCursorPos(
int
x,
int
y);

#endregion

#region
封装函数

///

<summary>


///
在当前鼠标的位置左键点击一下

///

</summary>



public
static
void
MouseClick()

///

<summary>


///
移动到坐标位置点击

///

</summary>


///

<param name="location">
要点击的坐标位置,屏幕绝对值
</param>



public
static
void
MouseClick(Point location)

///

<summary>


///
移动到坐标位置点击

///

</summary>


///

<param name="location">
要点击的坐标位置,屏幕绝对值
</param>



public
static
void
MouseRightClick(Point location)

///

<summary>


///
移动到坐标位置

///

</summary>



public
static
void
MouseMove(Point location)

#endregion

2)

辅助类

MouseHelper的使用例子代码如下所示

操作比较简单,自己操作下即可。

8、全局的鼠标钩子操作类,用作捕捉全局的鼠标输入操作的辅助类 MouseHook

实现效果

1)本辅助类主要是用来方便实现全局的鼠标钩子,用作捕捉全局的鼠标输入操作。

实现代码

1)辅助类提供的方法接口如下所示:

///

<summary>


///
鼠标输入处理代理

///

</summary>


///

<param name="button">
操作的鼠标键
</param>


///

<returns>
如果想应用程序能捕捉到,设置为True;如果设置为False,则鼠标事件被屏蔽。
</returns>



public
delegate
bool
MouseButtonHandler(MouseButtons button);

///

<summary>


///
鼠标按键按下处理操作

///

</summary>



public
static
MouseButtonHandler ButtonDown;

///

<summary>


///
鼠标按键弹起处理操作

///

</summary>



public
static
MouseButtonHandler ButtonUp;

///

<summary>


///
鼠标移动处理操作

///

</summary>



public
static
MouseMoveHandler Moved;

///

<summary>


///
鼠标滚动处理操作

///

</summary>



public
static
MouseScrollHandler Scrolled;

///

<summary>


///
启动鼠标钩子处理

///

</summary>


///

<returns>
如无异常则返回True
</returns>



public
static
bool
Enable()

///

<summary>


///
禁用鼠标钩子操作

///

</summary>


///

<returns>
禁用成功则返回True
</returns>


public
static
bool
Disable()

2)辅助类

MouseHook的使用例子代码如下所示

private
void
btnMouseHook_Click(
object
sender, EventArgs e)
{
MouseHook.ButtonDown =
new
MouseHook.MouseButtonHandler(TestMouseHook);
MouseHook.Scrolled =
new
MouseHook.MouseScrollHandler(TestMouseScroll);
MouseHook.Enable();
}

private
bool
TestMouseHook(MouseButtons sender)
{
this
.Text =
string
.Format(
"
你单击了鼠标键:{0}
"
, sender);
return
true
;
}

private
bool
TestMouseScroll(
int
delta)
{
this
.Text =
string
.Format(
"
你滚动了鼠标值:{0}
"
, delta);
return
true
;

}

整理文档本身也对类库进行进一步的优化,整理过程本身也是一次马拉松式的身心赛跑。