VC 視窗建立以及視窗之間傳遞資料、傳遞訊息(模態、非模態)

來源:互聯網
上載者:User

在VC++中,開啟對話方塊一般是用DoModal()函數調用模態對話方塊,但是模態對話方塊只能在對彈出的當前子視窗進行操作,而不能對父視窗進行操作,也無法傳遞資料到父視窗中,根據筆者的研究發現,採用非模態對話方塊的模式可以很好的解決這一問題。

在VS2008中建立一個就有MFC應用程式的Project項目,在彈出的MFC應用程式嚮導中選擇“基於對話方塊”,取消“使用Unicode庫”,單擊完成。在“資源檢視”裡面添加一個對話方塊,預設ID為IDD_DIALOG1。

雙擊IDD_DIALOG1對話方塊,在彈出的MFC類嚮導中,類名填寫CSonDialog,基類選擇CDialog,單擊完成。這樣我們就將建立的IDD_DIALOG1關聯上一個基於CDialog的類了。

在父視窗上添加一個按鈕,雙擊,便可進入這個按鈕的訊息響應函數。在最上麵包含CSonDialog的標頭檔#include “SonDialog.h”。如果在訊息響應函數中寫入如下代碼:

CSonDialogSonWnd;

SonWnd.DoModal();

運行之後按下父視窗上的按鈕,可以發現彈出了IDD_DIALOG1,但是只能在IDD_DIALOG1上操作,無法操作父視窗。如果想要在彈出子視窗後還可以操作父視窗的話,需要採用非模態對話方塊的模式彈出子視窗。

MFC在CDialog類中有一個Create(UINT nIDTemplate, CWnd *pParentWnd =0),這個函數可以建立一個Dialog,其中參數nIDTemplate為需要建立的Dialog的ID。同時還有一個函數ShowWindow(int nCmdShow),用來顯示建立的這個Dialog。在訊息響應函數中寫入如下代碼:

CSonDialogSonWnd;

SonWnd.Create(IDD_DIALOG1);

SonWnd.ShowWindow(SW_SHOW);

運行之後按下父視窗上的按鈕發現視窗閃了一下,然後就消失了。這是因為對象SonWnd是一個局部對象,在運行完SonWnd.ShowWindow(SW_SHOW)這條語句之後便退出了訊息響應函數,因此SonWnd對象也就被銷毀了。如果想要退出訊息響應函數之後視窗依然存在,則需要將SonWnd定義為一個全域變數。因此在ProjectDlg.h中添加一個CSonDialog SonWnd的定義,同時由於VC++在編譯的時候先行編譯標頭檔,因此還需要在ProjectDlg.h中包含CSonDialog的標頭檔#include “SonDialog.h”,這樣在ProjectDlg.cpp中,便可以把SonDialog.h刪掉了。然後在按鈕的訊息響應函數中添加如下代碼:

SonWnd.Create(IDD_DIALOG1);

SonWnd.ShowWindow(SW_SHOW);

我們發現IDD_DIALOG1被建立出來,並且一直保留著。但是還是無法和父視窗進行資料交流。根據尋找資料我們發現在C++中有一個指標很特別,它指向的是當前視窗,這個指標就是this指標。我們通過傳遞this指標來相互調用對方的資料。

在CSonDialog類中,我們添加一個指向父視窗的全域指標變數CProjectDlg *m_pFaher,同時添加一個函數WndCreate(CProjectDlg *pParent),代碼如下:

voidCSonDialog::WndCreate(CProjectDlg *pParent)

{

        Create(IDD_DIALOG1);                         //建立對話方塊

        ShowWindow(SW_SHOW);                         //顯示對話方塊

        m_pFather = pParent;                         //將父視窗指標傳遞進來

}

這個函數中調用了CDialog類中的Create()和ShowWindow()函數來建立和顯示對話方塊,同時採用參數傳遞的辦法將父視窗的指標傳遞到子視窗中。而在父視窗ProjectDlg.cpp的訊息響應函數中,我們添加如下代碼:

SonWnd.WndCreate(this);

編譯運行之後發現有錯,因為在ProjectDlg.h的標頭檔中包含了SonDialog.h,而在SonDialog.h中又包含了ProjectDlg.h,這樣程式在進行編譯的時候就會出現標頭檔重複包含的錯誤,有兩種辦法可以解決此問題。

第一種辦法是在兩個標頭檔中分別加入先行編譯命令#ifndef #define #endif命令,在SonDialog.h最上面加入

#ifndefSONDIALOG

#defineSONDIALOG

最下面加入

#endif

在ProjectDlg.h最上面加入

