VC++对话框学习总结
生活随笔
收集整理的這篇文章主要介紹了
VC++对话框学习总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
VC++中如何復制對話框資源
http://www.cnblogs.com/Yogurshine/p/3710566.html法1:
在你的工程中添加另一個工程的rc文件,這時資源視圖中就會出現兩個rc,從后加的rc中拷貝資源到你自己工程的rc中就可以了。
?
法2:vc中如何拷貝一個工程的對話框資源到另一個工程中?
?
這是一個很專業也很有用的問題。其實VC的設計者早就為我們考慮了這個問題。
在VC6環境下,選擇Class視圖,選中想要克隆的對話框所對應的類,例如CAboutDlg,點擊鼠標右鍵,選擇Add to gallery。在新工程中選擇Project菜單,選擇Add Component and ActivX,你會看到多了一個文件夾(與上一個工程同名),進入該文件夾,選擇*.ogx。選擇Insert,你會發現原來的對話框被加入到新的工程中了!
?
補充:
.net下更簡單,將原來的工程加到新的工程中,直接將對話框拷貝過去就行了!
?
法3:
VC++中如何復制對話框資源
第一步:用記事本打開原工程的.rc文件,找到想復制的對話框的信息,如下所示
?
IDD_UGMS_DIALOGDIALOGEX 0, 0, 320, 230 STYLE WS_CHILD | WS_VISIBLE EXSTYLE WS_EX_APPWINDOW FONT 9, "宋體" BEGINGROUPBOX "學生信息",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 "學號:",IDC_STATIC,52,75,25,8LTEXT "姓名:",IDC_STATIC,52,100,25,8LTEXT "性別:",IDC_STATIC,52,125,25,8LTEXT "入學時間:",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
?上面代碼中綠色背景代表的是要復制的對話框資源的ID,此段代碼也就是.rc文件中記錄的此對話框的信息,黃色背景中間的代碼就是
?相應對話框中添加的控件信息,只需將相應代碼拷到新工程的相應.rc文件相應的ID對話框資源的BEGIN 和END之間即可;
?
第二步:打開原工程的FileView視圖下的Header Files 下的resource.h文件,將其中相應ID的信息復制到新工程的resource.h中即可;
?例如:
?
//復制的資源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重復,可以更改一下即可!
??
法4:
?今天碰到模塊移植問題了,自己做的對話框類(繼承于CDialog)要移植到目標工程中.在網上搜了幾個帖子發現都說的很生澀.問了我們的技術總監之后總算解決這個問題了.
?? ? ? 問題:把一個MFC SDI工程中的一個對話框資源和類拷貝到另一個MFC SDI中.
?? ? ? 1.在VC6中打開老的工程,在工作區Resource標簽頁中選中Dialog文件夾下的資源文件(就是雙擊后會出現編輯窗口界面的那個東西),按Ctrl+C(Edit->Copy也一樣).
?? ? ? 2.關閉當前工程,注意不要關閉VC6,打開目標工程(File->OpenWorkspace),然后選中工作區的Resource標簽頁中的Dialog文件夾,然后按Ctrl+V(Edit->Paste也一樣).好了,對話框拷貝過來了.
?? ? ? 3.將對話框類的cpp h文件拷貝到目標工程中(不詳細說了,往當前工程添加文件)
?? ? ? 4.打開復制過來的類cpp和h文件,刪除沒用的頭文件(老工程相關的),并且在.h文件中添加文件包含
?
#include "Resource.h"
第四步很關鍵,老工程中根本就沒有這個文件包含,可是移植之后必須手動添加頭文件包含.因為這個問題卡了10幾分鐘...
當你用資源ID時(通常資源編輯器編輯的資源ID都在resource.h中),如果沒有包含CWinApp的派生類所在的頭文件就會出錯,你看一下它的頭文件里,包含了這個文件, 而向導生成的類,它的實現文件都有包含CWinApp派生類所在的頭文件的
然后在新工程中就可以使用這個類了,主要就是這個類的對話框中的資源復制頭一次遇到.不敢獨享,拿出來跟新手們一起學習.
?
于是,當有已經創建好的對話框資源要添加到新工程中時:
(1)右鍵單擊新工程所在的解決方案添加“現有項目”把舊工程添加進來;
(2)切換到“資源視圖”并在舊工程對話框資源上右鍵“復制”;
(3)在新工程對話框資源上右鍵“粘貼”;
(4)現在就可以為新對話框添加類了,順便把舊工程的響應函數拷貝過來;
(5)切換回“解決方案資源管理器”,右鍵舊工程“移除”。
========
VS2010/MFC編程入門之十六(對話框:消息對話框)
http://www.jizhuomi.com/software/171.html
? ? ? ?前面幾節雞啄米講了屬性頁對話框,我們可以根據所講內容方便的建立自己的屬性頁對話框。本節講解Windows系統中最常用最簡單的一類對話框--消息對話框。
? ? ? ?我們在使用Windows系統的過程中經常會見到消息對話框,提示我們有異常發生或提出詢問等。因為在軟件開發中經常用到消息對話框,所以MFC提供了兩個函數可以直接生成指定風格的消息對話框,而不需要我們在每次使用的時候都要去創建對話框資源和生成對話框類等。這兩個函數就是CWnd類的成員函數MessageBox()和全局函數AfxMessageBox()。
? ? ? ?一.CWnd::MessageBox()函數和AfxMessageBox()函數的用法
? ? ? ?下面雞啄米就分別講解兩個函數的用法。
? ? ? ?1.CWnd::MessageBox()函數
? ? ? ?CWnd::MessageBox()的函數原型如下:
? ? ? ?int MessageBox(
? ? ? ? ? ?LPCTSTR lpszText,
? ? ? ? ? ?LPCTSTR lpszCaption = NULL,
? ? ? ? ? ?UINT nType = MB_OK?
? ? ? ?);
? ? ? ?參數說明:
? ? ? ?lpszText:需要顯示的消息字符串。
? ? ? ?lpszCaption:消息對話框的標題字符串。默認值為NULL。取值為NULL時使用默認標題。
? ? ? ?nType:消息對話框的風格和屬性。默認為MB_OK風格,即只有“確定”按鈕。
? ? ? ?nType的取值可以是下面兩個表中任取一個值,也可以是各取一個值的任意組合。即可以指定一個對話框類型,也可以指定一個對話框圖標,還可以兩者都設定。
nType 取值 參數說明
MB_ABORTRETRY 有“終止”、“重試”和“忽略”按鈕
MB_OK 有“確定”按鈕
MB_OKCANCEL 有“確定”和“取消”按鈕
MB_RETRYCANCEL 有“重試”和“取消”按鈕
MB_YESNO 有“是”和“否”按鈕
MB_YESNOCANCEL 有“是”、“否”和“取消”按鈕
對話框類型表
nType 取值 顯示圖標
MB_ICONEXCLAMTION
MB_ICONWARNING VS2010/MFC編程入門之十六(對話框:消息對話框)
MB_ICONASTERISK
MB_ICONINFORMATION VS2010/MFC編程入門之十六(對話框:消息對話框)
MB_ICONQUESTION VS2010/MFC編程入門之十六(對話框:消息對話框)
MB_ICONHAND
MB_ICONSTOP
MB_ICONERROR VS2010/MFC編程入門之十六(對話框:消息對話框)
? ? ? ?如果想要設置nType的值為類型和圖標的組合,可以像這樣取值:MB_OKCANCEL | MB_ICONQUESTION。按位取或就可以了。
VS2010/MFC編程入門之十六(對話框:消息對話框)
? ? ? ?2.AfxMessageBox()函數
? ? ? ?AfxMessageBox()的函數原型為:
? ? ? ?int AfxMessageBox(
? ? ? ? ? ?LPCTSTR lpszText,
? ? ? ? ? ?UINT nType = MB_OK,
? ? ? ? ? ?UINT nIDHelp = 0?
? ? ? ?);
? ? ? ?參數說明:
? ? ? ?lpszText:同CWnd::MessageBox()函數
? ? ? ?nType:CWnd::MessageBox()函數
? ? ? ?nIDHelp:此消息的幫助的上下文ID。默認值為0,取0時表示要使用應用程序的默認幫助上下文。
? ? ? ?二.CWnd::MessageBox()和AfxMessageBox()的返回值
? ? ? 我們在調用了上面兩個函數后,都可以彈出模態消息對話框。消息對話框關閉后,我們也都可以得到它們的返回值。兩者的返回值就是用戶在消息對話框上單擊的按鈕的ID,可以是以下值:
? ? ? IDABORT:單擊“終止”按鈕。
? ? ? IDCANCEL:單擊“取消”按鈕。
? ? ? IDIGNORE:單擊“忽略”按鈕。
? ? ? IDNO:單擊“否”按鈕。
? ? ? IDOK:單擊“確定”按鈕。
? ? ? IDRETRY:單擊“重試”按鈕。
? ? ? IDYES:單擊“是”按鈕。
? ? ? 三.應用舉例
? ? ?我們還是拿前面加法計算器的程序做例子。
? ? ? ?大家是否記得,在模態對話框及其彈出過程中我們修改了CAdditionDlg::OnBnClickedAddButton()函數,在點了“計算”按鈕以后先彈出了一個模態對話框,詢問用戶是否確定要進行加法計算,并通過模態對話框DoModal函數的返回值判斷用戶選擇了“確定”還是“取消”。這些功能很明顯消息對話框完全能夠實現,雞啄米就使用消息對話框來替代原來的模態對話框。
? ? ? ?在非模態對話框的創建及顯示中,雞啄米注釋了模態對話框的相關代碼,加入了非模態對話框的創建和顯示代碼,我們在加入消息對話框之前將非模態對話框的代碼也注釋或刪除掉,確保此函數中不再生成原來的模態對話框或非模態對話框。
? ? ? ?修改后的CAdditionDlg::OnBnClickedAddButton()函數如下:
C++代碼
void CAdditionDlg::OnBnClickedAddButton() { // TODO: Add your control notification handler code here INT_PTR nRes; // 顯示消息對話框 nRes = MessageBox(_T("您確定要進行加法計算嗎?"), _T("加法計算器"), MB_OKCANCEL | MB_ICONQUESTION); // 判斷消息對話框返回值。如果為IDCANCEL就return,否則繼續向下執行 if (IDCANCEL == nRes) return; // 將各控件中的數據保存到相應的變量 UpdateData(TRUE); // 將被加數和加數的加和賦值給m_editSum m_editSum = m_editSummand + m_editAddend; // 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值 UpdateData(FALSE); // 設置屬性對話框為向導對話框 //sheet.SetWizardMode(); }
? ? ? ? 編譯運行,在運行結果對話框上點“計算”按鈕彈出以下消息對話框:
VS2010/MFC編程入門之十六(對話框:消息對話框)
? ? ? ?大家也可以將MessageBox函數換為AfxMessageBox()函數,同時參數進行相應修改,運行下看看效果。
========
VC++創建對話框(轉) ?
http://blog.163.com/yx_xie2007/blog/static/102464253201002904022375/?對話框有模式對話框和非模式對話框兩種。以下用基于Visual Studio 2008的MFC為例,創建一個程序。
?首先創建一個MFC單文檔應用程序,名稱為DialogTest.打開資源視圖——Menu——IDR_MAINFRAME,在菜單欄中添加一個標簽“對話框測試”,ID設置為IDM_DIALOGTEST,在屬性中把popup屬性設置為false.添加兩個子菜單,分別是“模式對話框”,ID為IDM_DIALOG1;“非模式對話框”,ID為IDM_DIALOG2.
?之后在資源視圖中的Dialog中添加一個對話框,并添加一個靜態文本控件,Caption設置為“模式對話框”,ID為IDD_DIALOG1,雙擊對話框空白處,在彈出的MFC類向導中命名類名為CTestDlg1,基類選擇CDialog,之后完成。同理添加另一個對話框,ID為IDD_DIALOG2。在MFC類向導中的類名設置為CTestDlg2,基類同樣為CDialog.
?完成資源的添加后,我們就要完善代碼。再次打開IDR_MAINFRAME,右鍵選擇“模式對話框”,在彈出的右鍵菜單中選擇“添加事件處理程序”,在彈出的對話框中的“消息類型”選擇COMMAND,類列表選擇CDialogTestView,點擊“添加編輯”,輸入代碼:
?CTestDlg1 dlg;
?dlg.DoModal();
此時,模式對話框創建完畢。相對于模式對話框來說,非模式對話框的創建相對復雜一點。同樣是再次打開IDR_MAINFRAME,右鍵選擇“非模式對話框”,在彈出的右鍵菜單中選擇“添加事件處理程序”,在彈出的對話框中的“消息類型”選擇COMMAND,類列表選擇CDialogTestView,點擊“添加編輯”,輸入代碼:
?CTestDlg2 *pDlg=new CTestDlg2;
?pDlg->Create(IDD_DIALOG2,this);
?pDlg->ShowWindow(SW_SHOW);
在這里,我將對話框對象定義為指針,在堆上分配內存,使其與程序的生命周期一致。之后用Creat()函數創建一個對話框,并用ShowWindow()將其顯示出來。這里用到了指針指向操作符,只因為定義的對話框對象為指針類型,且調用了其成員函數(有C++基礎的都會明白這一點吧......)。由于pDlg這個指針變量為局部對象,當其生命周期結束后,其保存的內存地址就會丟失。所以我們應該在CTestDlg2類中重載PostNcDestroy這個虛函數來釋放this指針指向的內存。只需在這個函數中添加一句:
?delete this;
?CDialog::PostNcDestroy();
因為我們在程序中使用了CTestDlg1,CTestDlg2,CDialogTestView類并不清楚其數據類型。因此我們要在DialogTestView.cpp開始出添加:
#include "TestDlg1.h"
#include "TestDlg2.h"
編譯運行程序,結果如下所示:VC++創建對話框(轉)
========
VC++如何最大化對話框
一打開一個對話框程序,對話框就最大化,并且要求沒有標題欄,沒有右上角的關閉,最大化,最小化等按鈕,總之就是全屏顯示的對話框如何實現?
1. API方式:
可以通過 ShowWindow 函數改變窗口的顯示狀態。語法為:
BOOL ShowWindow( ? ? ? ? ?HWND hWnd,
int nCmdShow
);
hWnd 表示窗口句柄
nCmdShow 表示想要顯示的狀態。SW_MAXIMIZE表示最大化,SW_HIDE表示隱藏等等。
2. MFC方式:
如果是MFC程序,可以使用 CWnd類的 ShowWindow( ?int nCmdShow ) 方法,狀態參數與API一致。
狀態參數還可以取以下數值(詳情也可參考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.
資源視圖,選中你的對話框,在修改外觀的Title Bar為False,這一步是去掉對話框的標題欄以及關閉按鈕;然后進入類視圖,選中要執行最大化的對話框類,為其重載OnInitDialog函數,在該函數中增加語句ShowWindow(SW_MAXIMIZE);(要保證在return語句之前)。如果這個對話框是用mfc向導建立的主對話框,那么可能OnInitDialog函數已被重載,只需要在源代碼中的該函數中增加這一語句即可。
========
VC++深入詳解(5):MFC對話框(一)
http://blog.csdn.net/thefutureisour/article/details/8072873對話框可以分為兩大類:模態對話框和非模態對話框。模態對話框是指,當其顯示時,程序會暫停執行,直到關閉這個對話框之后,才能繼續執行程序中的其他任務。非模態對話框是指,當對話框顯示時,允許轉而執行程序中的其他任務,而可以不理會這個對話框。
對話框也是一種資源,可以在資源視圖中新建一個對話框來實現。新建的對話框已經包含了2個按鈕,確定和取消。
在MFC中,對資源的操作都是通過一個與資源相關的類來完成的。與話框通相關的是CDialog類。當我們使用類向導時,編譯器自動檢測出我們添加了一個資源,提示我們是否需要為他創建一個類,然后編譯器會自動將我們的資源,以及基類選擇好,我們只需要填寫類名就可以了,我們起名為CTestDlg。編譯器會自動的幫我們填寫對應的源文件和頭文件名,如果我們的類名很長,那么文件名也很長,可以改變。
此時,編譯器為這個類編寫了兩個函數:1.構造函數2.DoDataExchange,用來完成數據的交換和校驗。
下面我們希望在程序中顯示這個對話框,最簡單的做法:增加一個菜單項,點擊菜單顯示對話框。
我們我們在菜單中添加一個菜單項,然后在VIEW類中為其添加消息響應函數:建立一個CTestDlg對象,調用DoModal函數來實現模態對話框:
void CCH_7_DialogView::OnDialog() { // TODO: Add your command handler code here CTestDlg dlg; dlg.DoModal(); }
注意,我們還得自己包含#include "TestDlg.h",因為這句代碼類向導并沒有幫我們添加。
非模態對話框使用的是Create 創建的,注意,創建完成后必須調用ShowWindow函數來顯示對話框。
CTestDlg dlg; dlg.Create(IDD_DIALOG1,this); dlg.ShowWindow(SW_SHOW)
可是程序編譯后依然沒有顯示,這是為什么呢?因為這里的dlg是一個局部變量,程序執行完以后,就析構了。那為什么前面的模態對話框就可以呢?因為模態對話框創建之后,程序就停在了這里,所以他的生命周期并沒有結束。那么怎么解決呢?
1.把這個對話框變量定義為局部變量。
2.定義一個指針,指向堆上的數據:
CTestDlg *pDlg = new CTestDlg; pDlg->Create(IDD_DIALOG1,this); pDlg->ShowWindow(SW_SHOW);
雖然這樣做可以實現功能,但是并不好,因為pDlg會在程序結束時被釋放,所以我們以后就拿不到這個指針了,自然也就無法釋放它,會造成內存泄露。這個問題可以通過將指針定義為類的成員變量來解決。
還有一點區別在于:對于模態對話框,點擊“確定”后,對話框是被“銷毀了”;而對于非模態對話框,則是“隱藏了”,你需要重寫虛函數OnOK,并在其中調用DestroyWindow ,基類的OnOK只是調用了EndDialog來隱藏對話框。
下面實現一個功能:單擊對話框的按鈕時,在對話框中動態的創建一個新的按鈕。
這里為了方便,使用模態對話框。我們回到資源視圖,打開原來的對話框,從工具箱中托一個按鈕到對話框上,修改的它的ID為IDC_BTN_ADD,名字為Add。然后右鍵點擊它,選擇類向導,然后為其添加消息響應函數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); }
我們發現,程序運行時,當我們點擊Add按鈕,的確會顯示一個新的按鈕,但是我們再次點擊,程序就會錯誤,這是因為,當點擊時,會調用OnBtnAdd,這個函數調用Create函數創建了一個按鈕;但是如果你又點擊一次,那么還會調用Create函數將按鈕與m_btn關聯,可是m_btn已經和第一次創建的按鈕相關聯了,所以會出錯。為此,我們可以增加一個成員變量m_bIsCreate來記錄窗口是否已經創建,如果創建,那么就會銷毀窗口,而在下一次點擊時,又能創建了:
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; } }
實際上,有一種更為直接的方法解決這個問題:CWnd有一個成員變量m_hWnd指向窗口句柄,我們可以利用這個句柄是否為空來判斷:
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(); }
下面我們我們看看控件的訪問:
我們給對話框上添加3個靜態文本框沒把他們改名為Number1,Number2,Number3;再添加3個編輯框。我們可以通過Layout菜單提供的功能來將它們對其。
首先我們實現一個簡單的功能:當點擊Number1以后,將它的顯示變為“數字1”:
大的思路肯定是對這個控件響應BN_CLICKED消息。可是我們發現,這個控件的ID是IDC_STATIC,但是卻在類向導中根本找不見這個ID,原因是因為這個所有的靜態文本框都是這個ID。實際上,這個控件一般是用來當做標簽用的,并不是用來響應消息的。但是如果我們非要讓它響應消息,也是可以的,但是需要改變它的標簽,我們改為IDC_NUMBER1,然后為其添加消息響應函數:
首先,按鈕也是一個窗口,我們先要獲得這個靜態文本框,然后再獲得它上面的文本。然后把文本重新設置一下:
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("數值1"); } else { GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1"); } }
但是程序運行以后并沒有反應,原因是因為靜態文本控件在默認狀態下,是不接收通告消息的:我們得在這個控件的屬性->樣式中,把通知選上,就行了。可見,為了讓靜態文本框響應消息,需要兩個特殊的步驟:1.改變它的ID。2.在它的樣式中,選擇通知消息。
下面實現一個稍微復雜一點的功能:在兩個編輯框中輸入數字,然后點擊Add按鈕,在第三個編輯框中顯示結果。
實現的方法有很多種,我們一種一種介紹:
第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個字符串和3個int。將編輯框中的字符串獲取出來以后轉化為int,然后做加法,做完以后轉化回去,然后顯示在編輯框上。
第二種:
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);
其實跟第一種差不多,但是通過GetDlgItemText和SetDlgItemText完成了第一種中需要兩步才能完成工作。
第三種:
使用GetDlgItemInt 函數,這個函數直接通過控件ID獲取空間的文本,并把它轉化為int類型,然后使用SetDlgItemInt函數:
int num1,num2,num3; num1 = GetDlgItemInt(IDC_EDIT1); num2 = GetDlgItemInt(IDC_EDIT2); num3 = num1 + num2; SetDlgItemInt(IDC_EDIT3,num3);
第四種:
將編輯框分對話框類的三個成員變量相關,然后通過成員變量來檢索和設置編輯框的文本。
首先,先要為這三個編輯框關聯3個成員變量:在類視圖下的建立向導類中,選擇CTestDlg類,依次選擇
IDC_EDIT1、IDC_EDIT2、IDC_EDIT3,為它們添加int型的變量m_num1、m_num2、m_num3。我們發現classWizzard為我們添加3處代碼:
在頭文件中,注釋宏之間:
// Dialog Data //{{AFX_DATA(CTestDlg) enum { IDD = IDD_DIALOG1 }; int m_num1; int m_num2; int m_num3; //}}AFX_DATA
??
源文件的構造函數中:
[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函數完成數據轉化的功能。
我們發現,程序運行時,編輯框里的值被自動的設為0了。這個映射關系時通過DoDataExchange函數來實現的。如果這么方便,我們在OnBtnAdd函數中添加一句代碼就夠了:
[cpp] view plain copy
void CTestDlg::OnBtnAdd() ??
{ ?
? ? m_num3 = m_num1 + m_num2; ?
} ?
可是編譯后發現運行時不能顯示正確的結果,這是為什么呢?通過單步調試,我們可以發現:不論我們的輸入是多少,執行到m_num3 = m_num1 + m_num2時,m_num1 和 m_num2的值總是為0!看來我們有必要仔細看看DoDataExchange函數,通過MSDN,我們可以看出,這個函數不是直接調用的,而是通過UpdateData 函數調用的。而UpdateData 函數有一個參數:當他為true時(默認值),是從對話框獲取數據,當他為false時,向對話框寫數據。于是我們只要改為下面的代碼就行了:
[cpp] view plain copy
UpdateData(); ?
m_num3 = m_num1 + m_num2; ?
UpdateData(FALSE); ?
假設我們向帶畫框輸入一個字符,那么點擊Add的時候,它會提示你請輸入一個整數;甚至,在類向導中,你可以設置整數的范圍。如果越界也會提示錯誤。
第五種方式:
將編輯框與控件變量相關聯。我們這里選擇的是CEdit類型。有了這些成員變量,我們就不需要第一種方法中的GetDlgItem(IDC_EDIT1)步驟了,直接用這些變量來調用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); ?
第六種方式:
通過消息。通過向編輯框發送指定的消息(獲取文本WM_GETTEXT、設置文本WM_SETTEXT),來實現:
[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下的函數,所以調用前需要加上::.
2.發送WM_GETTEXT消息時,wParam指明最大字節數,lParam填字符串的地址,但是需要強制類型轉化。
3.發送WM_SETTEXT消息時,wParam不使用,填為0,lParam填字符串的地址,但是需要強制類型轉化。
第七種方式:
直接給對畫框的子控件發送消息:
[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); ?
使用成員函數,就省去了獲取編輯框的工作。
如果想獲取編輯框中的一部分文本,可以通過發送EM_SETSEL消息來獲得,其中wParam表示起始位置,lParam表示結束位置。但是如果你想獲取一部分文本,那么你的焦點必須設在這個文本框上:
[cpp] view plain copy
SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,2); ?
m_edit3.SetFocus(); ?
總結起來,7中方法中:1、4、5比較常用。
下面我們看另外一個例子:對話框伸縮功能的實現。
這個功能其實也很常見,比如windowsXP下的畫圖中的顏色菜單中的編輯顏色,點擊規定自定義顏色時,這個對話框就被擴充起來了。通常對于一些用戶不太需要的功能,可以把它們放在隱藏的區域內,這樣能讓用戶考慮主要的問題。
我們考慮如何設計這個問題:首先肯定是有一個按鈕(名字為“收縮”),點擊一下以后之后,對話框收縮一部分,按鈕的名字改為“擴張”。我們先搞定點擊之后名字轉化的問題:
[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,"擴張"); ?
? ? } ?
? ? else ?
? ? { ?
? ? ? ? SetDlgItemText(IDC_BUTTON1,"收縮"); ?
? ? } ?
} ?
接下來的才是重頭戲,這種對話框分割的秘密在于:在原來的對話框上添加了一個看不見的,比較細的圖像控件(一般是矩形),通過這個矩形確定點擊收縮、擴張之后,對話框的位置。
我們先將這個圖像控件改名為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 ); ? ? ? ? ?
} ?
在處理函數中,我們定義了3個矩形,rectLarge是對話框的原始尺寸,rectSmall是點擊收縮以后對話框的尺寸,而rectSeparator則是我們添加的一條細線的尺寸。rectSmall的left、top、right都等于rectLarge,只是把它的button改為rectSeparator的button即可。
獲取了窗口的大小,我們只需要使用SetWindowPos重新設置窗口的位置,大小就行了。
我們的程序有一點小瑕疵,當輸入一個數字以后,按一下回車結果程序就窗口就關閉了,我們希望按下回車后能轉到第二編輯框繼續輸入。這該怎么辦呢?
首先解決第一個問題,為什么按一下回車就關閉了。我們看一下確定按鈕的屬性,在style里面看到,它是默認選中的。所以如果我們按了回車,就會由確定鍵的消息響應函數來處理。雖然我們沒有寫,但是基類中OnOK函數卻寫了,作用就是關閉對話框。
所以,如果我們希望實現自己的功能,那么得在派生類中重寫OK的消息響應函數。我們為其添加響應函數時,類向導會默認的幫我們添加函數,調用基類的成分:
[cpp] view plain copy
void CTestDlg::OnOK() ??
{ ?
? ? // TODO: Add extra validation here ?
? ? ??
? ? CDialog::OnOK(); ?
} ?
如果我們把它注釋起來,點擊ok就不會關閉窗口了。
那么如何實現回車以后把輸入焦點轉移到第二個編輯框中呢?
有兩種大的思路:1.讓編輯框控件生成一個相關聯的類,然后利用這個類來出來鍵盤消息;2.修改編輯框控件的窗口過程函數,在這個函數中判斷,如果輸入回車,則移動到下一個編輯框。
我們采用第二種思路。首先,改變窗口的消息處理函數的代碼應該放在哪里?肯定不能放在create下面,因為此時對話框還沒有創建完成呢。實際上,當對話框及其子控件創建完成,顯示之前會發送消息:WM_INITDIALOG,我們為CTestDlg添加這個消息的響應函數。
[cpp] view plain copy
WNDPROC prevProc;//聲明先前的消息響應函數 ?
??
//新的消息處理函數 ?
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); ?
? ? } ?
} ?
其實這個函數并不復雜,如果消息是回車,那么把焦點設置為下一個窗口。如果不是,則調用原來的消息處理函數來處理。原來的處理函數是哪里來的呢?
[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函數的返回值就是了!
唯一需要注意的是得給編輯框選上多行選項。因為沒有這個選項,編輯框就只能接受一行消息,所以就不能接受回車鍵了。
我們也注意到,我們只是為第一個編輯框寫了代碼,所以第二個編輯框下按回車是不起作用的。下面介紹另一種獲得窗口句柄的方法:GetWindow它返回與指定窗口有關系的窗口,所以也可以這樣寫:
[cpp] view plain copy
::SetFocus(::GetWindow(hwnd,GW_HWNDNEXT)); ?
最后介紹一種獲得獲得窗口句柄的方法:GetNextDlgTabItem。這個函數返回一個指定控件前面后者后面的一個具有WS_TABSTOP風格的控件。那么什么是WS_TABSTOP風格呢?對于按鈕的屬性,都有制表站這一項,如果選上了,就有這個風格,如果沒選,就沒有。
[cpp] view plain copy
::SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE)); ?
說了這么多,其實這些方法都很麻煩:你得為每個控件寫一推代碼,有沒有簡單的方法呢?
很簡單,我們把響應回車鍵的默認函數改了就行了:
[cpp] view plain copy
void CTestDlg::OnOK() ??
{ ?
? ? // TODO: Add extra validation here ?
? ? GetFocus()->GetNextWindow()->SetFocus(); ?
// ?CDialog::OnOK(); ?
} ?
獲取當前焦點,獲取這個焦點的下個窗口,將焦點設置在這個窗口,一目了然。
但這個程序是有問題的:當你多輸入幾次回車以后,就崩潰了,因為最后一個窗口調用GetNextWindow()時,會得到一個空指針,對它進行SetFocus();就會出錯。為了解決這個問題,可以使用GetNextDlgTabItem來代替。這個函數的作用是按照順序查找具有tabstop屬性的控件。在layout菜單的taborder下,可以看到他們的順序。
[cpp] view plain copy
void CTestDlg::OnOK() ??
{ ?
? ? // TODO: Add extra validation here ?
? ? GetNextDlgTabItem(GetFocus())->GetNextWindow()->SetFocus(); ?
// ?CDialog::OnOK(); ?
} ?
最后再看看默認按鈕:對于這個對話框,默認按鈕時確定,但是可以通過修改屬性來讓別的按鈕響應。
========
VC++:對話框
http://www.cnblogs.com/huan7550/archive/2013/03/21/2973104.html《VC++深入詳解:第七章》 孫鑫
?
在MFC中,對資源的操作通常都是通過一個與資源相關的類來完成的。
DoDataExchange:主要用來完成對話框數據的交換和校驗。
CWnd對象都有一個成員變量m_hWnd,用來保存與窗口對象相關聯的窗口句柄,如果窗口對象沒有與任何一個窗口相關聯,此句柄為NULL。
atoi——將char[]轉換為int,用法:num1 = atoi(ch1);
itoa——將數值轉換為文本,用法:itoa(num3,ch3,10);
CWnd類還提供了一個成員函數:GetDlgItemText,這個函數將返回對話框中指定ID的控件上的文本,即組合了GetDlgItem和GetWindowText兩個函數的功能;同樣對應的也有SetDlgItemText。
CWnd類還有另一對成員函數:GetDlgItemInt和SetDlgItemInt。GetDlgItemInt函數返回指定控件的文本,并將其轉換為一個整形數值。
?
在DoDataExchange函數內部實現了對話框控件與類成員變量的關聯。MFC提供了多種以DDX_為前綴的函數,這些函數分別用于不同控件的數據交換;MFC也提供了多個以DDV_為前綴的數據校驗函數。
DoDataExchange
DDX——Dialog Data Exchange,對話框數據交換;
DDV——Dialog Data Validation,對話框數據校驗。
Windows程序都是基于消息的系統,因此,為了獲取或設置窗口的文本,只要知道獲取或設置窗口文本的消息,就可以通過SendMessage來發送這條消息,從而獲取或設置窗口的文本。
Windows系統中,獲取窗口文本的消息是WM_GETEXT,發送該消息后,系統將把指定窗口的文本復制到調用者提供的一個緩存中;設置窗口文本的消息是WM_SETTEXT。
WM_GETTEXT消息與WM_SETTEXT消息的附加信息
WM_GETTEXT
wParam指定將復制的字符數
lParam就是調用者提供的用來保存窗口文本的緩存地址
WM_SETTEXT
wParam沒使用,值為0
lParam參數指定了用來設置窗口文本的字符串地址
SendMessage消息說明
Platform SDK和CWnd類都提供SendMessage函數;所以,如果想要調用Platform SDK的函數,前面必須加雙冒號(::)
每個窗口類對象都有一個保存了窗口句柄的成員m_hWnd。獲取編輯框控件窗口句柄的方法:可以通過調用GetDlgItem函數獲取編輯框窗口對應的C++對象指針,然后通過該指針獲得窗口句柄。
對話框的創建
模態對話框的創建
DoModal
代碼
CTestDlg dlg;
dlg.DoModal();
非模態對話框的創建
Create
注意:創建非模態對話框時,不能把對話框對象定義為局部對象。
將對話框對象定義為視類的成員變量
將它定義為指針,在堆上分配內存(在堆上分配的內存與程序的整個生命周期是一致的)
錯誤代碼(dlg是局部對象、無法顯示)
CTestDlg dlg;
dlg.Create(IDD_DIALOG1,this);
dlg.ShowWindow(SW_SHOW);
正確代碼
CTestDlg *pDlg = new CTestDlg;
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);
解決內存丟失問題
方法1:將這個指針變量定義為視類的成員變量,然后在視類的析構函數中調用delete;
方法2:在CTestDlg中重載PostNcDestory虛函數,釋放this指針所指向的內存
void CTestDlg::PostNcDestroy()
{
? ? delete this;
? ? CDialog::PostNcDestroy();
}
動態創建按鈕
想法:為對話框創建一個CButton類的對象m_btn?
做法
先為CTestDlg類添加一個私有的CButton成員變量m_btn
之后,m_btn.Create("New",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123);
解決多次創建按鈕非法操作問題
為CTestDlg類增加一個私有的BOOL成員變量m_bIsCreated(標識是否已經創建過按鈕窗口了),之后調用Create函數時對變量進行判斷
在OnBtnAdd函數中將m_bIsCreated設置為static的(static BOOL bIsCreated = FALSE;)
直接判斷與窗口關聯的句柄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();
? ? ?}
}
靜態文本控件
操作靜態文本控件
獲取靜態文本框控件
函數:CWnd *GetDlgItem(int nID) const;
獲取靜態文本控件的文本
函數:GetWindowText
設置靜態文本控件的文本
函數:SetWindowText
代碼
CString str;
if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str), str == "Number1:")
?{
? ? GetDlgItem(IDC_NUMBER1)->SetWindowText("數值1:");
? }
else
? {
? ? GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1:");
? }
注意:靜態文本控件在默認狀態下不發送通告消息,需要在其屬性對話框中選擇Notify選項
編輯框控件
求和:第三個編輯框顯示前兩個編輯框的和。
七種實現方式(即:七種訪問對話框控件的方式)
用CWnd的GetDlgItem和GetWindowText/SetWindowText、itoa/atoi
用GetDlgItemText/SetDlgItemText、itoa/atoi
用GetDlgItemInt/SetDlgItemInt
將三個編輯框分別與對話框類的三個成員變量相關聯,然后通過這些成員變量來檢索和設置編輯框的文本
添加值變量:int型,Value
使用UpdateData(FALSE)更新顯示;UpdataData(TRUE)更新數據。
說明:添加值變量之后程序的變化
類的頭文件,兩個AFX_DATA注釋宏之間增加了成員變量int m_num1;
CTestDlg類構造函數中增加了初始化代碼m_num1 = 0;
CTestDlg類的DoDataExchange函數內部調用了三個DDX_Text函數,類似DDX_Text(pDX,IDC_EDIT1,m_num1);
這種方式可以設置輸入框數值范圍。設置范圍后程序變化:DoDataExchange函數中增加了下述代碼:
DDV_MinMaxInt(pDX,m_num1,0,100);
DDV_MinMaxInt(pDX,m_num2,0,100);
將編輯框控件關聯控件變量
添加控件變量,Control, CEdit
添加控件變量之后程序的變化
類的頭文件,連個AFX_DATA注釋宏之間增加了成員變量CEdit m_edit1;
DoDataExchange函數中增加了三個DDX_Control函數,分別將一個對話框控件與一個控件變量相關聯,類似DDX_Control(pDX,IDC_EDIT1,m_edit1);
說明:這些控件變量代表的就是控件本身,并且CEdit類派生于CWnd類,因此,可以利用這些控件變量調用GetWindowText和SetWindowText來獲取和設置編輯框的文本。
通過SendMessage發送消息,從而獲取或設置窗口的文本
::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);
通過直接給對話框的子控件發送消息來完成對控件的訪問
函數:SendDlgItemMessage,相當于GetDlgItem和SendMessage的結合
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種方式總結:
獲取和設置編輯框復選的內容
前提:如果要對編輯框控件的內容進行復選,當前焦點應該位于這個編輯框上
可以利用EM_GETSEL消息獲得編輯框復選的內容
這個消息的wParam參數將接收復選內容的開始位置
lParam參數將接收復選內容的結束位置
這兩個參數都要求是指向DWORD類型的指針
EM_SETSEL用來設置編輯框控件中的復選內容
例如:SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,3);
注意:為了看到第三個編輯框上的復選內容,需要把焦點轉移到這個編輯框上,使用m_edit3.SetFocus();
注意2:如果這個消息wParam參數值為0,lParam參數值為-1,則所有內容將被復選
說明:EM_開頭的消息是指編輯框控件消息(Edit Control Message)
對話框伸縮功能
幾個重要函數及用法示例
rectLarge.IsRectNull(); ?//矩形幾個坐標值是否都為零
rectLarge.IsRectEmpty(); ?//矩形區域是否為空
GetWindowRect(&rectLarge); ?//獲得當前窗口矩形
SetWindowPos(NULL,smallRect.left,smallRect.top,smallRect.Width(),smallRect.Height(),SWP_NOMOVE | SWP_NOZORDER); ?//設置窗口的位置和大小
實現
定義兩個矩形變量:rectLarge/rectSmall(靜態變量)
判斷對話框的原始尺寸是否已經賦值
IsRectEmpty——檢測矩形區域是否為空,若寬度和高度為0或負值,說明矩形為空
IsRectNull——如果矩形左上角和右下角四個坐標值都是0,返回非零值;否則返回0
有了原始和切除后的矩形尺寸,利用SetWindowsPos函數來設置對話框的收縮和擴展之后的大小
SetWindowPos函數
作用:設置窗口的位置和大小
pWndInsertAfter:標識一個CWnd對象,該對象是在以Z次序排序的窗口中位于當前窗口前面的那個窗口對象;該對象可以是指向某個CWnd對象的指針,也可以是下面幾個取值之一:
wndBottom
wndTop
wndTopMost
wndNoTopMost
x,y:左上角xy坐標
cx,xy:窗口寬度和高度
nFlags:設定窗口的尺寸和定位
代碼示例
輸入焦點的傳遞
主要內容
SetWindowLong():改變指定窗口的屬性
OnInitDialog():替換之前的WM_INITDIALOG消息,在對話框及其子控件創建完成、顯示之前執行
自定義窗口過程捕獲回車字符
if (uMsg == WM_CHAR && wParam == 0x0d)
設置焦點至下一個控件
::SetFocus(GetNextWindow(hwnd, GW_HWNDNEXT));
SetFocus用來設置控件的焦點,參數為控件的句柄(HWND)
實現的功能
在測試對話框中第一個編輯框中按下回車鍵后,輸入焦點被轉移到第二個編輯框。
思路:可以通過捕獲鍵盤按鍵消息,然后在此消息響應函數中把輸入焦點移動到下一個編輯框控件來實現。
兩種實現方式
為編輯框控件生成一個相關聯的類,然后利用這個類來捕獲鍵盤按鍵消息。
修改編輯框控件的窗口過程函數,即自己編寫一個編輯框控件的窗口過程函數,然后替換MFC提供的默認的編輯框控件窗口過程函數。
SetWindowLong函數
改變指定窗口的屬性。當一個窗口已經創建之后,修改該窗口已制定的過程函數可以通過此函數來實現。
參數取值及含義
hWnd:指定想要改變其屬性的窗口句柄
nIndex:指定要設置的偏移地址
取值:
GWL_EXSIYLE:設置一個新的擴展窗口風格
GWL_STYLE:設置一個新的窗口風格
GWL_WNDPROC:設置一個新的窗口過程
GWL_HINSTANCE:設置一個新的應用程序實例句柄
GWL_ID:為窗口設置一個新的標識
GWL_USERDATA:設置與窗口相關的32位值
如果hWnd參數指定的是一個對話框,還可以取值:
DWL_DLGPROC:設置新的對話框過程
DWL_MSGRESULT:設置在對話框過程中處理的消息返回值
DWL_USER:設置新的額外信息,該信息僅為應用程序所有,例如句柄或指針
dwNewLong:指定設置的新值
修改時機,即在哪里調用SetWindowLong函數?
WM_CREATE消息的響應函數-不合適:在響應WM_CREATE消息時,對話框的子控件還未創建完成,只有在此消息處理完畢之后,對話框及其子控件才全部創建完成。
WM_INITDIALOG消息:當對話框及其上的子控件創建完成,將要顯示之前,會發送此消息——在VS2005中,此消息被OnInitDialog函數替代。
所以:將SetWindowLong函數寫到OnInitDialog函數中
獲得窗口句柄的三種方式
1 GetNextWindow函數
SDK函數用法:GetNextWindow(hwnd, GW_HWNDNEXT);
CWnd的此函數:GetFocus()->GetNextWindow();
2 GetWindow函數
功能:該函數返回與指定窗口有特定關系的窗口句柄
SDK原型:HWND GetWindow(HWND hWnd,UINT uCmd);
第一個參數是開始查找的窗口的句柄
第二個參數指定hWnd參數指定的窗口與要獲得的窗口之間的關系,取值
GW_HWNDNEXT,則查找在Z次序中位于指定窗口下面的窗口
GW_HWNDPREV,則查找在Z次序中位于指定窗口前面的窗口
CWnd的此函數:GetWindow(GW_HWNDNEXT);
3 GetNextDlgTabItem函數
該函數返回指定控件前面或后面的一個具有WS_TABSTOP風格的控件。
WS_TABSTOP風格:屬性下選中“Tab stop”選項
原型:HWND GetNextDlgTabItem(HWND hDlg, HWND hCtl, BOOL bPrevious);
參數含義:
hDlg:指定將被搜索的對話框
HCtl:指定用來作為搜索開始點的控件
hPrevious:指定搜索的方向——TRUE:上一個;FALSE:下一個。
另一種簡單的實現方式
在IDOK的響應函數中添加代碼:
GetNextDlgTabItem(GetFocus())->SetFocus();
========
怎么實現VC登錄對話框
MFC中如何添加登錄對話框呢。VC做的管理系統,通常需要加一個登錄界面,以便確認身份。今天和網友們說說,如何在VC中設計登錄對話框 ^_^
怎么實現VC登錄對話框
方法/步驟
1
新建MFC應用程序,程序類型選擇基于對話框,其他默認即可
2
在資源視圖下面的Dialog對話框文件夾上右擊,選擇插入 Dialog
3
在新建的對話框上右擊,選擇添加類
4
在類向導對話框中,輸入類名,確定
這樣就建立了類與對話框之間的關聯,可以用這個類來創建這個對話框對象了
5
雙擊打開工程的Welcome.cpp文件,找到 InitInstance() 函數
6
在 Welcome.cpp 上面加上頭文件 #include "Login.h"
7
在 CWelcomeApp::InitInstance() 函數中添加修改如下代碼
8
運程程序,首先顯示了登錄對話框啦 #^_^#
END
可以將登錄后的對話框在 Login.cpp 的按鈕響應函數中顯示 #^_^#
======== 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的VC++对话框学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# - Marshal 学习总结
- 下一篇: s3c2440移植MQTT