先給SendMessage範例
以下範例都要先加入 using System.Runtime.InteropServices;
SendMessage A端(控制端):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace TestA
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
uint MSG_SHOW = RegisterWindowMessage("Show Message");
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
IntPtr form_name = FindWindow(null, "要控制的視窗元件名稱(text,不是name)");//找B的IntPtr 用來代表指標或控制代碼
if (form_name != IntPtr.Zero)
{
try
{
int iNum = 9527;
SendMessage(form_name, MSG_SHOW, iNum, IntPtr.Zero);
}
catch (Exception)
{
}
}
}
}
}
SendMessage B端(接收端):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace TestB
{
public partial class TestB_1 : Form
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
uint MSG_SHOW = RegisterWindowMessage("Show Message");
public TestB_1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == MSG_SHOW)
{
label1.Text = (string)m.WParam.ToString();
}
base.WndProc(ref m);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace postmessager
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private void post()
{
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr ptr = FindWindow(null, "post messager B");
if (ptr != IntPtr.Zero)
{
int msg = 9527;
PostMessage(ptr, msg, IntPtr.Zero, IntPtr.Zero);
}
}
}
}
PostMessage B端(接收端):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace PostmessagerB
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 9527)//m.Msg == MSG_SHOW
{
//label1.Text = (string)m.WParam.ToString();
MessageBox.Show("9527");
}
base.WndProc(ref m);
}
}
}
至於為何可以使用SendMessage(),PostMessage(),FindWindow(),RegisterWindowMessage(),都是要先
import user32.dll (也就是[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 後面為參數)
然後接收端使用WndProc (WindowProcess,我個人理解縮寫函意)去接收。
大部分程式碼也是參考網路上的,但大家都抄來抄去,而且我有修改程式碼,所以就不註明出處了(因為也不知道原始是誰的),當然我的版本是比較精簡化。
End
End
請問PostMessage接收端有需要宣告win32api嗎?
回覆刪除我在VS2008下編譯好像會不給過
錯誤 1 必須是類別、委派、列舉、介面或結構
protected override void WndProc(ref Message m)
不好意思 我的問題解決了..
刪除^^ good!
刪除謝謝版大詳細的熱心分享!!
回覆刪除不知道您是否可以分享PeekMessage 與 GetMessage這兩個函數在C#上的使用呢?
(這兩個函數可以查到的資料更少Q_Q)
再次感謝!!
目前還沒有寫到關於Peek & Get這部份耶!
刪除但這篇我想您可以參考看看
http://blog.xuite.net/grimmslaw/78/55733626-GetMessage+PeekMessage+WaitMessage%E5%87%BD%E6%95%B8%E7%9A%84%E7%94%A8%E6%B3%95
希望對您有幫助!
謝謝您提供的資訊! 我會好好研究@@
刪除另外想請問版大!
假設我用PostMessage要如何傳遞結構(structure)?
我是參考 http://msdn.microsoft.com/zh-tw/library/4ca6d5z7(v=vs.110).aspx
想法:
(A端)
struct AStudent
{
public string name;
public int number;
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr ptr = FindWindow(null, "PostMessage-Get");
AStudent ATom;
ATom.name = "Tom";
ATom.number = 1;
// Initialize unmanged memory to hold the struct.
IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(ATom));
Marshal.StructureToPtr(ATom, pnt, false);
if (ptr != IntPtr.Zero)
{
int msg = 9527;
PostMessage(ptr, msg, IntPtr.Zero, pnt);
}
}
B端
struct BStudent
{
public string name;
public int number;
}
protected override void WndProc(ref Message m) //WndProc():Processes Windows messages.
{
if (m.Msg == 9527)//m.Msg == MSG_SHOW
{
label1.Text = Convert.ToString(m.Msg);
BStudent BTom;
BTom = (BStudent)Marshal.PtrToStructure(m.LParam, typeof(BStudent));
label3.Text = BTom.name;
}
base.WndProc(ref m);
}
但在傳資料時(A端按下button), B端的
BTom = (BStudent)Marshal.PtrToStructure(m.LParam, typeof(BStudent));
此行出現錯誤, 不知為什麼>_<
想請問版主我這樣寫哪裡出了問題 還是根本不該這樣寫Orz
謝謝!!
可能要麻煩您有完整的錯誤訊息會比較好研究,
刪除如果說是要傳結構,我覺得用Serialize/Deserialize也很不錯~
因為WndProc()會不停的一直找尋是否有message進來,如果只是單純要把
東西傳到另一支程式,可以試試看用開檔讀檔的方式(前面幾篇有寫到序列化)
另外可以設中斷點(F9)在那一行,看看傳入的型態是甚麼?
刪除不過沒有完整的錯誤訊息可能debug稍稍困難
嗯!謝謝回覆!
刪除我直接把出問題的敘述貼到imgur這個照片分享空間@@
http://imgur.com/0gXjJId
希望版主能幫我看一下>_<
另外, 我也有去讀版主建議我看您之前寫的"序列化"並測試過基本功能OK!
也是個非常好的結構傳遞方式!!
但還是希望能搞清楚用PostMessage傳資料到底是哪裡出了問題Orz
謝謝!!
其實這問題我也是第一次看到,但我想....會不會是需要加unsafe?
刪除一同學習囉!
謝謝建議! 但我用unsafe試過也不太行QQ
刪除請問如果要傳結構的話 您會怎麼寫阿?
感恩!!
我剛好有寫到 要兩支程式傳結構的部分,但不曉得是否為你需要的?
刪除不論如何,講一下我的想法,首先是先建立一個類別(可序列化)
1.A程式先把要的資料(Student,PhoneNumber,Name)放入structure
2.把Structure利用Stream方式+Serialize寫入檔案(我是用.dat,反正別人開不了就是了)
3.在另一支程式定期去收(利用timer)或是利用postmessage通知說 我寫入囉~(這邊很隨意,就是有通知就好了)然後Deserialize 然後就可在另一支程式上有這樣完整的Structure了:)
嗯!! 瞭解了 謝謝!
刪除我也用您教的序列化方式來傳struct吧!
感謝您這麼有耐心的替我解惑T_T
不會~ 這是我想很久,但最容易的方式了(其他方法也是可以 但是都很複雜)
刪除記得要用try catch以免同時開檔(機率很小 我試過) 會有error
恩恩!! 謝謝提醒^____^
刪除