.NET(C#) 平台调用:不依赖平台的GetWindowLongPtr和SetWindowLongPtr API
来源:互联网 发布:犬神带什么御魂 知乎 编辑:程序博客网 时间:2024/04/30 10:21
http://www.cnblogs.com/mgen/archive/2012/04/09/2439149.html
首先在方法声明上,由于在32位Windows上GetWindowLongPtr和SetWindowLongPtr仅仅是宏定义,不是具体函数,所以只能去使用GetWindowLong和SetWindowLongPtr函数。因此我们需要定义两份这样的函数。其次是参数在不同环境下的变化。比如GetWindowLang的函数原型:
LONG WINAPI GetWindowLong(
__in HWND hWnd,
__in int nIndex
);
它是返回LONG的。而GetWindowLongPtr的函数原型:
LONG_PTR WINAPI GetWindowLongPtr(
__in HWND hWnd,
__in int nIndex
);
它是返回LONG_PTR的。这个LONG_PTR联通其他的类型比如INT_PTR、UINT_PTR、DWORD_PTR……都是用来使定义好的类型不需要改变就可以轻松在32位和64位上的API正确运行。在32位下,它们保持自己的默认大小。在64位下,它们会被扩展成64为下的大小。而注意在.NET下,int永远是32位的(int仅仅是System.Int32类型的别名),而long(System.Int64类型)永远是64位的,因此我们只能用依赖平台大小的IntPtr来表示上述数据类型。
那么首先把这四个API都声明一下:
[DllImport("user32.dll", EntryPoint= "GetWindowLong")]
static externIntPtr GetWindowLong32(IntPtr hWnd,int nIndex);
[DllImport("user32.dll", EntryPoint= "GetWindowLongPtr")]
static externIntPtr GetWindowLong64(IntPtr hWnd,int nIndex);
[DllImport("user32.dll", EntryPoint= "SetWindowLong")]
static externIntPtr SetWindowLong32(IntPtr hWnd,int nIndex,IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint= "SetWindowLongPtr")]
static externIntPtr SetWindowLong64(IntPtr hWnd,int nIndex,IntPtr dwNewLong);
接着用专门的方法判断是32位还是64位执行环境,然后根据环境调用相应的本地API。
//WindowLongFlags的定义可以参考:http://www.pinvoke.net/default.aspx/Enums/WindowLongFlags.html
public staticIntPtr GetWindowLongPtr(IntPtr hWnd,WindowLongFlags nIndex)
{
if (IntPtr.Size== 8)
return GetWindowLong64(hWnd, (int)nIndex);
else
return GetWindowLong32(hWnd, (int)nIndex);
}
public staticIntPtr SetWindowLongPtr(IntPtr hWnd,WindowLongFlags nIndex,IntPtr dwNewLong)
{
if (IntPtr.Size== 8)
return SetWindowLong64(hWnd, (int)nIndex, dwNewLong);
else
return SetWindowLong32(hWnd, (int)nIndex, dwNewLong);
}
方法定义好后,就可以调用它执行了,不过还有一个问题就是枚举值的设置,由于对应枚举对象是依赖平台的,所以把它定义成IntPtr,可是IntPtr对于枚举值的设置可能会遇到麻烦,可以使用如下方法。
首先我们使用这篇文章(.NET(C#):负数位域和正数位域)中的EnumHelper类型,接着定义一个针对基于IntPtr枚举值的有好封装类型:IntPtrEnumHelper如下代码:
static classIntPtrEnumHelper
{
//判读是否包含指定标志位
publicstatic bool HasFlags(IntPtr val,object flag)
{
returnEnumHelper.HasFlag(val.ToInt64(), (long)flag);
}
//设置标志位
publicstatic IntPtr SetFlag(IntPtr val,object flag)
{
returnnew IntPtr(EnumHelper.SetFlag(val.ToInt64(), (long)flag));
}
//取消标志位
publicstatic IntPtr UnsetFlag(IntPtr val,object flag)
{
returnnew IntPtr(EnumHelper.UnsetFlag(val.ToInt64(), (long)flag));
}
}
这样的话,比如我们想要通过SetWindowLongPtr设置窗体的样式。我们可以直接用上面的方法来对基于IntPtr枚举对象进行位域的设置或者取消操作。
如下封装代码:
//WindowLongFlags定义可以参考:http://www.pinvoke.net/default.aspx/Enums/WindowLongFlags.html
//设置标志位
public staticIntPtr SetWindowStyles(IntPtr hWnd,WindowStyles ws)
{
var style= GetWindowLongPtr(hWnd,WindowLongFlags.GWL_STYLE);
return SetWindowLongPtr(hWnd,WindowLongFlags.GWL_STYLE,IntPtrEnumHelper.SetFlag(style, ws));
}
//取消标志位
public staticIntPtr UnsetWindowStyles(IntPtr hWnd,WindowStyles ws)
{
var style= GetWindowLongPtr(hWnd,WindowLongFlags.GWL_STYLE);
return SetWindowLongPtr(hWnd,WindowLongFlags.GWL_STYLE,IntPtrEnumHelper.UnsetFlag(style, ws));
}
代码下载:
参考这篇文章:.NET(C#):Win32窗体API封装工程
- .NET(C#) 平台调用:不依赖平台的GetWindowLongPtr和SetWindowLongPtr API
- SetWindowLongPtr和GetWindowLongPtr函数
- SetWindowLongPtr和GetWindowLongPtr函数
- SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- Windows API一日一练(21)SetWindowLongPtr和GetWindowLongPtr函数
- zTree接受后台传过来的JSON数组
- Redis与Memcached的比较
- VS2005快捷键(新)
- svn图标不显示
- wget 使用技巧
- .NET(C#) 平台调用:不依赖平台的GetWindowLongPtr和SetWindowLongPtr API
- Unix awk命令(3) -- awk命令详解
- Android-WebView的使用
- Linux awk命令详解
- AWK指令详解
- JAVA———窗口布局的综合练习
- hdu 4430 Yukari's Birthday 枚举+二分
- 数学、物理、化学、生物、地理常用软件介绍(草稿)
- openstack遇到问题怎么办