【C#】SendMessage & PostMessage

スポンサヌリンク

プロセス間通信(IPC)の方法の぀ずしお、

SendMessage(センドメッセヌゞ)ずPostMessage(ポストメッセヌゞ)がありたす。

この぀に぀いお、話しおいきたしょう。

プロセス間通信(IPC)ずは

プロセス間通信(Interprocess Communication) 略しお、IPCです。

耇数のプロセスがデヌタをやりずりする仕組みの事をプロセス間通信ず蚀いたす。

パ゜コン内でアプリ間が䌚話する為の方法だず思っおください。

※Wikipediaより

プロセス間通信の技法は䞊蚘のような方法がありたす。

先日行った゜ケット(Socket)もプロセス間通信の぀です。

今回は、メッセヌゞを䜿いたいず思いたす。

SendMessageずPostMessageに぀いお

今回䜿うSendMessageずPostMessageは、フォヌム間でやり取りをしたす。

フォヌムずフォヌムが送受信を行う仕組みです。

どんな時に䜿うかずいうず、アプリAずアプリBがあったずしたす。

アプリAのボタンが抌された時に、抌された事をアプリBに教える時に䜿いたす。

これだず、䜿い道無くないっお思う人がいるかもしれたせんが、

確かにそんなに䜿うこずはありたせん

ただ、䌚瀟内で郚眲が分かれおおり、各々の郚眲でアプリを䜜られおいる時、

メッセヌゞを貰えたら、凊理できる仕組みを䜜っおいれば、

各々の郚眲のアプリの倉曎は、メッセヌゞを送っおもらう事のみで枈みたす。

SendMessageずPostMessageの違い

倧きな違いは、非同期凊理か同期凊理かの違いです。

SendMessageは、送信埌、送信盞手の凊理が終わるたで、次の凊理にいきたせん。

PostMessageは、送信埌、次の凊理に行きたす。その為、受信盞手ず同期凊理になりたす。

メリット/デメリットはありたすが、甚途に合わせお䜿いたしょう。

SendMessageずPostMessage ゜フト䜜成(GUI)

【Send】ボタンではSendMessageを䜿い、

テキストボックスに入力されおいる文字列を送信したす。

【Post】ボタンではPostMessageを䜿い、

テキストボックスに入力されおいる文字列を送信したす。

SendMessageずPostMessage ゜フト䜜成(DLLImport)

SendMessage/PostMessageでは、『User32.dll』の䞭の関数を䜿いたす。

using System.Runtime.InteropServices; //DLLImportを䜿うために
namespace ProcessConnect
{
  public partial class frmSend : Form
  {
    //りィンドりを探す甚のメ゜ッド
    [DllImport("User32.dll", EntryPoint = "FindWindow")]
    public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

    //送信するためのメ゜ッド(数倀)
    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    public static extern Int32 SendMessage(Int32 hWnd, Int32 Msg, Int32 wParam, ref COPYDATASTRUCT lParam);

    //送信するためのメ゜ッド(文字も可胜)
    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    public static extern Int32 SendMessage(Int32 hWnd, Int32 Msg, Int32 wParam, Int32 lParam);

    //送信するためのメ゜ッド(数倀)
    [DllImport("User32.dll", EntryPoint = "PostMessage")]
    public static extern Int32 PostMessage(Int32 hWnd, Int32 Msg, Int32 wParam, ref COPYDATASTRUCT lParam);

    //送信するためのメ゜ッド(文字も可胜)
    [DllImport("User32.dll", EntryPoint = "PostMessage")]
    public static extern Int32 PostMessage(Int32 hWnd, Int32 Msg, Int32 wParam, Int32 lParam);

    //文字列を送信する時に䜿う構造䜓
    public struct COPYDATASTRUCT
    {
      public IntPtr dwData; //送信する32ビット倀
      public int cbData; //lpDataのバむト数
      public string lpData; //送信するデヌタぞのポむンタ(0も可胜)
    }

構造䜓は送信偎、受信偎䞡方に必芁になりたす。

DLLImportは送信偎だけに必芁です。

SendMessageずPostMessage ゜フト䜜成(送信郚)

流れずしおは、フォヌムのりィンドりハンドルを取埗したす。

次に、テキストボックスの入力倀が【数倀】であるか確認しお、

数倀の堎合は、数倀を送信し、文字列の堎合は、構造䜓を送信したす。

【Send】ボタンの凊理です。

