使用C#封装Win32API
微软.NET框架的类库功能强大,内容丰富,可以处理大部分的编程要求,但在一些场合下,.NET框架类库不提供支持,此时需要借助Win32API来实现了。
一般的小弟不推荐在.NET程序中使用Win32API,因为这样不符合.NET编程的安全框架,而且让程序绑定到特定的操作系统,因为未来你的.NET程序可能不在Win32操作系统下运行。
推荐归推荐,有时候要用还得用,在此说说.NET下使用Win32API,本人现在使用C#,因此在此只说说C#语言来使用Win32API。
在C#使用Win32API很方便,只需要从指定的DLL文件中导入函数声明即可。比如在某个类中写下
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(int hDC , int index );
此后程序就像调用静态函数一样调用这个API函数了。这有点类似VB中声明API了。
大家知道,Win32API是平面结构,将一个DLL中的API罗列出来,成百上千的API一字排开,好生壮观,可惜使用不方便,调用它们需要了解各个API入口和出口以及各个API之间的影响,而且一些API比较危险,需要小心调用,若在错误的时间使用错误的参数调用错误的API则可能导致系统资源泄漏,程序突然退出,甚至会伤害操作系统。
而.NET类库则是树状的立体结构,它使用了面向对象的编程结构,从而掩盖了很多细节,我们调用也方便,也很安全。
以前小弟为了调用API就是在到用的时候就声明API,或者作个模块,列出很多API声明供其他地方调用。经验告诉我,这种简单的用法不够好。于是小弟就开始使用C#的语法结构来封装API。
在此使用API函数GetDeviceCaps作例子,这个函数就是获得指定设备上下文的某些信息,参数为设备上下文句柄(hdc)和类型为DeviceCapsConst信息编号。这个设备上下文句柄是个比较重的句柄,严禁浪费,用完只后需要释放掉该句柄,但释放HDC并不简单,需要知道句柄的来源,当使用CreateDC获得的句柄则必须使用DeleteDC来释放。
对于比较重要的资源,比如句柄,文件,数据库连接等等,有个原则就是尽晚获得,尽早释放,因此需要尽量减少持有句柄的时间。
小弟定义了一个类DeviceCapsClass,用于封装GetDeviceCaps,在获得一个句柄时就立即多次调用GetDeviceCaps来获得所有的信息,然后保存到一个缓冲区中,然后立即释放句柄。并定义了方便的访问缓冲数据的接口。这样其他程序只需要实例化一个DeviceCapsClass,调用它的属性就可获得设备上下文信息而无需考虑细节。
其实这种做法.NET框架类库自己就这么搞,大家看看.NET类库的反编译结果,可以看到.NET类库中有很多就是Win32API的封装。相信大家已经这么做了或将来也这样做。
现列出DeviceCapsClass所有代码
using System;
namespace Windows32
{
/// <summary>
/// 获得指定设备上下文信息的对象,本模块为API函数GetDeviceCaps的封装
/// </summary>
/// <remarks>编制 有为青年 XDesigner 2006-5-4</remarks>
public class DeviceCapsClass
{
#region 静态成员 **************************************************************************
private static DeviceCapsClass myDisplayInstance = null;
/// <summary>
/// 针对屏幕的设备上下文信息对象
/// </summary>
/// <remarks>程序可能经常访问屏幕的设备上下文信息,在此专门提供静态成员给予访问</remarks>
public static DeviceCapsClass DispalyInstance
{
get
{
if( myDisplayInstance == null)
{
myDisplayInstance = new DeviceCapsClass();
myDisplayInstance.ResetForDisplay();
}
return myDisplayInstance ;
}
}
#endregion
#region 构造函数 **************************************************************************
/// <summary>
/// 无作为的初始化对象
/// </summary>
public DeviceCapsClass()
{
}
/// <summary>
/// 使用指定设备上下文初始化对象
/// </summary>
/// <param name="hdc">设备上下文句柄</param>
public DeviceCapsClass( int hdc )
{
Reset( hdc );
}
/// <summary>
/// 使用指定设备名初始化对象
/// </summary>
/// <remarks>本函数根据名称创建设备上下文,获得所需数据后立即删除设备上下文</remarks>
/// <param name="DriverName">设备名</param>
public DeviceCapsClass( string vDriverName )
{
Reset( vDriverName );
}
#endregion
private string strDriverName = null;
/// <summary>
/// 设备名称
/// </summary>
public string DriverName
{
get{ return strDriverName ;}
}
public void Reset( int hDC )
{
strDriverName = null;
System.Array myValues = System.Enum.GetValues( typeof( enumDeviceCapsConst ));
intValues = new int[ myValues.Length * 2 ];
for(int iCount = 0 ; iCount < myValues.Length ; iCount ++ )
{
int CapsValue = Convert.ToInt32( myValues.GetValue( iCount ));
intValues[iCount * 2 ] = CapsValue ;
intValues[iCount * 2 + 1] = GetDeviceCaps( hDC , CapsValue );
}
}
public void Reset( string vDriverName )
{
int hdc = CreateDC( vDriverName , null , 0 , 0 );
if( hdc != 0 )
{
Reset( hdc );
DeleteDC( hdc );
strDriverName = vDriverName ;
}
}
public void ResetForDisplay( )
{
Reset( "DISPLAY" );
}
/// <summary>
/// 已重载:获得对象所有内容的字符串
/// </summary>
/// <returns></returns>
public override string ToString()
{
if( intValues == null)
return "DeviceCapsClass:对象尚未初始化";
System.Text.StringBuilder myStr = new System.Text.StringBuilder();
myStr.Append("DeviceCapsClass");
if( strDriverName != null)
myStr.Append(" Driver:" + strDriverName );
System.Array myValues = System.Enum.GetValues( typeof( enumDeviceCapsConst ));
foreach( enumDeviceCapsConst dc in myValues )
{
myStr.Append( System.Environment.NewLine );
myStr.Append( dc.ToString() + " = " + GetValue( dc ) );
}
return myStr.ToString();
}
#region 获得数据的属性群 ******************************************************************
/// <summary>
/// Device driver version
/// </summary>
public int DRIVERVERSION{ get { return GetValue( enumDeviceCapsConst.DRIVERVERSION );} }
/// <summary>
/// Device classification
/// </summary>
public int TECHNOLOGY { get { return GetValue( enumDeviceCapsConst.TECHNOLOGY );} }
/// <summary>
/// Horizontal size in millimeters
/// </summary>
public int HORZSIZE { get { return GetValue( enumDeviceCapsConst.HORZSIZE );} }
/// <summary>
/// Vertical size in millimeters
/// </summary>
public int VERTSIZE { get { return GetValue( enumDeviceCapsConst.VERTSIZE );} }
/// <summary>
/// Horizontal width in pixels
/// </summary>
public int HORZRES { get { return GetValue( enumDeviceCapsConst.HORZRES );} }
/// <summary>
/// Vertical width in pixels
/// </summary>
public int VERTRES { get { return GetValue( enumDeviceCapsConst.VERTRES );} }
/// <summary>
/// Logical pixels/inch in X
/// </summary>
public int LOGPIXELSX { get { return GetValue( enumDeviceCapsConst.LOGPIXELSX );} }
/// <summary>
/// Logical pixels/inch in Y
/// </summary>
public int LOGPIXELSY { get { return GetValue( enumDeviceCapsConst.LOGPIXELSY );} }
/// <summary>
/// Number of planes
/// </summary>
public int PLANES { get { return GetValue( enumDeviceCapsConst.PLANES );} }
/// <summary>
/// Number of brushes the device has
/// </summary>
public int NUMBRUSHES { get { return GetValue( enumDeviceCapsConst.NUMBRUSHES );} }
/// <summary>
/// Number of colors the device supports
/// </summary>
public int NUMCOLORS { get { return GetValue( enumDeviceCapsConst.NUMCOLORS );} }
/// <summary>
/// Number of fonts the device has
/// </summary>
public int NUMFONTS { get { return GetValue( enumDeviceCapsConst.NUMFONTS );} }
/// <summary>
/// Number of pens the device has
/// </summary>
public int NUMPENS { get { return GetValue( enumDeviceCapsConst.NUMPENS );} }
/// <summary>
/// Length of the X leg
/// </summary>
public int ASPECTX { get { return GetValue( enumDeviceCapsConst.ASPECTX );} }
/// <summary>
/// Length of the hypotenuse
/// </summary>
public int ASPECTXY { get { return GetValue( enumDeviceCapsConst.ASPECTXY );} }
/// <summary>
/// Length of the Y leg
/// </summary>
public int ASPECTY { get { return GetValue( enumDeviceCapsConst.ASPECTY );} }
/// <summary>
/// Size required for device descriptor
/// </summary>
public int PDEVICESIZE { get { return GetValue( enumDeviceCapsConst.PDEVICESIZE );} }
/// <summary>
/// Clipping capabilities
/// </summary>
public int CLIPCAPS { get { return GetValue( enumDeviceCapsConst.CLIPCAPS );} }
/// <summary>
/// Number of entries in physical palette
/// </summary>
public int SIZEPALETTE { get { return GetValue( enumDeviceCapsConst.SIZEPALETTE );} }
/// <summary>
/// Number of reserved entries in palette
/// </summary>
public int NUMRESERVED { get { return GetValue( enumDeviceCapsConst.NUMRESERVED );} }
/// <summary>
/// Actual color resolution
/// </summary>
public int COLORRES { get { return GetValue( enumDeviceCapsConst.COLORRES );} }
/// <summary>
/// Physical Printable Area x margin
/// </summary>
public int PHYSICALOFFSETX { get { return GetValue( enumDeviceCapsConst.PHYSICALOFFSETX );} }
/// <summary>
/// Physical Printable Area y margin
/// </summary>
public int PHYSICALOFFSETY { get { return GetValue( enumDeviceCapsConst.PHYSICALOFFSETY );} }
/// <summary>
/// Physical Height in device units
/// </summary>
public int PHYSICALHEIGHT{ get { return GetValue( enumDeviceCapsConst.PHYSICALHEIGHT );} }
/// <summary>
/// Physical Width in device units
/// </summary>
public int PHYSICALWIDTH { get { return GetValue( enumDeviceCapsConst.PHYSICALWIDTH );} }
/// <summary>
/// Scaling factor x
/// </summary>
public int SCALINGFACTORX { get { return GetValue( enumDeviceCapsConst.SCALINGFACTORX );} }
/// <summary>
/// Scaling factor y
/// </summary>
public int SCALINGFACTORY { get { return GetValue( enumDeviceCapsConst.SCALINGFACTORY );} }
public int LISTEN_OUTSTANDING{ get { return GetValue( enumDeviceCapsConst.LISTEN_OUTSTANDING );} }
/// <summary>
/// Curve capabilities
/// </summary>
public int CURVECAPS{ get { return GetValue( enumDeviceCapsConst.CURVECAPS );} }
/// <summary>
/// Line capabilities
/// </summary>
public int LINECAPS{ get { return GetValue( enumDeviceCapsConst.LINECAPS );} }
/// <summary>
/// Polygonal capabilities
/// </summary>
public int POLYGONALCAPS { get { return GetValue( enumDeviceCapsConst.POLYGONALCAPS );} }
/// <summary>
/// Text capabilities
/// </summary>
public int TEXTCAPS { get { return GetValue( enumDeviceCapsConst.TEXTCAPS );} }
#endregion
#region 声明 Win32 API 函数及常量 *********************************************************
[System.Runtime.InteropServices.DllImport("gdi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private static extern int GetDeviceCaps(int hDC , int index );
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private static extern int ReleaseDC(int hWnd, int hDC);
[System.Runtime.InteropServices.DllImport("gdi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private static extern int CreateDC( string strDriver , string strDevice , int Output , int InitData );
[System.Runtime.InteropServices.DllImport("gdi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private static extern int DeleteDC( int Hdc );
/// <summary>
/// 为Win32API函数GetDeviceCaps的第二个参数配备的枚举变量
/// </summary>
private enum enumDeviceCapsConst
{
/// <summary>
/// Device driver version
/// </summary>
DRIVERVERSION = 0 ,
/// <summary>
/// Device classification
/// </summary>
TECHNOLOGY = 2 ,
/// <summary>
/// Horizontal size in millimeters
/// </summary>
HORZSIZE = 4 ,
/// <summary>
/// Vertical size in millimeters
/// </summary>
VERTSIZE = 6 ,
/// <summary>
/// Horizontal width in pixels
/// </summary>
HORZRES = 8 ,
/// <summary>
/// Vertical width in pixels
/// </summary>
VERTRES = 10 ,
/// <summary>
/// Logical pixels/inch in X
/// </summary>
LOGPIXELSX = 88 ,
/// <summary>
/// Logical pixels/inch in Y
/// </summary>
LOGPIXELSY = 90 ,
/// <summary>
/// Number of planes
/// </summary>
PLANES = 14 ,
/// <summary>
/// Number of brushes the device has
/// </summary>
NUMBRUSHES = 16 ,
/// <summary>
/// Number of colors the device supports
/// </summary>
NUMCOLORS = 24 ,
/// <summary>
/// Number of fonts the device has
/// </summary>
NUMFONTS = 22 ,
/// <summary>
/// Number of pens the device has
/// </summary>
NUMPENS = 18 ,
/// <summary>
/// Length of the X leg
/// </summary>
ASPECTX = 40 ,
/// <summary>
/// Length of the hypotenuse
/// </summary>
ASPECTXY = 44 ,
/// <summary>
/// Length of the Y leg
/// </summary>
ASPECTY = 42 ,
/// <summary>
/// Size required for device descriptor
/// </summary>
PDEVICESIZE = 26 ,
/// <summary>
/// Clipping capabilities
/// </summary>
CLIPCAPS = 36 ,
/// <summary>
/// Number of entries in physical palette
/// </summary>
SIZEPALETTE = 104 ,
/// <summary>
/// Number of reserved entries in palette
/// </summary>
NUMRESERVED = 106 ,
/// <summary>
/// Actual color resolution
/// </summary>
COLORRES = 108 ,
/// <summary>
/// Physical Printable Area x margin
/// </summary>
PHYSICALOFFSETX = 112 ,
/// <summary>
/// Physical Printable Area y margin
/// </summary>
PHYSICALOFFSETY = 113 ,
/// <summary>
/// Physical Height in device units
/// </summary>
PHYSICALHEIGHT = 111 ,
/// <summary>
/// Physical Width in device units
/// </summary>
PHYSICALWIDTH = 110 ,
/// <summary>
/// Scaling factor x
/// </summary>
SCALINGFACTORX = 114 ,
/// <summary>
/// Scaling factor y
/// </summary>
SCALINGFACTORY = 115 ,
LISTEN_OUTSTANDING = 1 ,
/// <summary>
/// Curve capabilities
/// </summary>
CURVECAPS = 28 ,
/// <summary>
/// Line capabilities
/// </summary>
LINECAPS = 30 ,
/// <summary>
/// Polygonal capabilities
/// </summary>
POLYGONALCAPS = 32 ,
/// <summary>
/// Text capabilities
/// </summary>
TEXTCAPS = 34 ,
}
#endregion
#region 内部私有成员 **********************************************************************
private int[] intValues = null;
private int GetValue( enumDeviceCapsConst CapsValue)
{
if( intValues == null)
return int.MinValue ;
for(int iCount = 0 ; iCount < intValues.Length ; iCount += 2 )
{
if( intValues[iCount] == Convert.ToInt32( CapsValue) )
return intValues[iCount+1];
}
return int.MinValue ;
}
#endregion
}//public class DeviceCapsClass
}