MFCで、タブコントロール上に表示する子ダイアログ上のコントロール位置をダイアログエディタ上とデバッグ実行中で一致させたい


MFCで、タブコントロール上に表示する子ダイアログを作成して、ダイアログエディタ上でボタンコントロールを追加してデバッグ実行すると、ボタンコントロールを貼り付けた位置よりもやや左下にボタンコントロールがずれて描画されているように見えるというバグで困っています。

※1.
単純にダイアログエディタ上でボタンコントロールをずれたぶんだけ右上にドラッグ&ドロップすれば解決するのですが、ダイアログエディタ上とデバッグ実行中でコントロールの描画位置に差異のないようにしたいです。

※2.
MoveWindow関数等のコントロールを移動する関数を使えば、解決するかもしれませんが、コントロールを追加する毎にその処理を読んだりメンバ変数を作らなければならないので、修正がなるべく少ない方法を教えて頂きたいです。

【ダイアログエディタ上でボタンコントロールを追加した位置とデバッグ実行中のボタンコントロールの位置の差異】  
[![画像の説明をここに入力](https://i.stack.imgur.com/JJgga.png)](https://i.stack.imgur.com/JJgga.png)

解決策のご回答をお願い致します。




**まず、質問の現象はバグではなく正常な動作でしょう。**

子ダイアログをタブコントロールに組み込んだ時点で、子ダイアログの原点(0, 0)はタブコントロールの「To Do」の文言の下になっているでしょう。  
質問記事の図で言えば、以下のように **子ダイアログとタブコントロールの緑色の十字の位置が同じ原点(0, 0)** と思われます。
**質問の意図としては赤色の十字の位置を子ダイアログの原点(0, 0)にしたい** のでしょうが、簡単には出来ないでしょうね。(ピンクの部分は後述)

[![回答画像](https://i.stack.imgur.com/Kwt7d.jpg)](https://i.stack.imgur.com/Kwt7d.jpg)

子ダイアログの表示位置・サイズを調節することは可能ですが、以下のような課題があります。  
それらの課題があったとしても表示位置・サイズを調節したいかどうか、を考えてみてください。

例えば @Cold Starch Jelly さんの紹介記事では以下の箇所でタブコントロール上の子ダイアログ表示位置・サイズを設定しています。

>
[code]

>     // サイズを計算する
>     CRect r;
>     m_ctrlTab.GetClientRect(&r);
>     r.left +=2;
>     r.right -=4;
>     r.top += 20;
>     r.bottom -= 4;
>  
>     // ダイアログを、タブの子ウィンドウとして作る
>     m_pDlg1 = new CDlg1(&m_ctrlTab);  
>     m_pDlg1->Create(CDlg1::IDD, &m_ctrlTab);
>     m_pDlg1->MoveWindow(&r);
>  
[/code]

表示結果は以下になります。

[![初期画像](https://i.stack.imgur.com/Kisi0.png)](https://i.stack.imgur.com/Kisi0.png)

これを特に工夫せず上記の表示位置・サイズ計算をコメントアウトして、`m_ctrlTab.GetClientRect(&r)`で取得した情報をそのまま`m_pDlg1->MoveWindow(&r)`にすると以下のようになり、タブコントロールのタブキャプション部分等が覆い隠されてしまいます。

[![位置だけ調整画像](https://i.stack.imgur.com/dSNef.png)](https://i.stack.imgur.com/dSNef.png)

そのため、いったん表示範囲を限定するためのウィンドウを間に挟んで、今は子ウィンドウとなっているものを孫ウィンドウとする形にします。  
ただし、 **子ウィンドウでクリッピングするため、孫ウィンドウの上端と左端(上記質問記事図のピンク色の部分)は常に表示されなくなります。**

>
[code]

>     // サイズを計算する
>     CRect r;
>     m_ctrlTab.GetClientRect(&r);
>     r.left +=2;
>     r.right -=4;
>     r.top += 20;
>     r.bottom -= 4;
>  
>     // 孫ウィンドウをクリッピングする子ウィンドウを作成する
>     pW1 = new CWnd();  // CWnd* pW1;を .hに追加しておく
>     pW1->Create(_T("STATIC"), NULL, WS_CHILD | WS_VISIBLE, r, &m_ctrlTab,
> 145);
>     pW1->MoveWindow(&r);
>  
>     // ダイアログを、タブの孫ウィンドウとして作る
>     m_pDlg1 = new CDlg1(pW1);
>     m_pDlg1->Create(CDlg1::IDD, pW1);
>     CRect c1;
>     c1.left = -15; // 孫ウィンドウの表示位置調節
>     c1.top  = -15; // 以下同じ
>     c1.right = r.right - r.left;
>     c1.bottom = r.bottom - r.top;
>     m_pDlg1->MoveWindow(&c1);
>  
>     // 子＆孫ウィンドウの表示
>     pW1->ShowWindow(SW_SHOW);
>     m_pDlg1->ShowWindow(SW_SHOW);
>  
>     // OnTcnSelchangeTab1()の表示切替処理
>     if (m_ctrlTab.GetCurSel() == 0)
>     {
>         pW1->ShowWindow(SW_SHOW);
>         m_pDlg1->ShowWindow(SW_SHOW);
>         pW2->ShowWindow(SW_HIDE);
>         m_pDlg2->ShowWindow(SW_HIDE);
>     }
>     else
>     {
>         pW2->ShowWindow(SW_SHOW);
>         m_pDlg2->ShowWindow(SW_SHOW);
>         pW1->ShowWindow(SW_HIDE);
>         m_pDlg1->ShowWindow(SW_HIDE);
>     }
>  
[/code]

こちらの表示結果は以下になります。

[![クリッピング画像](https://i.stack.imgur.com/6lx5o.png)](https://i.stack.imgur.com/6lx5o.png)




**まず、質問の現象はバグではなく正常な動作でしょう。**

子ダイアログをタブコントロールに組み込んだ時点で、子ダイアログの原点(0, 0)はタブコントロールの「To Do」の文言の下になっているでしょう。  
質問記事の図で言えば、以下のように **子ダイアログとタブコントロールの緑色の十字の位置が同じ原点(0, 0)** と思われます。
**質問の意図としては赤色の十字の位置を子ダイアログの原点(0, 0)にしたい** のでしょうが、簡単には出来ないでしょうね。(ピンクの部分は後述)

[![回答画像](https://i.stack.imgur.com/Kwt7d.jpg)](https://i.stack.imgur.com/Kwt7d.jpg)

子ダイアログの表示位置・サイズを調節することは可能ですが、以下のような課題があります。  
それらの課題があったとしても表示位置・サイズを調節したいかどうか、を考えてみてください。

例えば @Cold Starch Jelly さんの紹介記事では以下の箇所でタブコントロール上の子ダイアログ表示位置・サイズを設定しています。

>
[code]

>     // サイズを計算する
>     CRect r;
>     m_ctrlTab.GetClientRect(&r);
>     r.left +=2;
>     r.right -=4;
>     r.top += 20;
>     r.bottom -= 4;
>  
>     // ダイアログを、タブの子ウィンドウとして作る
>     m_pDlg1 = new CDlg1(&m_ctrlTab);  
>     m_pDlg1->Create(CDlg1::IDD, &m_ctrlTab);
>     m_pDlg1->MoveWindow(&r);
>  
[/code]

表示結果は以下になります。

[![初期画像](https://i.stack.imgur.com/Kisi0.png)](https://i.stack.imgur.com/Kisi0.png)

これを特に工夫せず上記の表示位置・サイズ計算をコメントアウトして、`m_ctrlTab.GetClientRect(&r)`で取得した情報をそのまま`m_pDlg1->MoveWindow(&r)`にすると以下のようになり、タブコントロールのタブキャプション部分等が覆い隠されてしまいます。

[![位置だけ調整画像](https://i.stack.imgur.com/dSNef.png)](https://i.stack.imgur.com/dSNef.png)

そのため、いったん表示範囲を限定するためのウィンドウを間に挟んで、今は子ウィンドウとなっているものを孫ウィンドウとする形にします。  
ただし、 **子ウィンドウでクリッピングするため、孫ウィンドウの上端と左端(上記質問記事図のピンク色の部分)は常に表示されなくなります。**

>
[code]

>     // サイズを計算する
>     CRect r;
>     m_ctrlTab.GetClientRect(&r);
>     r.left +=2;
>     r.right -=4;
>     r.top += 20;
>     r.bottom -= 4;
>  
>     // 孫ウィンドウをクリッピングする子ウィンドウを作成する
>     pW1 = new CWnd();  // CWnd* pW1;を .hに追加しておく
>     pW1->Create(_T("STATIC"), NULL, WS_CHILD | WS_VISIBLE, r, &m_ctrlTab,
> 145);
>     pW1->MoveWindow(&r);
>  
>     // ダイアログを、タブの孫ウィンドウとして作る
>     m_pDlg1 = new CDlg1(pW1);
>     m_pDlg1->Create(CDlg1::IDD, pW1);
>     CRect c1;
>     c1.left = -15; // 孫ウィンドウの表示位置調節
>     c1.top  = -15; // 以下同じ
>     c1.right = r.right - r.left;
>     c1.bottom = r.bottom - r.top;
>     m_pDlg1->MoveWindow(&c1);
>  
>     // 子＆孫ウィンドウの表示
>     pW1->ShowWindow(SW_SHOW);
>     m_pDlg1->ShowWindow(SW_SHOW);
>  
>     // OnTcnSelchangeTab1()の表示切替処理
>     if (m_ctrlTab.GetCurSel() == 0)
>     {
>         pW1->ShowWindow(SW_SHOW);
>         m_pDlg1->ShowWindow(SW_SHOW);
>         pW2->ShowWindow(SW_HIDE);
>         m_pDlg2->ShowWindow(SW_HIDE);
>     }
>     else
>     {
>         pW2->ShowWindow(SW_SHOW);
>         m_pDlg2->ShowWindow(SW_SHOW);
>         pW1->ShowWindow(SW_HIDE);
>         m_pDlg1->ShowWindow(SW_HIDE);
>     }
>  
[/code]

こちらの表示結果は以下になります。

[![クリッピング画像](https://i.stack.imgur.com/6lx5o.png)](https://i.stack.imgur.com/6lx5o.png)

