| 特性 | SendMessage | PostMessage |
|---|---|---|
| 回傳值 | LRESULT(訊息處理後的回傳值) | BOOL(是否成功放入佇列) |
| 同步性 | 同步:等待處理完成才回傳 | 非同步:放入佇列即回傳 |
| 同執行緒行為 | 直接呼叫視窗程序,不進佇列 | 放入執行緒訊息佇列,經迴圈分派 |
| 跨執行緒行為 | 放入目標執行緒佇列並等待 | 放入目標執行緒佇列不等待 |
| 系統自動封送 | 系統訊息(0~WM_USER)自動封送 | 系統訊息自動封送 |
| 使用者訊息(WM_USER+) | 需自行封送 | 需自行封送 |
| 指標參數安全性 | 安全(等待處理) | 不安全(發送者可能提早釋放記憶體) |
public class Win32API {
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref My_lParam lParam);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, ref My_lParam lParam);
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
public struct My_lParam { public int i; public string s; }
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT {
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)] public string lpData;
}
}
SendMessage/PostMessage 皆成功(wParam/lParam 直接傳 int)。SendMessage 成功;PostMessage 結構體傳遞失敗(指標失效)。SendMessage 成功;PostMessage 失敗。結論:跨執行緒/進程傳遞結構體或字串必須用 SendMessage,PostMessage 僅適合簡單整數參數。
protected override void DefWndProc(ref Message m) {
switch (m.Msg) {
case 0x60: // 兩個 int
label1.Text = m.WParam.ToInt32() + "-" + m.LParam.ToInt32(); break;
case 0x61: // 結構體
My_lParam ml = (My_lParam)m.GetLParam(typeof(My_lParam));
label2.Text = ml.i + ":" + ml.s; break;
case 0x62: // COPYDATASTRUCT
COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
label3.Text = cds.lpData; break;
// PostMessage 對應 0x63/0x64/0x65 僅整數成功
default: base.DefWndProc(ref m); break;
}
}