0

我们的应用程序中有以下 C# 代码:

private IntPtr _DefaultWndProc = IntPtr.Zero;

[DllImport("user32")]
private static extern IntPtr SetWindowLongPtr(IntPtr hwnd, int index, 
                                              WndProcPointer wndProcPointer);

[DllImport("user32")]
private static extern IntPtr SetWindowLongPtr(IntPtr hwnd, int index, 
                                              IntPtr wndProc);

[DllImport("user32")]
private static extern IntPtr GetWindowLongPtr(IntPtr hwnd, int index);

[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern int CallWindowProc(IntPtr wndProc, IntPtr hwnd, int msg, 
                                         IntPtr wparam, IntPtr lparam);

private const int GWL_WNDPROC = (-4);
private const int WM_NCDESTROY = 0x0082;
private delegate int WndProcPointer(IntPtr hwnd, nt msg, 
                                    IntPtr wparam, IntPtr lparam);

protected virtual int WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam)
{ 
  return CallWindowProc(_DefaultWndProc, hwnd, msg, wparam, lparam);
}

_DefaultWndProc设置如下:

_DefaultWndProc = SetWindowLongPtr(control.Handle, GWL_WNDPROC, _MyWndProc);

当我们为 32 位配置编译并执行该程序时,一切正常。

但是,如果我们将配置设置为 64 位,上面列出的方法调用CallWindowProc(_DefaultWndProc, hwnd, msg, wparam, lparam)会抛出以下异常:

System.OverflowException - {"Arithmetic operation resulted in an overflow."}

仅当我们将鼠标光标移到ListView.

任何想法 ?

4

2 回答 2

1
 private delegate int WndProcPointer(IntPtr hwnd, nt msg, 
                                     IntPtr wparam, IntPtr lparam);

您的声明是错误的,返回值是 IntPtr,而不是 int。我认为味精的类型是错字。是的,这可能会在 64 位模式下造成麻烦。

有更好的方法来做到这一点:

  1. 从 ListView 派生您自己的类并覆盖其 WndProc() 方法

  2. 从 NativeWindow 派生您自己的类并覆盖其 WndProc() 方法。调用 this.DefWndProc() 来传递消息。一旦你有一个有效的窗口句柄,就使用它的 Attach() 方法。当您获得 WM_NCDESTROY 时,在您的 WndProc() 覆盖中调用 Detach()。

于 2013-07-17T13:19:49.290 回答
0

出于好奇,如果你改变会发生什么:

private static extern IntPtr SetWindowLongPtr(IntPtr hwnd, int index, WndProcPointer wndProcPointer);

private static extern IntPtr SetWindowLongPtr(IntPtr hwnd, IntPtr index, WndProcPointer wndProcPointer);

将 index 更改为 aIntPtr而不是int. 我从以下 SO question 中得到了这个想法

64 位 Windows 上的 P/Invoke 是否需要与 32 位不同的签名?

于 2013-07-17T10:28:37.057 回答