タブコントロールについて

[戻る]
きみまろ 2004/10/27(水) 14:56:19
こんにちは。

タブコントロールについてお聞きしたい事があります。

タブコントロールに、タブコントロールのページとして作成した
ダイアログ(ダイアログ内にエディットボックスを1つ設定)を
貼り付けて(とりあえず2ページ)表示しました。
ダイアログの表示、タブの切替、エディットボックスへの入力は、
なんなく動作したのですが、タブ内のエディットボックスにフォ
ーカスがある状態で、[ESC]キーを押下するとタブ内のエディット
ボックス(多分、ページとして設定したダイアログ自体が)が消
えてしまいます。
タブコントロールのページとして設定したダイアログの[ESC]キー
押下時の処理を行わないようにする方法はあるのでしょうか?

宜しくお願い致します。

RsrS 2004/10/27(水) 15:16:29
タブページのダイアログ、および親ウィンドウの両方に
  WS_EX_CONTROLPARENT
スタイルを設定してみて。

きみまろ 2004/10/27(水) 16:37:29
RsrS様、ご回答ありがとうございます。

教えていただいた通り、各ダイアログに「WS_EX_CONTROLPARENT」を
設定しましたが、現象は変わりませんでした。

いろいろ調べてみたのですが、どこかのHPでページ用のダイアロ
グのプロパティで「[コントロール]をチェックする」というのが
ありましたので、早速設定してみましたが、ページ用ダイアログの
エディトボックスにフォーカスが移動したと同時に固まってしまい
ました。
他にもいろいろ探しているのですが、良い解決策は見つかりません。
引き続き、ネットで調べてみます。

RsrS様も、何かお気付きの事がありましたら、また宜しくお願い致
します。

2004/10/27(水) 16:53:29
[Esc]キー押下をダイアログが処理していることによる終了ではないでしょうか。
VCのダイアログは[Enter]キー、[Esc]キー押下で閉じてしまうのが
デフォルト動作のようですので。

OnCancel() の処理でダイアログが終了しないようにすればよい気はします。

RsrS 2004/10/27(水) 16:56:52
>いろいろ調べてみたのですが、どこかのHPでページ用のダイアロ
>グのプロパティで「[コントロール]をチェックする」というのが
>ありましたので、早速設定してみましたが、ページ用ダイアログの
>エディトボックスにフォーカスが移動したと同時に固まってしまい
>ました。

これ自体がおかしな現象です。
それが不正な動作になるということであれば、
プロパティページの Create 自体にどこか誤りがあるのではないでしょうか。
となると、おそらく現在の情報だけでは不足です。

MFC か SDKか、VC のバージョンは何か、といった基礎的な情報と、
子ダイアログをどのように Create しているか等の詳細が必要と思います。

あと、タブのページを作る場合、ページをタブの子ウィンドウとする場合もあれば、
兄弟ウィンドウとする場合もありますね。どちらでしょう?
#自分は通常、プロパティページの真似をして兄弟にしますが...

きみまろ 2004/10/27(水) 17:50:53
RsrS様、ん様、ご回答ありがとうございます。

VCのバージョンですが、「Microsoft Visual C++ 6.0」です。

下記がタブコントロールを生成している箇所です。
-------------------------------------------------------------------------------
[SampleDlg.h]
class CSampleDlg : public CDialog
{
// 構築
public:
    CTabPage01Dlg    m_cTabPage01;    <--- タブページ用ダイアログその1
    CTabPage02Dlg    m_cTabPage02;    <--- タブページ用ダイアログその2

// ダイアログ データ
    //{{AFX_DATA(CPetitMailCheckerDlg)
    enum { IDD = IDD_PETITMAILCHECKER_DIALOG };
    CTabCtrl    m_cMainTab;               <--- タブコントロール
    //}}AFX_DATA
                ・
                ・
                ・
                ・
}