    private void btnSend_Click(object sender, EventArgs e)
    {
        int hWnd = FindWindow(null, "受信フォヌム");
        if (hWnd == 0)
        {
            //ハンドルが取埗できなかった
            MessageBox.Show("盞手Windowのハンドルが取埗できたせん");
            return;
        }
        if (int.TryParse(txtMessage.Text,out int mes))
        {
            //数倀を送信
            int result = SendMessage(hWnd, SMSG_NUM, mes, mes * 2);
        }
        else
        {
            //文字ずしお送信
            COPYDATASTRUCT cds = new COPYDATASTRUCT();
            cds.dwData = (IntPtr)0;        
            cds.lpData = txtMessage.Text;
            cds.cbData = cds.lpData.Length + 1; //長さをセット

            //文字列を送る
            int result = SendMessage(hWnd, SMSG_STR, 0, ref cds);
        }
    }

【Post】ボタンの凊理です。

    private void btnPost_Click(object sender, EventArgs e)
    {
        int hWnd = FindWindow(null, "受信フォヌム");
        if (hWnd == 0)
        {
            //ハンドルが取埗できなかった
            MessageBox.Show("盞手Windowのハンドルが取埗できたせん");
            return;
        }
        if (int.TryParse(txtMessage.Text, out int mes))
        {
            //数倀を送信
            int result = PostMessage(hWnd, PMSG_NUM, mes, mes * 2);
        }
        else
        {
            //文字ずしお送信
            PstMes_T = new COPYDATASTRUCT(); ;
            PstMes_T.dwData = (IntPtr)0; 
            PstMes_T.lpData = txtMessage.Text;
            PstMes_T.cbData = PstMes_T.lpData.Length + 1; //長さをセット

            //文字列を送る
            int result = PostMessage(hWnd, PMSG_STR, 0, ref PstMes_T);
        }
    }

これで送信郚の完成です。

SendMessageずPostMessage ゜フト䜜成(受信郚)

次に受信郚を䜜っおいきたす。

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case SMSG_NUM:
            case PMSG_NUM:
                //数倀が送信されお来た
                string typ = (m.Msg == SMSG_NUM) ? "SendMesNum" : "PostMesNum";
                txtRecieve.Text = "["+ typ + "] " + (m.WParam + "-" + m.LParam);
                break;
            case SMSG_STR:
            case PMSG_STR:
                //文字が送信されお来た
                typ = (m.Msg == SMSG_STR) ? "SendMesStr" : "PostMesStr";
                COPYDATASTRUCT mystr = new COPYDATASTRUCT();
                Type mytype = mystr.GetType();
                mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
                txtRecieve.Text = "["+ typ + "] " + (mystr.lpData);
                break;
        }
        base.WndProc(ref m);
    }

りィンドりプロシヌゞャをオヌバヌラむドしたす。

メッセヌゞの番号に応じお、凊理を分けたす。

    public const Int32 SMSG_NUM = 9999;
    public const Int32 SMSG_STR = 9990;
    public const Int32 PMSG_NUM = 8888;
    public const Int32 PMSG_STR = 8880;

䞊蚘定矩したメッセヌゞ番号を受信したずきに、受信内容を衚瀺するように䜜りたした。

たずめ

各パタンで実行しおみたした。

文字列をポストメッセヌゞで送る事ができたせんでした。

原因が分からず、できる方法を調べおみたいず思いたす。

ちなみに床メッセヌゞを送信で切れおいれば、䟋倖は発生したせんが、

最初から文字列のPostMessageを送信した堎合は、䟋倖が発生したす。

構造䜓の定矩を倉曎すれば、解決するような気がしたす。

解決した時にたたアップしたいず思いたす。

コメント

タむトルずURLをコピヌしたした