該聲明是錯誤的,wParam和lParam參數是IntPtr,不長。
由於您嘗試發送字符串,因此會出現複雜情況。如果目標窗口是Unicode啓用或不啓用,那麼重要。有兩個版本的SendMessage,SendMessageA()和SendMessageW()。如果程序過期並使用8位字符串而不是UTF-16編碼字符串,則需要使用前者。
你可以通過使用Spy ++找到。使用取景器工具選擇應用程序的窗口。在General屬性選項卡中,您會看到「Window proc」。它會說(Unicode)該窗口是否啓用了Unicode。如果你沒有看到它,那麼字符串必須被轉換爲8位字符。
要生成需要傳遞的字符串指針,可以使用Marshal.StringToHGlobalAnsi或StringToHGlobalUni(分別爲8位和Unicode)。然而,您可以玩一些技巧讓P/Invoke編組人員爲您翻譯字符串。在通話結束後,您不必麻煩地取出字符串,這讓您省卻麻煩。對於ANSI版本,你可以宣佈這樣的API函數:
[DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
和Unicode版本是這樣的:
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
最後一點:這是行不通的,是如果該窗口屬於另一個應用程序,你會崩潰它。你傳遞的指針值只在你自己的進程中有效,而不在C++進程中。要解決該問題,您必須在目標進程中分配內存,以便指針有效。這需要OpenProcess獲得進程的句柄,VirtualAllocEx()在目標進程中分配內存,足以存儲字符串WriteProcessMemory以寫入字符串。現在,您可以調用SendMessage(),使用用IntPtr聲明的版本作爲wParam和lParam參數,傳遞從VirtualAllocEx獲得的值。接下來使用VirtualFreeEx()釋放內存和CloseHandle進行清理。或者如果你經常這樣做,下次保持記憶。
很多P/Invoke在那裏出錯。更不用說安全問題了,WriteProcessMemory需要管理員權限,UAC提升是必需的。
我相信'MarshalAs'屬性是有序的。 – ChaosPandion 2010-06-22 15:13:03