更新說明:v2.0 發布後收到回饋,發現列印預覽視窗中工具列按鈕命令狀態無法更新。v2.1 已修復此問題(見第 10 點說明),並補充文件說明。
本軟體為對話方塊型個人考勤工具,功能:
對話方塊型應用原無 CFrameWnd/CView,為實現列印功能,採用「子框架+子視圖」嵌入主對話方塊的非常規架構(參考《Visual C++ 程式設計高手》範例 18-05 改良)。
CAttendanceDlg dlg;
m_pMainWnd = &dlg;
m_pMiddle = &dlg; // 備份主視窗指標
CChildFrame* pFrame = new CChildFrame;
m_pChildFrame = pFrame;
pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
pFrame->ShowWindow(SW_HIDE); // 初始隱藏
CCreateContext ctx;
ctx.m_pNewViewClass = RUNTIME_CLASS(CChildView);
ctx.m_pCurrentFrame = this;
m_pView = STATIC_DOWNCAST(CChildView, CreateView(&ctx));
if (m_pView) { m_pView->ShowWindow(SW_HIDE); SetActiveView(m_pView); }
// 列印
m_pChildFrame->SendMessage(WM_COMMAND, ID_FILE_PRINT);
// 預覽
m_pChildFrame->ShowWindow(SW_SHOW);
m_pChildFrame->SendMessage(WM_COMMAND, ID_FILE_PRINT_PREVIEW);
CAttendanceApp* app = (CAttendanceApp*)AfxGetApp();
app->m_pMainWnd = this; // 臨時替換
m_pView->ShowWindow(SW_SHOW);
SetActiveView(m_pView);
m_pView->OnFilePrintPreview(this);
pParent->ShowWindow(SW_HIDE);
pParent->UpdateWindow();
app->m_pMainWnd = app->m_pMiddle; // 恢復主對話方塊
app->m_pMiddle->UpdateWindow();
置於 CWrapperView::OnEndPrintPreview 結尾。
問題成因:子框架/子視圖成為對話方塊子物件後,UPDATE_COMMAND_UI 訊息路由受阻,導致預覽工具列按鈕無法正常更新啟用/停用狀態。
解決方案:在 CMyPreviewView::OnDraw(CDC* pDC) 繪製結尾補發訊息:
// 方案一
m_pToolBar->OnUpdateCmdUI((CFrameWnd*)AfxGetApp()->m_pMainWnd, TRUE);
// 方案二
m_pToolBar->PostMessage(WM_IDLEUPDATECMDUI, (WPARAM)TRUE);
每次視圖重繪即主動觸發命令 UI 更新,確保工具列、狀態列狀態即時同步。