VC++对话框学习总结
生活随笔
收集整理的這篇文章主要介紹了
VC++对话框学习总结
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
VC++中如何復(fù)制對(duì)話框資源
http://www.cnblogs.com/Yogurshine/p/3710566.html法1:
在你的工程中添加另一個(gè)工程的rc文件,這時(shí)資源視圖中就會(huì)出現(xiàn)兩個(gè)rc,從后加的rc中拷貝資源到你自己工程的rc中就可以了。
?
法2:vc中如何拷貝一個(gè)工程的對(duì)話框資源到另一個(gè)工程中?
?
這是一個(gè)很專業(yè)也很有用的問題。其實(shí)VC的設(shè)計(jì)者早就為我們考慮了這個(gè)問題。
在VC6環(huán)境下,選擇Class視圖,選中想要克隆的對(duì)話框所對(duì)應(yīng)的類,例如CAboutDlg,點(diǎn)擊鼠標(biāo)右鍵,選擇Add to gallery。在新工程中選擇Project菜單,選擇Add Component and ActivX,你會(huì)看到多了一個(gè)文件夾(與上一個(gè)工程同名),進(jìn)入該文件夾,選擇*.ogx。選擇Insert,你會(huì)發(fā)現(xiàn)原來的對(duì)話框被加入到新的工程中了!
?
補(bǔ)充:
.net下更簡單,將原來的工程加到新的工程中,直接將對(duì)話框拷貝過去就行了!
?
法3:
VC++中如何復(fù)制對(duì)話框資源
第一步:用記事本打開原工程的.rc文件,找到想復(fù)制的對(duì)話框的信息,如下所示
?
IDD_UGMS_DIALOGDIALOGEX 0, 0, 320, 230 STYLE WS_CHILD | WS_VISIBLE EXSTYLE WS_EX_APPWINDOW FONT 9, "宋體" BEGINGROUPBOX "學(xué)生信息",IDC_STATIC,10,8,290,200GROUPBOX "",IDC_STATIC,25,55,205,120PUSHBUTTON "最前(&F)",IDC_BUTTON_FIRST,30,30,35,15PUSHBUTTON "向前(&B)",IDC_BUTTON_PRE,82,30,35,15PUSHBUTTON "向后(&N)",IDC_BUTTON_NEXT,134,30,35,15PUSHBUTTON "最后(&L)",IDC_BUTTON_LAST,186,30,35,15PUSHBUTTON "查詢(&Q)",IDC_BUTTON_QUERY,246,70,40,15PUSHBUTTON "增加(&A)",IDC_BUTTON_ADD,246,96,40,15PUSHBUTTON "修改(&M)",IDC_BUTTON_MODIFY,246,122,40,15PUSHBUTTON "刪除(&D)",IDC_BUTTON_DELETE,246,148,40,15PUSHBUTTON "確定(&O)",IDC_BUTTON_OK,58,183,40,15PUSHBUTTON "取消(&C)",IDC_BUTTON_CANCEL,150,183,40,15LTEXT "學(xué)號(hào):",IDC_STATIC,52,75,25,8LTEXT "姓名:",IDC_STATIC,52,100,25,8LTEXT "性別:",IDC_STATIC,52,125,25,8LTEXT "入學(xué)時(shí)間:",IDC_STATIC,44,151,41,8EDITTEXT IDC_EDIT_SID,91,72,95,15,ES_AUTOHSCROLLEDITTEXT IDC_EDIT_SNAME,91,96,95,15,ES_AUTOHSCROLLEDITTEXT IDC_EDIT_SSEX,91,120,95,15,ES_AUTOHSCROLLCONTROL "DateTimePicker1",IDC_DATETIMEPICKER_SCOMEDATE,"SysDateTimePick32",DTS_RIGHTALIGN | WS_TABSTOP,91,144,95,15GROUPBOX "",IDC_STATIC,25,19,205,35 END
?上面代碼中綠色背景代表的是要復(fù)制的對(duì)話框資源的ID,此段代碼也就是.rc文件中記錄的此對(duì)話框的信息,黃色背景中間的代碼就是
?相應(yīng)對(duì)話框中添加的控件信息,只需將相應(yīng)代碼拷到新工程的相應(yīng).rc文件相應(yīng)的ID對(duì)話框資源的BEGIN 和END之間即可;
?
第二步:打開原工程的FileView視圖下的Header Files 下的resource.h文件,將其中相應(yīng)ID的信息復(fù)制到新工程的resource.h中即可;
?例如:
?
//復(fù)制的資源ID #define IDC_BUTTON_FIRST 1000 #define IDC_BUTTON_PRE 1001 #define IDC_BUTTON_NEXT 1002 #define IDC_BUTTON_LAST 1003 #define IDC_BUTTON_QUERY 1004 #define IDC_BUTTON_ADD 1005 #define IDC_BUTTON_MODIFY 1006 #define IDC_BUTTON_DELETE 1007 #define IDC_BUTTON_OK 1008 #define IDC_BUTTON_CANCEL 1009 #define IDC_EDIT_SID 1010 #define IDC_EDIT_SNAME 1011 #define IDC_EDIT_SSEX 1012 #define IDC_DATETIMEPICKER_SCOMEDATE 1013
?
第三步:記得不要遺漏啊,如有ID重復(fù),可以更改一下即可!
??
法4:
?今天碰到模塊移植問題了,自己做的對(duì)話框類(繼承于CDialog)要移植到目標(biāo)工程中.在網(wǎng)上搜了幾個(gè)帖子發(fā)現(xiàn)都說的很生澀.問了我們的技術(shù)總監(jiān)之后總算解決這個(gè)問題了.
?? ? ? 問題:把一個(gè)MFC SDI工程中的一個(gè)對(duì)話框資源和類拷貝到另一個(gè)MFC SDI中.
?? ? ? 1.在VC6中打開老的工程,在工作區(qū)Resource標(biāo)簽頁中選中Dialog文件夾下的資源文件(就是雙擊后會(huì)出現(xiàn)編輯窗口界面的那個(gè)東西),按Ctrl+C(Edit->Copy也一樣).
?? ? ? 2.關(guān)閉當(dāng)前工程,注意不要關(guān)閉VC6,打開目標(biāo)工程(File->OpenWorkspace),然后選中工作區(qū)的Resource標(biāo)簽頁中的Dialog文件夾,然后按Ctrl+V(Edit->Paste也一樣).好了,對(duì)話框拷貝過來了.
?? ? ? 3.將對(duì)話框類的cpp h文件拷貝到目標(biāo)工程中(不詳細(xì)說了,往當(dāng)前工程添加文件)
?? ? ? 4.打開復(fù)制過來的類cpp和h文件,刪除沒用的頭文件(老工程相關(guān)的),并且在.h文件中添加文件包含
?
#include "Resource.h"
第四步很關(guān)鍵,老工程中根本就沒有這個(gè)文件包含,可是移植之后必須手動(dòng)添加頭文件包含.因?yàn)檫@個(gè)問題卡了10幾分鐘...
當(dāng)你用資源ID時(shí)(通常資源編輯器編輯的資源ID都在resource.h中),如果沒有包含CWinApp的派生類所在的頭文件就會(huì)出錯(cuò),你看一下它的頭文件里,包含了這個(gè)文件, 而向?qū)傻念?#xff0c;它的實(shí)現(xiàn)文件都有包含CWinApp派生類所在的頭文件的
然后在新工程中就可以使用這個(gè)類了,主要就是這個(gè)類的對(duì)話框中的資源復(fù)制頭一次遇到.不敢獨(dú)享,拿出來跟新手們一起學(xué)習(xí).
?
于是,當(dāng)有已經(jīng)創(chuàng)建好的對(duì)話框資源要添加到新工程中時(shí):
(1)右鍵單擊新工程所在的解決方案添加“現(xiàn)有項(xiàng)目”把舊工程添加進(jìn)來;
(2)切換到“資源視圖”并在舊工程對(duì)話框資源上右鍵“復(fù)制”;
(3)在新工程對(duì)話框資源上右鍵“粘貼”;
(4)現(xiàn)在就可以為新對(duì)話框添加類了,順便把舊工程的響應(yīng)函數(shù)拷貝過來;
(5)切換回“解決方案資源管理器”,右鍵舊工程“移除”。
========
VS2010/MFC編程入門之十六(對(duì)話框:消息對(duì)話框)
http://www.jizhuomi.com/software/171.html
? ? ? ?前面幾節(jié)雞啄米講了屬性頁對(duì)話框,我們可以根據(jù)所講內(nèi)容方便的建立自己的屬性頁對(duì)話框。本節(jié)講解Windows系統(tǒng)中最常用最簡單的一類對(duì)話框--消息對(duì)話框。
? ? ? ?我們?cè)谑褂肳indows系統(tǒng)的過程中經(jīng)常會(huì)見到消息對(duì)話框,提示我們有異常發(fā)生或提出詢問等。因?yàn)樵谲浖_發(fā)中經(jīng)常用到消息對(duì)話框,所以MFC提供了兩個(gè)函數(shù)可以直接生成指定風(fēng)格的消息對(duì)話框,而不需要我們?cè)诿看问褂玫臅r(shí)候都要去創(chuàng)建對(duì)話框資源和生成對(duì)話框類等。這兩個(gè)函數(shù)就是CWnd類的成員函數(shù)MessageBox()和全局函數(shù)AfxMessageBox()。
? ? ? ?一.CWnd::MessageBox()函數(shù)和AfxMessageBox()函數(shù)的用法
? ? ? ?下面雞啄米就分別講解兩個(gè)函數(shù)的用法。
? ? ? ?1.CWnd::MessageBox()函數(shù)
? ? ? ?CWnd::MessageBox()的函數(shù)原型如下:
? ? ? ?int MessageBox(
? ? ? ? ? ?LPCTSTR lpszText,
? ? ? ? ? ?LPCTSTR lpszCaption = NULL,
? ? ? ? ? ?UINT nType = MB_OK?
? ? ? ?);
? ? ? ?參數(shù)說明:
? ? ? ?lpszText:需要顯示的消息字符串。
? ? ? ?lpszCaption:消息對(duì)話框的標(biāo)題字符串。默認(rèn)值為NULL。取值為NULL時(shí)使用默認(rèn)標(biāo)題。
? ? ? ?nType:消息對(duì)話框的風(fēng)格和屬性。默認(rèn)為MB_OK風(fēng)格,即只有“確定”按鈕。
? ? ? ?nType的取值可以是下面兩個(gè)表中任取一個(gè)值,也可以是各取一個(gè)值的任意組合。即可以指定一個(gè)對(duì)話框類型,也可以指定一個(gè)對(duì)話框圖標(biāo),還可以兩者都設(shè)定。
nType 取值 參數(shù)說明
MB_ABORTRETRY 有“終止”、“重試”和“忽略”按鈕
MB_OK 有“確定”按鈕
MB_OKCANCEL 有“確定”和“取消”按鈕
MB_RETRYCANCEL 有“重試”和“取消”按鈕
MB_YESNO 有“是”和“否”按鈕
MB_YESNOCANCEL 有“是”、“否”和“取消”按鈕
對(duì)話框類型表
nType 取值 顯示圖標(biāo)
MB_ICONEXCLAMTION
MB_ICONWARNING VS2010/MFC編程入門之十六(對(duì)話框:消息對(duì)話框)
MB_ICONASTERISK
MB_ICONINFORMATION VS2010/MFC編程入門之十六(對(duì)話框:消息對(duì)話框)
MB_ICONQUESTION VS2010/MFC編程入門之十六(對(duì)話框:消息對(duì)話框)
MB_ICONHAND
MB_ICONSTOP
MB_ICONERROR VS2010/MFC編程入門之十六(對(duì)話框:消息對(duì)話框)
? ? ? ?如果想要設(shè)置nType的值為類型和圖標(biāo)的組合,可以像這樣取值:MB_OKCANCEL | MB_ICONQUESTION。按位取或就可以了。
VS2010/MFC編程入門之十六(對(duì)話框:消息對(duì)話框)
? ? ? ?2.AfxMessageBox()函數(shù)
? ? ? ?AfxMessageBox()的函數(shù)原型為:
? ? ? ?int AfxMessageBox(
? ? ? ? ? ?LPCTSTR lpszText,
? ? ? ? ? ?UINT nType = MB_OK,
? ? ? ? ? ?UINT nIDHelp = 0?
? ? ? ?);
? ? ? ?參數(shù)說明:
? ? ? ?lpszText:同CWnd::MessageBox()函數(shù)
? ? ? ?nType:CWnd::MessageBox()函數(shù)
? ? ? ?nIDHelp:此消息的幫助的上下文ID。默認(rèn)值為0,取0時(shí)表示要使用應(yīng)用程序的默認(rèn)幫助上下文。
? ? ? ?二.CWnd::MessageBox()和AfxMessageBox()的返回值
? ? ? 我們?cè)谡{(diào)用了上面兩個(gè)函數(shù)后,都可以彈出模態(tài)消息對(duì)話框。消息對(duì)話框關(guān)閉后,我們也都可以得到它們的返回值。兩者的返回值就是用戶在消息對(duì)話框上單擊的按鈕的ID,可以是以下值:
? ? ? IDABORT:單擊“終止”按鈕。
? ? ? IDCANCEL:單擊“取消”按鈕。
? ? ? IDIGNORE:單擊“忽略”按鈕。
? ? ? IDNO:單擊“否”按鈕。
? ? ? IDOK:單擊“確定”按鈕。
? ? ? IDRETRY:單擊“重試”按鈕。
? ? ? IDYES:單擊“是”按鈕。
? ? ? 三.應(yīng)用舉例
? ? ?我們還是拿前面加法計(jì)算器的程序做例子。
? ? ? ?大家是否記得,在模態(tài)對(duì)話框及其彈出過程中我們修改了CAdditionDlg::OnBnClickedAddButton()函數(shù),在點(diǎn)了“計(jì)算”按鈕以后先彈出了一個(gè)模態(tài)對(duì)話框,詢問用戶是否確定要進(jìn)行加法計(jì)算,并通過模態(tài)對(duì)話框DoModal函數(shù)的返回值判斷用戶選擇了“確定”還是“取消”。這些功能很明顯消息對(duì)話框完全能夠?qū)崿F(xiàn),雞啄米就使用消息對(duì)話框來替代原來的模態(tài)對(duì)話框。
? ? ? ?在非模態(tài)對(duì)話框的創(chuàng)建及顯示中,雞啄米注釋了模態(tài)對(duì)話框的相關(guān)代碼,加入了非模態(tài)對(duì)話框的創(chuàng)建和顯示代碼,我們?cè)诩尤胂?duì)話框之前將非模態(tài)對(duì)話框的代碼也注釋或刪除掉,確保此函數(shù)中不再生成原來的模態(tài)對(duì)話框或非模態(tài)對(duì)話框。
? ? ? ?修改后的CAdditionDlg::OnBnClickedAddButton()函數(shù)如下:
C++代碼
void CAdditionDlg::OnBnClickedAddButton() { // TODO: Add your control notification handler code here INT_PTR nRes; // 顯示消息對(duì)話框 nRes = MessageBox(_T("您確定要進(jìn)行加法計(jì)算嗎?"), _T("加法計(jì)算器"), MB_OKCANCEL | MB_ICONQUESTION); // 判斷消息對(duì)話框返回值。如果為IDCANCEL就return,否則繼續(xù)向下執(zhí)行 if (IDCANCEL == nRes) return; // 將各控件中的數(shù)據(jù)保存到相應(yīng)的變量 UpdateData(TRUE); // 將被加數(shù)和加數(shù)的加和賦值給m_editSum m_editSum = m_editSummand + m_editAddend; // 根據(jù)各變量的值更新相應(yīng)的控件。和的編輯框會(huì)顯示m_editSum的值 UpdateData(FALSE); // 設(shè)置屬性對(duì)話框?yàn)橄驅(qū)?duì)話框 //sheet.SetWizardMode(); }
? ? ? ? 編譯運(yùn)行,在運(yùn)行結(jié)果對(duì)話框上點(diǎn)“計(jì)算”按鈕彈出以下消息對(duì)話框:
VS2010/MFC編程入門之十六(對(duì)話框:消息對(duì)話框)
? ? ? ?大家也可以將MessageBox函數(shù)換為AfxMessageBox()函數(shù),同時(shí)參數(shù)進(jìn)行相應(yīng)修改,運(yùn)行下看看效果。
========
VC++創(chuàng)建對(duì)話框(轉(zhuǎn)) ?
http://blog.163.com/yx_xie2007/blog/static/102464253201002904022375/?對(duì)話框有模式對(duì)話框和非模式對(duì)話框兩種。以下用基于Visual Studio 2008的MFC為例,創(chuàng)建一個(gè)程序。
?首先創(chuàng)建一個(gè)MFC單文檔應(yīng)用程序,名稱為DialogTest.打開資源視圖——Menu——IDR_MAINFRAME,在菜單欄中添加一個(gè)標(biāo)簽“對(duì)話框測(cè)試”,ID設(shè)置為IDM_DIALOGTEST,在屬性中把popup屬性設(shè)置為false.添加兩個(gè)子菜單,分別是“模式對(duì)話框”,ID為IDM_DIALOG1;“非模式對(duì)話框”,ID為IDM_DIALOG2.
?之后在資源視圖中的Dialog中添加一個(gè)對(duì)話框,并添加一個(gè)靜態(tài)文本控件,Caption設(shè)置為“模式對(duì)話框”,ID為IDD_DIALOG1,雙擊對(duì)話框空白處,在彈出的MFC類向?qū)е忻惷麨镃TestDlg1,基類選擇CDialog,之后完成。同理添加另一個(gè)對(duì)話框,ID為IDD_DIALOG2。在MFC類向?qū)е械念惷O(shè)置為CTestDlg2,基類同樣為CDialog.
?完成資源的添加后,我們就要完善代碼。再次打開IDR_MAINFRAME,右鍵選擇“模式對(duì)話框”,在彈出的右鍵菜單中選擇“添加事件處理程序”,在彈出的對(duì)話框中的“消息類型”選擇COMMAND,類列表選擇CDialogTestView,點(diǎn)擊“添加編輯”,輸入代碼:
?CTestDlg1 dlg;
?dlg.DoModal();
此時(shí),模式對(duì)話框創(chuàng)建完畢。相對(duì)于模式對(duì)話框來說,非模式對(duì)話框的創(chuàng)建相對(duì)復(fù)雜一點(diǎn)。同樣是再次打開IDR_MAINFRAME,右鍵選擇“非模式對(duì)話框”,在彈出的右鍵菜單中選擇“添加事件處理程序”,在彈出的對(duì)話框中的“消息類型”選擇COMMAND,類列表選擇CDialogTestView,點(diǎn)擊“添加編輯”,輸入代碼:
?CTestDlg2 *pDlg=new CTestDlg2;
?pDlg->Create(IDD_DIALOG2,this);
?pDlg->ShowWindow(SW_SHOW);
在這里,我將對(duì)話框?qū)ο蠖x為指針,在堆上分配內(nèi)存,使其與程序的生命周期一致。之后用Creat()函數(shù)創(chuàng)建一個(gè)對(duì)話框,并用ShowWindow()將其顯示出來。這里用到了指針指向操作符,只因?yàn)槎x的對(duì)話框?qū)ο鬄橹羔橆愋?#xff0c;且調(diào)用了其成員函數(shù)(有C++基礎(chǔ)的都會(huì)明白這一點(diǎn)吧......)。由于pDlg這個(gè)指針變量為局部對(duì)象,當(dāng)其生命周期結(jié)束后,其保存的內(nèi)存地址就會(huì)丟失。所以我們應(yīng)該在CTestDlg2類中重載PostNcDestroy這個(gè)虛函數(shù)來釋放this指針指向的內(nèi)存。只需在這個(gè)函數(shù)中添加一句:
?delete this;
?CDialog::PostNcDestroy();
因?yàn)槲覀冊(cè)诔绦蛑惺褂昧薈TestDlg1,CTestDlg2,CDialogTestView類并不清楚其數(shù)據(jù)類型。因此我們要在DialogTestView.cpp開始出添加:
#include "TestDlg1.h"
#include "TestDlg2.h"
編譯運(yùn)行程序,結(jié)果如下所示:VC++創(chuàng)建對(duì)話框(轉(zhuǎn))
========
VC++如何最大化對(duì)話框
一打開一個(gè)對(duì)話框程序,對(duì)話框就最大化,并且要求沒有標(biāo)題欄,沒有右上角的關(guān)閉,最大化,最小化等按鈕,總之就是全屏顯示的對(duì)話框如何實(shí)現(xiàn)?
1. API方式:
可以通過 ShowWindow 函數(shù)改變窗口的顯示狀態(tài)。語法為:
BOOL ShowWindow( ? ? ? ? ?HWND hWnd,
int nCmdShow
);
hWnd 表示窗口句柄
nCmdShow 表示想要顯示的狀態(tài)。SW_MAXIMIZE表示最大化,SW_HIDE表示隱藏等等。
2. MFC方式:
如果是MFC程序,可以使用 CWnd類的 ShowWindow( ?int nCmdShow ) 方法,狀態(tài)參數(shù)與API一致。
狀態(tài)參數(shù)還可以取以下數(shù)值(詳情也可參考MSDN):
SW_HIDE ? Hides this window and passes activation to another?
window.
SW_MINIMIZE ? Minimizes the window and activates the top-level window?
in the system's list.
SW_RESTORE ? Activates and displays the window. If the window is?
minimized or maximized, Windows restores it to its original size and?
position.
SW_SHOW ? Activates the window and displays it in its current size and?
position.
SW_SHOWMAXIMIZED ? Activates the window and displays it as a maximized?
window.
SW_SHOWMINIMIZED ? Activates the window and displays it as an?
icon.
SW_SHOWMINNOACTIVE ? Displays the window as an icon. The window that?
is currently active remains active.
SW_SHOWNA ? Displays the window in its current state. The window that?
is currently active remains active.
SW_SHOWNOACTIVATE ? Displays the window in its most recent size and?
position. The window that is currently active remains active.
SW_SHOWNORMAL ? Activates and displays the window. If the window is?
minimized or maximized, Windows restores it to its original size and?
position.
資源視圖,選中你的對(duì)話框,在修改外觀的Title Bar為False,這一步是去掉對(duì)話框的標(biāo)題欄以及關(guān)閉按鈕;然后進(jìn)入類視圖,選中要執(zhí)行最大化的對(duì)話框類,為其重載OnInitDialog函數(shù),在該函數(shù)中增加語句ShowWindow(SW_MAXIMIZE);(要保證在return語句之前)。如果這個(gè)對(duì)話框是用mfc向?qū)Ы⒌闹鲗?duì)話框,那么可能OnInitDialog函數(shù)已被重載,只需要在源代碼中的該函數(shù)中增加這一語句即可。
========
VC++深入詳解(5):MFC對(duì)話框(一)
http://blog.csdn.net/thefutureisour/article/details/8072873對(duì)話框可以分為兩大類:模態(tài)對(duì)話框和非模態(tài)對(duì)話框。模態(tài)對(duì)話框是指,當(dāng)其顯示時(shí),程序會(huì)暫停執(zhí)行,直到關(guān)閉這個(gè)對(duì)話框之后,才能繼續(xù)執(zhí)行程序中的其他任務(wù)。非模態(tài)對(duì)話框是指,當(dāng)對(duì)話框顯示時(shí),允許轉(zhuǎn)而執(zhí)行程序中的其他任務(wù),而可以不理會(huì)這個(gè)對(duì)話框。
對(duì)話框也是一種資源,可以在資源視圖中新建一個(gè)對(duì)話框來實(shí)現(xiàn)。新建的對(duì)話框已經(jīng)包含了2個(gè)按鈕,確定和取消。
在MFC中,對(duì)資源的操作都是通過一個(gè)與資源相關(guān)的類來完成的。與話框通相關(guān)的是CDialog類。當(dāng)我們使用類向?qū)r(shí),編譯器自動(dòng)檢測(cè)出我們添加了一個(gè)資源,提示我們是否需要為他創(chuàng)建一個(gè)類,然后編譯器會(huì)自動(dòng)將我們的資源,以及基類選擇好,我們只需要填寫類名就可以了,我們起名為CTestDlg。編譯器會(huì)自動(dòng)的幫我們填寫對(duì)應(yīng)的源文件和頭文件名,如果我們的類名很長,那么文件名也很長,可以改變。
此時(shí),編譯器為這個(gè)類編寫了兩個(gè)函數(shù):1.構(gòu)造函數(shù)2.DoDataExchange,用來完成數(shù)據(jù)的交換和校驗(yàn)。
下面我們希望在程序中顯示這個(gè)對(duì)話框,最簡單的做法:增加一個(gè)菜單項(xiàng),點(diǎn)擊菜單顯示對(duì)話框。
我們我們?cè)诓藛沃刑砑右粋€(gè)菜單項(xiàng),然后在VIEW類中為其添加消息響應(yīng)函數(shù):建立一個(gè)CTestDlg對(duì)象,調(diào)用DoModal函數(shù)來實(shí)現(xiàn)模態(tài)對(duì)話框:
void CCH_7_DialogView::OnDialog() { // TODO: Add your command handler code here CTestDlg dlg; dlg.DoModal(); }
注意,我們還得自己包含#include "TestDlg.h",因?yàn)檫@句代碼類向?qū)Р]有幫我們添加。
非模態(tài)對(duì)話框使用的是Create 創(chuàng)建的,注意,創(chuàng)建完成后必須調(diào)用ShowWindow函數(shù)來顯示對(duì)話框。
CTestDlg dlg; dlg.Create(IDD_DIALOG1,this); dlg.ShowWindow(SW_SHOW)
可是程序編譯后依然沒有顯示,這是為什么呢?因?yàn)檫@里的dlg是一個(gè)局部變量,程序執(zhí)行完以后,就析構(gòu)了。那為什么前面的模態(tài)對(duì)話框就可以呢?因?yàn)槟B(tài)對(duì)話框創(chuàng)建之后,程序就停在了這里,所以他的生命周期并沒有結(jié)束。那么怎么解決呢?
1.把這個(gè)對(duì)話框變量定義為局部變量。
2.定義一個(gè)指針,指向堆上的數(shù)據(jù):
CTestDlg *pDlg = new CTestDlg; pDlg->Create(IDD_DIALOG1,this); pDlg->ShowWindow(SW_SHOW);
雖然這樣做可以實(shí)現(xiàn)功能,但是并不好,因?yàn)閜Dlg會(huì)在程序結(jié)束時(shí)被釋放,所以我們以后就拿不到這個(gè)指針了,自然也就無法釋放它,會(huì)造成內(nèi)存泄露。這個(gè)問題可以通過將指針定義為類的成員變量來解決。
還有一點(diǎn)區(qū)別在于:對(duì)于模態(tài)對(duì)話框,點(diǎn)擊“確定”后,對(duì)話框是被“銷毀了”;而對(duì)于非模態(tài)對(duì)話框,則是“隱藏了”,你需要重寫虛函數(shù)OnOK,并在其中調(diào)用DestroyWindow ,基類的OnOK只是調(diào)用了EndDialog來隱藏對(duì)話框。
下面實(shí)現(xiàn)一個(gè)功能:單擊對(duì)話框的按鈕時(shí),在對(duì)話框中動(dòng)態(tài)的創(chuàng)建一個(gè)新的按鈕。
這里為了方便,使用模態(tài)對(duì)話框。我們回到資源視圖,打開原來的對(duì)話框,從工具箱中托一個(gè)按鈕到對(duì)話框上,修改的它的ID為IDC_BTN_ADD,名字為Add。然后右鍵點(diǎn)擊它,選擇類向?qū)?#xff0c;然后為其添加消息響應(yīng)函數(shù)OnBtnAdd:
void CTestDlg::OnBtnAdd() { // TODO: Add your control notification handler code here m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123); }
我們發(fā)現(xiàn),程序運(yùn)行時(shí),當(dāng)我們點(diǎn)擊Add按鈕,的確會(huì)顯示一個(gè)新的按鈕,但是我們?cè)俅吸c(diǎn)擊,程序就會(huì)錯(cuò)誤,這是因?yàn)?#xff0c;當(dāng)點(diǎn)擊時(shí),會(huì)調(diào)用OnBtnAdd,這個(gè)函數(shù)調(diào)用Create函數(shù)創(chuàng)建了一個(gè)按鈕;但是如果你又點(diǎn)擊一次,那么還會(huì)調(diào)用Create函數(shù)將按鈕與m_btn關(guān)聯(lián),可是m_btn已經(jīng)和第一次創(chuàng)建的按鈕相關(guān)聯(lián)了,所以會(huì)出錯(cuò)。為此,我們可以增加一個(gè)成員變量m_bIsCreate來記錄窗口是否已經(jīng)創(chuàng)建,如果創(chuàng)建,那么就會(huì)銷毀窗口,而在下一次點(diǎn)擊時(shí),又能創(chuàng)建了:
void CTestDlg::OnBtnAdd() { // TODO: Add your control notification handler code here if(m_bIsCreate == FALSE) { m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123); m_bIsCreate = TRUE; } else { m_btn.DestroyWindow(); m_bIsCreate = FALSE; } }
實(shí)際上,有一種更為直接的方法解決這個(gè)問題:CWnd有一個(gè)成員變量m_hWnd指向窗口句柄,我們可以利用這個(gè)句柄是否為空來判斷:
if(!m_btn.m_hWnd) { m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123); } else { m_btn.DestroyWindow(); }
下面我們我們看看控件的訪問:
我們給對(duì)話框上添加3個(gè)靜態(tài)文本框沒把他們改名為Number1,Number2,Number3;再添加3個(gè)編輯框。我們可以通過Layout菜單提供的功能來將它們對(duì)其。
首先我們實(shí)現(xiàn)一個(gè)簡單的功能:當(dāng)點(diǎn)擊Number1以后,將它的顯示變?yōu)椤皵?shù)字1”:
大的思路肯定是對(duì)這個(gè)控件響應(yīng)BN_CLICKED消息。可是我們發(fā)現(xiàn),這個(gè)控件的ID是IDC_STATIC,但是卻在類向?qū)е懈菊也灰娺@個(gè)ID,原因是因?yàn)檫@個(gè)所有的靜態(tài)文本框都是這個(gè)ID。實(shí)際上,這個(gè)控件一般是用來當(dāng)做標(biāo)簽用的,并不是用來響應(yīng)消息的。但是如果我們非要讓它響應(yīng)消息,也是可以的,但是需要改變它的標(biāo)簽,我們改為IDC_NUMBER1,然后為其添加消息響應(yīng)函數(shù):
首先,按鈕也是一個(gè)窗口,我們先要獲得這個(gè)靜態(tài)文本框,然后再獲得它上面的文本。然后把文本重新設(shè)置一下:
void CTestDlg::OnNumber1() { // TODO: Add your control notification handler code here CString str; if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str == "Number1") { GetDlgItem(IDC_NUMBER1)->SetWindowText("數(shù)值1"); } else { GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1"); } }
但是程序運(yùn)行以后并沒有反應(yīng),原因是因?yàn)殪o態(tài)文本控件在默認(rèn)狀態(tài)下,是不接收通告消息的:我們得在這個(gè)控件的屬性->樣式中,把通知選上,就行了。可見,為了讓靜態(tài)文本框響應(yīng)消息,需要兩個(gè)特殊的步驟:1.改變它的ID。2.在它的樣式中,選擇通知消息。
下面實(shí)現(xiàn)一個(gè)稍微復(fù)雜一點(diǎn)的功能:在兩個(gè)編輯框中輸入數(shù)字,然后點(diǎn)擊Add按鈕,在第三個(gè)編輯框中顯示結(jié)果。
實(shí)現(xiàn)的方法有很多種,我們一種一種介紹:
第1種:
void CTestDlg::OnBtnAdd() { // TODO: Add your control notification handler code here int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; GetDlgItem(IDC_EDIT1)->GetWindowText(ch1,10); GetDlgItem(IDC_EDIT2)->GetWindowText(ch2,10); num1 = atoi(ch1); num2 = atoi(ch2); num3 = num1 + num2; itoa(num3,ch3,10); GetDlgItem(IDC_EDIT3)->SetWindowText(ch3); }
這種方法思路清晰:定義的3個(gè)字符串和3個(gè)int。將編輯框中的字符串獲取出來以后轉(zhuǎn)化為int,然后做加法,做完以后轉(zhuǎn)化回去,然后顯示在編輯框上。
第二種:
int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; GetDlgItemText(IDC_EDIT1,ch1,10); GetDlgItemText(IDC_EDIT2,ch2,10); num1 = atoi(ch1); num2 = atoi(ch2); num3 = num1 + num2; itoa(num3,ch3,10); SetDlgItemText(IDC_EDIT3,ch3);
其實(shí)跟第一種差不多,但是通過GetDlgItemText和SetDlgItemText完成了第一種中需要兩步才能完成工作。
第三種:
使用GetDlgItemInt 函數(shù),這個(gè)函數(shù)直接通過控件ID獲取空間的文本,并把它轉(zhuǎn)化為int類型,然后使用SetDlgItemInt函數(shù):
int num1,num2,num3; num1 = GetDlgItemInt(IDC_EDIT1); num2 = GetDlgItemInt(IDC_EDIT2); num3 = num1 + num2; SetDlgItemInt(IDC_EDIT3,num3);
第四種:
將編輯框分對(duì)話框類的三個(gè)成員變量相關(guān),然后通過成員變量來檢索和設(shè)置編輯框的文本。
首先,先要為這三個(gè)編輯框關(guān)聯(lián)3個(gè)成員變量:在類視圖下的建立向?qū)ь愔?#xff0c;選擇CTestDlg類,依次選擇
IDC_EDIT1、IDC_EDIT2、IDC_EDIT3,為它們添加int型的變量m_num1、m_num2、m_num3。我們發(fā)現(xiàn)classWizzard為我們添加3處代碼:
在頭文件中,注釋宏之間:
// Dialog Data //{{AFX_DATA(CTestDlg) enum { IDD = IDD_DIALOG1 }; int m_num1; int m_num2; int m_num3; //}}AFX_DATA
??
源文件的構(gòu)造函數(shù)中:
[cpp] view plain copy
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/) ?
? ? : CDialog(CTestDlg::IDD, pParent) ?
{ ?
? ? //{{AFX_DATA_INIT(CTestDlg) ?
? ? m_num1 = 0; ?
? ? m_num2 = 0; ?
? ? m_num3 = 0; ?
? ? //}}AFX_DATA_INIT ?
} ?
在源文件的DoDataExchange中:
[cpp] view plain copy
void CTestDlg::DoDataExchange(CDataExchange* pDX) ?
{ ?
? ? CDialog::DoDataExchange(pDX); ?
? ? //{{AFX_DATA_MAP(CTestDlg) ?
? ? DDX_Text(pDX, IDC_EDIT1, m_num1); ?
? ? DDX_Text(pDX, IDC_EDIT2, m_num2); ?
? ? DDX_Text(pDX, IDC_EDIT3, m_num3); ?
? ? //}}AFX_DATA_MAP ?
} ?
其中DDX_Text函數(shù)完成數(shù)據(jù)轉(zhuǎn)化的功能。
我們發(fā)現(xiàn),程序運(yùn)行時(shí),編輯框里的值被自動(dòng)的設(shè)為0了。這個(gè)映射關(guān)系時(shí)通過DoDataExchange函數(shù)來實(shí)現(xiàn)的。如果這么方便,我們?cè)贠nBtnAdd函數(shù)中添加一句代碼就夠了:
[cpp] view plain copy
void CTestDlg::OnBtnAdd() ??
{ ?
? ? m_num3 = m_num1 + m_num2; ?
} ?
可是編譯后發(fā)現(xiàn)運(yùn)行時(shí)不能顯示正確的結(jié)果,這是為什么呢?通過單步調(diào)試,我們可以發(fā)現(xiàn):不論我們的輸入是多少,執(zhí)行到m_num3 = m_num1 + m_num2時(shí),m_num1 和 m_num2的值總是為0!看來我們有必要仔細(xì)看看DoDataExchange函數(shù),通過MSDN,我們可以看出,這個(gè)函數(shù)不是直接調(diào)用的,而是通過UpdateData 函數(shù)調(diào)用的。而UpdateData 函數(shù)有一個(gè)參數(shù):當(dāng)他為true時(shí)(默認(rèn)值),是從對(duì)話框獲取數(shù)據(jù),當(dāng)他為false時(shí),向?qū)υ捒驅(qū)憯?shù)據(jù)。于是我們只要改為下面的代碼就行了:
[cpp] view plain copy
UpdateData(); ?
m_num3 = m_num1 + m_num2; ?
UpdateData(FALSE); ?
假設(shè)我們向帶畫框輸入一個(gè)字符,那么點(diǎn)擊Add的時(shí)候,它會(huì)提示你請(qǐng)輸入一個(gè)整數(shù);甚至,在類向?qū)е?#xff0c;你可以設(shè)置整數(shù)的范圍。如果越界也會(huì)提示錯(cuò)誤。
第五種方式:
將編輯框與控件變量相關(guān)聯(lián)。我們這里選擇的是CEdit類型。有了這些成員變量,我們就不需要第一種方法中的GetDlgItem(IDC_EDIT1)步驟了,直接用這些變量來調(diào)用GetWindowText或者SetWindowText就行了。
[cpp] view plain copy
int num1,num2,num3; ?
char ch1[10],ch2[10],ch3[10]; ?
m_edit1.GetWindowText(ch1,10); ?
m_edit2.GetWindowText(ch2,10); ?
??
num1 = atoi(ch1); ?
num2 = atoi(ch2); ?
num3 = num1 + num2; ?
itoa(num3,ch3,10); ?
??
m_edit3.SetWindowText(ch3); ?
第六種方式:
通過消息。通過向編輯框發(fā)送指定的消息(獲取文本W(wǎng)M_GETTEXT、設(shè)置文本W(wǎng)M_SETTEXT),來實(shí)現(xiàn):
[cpp] view plain copy
int num1,num2,num3; ?
char ch1[10],ch2[10],ch3[10]; ?
::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10, ?
? ? (LPARAM)ch1); ?
::SendMessage(m_edit2.m_hWnd,WM_GETTEXT,10, ?
? ? (LPARAM)ch2); ?
num1 = atoi(ch1); ?
num2 = atoi(ch2); ?
num3 = num1 + num2; ?
itoa(num3,ch3,10); ?
m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3); ?
注意:
1.SendMessage是SDK下的函數(shù),所以調(diào)用前需要加上::.
2.發(fā)送WM_GETTEXT消息時(shí),wParam指明最大字節(jié)數(shù),lParam填字符串的地址,但是需要強(qiáng)制類型轉(zhuǎn)化。
3.發(fā)送WM_SETTEXT消息時(shí),wParam不使用,填為0,lParam填字符串的地址,但是需要強(qiáng)制類型轉(zhuǎn)化。
第七種方式:
直接給對(duì)畫框的子控件發(fā)送消息:
[cpp] view plain copy
int num1,num2,num3; ?
char ch1[10],ch2[10],ch3[10]; ?
??
SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10, (LPARAM)ch1); ?
SendDlgItemMessage(IDC_EDIT2,WM_GETTEXT,10, (LPARAM)ch2); ?
num1 = atoi(ch1); ?
num2 = atoi(ch2); ?
num3 = num1 + num2; ?
itoa(num3,ch3,10); ?
SendDlgItemMessage(IDC_EDIT3,WM_SETTEXT,0, ?(LPARAM)ch3); ?
使用成員函數(shù),就省去了獲取編輯框的工作。
如果想獲取編輯框中的一部分文本,可以通過發(fā)送EM_SETSEL消息來獲得,其中wParam表示起始位置,lParam表示結(jié)束位置。但是如果你想獲取一部分文本,那么你的焦點(diǎn)必須設(shè)在這個(gè)文本框上:
[cpp] view plain copy
SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,2); ?
m_edit3.SetFocus(); ?
總結(jié)起來,7中方法中:1、4、5比較常用。
下面我們看另外一個(gè)例子:對(duì)話框伸縮功能的實(shí)現(xiàn)。
這個(gè)功能其實(shí)也很常見,比如windowsXP下的畫圖中的顏色菜單中的編輯顏色,點(diǎn)擊規(guī)定自定義顏色時(shí),這個(gè)對(duì)話框就被擴(kuò)充起來了。通常對(duì)于一些用戶不太需要的功能,可以把它們放在隱藏的區(qū)域內(nèi),這樣能讓用戶考慮主要的問題。
我們考慮如何設(shè)計(jì)這個(gè)問題:首先肯定是有一個(gè)按鈕(名字為“收縮”),點(diǎn)擊一下以后之后,對(duì)話框收縮一部分,按鈕的名字改為“擴(kuò)張”。我們先搞定點(diǎn)擊之后名字轉(zhuǎn)化的問題:
[cpp] view plain copy
void CTestDlg::OnButton1() ??
{ ?
? ? // TODO: Add your control notification handler code here ?
? ? CString str; ?
? ? if(GetDlgItemText(IDC_BUTTON1,str), str == "收縮") ?
? ? { ?
? ? ? ? SetDlgItemText(IDC_BUTTON1,"擴(kuò)張"); ?
? ? } ?
? ? else ?
? ? { ?
? ? ? ? SetDlgItemText(IDC_BUTTON1,"收縮"); ?
? ? } ?
} ?
接下來的才是重頭戲,這種對(duì)話框分割的秘密在于:在原來的對(duì)話框上添加了一個(gè)看不見的,比較細(xì)的圖像控件(一般是矩形),通過這個(gè)矩形確定點(diǎn)擊收縮、擴(kuò)張之后,對(duì)話框的位置。
我們先將這個(gè)圖像控件改名為IDC_SEPERATOR,然后將它的樣式改為下陷。
[cpp] view plain copy
static CRect rectLarge; ?
static CRect rectSmall; ?
if(rectLarge.IsRectNull()) ?
{ ?
??
? ? CRect rectSeparator; ?
? ? GetWindowRect(&rectLarge); ?
? ? GetDlgItem(IDC_SEPARATOR)->GetWindowRect(&rectSeparator); ?
??
? ? rectSmall.left = rectLarge.left; ?
? ? rectSmall.top = rectLarge.top; ?
? ? rectSmall.right = rectLarge.right; ?
? ? rectSmall.bottom = rectSeparator.bottom; ?
} ?
??
if(str == "收縮") ?
{ ?
? ? SetWindowPos(NULL,0,0,rectSmall.Width(),rectSmall.Height(), ?
? ? ? ? SWP_NOMOVE | SWP_NOZORDER ); ?
} ?
else ?
{ ?
? ? SetWindowPos(NULL,0,0,rectLarge.Width(),rectLarge.Height(), ?
? ? ? ? SWP_NOMOVE | SWP_NOZORDER ); ? ? ? ? ?
} ?
在處理函數(shù)中,我們定義了3個(gè)矩形,rectLarge是對(duì)話框的原始尺寸,rectSmall是點(diǎn)擊收縮以后對(duì)話框的尺寸,而rectSeparator則是我們添加的一條細(xì)線的尺寸。rectSmall的left、top、right都等于rectLarge,只是把它的button改為rectSeparator的button即可。
獲取了窗口的大小,我們只需要使用SetWindowPos重新設(shè)置窗口的位置,大小就行了。
我們的程序有一點(diǎn)小瑕疵,當(dāng)輸入一個(gè)數(shù)字以后,按一下回車結(jié)果程序就窗口就關(guān)閉了,我們希望按下回車后能轉(zhuǎn)到第二編輯框繼續(xù)輸入。這該怎么辦呢?
首先解決第一個(gè)問題,為什么按一下回車就關(guān)閉了。我們看一下確定按鈕的屬性,在style里面看到,它是默認(rèn)選中的。所以如果我們按了回車,就會(huì)由確定鍵的消息響應(yīng)函數(shù)來處理。雖然我們沒有寫,但是基類中OnOK函數(shù)卻寫了,作用就是關(guān)閉對(duì)話框。
所以,如果我們希望實(shí)現(xiàn)自己的功能,那么得在派生類中重寫OK的消息響應(yīng)函數(shù)。我們?yōu)槠涮砑禹憫?yīng)函數(shù)時(shí),類向?qū)?huì)默認(rèn)的幫我們添加函數(shù),調(diào)用基類的成分:
[cpp] view plain copy
void CTestDlg::OnOK() ??
{ ?
? ? // TODO: Add extra validation here ?
? ? ??
? ? CDialog::OnOK(); ?
} ?
如果我們把它注釋起來,點(diǎn)擊ok就不會(huì)關(guān)閉窗口了。
那么如何實(shí)現(xiàn)回車以后把輸入焦點(diǎn)轉(zhuǎn)移到第二個(gè)編輯框中呢?
有兩種大的思路:1.讓編輯框控件生成一個(gè)相關(guān)聯(lián)的類,然后利用這個(gè)類來出來鍵盤消息;2.修改編輯框控件的窗口過程函數(shù),在這個(gè)函數(shù)中判斷,如果輸入回車,則移動(dòng)到下一個(gè)編輯框。
我們采用第二種思路。首先,改變窗口的消息處理函數(shù)的代碼應(yīng)該放在哪里?肯定不能放在create下面,因?yàn)榇藭r(shí)對(duì)話框還沒有創(chuàng)建完成呢。實(shí)際上,當(dāng)對(duì)話框及其子控件創(chuàng)建完成,顯示之前會(huì)發(fā)送消息:WM_INITDIALOG,我們?yōu)镃TestDlg添加這個(gè)消息的響應(yīng)函數(shù)。
[cpp] view plain copy
WNDPROC prevProc;//聲明先前的消息響應(yīng)函數(shù) ?
??
//新的消息處理函數(shù) ?
LRESULT CALLBACK NewEditProc( ?
? HWND hwnd, ? ? ?// handle to window ?
? UINT uMsg, ? ? ?// message identifier ?
? WPARAM wParam, ?// first message parameter ?
? LPARAM lParam ? // second message parameter ?
) ?
{ ?
? ? if(uMsg == WM_CHAR && wParam == 0x0d) ?
? ? { ?
? ? ? ? ::SetFocus(GetNextWindow(hwnd,GW_HWNDNEXT)); ?
? ? ? ? return 1; ?
? ? } ?
? ? else ?
? ? { ?
? ? ? ? return prevProc(hwnd,uMsg,wParam,lParam); ?
? ? } ?
} ?
其實(shí)這個(gè)函數(shù)并不復(fù)雜,如果消息是回車,那么把焦點(diǎn)設(shè)置為下一個(gè)窗口。如果不是,則調(diào)用原來的消息處理函數(shù)來處理。原來的處理函數(shù)是哪里來的呢?
[cpp] view plain copy
BOOL CTestDlg::OnInitDialog() ??
{ ?
? ? CDialog::OnInitDialog(); ?
? ? ??
? ? // TODO: Add extra initialization here ?
? ? prevProc = (WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd, ?
? ? ? ? GWL_WNDPROC,(LONG)NewEditProc); ?
? ? return TRUE; ?// return TRUE unless you set the focus to a control ?
? ? ? ? ? ? ? ? ? // EXCEPTION: OCX Property Pages should return FALSE ?
} ?
SetWindowLong函數(shù)的返回值就是了!
唯一需要注意的是得給編輯框選上多行選項(xiàng)。因?yàn)闆]有這個(gè)選項(xiàng),編輯框就只能接受一行消息,所以就不能接受回車鍵了。
我們也注意到,我們只是為第一個(gè)編輯框?qū)懥舜a,所以第二個(gè)編輯框下按回車是不起作用的。下面介紹另一種獲得窗口句柄的方法:GetWindow它返回與指定窗口有關(guān)系的窗口,所以也可以這樣寫:
[cpp] view plain copy
::SetFocus(::GetWindow(hwnd,GW_HWNDNEXT)); ?
最后介紹一種獲得獲得窗口句柄的方法:GetNextDlgTabItem。這個(gè)函數(shù)返回一個(gè)指定控件前面后者后面的一個(gè)具有WS_TABSTOP風(fēng)格的控件。那么什么是WS_TABSTOP風(fēng)格呢?對(duì)于按鈕的屬性,都有制表站這一項(xiàng),如果選上了,就有這個(gè)風(fēng)格,如果沒選,就沒有。
[cpp] view plain copy
::SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE)); ?
說了這么多,其實(shí)這些方法都很麻煩:你得為每個(gè)控件寫一推代碼,有沒有簡單的方法呢?
很簡單,我們把響應(yīng)回車鍵的默認(rèn)函數(shù)改了就行了:
[cpp] view plain copy
void CTestDlg::OnOK() ??
{ ?
? ? // TODO: Add extra validation here ?
? ? GetFocus()->GetNextWindow()->SetFocus(); ?
// ?CDialog::OnOK(); ?
} ?
獲取當(dāng)前焦點(diǎn),獲取這個(gè)焦點(diǎn)的下個(gè)窗口,將焦點(diǎn)設(shè)置在這個(gè)窗口,一目了然。
但這個(gè)程序是有問題的:當(dāng)你多輸入幾次回車以后,就崩潰了,因?yàn)樽詈笠粋€(gè)窗口調(diào)用GetNextWindow()時(shí),會(huì)得到一個(gè)空指針,對(duì)它進(jìn)行SetFocus();就會(huì)出錯(cuò)。為了解決這個(gè)問題,可以使用GetNextDlgTabItem來代替。這個(gè)函數(shù)的作用是按照順序查找具有tabstop屬性的控件。在layout菜單的taborder下,可以看到他們的順序。
[cpp] view plain copy
void CTestDlg::OnOK() ??
{ ?
? ? // TODO: Add extra validation here ?
? ? GetNextDlgTabItem(GetFocus())->GetNextWindow()->SetFocus(); ?
// ?CDialog::OnOK(); ?
} ?
最后再看看默認(rèn)按鈕:對(duì)于這個(gè)對(duì)話框,默認(rèn)按鈕時(shí)確定,但是可以通過修改屬性來讓別的按鈕響應(yīng)。
========
VC++:對(duì)話框
http://www.cnblogs.com/huan7550/archive/2013/03/21/2973104.html《VC++深入詳解:第七章》 孫鑫
?
在MFC中,對(duì)資源的操作通常都是通過一個(gè)與資源相關(guān)的類來完成的。
DoDataExchange:主要用來完成對(duì)話框數(shù)據(jù)的交換和校驗(yàn)。
CWnd對(duì)象都有一個(gè)成員變量m_hWnd,用來保存與窗口對(duì)象相關(guān)聯(lián)的窗口句柄,如果窗口對(duì)象沒有與任何一個(gè)窗口相關(guān)聯(lián),此句柄為NULL。
atoi——將char[]轉(zhuǎn)換為int,用法:num1 = atoi(ch1);
itoa——將數(shù)值轉(zhuǎn)換為文本,用法:itoa(num3,ch3,10);
CWnd類還提供了一個(gè)成員函數(shù):GetDlgItemText,這個(gè)函數(shù)將返回對(duì)話框中指定ID的控件上的文本,即組合了GetDlgItem和GetWindowText兩個(gè)函數(shù)的功能;同樣對(duì)應(yīng)的也有SetDlgItemText。
CWnd類還有另一對(duì)成員函數(shù):GetDlgItemInt和SetDlgItemInt。GetDlgItemInt函數(shù)返回指定控件的文本,并將其轉(zhuǎn)換為一個(gè)整形數(shù)值。
?
在DoDataExchange函數(shù)內(nèi)部實(shí)現(xiàn)了對(duì)話框控件與類成員變量的關(guān)聯(lián)。MFC提供了多種以DDX_為前綴的函數(shù),這些函數(shù)分別用于不同控件的數(shù)據(jù)交換;MFC也提供了多個(gè)以DDV_為前綴的數(shù)據(jù)校驗(yàn)函數(shù)。
DoDataExchange
DDX——Dialog Data Exchange,對(duì)話框數(shù)據(jù)交換;
DDV——Dialog Data Validation,對(duì)話框數(shù)據(jù)校驗(yàn)。
Windows程序都是基于消息的系統(tǒng),因此,為了獲取或設(shè)置窗口的文本,只要知道獲取或設(shè)置窗口文本的消息,就可以通過SendMessage來發(fā)送這條消息,從而獲取或設(shè)置窗口的文本。
Windows系統(tǒng)中,獲取窗口文本的消息是WM_GETEXT,發(fā)送該消息后,系統(tǒng)將把指定窗口的文本復(fù)制到調(diào)用者提供的一個(gè)緩存中;設(shè)置窗口文本的消息是WM_SETTEXT。
WM_GETTEXT消息與WM_SETTEXT消息的附加信息
WM_GETTEXT
wParam指定將復(fù)制的字符數(shù)
lParam就是調(diào)用者提供的用來保存窗口文本的緩存地址
WM_SETTEXT
wParam沒使用,值為0
lParam參數(shù)指定了用來設(shè)置窗口文本的字符串地址
SendMessage消息說明
Platform SDK和CWnd類都提供SendMessage函數(shù);所以,如果想要調(diào)用Platform SDK的函數(shù),前面必須加雙冒號(hào)(::)
每個(gè)窗口類對(duì)象都有一個(gè)保存了窗口句柄的成員m_hWnd。獲取編輯框控件窗口句柄的方法:可以通過調(diào)用GetDlgItem函數(shù)獲取編輯框窗口對(duì)應(yīng)的C++對(duì)象指針,然后通過該指針獲得窗口句柄。
對(duì)話框的創(chuàng)建
模態(tài)對(duì)話框的創(chuàng)建
DoModal
代碼
CTestDlg dlg;
dlg.DoModal();
非模態(tài)對(duì)話框的創(chuàng)建
Create
注意:創(chuàng)建非模態(tài)對(duì)話框時(shí),不能把對(duì)話框?qū)ο蠖x為局部對(duì)象。
將對(duì)話框?qū)ο蠖x為視類的成員變量
將它定義為指針,在堆上分配內(nèi)存(在堆上分配的內(nèi)存與程序的整個(gè)生命周期是一致的)
錯(cuò)誤代碼(dlg是局部對(duì)象、無法顯示)
CTestDlg dlg;
dlg.Create(IDD_DIALOG1,this);
dlg.ShowWindow(SW_SHOW);
正確代碼
CTestDlg *pDlg = new CTestDlg;
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);
解決內(nèi)存丟失問題
方法1:將這個(gè)指針變量定義為視類的成員變量,然后在視類的析構(gòu)函數(shù)中調(diào)用delete;
方法2:在CTestDlg中重載PostNcDestory虛函數(shù),釋放this指針?biāo)赶虻膬?nèi)存
void CTestDlg::PostNcDestroy()
{
? ? delete this;
? ? CDialog::PostNcDestroy();
}
動(dòng)態(tài)創(chuàng)建按鈕
想法:為對(duì)話框創(chuàng)建一個(gè)CButton類的對(duì)象m_btn?
做法
先為CTestDlg類添加一個(gè)私有的CButton成員變量m_btn
之后,m_btn.Create("New",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123);
解決多次創(chuàng)建按鈕非法操作問題
為CTestDlg類增加一個(gè)私有的BOOL成員變量m_bIsCreated(標(biāo)識(shí)是否已經(jīng)創(chuàng)建過按鈕窗口了),之后調(diào)用Create函數(shù)時(shí)對(duì)變量進(jìn)行判斷
在OnBtnAdd函數(shù)中將m_bIsCreated設(shè)置為static的(static BOOL bIsCreated = FALSE;)
直接判斷與窗口關(guān)聯(lián)的句柄m_hWnd,代碼
void CTestDlg::OnBtnAdd()
{
? ? if(!m_btn.m_hWnd)
? ? {
? ? ? ? ?m_btn.Create( "New",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123);
? ? }
? ? else
? ? {
? ? ? ? m_btn.DestroyWindow();
? ? ?}
}
靜態(tài)文本控件
操作靜態(tài)文本控件
獲取靜態(tài)文本框控件
函數(shù):CWnd *GetDlgItem(int nID) const;
獲取靜態(tài)文本控件的文本
函數(shù):GetWindowText
設(shè)置靜態(tài)文本控件的文本
函數(shù):SetWindowText
代碼
CString str;
if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str), str == "Number1:")
?{
? ? GetDlgItem(IDC_NUMBER1)->SetWindowText("數(shù)值1:");
? }
else
? {
? ? GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1:");
? }
注意:靜態(tài)文本控件在默認(rèn)狀態(tài)下不發(fā)送通告消息,需要在其屬性對(duì)話框中選擇Notify選項(xiàng)
編輯框控件
求和:第三個(gè)編輯框顯示前兩個(gè)編輯框的和。
七種實(shí)現(xiàn)方式(即:七種訪問對(duì)話框控件的方式)
用CWnd的GetDlgItem和GetWindowText/SetWindowText、itoa/atoi
用GetDlgItemText/SetDlgItemText、itoa/atoi
用GetDlgItemInt/SetDlgItemInt
將三個(gè)編輯框分別與對(duì)話框類的三個(gè)成員變量相關(guān)聯(lián),然后通過這些成員變量來檢索和設(shè)置編輯框的文本
添加值變量:int型,Value
使用UpdateData(FALSE)更新顯示;UpdataData(TRUE)更新數(shù)據(jù)。
說明:添加值變量之后程序的變化
類的頭文件,兩個(gè)AFX_DATA注釋宏之間增加了成員變量int m_num1;
CTestDlg類構(gòu)造函數(shù)中增加了初始化代碼m_num1 = 0;
CTestDlg類的DoDataExchange函數(shù)內(nèi)部調(diào)用了三個(gè)DDX_Text函數(shù),類似DDX_Text(pDX,IDC_EDIT1,m_num1);
這種方式可以設(shè)置輸入框數(shù)值范圍。設(shè)置范圍后程序變化:DoDataExchange函數(shù)中增加了下述代碼:
DDV_MinMaxInt(pDX,m_num1,0,100);
DDV_MinMaxInt(pDX,m_num2,0,100);
將編輯框控件關(guān)聯(lián)控件變量
添加控件變量,Control, CEdit
添加控件變量之后程序的變化
類的頭文件,連個(gè)AFX_DATA注釋宏之間增加了成員變量CEdit m_edit1;
DoDataExchange函數(shù)中增加了三個(gè)DDX_Control函數(shù),分別將一個(gè)對(duì)話框控件與一個(gè)控件變量相關(guān)聯(lián),類似DDX_Control(pDX,IDC_EDIT1,m_edit1);
說明:這些控件變量代表的就是控件本身,并且CEdit類派生于CWnd類,因此,可以利用這些控件變量調(diào)用GetWindowText和SetWindowText來獲取和設(shè)置編輯框的文本。
通過SendMessage發(fā)送消息,從而獲取或設(shè)置窗口的文本
::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
::SengMessage(m_edit2.m_hWnd,WM_GETTEXT,10,(LPARAM)ch2);
m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3);
通過直接給對(duì)話框的子控件發(fā)送消息來完成對(duì)控件的訪問
函數(shù):SendDlgItemMessage,相當(dāng)于GetDlgItem和SendMessage的結(jié)合
SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1);
SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch2);
SendDlgItemMessage(IDC_EDIT3,WM_SETTEXT,0,(LPARAM)ch3);
7種方式總結(jié):
獲取和設(shè)置編輯框復(fù)選的內(nèi)容
前提:如果要對(duì)編輯框控件的內(nèi)容進(jìn)行復(fù)選,當(dāng)前焦點(diǎn)應(yīng)該位于這個(gè)編輯框上
可以利用EM_GETSEL消息獲得編輯框復(fù)選的內(nèi)容
這個(gè)消息的wParam參數(shù)將接收復(fù)選內(nèi)容的開始位置
lParam參數(shù)將接收復(fù)選內(nèi)容的結(jié)束位置
這兩個(gè)參數(shù)都要求是指向DWORD類型的指針
EM_SETSEL用來設(shè)置編輯框控件中的復(fù)選內(nèi)容
例如:SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,3);
注意:為了看到第三個(gè)編輯框上的復(fù)選內(nèi)容,需要把焦點(diǎn)轉(zhuǎn)移到這個(gè)編輯框上,使用m_edit3.SetFocus();
注意2:如果這個(gè)消息wParam參數(shù)值為0,lParam參數(shù)值為-1,則所有內(nèi)容將被復(fù)選
說明:EM_開頭的消息是指編輯框控件消息(Edit Control Message)
對(duì)話框伸縮功能
幾個(gè)重要函數(shù)及用法示例
rectLarge.IsRectNull(); ?//矩形幾個(gè)坐標(biāo)值是否都為零
rectLarge.IsRectEmpty(); ?//矩形區(qū)域是否為空
GetWindowRect(&rectLarge); ?//獲得當(dāng)前窗口矩形
SetWindowPos(NULL,smallRect.left,smallRect.top,smallRect.Width(),smallRect.Height(),SWP_NOMOVE | SWP_NOZORDER); ?//設(shè)置窗口的位置和大小
實(shí)現(xiàn)
定義兩個(gè)矩形變量:rectLarge/rectSmall(靜態(tài)變量)
判斷對(duì)話框的原始尺寸是否已經(jīng)賦值
IsRectEmpty——檢測(cè)矩形區(qū)域是否為空,若寬度和高度為0或負(fù)值,說明矩形為空
IsRectNull——如果矩形左上角和右下角四個(gè)坐標(biāo)值都是0,返回非零值;否則返回0
有了原始和切除后的矩形尺寸,利用SetWindowsPos函數(shù)來設(shè)置對(duì)話框的收縮和擴(kuò)展之后的大小
SetWindowPos函數(shù)
作用:設(shè)置窗口的位置和大小
pWndInsertAfter:標(biāo)識(shí)一個(gè)CWnd對(duì)象,該對(duì)象是在以Z次序排序的窗口中位于當(dāng)前窗口前面的那個(gè)窗口對(duì)象;該對(duì)象可以是指向某個(gè)CWnd對(duì)象的指針,也可以是下面幾個(gè)取值之一:
wndBottom
wndTop
wndTopMost
wndNoTopMost
x,y:左上角xy坐標(biāo)
cx,xy:窗口寬度和高度
nFlags:設(shè)定窗口的尺寸和定位
代碼示例
輸入焦點(diǎn)的傳遞
主要內(nèi)容
SetWindowLong():改變指定窗口的屬性
OnInitDialog():替換之前的WM_INITDIALOG消息,在對(duì)話框及其子控件創(chuàng)建完成、顯示之前執(zhí)行
自定義窗口過程捕獲回車字符
if (uMsg == WM_CHAR && wParam == 0x0d)
設(shè)置焦點(diǎn)至下一個(gè)控件
::SetFocus(GetNextWindow(hwnd, GW_HWNDNEXT));
SetFocus用來設(shè)置控件的焦點(diǎn),參數(shù)為控件的句柄(HWND)
實(shí)現(xiàn)的功能
在測(cè)試對(duì)話框中第一個(gè)編輯框中按下回車鍵后,輸入焦點(diǎn)被轉(zhuǎn)移到第二個(gè)編輯框。
思路:可以通過捕獲鍵盤按鍵消息,然后在此消息響應(yīng)函數(shù)中把輸入焦點(diǎn)移動(dòng)到下一個(gè)編輯框控件來實(shí)現(xiàn)。
兩種實(shí)現(xiàn)方式
為編輯框控件生成一個(gè)相關(guān)聯(lián)的類,然后利用這個(gè)類來捕獲鍵盤按鍵消息。
修改編輯框控件的窗口過程函數(shù),即自己編寫一個(gè)編輯框控件的窗口過程函數(shù),然后替換MFC提供的默認(rèn)的編輯框控件窗口過程函數(shù)。
SetWindowLong函數(shù)
改變指定窗口的屬性。當(dāng)一個(gè)窗口已經(jīng)創(chuàng)建之后,修改該窗口已制定的過程函數(shù)可以通過此函數(shù)來實(shí)現(xiàn)。
參數(shù)取值及含義
hWnd:指定想要改變其屬性的窗口句柄
nIndex:指定要設(shè)置的偏移地址
取值:
GWL_EXSIYLE:設(shè)置一個(gè)新的擴(kuò)展窗口風(fēng)格
GWL_STYLE:設(shè)置一個(gè)新的窗口風(fēng)格
GWL_WNDPROC:設(shè)置一個(gè)新的窗口過程
GWL_HINSTANCE:設(shè)置一個(gè)新的應(yīng)用程序?qū)嵗浔?
GWL_ID:為窗口設(shè)置一個(gè)新的標(biāo)識(shí)
GWL_USERDATA:設(shè)置與窗口相關(guān)的32位值
如果hWnd參數(shù)指定的是一個(gè)對(duì)話框,還可以取值:
DWL_DLGPROC:設(shè)置新的對(duì)話框過程
DWL_MSGRESULT:設(shè)置在對(duì)話框過程中處理的消息返回值
DWL_USER:設(shè)置新的額外信息,該信息僅為應(yīng)用程序所有,例如句柄或指針
dwNewLong:指定設(shè)置的新值
修改時(shí)機(jī),即在哪里調(diào)用SetWindowLong函數(shù)?
WM_CREATE消息的響應(yīng)函數(shù)-不合適:在響應(yīng)WM_CREATE消息時(shí),對(duì)話框的子控件還未創(chuàng)建完成,只有在此消息處理完畢之后,對(duì)話框及其子控件才全部創(chuàng)建完成。
WM_INITDIALOG消息:當(dāng)對(duì)話框及其上的子控件創(chuàng)建完成,將要顯示之前,會(huì)發(fā)送此消息——在VS2005中,此消息被OnInitDialog函數(shù)替代。
所以:將SetWindowLong函數(shù)寫到OnInitDialog函數(shù)中
獲得窗口句柄的三種方式
1 GetNextWindow函數(shù)
SDK函數(shù)用法:GetNextWindow(hwnd, GW_HWNDNEXT);
CWnd的此函數(shù):GetFocus()->GetNextWindow();
2 GetWindow函數(shù)
功能:該函數(shù)返回與指定窗口有特定關(guān)系的窗口句柄
SDK原型:HWND GetWindow(HWND hWnd,UINT uCmd);
第一個(gè)參數(shù)是開始查找的窗口的句柄
第二個(gè)參數(shù)指定hWnd參數(shù)指定的窗口與要獲得的窗口之間的關(guān)系,取值
GW_HWNDNEXT,則查找在Z次序中位于指定窗口下面的窗口
GW_HWNDPREV,則查找在Z次序中位于指定窗口前面的窗口
CWnd的此函數(shù):GetWindow(GW_HWNDNEXT);
3 GetNextDlgTabItem函數(shù)
該函數(shù)返回指定控件前面或后面的一個(gè)具有WS_TABSTOP風(fēng)格的控件。
WS_TABSTOP風(fēng)格:屬性下選中“Tab stop”選項(xiàng)
原型:HWND GetNextDlgTabItem(HWND hDlg, HWND hCtl, BOOL bPrevious);
參數(shù)含義:
hDlg:指定將被搜索的對(duì)話框
HCtl:指定用來作為搜索開始點(diǎn)的控件
hPrevious:指定搜索的方向——TRUE:上一個(gè);FALSE:下一個(gè)。
另一種簡單的實(shí)現(xiàn)方式
在IDOK的響應(yīng)函數(shù)中添加代碼:
GetNextDlgTabItem(GetFocus())->SetFocus();
========
怎么實(shí)現(xiàn)VC登錄對(duì)話框
MFC中如何添加登錄對(duì)話框呢。VC做的管理系統(tǒng),通常需要加一個(gè)登錄界面,以便確認(rèn)身份。今天和網(wǎng)友們說說,如何在VC中設(shè)計(jì)登錄對(duì)話框 ^_^
怎么實(shí)現(xiàn)VC登錄對(duì)話框
方法/步驟
1
新建MFC應(yīng)用程序,程序類型選擇基于對(duì)話框,其他默認(rèn)即可
2
在資源視圖下面的Dialog對(duì)話框文件夾上右擊,選擇插入 Dialog
3
在新建的對(duì)話框上右擊,選擇添加類
4
在類向?qū)?duì)話框中,輸入類名,確定
這樣就建立了類與對(duì)話框之間的關(guān)聯(lián),可以用這個(gè)類來創(chuàng)建這個(gè)對(duì)話框?qū)ο罅?
5
雙擊打開工程的Welcome.cpp文件,找到 InitInstance() 函數(shù)
6
在 Welcome.cpp 上面加上頭文件 #include "Login.h"
7
在 CWelcomeApp::InitInstance() 函數(shù)中添加修改如下代碼
8
運(yùn)程程序,首先顯示了登錄對(duì)話框啦 #^_^#
END
可以將登錄后的對(duì)話框在 Login.cpp 的按鈕響應(yīng)函數(shù)中顯示 #^_^#
======== 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的VC++对话框学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# - Marshal 学习总结
- 下一篇: VC++ 解析JSON 学习总结