MFCフローティングウィンドウの使用方法と注意事項

7924 ワード

VS 2008+SP 1を使用してサスペンションウィンドウを作成するには:
1.フローティングウィンドウクラスを作成各フローティングウィンドウは、CDockablePaneの派生クラスのオブジェクトであるため、フローティングウィンドウごとに新しいクラスを作成する
1.1クラスを追加メニューProject->Add Class...または、クラスビューでプロジェクト名を右クリックしてAdd->Classを選択します.クラス選択MFCクラスを追加する、Addボタンをクリックして次のクラス名を書き込む、ここではCDock、Base classを選択してCDockablePaneのFinishボタンを押す、クラスを追加完了する.
1.2メッセージ処理関数を追加するには、一般的に少なくとも2つのメッセージを処理しなければならない.1つはWM_CREATE、一つはWM_SIZE、具体的な手順は、(1)ヘッダファイルに関数宣言(関数名およびパラメータを書き間違えない)protectedを追加する:afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSize(UINT nType, int cx, int cy);(2)cppファイルにメッセージマッピングBEGIN_を追加MESSAGE_MAP(CDock, CDockablePane) ON_WM_CREATE() ON_WM_SIZE()END_MESSAGE_MAP()ここBEGIN_MESSAGE_MAPとEND_MESSAGE_MAPマクロは自動的に生成され、中間2行のコードを追加するだけでよい(3)関数実装部分int CDock::OnCreate(LPCREATESTRUCT lpCreateStruct){if(CDockablePane::OnCreate(lpCreateStruct)=-1)return-1;//ここでコントロールreturn 0を作成する;}void CDock::OnSize(UINT nType,int cx,int cy){CDockablePane::OnSize(nType,cx,cy);//コードを追加}
1.3コントロールを追加する現在作成されているCDockクラスにはコントロールがないため、クラスのオブジェクトを作成して表示すると、この領域はゴミデータだらけであるため、ウィンドウの表示時にスクリーンになる可能性がある.プログラムの実行中にスクリーンのような問題が発生した場合、いくつかの可能性があります.1.コントロール2が作成されていません.コントロールは作成されましたが、コントロールの位置がdockablePane 3全体を上書きしていません.コントロールは領域全体を占めていますが、ここを自動的にリフレッシュすることはできません.listBoxを追加する例:(1)クラスのヘッダファイルにコントロールオブジェクトを追加します.コードはprotected:CListBox_です.listBox;(2)OnCreate()にコントロールウィンドウを作成するコードを追加する:ここでは、ベースクラスの関数OnCreate()int CDock 1::OnCreate(LPCREATESTRUCT lpCreateStruct){if(CDockablePane::OnCreate(lpCreateStruct)=-1)return-1を呼び出す必要があることに注意してください.
//ここでコントロールを作成//nIDはこのコントロールのIDで、自分で設定することができます.IDに興味がない場合は、0を渡してシステムにif(!_listBox.create(WS_CHILD|WS_VISIBLE,CRect(0,0,0,0,0),this,nID){TRACE 0("listboxの作成に失敗しました");return-1; }
 return 0;}(3)OnSizeにおいて各コントロールの位置を設定ここで注意すべきことは、コントロールをウィンドウ全体にわたって満たすことである.ここにはlistBoxが1つしかないので、直接listBoxでウィンドウを覆うことができる.同様に、ベースクラス関数CDockablePane::OnSize(nType,cx,cy)void CDock::OnSize(UINT nType,int cx,int cy){CDockablePane::OnSize(nType,cx,cy);//コードif(GetSafeHwnd()=NULL){return; }
 if (_listBox.GetSafeHwnd() != NULL) {  CRect rectClient;  GetClientRect(rectClient);  _listBox.SetWindowPos(NULL, rectClient.left, rectClient.top, rectClient.Width(), rectClient.Height(), SWP_NOACTIVATE | SWP_NOZORDER); }
}
 
2.プログラムに懸濁窓オブジェクトを追加する前のステップは、プロジェクトに懸濁窓クラスを追加しただけで、そのクラスのインスタンスは生成されなかった.ここでこのインスタンスを作成します(CMainFrameクラスで)
2.1メインフレームワーククラス宣言にオブジェクトを追加します.コード:protected:CDock m_wndDock;
2.2 dockablePaneを作成するウィンドウ、メインフレームワークのOnCreate()関数で(注:OnCreate関数でコードEnableAutoHidePanes(CBRS_ALIGN_ANY)の後に追加することをお勧めします)int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){...EnableAutoHidePanes(CBRS_ALIGN_ANY);//ここのCBRSを利用してRIGHTは最初のウィンドウが止まる位置を設定し、可能な値は//CBRS_です.NOALIGN, CBRS_LEFT, CBRS_TOP, CBRS_RIGHT, CBRS_BOTTOM DWORD style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI;if(!wndDock 1.CReate(//このdockウィンドウのタイトル(できれば...)  _T("Dock 1"),//このdockウィンドウのparentは、this,//ウィンドウのサイズに設定、注意が「浮遊」の場合のサイズであり、dock状態にある場合のサイズはその値に関係なくCRect(0,0,200,200),//このdockウィンドウにタイトルがあるかどうか、FALSEであれば最初の文字列パラメータはTRUE,//このdockウィンドウのID値が表示されない.注意:dockウィンドウのステータスをレジストリに保存したい場合(次回プログラムを起動してもそのステータスを維持する)、この値に必要な一意のnID、//style){return FALSE; } ...} 
2.3 CDockablePaneのCloseボタンを外す?
方法1:
CDockablePaneを継承するクラスでCanBeClosed()メソッドを書き換えます.
virtual BOOL CanBeClosed() const; ... BOOL COutputWnd::CanBeClosed() const { return FALSE;
}
方法2:
if (!m_wndView.Create(strFileView, this, CRect(0, 0, 250, 200), TRUE, ID_VIEW_VIEW,
  WS_CHILD | WS_VISIBLE | CBRS_LEFT | CBRS_HIDE_INPLACE | WS_CAPTION, AFX_CBRS_REGULAR_TABS, AFX_CBRS_RESIZE))Createの時にこのようなパラメータを付けてAFX_を設定するCBRS_REGULAR_TABS, AFX_CBRS_RESIZEにはそのクローズボタンはありません
2.4隠しCDockablePaneを表示する
m_wndFileView.ShowPane(TRUE,FALSE,TRUE);// 


m_wndFileView.ShowPane(FALSE,FALSE,TRUE);//

2.5懸濁窓にiconを追加する、しばらく省略する.
 
3.ウィンドウの浮遊方式を設定し、ウィンドウを浮遊させる
3.1ウィンドウの浮遊位置を設定この部分のコードもMainFrame類のOnCreate関数の中にあるべきで、しかも浮遊ウィンドウを作成する後についている.浮遊位置を設定するにはCDockablePane::EnableDockingを呼び出すだけでよいm_wndDock.EnableDocking(CBRS_ALIGN_ANY);ここで、パラメータはCBRS_であってもよいALIGN_TOP, CBRS_ALIGN_RIGHT, CBRS_ALIGN_BOTTOM, CBRS_ALIGN_ANY
3.2ウィンドウを浮遊させるCDockablePaneオブジェクトを浮遊させるには、フレームクラスのDockPane関数を呼び出すだけでよい:DockPane(&m_wndDock);しかし、別の懸濁ウィンドウのオブジェクトが必要な場合はm_wndDockが一緒に表示され、1つのグループ(VSのリソース視力とクラスビューのように)を構成すると、2番目の懸濁ウィンドウはCDockablePaneクラスのAttchToTabWnd関数を使用する必要があり、コードは以下の通りである:DockPane(&m_wndDock); CDockablePane *pTabbedBar = NULL; m_wndDock2.AttachToTabWnd(&m_wndDock, DM_SHOW, FALSE, &pTabbedBar);
 
 
CDockablePane使用
これは転載です
int m_nshowCurrent;
m_nshowCurrent=theApp.GetProfileInt(_T("Workspace//Pane-377"),_T("IsFloating"),0);//コンストラクタで
まず2つのサブクラスを派生して、ソースコードは書く必要はありませんて、紙面を占めて、MainFrmの中で申明します:CCurrentDockablePane m_wndCurrentDockablePane;CHistoryDockablePane        m_wndHistoryDockablePane;CDockablePane* m_pTabbedBar;
そしてOnCreate()の中:CString strHistoryDockablePane;CString strCurrentView;strCurrentView.LoadString(IDS_Current_VIEW);strHistoryDockablePane.LoadString(IDS_History_VIEW);
if (!m_wndHistoryDockablePane.Create(strHistoryDockablePane, this, CRect(0, 0, 200, 200),    TRUE, ID_VIEW_HistoryDockablePane, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI)){     TRACE0("Failed to create Class View window/n");      return FALSE;//failed to create}
if (!m_wndCurrentDockablePane.Create(strCurrentView, this, CRect(0, 0, 200, 200),    TRUE, ID_VIEW_CurrentView, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT| CBRS_FLOAT_MULTI)){    TRACE0("Failed to create File View window/n");     return FALSE;//failed to create}
アイコンを追加:HICON hHistoryDockablePaneIcon=(HICON):LoadImage(::AfxGetResourceHandle()、MAKEINTRESOURCE(bHiColorIcons?IDI_history:IDI_history)、IMAGE_ICON,::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON), 0);m_wndHistoryDockablePane.SetIcon(hHistoryDockablePaneIcon, FALSE);HICON hCurrentViewIcon = (HICON)::LoadImage(::AfxGetResourceHandle(),    MAKEINTRESOURCE(bHiColorIcons ? IDI_Currrently : IDI_Currrently), IMAGE_ICON,::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON), 0);m_wndCurrentDockablePane.SetIcon(hCurrentViewIcon, FALSE);m_wndHistoryDockablePane.EnableDocking(CBRS_ALIGN_ANY);m_wndCurrentDockablePane.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndHistoryDockablePane);DockPane(&m_wndCurrentDockablePane);m_pTabbedBar = NULL;
m_wndCurrentDockablePane.AttachToTabWnd(&m_wndHistoryDockablePane, DM_SHOW, FALSE, &m_pTabbedBar);
関連表示コードはこのようになった.その後、ボスはツールバーの表示状態を変更する必要があると言って、チェックを外しました.ツールバーで表示と非表示を制御するのは簡単ですね.m_を使います.wndCurrentDockablePane.ShowPane(TRUE,FALSE,TRUE);しかし閉じてからツールバーを修正してしばらく考えていたが、CDockablePaneのClose()メッセージをリロードするかと思ったら、また彼の多くのメッセージを試してみたが、間違っていた.追跡してMainFrmを呼び出して閉じたことを知った.中にはpMainfrmが入っていますonCloseDockingPane(this);では、この方法を再ロードします.
BOOL CMainFrame::OnCloseDockingPane( CDockablePane* pWnd ){     CWnd * pfWnd = pWnd->GetFocus();    if (*pfWnd == m_wndCurrentDockablePane)    {        m_nshowCurrent = 0;    }    else if(*pfWnd == m_wndHistoryDockablePane)    {       m_nshowHistory = 0;    }   return TRUE; }これでツールバーの情報が更新されます.ほほほ、喜ぶのは早すぎて、やっと半分して、2つのパネルが分解して、つまり浮動状態にある時に閉じて根本的にここを呼び出しません.またしばらく気がふさいでいたが、やはりボス牛が追い詰めて、その状況はOnCloseMiniFrameだと言って、そこで次のような重荷があった.
BOOL CMainFrame::OnCloseMiniFrame( CPaneFrameWnd* pWnd ){       CWnd *ptWnd = pWnd->GetWindow( GW_CHILD );     if (*ptWnd ==m_wndCurrentDockablePane)      {            m_nshowCurrent = 0;     }      else if (*ptWnd == m_wndHistoryDockablePane)    {             m_nshowHistory = 0;    }   return TRUE; }
 
//レジストリを書き込み、構造関数で
theApp.WriteProfileInt(_T("Workspace//Pane-377"),_T("IsFloating"),m_nshowCurrent);