アクセラレータキーがうまくいかないのは?

解決


みけにゃん  URL  2002-12-02 14:36:21  No: 50752  IP: [192.*.*.*]

続けざまの質問で申し訳ないのですがアクセラレータキーに関する質問です。
いつもは猫でも分かる〜のアクセラレータキーの書き方でやっていたので
特に問題はなかったのですが、今やっているプログラムの場合猫でもの
書き方と違いWinMain関数に直にCreateWindowなどを書いています。

その状態でアクセラレータキーをロードしてメッセージループに
猫でもと同じようにアクセラレータキーのメッセージも動くように
コードを記述したのにもかかわらず、アクセラレータキーが動きません。

これはどうしてでしょうか?
以下に書いたコードを書いておきます。

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lParamszCmd, int nCmdShow){

          HWND hWnd;
          MSG msg;
          HACCEL hAccel;
          HWND hMWnd;
          WNDCLASSEX wcex;

          wcex.hInstance = hInstance;
          wcex.lpszClassName = szWinName;
          wcex.lpfnWndProc = WndProc;
          wcex.style = CS_HREDRAW | CS_VREDRAW;
          wcex.cbSize = sizeof(WNDCLASSEX);
          wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
          wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
          wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
          wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
          wcex.cbClsExtra = 0;
          wcex.cbWndExtra = 0;
          wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

          if(!RegisterClassEx(&wcex)){
              return(0);
  }

          hWnd = CreateWindow(szWinName, "Mail Viewer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);

          hMWnd = hWnd;
          hParent = hWnd;
          hInst = hInstance;

          ShowWindow(hWnd, nCmdShow);
          UpdateWindow(hWnd);

          hAccel = LoadAccelerators(hCurInst, MAKEINTRESOURCE(IDR_ACCELERATOR1));

          if(hParent == NULL){
              return(0);
          }

          while(GetMessage(&msg, NULL, 0, 0)){
                if(!TranslateAccelerator(hParent, hAccel, &msg)){
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
          }

          return(msg.wParam);
}

編集 削除
YuO  2002-12-02 17:07:18  No: 50753  IP: [192.*.*.*]

hCurInstって何ですか?
LoadAcceleratorsは正しいハンドルを返していますか?


でもって……。
>      wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
はやめましょうよ。ゲームとかならともかく……。
画面のプロパティでウィンドウの色をいじってみるとよくわかると思います。
#wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);を利用。
#場合によってはCOLOR_APPWORKSPACE + 1を使う場合も。

編集 削除
みけにゃん  URL  2002-12-02 17:28:54  No: 50754  IP: [192.*.*.*]

あっ書き間違いです。>hCurInst
これはhInstanceが入ります。

wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);に直したのを載せます。

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lParamszCmd, int nCmdShow){

          HWND hWnd;
          MSG msg;
          HACCEL hAccel;
          HWND hMWnd;
          WNDCLASSEX wcex;

          wcex.hInstance = hInstance;
          wcex.lpszClassName = szWinName;
          wcex.lpfnWndProc = WndProc;
          wcex.style = CS_HREDRAW | CS_VREDRAW;
          wcex.cbSize = sizeof(WNDCLASSEX);
          wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
          wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
          wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
          wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
          wcex.cbClsExtra = 0;
          wcex.cbWndExtra = 0;
          wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

          if(!RegisterClassEx(&wcex)){
              return(0);
          }

          hWnd = CreateWindow(szWinName, "Mail Viewer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);

          hMWnd = hWnd;
          hParent = hWnd;
          hInst = hInstance;

          ShowWindow(hWnd, nCmdShow);
          UpdateWindow(hWnd);

          hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));

          if(hParent == NULL){
              return(0);
          }

          while(GetMessage(&msg, NULL, 0, 0)){
                if(!TranslateAccelerator(hParent, hAccel, &msg)){
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
          }

          return(msg.wParam);
}

編集 削除
みけにゃん  URL  2002-12-02 17:49:04  No: 50755  IP: [192.*.*.*]

http://knekodo.hp.infoseek.co.jp/new.htmlのMailViewerのリンクから
この状態のファイルをダウンロードできるようにしたのでこれで確認を
お願いできないでしょうか?

編集 削除
YuO  2002-12-02 18:51:58  No: 50756  IP: [192.*.*.*]

