MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
MFCコントロール - 分割ウインドウのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
MFCコントロール - 分割ウインドウ
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == 分割ウインドウとは、ウインドウが2つ以上に分割されているウィンドウの事である。<br> Visual C++ではそれぞれの分割された個々のウインドウを「ペイン」と呼ぶ。<br> <br><br> == 左右2分割の分割ウインドウの作成 == MFCでは、分割ウインドウを作成するAPIが標準で用意されている。それが、CSplitterWnd::CreateStatic関数である。<br> 下図のような1行2列の2ペインを持つ分割ウインドウのプログラムを記述する。<br> <br> まず、各ペインを管理するViewクラスを作成する。<br> Viewクラスは、ペインの数だけ必要になるので、上図のように左右2つに分割すると、Viewクラスは全部で2つ必要になる。<br> paneA(左ペイン)にはプロジェクト作成時で用意されているViewクラスを利用し、paneB(右ペイン)のViewクラスは新規で作成する。<br> <br> プロジェクトに新規Viewクラスを追加する。<br> 流れは以下の通りである。<br> [挿入(I)]->[クラスの新規作成(N)]<br> [クラスの種類(T)] MFCクラスを選択<br> [クラス名(N)] 好きなクラス名(ここではCPaneAView)<br> [基本クラス(B)] CFormViewクラス(CViewの派生クラスならどれでもよい)<br> <br> まず、CMainFrm.hファイルを開いて、以下のコードを入力する。<br> '''※MDIアプリケーションの場合は、CChildFrm.hファイルのCChildFrameクラスに同様のコードを追加する。'''<br> <source lang="c++"> CMainFrame.h class CMainFrame : public CFrameWnd { // ... public: CSplitterWnd m_SplitWndMain; // スプリッタウィンドウ // ... } </source> <br> 次に、CMainFrm.cppファイルのCMainFrameクラスにOnCreateClientメンバ関数をオーバーライドする。<br> 手順は以下の通りである。<br> [表示(V)]->[ClassWizard(W)]<br> [プロジェクト(P)] PaneTest<br> [クラス名(N)] CMainFrame<br> [オブジェクトID(I)] CPaneBView<br> [メッセージ(G)] OnCreateClient<br> <br> そして、CMainFrm.cppファイルに、以下のコードを追加する。<br> <source lang="c++"> #include "CPaneTestDoc.h" // CPaneAView.hよりも先にインクルード #include "CPaneAView.h" // CPaneAViewクラスのヘッダをインクルード #include "CPaneBView.h" // CPaneBViewクラスのヘッダをインクルード // ... BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { // ... // ... m_SplitWndMain.CreateStatic( // スプリッタウィンドウの作成 this, // スプリッタウィンドウの親ウィンドウを指定。ここではメインフレームを分割するのでthisを指定。 1, // 行の分割数を指定。ここでは縦分割は無いので1を指定 2); // 列の分割数を指定。ここでは左右分割なので2を指定 m_SplitWndMain.CreateView( // paneA(ペイン場所1x1)を作成。 0, // スプリッタの行番号を指定 0, // スプリッタの列番号を指定 RUNTIME_CLASS(CPaneAView), // 指定ペインを管理するViewクラスCPaneAViewを指定 CSize(20, 0), // ペインのサイズ pContext); m_SplitWndMain.CreateView( // paneB(ペイン場所1x2)を作成。 0, // スプリッタの行番号を指定 1, // スプリッタの列番号を指定 RUNTIME_CLASS(CPaneBView), // paneBを管理するViewクラスCPaneBViewを指定 CSize(0,0), // ペインのサイズ pContext); // ... // ... } </source> <br> ここで注意するのが、CSplitterWnd::CreateView関数の第3引数である。<br> 第3引数において、指定ペインを管理するViewクラスを指定する。<br> paneAを管理するのはCPaneAViewなのでこれを指定する。同様に、paneBを管理するのはCPaneBViewクラスなので、CPaneBViewを指定する。<br> 尚、MDIアプリケーションの場合も同様に、CChildFrameクラスにOnCreateClient関数をオーバーライドして、OnCreateClient関数内に同様のコードを追加する。<br> <br><br> == 変則分割ペインを持つ分割ウインドウの作成 == 下図のように、左側に1つ、右側に2つのウインドウを持つ分割ウインドウを作成する。<br> [[ファイル:MFC Pane 02.jpg|フレームなし|中央]] <br> CSplitterWnd::CreateStatic関数は、n行m列に分割するしか出来ないので、以下の方法を用いる。<br> 左右に2分割した後、分割した右側のペインを更に上下に2分割する。(このように2つのスプリッタが交錯するような構造をネストと呼ぶ)<br> <br> まず、基本分割ウインドウと同様に、それぞれのペインを管理するViewクラスを作成する。<br> ペインAの管理にはCPaneAViewクラス、ペインBはCPaneBView、ペインCはCPaneCViewとしてクラスを追加する。<br> 次に、CMainFrm.hファイルに下記のソースコードを追加する。<br> <source lang="c++"> class CMainFrame : public CFrameWnd { // ... public: CSplitterWnd m_SplitMain; // メインフレームを左右分割する為に使用する分割ウインドウ(メインスプリッタと仮命名) CSplitterWnd m_SplitSub; // 左右分割されたウインドウの右ペインを上下分割するために使用する分割ウインドウ(サブスプリッタと仮命名) // ... } </source> <br> 次に、CMainFrm.cppファイルにCMainFrame::OnCreateClient関数をオーバーライドして、下記のソースコードを追加する。<br> '''※MDIアプリケーションの場合は、CChildFrameクラスに追加すること。'''<br> <source lang="c++"> #include "PaneADoc.h" #include "PaneAView.h" // CPaneAViewクラスのヘッダをインクルード #include "PaneBView.h" // CPaneBViewクラスのヘッダをインクルード #include "PaneCView.h" // CPaneCViewクラスのヘッダをインクルード // ... BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { // ... m_SplitMain.CreateStatic( // メインスプリッタを作成 this, // メインスプリッタの親ウインドウを指定。ここではメインフレームを分割するのでthisを指定 1, // メインスプリッタの行分割数を指定 2); // メインスプリッタの列分割数を指定 m_SplitSub.CreateStatic( // サブスプリッタを作成 &m_SplitMain, // サブスプリッタの親ウィンドウはm_SplitMain 2, // サブスプリッタの行分割を指定 1, // サブスプリッタの列分割を指定 WS_CHILD | WS_VISIBLE, // サブスプリッタのスタイルを指定 m_SplitMain.IdFromRowCol(0,1)); // 子ウィンドウIDを指定。m_SplitMainの行0(=1行目)列1(=2列目)のIDを取得 m_SplitMain.CreateView( // ペインAを作成 0, // メインスプリッタの行番号を指定 0, // メインスプリッタの列番号を指定 RUNTIME_CLASS(CPaneAView), // ペインAを管理するViewクラスCPaneAViewを指定。 CSize(20, 0), // ペインのサイズ pContext); m_SplitSub( // ペインBを作成 0, // サブスプリッタの行番号を指定 0, // サブンスプリッタの列番号を指定 RUNTIME_CLASS(CPaneBView), // ペインBを管理するViewクラスCPaneBViewを指定。 CSize(100, 0), // ペインのサイズ pContext); m_SplitSub( // ペインCを作成。 1, // サブスプリッタの行番号を指定 0, // サブンスプリッタの列番号を指定 RUNTIME_CLASS(CPaneCView), // ペインCを管理するViewクラスCPaneCViewを指定。 CSize(0, 0), // ペインのサイズ pContext); // ... } </source> <br><br> == 管理外Viewクラスからの各ペインへのアクセス方法(SDIの場合) == ここまで、分割ウインドウを作成して様々なペインを作成したが、各ペインをリンクさせながら動作させる方法を説明する。(ペインAで左クリックされたらペインBにテキストを出力する等)<br> ここでは、上記で作成した変則分割ペインを使用する。<br> <br> 各ペインに描画するには、各ペインを管理しているViewクラスの描画関数(OnDraw関数やOnPaint関数)を用いる。<br> <br> CPaneAView.hファイルとCPaneAView.cppファイルに以下のソースコードを追加する。<br> <source lang="c++"> CPaneAView.h #include "CPaneBView.h" #include "CPaneCView.h" #include "CMainFrm.h" class CPaneAView : public CFormView { // ... public: CPaneBView *pPaneB; // CPaneBViewクラスへのポインタ CPaneCView *pPaneC; // CPaneCViewクラスへのポインタ // ... } </source> <source lang="c++"> CPaneAView.cpp #include "CMainFrm.h" // ... CPaneAView::OnDraw(CDC *pDC) { // ... pPaneB = (CPaneBView*)((CMainFrame*)AfxGetMainWnd())->m_SplitSub.GetPane(0, 0); pPaneC = (CPaneCView*)((CMainFrame*)AfxGetMainWnd())->m_SplitSub.GetPane(1, 0); // ... } </source> AfxGetMainWnd関数はメインフレームのオブジェクトを返すので、CPaneAtViewクラスの任意の場所でペインBやペインCにアクセス出来る。<br> また、各ペインのドキュメントには、CWnd::GetDC関数でアクセスできる。例えば、ペインBに"This region is PaneB."と出力する場合は、下記のように記述する。<br> <source lang="c++"> pPaneB->GetDC()->TextOut(0, 0, _T("This region is PaneB.")); </source> <br><br> __FORCETOC__ [[カテゴリ:MFC]]
MFCコントロール - 分割ウインドウ
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse