使用VS2008+SP1創建懸浮窗口的步驟: (自己寫的文檔, 以備以後使用)
1. 創建懸浮窗口類
每一個懸浮窗口都是一個CDockablePane的派生類的對象, 因此要爲每一個懸浮窗口創建一個新類
1.1 添加類
通過菜單Project->Add Class...或者在類視圖中工程名字處右鍵選擇Add->Class...添加類
選擇MFC Class, 點Add按鈕進入下一步
Class name處寫入新類的名字, 這裏用CDock, 選擇Base class爲CDockablePane
按Finish按鈕, 添加類完成.
1.2 添加消息處理函數
一般至少要處理兩個消息, 一個是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宏都是自動生成的, 只需要添加中間兩行代碼即可
(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 CDock1::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), this, nID))
{
TRACE0("創建listbox失敗");
return -1;
}
return 0;
}
(3) 在OnSize中設置各個控件的位置
這裏要注意的是, 需要將控件佈滿整個窗口. 這裏只有一個listBox, 故可以直接用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 (!wndDock1.Create(
// 該dock窗口的標題(如果可以有的話...)
_T("Dock1"),
// 該dock窗口的parent, 設置爲this
this,
// 窗口的大小, 注意是"懸浮"的情況下的大小, 處於dock狀態時大小與該值無關
CRect(0, 0, 200, 200),
// 該dock窗口是否有標題, 如果爲FALSE, 則第一個字符串參數顯示不出來
TRUE,
// 該dock窗口的ID值. 注意: 如果希望dock窗口的狀態可以保存在註冊表中(這樣下次啓動程序時仍保持該狀態), 則該值必須的唯一的
nID,
//
style))
{
return FALSE;
}
...
}
2.3 給懸浮窗口添加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在一起顯示, 構成一個組(就像VS的資源視力和類視圖), 那麼第二個懸浮窗口需要使用CDockablePane類的AttchToTabWnd函數, 代碼如下:
DockPane(&m_wndDock);
CDockablePane *pTabbedBar = NULL;
m_wndDock2.AttachToTabWnd(&m_wndDock, DM_SHOW, FALSE, &pTabbedBar);