User32 SetWindowLong接受int而不是long

时间:2016-01-03 14:30:53

标签: c# user32

当我尝试在C#,SetWindowLong中调用User32.dll中的函数时,没有任何反应。我知道为什么,但我不知道如何修理"这个。 这是一段代码。

[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没有。在快速检查代码后,我发现了一些有趣的东西。变量" actualStyle"在GetWindowLong等于4295295232之后,在OR运算4295295240之后。这是问题,函数SetWindowLong接受dwNewLong为整数。当我在SetWindowLong的定义中用long更改int时,pinvoke会抛出一个错误,因为"无法匹配的函数和目标函数"。

它如何解决?

1 个答案:

答案 0 :(得分:3)

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

现在关于问题标题,SetWindowLongGetWindowLong必须声明为int,而不是long
这有以下两个原因。首先,C和C#之间的差异。整个Windows API文档用C术语where long means 32 bits signed integer定义,但C#威胁long定义为64位有符号整数,因此给出了错误。使用64位的函数在API文档中声明为long long 这种差异的另一个原因是历史性的。这两个函数都是在Windows的16位时代创建的,int为16位,long为32位。 int类型后来被扩展,但long保持不变。该名称未更改以保持兼容性。