第七章:無模式對話框 和 Windows通用對話框類
1,[無模式對話框]在它處於激活狀態下還允許用戶在(同一個應用程序中)其它地方工作。
[通用對話框]則是C++和一組Windows的實用對話框之間的程序設計借口,包括File Open,Page Setup,Color等等,它們都是通過COMDLG32.DLL來實現的。
2,兩種發送Windows消息:
CWnd::SendMessage//立刻導致對窗口控制函數的調用
CWnd::PostMessage//將消息放進Windows消息隊列。對消息的處理可能被滯後。
具體:
1)LRESULT SendMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
//Sends the specifIEd message to this window. The SendMessage member function calls the window procedure directly and does not return until that window procedure has processed the message. This is in contrast to the PostMessage member function, which places the message into the window’s message queue and returns immediately.
2)BOOL PostMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
//Places a message in the window’s message queue and then returns without waiting for the corresponding window to process the message. Messages in a message queue are retrIEved by calls to the GetMessage or PeekMessage Windows function.
3,對話框實際上應該屬於應用程序的主框架窗口,而不屬於視圖。(對話框默認彈出特性)
(注:還未領悟,先留著。)
4,對話框窗口的創建和取消完全取決與用戶的操作,而對話框對象則將直到應用程序被終止時才會被刪除。
(除了主框架窗口之外,對於幾乎所有的窗口類型,DestroyWindow函數都不會將C++對象刪除掉。所以要注意手動添加刪除對話框對象代碼)
5,Windows 常量WM_USER是用戶自定義消息中可以利用的第一個消息ID。
#define WM_USER 0x0400
//The WM_USER constant is used by applications to help define private messages, usually of the form WM_USER+X, where X is an integer value.
說明:
1)CWnd::PostMessage//發送消息。利用wParam , LPARAM可以向響應消息的處理函數傳送附加數據信息。
BOOL PostMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
2)在WIN32中,用wParam 和LPARAM參數來傳遞消息數據是最常用的手段(如:將鼠標的X,Y坐標壓縮進lParam)。而在MFC庫中,消息數據可以更多樣的類型來傳遞(如:可以CPoint對象來傳遞鼠標信息)。
對於用戶自定義消息,只能使用wParam 和LPARAM參數來傳遞消息附加數據信息。
3)案例說明:
在對話框類中:
#define WM_GOODBYE WM_USER + 5//定義自定義消息
m_pView->PostMessage(WM_GOODBYE, IDOK);//向View類發送WM_GOODBYE消息,附加消息IDOK存放在wParam 中。m_pView指向當前VIEw類對象。
在VIEw 類對象中
afx_msg LRESULT OnGoodbye(WPARAM wParam, LPARAM lParam);
ON_MESSAGE(WM_GOODBYE, OnGoodbye)
LRESULT CEx07aVIEw::OnGoodbye(WPARAM wParam, LPARAM lParam)
{
return 0L;
}
4)技巧:在對話框類中重載構造函數,參數為CView*指針。再在對話框類中定義一個CView*指針數據成員。這樣,如果在View類中通過傳入this指針來構造對話框對象的時候,對話框類中CView*指針數據成員可以在帶參數為CView*指針重載構造函數裡方便獲取構造它的VIEw類指針。
6,ClassWizard並不支持用戶自定義消息的響應,所以當使用用戶自定義消息編程的時候,必須自己編寫自定義消息的處理代碼。(三步,首先是消息響應函數原型聲明,其次消息映射,最後是編寫消息響應函數代碼。這裡要注意:用戶自定義消息的消息映射一定要加在BEGIN_MESSAGE_MAP(..)~~END_MESSAGE_MAP()之間,//{{AFX_MSG_MAP(CEx07aVIEw)~~ //}}AFX_MSG_MAP注釋宏對之外)
7,對於無模式對話框一定要注意不要調用CDialog::OnOk或者CDialog::OnCancel函數,既在無模式對話框類中必須重載這些虛函數;否則當使用ESC鍵,回車鍵或者用鼠標單擊OK|CANCEL按鈕的時候,會激發對應基類函數的調用,進而導致調用Windows 的EndDialog函數,EndDialog函數只適合於模式對話框。對於無模式對話框,必須調用DestroyWindow函數。
如果需要的話,還可調用Updatedata函數來將數據從對話框控件中傳到類數據成員中。
8,Windows通用對話框:
共同特點:都從用戶處獲得消息,但並不對信息做處理。如:文件對話框只為程序提供路徑名,字體對話框只是填充一個描敘字體的結構,並不創建字體。
所有的通用對話框類都從公有基類CCommonDialog派生而來。
COMDLG32中類列表如下:
CColorDialog 允許用戶選擇或創建顏色
CFileDialog 允許用戶打開或者保存一個文件
CFindReplaceDialog 允許用戶將一個字符串換成另一個字符串
CPageSetupDialog 允許用戶輸入頁面參數
CFontDialog 允許用戶從列出的可用字體中選擇一種字體
CPrintDialog 允許用戶設置打印機並打印文檔
9,注意:在Win32中,不能在標准文件對話框內部動態創建控件。(其它標准對話框中也應該如此吧)
10,嵌套對話框(這些內容熔入EX07B事例中講解了,不打算重復,強烈建議看看和跟著做做,頁碼:P135-141。下面只對其中重要的函數做些說明筆記。)
利用MFC,從通用
1)CFileDialog::m_ofn
//m_ofn is a structure of type OPENFILENAME. Use this structure to initialize the appearance of a File Open or File Save As dialog box after it is constructed but before it is displayed with the DoModal member function.
2)CFileDialog::CFileDialog
CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWord dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );
//bOpenFileDialog
Set to TRUE to construct a File Open dialog box or FALSE to construct a File Save As dialog box.
3)CFileDialog::DoModal
//Call this function to display the Windows common file dialog box and allow the user to browse files and directorIEs and enter a filename.
//If you want to initialize the various file dialog-box options by setting members of the m_ofn structure, you should do this before calling DoModal, but after the dialog object is constructed.
//When the user clicks the dialog box’s OK or Cancel buttons, or selects the Close option from the dialog box’s control menu, control is returned to your application. You can then call other member functions to retrIEve the settings or information the user inputs into the dialog box.
4)CFileDialog::GetPathName
//Call this function to retrIEve the full path of the file entered in the dialog box. The path of the filename includes the file’s title plus the entire directory path.
5)事例中注意設置自己創建的子對話框上的組筐控件的ID為stc32。這樣才保證文件通用對話框嵌入的位置在組筐所在的位置上,否則默認為自己創建的子對話框的同寬度。(stc32應該是與文件通用對話框相關聯的,具體是如何關聯的哦?)
6)事例中可見到這樣的代碼(GetParent()->GetDlgItem(IDOK)->SetWindowText("Delete");)來獲取文件通用對話框上的控件指針,這裡要理解為什麼要用GetParent()函數來獲得父窗口指針(因為事例中自己所創建的對話框被設置成Child Style。)(Child style,None border,Group box ID=stc32這些設置都是必不可少的,自己可以試著改變這些設置,看看效果印象也就深了)
7)事例中CSpecialFileDialog::OnDelete() 函數中代碼(GetParent()->GetDlgItem(0x480)->GetWindowText(m_strFileName);)通過獲取文件通用對話框上文件名對應的編輯框的指針調用CWnd::GetWindowText函數來獲取編輯框中的文本保存在m_strFileName數據成員中。其中0x480應該是文件通用對話框上文件名對應的編輯框的ID。
8)事例中CSpecialFileDialog::OnDelete() 函數中代碼(GetParent()->SendMessage(WM_COMMAND,IDCANCEL);)向文件通用對話框發送IDCANCEL消息,該操作引起OnCancel函數的調用終止當前模式對話框同時使得CFileDialog::DoModal函數返回IDCANCEL值。
MSDN:
CDialog::OnCancel (The default simply terminates a modal dialog box by calling EndDialog and causing DoModal to return IDCANCEL.)
9)SDK函數:FindFirstFile,DeleteFile
//FindFirstFile Searches a directory for a file whose name matches the specified file name on the destination site identifIEd by this object. It examines subdirectory names as well as file names.
//DeleteFile Deletes the given file from the destination site.
10)CFile::Remove
A static function ,deletes the file specifIEd by the path. It will not remove a directory. (注意:用這函數刪除的文件是不經過回收站的哦。)
11,在對話框標題欄添加圖標:在對話框類OnInitDialog函數中添加如下代碼。
HICON hIcon =AfxGetApp()->LoadIcon(ID_MYICON);//ID_MYICON是用資源編輯器創建的圖標ID。
this->SetIcon(hIcon,TRUE);
this->SetIcon(hIcon,FALSE);注:這裡帶上this指針目的是為了強調必須使用目的對話框類對象指針調用SetIcon設置圖標。
比如在書EX07B事例中,由於CSpecialFileDialog類設置為子窗口類,而且所關聯的資源窗口沒有Tittle Bar,要在父窗口文件通用對話框Tittle Bar上添加圖標,必須獲取父窗口文件通用對話框對象指針來調用SetIcon設置圖標。
如在書EX07B事例中:在CSpecialFileDialog::OnInitDialog函數中添加如下代碼,可設置文件通用對話框標題圖標:
HICON hIcon =AfxGetApp()->LoadIcon(ID_MYICON);
GetParent()->SetIcon(hIcon,TRUE);
GetParent()->SetIcon(hIcon,FALSE);