更新說明:自拙作 attendance( 2.0 版 ) 個人考勤軟件登出後,不時有網友來信交流,最近有網友指出程序中的一個缺陷:在打印預覽窗口中工具條按鈕的命令狀態不能改變。現在這個問題已基本解決。現將改好的源代碼(可以算作2.1版)發布出來,同時對說明文檔進行了增補(第10點說明)。
這個程序是一個個人考勤軟件,它從系統時鐘獲取時間信息,只要上下班時按時在當日考勤欄內點擊相應的欄目標題即可逐日記錄下個人每天的工作時間,按月統計匯總,按年形成文件.可以隨意查看過去的記錄,也可把記錄按月打印出來.在年匯總欄內可以選擇要查看或打印的月份。 這個小程序是我的一個習作,希望與感興趣的同好切磋交流。
本程序是一個基於對話框的實用程序,在基於對話框界面的程序中實現打印和打印預覽是采用了非常規MFC方法。 基於對話框的程序原本是不含框架類CFrameWnd和視類CView對象的,為了實現打印和打印預覽,需要在主對話框對象中創建子框架對象CChildFrame,再在子框架中創建子視類對象CChildView,打印和打印預覽就在CChildView中完成。這部分內容基本上直接取自北京希望電子出版社出版的《Vsual C++ 編程高手》一書中的例18\05,但要把書中的主框架CMainFrm改為子框架CChildFrame而置於主對話框管理之下。
具體做法如下:
1.在創建應用程序實例的InitInstance()函數中創建我們的主對話框對象:CAttendanceDlg dlg;
之後立即把這個對象的指針信息存入CWinApp::m_pMainWnd 和附加的m_pMiddle中備用:m_pMainWnd = &dlg;
2.在ClassWizard中為主對話框類導入OnCreate()函數,在其中創建子框架對象CChildFrame
m_pMiddle = &dlg;CChildFrame* pFrame = new CChildFrame;
暫時將其顯示狀態置為隱藏: m_pChildFrame->ShowWindow(SW_HIDE);
m_pChildFrame = pFrame;
pFrame->LoadFrame(IDR_MAINFRAME,
WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,//,m_pMainWnd
NULL);
3.在子框架對象CChildFrame的OnCreate()函數中創建子視類對象CChildViewCCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS(CChildView);
context.m_pCurrentFrame = this;
context.m_pCurrentDoc = NULL;
context.m_pLastView = NULL;
m_pView = STATIC_DOWNCAST(CChildView, CreateView(&context)); //CreateView(&context);
if(m_pView != NULL)
{
m_pView->ShowWindow(SW_HIDE);//暫時將其顯示狀態也置為隱藏
SetActiveView(m_pView);
}
4.在主對話框的打印或打印預覽處理函數中只要向子框架CChildFrame發送相應的消息即可: 對於打印函數為:m_pChildFrame->SendMessage(WM_COMMAND, ID_FILE_PRINT);
或對於打印預覽函數為: m_pChildFrame->ShowWindow(SW_SHOW);//將子框架CChildFrame顯示狀態置為顯示
m_pChildFrame->SendMessage(WM_COMMAND, ID_FILE_PRINT_PREVIEW);//打印預覽
5.在子框架CChildFrame的打印預覽處理函數中需要將CWinApp::m_pMainWnd暫時替換為子框架CChildFrame的指針,並把子視類對象的顯示狀態激活後調用子視類對象的打印預覽處理函數
CAttendanceApp* app=(CAttendanceApp*)AfxGetApp();
app->m_pMainWnd = this;//應用程序主窗口臨時替換為子框架窗口
m_pView->ShowWindow(SW_SHOW);
SetActiveView(m_pView);
m_pView->OnFilePrintPreview(this);
6.打印預覽結束退出之前必須恢復原有的顯示狀態,並將CWinApp::m_pMainWnd恢復為主對話框:
pParent->ShowWindow(SW_HIDE);//將子框架CChildFrame顯示狀態重新置為隱藏
這些後處理工作放在CWrapperView::OnEndPrintPreview(..)函數中的結尾處完成。
pParent->UpdateWindow();
CAttendanceApp* app=(CAttendanceApp*)AfxGetApp();
app->m_pMainWnd = app->m_pMiddle;//應用程序主窗口恢復為主對話框窗口
app->m_pMiddle->UpdateWindow();
7.最後還要為子框架創建一個標識為IDR_MAINFRAME的菜單資源,其中只需要打印和打印預覽兩項即可。
8.打印的內容和頁面布局都放在CChildView::OnDraw(CDC* pDC)函數中完成。
9.函數CAttendanceApp::SetPrntOrientation()是用來強制設定打印方向為縱向的,在打印或打印預覽中先要調用它。如果要設為橫向則只要把其中的 DMORIENT_PORTRAIT 替換為 DMORIENT_LANDSCAPE 即可 閱讀以上說明請參照程序的源代碼。
10. 對 2.1 版的補充:可能是由於子框架、子視圖成為對話框的子對象以後,致使本來在框架、視圖中暢通的UPDATE_COMMAND_UI消息路由被阻斷,造成打印預覽對話框各個命令按鈕不能正常地更新其命令狀態,解決的辦法是在 CMyPreviewView::OnDraw(CDC* pDC)函數的最後添加一行: m_pToolBar->OnUpdateCmdUI((CFrameWnd*)AfxGetApp()->m_pMainWnd,1);
或 m_pToolBar->PostMessage(WM_IDLEUPDATECMDUI,(WPARAM)TRUE);
每當視圖發生改變重畫以後及時向預覽視圖補發 UPDATE_COMMAND_UI 消息,使工具條和狀態條及時更新其狀態。
本文配套源碼