WS_TABSTOPが機能しないコントロールを作っていますが、なぜ素通りされるのか分かりません

このQ&Aのポイント
  • 質問者はダイアログに貼り付けた独自のコントロールが、TABキーでフォーカスが移動されないことに困っています
  • WS_TABSTOPを指定しているが、スタイルの値がWS_MINIMIZEBOXと同じになっていることに気づきました
  • SPY++で調べるとスタイルの値が異なる表示になっており、なぜ区別されているのか疑問に感じています
回答を見る
  • ベストアンサー

WS_TABSTOPが機能するコントロールを作る

Windowsにおいてダイアログに貼り付ける独自のコントロールを作っているのですが、TABキーでコントロールのフォーカスを移動させたとき、自分のコントロールを素通りしてしまいます。 もちろんウィンドウスタイルにWS_TABSTOPを指定して生成しているのですが、今さらながらWS_TABSTOPはWS_MINIMIZEBOXと同じ値であることに気づきました。 もしかすると、WS_TABSTOPではなく、WS_MINIMIZEBOXとして認識されているのではないか?と思いましたが、 その違いがどのように判別されているのかが分かりませんでした。 SPY++で調べてみると、確かに今回問題のコントロールのスタイルは0x50030000となっていますが、SPY++はこれをWS_CHILDWINDOW、WS_VISIBLE、WS_MINIMIZEBOX、WS_MAXIMIZEBOXと表示しています。 一方、普通にダイアログに貼り付けたプッシュボタンでは、スタイルは0x50010000なのにSPY++はWS_CHILDWINDOW、WS_VISIBLE、WS_TABSTOP、BS_PUSHBUTTONとなっていて、同じ値であるのにWS_TABSTOPとWS_MINIMIZEBOXを区別して表示しています。 これは、どういう理屈なのでしょうか? ご存じの方、よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • davidfox
  • ベストアンサー率58% (21/36)
回答No.2

GetNextDlgTabItem によるフォーカス移動は確認済みでしょうか? 私が見ている古い Win32 の説明には 「Windowsは、 GetNextDlgTabItem関数を使って、 表示されていて使用不能ではなく、 WS_TABSTOPスタイルを持つ次のコントロールを探します。」 と有ります。 私は最初の2つのどちらかが条件を満たしていない気がします。

haniriito
質問者

お礼

davidfoxさん、回答ありがとうございます。 GetNextDlgTabItem()で試してみることは気がつきませんでした。 試してみたところ、やはり素通りしました。ダイアログ上のTABキー操作でも結局はGetNextDlgTabItem()相当の処理で次のコントロールを探すのでしょうから、結果は同じになったのでしょう。 で、試行錯誤の末、原因が分かりました。 つまらないミスですが、コントロールそのものにWS_EX_CONTROLPARENT拡張スタイルが設定されていたのがNGでした。これを外すとTABキーで止まるようになりました。

その他の回答 (1)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>今さらながらWS_TABSTOPはWS_MINIMIZEBOXと同じ値であることに WS_MAXIMIZEBOXですよね? >同じ値であるのにWS_TABSTOPとWS_MINIMIZEBOXを区別して表示しています。 >これは、どういう理屈なのでしょうか? Spy++が値をどう表示するか…の問題かと。 WS_SYSMENUがある=>WS_MAXIMIZEBOX WS_CAPTIONがある=>WS_MAXIMIZEBOX ウィンドウクラス名がコントロールとして登録済みのもの=>WS_TABSTOP とか……。 で、TABキーで移動できない。 っていう独自コントロールはどのように作成していますか? あと…そのダイアログはどのように生成していますか? http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+200506/05060084.txt こんな話もあるみたいですが…。

haniriito
質問者

お礼

