首先发送SendMessageTimeout的文档:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644952%28v=vs.85%29.aspx
我有这个C ++代码,我想将其转换为C#:
LRESULT success = SendMessageTimeout(
HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
(LPARAM) "Environment",
SMTO_ABORTIFHUNG,
5000,
NULL
);
我在C#中做了什么:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
uint Msg,
UIntPtr wParam,
IntPtr lParam,
uint fuFlags,
uint uTimeout,
out UIntPtr lpdwResult
);
SendMessageTimeout(
(IntPtr)0xFFFFFFFF, //HWND_BROADCAST
0x001A, //WM_SETTINGCHANGE
(UIntPtr)0,
(IntPtr)"Environment", // ERROR_1: can't convert string to IntPtr
0x0002, // SMTO_ABORTIFHUNG
5000,
out UIntPtr.Zero // ERROR_2: a static readonly field can not be passed ref or out
);
答案 0 :(得分:5)
对于你的问题。
0xFFFF
而不是0xFFFFFFFF
lpdwResult
,只需创建一个IntPtr
变量并将其传入。您可以忽略其值。代码应该是这样的:
IntPtr result = IntPtr.Zero;
IntPtr setting = Marshal.StringToHGlobalUni("Environment");
SendMessageTimeout(
(IntPtr)0xFFFF, //HWND_BROADCAST
0x001A, //WM_SETTINGCHANGE
(UIntPtr)0,
(IntPtr)setting,
0x0002, // SMTO_ABORTIFHUNG
5000,
out result
);
Marshal.FreeHGlobal(setting);
一般情况下,在释放传递给SendMessage
调用的内存时需要小心,因为您不知道接收窗口将对您传递给它的指针执行什么操作。由于WM_SETTINGCHANGE
是内置的Windows消息,因此Windows将为您处理此指针。
答案 1 :(得分:5)
SendMessage由于它使用的非描述参数类型而有点痛苦。必要的是因为它需要做很多工作。在C语言中是必需的,但在C#中则不然。你想要做的是利用支持重载的C#语言。 IntPtr参数可以只是引用类型引用,pinvoke marshaller会正确地将它们转换为指针并处理内存管理的麻烦。因此,只需制作另一个与您想要使用它的方式兼容的产品:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
int Msg,
IntPtr wParam,
string lParam,
int fuFlags,
int uTimeout,
IntPtr lpdwResult
);
现在你可以使用:
SendMessageTimeout((IntPtr)0xffff, 0x001A, IntPtr.Zero, "Environment",
2, 5000, IntPtr.Zero);