VC++6.0 SDK ダイヤログボックスでプログラムを作っています。
質問なのですが、キー入力でイベントを実行するには、どの様にしたら良いのでしょうか。
(例えば '1'を入力すると測定を実行する。)
どなたか教えて下さい。
WM_CHARかWM_KEYDOWNハンドラでキー押下イベントを捕捉し、
そこで目的の処理を果たします。
くたくたさんの方法で実現できるかどうかは別として、
単に1キーを押しただけでイベントが発生するような
Winアプリってどうなんだろうかなぁ?
せめて、Ctrl+1にするとか、Alt+1にするとか・・・。
頑固なエンドユーザーの要求としても拒否するべきと思うが・・・。
とりあえず、どうしてもというのであれば、アクセラレータを登録してみるのが
いちばん簡単かも。
以下の様に(====> の部分)WM_CHAR を追加しましたが
うまく動きません。どうしてでしょうか。
どなたか、よろしくお願いします。
// [メッセージ処理ルーチン]
***********************************************************
BOOL WINAPI GPIB_Sample( HWND hDlg, unsigned Message, WPARAM wParam,
LPARAM lParam)
{
lParam = lParam;
switch (Message)
{
case WM_INITDIALOG:
FORM_LOAD(hDlg);
break;
case WM_COMMAND:
switch (wParam) {
case IDC_CB2: CB2(hDlg);
break; // 終了
case IDC_KAISI: KAISI(hDlg);
break; // 開始
case IDC_SOKUTEI: SOKUTEI(hDlg); break; // 測定
case IDC_BACK: BACK(hDlg);
break; // 一つ前に戻る
case IDC_END: END(hDlg);
break; // 測定終了
case IDC_FDOUT: FDOUT(hDlg);
break; // FD 出力
default:
break;
}
break;
====> case WM_CHAR:
====> switch(wParam){
====> case '1': SOKUTEI(hDlg); break;
====> default: break;
====> }
====> break;
case WM_TIMER:
RECEIVE(hDlg);
for (J=0;J<11;++J) { // BUF=MID(BUFR,6,10)
strcpy(&BUF[J],&BUFR[J+5]);
}
strcpy(&BUF[11],\0);
C1=atof(BUF);// BUF: C 値
C1=C1*1000000000000;
_gcvt(C1,4,BUF);
SetDlgItemText(hDlg, IDC_LC, BUF);
DAT=atof(BUF);
break;
case WM_CLOSE:
KillTimer(hDlg, ID_TIMER1);
EndDialog(hDlg, TRUE);
break;
default:
return FALSE;
}
return FALSE;
}
たぶん、エディットボックスやボタン等があるからだと思います。
何もないダイアログボックスだとイベントが取得できると思います。
コントロール側でキーイベント処理をして、親にイベントが渡らない???等
SDKの場合は、このへんの処理が私にもわかりません。
以前何かで見たような気がするのですが、誰か知ってたら私にも教えてください。
>たぶん、エディットボックスやボタン等があるからだと思います。
>何もないダイアログボックスだとイベントが取得できると思います。
仰る通りですね。ダイアログボックスという事を忘れておりました。失礼しました。
>以下の様に(====> の部分)WM_CHAR を追加しましたがうまく動きません。
ダイアログボックスをDialogBox()で作った場合の対処法は、残念ながら分かりません。
( モーダルループをフック出来ればいいのですが... )
この為、「モードレスダイアログを作り、それをあたかもモーダルのような挙動にする」
といいと思います。この為 メッセージループでそのダイアログへのWM_KEYDOWNを掠め取る
事が出来ます。後はそれをダイアログへ送れば、ダイアログプロシージャで
WM_KEYDOWNを受信できます。
( CDialog::DoModal(),CWnd::PreTranslateMessage()の自前版 )
具体的には
o CreateDialog()でモードレスダイアログ作成
o ダイアログに親ウィンドウがいる時はEnableWindow()で仮想モーダル化
o メッセージループでダイアログに対するWM_KEYDOWNを掠め取り、それへSendMessage()
といった感じです。(動作確認済み)
まだ、解決しません。
zeta さんへ
>アクセラレータを登録してみるのが
>いちばん簡単かも。
初心者なのでよく分からないのですが、これはどの様にすればいいのでしょうか。
くたくたさんへ
>具体的には
>o CreateDialog()でモードレスダイアログ作成
>o ダイアログに親ウィンドウがいる時はEnableWindow()で仮想モーダル化
>o メッセージループでダイアログに対するWM_KEYDOWNを掠め取り、それへSendMessage()
>といった感じです。(動作確認済み)
これも初心者の私にはどの様にすれば良いのか良く分かりません。
サンプルプログラムを送って下さると助かるのですが。
宜しくお願いします。
こんな感じでやればなんとかできましたよ
あとは元プロシージャの呼ぶところとか、どんなキーを判定するのかとか
変更してください
フックプロシージャ
LRESULT CALLBACK KeyDownHook(HWND hCtrl, UINT message, WPARAM wParam, LPARAM
lParam)
{
WNDPROC OldCtrlProc = (WNDPROC)GetWindowLong(hCtrl,GWL_USERDATA);
if (message == WM_KEYDOWN) {
MessageBox(hCtrl, test, aaa, MB_OK);
return TRUE;
}else if (OldCtrlProc) {
return OldCtrlProc(hCtrl, message, wParam, lParam);
} else {
return FALSE;
}
}
ダイアログプロシージャ
LRESULT CALLBACK DlgProct(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
{
int anCtrlID[] = {IDC_EDIT1, IDC_BUTTON1};// 処理するコントロールの全IDを
列挙
int nIDPos;
for (nIDPos = 0; nIDPos < sizeof(anCtrlID) / sizeof(int); nIDPos++) {
HWND hCtrl = GetDlgItem(hDlg, anCtrlID[nIDPos]);
WNDPROC OldCtrlProc = (WNDPROC)SetWindowLong(hCtrl,
GWL_WNDPROC, (DWORD)KeyDownHook);
SetWindowLong(hCtrl, GWL_USERDATA, (DWORD)OldCtrlProc);
}
return TRUE;
}
...
>サンプルプログラムを送って下さると助かるのですが。
>o CreateDialog()でモードレスダイアログ作成
恐らく、DialogBox()を使ってらっしゃる事でしょう。それをCreateDialog()に置換
>o ダイアログに親ウィンドウがいる時はEnableWindow()で仮想モーダル化
今回は、無視して下さい。
>o メッセージループでダイアログに対するWM_KEYDOWNを掠め取り、それへSendMessage()
MSG msg;
while( GetMessage(&msg, NULL, 0, 0) ){
if( msg.message == WM_CHAR ){
SendMessage( msg.hwnd, WM_KEYDOWN, msg.wParam, msg.lParam );
}else if( !IsDialogMessage( msg.hwnd, &msg ) ){
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
以上です。
皆さんへ迷惑かけて済みません。
VC++ は全くの初心者で(今回のプログラムもサンプルプログラムを変更して作成しました。)
RES を頂くのですが、変更方法がよく分かりません。
済みませんが、もう一度わかりやすく教えて下さい。
現在までのプログラムを添付します。
// [WinMainルーチン]
**************************************************************
int PASCAL WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow )
{
int Ret;
hPrevInstance = hPrevInstance;
lpCmdLine = lpCmdLine;
nCmdShow = nCmdShow;
// Create Dialog
Ret = DialogBox( hInstance, MAKEINTRESOURCE(IDD_OSCILLO_DIALOG),
NULL, GPIB_Sample );
return Ret;
}
// [メッセージ処理ルーチン]
********************************************************
BOOL WINAPI GPIB_Sample( HWND hDlg, unsigned Message, WPARAM wParam,
LPARAM lParam)
{
lParam = lParam;
switch (Message)
{
case WM_INITDIALOG:
FORM_LOAD(hDlg);
break;
case WM_COMMAND:
switch (wParam) {
case IDC_CB2: CB2(hDlg);
break; // 終了
case IDC_KAISI: KAISI(hDlg);
break; // 開始
case IDC_SOKUTEI: SOKUTEI(hDlg); break; // 測定
case IDC_BACK: BACK(hDlg);
break; // 一つ前に戻る
case IDC_END: END(hDlg);
break; // 測定終了
case IDC_FDOUT: FDOUT(hDlg);
break; // FD 出力
default:
break;
}
break;
====> case WM_CHAR:
====> switch(wParam){
====> case '1': SOKUTEI(hDlg); break;
====> default: break;
====> }
====> break;
case WM_TIMER:
RECEIVE(hDlg);
for (J=0;J<11;++J) { // BUF=MID(BUFR,6,10)
strcpy(&BUF[J],&BUFR[J+5]);
}
strcpy(&BUF[11],\0);
C1=atof(BUF);// BUF: C 値
C1=C1*1000000000000;
_gcvt(C1,4,BUF);
SetDlgItemText(hDlg, IDC_LC, BUF);
DAT=atof(BUF);
break;
case WM_CLOSE:
KillTimer(hDlg, ID_TIMER1);
EndDialog(hDlg, TRUE);
break;
default:
return FALSE;
}
return FALSE;
}
void FORM_LOAD(HWND hDlg)// [ウィンドウ初期化ルーチン] *****************
{
MODE=0;// '1'-> 通常、'0'-> デバック
MYADR=0;
YRADR=11;
if (MODE==1){
GpibInit(BUF);// 初期化
strcpy(BUFT,A8B4 EN);// C,Q 測定モード
SEND(hDlg);//**
}
strcpy(BUF,ファイル名を入力して下さい。);
SetDlgItemText(hDlg, IDC_LB1, BUF);
strcpy(BUF,ファイル名を入力したら [開始] をクリックして下さい。);
SetDlgItemText(hDlg, IDC_LB2, BUF);
strcpy(BUF,");
SetDlgItemText(hDlg, IDC_LB3, BUF);
strcpy(BUF,0);
SetDlgItemText(hDlg, IDC_LC, BUF);
strcpy(BUF,0);
SetDlgItemText(hDlg, IDC_LB4, BUF);
I=0;// 測定数
J1=0;
}
くたくたさんへ ******************
① CreateDialog に変更すると
<warning C4047: '=' : 間接参照のレベルが 'int ' と
'struct HWND__ *' で異なっています。>
といったワーニングが出ます。
これはどうすれば良いのでしょうか。
② <メッセージループでダイアログに対するWM_KEYDOWNを掠め取り、それへSendMessage() >
の部分のプログラムはどこに追加すれば良いのでしょうか。
③ 具体的にキー入力処理でイベントを実行する部分は、どこにどの様に記述すれば
良いのでしょうか。
ku さんへ ******************
① プログラムを追加したら、他をどの様に変更すれば良いのでしょうか。
② 具体的にキー入力処理でイベントを実行する部分は、どこにどの様に記述すれば
良いのでしょうか。
済みません。宜しくお願いします。
ここが参考になると思いますよ.
http://www.kumei.ne.jp/c_lang/sdk/sdk_36.htm
>CreateDialog に変更すると
><warning C4047: '=' : 間接参照のレベルが 'int ' と
>'struct HWND__ *' で異なっています。>
>といったワーニングが出ます。
>これはどうすれば良いのでしょうか。
DialogBoxとCreateDialogでは戻り値が異なるからです.
もっとMSDNを使いましょう(◎-◎;)