Wr5さん、早速のコメントありがとうございます。 >>今さらながらWS_TABSTOPはWS_MINIMIZEBOXと同じ値であることに >WS_MAXIMIZEBOXですよね? そうですね。勘違いです。 ご指摘ありがとうございます。 >Spy++が値をどう表示するか…の問題かと。 それはそのとおりだと思います。おそらくSPY++自体はウィンドウクラスあたりから判定しているのだと思います。そうでないと、例えばボタンスタイルなんかは判別できませんから。 でも、Windows自体は何かの条件でスタイル値=0x00010000をWS_TABSTOPかWS_MAXIMIZEBOXのどちらの意味であるかを区別しているはずですよね。その理屈が知りたいのです。 少なくとも、WS_SYSMENUやWS_CAPTIONスタイルで判別しているわけではないようです。SPY++で見る限りでは、普通のボタンでも、私が作ったコントロールでもWS_SYSMENUやWS_CAPTIONスタイルはついていませんが、普通のボタンしかTABキーで止まってくれません。 >っていう独自コントロールはどのように作成していますか? MFCのCWnd派生クラスとしています。 ウィンドウクラスはAfxRegisterWndClass()で独自のクラスを与えています。 コントロールの生成時には、WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_GROUPスタイルを指定しています。 このコントロールはWM_GETDLGCODEを処理して、DLGC_WANTARROWSとDLGC_WANTCHARSを返すようにしています(コントロールはキー操作を受け取る必要があるため)。 >あと…そのダイアログはどのように生成していますか? ダイアログ自体は、普通にリソースエディタで作ったダイアログテンプレートをCDialogクラスに渡してCreate()しているだけです(モードレスダイアログ)。 そして、WM_INITDIALOG中で自前のコントロールを動的に生成して追加しています。 このダイアログ中の他のコントロール(リソースエディタで設定したもの)については正しくTABストップしますので、ダイアログそのものは問題ではないとおもっています。 >http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+200506/05060084.txt ありがとうございます。 ざっくり読んでみましたが、ダイアログ自体をカスタマイズしたいという訳でもないし、基本的にダイアログ自体はTABキーを正しく処理しているようですので関係がないというふうに理解しました。 問題は、ダイアログ上のコントロールである自前のウィンドウ側にあると考えています。 何か、お気づきの点はあればよろしくお願いします。