アクセラレータは正しくロードできているのですか?
記述されたソースでは一切チェックされていないのですが。
#ウィンドウの作成のチェックもタイミングが間違っているし……。

また,アクセラレータが動かないと言うのは,
・TranslateAcceleratorが失敗する
・TranslateAcceleratorは成功しているがWM_COMMAND(or WM_SYSCOMMAND)が来ない
のどちらですか。また,前者であればGetLastErrorで得られるエラーは何ですか?


掲示板で質問する前に,このような基本的な事項は調べて置いてください。

編集 削除
みけにゃん  URL  2002-12-03 09:52:18  No: 50757  IP: [192.*.*.*]

ウィンドウ作成のタイミングを猫でも〜のものと同じように修正して
もう一度試してみたのですがやっぱりアクセラレータキーが動作しないようです。

ちなみにGetLastErrorを表示できる関数を別のページから探して
実装してみたのですが、そうすると最初に「アクセスが拒否されました」と出て
それ以降は「インデックスの値が無効です」というものがずっと出ていました。

基本的事項がうまく調べられなくて本当にごめんなさいです。(>_<)

編集 削除
みけにゃん  URL  2002-12-03 09:57:55  No: 50758  IP: [192.*.*.*]

あと追加で「システムコールに渡されるデータ領域が小さすぎます」と
表示されました。

編集 削除
みけにゃん  URL  2002-12-03 10:05:19  No: 50759  IP: [192.*.*.*]

http://knekodo.hp.infoseek.co.jp/mview_src.lzhにエラーコードを
ステータスバーに出すものを載せたので見ていただけないでしょうか?

今までは出来ていたのにいきなり出来なくなったのでどうしてかなぁって
なってしまったので本当に困っています。

編集 削除
YuO  2002-12-03 14:12:18  No: 50760  IP: [192.*.*.*]

だからぁ……。
どのタイミングで失敗しているのかが分からないと答えようがないです。

前から書いているように,失敗する可能性があるのは二ヶ所。
・LoadAccelerators
・TranslateAccelerator
です。どちらが原因で失敗しているのかをまず突き止めてください。
その上で,GetLastError(とFormatMessage APIやErrlook.exe)を使って,失敗の原因を突き止めるのです。
もちろん,MSDNを参照するのは必須事項です。

質問をするならそのあとです。
デバッグもしていないようなソースを見る気にはなりません。

編集 削除
みけにゃん  URL  2002-12-03 18:02:55  No: 50761  IP: [192.*.*.*]

>どちらが原因で失敗しているのかをまず突き止めてください。
>もちろん,MSDNを参照するのは必須事項です。

やっと失敗する原因がわかりました。
後者のTranslateAcceleratorが失敗しているようです。

LoadAcceleratorsで失敗したのであればhAccelがNULLで
読み込み失敗のメッセージボックスが表示されるのに表示されずに
通り抜けていったのと、設定したアクセラレータキーを押すと
TranslateAcceleratorの戻り値(失敗)を返すのでおかしいと
思われるのはTranslateAcceleratorです。

過去に作ったNMail(NyantaMail)などのソースではこのような
LoadAcceleratorsで失敗する事がなかったのでどうしてこんな事に
なったのかがいまいち理解できていないです。

問題があると思われる部分のコードを載せます。

HINSTANCE hInst;
HWND hParent;
HACCEL hAccel;
static HWND hStatus;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lParamszCmd, int nCmdShow){

          MSG msg;

          hInst = hInstance;

          if(!hPrevInst){
                    if(!InitApp(hInstance)){
                              return FALSE;
                    }
          }

          if(!InitInstance(hInstance, nCmdShow)){
                    return FALSE;
          }

          hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));

          if(hAccel == NULL){
                    MessageBox(NULL, "アクセラレータの組込みに失敗しました", "Mail Viewer", MB_OK);
          }

          if(hParent == NULL){
                    return(0);
          }

          while(GetMessage(&msg, NULL, 0, 0)){
                    if(!TranslateAccelerator(hParent, hAccel, &msg)){
                              TranslateMessage(&msg);
                              DispatchMessage(&msg);
                    }
          }
          return msg.wParam;
}

