「MFCコントロール - 分割ウインドウ」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

文字列「</source>」を「</syntaxhighlight>」に置換
 
(3人の利用者による、間の8版が非表示)
22行目: 22行目:
まず、CMainFrm.hファイルを開いて、以下のコードを入力する。<br>
まず、CMainFrm.hファイルを開いて、以下のコードを入力する。<br>
'''※MDIアプリケーションの場合は、CChildFrm.hファイルのCChildFrameクラスに同様のコードを追加する。'''<br>
'''※MDIアプリケーションの場合は、CChildFrm.hファイルのCChildFrameクラスに同様のコードを追加する。'''<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  CMainFrame.h
  CMainFrame.h
   
   
32行目: 32行目:
     // ...
     // ...
  }
  }
  </source>
  </syntaxhighlight>
<br>
<br>
次に、CMainFrm.cppファイルのCMainFrameクラスにOnCreateClientメンバ関数をオーバーライドする。<br>
次に、CMainFrm.cppファイルのCMainFrameクラスにOnCreateClientメンバ関数をオーバーライドする。<br>
43行目: 43行目:
<br>
<br>
そして、CMainFrm.cppファイルに、以下のコードを追加する。<br>
そして、CMainFrm.cppファイルに、以下のコードを追加する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  CMainFrm.cpp
  CMainFrm.cpp
   
   
84行目: 84行目:
     }
     }
     // ...
     // ...
    //return CFrameWndEx::OnCreateClient(lpcs, pContext);
     return TRUE;
     return TRUE;
  }
  }
  </source>
  </syntaxhighlight>
<br>
<br>
ここで注意するのが、CSplitterWndEx::CreateView関数の第3引数である。<br>
ここで注意するのが、CSplitterWndEx::CreateView関数の第3引数である。<br>
111行目: 112行目:
<br>
<br>
次に、CMainFrm.hファイルに下記のソースコードを追加する。<br>
次に、CMainFrm.hファイルに下記のソースコードを追加する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  CMainFrm.h
  CMainFrm.h
   
   
122行目: 123行目:
     // ...
     // ...
  }
  }
  </source>
  </syntaxhighlight>
<br>
<br>
次に、CMainFrm.cppファイルにCMainFrame::OnCreateClient関数をオーバーライドして、下記のソースコードを追加する。<br>
次に、CMainFrm.cppファイルにCMainFrame::OnCreateClient関数をオーバーライドして、下記のソースコードを追加する。<br>
133行目: 134行目:
<br>
<br>
'''※MDIアプリケーションの場合は、CChildFrameクラスに追加すること。'''<br>
'''※MDIアプリケーションの場合は、CChildFrameクラスに追加すること。'''<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  CMainFrm.cpp
  CMainFrm.cpp
   
   
197行目: 198行目:
     return TRUE;
     return TRUE;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


208行目: 209行目:
<br>
<br>
CPaneAView.hファイルとCPaneAView.cppファイルに以下のソースコードを追加する。<br>
CPaneAView.hファイルとCPaneAView.cppファイルに以下のソースコードを追加する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  CPaneAView.h
  CPaneAView.h
   
   
223行目: 224行目:
     // ...
     // ...
  }
  }
  </source>
  </syntaxhighlight>
  <source lang="c++">  
  <syntaxhighlight lang="c++">  
  CPaneAView.cpp
  CPaneAView.cpp
   
   
238行目: 239行目:
     // ...
     // ...
  }
  }
  </source>
  </syntaxhighlight>
AfxGetMainWnd関数はメインフレームのオブジェクトを返すので、CPaneAtViewクラスの任意の場所でペインBやペインCにアクセス出来る。<br>
AfxGetMainWnd関数はメインフレームのオブジェクトを返すので、CPaneAtViewクラスの任意の場所でペインBやペインCにアクセス出来る。<br>
また、各ペインのドキュメントには、CWnd::GetDC関数でアクセスできる。<br>
また、各ペインのドキュメントには、CWnd::GetDC関数でアクセスできる。<br>
例えば、ペインBに"This region is PaneB."と出力する場合は、下記のように記述する。<br>
例えば、ペインBに"This region is PaneB."と出力する場合は、下記のように記述する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  CPaneAView.cpp
  CPaneAView.cpp
   
   
  pPaneB->GetDC()->TextOut(0, 0, _T("This region is PaneB."));
  pPaneB->GetDC()->TextOut(0, 0, _T("This region is PaneB."));
  </source>
  </syntaxhighlight>
