winapiinC#。从IntPtr获取高位和低位字我正在尝试在C#中处理WM_MOUSEMOVE消息。从lParam获取X和Y坐标的正确方法是什么?这是一种IntPtr吗?尝试:(注意这是初始版本,阅读下面的最终版本)IntPtrxy=value;intx=unchecked((短)xy);inty=unchecked((short)((uint)xy>>16));通常不需要未选中(因为“默认”c#项目未选中)考虑以下是所用宏的定义:#defineLOWORD(l)((WORD)(((DWORD_PTR)(l))&0xffff))#defineHIWORD(l)((WORD)((((DWORD_PTR)(l))>>16)&0xffff))#defineGET_X_LPARAM(lp)((int)(short)LOWORD(lp))#defineGET_Y_LPARAM(lp)((int)(short)HIWORD(lp))其中WORD==ushort和DWORD==uint。我正在削减一些ushort->short转换。补充:时隔一年半,在经历了64位.NET的“变幻莫测”后,我同意Celess的观点(但注意,出于兼容性原因,99%的Windows消息仍然是32位的,所以我不认为这个问题现在不是很大。它更适合未来,因为如果你想做某事,你应该做对。)我唯一的区别是:IntPtrxy=value;intx=unchecked((短)(长)xy);inty=unchecked((短)((长)xy>>16));我没有检查“IntPtr是4字节还是8字节长”,而是采用最坏的情况(8字节长)并将xy转换为long。运气好的话,编译器会优化掉双重推导(long,然后是short/touint)(最后,显式转换为IntPtrint是一个红色鲱鱼......如果你使用它,你就会把自己置于危险之中未来。您应该始终转换为long,然后直接使用/重新转换为您需要的内容,向未来的程序员展示您知道自己在做什么。一个测试示例:http://ideone.com/a4oGW2(不幸的是只有32位,但如果你有一台64位机器,你可以测试相同的代码)适用于32位和64位:PointGetPoint(IntPtr_xy){uintxy=unchecked(IntPtr.Size==8?(uint)_xy.ToInt64():(uint)_xy.ToInt32());intx=unchecked((短)xy);inty=unchecked((短)(xy>>16));返回新点(x,y);}–或–intGetIntUnchecked(IntPtrvalue){returnIntPtr.Size==8?未检查((int)value.ToInt64()):值.ToInt32();}intLow16(IntPtrvalue){returnunchecked((short)GetIntUnchecked(value));}intHigh16(IntPtrvalue){returnunchecked((short)(((uint)GetIntUnchecked(value))>>16));这些也有效:intLow16(IntPtrvalue){returnunchecked((short)(uint)value);//经典的unchecked转换为uint}intHigh16(IntPtrvalue){returnunchecked((short)((uint)value>>16));}–或–intLow16(IntPtrvalue){returnunchecked((short)(long)value);//关于内部结构的假设}//框架lib使用的是什么intHigh16(IntPtrvalue){r返回未经检查的((短)((长)值>>16));}走另一条路C定义的好翻译如果你直接处理原始'void*',那么大部分都可以。但是,在.Net64位执行环境'unchecked'中使用'IntPtr'并不能防止从中抛出转换溢出异常未选中时在IntPtr中。未选中的块不会影响IntPtr函数和运算符内部发生的转换。当前接受的答案表明没有必要使用“unchecked”。但是,使用“unchecked”是绝对必要的,因为在以下情况下总是如此从较大的类型转换为负值。在64位上,从接受的答案:varxy=newIntPtr(0x0FFFFFFFFFFFFFFF);intx=unchecked((短)xy);//>16));//幸运的是,'uint'隐式'long'y=unchecked((short)((int)xy>>16));//>16));//仍然幸运y=(short)((uint)xy>>16);//在64位上,使用DmitryG的外推版本:varptr=newIntPtr(0x0FFFFFFFFFFFFFF);varxy=IntPtr.Size==8?(int)ptr.ToInt64():ptr.ToInt32();//>16));//很好,如果到此为止y=unchecked((short)(xy>>16));//也很好,如果得到这么远ptr=newIntPtr(0x00000000FFFF0000);//0,-1xy=IntPtr.Size==8?(int)ptr.ToInt64():ptr.ToInt32();//关于性能返回IntPtr.Size==8?未检查((int)value.ToInt64()):value.ToInt32();IntPtr.Size属性返回一个常量作为编译时文字,如果跨程序集内联则有效。所以JIT几乎可以优化所有这些。也这样做:returnunchecked((int)value.ToInt64());-或-返回未经检查的((int)(long)值);-或-返回未检查((uint)值);//traditionalandall这三个将始终调用IntPtr.ToInt64()的等价物。ToInt64()和operatorlong也可以内联,但可能性较小。32位版本的代码比大小常量多得多。我认为顶部的解决方案在语义上可能更正确。了解符号扩展工件也很重要,它会在(long)int_val之类的东西上填充所有64位,尽管我在这里略微掩盖了这一点,但它可能还会影响32位内联。用法if(Low16(wParam)==NativeMethods.WM_CREATE)){}varx=Low16(lParam);varpoint=GetPoint(lParam);下面显示的“安全”IntPtr模型适用于未来的旅行者。这可以在不设置32位WIN32定义的情况下运行,以获得64位IntPtr行为的可靠模拟。publicstructIntPtrMock{#ifWIN32intm_value;#elselongm_value;#endifintIntPtr_ToInt32(){#ifWIN32返回(int)m_value;#elselongl=m_value;返回选中((int)l);#endif}publicstaticexplicitoperatorint(IntPtrMockvalue){//(短)在这里解析#ifWIN32return(int)value.m_value;#elselongl=value.m_value;返回选中((int)l);//如果有任何高32位,则在此处抛出#endif//检查强制符号保持签名}publicstaticexplicitoperatorlong(IntPtrMockvalue){//(uint)在这里解析#ifWIN32return(long)(int)value.m_value;#elsereturn(long)value.m_value;#endif}publicintToInt32(){#ifWIN32return(int)value.m_value;#elselongl=m_value;返回选中((int)l);//如果有任何高32位,则在此处抛出#endif//检查强制符号保持符号状态}publiclongToInt64(){#ifWIN32return(long)(int)m_value;#else返回(长)m_value;#endif}publicIntPtrMock(longvalue){#ifWIN32m_value=checked((int)value);#elsem_value=值;#endif}}publicstaticIntPtrMAKELPARAM(intlow,inthigh){return(IntPtr)((high>16));//很幸运,'uint'隐式'long'y=unchecked((short)((int)xy>>16));//通常,对于低级鼠标处理,我使用以下帮助程序(它还考虑依赖于x86/x64的IntPtr大小):#winapiin从IntPtr中获取所有的高位和低位字。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注---//...Pointpoint=WinAPIHelper.GetPoint(msg.LParam);//...staticclassWinAPIHelper{publicstaticPointGetPoint(IntPtrlParam){returnnewPoint(GetInt(lParam));}publicstaticMouseButtonsGetButtons(IntPtrwParam){MouseButtons按钮=MouseButtons.None;intbtns=GetInt(wParam);if((btn??s&MK_LBUTTON)!=0)按钮|=MouseButtons.Left;if((btn??s&MK_RBUTTON)!=0)按钮|=MouseButtons.Right;返回按钮;}staticintGetInt(IntPtrptr){返回IntPtr.Size==8?未检查((int)ptr.ToInt64()):ptr.ToInt32();}constintMK_LBUTTON=1;constintMK_RBUTTON=2;}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