[SampleDlg.cpp]
BOOL CSampleDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // "バージョン情報..." メニュー項目をシステム メニューへ追加します。
                                        ・
                                        ・
                                        ・
    // TODO: 特別な初期化を行う時はこの場所に追加してください。
    
    TC_ITEM    TabCtrlItem;
    
    TabCtrlItem.mask = TCIF_TEXT;
    TabCtrlItem.pszText = "ページ1";
    m_cMainTab;.InsertItem( 0, &TabCtrlItem );
    TabCtrlItem.pszText = "ページ2";
    m_cMainTab;.InsertItem( 1, &TabCtrlItem );
    
    m_cTabPage01.Create(IDD_TAB01_DIALOG, &m_cMainTab;);
    m_cTabPage01.SetWindowPos(&wndTop,10,30,0,0,SWP_NOSIZE | SWP_SHOWWINDOW);
    
    m_cTabPage02.Create(IDD_TAB02_DIALOG, &m_cMainTab;);
    m_cTabPage02.SetWindowPos(&wndTop,10,30,0,0,SWP_NOSIZE | SWP_HIDEWINDOW);
                                        ・
                                        ・
                                        ・
    return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われませ
ん。
}

void SampleDlg::OnSelchangeMainTab(NMHDR* pNMHDR, LRESULT* pResult) 
{
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    
    int nidx = m_cMainTab.GetCurSel();

    m_cTabPage01.ShowWindow(SW_HIDE);
    m_cTabPage02.ShowWindow(SW_HIDE);
    
    switch(nidx)
    {
       case 0:
          m_cTabPage01.ShowWindow(SW_SHOW);
          break;
       case 1:
          m_cTabPage02.ShowWindow(SW_SHOW);
          break;
    }
    *pResult = 0;
}
-------------------------------------------------------------------------------
と、こんな感じです。

特にこれといっておかしいところはないかなと思うのですが・・・。
(あくまでも、私が思っているだけですが(笑))

RsrS 2004/10/27(水) 18:28:06
ページはタブの子ウィンドウ(トップのダイアログから見て孫ウィンドウ)なのです
ね。

では、OnInitDialog()の中の処理を、

    ModifyStyleEx(0, WS_EX_CONTROLPARENT);  // 【追加】
    m_cMainTab.ModifyStyleEx(0, WS_EX_CONTROLPARENT);  // 【追加】

    TC_ITEM    TabCtrlItem;
    
    TabCtrlItem.mask = TCIF_TEXT;
    TabCtrlItem.pszText = "ページ1";
    m_cMainTab;.InsertItem( 0, &TabCtrlItem );
    TabCtrlItem.pszText = "ページ2";
    m_cMainTab;.InsertItem( 1, &TabCtrlItem );
    
    m_cTabPage01.Create(IDD_TAB01_DIALOG, &m_cMainTab;);
    m_cTabPage01.ModifyStyle(0, WS_CLIPSIBLINGS | DS_CONTROL);  // 【追加】
    m_cTabPage01.ModifyStyleEx(0, WS_EX_CONTROLPARENT);  // 【追加】
    m_cTabPage01.SetWindowPos(&wndTop,10,30,0,0,SWP_NOSIZE | SWP_SHOWWINDOW);
    
    m_cTabPage02.Create(IDD_TAB02_DIALOG, &m_cMainTab;);
    m_cTabPage02.ModifyStyle(0, WS_CLIPSIBLINGS | DS_CONTROL);  // 【追加】
    m_cTabPage02.ModifyStyleEx(0, WS_EX_CONTROLPARENT);  // 【追加】
    m_cTabPage02.SetWindowPos(&wndTop,10,30,0,0,SWP_NOSIZE | SWP_HIDEWINDOW);

としてみてください。
自作サンプルを同様にしてみて、それらしく動いています。
#これで[ESC]キー処理はトップのダイアログまでパススルーします。
#つまりトップダイアログで [ESC]キー が押されたのと同じ理想的な動作になる。

あと、補足するとページの表示位置は固定値とするのではなく、
    CRect rcDisp;
    m_tab.GetClientRect(rcDisp);
    m_tab.AdjustRect(FALSE, rcDisp);
などとしてタブの表示領域を取得して決めるといいです。

RsrS 2004/10/27(水) 18:34:18
>    m_tab.GetClientRect(rcDisp);
>    m_tab.AdjustRect(FALSE, rcDisp);

