LoginSignup
5
4

More than 3 years have passed since last update.

いまさらのMFC

Last updated at Posted at 2020-06-25

MFCの選択

C++でWindowsの処理をするのにC++/Cliとか、C++/CXとか、C++/WinRXとかついていけないし、ハードウエア周りの処理なので、MFCでとりあえず実装することにする。
C++のDLLにして、C#でGUI実装のほうが簡単だけど、ちょっと理由があってC++ですべて作成しないといけない。
MFCのUI部と、ハードウエア周りのコードは別にして、ハードウエア周りは標準のC++で作成したいものです。
C++は最新の文法を使いたい。しかしWin32がwchar_tなので、std::stringとうまく調和しない。いろいろ変換をいれる必要がある

std::string 周りの対応

ハードウエア側はstd::stringでデータを取得するが、MFCのUIに表示するときは、whar_tに変換しないといけない。Windowsの設計思想が20年前ですからね。

MFCのCStringAとCStringを使って変換するのが簡単らしい。

std::string str = "ABCDE";
CStringA str2(str.c_str());
CString str3(str2);

エンコードがUTF-8の場合はこの方法ではうまくいかず、MultiByteToWideChar()関数で変換する必要があります。

スレッド

_biginthread などの、Windowsのローカルなスレッド関数は引数が多すぎて理解できないので、std::threadを使用したい。
ただ、メインスレッドでUIをコントロールしないといけないので、メインスレッドにメッセージを送る必要があります。
ワーカースレッド側から、postMessage関数にてWindowsのメッセージをポストし、メインスレッドのメッセージキューから独自のメッセージを処理するメソッドを設定してそちらでUIの更新をおこなうことにします。

Windowsメッセージの定義

ユーザー定義のメッセージを準備します。

SampleDialog.cpp
#define WM_SAMPLEMSG (WM_APP + 1)

それを取得するメッセージマップをMFCのマクロに追加します。
OnStart とOnStopでスレッド開始、停止をできるようにします。

SampleDialog.cpp
BEGIN_MESSAGE_MAP(SampleDialog, CDialogEx)
    ON_BN_CLICKED(IDC_BUTTON_START, &SampleDialog::OnBnClickedButtonStart)
    ON_BN_CLICKED(IDC_BUTTON_STOP, &SampleDialog::OnBnClickedButtonStop)
    ON_MESSAGE(WM_SAMPLEMSG, SampleDialog::OnMessage)
END_MESSAGE_MAP()

OnMessageメソッドをヘッダに追加

SampleDialog.h
Class SampleDilaog : public CDialogEx
{
///省略

//追加
public:
    LRESULT OnMessage(WPARAM w_param, LPARAM l_param);
    volatile bool run;
    std::thread th;

};

OnBnClickedButtonStart OnBnClickStop実装

SampleDialog.cpp

void SampleDialog::OnBnClickedButtonStart()
{
   run = true;
   th= std::thread([&]() -> void {
       while(run){
          //ハードウエアから何かデータが来る。
          if(something) {
             //ヒープに割り当てる
             std::string *ptr = new std::string("aaaa");
             PostMessageW(WM_PHOENIXMSG, 0,(LPARAM) ptr);
          }
       }

   });
}

//スレッド停止
void SampleDialog::OnBnClickedButtonStop()
{
   run = false;
}


OnMessageをソースコードに追加
ヒープの文字列データを取得して、リストビューに追加

SampleDialog.cpp
LRESULT SampleDialog::OnMessage(WPARAM w_param, LPARAM l_param)
{
    std::String * data = (Std::String*)l_param;
    CStringA dataA = CStringA(*data.c_str());
    CString dataB = CString(dataA);
    listTag.InsertItem(0,dataB );

    delete data;

    return 0;
}

コードを実行すると、スレッドからUIへデータが受け渡されます。

5
4
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4