C++ Builder XE4, 10.2 Tokyo > Window Message > 他のアプリに数値を送る > 2つのアプリの実装


動作環境
C++ Builder XE4
Rad Studio 10.2 Tokyo Update 2 (追記: 2017/12/27)

したいこと

あるアプリから別のアプリに数値を送りたい。

以下の例では

  • 子アプリ : カウントダウン
  • 親アプリ : 子アプリへのカウントのフィード

を行う。

参考

(追記 2018/10/24)

下記、VisualStudioのドキュメントであるようだが。。。

static CWnd* PASCAL FindWindow(
   LPCTSTR lpszClassName,
   LPCTSTR lpszWindowName 
);

(下記、強調部分はこちらで強調)

lpszClassName
ウィンドウ クラスの名前 ( WNDCLASS の構造) を指定する NULL で終わる文字列へのポインター。 lpClassName が nullの場合、すべてのクラス名に一致します

「すべてのクラス名に一致」、つまり、起動中のソフトウェア全てが対象になる、
という理解。

子アプリ (Receiver)

UnitReceiver.h
//---------------------------------------------------------------------------

#ifndef UnitReceiverH
#define UnitReceiverH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------

#define WM_IDX (0) // WM_APPに足して使用する

class TForm2 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TLabel *L_countDown;
    TTimer *Timer1;
    void __fastcall Timer1Timer(TObject *Sender);
private:    // ユーザー宣言
public:     // ユーザー宣言
    __fastcall TForm2(TComponent* Owner);
    void __fastcall ReceiveContinue(TMessage & msg);

BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_APP + WM_IDX, TMessage, ReceiveContinue);
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif
UnitReceiver.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UnitReceiver.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------

static int s_currentValue = 20;

static const int kKeyValue = 31415;

__fastcall TForm2::TForm2(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Timer1Timer(TObject *Sender)
{
    s_currentValue--;

    L_countDown->Caption = IntToStr(s_currentValue);
}
//---------------------------------------------------------------------------

void __fastcall TForm2::ReceiveContinue(TMessage & msg)
{
    UINT keyval = msg.WParam;
    LONG continueCount = msg.LParam;

    if (keyval != kKeyValue) {
        return;
    }

    s_currentValue = s_currentValue + continueCount;
}

親アプリ (Sender)

UnitSender.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UnitSender.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------


#define WM_IDX (0) // WM_APPに足して使用する
static const int kKeyValue = 31415;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    HWND hChild;

    hChild = FindWindow(NULL, L"Form2");
    if (hChild == NULL) {
        return;
    }

#if 1
    SendMessage(hChild, WM_APP + WM_IDX, kKeyValue, 20);
#else
    PostMessage(hChild, WM_APP + WM_IDX, kKeyValue, 20);
#endif

    int nop = 1;
}
//---------------------------------------------------------------------------

SendMessage()する時、FindWindow()を前にしないといけないようだ。


子アプリは実行してからカウントダウンしていく。

親アプリ側でボタンを押すと、子アプリ側のカウントが20追加される。

他のアプリを自動終了させる仕組みを考えていて、これが必要になった。
ソフト起動時にカウントダウンの上限を指定しておき、0以下になった時に終了する。
何か作業をした時に、カウントを増やすか初期値に戻す。