|ハイブリッドOS|File System|ARM|Android|Java|制御システム|オープンシステム

 

VC

 
フォーム
 
Messageの構造体送信
2013-12-02
前回は、SendMessageで Formに Msg、wpram,lparamの3つの値を送信しました。
今回は、構造体を送信する方法です。
今回も、win32の資産を使います。
コンパイルには、usr32.lib のリンカ設定が必要です。
構造体を送信するには、Messageに
WM_COPYDATA
を使用し
lparamに、COPYDATASTRUCT型の構造体アドレスで送信するデータを設定する必要があります。
また、構造体を送信するMessageに非同期のMessage(PostMessageなど)は使用できません。
(いつメモリを解放して良いかわからないため。だそうです。)

例は、以下の構造体を button1 が押されたら param1=123、param="456"を設定し、自分のFormにMessageを送信して、受信したら
param1とparam2をそれぞれ、TextBox1、TextBox2に反映する例です。
typedef struct _msg_data {
    int   param1;
    TCHAR param2[10];
}MSG_DATA;
#include <windows.h>
// sendする構造体
typedef struct _msg_data {
    int   param1;
    TCHAR param2[10];
}MSG_DATA;
namespace SendMsgStruct {
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
        }
        :<略>
        protected:
            virtual void WndProc( Message% m ) override
            {
                MSG_DATA *msg_data;
                switch(m.Msg) {
                    // 受信した構造体データをTextBoxに反映
                    case WM_COPYDATA:
                        msg_data = (MSG_DATA *)m.LParam.ToPointer();
                        textBox1->Text = msg_data->param1.ToString();
                        textBox2->Text = gcnew String(msg_data->param2);
                        break;
                    default:
                        break;
                }
                Form::WndProc(m); //ここで見ているcase以外の標準処理をここでさせる。
            }

    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
        {
            HWND myh;
            MSG_DATA msg_data;
            COPYDATASTRUCT data;
            TCHAR    tc_buf[64];
            data.lpData = &msg_data;        // 送信する構造体アドレス設定
            data.cbData = sizeof(msg_data);    // サイズ指定
            msg_data.param1 = 123;
            wcscpy_s(msg_data.param2, L"456");

            // 自Formへ送信
            wcscpy_s(tc_buf, L"Form1");
            myh = FindWindow(NULL, tc_buf);
            ::SendMessage(myh, WM_COPYDATA, (WPARAM)0x0000, (LPARAM)&msg_data);
        }
    };
}
(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
 
FormへMessage送信する。
2013-11-26
今回は、win32の資産を使います。
コンパイルには、usr32.lib のリンカ設定が必要です。
[プロジェクト] -> ["プロジェクト名" プロパティページ ] -> [ 構成プロパティ ] -> [ リンカ ] → [ 入力 ] → "追加依存ファイル"に "usr32.lib"を記述。
例の内容
    "Form1"という名前の Form に button1 がついていて、それを押すと、自Form に Messageを送信します。
    この手段を使えば、別のForm に Message を送信することができます。
    基本的には、Msg、wpram,lparamの3つの値で、Messageの種類を区別することができます。
    整数以外を送りたい場合は Msg を別途指定しますが、いろいろ制約があります。
    それは、またの機会に。
#include <windows.h>
#define WM_MSG_FORM1    WM_APP+1
public ref class Form1 : public System::Windows::Forms::Form
{
public:
    Form1(void)
    {
        InitializeComponent();
    }
    :<略>
    protected:
        // Mesage受信処理
        virtual void WndProc( Message% m ) override
        {
            int lparam;
            int wparam;
            String ^msg_str = gcnew String("RecvMsg W=");
            switch(m.Msg) {
                case WM_MSG_FORM1:
                    lparam = (int)m.LParam;
                    wparam = (int)m.WParam;
                    msg_str = String::Concat(msg_str, wparam.ToString(), " L=");
                    msg_str = String::Concat(msg_str, lparam.ToString());
                    MessageBox::Show(msg_str);
                    break;
                default:
                    break;
            }
            Form::WndProc(m);    //ここで見ているcase以外の標準処理をここでさせる。
        }
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
        {
            HWND    myh;
            TCHAR    buf[1024];
            // Message送信
            wcscpy_s(buf, L"Form1");
            myh = FindWindow(NULL, buf);
            ::SendMessage(myh, WM_MSG_FORM1, 0x0001, 0x0002);
        }
};
(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
 
FileWrite( StreamWriter )
2013-11-19
Textファイルを作成する方法を以下にまとめます。
using namespace System::IO;                // StreamReader
using namespace System::Text;            // Encoding::ASCII
サンプルでは、上記の namespace を使用します。
StreamWriter ^sw;
String ^filename = gcnew String("C:\\TEMP\\TestW.txt");
String ^wt_data_str = gcnew String("data");
try {
    // FileOpen
    //    第2引数について
    //        データを既存のファイルに追加する場合は true。
    //        既存のファイルを上書きする場合は false。
    //        指定したファイルが存在しない場合は、
    //        このパラメーターの値に関係なく、新しいファイルが作成されます。
    sw = gcnew StreamWriter(filename, false, Encoding::GetEncoding("shift_jis"));
    sw->Write("write data =");    // 改行付かない
    sw->WriteLine(wt_data_str);    // 改行つく
    sw->Flush();                // bufferのをFileに出力
    sw->Close();
}
catch(Exception ^e) {
    e;
    // Err処理
}
(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
 
FileRead( StreamReader )
2013-11-12
Textファイルの内容を読みだし、1行づつ処理する方法を以下にまとめます。
 
    using namespace System::IO;                // StreamReader
    using namespace System::Text;            // Encoding::ASCII
    using namespace System::Diagnostics;    // Debug::Write()

    以下のサンプルでは、上記の namespace を使用します。

    int i;                // Fileの行カウント
    int leng;            // Fileの総行数
    StreamReader ^sr;
    String ^filename = gcnew String("C:\\TEMP\\Test.txt");
    try {
        leng = 0;
        // FileOpen
        sr = gcnew StreamReader(filename, Encoding::ASCII);
        // Read and Close
        String^ list;
        list = sr->ReadToEnd();            // 終わりまで Read
        sr->Close();
        // 1行ごとに分解
        array<String^>^ textLine = list->Split('\n');
        leng = textLine->Length;
        // 1行ごとに処理
        for(i=0; i<leng; i++) {
            // ここでは、サンプルのため、デバッグの出力に1行づつ表示。
            Debug::Write(textLine[i]);
        }
    }
    catch(Exception ^e) {
        e;
        // Err処理
    }

(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
 
別FormのCloseを知る方法
2013-10-07
Window Form1 から Window Form2 を起動しForm2 が閉じたときに、その Evetn をForm1で知る方法を以下にまとめます。

例は、Form1起動時に Form2も起動し、Form2を閉じると、Form2_End()メソッドがcall されます。

public ref class Form1 : public System::Windows::Forms::Form
{
    public:
        Form1(void)
        {
            InitializeComponent();
        }

        :<略>

    private:
        Form2 ^fm2;

        // Form2が閉じたときに Callされるメソッド
        void Form2_End(System::Object^  sender, System::EventArgs^  e)
        {
            // Form2が閉じたときに 処理したい内容を記述
        }

    private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
        {
            // Form2 生成
            fm2 = gcnew Form2();

            // Form2閉じたときに、callする メソッド登録
            fm2->Closed += gcnew EventHandler(this, &TestForm2close::Form1::Form2_End);
            
            // Form2 表示
            fm2->Show();
        }
    };
}

(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
3