1. 程式人生 > >總結VC6對話方塊控制元件訪問的七種方式

總結VC6對話方塊控制元件訪問的七種方式

一、GetDlgItem()->Get(Set)WindowText(ch3);
二、GetWindowText()/SetDlgItemText();
三、GetDlgItemInt()/SetDlgItemInt();
四、將控制元件和整形變數相關聯;
五、將控制元件和控制元件變數相關聯;
六、SendMessage();
七、SenDlgItemMessage(); 一、準備工作:
    (一)新建一個MFC AppWizard(exe)工程,名稱為“Mybole”,“OK”,選擇一個“Single document”,完成。     (二)程式中,要建立一個對話方塊架,可以通過插入一個資源來完成,選擇Insert->Resource(Ctrl+R),在視窗中選擇“Dialog”,然後“New”;也可以通過工具欄上的按鈕“New Dialog(Ctrl+1)”,就會出現一個對話方塊資源,它的ID是“IDD_DIALOG1”。     (三)在MFC程式設計當中,對資源的操作,通常都是通過一個和資源相對應的一個類來完成的。對話方塊的資源也有一個相應的類。這個類叫CDialog,它是從CWnd類派生出來的。CDialog類,它是一個基類,主要是用來在螢幕上顯示一個對話方塊。對話方塊有兩類:模態對話方塊和非模態對話方塊。模態對話方塊在應用程式能夠繼續執行之前必須關閉。非模態對話方塊允許使用者執行另外的操作而不必取消或刪除該對話方塊。     (四)既然對資源的操作,通常都是通過一個和資源相對應的一個類來完成的,接下來我們要建立一個類,讓它和我們的對話方塊資源相關聯。     1.可以選擇“View->ClassWizard”,這時會彈出一個提示對話方塊“Adding a Class”,提示建立一個新的類,也可以選擇一個 現存的類,當然這裡我們選擇“Create a new class”,“OK”。
    2.也可以在對話方塊資源上雙擊一下滑鼠左鍵(推薦方法),它也會彈出一個提示對話方塊“Adding a Class”,提示建立一個新的類,也可以選擇一個現存的類,當然這裡我們選擇“Create a new class”,“OK”。接下來給新的類起一個名稱“CTestDlg”,程式會自動幫我們選擇一個基類“CDialog”,ID號就是“IDD_DIALOG1”。完成“OK”。     (五)這樣,在類檢視欄中,可以看到新建了一個類,在這個新建的類中,有兩個方法:     1.一個是它的建構函式 
 CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
 : CDialog(CTestDlg::IDD, pParent)
 {
 }
    在這個CTestDlg函式當中,它呼叫基類CDialog的建構函式,傳遞CTestDlg當中的IDD成員,這個IDD成員是一個什麼樣的值呢,我們可以看一下CTestDlg的標頭檔案“enum { IDD = IDD_DIALOG1 };”,可以看到這個IDD就是我們剛才所插入的資源的ID號“IDD_DIALOG1”。     2.另外還有一個函式
 void CTestDlg::DoDataExchange(CDataExchange* pDX)
 {
  CDialog::DoDataExchange(pDX);
 }