関連するQ&A

  • ダイアログボックスのボタンコントロールのフォーカスについて

    ダイアログボックスのボタンコントロールのフォーカスについて 教えて下さい。  モーダルダイアログにボタン「OK」を一つ貼り付けて それを「標準のボタン」(BS_DEFPUSHBUTTON)として作成したのですが ダイアログ表示直後は下画像(1)のようになってエンターキーを押しても 反応しません。何度かカーソルキーを押すとようやく(2)のように ボタンに枠線がついてエンターで押せるようになるのですが ダイアログ表示直後に(2)のようにするにはどうするべきでしょうか? ダイアログのコールバック・プロシージャ(WM_INITDIALOG部分でボタン作成) LRESULT CALLBACK SettingWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ switch (msg){ case WM_INITDIALOG: CreateWindowEx(0x00000000,"BUTTON","OK", WS_CHILD |WS_VISIBLE| WS_TABSTOP | BS_DEFPUSHBUTTON, 16,16,80,21,hWnd,(HMENU)IDOK,GetModuleHandle(0),0); return TRUE; } return FALSE; }

  • Tabでのフォーカス(win32)

    edit = CreateWindow( TEXT("EDIT") , NULL , WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER | ES_LEFT , 0 , 0 , 35 , 18 , hWnd , (HMENU)1 , ((LPCREATESTRUCT)(lParam))->hInstance , NULL ); でエディットコントロールを作成しました。 フォーカスがエディットコントロールにある時、TABキーで フォーカスをなくしたいのですが、どうしたらよいでしょうか? デバッガーで追ってみると、WM_KEYDOWNがウィンドウに送られていませんでした。

  • staticコントロール

    CreateWindow( "static", // スタティックコントロールのクラス名 "text is here.", // 表示する文字列 SS_SIMPLE | WS_CHILD | WS_VISIBLE, // 詳細はあとで。 x, y, // 左上の座標 iWidth, iHeight, // 幅と高さ hParent, // 親ウインドウのウインドウハンドル NULL, // メニューハンドル。NULLでよい。 hInstance, // アプリケーションのインスタンスハンドル。 NULL // ウインドウ作成データ。NULLでよい ) ; のメッセージを処理したいのですが既成のwindowなのでどのようにウィンドウ処理関数を指定すればいいのかわかりません。 自分で登録した場合にはウィンドウ処理関数を指定できますが既成の場合どうするのでしょうか。

  • VC++2005でのリソースコンパイルエラーについて

    よろしくお願いします。 猫でもわかる…… を参考にしながら、C言語でスクリーンセイバーを作成しています。 BCCForm and Skelton で作成したリソースをVC++2005で利用してます。 『設定のためのダイアログボックスを表示しないスクリーンセイバー』 はうまく行ったのですが、 『設定用ダイアログボックスを表示させるプログラム』 ではエラーが出てしまいます。 WS_EX_DLGMODALFRAME  この部分が良くないらしいのですが、コメントアウトしてみたり、 削除してみたり、記述を変えたりしたのですが、うまくコンパイルしてくれません。 詳しい方、アドバイスをお願いします。 //----------------------------------------- // BCCForm Ver 2.41 // An Easy Resource Editor for BCC // Copyright (c) February 2002 by ysama //----------------------------------------- #include "Resscreensav.h" //---------------------------------- // ダイアログ (DLG_SCRNSAVECONFIGURE) //---------------------------------- DLG_SCRNSAVECONFIGURE DIALOG DISCARDABLE 0, 0, 270, 180 EXSTYLE WS_EX_DLGMODALFRAME | WS_EX_APPWINDOW STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX CAPTION "設定" FONT 8, "MS 明朝" { CONTROL "表示間隔", IDC_STATIC, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 24, 18, 63, 15 CONTROL "表示文字列", IDC_STATIC, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 24, 54, 63, 15 CONTROL "表示回数", IDC_STATIC, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 27, 93, 63, 15 CONTROL "", IDC_EDIT1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 102, 18, 102, 15 CONTROL "", IDC_EDIT2, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 102, 51, 102, 15 CONTROL "", IDC_EDIT3, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL | ES_LEFT, 105, 90, 102, 15 CONTROL "OK", IDOK, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 18, 144, 69, 15 CONTROL "キャンセル", IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 165, 144, 69, 15 } //-------------------------- // イメージ(MYBMP) //-------------------------- MYBMP BITMAP DISCARDABLE "C:\My Pictures\scan1\scan5.bmp" //-------------------------- // イメージ(ID_APP) //-------------------------- ID_APP DISCARDABLE "icon1.ico" //----------------------------------------- // BCCForm Ver 2.41 // Header File for Resource Script File // Copyright (c) February 2002 by ysama //----------------------------------------- //--------------------- // ダイアログリソース //--------------------- // ダイアログ DLG_SCRNSAVECONFIGURE #define IDC_STATIC 100 #define IDC_EDIT1 103 #define IDC_EDIT2 104 #define IDC_EDIT3 105 #define DLG_SCRNSAVECONFIGURE 2003 //--------------------- // メニューリソース //--------------------- //--------------------- // イメージリソース //--------------------- //#define MYBMP 200 //#define ID_APP 100 //--------------------- // ストリングテーブル //--------------------- //-------------------- // アクセラレーター //-------------------- //------------------ // ヴァージョン情報 //------------------ ------ ビルド開始: プロジェクト: screensav, 構成: Release Win32 ------ リソースをコンパイルしています... ..\..\..\..\Bitmap\screensav\screensav.rc(12) : error RC2104 : undefined keyword or key name: WS_EX_DLGMODALFRAME ビルドログは "file://c:\Visual Studio 2005\Projects\screensav\screensav\Release\BuildLog.htm" に保存されました。 screensav - エラー 1、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========

  • 親ウィンドウの領域外でも表示されるエディットボックスについて

    親ウィンドウの領域外でも表示されるエディットボックスについて VisualStudio2005でMFCアプリを作っています。 親ウィンドウに指定したコントロールの領域外でも 表示されるようなエディットボックスを作りたいのですが、方法はありますか? イメージとしては、ダイアログ上にボタンがあって、 そのボタンを押すとエディットコントロールが表示され、入力待ちとなるようなものです。 このエディットには改行を入力させるのですが、改行してウィンドウサイズを大きくしていくと、 ダイアログの下の端でエディットボックスが途切れてしまいます。 ダイアログの下より大きくなっても全体が表示されるようにしたいんです。 このエディットの生成は次のような感じで行っています。 DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_AUTOHSCROLL | ES_MULTILINE | ES_WANTRETURN; m_edit.Create(dwStyle, rect, this/*ダイアログ*/, -1); よろしくお願いします。

  • ダイアログボックスで指定したサイズどおり表示されない

    ダイアログボックスで指定したサイズがメイン上では約2倍の大きさになって表示されてしまい、困っています。 メニューリソースは以下のとおりです。 MYDLG DIALOG DISCARDABLE 25, 50, 100, 150 STYLE WS_VISIBLE | WS_CHILD | DS_CONTROL CAPTION "Dialog" FONT 9, "MS Pゴシック" BEGIN END WndProc内にダイアログを貼り付けています。 if(hDlgWnd) break; hDlgWnd = CreateDialog((HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE),"MYDLG",hWnd,DialogProc); それが実際にウィンドウを開くとダイアログがだいたいですが(50,115,200,340)のように表示されてしまいます。 VC++ Ver.6.0です。コンパイラ等の問題でしょうか。 ご存知の方、宜しくお願いします。

  • ウインドウの移動禁止

    最大化したウインドウをタイトルバーでドラッグして移動させるのを禁止したいのですが、うまくいきません!どなたかご教授下さい。 現在 1.OnInitDialog()内  ・ウインドウを最大化   this->ShowWindow(SW_SHOWMAXIMIZED);  ・最大化,最小化ボタン消去、サイズ変更禁止   lStyle = GetWindowLong( this->m_hWnd, GWL_STYLE );   lStyle &= ~WS_MINIMIZEBOX;   lStyle &= ~WS_MAXIMIZEBOX;   lStyle &= ~WS_SIZEBOX;   SetWindowLong( this->m_hWnd, GWL_STYLE, lStyle ); 2.WindowProc()内  ・タイトルバーでのダブルクリックを無視   if( message == WM_NCLBUTTONDBLCLK ){     return TRUE;   } しかし、ウインドウをタイトルバーでドラッグして移動を禁止する事が出来ません。 何か方法は無いのでしょうか? 環境 WindowsXP Pro SP3 VC++6.0 SP6 以上、よろしくお願いします。

  • ウインドウスタイルの、WS_EX_TOPMOST

    引き続きVC++2008でWindowsフォームアプリケーションを作っています。 WindowsAPIでのウインドウ製作中です。 今Form1を親とするウインドウで、CreateWindowEx内のウインドウスタイルの個所の引数にWS_EX_TOPMOSTを指定したのですが どうも最前面に表示されてくれないようです。 これは何か他にやらないといけない事があるのでしょうか? なお、CreateWindowEx関数は現在、最初の引数を WS_EX_TOOLWINDOW にして、WS_EX_TOPMOST以外のウインドウスタイルは WS_SYSMENU | WS_VSCROLL | WS_SIZEBOX がある状態です。

  • MFCでのボタン配置

    ダイアログではなく、直接Windowにボタンを貼り付けるために、AppWizaerdを使用して、MyAppというプロジェクトをつくり、MyAppクラスのヘッダに CButton mybutton を定義し、cppファイルのInitInstance関数内の m_pMainWnd->UpdateWindow();の下に、以下のように記述したところ、 mybutton.Create(_T("OK"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(10,10,100,100), m_pMainWnd, 1); ボタンは表示されるのですが、押しても凹んでくれません。どうしてなのでしょうか?? 環境はWinXP VisualStudio.Net2003です。

  • ダイアログリソース内でボタンコントロールの表示を改行させたいんですけど

    VC++2005 win32アプリケーションにて ダイアログリソース内でボタンコントロールの表示を改行させたいんですけど、どうすれば出来ますか? いくらキャプションをイジッても出来ないので***.rcを色々イジってるんですが・・・ ・PUSHBUTTON "文字列1"\r\n"文字列2",IDC_BUTTON3,7,36,74,27 ・PUSHBUTTON "文字列1"+\r\n+"文字列2",IDC_BUTTON3,7,36,74,27 ・PUSHBUTTON "文字列1"&\r\n&"文字列2",IDC_BUTTON3,7,36,74,27 本当に初心者でアホなんで誰か教えてください。m__m

専門家に質問してみよう