<br><br>
 
== 分割ウインドウの固定化 ==
分割ウインドウを手動で変更できないようにする方法がある。(分割を固定にする)<br>
<br>
まず、CSplitterWndExの派生クラスを作成して、OnLButtonDownハンドラをオーバーライドして<br>
CSplitterWndEx::OnLButtonDown関数を呼ばないようにすれば可能である。<br>
また、スプリッターバー上でマウスカーソルを変更しないようにするには、OnMouseMoveハンドラをオーバーライドして<br>
CSplitterWndEx::OnMouseMove関数を呼ばないようにすれば可能である。<br>
<br>
上記よりも簡単な方法がある。<br>
それは、CSplitterWndExの派生クラスを作成して、OnNcHitTestハンドラをオーバーライドして<br>
CSplitterWndEx::OnNcHitTest関数で無条件にHTBORDERを返せば、マウスカーソルも変更されない。<br>
<br>
<br>
分割ウインドウにて、仕切り位置を固定し、ユーザーに位置変更をさせない方法がある。<br>
また、カーソルが乗っても移動用のカーソルに変更しないようにする。<br>
<br>
まず、CSpritterWndまたはCSpritterWndExの派生クラスを作成する。(ここではCMySplitterWndEx)<br>
CMySplitterWndExにてHitTestハンドラをオーバーライドする。<br>
HitTestハンドラは、下記のように宣言されている。<br>
virtual int HitTest(CPoint pt) const;
<br>
HitTestの戻り値は下記の通りで、操作禁止にしたい方向のときに"0"を返すようにする。<br>
<syntaxhighlight lang="c++">
enum HitTestValue
{
    noHit                  = 0,
    vSplitterBox            = 1,
    hSplitterBox            = 2,
    bothSplitterBox        = 3,          // just for keyboard
    vSplitterBar1          = 101,        // 横方向の上下に動かすバー
    vSplitterBar15          = 115,
    hSplitterBar1          = 201,        // 縦方向の左右に動かすバー
    hSplitterBar15          = 215,
    splitterIntersection1  = 301,        // 縦と横が交わる点
    splitterIntersection225 = 525
};
</syntaxhighlight>
<syntaxhighlight lang="c++">
int CMySplitterWndEx::HitTest(CPoint pt) const
{
    int ht = CSplitterWndEx::HitTest(pt);  // CSpritterWndExは、テーマの変更処理が追加されただけなのでCSplitterWndでも可
    if(ht == 201 || ht == 301)
    {  // 横方向のバーだけ上下に移動可
      ht = 0;  // ヒットしてないことにする
    }
    return ht;
}
</syntaxhighlight>
上記の例では、横方向のバーだけ上下に移動出来るようになり、縦方向や交差している点ではカーソルも変更されない。<br>
enumのHitTestValueはcppファイル内で宣言されているため、使用する場合は各自で追加する。<br>
<br><br>
 
== リサイズ変更 ==
SetRowInfo and SetColumnInfo are responsible for managing the size of the splitters. Add a handler for the WM_ONSIZE message and add the following code:<br>
<br>
Hide  Copy Code<br>
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
    CFrameWnd::OnSize(nType, cx, cy);
    CRect cr;
    GetWindowRect(&cr);
 
    if (  m_bInitSplitter && nType != SIZE_MINIMIZED )
    {
        m_mainSplitter.SetRowInfo( 0, cy, 0 );
        m_mainSplitter.SetColumnInfo( 0, cr.Width() / 2, 50);
        m_mainSplitter.SetColumnInfo( 1, cr.Width() / 2, 50);
 
        m_mainSplitter.RecalcLayout();
    }
}
<br>
In the above code, we first check that the splitters have been initialized by checking the boolean value. This check is required since I think a WM_SIZE message is passed to the frame before the create method is ran - therefore, the object won't exist the first time this code runs and would crash if you didn't check for its existence.<br>
<br>
The application should now run and provide something resembling the screenshot at the start of the article! I will probably add a second article in this series to add further nested splitters and other views based on forms! Stay tuned...<br>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:MFC]]
[[カテゴリ:MFC]]