子ウィンドのオブジェクトのリファレンスの取得の仕方

[戻る]
f_take2000 2003/11/26(水) 19:38:54
CTabCtrlを使った、MFCアプリケーションを作っています。
CDialogの上に、CTabCtrlをつけて、
それぞれのタブに対応した、CDialogのオブジェクト(子ウィンドウ)を、はりつけてい
ます。
実際には、Tabが押されたときに、そのタブに、対応した、子ウィンドウが見えるよう
に、インプリされています。
ここまでは、動くのですが、
いま、一番下(parent)のウィンドウから、子ウィンドウのオブジェクトのリファレンスが
GetDlgItem で取得できなくて困っています。
子ウィンドウのオブジェクトのリファレンスを、parentウィンドウから取得するいい方法
を教えてください。

環境は、
VC++6.0 Windows2000
よろしくお願いします。

コードの一部です。

dialog1 = (CDialog*)tab->GetDlgItem(IDD_DIALOG1);    
    if(dialog1 == NULL)
    {
// if null, notify on listbox
        ((CListBox*)GetDlgItem(IDC_LIST1))->InsertString(-1,"Failed 
to get IDD_DIALOG1");
        
    }
    else
    {
        ((CListBox*)GetDlgItem(IDC_LIST1))->InsertString(-1,"Success 
to get IDD_DIALOG1");

    }

iijima 2003/11/27(木) 00:31:09
それらの子ウィンドウはどこでどのように作成しているのでしょうか。
parentの子ウィンドウとしてモードレスで作成しているのであれば、普通のモードレス
ダイアログと同じように取り扱えばよいと思います。
見当違いだったらごめんなさい。

f_take2000 2003/11/27(木) 09:53:20
返事ありがとうございます。
すみません、普通のモードレスダイアログのやり方は、どうするのでしょうか?
(GedDlgItem() が普通なのかと思っていました。)

それぞれの子ウィンドウ(mdlg1,mdl12,mdl3)は、parent ダイアログクラスの定義の中
で、protected として、定義されていて、
parent の ダイアログ(CTagDlg)のなかで、それぞれの子ウィンドウ(mdlg1,mdl12,mdl3)
の、Create メソッドを呼び出しいます。

下のコードは、parent ダイアログ class の定義の一部と、parent ダイアログの 
OnInitDialog() method です。


class CTabDlg : public CDialog
{
protected:
    CDialog1 m_dlg1;
    CDialog2 m_dlg2;
    CDialog3 m_dlg3;
    CDialog3 m_dlg4;
    CTabCtrl *m_tab;
    int m_nCurPag;
........................

BOOL CTabDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, 
strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this 
automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    // TODO: Add extra initialization here
       // タブコントロールの初期化
    m_tab = (CTabCtrl*)GetDlgItem(IDC_TAB1);
    TC_ITEM tc[3];
    tc[0].mask = TCIF_TEXT;
    tc[0].pszText = "Tab A";
    tc[1].mask = TCIF_TEXT;
    tc[1].pszText = "Tab B";
    tc[2].mask = TCIF_TEXT;
    tc[2].pszText = "Tab C";
    for(int i=0; i<3; i++){
        m_tab->InsertItem(i, &tc[i]);
    }

 
    int m_nCurPage; // 0:m_dlgA,  1:m_dlgB,  2:m_dlgC
    // ダイアログボックス(Windowsのウィンドウ)の作成
    m_dlg1.Create(IDD_DIALOG1,this);
    m_dlg2.Create(IDD_DIALOG2,this);
    m_dlg3.Create(IDD_DIALOG3,this);
    m_dlg4.Create(IDD_DIALOG4,this);

    
   // タブコントロールの表示領域の取得
    CRect rect;
    m_tab->GetWindowRect(&rect);     // タブコントロールのウィンドウ領域(スクリ
ーン座標系)
    ScreenToClient(&rect);          // クライアント座標系に修正
    m_tab->AdjustRect(FALSE, &rect); // ウィンドウ領域に基づき、表示部の領域に調
整

    // ダイアログボックスの位置あわせ
    m_dlg1.MoveWindow(&rect);
    m_dlg2.MoveWindow(&rect);
    m_dlg3.MoveWindow(&rect);

    // 最初のページを表示
    m_nCurPage = 0;
    m_dlg1.ShowWindow(SW_SHOW);



    return TRUE;  // return TRUE  unless you set the focus to a control
}

PATIO 2003/11/27(木) 10:48:44
タブコントロールにGetDlgItemしていますが、
タブコントロールと実際の各ページにあたるダイアログとは何の関係もないわけで
このコードで対象のダイアログのポインタが取れるとは思えないのですけれど。

タブコントロールは、ユーザーにページの切り替えをさせるためのコントロールであって
ダイアログ表示/非表示の制御をしているわけではありませんよね。
この辺の制御は親のダイアログがしていると思います。
各ダイアログのインスタンスは親のダイアログが持っているようなので
それを直接使って各ダイアログ内のコントロールにアクセスすれば良いだけです。
他は通常のダイアログの扱いと何も変わりません。

dairygoods 2003/11/27(木) 10:49:58
普通にm_dlg1を使えばよいと思うのですが。

f_take2000 2003/11/27(木) 11:36:22
返事ありがとうございます。
>タブコントロールは、ユーザーにページの切り替えをさせるためのコントロールであっ>ダイアログ表示/非表示の制御をしているわけではありませんよね
そうですね。ただ、parent Dialogの中で、直接 GetDlgItemを呼んでも結果は、同じで
した。(下のコードのように)
>各ダイアログのインスタンスは親のダイアログが持っているようなので
>それを直接使って各ダイアログ内のコントロールにアクセスすれば良いだけです
確かに、その方法で、直接の子ウィンドウには、アクセスできるのです。
でも、その子ウィンドウのその子ウィンドウにアクセスしたりする場合には、リソースの
IDで、ウィドウのオブジェクトのリファレンスを取れるほうが、parent のウィンドウ
で、集中的にすべてのウィンドウを管理できて、便利だと思っています。

リソースのIDで、ウィドウのオブジェクトのリファレンスをとる方法は、ないのでしょう
か?



    dialog1 = (CDialog*)GetDlgItem(IDD_DIALOG1);    
    if(dialog1 == NULL)
    {
        ((CListBox*)GetDlgItem(IDC_LIST1))->InsertString(-1,"Failed 
to get IDD_DIALOG1");
        
    }
    else
    {
        ((CListBox*)GetDlgItem(IDC_LIST1))->InsertString(-1,"Success 
to get IDD_DIALOG1");

    }
}

f_take2000 2003/11/27(木) 13:29:35
追加します。
子ウィンドウのCtrlIdをGetDlgCtrlID()でチェックしたら、正しい値が入っていませんで
した(0を返した。)
これは、Create(ctrlId,this)を呼んだときに、設定されると、MFCのCDialogのCreateメ
ソッドのとこれに書いてあると思います。なんか、つかいかたがまずいんのでしょうか?
とりあえず、Createしたあとに、SetDlgCtrlIdをよびだせば、GetDlgItemでとれました。
でもこれって変だと思いますけど。。

    m_dlg1.Create(IDD_DIALOG1,this);
    m_dlg1.SetDlgCtrlID(IDD_DIALOG1);

f_take2000 2003/11/27(木) 13:29:58
追加します。
子ウィンドウのCtrlIdをGetDlgCtrlID()でチェックしたら、正しい値が入っていませんで
した(0を返した。)
これは、Create(ctrlId,this)を呼んだときに、設定されると、MFCのCDialogのCreateメ
ソッドのとこれに書いてあると思います。なんか、つかいかたがまずいんのでしょうか?
とりあえず、Createしたあとに、SetDlgCtrlIdをよびだせば、GetDlgItemでとれました。
でもこれって変だと思いますけど。。

    m_dlg1.Create(IDD_DIALOG1,this);
    m_dlg1.SetDlgCtrlID(IDD_DIALOG1);

dairygoods 2003/11/27(木) 13:44:20
CDialog::Create()に指定するIDと、コントロールIDは無関係です。
コントロールIDは、その名の通りダイアログ内のコントロールを
識別する目的で使われる番号です。
ダイアログのIDは、ダイアログリソースの番号です。

普通の子ウィンドウにもIDを割り振ったり、
そのIDで検索したりすることはできますが、
一般にそのような利用はしないため、
Createの引数等には指定する項目がありません。

f_take2000 2003/11/27(木) 18:27:51
返事ありがとうございます。
もう少し、質問させてください。
では、そのリソースIDで、直接、CDilaogのオブジェクトにアクセスする方法はあるので
しょううか? Create した直後に、かならず、SetDlgCtrlIDを呼ぶというのは、なんか
同じ情報を2度設定しているみたいで少し気持ち悪いです。

tipe 2003/11/27(木) 18:35:22
((CListBox*)m_dlg1.GetDlgItem(IDC_LIST1))->InsertString(-1,"Failed to get 
IDD_DIALOG1");

これではだめなのですか?

dairygoods 2003/11/27(木) 20:39:13
> では、そのリソースIDで、直接、CDilaogのオブジェクトにアクセスする方法はあるので
> しょううか? Create した直後に、かならず、SetDlgCtrlIDを呼ぶというのは、なんか
> 同じ情報を2度設定しているみたいで少し気持ち悪いです。

ありません。
たまたま二箇所で同じ値を使っているだけですから。

ダイアログは、ID以外にも文字列リソース名やメモリーリソースからも構築できますし、
リソースを指定しないで構築することもできます。
IDとダイアログが結び付けられるわけではないのです。

iijima 2003/11/27(木) 23:06:53
すでにたくさんの方が回答されていますが、最初に回答をした手前、、、

PATIOさんwrote:(2003/11/27(木) 10:48:44)
>各ダイアログのインスタンスは親のダイアログが持っているようなので
>それを直接使って各ダイアログ内のコントロールにアクセスすれば良いだけです

私が始めに申し上げたかったのは、こういうことでした。

f_take2000さんwrote:(2003/11/27(木) 11:36:22)
>確かに、その方法で、直接の子ウィンドウには、アクセスできるのです。
>でも、その子ウィンドウのその子ウィンドウにアクセスしたりする場合には、リソース>IDで、ウィドウのオブジェクトのリファレンスを取れるほうが、parent のウィンドウ
>で、集中的にすべてのウィンドウを管理できて、便利だと思っています。

tipeさん(2003/11/27(木) 18:35:22)がおしゃった方法によれば、parentで子ウィンド
ウのコントロールを管理するという目的は達成できるのではないでしょうか。

# OnInitDialogの定義はどこかでみたようなコードですが、気のせいかな(^^;

f_take2000 2003/11/28(金) 09:54:48
[[解決]]
返事ありがとうございます。
tipe さん
>((CListBox*)m_dlg1.GetDlgItem(IDC_LIST1))->InsertString(-1,"Failed to get 
IDD_DIALOG1");

>これではだめなのですか?
これは、動いていて、これと同じことを、resource IDで、child windowを取得できます
か?ということが、質問でした。で、これは、CDialogのCreateメソッドで、指定する、
resource IDは、Ctrl ID にセットされないようなので(from dailywood-san)、無理みた
いです。
iijima さん
それでもいいのですが、child windowが、また、child window(孫winodw)を持っている
場合、parent から、孫window にアクセスするには、その方法では、はじめに、child 
window がCreateされたときに、孫windowの、オブジェクトのリファレンスを、parentに
わたさなくてはいけません。この手順をいちいち実装するくらいなら、resource IDで、
parent window から、孫windowを直接、取得したいと思って質問しました。
で、dailywood さん、
>それは、残念です。CDialogのCreateをよぶときに、SetDlgCtrlItem で、rsource ID 
を、ctrl id に指定することにします。

一応、上の方法で、私のしたいことは、うまくいったので、解決したということにしま
す。多くの、レスポンスありがとうございました。

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