コールバック関数内で親ウィンドウのハンドルを取得するには?

解決


トッシ  2006-12-29 04:30:20  No: 64128

実験のためのプログラムを作成しております。

概要は以下のとおりです
ADボードとタイマーボードを使用しております。
それを用いて、例えばタイマを0.1秒おきに更新し、そのたびにADボードを用いて外部からデータを取り込みます。
その際に、タイマボードによるコールバック関数内でダイアログボックス上にリアルタイムで取得したデータを表示させたいと考えております。
つまり、ダイアログボックス上では、0.1秒ごと(ほぼリアルタイム)でADでとってきたデータが表示されるようにしたいと考えています。

プログラムとしては以下の感じになります。
ただし、あくまで概要を伝えるためAD変換等の関数は実際用いているのとは異なっております。

---------------------------------------------------------------------
void CALLBACK lpEventProc_calb(INT nChannel, DWORD dwEvent, DWORD dwUser){
    data = getAD;   (ADボードでデータを取得)

    _snprintf(txt_rh, 10000, "%.4f", data);
    SetDlgItemText(hWnd, IDC_DATA, txt);
}

BOOL CALLBACK DlgWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    CountStart;   (タイマをスタートします)
}

---------------------------------------------------------------------

しかし、これをこのまま実行すると
        error C2065: 'hWnd' : 定義されていない識別子です
と出てしまいます。
そこで、関数を調べてGetParent(hWnd)でコールバック関数内で親ダイアログボックスのハンドルを取得できると書いてあったので、
    snprintf(txt_rh, 10000, "%.4f", data);
    SetDlgItemText(GetParent(hWnd), IDC_DATA, txt);
としてみたのですが、
    error C2065: 'hWnd' : 定義されていない識別子です
と出てしまいます。

自分なりに原因を考えてみたのですが、
void CALLBACK lpEventProc_calb(INT nChannel, DWORD dwEvent, DWORD dwUser)
というWindowsのコールバック関数ではなく、タイマボード固有のコールバック関数を用いていることに原因があるのではないかと考えています。

というのも、Windowsのコールバック関数であれば
BOOL CALLBACK PageProc1(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp)
となっており、親ウィンドウのハンドルを引数の中にしているからです。

ここまではなんとか自分で考えたのですが、じゃあボード固有のコールバック関数を用いているときに、どのようにして親ウィンドウのハンドルを指定すればいいか?というところは解決できませんでした。
どなたかよい方法をご存知の方がいらっしゃったら、ご教授いただけると幸いです。

よろしくお願いします。


トッシ  2006-12-29 04:31:53  No: 64129

すいません、二重投稿してしまいました。
よろしくお願いします


超初心者  2006-12-29 06:16:43  No: 64130

lpEventProc_calb が呼ばれるから、
ここからSetDlgItemTextってことですね。

以下推測です。

タイマボードによるコールバック関数としてlpEventProc_calbを
登録するときにdwUserにIDC_DATAのウィンドウハンドルを指定できませんか?

指定できない場合はこの方法では不可能ということになります。
指定できるなら、pEventProc_calbが呼ばれたときの引数dwUserも
IDC_DATAのウィンドウハンドルになってくれるようになっていませんか?

void CALLBACK lpEventProc_calb(INT nChannel, DWORD dwEvent, DWORD dwUser)
{
    HWND hWnd = (HWND)dwUser;
    data = getAD; //  (ADボードでデータを取得)
    char txt_rh[1000];

    _snprintf(txt_rh, sizeof txt_rh, "%.4f", data);
    SetWindowText(hWnd, IDC_DATA, txt_rh);
}

指定できない場合はグローバル変数を使うことになるな。
でもそれはないと思う。
いかにも出来そうなdwUserがあるから。

(sizeof hWnd) == (sizeof dwUser)という前提で
キャストでコンパイルエラーを出させないようにして
渡してしまうってこと。


超初心者  2006-12-29 06:17:43  No: 64131

SetWindowText(hWnd, txt_rh);
だ!


オショウ  2006-12-31 17:37:00  No: 64132

簡単な例として・・・

#pragma data_seg(".hogehoge")
  HWND hWnd;
#pragma data_seg()
#pragma comment(linker,"/SECTION:.hogehoge,RWS")

と、宣言して使う方法もあります。
詳細は、ご自身で調べてみて下さい。

因みに、VC6で動作していたコードの抜粋です。

以上。


オショウ  2006-12-31 17:40:20  No: 64133

補足

hogehogeの部分ですが、名前はピリオド入れて8文字までで
宣言して下さい。マイクロソフトの仕様ですので。

以上。


トッシ  2006-12-31 18:29:43  No: 64134

超初心者様、オショウ様コメントありがとうございました

超初心者様の方法でやってみたところ、うまくいきました。
ありがとうございました。

また、オショウ様のコメントも今後の勉強のためになるので、参考にさせていただきます。

皆様、ありがとうございました


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加