這個函式主要是用來完成對話方塊資料的交換,和對話方塊資料的校驗的。     (六)現在,我們有了一個類,並和對話方塊資源關聯起來了。接下來,就要建立一個對話方塊資源的視窗。點“屬性”,可以在 選單項中增加一個選單項,取消Pop-up,起一個ID號為“IDM_DIALOG”,名稱叫“對話方塊”,然後在選單項上點右鍵,選擇 “ClassWizard”,然後在object IDs中找到“IDM_DIALOG”,放到view類完成:在CLass name中選擇“CMyboleView”,然後在 Messages中選擇“COMMAND”,然後“Add Function...”,“OK”,然後“Edit Code”。然後自動跳轉到程式碼編輯視窗中。     (七)首先看一下模態對話方塊的建立。     1.建立模態對話方塊,可以用CDialog類中的一下成員函式DoModal
 CDialog::DoModal
 virtual int DoModal();
    返回值:     整數值,指定了傳遞給CDialog::EndDialog 的nResult引數值。該函式EndDialog用於關閉對話方塊。如果函式不能建立對話方塊,則返回-1;如果出現其它錯誤,則返回IDABORT。     說明:
    呼叫該成員函式使用模態對話方塊並返回對話方塊結果。當對話方塊處於活動狀態時,該函式處理與使用者的互動。這使得對話方塊是模態的,使使用者在關閉對話方塊之前不能與其它視窗互動。     如果使用者單擊了對話方塊中的按鈕,如OK或Cancel,那麼訊息處理函式如OnOK或OnCancel被呼叫,從而關閉對話方塊。預設的OnOK成員函式會對對話方塊資料進行有效性檢驗和更新,並關閉它得到結果IDOK。預設OnCancel函式關閉對話方塊得到結果IDCANCEL,而不對對話方塊資料檢驗或更新,可以覆蓋這些訊息函式並改變它們的行為。    注意 目前PreTransMessage被呼叫來處理模態對話方塊的訊息。     程式碼如下:
 CTestDlg dlg;//先建立一個CTestDlg物件dlg
 dlg.DoModal();//然後利用這個物件dlg來呼叫DoModal來產生一個模態對話方塊並顯示它
    在VIEW類中,不知道CTestDlg是一個什麼樣的型別,所以在MyboleView.cpp中要包含CTestDlg所以的標頭檔案
#include "TestDlg.h"
    然後編譯一下執行,點選選單中的對話方塊,就會出現一個模態對話方塊,不關掉,程式就不會繼續執行。     2.建立一個非查模態對話方塊,可以用成員函式CDialog::Create
    CDialog::Create
    BOOL Create(LPCSTR lpszTemplateName, CWnd* pParentWnd = NULL);
    BOOL Create(UNIT nIDTemplate, CWnd* pParentWnd = NULL);
返回值:     如果對話方塊建立和初始化成功,則返回非零值,否則為0。     引數: lpszTemplateName 包含一個對話方塊模板資源的空終止字串。  
    pParentWnd 指向含有對話方塊的父視窗物件的指標。如果為NULL,對話方塊物件的父視窗設定為應用的主視窗。  
    nIDTemplate 包含對話方塊模板資源的ID數。      說明:
    呼叫Create,使用資源中對話方塊模板來建立非模態對話方塊。可將呼叫置於構造程式內部或者在構造程式啟動之後呼叫。Create成員函式為訪問對話方塊模板資源提供了兩種方法,既可以通過模板名稱,也可以模板ID號(如IDD_DIALOG1)。每種訪問方法都會給父視窗傳遞一個指標。如果pParentWnd為NULL,則應用的主視窗作為其父視窗或所有者視窗來進行建立。當建立對話方塊後,Create成員函式應立即返回。在父視窗中建立之後,如果要求對話框出現,則使用模板中的WS_VISIBLE風格。否則,必須呼叫ShowWindow。其它對話方塊風格及應用,請參閱聯機文件“Win32 SDK”中的DIGTEMPLATE結構和“Microsoft Visual C++ 6.0 MFC類庫參考手冊(二)”中的“Windows風格”。使用CWnd::DestroyWindow函式來刪除由Create函式建立的對話方塊。     請參閱: CDialog::CDialog, CWnd::DestroyWindow, CDialog::InitModalIndirect, CDialog::DoModal,::CreateDialog     程式碼如下:
CTestDlg dlg;//先建立一個CTestDlg物件dlg
dlg.Create(IDD_DIALOG1,this);//然後利用這個物件dlg來呼叫Create來產生一個非模態對話方塊,第一個引數是ID號,第二個引數是父視窗C++物件的指標,我們用VIEW類作為它的父視窗,選擇this
dlg.ShowWindows(SW_SHOW);//接下來,還要呼叫ShowWindows來顯示視窗(模態對話方塊不需要這一步)
    編譯一下,再執行。這時候,程式並沒有顯示出我們需要的對話方塊。為什麼?主要是因為,在這裡,我們定義的是一個區域性變數CTestDlg dlg,當程式執行完這個函式以後,dlg的生命週期到了,程式就會被銷燬,所以見不到視窗。模態對話方塊為什麼就可以呢?因為模態對話方塊執行到這裡會暫停,所以它可以顯示出窗體。     這裡可以用兩種方法來解決:
    一種是將dlg定義成View的成員變數,一種方式是定義成一個指標,在堆上分配一個記憶體。我們知道,在堆上分配一個記憶體,它是和程式整個的生命週期是一致的。這裡我們用第二種方法,定義一個指標。將它改成
    CTestDlg *pDlg=new CTestDlg();
    pDlg->Create(IDD_DIALOG1,this);//它是指標了,所以要用指向操作符。
    pDlg->ShowWindows(SW_SHOW); 
    再編譯執行一下。成功。注意一下,當這個窗口出現的時候,我們是可以點選其它的選單項,因為這個對話方塊是非模態對話方塊。當然這裡面有一個問題,我們定義的CTestDlg *pDlg本身是一個區域性變數,當它的生命週期結束的時候,它所儲存的記憶體地址就丟失了,它所指向的這塊記憶體,我們也就沒有辦法再引用到了。我們可以將它變成一個成員變數,然後在解構函式當中用Delet去釋放這個指標所指向的記憶體,這是一個需要注意的地方。另外,對於非模態對話方塊,當我們點選OK的時候,這個視窗並沒有被銷燬,其實是被隱藏了,因為它是呼叫的OnOK虛擬函式:
    CDialog::OnOK
    virtual void OnOK();
    說明:     當用戶按OK按鈕(ID是IDOK)時呼叫。覆蓋該函式執行OK按鈕動作。如果對話方塊包括自動資料檢驗和交換,預設方式是對應用的某些變數進行資料的檢驗和更新。如果在非模態對話方塊中實現OK按鈕,必須覆蓋OnOK成員函式,並在其中呼叫DestoryWindow。不要呼叫基類成員函式,那將會呼叫EndDialog,它是用來關閉模態對話方塊的,這只是讓對話方塊不可見,但沒有銷燬它。 這裡我們使用的還是模態對話方塊,因為非模態對話方塊使用起來比較麻煩。     二、建立完成一個模態對話方塊,並在上面拖放新增一個按鈕,將它的ID號改為“IDC_BTN_ADD”,Caption改為“Add”。
    (一)我們要完成一個功能,當點選Add按鈕的時候,在對話方塊視窗中動態建立一個按鈕。
    要完成這個功能,就必須在Add按鈕上響應一個滑鼠單擊事件,可以在按鈕上右擊選擇ClssWizard,為它新增一個BN_CLICKED的訊息。按鈕單擊,屬於一種通告訊息(訊息分為三類:標準訊息、命令訊息和通告訊息),象按鈕單擊、列表框的選擇,都屬於通告訊息。增加一個函式,選用預設的函式名,OK。編輯程式碼。     1.先定義一個BUTTON物件。
    因為這個物件是在CTestDlg中完成的,可以在CTestDlg類上點選右鍵,Add Member Variable,型別填入:CButton,名稱填入:m_btn,並將它選擇成私有的Private,OK。     接下來可以利用Create函式來建立一個按鈕
 m_btn.Create("按鍵的名稱",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, CRect(0,0,100,100),this,123);
    編譯它,成功。但是第二次點Add按鈕時,程式會出現非法操作,這是因為它重複建立了按鈕,應該改為建立前檢查是否存在。
    修改方法,在CTestDlg類上點選右鍵,再建立一個成員變數,型別為BOOL,名稱為“m_blsCreate”,同樣將它列入Private,OK。在
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
 : CDialog(CTestDlg::IDD, pParent)
{
 m_blsCreate=FALSE;
}
中,將這個變數初始化為FALSE。然後在函式裡判斷一下:
if(m_bliCreate==FALSE)
{
m_btn.Create("按鍵的名稱",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, CRect(0,0,100,100),this,123);
m_blsCreate=TRUE;
}
else //否則就銷燬它。
{
m_btn.DestroyWindow();
m_blsCreate=FALSE;
}
    再編譯一下。當我們第一次點選時,按鈕建立了,再次點選,銷燬了。這是通過一個變數來建立它。     (二)能否通過一個區域性變數來建立它呢?
    比如
