OSはXP-SP2、環境はVC++6.0、SDKで行っています。よろしくお願いします。
ダイアログボックス内のエディットボックスで取得した複数の値をメインウィンドウをプ
ロシージャに送りたいのですが、グローバルで宣言した変数を使わずに送る方法はないで
しょうか?
SendMessageでメインウィンドウハンドルを指定して、ユーザ定義のメッセージを送ります。
そのときに、LPARAMやWPARAMに適当な値を設定します。
適当な値とは、渡したい値そのものであったり構造体へのポインタであったり、適当に決
めます。
メインウィンドウのコールバック関数では、第二引数のUINTにあらかじめ決めたユーザ定
義メッセージが来たら、LPARAMやWPARAMを見れば、送ったデータがそのまま届きますの
で、後はご自由に。
これで、同じプロセス内であれば、自由に渡せると思います。
ただし、スタックに存在するような変数のポインタを渡し、コールバック関数内部でその
ポインタの指すメモリーを参照すると、問題が発生することもあります。
DialogBoxParam()でポインタをダイアログ側に渡しておくという手もあるかもしれませ
ん
あとはダイアログプロシージャの中のWM_COMMANDのIDOKなどで
そのポインタを使ってデータを格納すればいいと思います
NowNowさん、憂さんありがとうございます。
DialogBoxParam();の第5引数にポインタを用いてダイアログ側に渡しておくということ
でしょうか?
例えば
struct DATA
{
受け取りたいデータ群
};
DATA data;
DialogBoxParam(略, (LPARAM)&data);
とすればダイアログのWM_INITDIALOGでその数値を受け取ることができます
それをダイアログプロシージャ内のstaticな変数に保存しておくなどすれば、
ダイアログプロシージャ内の好きな場所でポインタを使ってデータをいじれます
ただ、この場合は引き渡す変数がオート変数では駄目なのではないかと思います。
この方法を使う場合、引き渡す変数は少なくとも引き渡されたダイアログと同じだけの
寿命が必要だと思います。
グローバルや静的変数が嫌なのであれば、malloc等でメモリを確保して
不要になったタイミングでfreeしないといけないと思います。
ご返答ありがとうございます。データを構造体ではなく配列として送るにはどうしたら
よいでしょうか?
初歩的な質問ですみません、、
> ご返答ありがとうございます。データを構造体ではなく配列として送るにはどうしたら
> よいでしょうか?
> DialogBoxParam(略, (LPARAM)&data);
これは、別に構造体そのものを引数で渡しているのではなく、
構造体のポインタを渡しているだけなので、
配列の場合も同じように配列の(先頭の)ポインタを渡せばOKです。
たとえばこんな感じ。
int Data[10];
DialogBoxParam(略, (LPARAM)Data);
ただし、PATIOさんも注意されていますが、変数の寿命に注意が必要です。
KING・王さん 初歩的な質問に返答していただきありがとうございます。
教えていただいたとおり配列でやってみたいと思います。
教えていただいたとおり配列でやってみたんですが、WM_INITDIALOGで受け取る時に配列
での受け取り方がうまくいかないみたいで値が入りません。
度々初歩的な質問なんですがよろしくお願いします。
ちょっとさすがにそれだけの情報ではどこがどううまくいってないのか判断できないの
で、いくつかソースを提示したほうがいいと思います
例えば
・メインウインドウ側で宣言したデータを受け取る配列の宣言部分
・DialogBoxParamの呼び出し部分
・WM_INITDIALOGで送られてきたポインタに対して処理をしている部分
・その他ダイアログプロシージャ内でそのポインタを使用している部分
など
ポインタをどのように使用してどのように値を入れようとしたのか、
その辺をもうちょっと具体的にしましょう
失礼しました。
WindowProcedure内はこうなっています。
WindowProcedure()
{
switch () {
case WM_COMMAND:
switch () {
case ID:
{
int Data[4];
DialogBoxParam(略, (LPARAM)Data);
DrawLine(Data[0],Data[1],Data[2],Data[3]); <-自作の関数です
}
break;
}
break;
}
}
DialogProcedure内では、
DialogProcedure()
{
static int Data[4];
switch () {
case WM_INITDIALOG:
: <-ここの処理が分かりません、、
:
break;
case WM_COMMAND:
switch () {
case IDOK:
{
char szString[256];
GetDlgItemText(略,szString,255);
Data[0]=atoi(szString);
同様に Data[1]=atoi(szString);
Data[2]=atoi(szString);
Data[3]=atoi(szString); // それぞれのエディットボックスから値を
取得し各配列に代入する。
EndDialog();
}
break;
}
break;
}
}
と、なっています。値1つなら受け取ることができますが配列になるとうまくいきません。
よろしくお願いします。
> static int Data[4];
ここがいけません
WM_INITDIALOGで送られてくるのは「配列の先頭ポインタ」なので、
それを受け取るためにはint*型の変数でなくてはなりません
DialogProcedure内でこのように宣言しても、単に同じ名前というだけでまったく別物の
配列が作られるだけです
そのためそこに値を代入してもDialogProcedure内のData[]に数値が入るだけで、
WindowProcedure内のData[]にはなんの影響も及ぼしません
この場合は
static int* lpData;
というようにDialogProcedure内で宣言します
で、WM_INITDIALOGの中で
lpData = (int*)送られてきた数値;
とします
あとはそのポインタを使って数値を格納します
WM_INITDIALOGの中でどのように数値を取得するかはヘルプで調べてみてください
それとポインタの扱いに関しては非常に重要な部分なのでしっかりと扱いを覚えましょ
う
本が手元になければ、解説しているサイトを探しましょう
検索すればいくつかはすぐに見つかると思います
ついでにコントロールから直接数値として取得するGetDlgItemInt()という関数もあるの
で調べてみるといいかもしれません
憂さん、ご親切にありがとうございます。
プログラミングの勉強を始めたばかりで、まだ確実にポインタの扱いを理解できていませ
ん。なのでこれからしっかり勉強していこうと思います。ありがとうございました。