#ifndefRPOJECTDLG

#definePROJECTDLG

最下面加入

#endif

以上語句塊的意識是如果SONDIALOG/PROJECTDLG沒有被定義的話,那麼就定義SONDIALOG/PROJECTDLG,如果SONDIALOG/PROJECTDLG被定義的話,直接跳轉到#endif,這樣就可以很好的避免被重複定義的情況。這種方法我在以前編程的時候很好用,但是不知道為什麼最近幾次寫程式這種方法都失效了,於是我又想出了另外一種辦法。

第二種辦法的原理是採取避免在標頭檔中定義具體類型的指標變數,用定義null 指標的方法繞過標頭檔重複包含的問題。由於在父視窗中,指向子視窗的對象必須是全域變數,這樣才能保證子視窗在銷毀之前一直有顯示。因此在父視窗ProjectDlg.h中不得不包含SonDialog.h的標頭檔,這樣就只能在SonDialog.h中想辦法了。其實仔細想來我們發現在SonDialog.h中只要定義一個null 指標就可以解決問題。具體方法如下:

在SonDialog.h不包含ProjectDlg.h標頭檔,也不定義CProjectDlg的對象,而是定義一個null 指標LPVOIDm­­­_pFather,將WndCreate()函數的參數改為LPVOID pPaernt,然後在WndCreate()函數中添加如下代碼:

voidCSonDialog::WndCreate(LPVOID pParent)

{

        Create(IDD_DIALOG1);                             //建立對話方塊

        ShowWindow(SW_SHOW);                             //顯示對話方塊

        m_pFather = pParent;                             //將父視窗指標傳遞進來

}

這樣,父視窗的this指標傳遞進來之後到m_pFather還是一個指向任意對象的指標,只要在SonDialog.cpp的函數中需要調用父視窗中的函數或者是改動父視窗的某些變數時,在cpp檔案中包含標頭檔ProjectDlg.h,在函數開始時加入代碼:

CProjectDlg*Main;

Main = (CProjectDlg*)m_pFather;                            //強制將LPVOID類型轉換

Main->

就可以通過指標Main來對父視窗進行操作。這樣就可以實現兩個對話方塊中的資訊相互傳遞了。

另外在建立非模態對話方塊的時候要注意,重寫OnOk()和OnCancel()兩個函數,要在裡面加入DestoryWindow()函數,OnOk()和OnCancel()函數裡面並沒有銷毀視窗,而是使得視窗不可見,如果不銷毀視窗,在下一次再次開啟子視窗時,就會出現錯誤。

以上代碼在Windows 7家庭普通版+Visual Studio 2008SP1下運行通過。

==============

模態對話方塊傳遞參數 http://blog.csdn.net/xiaobai1593/article/details/6591893

父 傳給 子

[cpp]  view plain copy void CDDDlg::OnBnClickedButton1()   {       // TODO: 在此添加控制項通知處理常式代碼       CDlg2 dlg;       dlg.strName="xipeng is a dog!!!";//CDlg2 中定義的public成員變數           dlg.DoModal();   }  
重寫CDlg2的 OnInitDialog函數。

在CDlg2中的建構函式初始化 strName

[cpp]  view plain copy BOOL CDlg2::OnInitDialog()   {       CDialog::OnInitDialog();          // TODO:  在此添加額外的初始化          m_edit2.SetWindowText(strName);       UpdateData(FALSE);       return TRUE;        // return TRUE unless you set the focus to a control       // 異常: OCX 屬性頁面應返回 FALSE   }  
子傳給父

在子視窗中建立到父視窗的指標,然後給其成員變數賦值(在模態對話方塊中也可以實現)

[cpp]  view plain copy void BDlg::OnOK()      {      // TODO: Add extra validation here        ADlg * adlg=(ADlg *)this->GetParent();       adlg->m_edit="i hate u";       adlg->UpdateData(FALSE);          CDialog::OnOK();    

最佳解決方案

最佳方法:

是在看孫鑫的VC視頻的時候看到的,確實是高人呀。

由於非模態對話方塊的執行並不會阻塞主對話方塊的執行,所以大多數時候只能用模態對話方塊。

對話方塊在執行DoModal()函數後,返回的時候視窗被銷毀,但該對象仍然存在,所以仍然可以訪問其中的成員變數。

即可以在主對話方塊中直接存取模態對話方塊對象的成員變數,而不用非得在子對話方塊中擷取父對話方塊的指標來傳遞參數。

[cpp]  view plain copy void ADlg::OnPopbtn()      {      if(updateDlg.DoModal()==IDOK)    

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.