1. 程式人生 > >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, "宋體"
BEGIN
  GROUPBOX      "學生資訊",IDC_STATIC,10,8,290,200
  GROUPBOX      "",IDC_STATIC,25,55,205,120
  PUSHBUTTON    "最前(&F)",IDC_BUTTON_FIRST,30,30,35,15
  PUSHBUTTON    "向前(&B)",IDC_BUTTON_PRE,82,30,35,15
  PUSHBUTTON    "向後(&N)",IDC_BUTTON_NEXT,134,30,35,15
  PUSHBUTTON    "最後(&L)",IDC_BUTTON_LAST,186,30,35,15
  PUSHBUTTON    "查詢(&Q)",IDC_BUTTON_QUERY,246,70,40,15
  PUSHBUTTON    "增加(&A)",IDC_BUTTON_ADD,246,96,40,15
  PUSHBUTTON    "修改(&M)",IDC_BUTTON_MODIFY,246,122,40,15
  PUSHBUTTON    "刪除(&D)",IDC_BUTTON_DELETE,246,148,40,15
  PUSHBUTTON    "確定(&O)",IDC_BUTTON_OK,58,183,40,15
  PUSHBUTTON    "取消(&C)",IDC_BUTTON_CANCEL,150,183,40,15
  LTEXT          "學號:",IDC_STATIC,52,75,25,8
  LTEXT          "姓名:",IDC_STATIC,52,100,25,8
  LTEXT          "性別:",IDC_STATIC,52,125,25,8
  LTEXT          "入學時間:",IDC_STATIC,44,151,41,8
  EDITTEXT      IDC_EDIT_SID,91,72,95,15,ES_AUTOHSCROLL
  EDITTEXT      IDC_EDIT_SNAME,91,96,95,15,ES_AUTOHSCROLL
  EDITTEXT      IDC_EDIT_SSEX,91,120,95,15,ES_AUTOHSCROLL
  CONTROL        "DateTimePicker1",IDC_DATETIMEPICKER_SCOMEDATE,
                  "SysDateTimePick32",DTS_RIGHTALIGN | WS_TABSTOP,91,144,
                  95,15
  GROUPBOX      "",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_ICONWARNINGVS2010/MFC程式設計入門之十六(對話方塊:訊息對話方塊)
MB_ICONASTERISK
MB_ICONINFORMATIONVS2010/MFC程式設計入門之十六(對話方塊:訊息對話方塊)
MB_ICONQUESTIONVS2010/MFC程式設計入門之十六(對話方塊:訊息對話方塊)
MB_ICONHAND
MB_ICONSTOP

MB_ICONERRORVS2010/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 的按鈕響應函式中顯示 #^_^#
========