自明とは思いますが、ここの m_tab は、きみまろ さんのコードでは
m_cMainTab です。(^^;

きみまろ 2004/10/27(水) 18:49:34
RsrS様、ご回答ありがとうございます。

教えていただいたように、スタイルの変更を追加しましたが、
やっぱり、タブページ内のコントロール(こちらのサンプル
ではエディットコントロール)に移動すると固まってしまい
ます。
RsrS様のサンプルでは、正常に動作しているとの事ですので
、こちらのソースの別の部分(他の処理)でおかしい動作を
していると思います。
今から、タブコントロールだけのサンプルプロを作成して、
どこがおかしいのか調べてみます。

>あと、補足するとページの表示位置は固定値とするのではなく、
>    CRect rcDisp;
>    m_tab.GetClientRect(rcDisp);
>    m_tab.AdjustRect(FALSE, rcDisp);
>などとしてタブの表示領域を取得して決めるといいです。
早速、試してみます。

RsrS 2004/10/27(水) 19:16:23
私のサンプルでは、ページにはボタンとエディットボックスがあります。
ページにするダイアログのプロパティでは、
  スタイル:チャイルド
  境界線:しない
の設定がしてあるだけで、それ以外のチェックボックスはすべて OFF です。
(必要なスタイルは前述のようにコード上で設定)

「固まる」というのは、
ページの親(今回の場合はタブコントロール)や、
更にその上の親(今回の場合はトップのダイアログ)に
WS_EX_CONTROLPARENT が設定されていなかった場合によくある現象ですが...

#前述のように、自分は通常、ページをタブの兄弟にしてしまうことが多いので、
#今回のようなパターンにはあまり自信が無いです。
#っていうか、最近はプロパティシートをダイアログに貼り付けてしまうって
#いうのが一番多いかも。(^^;

きみまろ 2004/10/27(水) 19:58:21
RsrS様、ご回答ありがとうございます。

RsrS様がおっしゃられた通りに、親、またその親のOnInitDialog関数
に、下記の2行を追加してみました。

    this->ModifyStyle(0, WS_CLIPSIBLINGS | DS_CONTROL);
    this->ModifyStyleEx(0, WS_EX_CONTROLPARENT);

これで、実行した結果、エディトコントロールにフォーカス移動する
こともできましたし、また、タブ切替も出来るようになりました。(やった〜!)

ところが、1枚のタブに、ボタンコントロールを追加したみたところ
、ボタンにタブが移動した瞬間に前回同様固まってしまいました。(
ボタンとは別にチェックボックスも追加しましたが、チェックボック
スは通常にタブ移動でき、チェックのON,OFFすることが出来ました)

う〜ん、ボタンに何か原因があるのか・・・。

他のコントロールでも調べてみます。

RsrS 2004/10/27(水) 20:15:59
>    this->ModifyStyle(0, WS_CLIPSIBLINGS | DS_CONTROL);
>    this->ModifyStyleEx(0, WS_EX_CONTROLPARENT);

上の行で DS_CONTROL を設定するのはやりすぎではないですか?
(下の行で WS_EX_CONTROLPARENT を設定しているのはこれでいいですが)

親ダイアログ(上記コードのthis)がチャイルドスタイルで、
更にその親がダイアログなら話は別ですが...
もしそうなら、その祖先ダイアログにも WS_EX_CONTROLPARENT が
必要ってことになるんだろうけど。

ところで、おおもとの[ESC]キーの件はうまくいったのかな?

RsrS 2004/10/27(水) 20:50:58
再確認です。
タブコントロールにも、

    m_cMainTab.ModifyStyleEx(0, WS_EX_CONTROLPARENT);  // 【追加】

はしてあるんですよね?

#私の4つめ以降の発言は、3つめの発言(RsrS 2004/10/27(水) 18:28:06)で
#示した修正コードについて繰り返し言っているだけですよ。
#あの修正コードで問題ないはずだけど...

きみまろ 2004/10/27(水) 23:55:19
[[解決]]
RsrS様、こんばんは。

RsrS様のおっしゃる通りです。
m_cMainTabのスタイル変更を行っていませんでした。

早速、m_cMainTabに、下記の1行を追加したところ、

 m_cMainTab.ModifyStyleEx(0, WS_EX_CONTROLPARENT);

期待通りの動作を致しました。(やった〜!!)

RsrS様、本当にありがとうございました。

>ところで、おおもとの[ESC]キーの件はうまくいったのかな?
はい、うまく動作致しました!

また、質問する機会があるかも知れませんが、その
時は宜しくお願い致します。

それでは。

古いスレッドには追加発言できません。