User32 SetWindowLong接受int而不是long

本文关键字:long int SetWindowLong 接受 User32 | 更新日期: 2023-09-27 18:28:51

当我尝试从C#中的User32.dll,SetWindowLong中调用函数时,什么都没有发生。我知道为什么,但我不知道如何"修复"这个。这是一段代码。

[DllImport("user32.dll")]
public static extern long GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
public static extern long SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
const int WS_EX_TOPMOST = 0x00000008;
const int GWL_EXSTYLE = -20;
public static bool IsWindowTopMost(int id)
{
    return (GetWindowLong(GetHWNDById(id), GWL_EXSTYLE) & WS_EX_TOPMOST) == WS_EX_TOPMOST;
}
public static void SetAlwaysOnTop(int id)
{
    IntPtr hWnd = GetHWNDById(id);
    long actuallyStyle = GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_TOPMOST;
    SetWindowLong(hWnd, GWL_EXSTYLE, (int)actuallyStyle));
}

IsWindowTopMost运行良好,但SetAlwaysOnTop不正常。经过对代码的快速检查,我发现了一些有趣的东西。在"或"运算4295295240之后,GetWindowLong之后的变量"actuallyStyle"等于4295295322。问题是,函数SetWindowLong接受一个整数作为dwNewLong。当我在SetWindowLong的定义中将int改为long时,pinvoke会抛出一个错误,因为"函数和目标函数不匹配"。

它是如何传播的?

User32 SetWindowLong接受int而不是long

将窗口始终放在顶部的正确方法是使用SetWindowPos函数。问题很可能是SetWindowLong只是设置了一个变量,但SetWindowPos实际上通知窗口管理器进行所需的重绘,所以请使用它。

现在关于问题标题,SetWindowLongGetWindowLong都必须声明为int,而不是long
这有两个原因。首先,C和C#之间的区别。整个Windows API文档都是用C术语定义的,其中long表示32位带符号整数,但C#威胁long为64位带符号的整数,因此会给出您得到的错误。使用64位的函数在API文档中声明为long long
造成这种差异的另一个原因是历史原因。这两个函数都是在Windows的16位时代创建的,其中int是16位,long是32位。int型在后一个时期得到扩展,但long仍保持原样。没有更改名称以保持兼容性。