BOOL blsCreate=FALSE;
if(bliCreate==FALSE)
{
m_btn.Create("按鍵的名稱",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, CRect(0,0,100,100),this,123);
blsCreate=TRUE;
}
else //否則就銷燬它。
{
m_btn.DestroyWindow();
blsCreate=FALSE;
}
    其實這樣是不行的,因為blsCreate是一個區域性變數,程式每次執行這個void CTestDlg::OnBtnAdd()函式時,都會將 blsCreate=FALSE,if(bliCreate==FALSE)永遠都是成立的,如何來解決這個問題呢,就是將blsCreate區域性變數定義成靜態的:     static BOOL blsCreate=FALSE;
作為一個靜態變數,第一次完成初始化後,以後再執行,程式就不會重新構造了。修改如下:
static BOOL blsCreate=FALSE;
if(bliCreate==FALSE)
{
m_btn.Create("按鍵的名稱",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,CRect(0,0,100,100),this,123);
blsCreate=TRUE;
}
else //否則就銷燬它。
{
m_btn.DestroyWindow();
blsCreate=FALSE;
}
 編譯一下,OK了。   (三)最簡單的辦法。我們知道,對於一個從CWnd派生出的類來說,其內部都有一個成員變數m_hWnd,儲存了和這個C++物件相關 的一個視窗的控制代碼,當一個物件和視窗相關聯的時候,這個控制代碼就有值了。當這個物件沒有和任何一個視窗相關聯的時候,這個句 柄是空的,所以可以判斷這個控制代碼是否為空。程式碼如下:
if(!m_btn.m_hWnd)//這是最簡單,最直接的一種方式建立.
{
m_btn.Create("按鍵的名稱",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, CRect(0,0,100,100),this,123);
}
else
{m_btn.DestroyWindow();} (第3課結束)
/* //第2種
 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種
 int num1,num2,num3;
 num1=GetDlgItemInt(IDC_EDIT1);
 num2=GetDlgItemInt(IDC_EDIT2);
 num3=num1+num2;
 SetDlgItemInt(IDC_EDIT3,num3);
*/
 /*//第4種方法-將控制元件和整形變數相關聯;
 UpdateData();
 m_num3=m_num1+m_num2;
 UpdateData(FALSE);
*/

/*  第5種
 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);
*/
/*
 int num1,num2,num3;//第6種訪問控制元件的方式
 char ch1[10],ch2[10],ch3[10];
 
 //::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10(LPARAM)ch1);//第一種方法傳送訊息.
 //::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);//第二種方法傳送訊息.
 //GetDlgItem(IDC_EDIT1)->SendMessage(WM_GETTEXT,10,(LPARAM)ch1);//第三種方法傳送訊息.
 m_edit1.SendMessage(WM_GETTEXT,10,(LPARAM)ch1);//第四種傳送訊息的方法,這4種都可以用.
 m_edit2.SendMessage(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);
 */
 
//第七種,直接訪問對話方塊的子控制元件
 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);
 SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,0,-1);//複選這個edit
 m_edit3.SetFocus();//設焦點
/*對話方塊控制元件訪問的7種方式
一、GetDlgItem()->Get(Set)WindowText(ch3);
二、GetWindowText()/SetDlgItemText();
三、GetDlgItemInt()/SetDlgItemInt();
四、將控制元件和整形變數相關聯;
五、將控制元件和控制元件變數相關聯;
六、SendMessage();
七、SenDlgItemMessage();
*/
轉自:http://blog.chinaunix.net/uid-16242888-id-142705.html