第七章:无模式对话框 和 Windows通用对话框类
第七章:無模式對話框 和 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);
?
第六章:模式對話框和Windows通用控件
1,對話框也是窗口,它不當可以接受消息,而且還可以被移動和關閉,甚至可以在它的客戶區中進行繪圖操作。
?
2,模式對話框在被關閉之前,用戶無法在同一應用程序的其它地方進行工作。模式對話框更易于編程。
無模式對話框在它仍保留在屏幕的同時,用戶還可以在應用程序的其它窗口進行工作。
?
3,對話框控件既可以通過CWnd指針來引用,也可以通過資源文件定義的索引值(和#define常量相關聯)來引用。對話框控件本身就是一個窗口。控件通過向上級對話框發送消息來響應用戶的動作。
利用ClassWizard可以幫助產生CDialog派生類,還可以使對話框類數據成員和對話框控件相聯系。
?
4,在現存在項目中添加模式對話框步驟:
1)用對話框編輯器創建包含各種控件的對話框資源。對話框編輯器會對項目的資源文件更新,使之包含新的對話框資源,并且該項目的resource.h文件也會被更新,以便能夠包含新的#define常量。
2)利用ClassWizard創建CDialog派生類,并將它和第一步所創建的資源相連接。
3)利用ClassWizard添加控件消息響應函數,并進行編輯。
4)在其它類中需要使用地方先構造該對話框類對象,再調用DoModal顯示模式對話框。
說明:
1)在產生的對話框頭文件中包含一個枚舉類型常量IDD,用于設置該對話框資源ID。枚舉常量IDD的使用減弱了CPP文件對資源ID的依賴。
2)《在其它類中顯示模式對話框后,只有當模式對話框退出后,才繼續執行該類顯示模式對話框代碼后的代碼。》
?
5,在組合筐中Data屬性頁下,添加一條后按CTRL+RETURN來結束(或添加下條item)。(VC6中按?鍵可以獲取相關幫助提示的)。組合框有Simple,Dropdown,Drop List三中風格,可以是Styles中選擇。
列表筐中,用戶只能用鼠標選擇選擇一個條目,而且在對話框編輯器中不能輸入列表框的初始選擇條目。
在靜態文本控件中可以內置'&'符號。運行時候,&符號后面的字符下將有一個下劃線。用戶在按下ALT鍵后同時按下相應帶下劃線的字母,則就可以跳轉到相應的控件上去。注意同一對話框中跳轉字符不能重復。
?
6,當DoModal被調用后,實際在幕后引起一系列如下的動作:
CDialog::DoModal->CEx06Dialog::OnInitDialog->其它的初始化->CDialog::OnInitDialog->CWnd::UpdateData(FALSE)->CEx06Dialog::DoDataExchange
用戶輸入數據...
用戶單擊OK按鈕
CEx06Dialog::OnOk->...其它的確認處理...->CDialog::OnOk->CWnd::UpDateData(TURE)->CEx06Dialog::DoDataExchange->CDialog::EndDialog(IDOK)
說明:
1)virtual BOOL OnInitDialog( );
//CDialog::OnInitDialog This member function is called in response to the WM_INITDIALOG message. This message is sent to the dialog box during the Create, CreateIndirect, or DoModal calls, which occur immediately before the dialog box is displayed.
//Override this member function if you need to perform special processing when the dialog box is initialized.
?
2)BOOL UpdateData( BOOL bSaveAndValidate = TRUE );
//CWnd::UpdateData :Call this member function to initialize data in a dialog box, or to retrieve and validate dialog data.
//bSaveAndValidate:Flag that indicates whether dialog box is being initialized (FALSE) or data is being retrieved (TRUE).
//By default UpdateData(TRUE) is called in the default CDialog::OnOK handler and UpdateData(FALSE) is called in the default CDialog::OnInitDialog.
?
3)virtual void DoDataExchange( CDataExchange* pDX );
//CWnd::DoDataExchange? Called by the framework to exchange and validate dialog data.
//Never call this function (DoDataExchange) directly. It is called by the UpdateData member function.
//Call UpdateData to initialize a dialog box’s controls or retrieve data from a dialog box.
?
4)void EndDialog( int nResult );
//CDialog::EndDialog? makes the dialog box invisible but does not destroy it.
//Call this member function to terminate a modal dialog box. This member function returns nResult as the return value of DoModal(IDOK表示接受對話框數據,IDCANCEL表示取消對話框數據). You must use the EndDialog function to complete processing whenever a modal dialog box is created.
//注意:If you implement the OK button in a modeless dialog box, you must override the OnOK member function and call DestroyWindow from within it.
?
5)當DoModal函數返回的時候,對話框窗口不再存在。我們可以在堆棧中創建模式對話框對象,這樣就可以保證當程序控制轉向到C++對話框對象所在的范圍之外時,它及時的刪除掉。
?
?
7,代碼解釋:
void CEx06aDialog::DoDataExchange(CDataExchange* pDX)
{
?CDialog::DoDataExchange(pDX);
?//{{AFX_DATA_MAP(CEx06aDialog)
?DDX_Text(pDX, IDC_BIO, m_strBio);//
?DDX_Radio(pDX, IDC_CAT, m_nCat);
?...
?DDV_MinMaxInt(pDX, m_nSsn, 0, 999999999);
?//}}AFX_DATA_MAP
}
說明:
1)DoDataExchange、DDX_(交換)、DDV_(確認)函數都具有雙向性。如果調用UpdateData(FALSE)(參數為FALSE),則這些數據就會將與控件相關聯(值關聯)的數據成員的值傳遞給對話框中的控件;相反,如果UpDateData(TURE)(參數是TURE),則這些函數會將數據從對話框控件中傳遞給與之相關聯(值關聯)的數據成員。
2)這里DDX_Text函數被重載,具體參閱MSDN。The DDX_Text function manages the transfer of int, UINT, long, DWORD, CString, float, or double data between an edit control in a dialog box, form view, or control view and a CString data member of the dialog box, form view, or control view object.
其它DDX_函數參閱MSDN。
?
8,Enter鍵觸發OnOk函數調用:
當用戶按下ENTER鍵后,OS會自動去查找輸入焦點落在哪個按鈕上,獲得焦點的按鈕四周將被點線矩形框包圍。如果所有的按鈕都沒獲得輸入焦點,則OS會自動去尋找程序或資源所指定的默認按鈕(默認按鈕邊框較粗)。如果對話框沒有默認按鈕,那么即使對話框中沒有OK按鈕,OnOk函數也會自動被調用。
由于OnOk函數是虛函數,可以重寫OnOk函數,將其函數體置空,變可以使使ENTER鍵無效。
分離OK按鈕:改寫OK按鈕ID,并除掉其默認按鈕(Default Button)的設置。
?
9,p107至WIN32程序員:強烈建議看看,下為簡要筆記。
對話框控件會向他們父對話框發送WM_COMMAND通告消息。大多數窗口程序處理函數都是通過一個嵌套的switch結構了處理這些通告消息的,而MFC則更直接了當地把這些控件通知消息和其它的Windows消息放在同一個層次上處理。
?
10,Esc鍵觸發OnCancel函數的調用,導致控制從對話框中退出,如果是模式對話框則DoModal的還返回IDCANCEL值。其消除方法同ENTER鍵。
?
總結
以上是生活随笔為你收集整理的第七章:无模式对话框 和 Windows通用对话框类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VC++与Java
- 下一篇: Winsock开发网络通信程序的经典入门