//ウィンドウ・クラスの登録
ATOM InitApp(HINSTANCE hInst)
{
          WNDCLASSEX wcex;

          wcex.hInstance = hInst;
          wcex.lpszClassName = szWinName;
          wcex.lpfnWndProc = WndProc;
          wcex.style = CS_HREDRAW | CS_VREDRAW;
          wcex.cbSize = sizeof(WNDCLASSEX);
          wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
          wcex.hIconSm = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
          wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
          wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
          wcex.cbClsExtra = 0;
          wcex.cbWndExtra = 0;
          wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

          return(RegisterClassEx(&wcex));
}

//ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nCmdShow)
{
          HWND hWnd;

          hWnd = CreateWindow(szWinName, "Mail Viewer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);

          if(!hWnd){
                    return FALSE;
          }

          ShowWindow(hWnd, nCmdShow);
          UpdateWindow(hWnd);
          hParent = hWnd;

          return TRUE;
}

編集 削除
YuO  2002-12-03 19:19:15  No: 50762  IP: [192.*.*.*]

で,その時のGetLastErrorの戻り値は?
もちろん,本来WM_COMMANDを生成するはずのメッセージに対するときの戻り値をチェックする必要があります。

編集 削除
YuO  2002-12-03 19:32:32  No: 50763  IP: [192.*.*.*]

で,GetLastErrorの戻り値は?
もちろん,本来WM_COMMANDを生成するはずのメッセージに対するときの戻り値をチェックする必要があります。

編集 削除
みけにゃん  URL  2002-12-04 08:48:27  No: 50764  IP: [192.*.*.*]

>で,その時のGetLastErrorの戻り値は?

エラーの番号で言うと122の「システムコールに渡されるデータ領域が小さすぎます」です。

編集 削除
みけにゃん  URL  2002-12-04 09:12:24  No: 50765  IP: [192.*.*.*]

>もちろん,本来WM_COMMANDを生成するはずのメッセージに対するときの戻り値をチェックする必要があります。

WM_COMMANDまでメッセージは渡っているのですが、それ以降の
動作(メール受信やメールの削除、アプリケーションの終了等)が
動作しないという状況です。

他のプログラムではそのような変な動作はしませんでした。
→試しに猫でも〜のアクセラレータキーつきのメニューのプログラムを
別に打ってみて実行しましたが問題なくアクセラレータキーが動作しました。

編集 削除
みけにゃん  URL  2002-12-04 10:32:33  No: 50766  IP: [192.*.*.*]

上の追加なのですがWM_COMMANDが発生する時のwParamの部分に
ブレークポイントを置いてアクセラレータキーを押したあとに
ステップイン実行を行ったのです。

正常なプログラムだと指定されたメニューのコマンドに飛ぶのですが、
問題のこのプログラムの場合はWM_COMMANDのbreakまで飛んでしまいました。
もちろんアクセラレータキーは正しく読み込まれていています。

編集 削除
みけにゃん  URL  2002-12-04 12:16:58  No: 50767  IP: [192.*.*.*]

埒があかないのでアクセラレータキーがちゃんと動く雛形プログラムを
作ってその中に今まで作った関数を組み込んでみて正常にアクセラレータキーが
動くか試してみようと思います。

もしだめだった場合は報告を、成功した場合は次のメッセージで
この問題は終了(解決)したいと思います。

編集 削除
みけにゃん  URL  2002-12-04 15:05:11  No: 50768  IP: [192.*.*.*]

アクセラレータキーの正常に動作する雛形プログラムに組み込んだところ
正常にアクセラレータキーが動くようになりました。

プロジェクト自体の名前やDSWやDSPファイルの中の名前を修正したりしたのが
原因なのかもしれません。

今回はこういう形での解決となってしまい本当にごめんなさいです。>YuOさん

編集 削除
YuO  2002-12-04 15:11:24  No: 50769  IP: [192.*.*.*]

> 問題のこのプログラムの場合はWM_COMMANDのbreakまで飛んでしまいました。

それは,単にIDを間違えただけでは?

編集 削除
みけにゃん  URL  2002-12-05 10:43:23  No: 50770  IP: [192.*.*.*]

>それは,単にIDを間違えただけでは?

いえ、そんな事はなかったですよ。
ちゃんとリソースエディタのアクセラレータキーの所で
メニューのIDを指定して割り当てるキーも設定しました。

編集 削除