對話框編程2

在VC6.0中,新建一個單文檔MFC工程,取名Prop,其它的步驟默認。

屬性表單的創建

插入三個屬性頁資源,Insert -> resource -> IDD_PROPPAGE_LAGE .

插入的屬性頁資源與通常的對話框有區別,查看屬性即可。手動插入的屬性頁資源在默認情況下其More Styles屬性是Disable 。其樣式如下圖,其中單選框的ID分別爲:IDD_PROP1,IDD_PROP2,IDD_PROP3 。

還有就是:這三個對話框的More Styles 要取消選擇 Disable 。

 

給這三個屬性頁資源分別添加三個類,選擇相應的屬性頁 -> class wizard… -> Add Class… -> New… -> (Name:CProp1 Base,class:CPropertyPage,Dialog ID: IDD_PROP1),用這種方法,連續的建三個類,OK!

Objects of class CPropertyPage represent individual pages of a property sheet, otherwise known as a tab dialog box. As with standard dialog boxes, you derive a class from CPropertyPage for each page in your property sheet. To use CPropertyPage-derived objects, first create a CPropertySheet object, and then create an object for each page that goes in the property sheet. Call CPropertySheet::AddPage for each page in the sheet, and then display the property sheet by calling CPropertySheet::DoModal for a modal property sheet, or CPropertySheet::Create for a modeless property sheet.

You can create a type of tab dialog box called a wizard, which consists of a property sheet with a sequence of property pages that guide the user through the steps of an operation, such as setting up a device or creating a newsletter. In a wizard-type tab dialog box, the property pages do not have tabs, and only one property page is visible at a time. Also, instead of having OK and Apply Now buttons, a wizard-type tab dialog box has a Back button, a Next or Finish button, and a Cancel button.

For more information on establishing a property sheet as a wizard, see CPropertySheet::SetWizardMode. For more information on using CPropertyPage objects, see the article Property Sheets in Visual C++ Programmer's Guide.

保存工程,保存所有文件,再關閉這個工程,刪除工程中的Prop.clw 文件,再打開工程,再打開ClassWizard… 對話框,提示是否重新從源文件中創建類,選擇確定,創建一個屬性表單, Insert -> New Class… ->(Name:CPropSheet,Base class:CPropertySheet,Dialog ID:IDD_PROP1) ,OK !!!

在CPropSheet類點右鍵,Add Member Variable… ,分別添加三個屬性類(CProp1,CProp2,CProp3)的成員變量m_prop1,m_prop2,m_prop3. 

public
    CProp1 m_prop1;//
添加三個成員變量
 
    CProp2 m_prop2; 
    CProp3 m_prop3; 
    virtual ~CPropSheet();

然後添加屬性表單,在CPropSheet的兩個構造函數中添加:

CPropSheet::CPropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)  
    :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)  
{  
    AddPage(&m_prop1);//增加屬性頁對象  
    AddPage(&m_prop2);  
    AddPage(&m_prop3);
  

}  
  
CPropSheet::CPropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)  
    :CPropertySheet(pszCaption, pParentWnd, iSelectPage)  
{  
    AddPage(&m_prop1);//增加屬性頁對象  
    AddPage(&m_prop2);  
    AddPage(&m_prop3);
  
}  

並在PropSheet.h中包含三個屬性頁的類的頭文件:

// CPropSheet

#include "Prop1.h"//包含三個屬性頁的類的頭文件

#include "Prop2.h"

#include "Prop3.h"

CPropertySheet::AddPage

This method adds a CPropertyPage object to the property sheet. Add pages to the property sheet in the left-to-right order you want them to appear.

void AddPage(

CPropertyPage* pPage );

Parameters

pPage

Points to the page to be added to the property sheet. Cannot be NULL.

Remarks

AddPage adds the CPropertyPage::CPropertyPage object to the CPropertySheet object list of pages but does not actually create the window for the page. The framework postpones creation of the window for the page until the user selects that page.

When you add a property page using AddPage, the CPropertySheet is the parent of the CPropertyPage. To gain access to the property sheet from the property page, call CWnd::GetParent.

It is not necessary to wait until creation of the property sheet window to call AddPage. Typically, you will call AddPage before calling DoModal or Create.

If you call AddPage after displaying the property page, the tab row will reflect the newly added page.

添加一個屬性表單菜單項,在Class Wizard… 中給他添加一個對View類的消息響應函數,

void CPropView::OnPropertysheet()  

    // TODO: Add your command handler code here 
    CPropSheet propSheet("
一個屬性表單程序");//構造一個屬性表單對象 
    propSheet.DoModal();//
顯示一個模態的屬性表單 
}
 

並且還包含頭文件:#include "PropSheet.h"//包含屬性表單頭文件

運行,會發現,中文都是亂碼顯示的。這就要在資源裏修改屬性頁對話框的語言,把IDD_PROP1, IDD_PROP2, IDD_PROP3這三個都改成中文,並將三個對話框的字體也改成宋體,這裏組合框的類型設置爲Drop List,

再運行,可以看到中文顯示正常了!

嚮導的創建

在CPropView::OnPropertysheet()函數中添加:

void CPropView::OnPropertysheet()  

    // TODO: Add your command handler code here 
    CPropSheet propSheet("
一個屬性表單程序");//構造一個屬性表單對象 
    propSheet.SetWizardMode();//
創建導向對話框 
    propSheet.DoModal();//
顯示一個模態的屬性表單 

CPropertySheet::SetWizardMode

void SetWizardMode( );

Remarks

Call this member function to establish a property page as a wizard. A key characteristic of a wizard property page is that the user navigates using Next or Finish, Back, and Cancel buttons instead of tabs.

Call SetWizardMode before calling DoModal. After you call SetWizardMode, DoModal will return either ID_WIZFINISH (if the user closes with the Finish button) or IDCANCEL.

SetWizardMode sets the PSF_WIZARD flag.

運行,即可看到,屬性表單變成了導向的模式。

修改第一頁的上一頁和最後一頁的下一頁,分別給三個屬性表單的類添加虛函數OnSetActive(),並編輯它們的代碼如下:

BOOL CProp1::OnSetActive()

{

    // TODO: Add your specialized code here and/or call the base class

    ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);//獲取父窗口的指針

    return CPropertyPage::OnSetActive();

}

BOOL CProp2::OnSetActive()

{

    // TODO: Add your specialized code here and/or call the base class

    ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT);//獲取父窗口的指針

    return CPropertyPage::OnSetActive();

}

BOOL CProp3::OnSetActive()

{

    // TODO: Add your specialized code here and/or call the base class

    ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH);//獲取父窗口的指針

    return CPropertyPage::OnSetActive();

}

CPropertySheet::SetWizardButtons

void SetWizardButtons( DWORD dwFlags );

Parameters

dwFlags

A set of flags that customize the function and appearance of the wizard buttons. This parameter can be a combination of the following values:

  • PSWIZB_BACK   Back button
  • PSWIZB_NEXT   Next button
  • PSWIZB_FINISH   Finish button
  • PSWIZB_DISABLEDFINISH   Disabled Finish button

Remarks

Call this member function to enable or disable the Back, Next, or Finish button in a wizard property sheet. Call SetWizardButtons only after the dialog is open; you can't call SetWizardButtons before you call DoModal. Typically, you should call SetWizardButtons from CPropertyPage::OnSetActive.

If you want to change the text on the Finish button or hide the Next and Back buttons once the user has completed the wizard, call SetFinishText. Note that the same button is shared for Finish and Next. You can display a Finish or a Next button at one time, but not both.

CPropertyPage::OnSetActive

virtual BOOL OnSetActive( );

Return Value

Nonzero if the page was successfully set active; otherwise 0.

Remarks

This member function is called by the framework when the page is chosen by the user and becomes the active page. Override this member function to perform tasks when a page is activated. Your override of this member function should call the default version before any other processing is done.

The default implementation creates the window for the page, if not previously created, and makes it the active page.

給屬性表單添加判斷

對第一個屬性表單的程序員設置成屬性中的爲選中狀態,然後選擇Class Wizard… -> Member Variables -> (Class Name:CProp1,ID:IDC_RADID1) -> Add Variable -> (name:m_occupation,Categury:Value)

點擊 OK! 給第一個單選按鈕添加了一個組後,這樣選中第一個單選按鈕時它所關聯的成員變量m_occupation的值就爲0,選中第二個單選按鈕時所關聯的值就爲1,選中第三個單選按鈕時所關聯的值就爲2。這個組直接遇到下一個具有那個單選按鈕的的屬性被選中時,這個才結束。如果把項目經理的組的屬性選中,那麼程序員和軟件工程師就是一組了,項目經理就是單獨的一組了。還有一點要提的是,如下

CProp1::CProp1() : CPropertyPage(CProp1::IDD)

{

    //{{AFX_DATA_INIT(CProp1)

    m_occupation = -1;//當初始化爲-1時,表明沒有一個單選按鈕被選中

    //}}AFX_DATA_INIT

}

添加一個虛函數OnWizardNext()對於這個屬性表單的下一步進行響應,編輯代碼:

LRESULT CProp1::OnWizardNext()  

    // TODO: Add your specialized code here and/or call the base class 
    UpdateData(TRUE);//
爲真時,取回控件中的值 
    if(m_occupation==-1
    { 
        MessageBox("
請選擇你的職業 "
); 
        return -1
    }
 
    return CPropertyPage::OnWizardNext(); 
} 

CPropertyPage::OnWizardNext

virtual LRESULT OnWizardNext();

Return Value

0 to automatically advance to the next page;  –1 to prevent the page from changing. To jump to a page other than the next one, return the identifier of the dialog to be displayed.

Remarks

This member function is called by the framework when the user clicks on the Next button in a wizard.

Override this member function to specify some action the user must take when the Next button is pressed.

For more information on how to make a wizard-type property sheet, see CPropertySheet::SetWizardMode.

CPropertySheet::SetWizardMode

void SetWizardMode( );

Remarks

Call this member function to establish a property page as a wizard. A key characteristic of a wizard property page is that the user navigates using Next or Finish, Back, and Cancel buttons instead of tabs.

Call SetWizardMode before calling DoModal. After you call SetWizardMode, DoModal will return either ID_WIZFINISH (if the user closes with the Finish button) or IDCANCEL.

SetWizardMode sets the PSF_WIZARD flag.

做工作地點的判斷

給CProp1添加一個WM_INITDIALOG消息響應函數,這個消息是在對話框將要顯示之前發送的,

BOOL CProp1::OnInitDialog()  

    CPropertyPage::OnInitDialog(); 
     
    // TODO: Add extra initialization here 
    (GListBox*)GetDlgItem(IDC_LIST1)->AddString("
北京"); 
    (GListBox*)GetDlgItem(IDC_LIST1)->AddString("
天津"); 
    (GListBox*)GetDlgItem(IDC_LIST1)->AddString("
上海
"); 
    return TRUE;  // return TRUE unless you set the focus to a control 
                  // EXCEPTION: OCX Property Pages should return FALSE 

CListBox::AddString

int AddString( LPCTSTR lpszItem );

Return Value

The zero-based index to the string in the list box. The return value is LB_ERR if an error occurs; the return value is LB_ERRSPACE if insufficient space is available to store the new string.

Parameters

lpszItem

Points to the null-terminated string that is to be added.

Remarks

Call this member function to add a string to a list box. If the list box was not created with the LBS_SORT style, the string is added to the end of the list. Otherwise, the string is inserted into the list, and the list is sorted. If the list box was created with the LBS_SORT style but not the LBS_HASSTRINGS style, the framework sorts the list by one or more calls to the

給IDC_LIST1控件在CProp1這個類上增加一個CString類型的成員變量m_workAddr。在CProp1::OnWizardNext()函數中增加:

LRESULT CProp1::OnWizardNext()

{

    // TODO: Add your specialized code here and/or call the base class

    UpdateData(TRUE);//爲真時,取回控件中的值

    if(m_occupation==-1)

    {

        MessageBox("請選擇你的職業 ");

        return -1;

    }

    if(m_workAddr=="") //對工作地點的選擇進行判斷

    {

        MessageBox("請選擇你的工作地點!");

        return -1;

    }

    return CPropertyPage::OnWizardNext();

}

對第二個頁面進行處理

在第二屬性頁中分別對四個複選框控件在CProp2上添加如下相應的成員變量:

BOOL    m_football;

    BOOL    m_basketball;

    BOOL    m_volleyball;

    BOOL    m_swim;

作判斷,在CProp2上增加一個OnWizardNext虛函數,編輯代碼:

LRESULT CProp2::OnWizardNext()  

    // TODO: Add your specialized code here and/or call the base class 
    UpdateData(); //
獲得控件的值 
    if(m_football||m_basketball||m_volleyball||m_swim) //
判斷第二個屬性頁 
    { 
        return CPropertyPage::OnWizardNext(); 
    } 
    else 
    { 
        MessageBox("
請選擇你的興趣愛好!
"); 
        return -1
    }
 

}

對第三個頁面進行處理

對CProp3類添加一個OnInitDialog消息處理,編輯:

BOOL CProp3::OnInitDialog()  

    CPropertyPage::OnInitDialog(); 
     
    // TODO: Add extra initialization here 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("1000
元以下"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("1000
元至2000"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("2000
元至3000"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("3000
元以上"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->SetCurSel(0); //
設置第1個列表項被選中

return TRUE;  // return TRUE unless you set the focus to a control 
                  // EXCEPTION: OCX Property Pages should return FALSE
 
}

如果要將顯示的選項按輸入的選項順序顯示,可以取消組合框屬性的sort選項。

將用戶的選擇輸出到View類當中

給CProp3增加成員變量,m_strSalary,類型CString;並增加虛函數OnWizardFinish,Add And Edit… 。

BOOL CProp3::OnWizardFinish()  

    // TODO: Add your specialized code here and/or call the base class 
    int index;  //
定義一個用於存放列表項索引值的變量 
    index=((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel(); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->GetLBText(index,m_strSalary);//
傳遞這個索引並取出用戶的選擇
 
    return CPropertyPage::OnWizardFinish(); 
}

CComboBox::SetCurSel

int SetCurSel( int nSelect );

Return Value

The zero-based index of the item selected if the message is successful. The return value is CB_ERR if nSelect is greater than the number of items in the list or if nSelect is set to –1, which clears the selection.

Parameters

nSelect

Specifies the zero-based index of the string to select. If –1, any current selection in the list box is removed and the edit control is cleared.

Remarks

Selects a string in the list box of a combo box. If necessary, the list box scrolls the string into view (if the list box is visible). The text in the edit control of the combo box is changed to reflect the new selection. Any previous selection in the list box is removed.

CPropertySheet::SetWizardMode

void SetWizardMode( );

Remarks

Call this member function to establish a property page as a wizard. A key characteristic of a wizard property page is that the user navigates using Next or Finish, Back, and Cancel buttons instead of tabs.

Call SetWizardMode before calling DoModal. After you call SetWizardMode, DoModal will return either ID_WIZFINISH (if the user closes with the Finish button) or IDCANCEL.

SetWizardMode sets the PSF_WIZARD flag.

 

作在View類中輸出用戶的選擇,在PropView.h頭文件中,添加成員變量用於存放用戶的選擇,

private:  //View類的成員變量用來,接收用戶的選擇 
    int m_iOccupation; 
    CSting m_strWorkAddr; 
    BOOL m_bLike[4]; 
    CString m_strSalary;
 

並在構造函數中初始化:

CPropView::CPropView()

{

    // TODO: add construction code here

    m_iOccupation=-1;//初始化-1,沒有被選中

    m_strWorkAddr="";

    meset(m_bLike,0,sizeof(m_bLike));//將數組中的buff都初始化成0

    m_strSalary="";

}

並在CPropView::OnPropertysheet()函數編輯:

void CPropView::OnPropertysheet()  

    // TODO: Add your command handler code here 
    CPropSheet propSheet("
一個屬性表單程序");//構造一個屬性表單對象 
    propSheet.SetWizardMode();//
創建導向對話框 
    //propSheet.DoModal();//
顯示一個模態的屬性表單 
    if(ID_WIZFINISH==propSheet.DoModal())//
如果返回的是完成嚮導的消息 
        //
注:在DoModal()值返回時,屬性的的窗口就被銷燬了,但是屬性表單對象的生命週期並沒有結束, 
        //
所以在下面仍然可以調用屬性表單的對象去訪問它內部的數據成員 
    { 
        m_iOccupation=propSheet.m_prop1.m_occupation; 
        m_strWorkAddr=propSheet.m_prop1.m_workAddr; 
        m_bLike[0]=propSheet.m_prop2.m_football; 
        m_bLike[1]=propSheet.m_prop2.m_basketball; 
        m_bLike[2]=propSheet.m_prop2.m_volleyball; 
        m_bLike[3]=propSheet.m_prop2.m_swim; 
        m_strSalary=propSheet.m_prop3.m_strSalary; 
        Invalidate();//
讓窗口無效,引起窗口的重繪 
 
    }
 
}

CWnd::Invalidate

void Invalidate( BOOL bErase = TRUE );

Parameters

bErase

Specifies whether the background within the update region is to be erased.

Remarks

Invalidates the entire client area of CWnd. The client area is marked for painting when the next WM_PAINT message occurs. The region can also be validated before a WM_PAINT message occurs by the ValidateRect or ValidateRgn member function.

The bErase parameter specifies whether the background within the update area is to be erased when the update region is processed. If bErase is TRUE, the background is erased when the BeginPaint member function is called; if bErase is FALSE, the background remains unchanged. If bErase is TRUE for any part of the update region, the background in the entire region, not just in the given part, is erased.

Windows sends a WM_PAINT message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.

然後在OnDraw()函數中完成各種信息的輸出,

void CPropView::OnDraw(CDC* pDC) 

    CPropDoc* pDoc = GetDocument(); 
    ASSERT_VALID(pDoc); 
    // TODO: add draw code for native data here 
    CFont font;//
創建一個字體 
    font.CreatePointFont(300,"
華文行楷"); 
     
    CFont *pOldFont;//
用於保存返回的先前的字體 
    pOldFont=pDC->SelectObject(&font); 
    //
將字體選擇到構架窗口的DC,返回先前的字體保存到pOldFont 
 
    CString strTemp;//
定義一個臨時變量 
    strTemp="
你的職業:"
 
    //
判斷用戶的選擇 
    switch(m_iOccupation) 
    { 
    case 0
        strTemp+="
程序員"
        break
    case 1
        strTemp+="
系統工程師"
        break
    case 2
        strTemp+="
項目經理"
        break
    default
        break
    } 
    pDC->TextOut(0,0,strTemp);//
將選擇的職業輸出到屏幕 
     
    strTemp="
你的工作地址:"
    strTemp+=m_strWorkAddr; 
 
    TEXTMETRIC tm;//
定義一個METRIC 
    pDC->GetTextMetrics(&tm); 
    pDC->TextOut(0,tm.tmHeight,strTemp); 
 
    strTemp="
你的興趣愛好:"
    if(m_bLike[0]) 
    { 
        strTemp+="
足球"
    } 
    if(m_bLike[1]) 
    { 
        strTemp+="
籃球"
    } 
    if(m_bLike[2]) 
    { 
        strTemp+="
排球"
    } 
    if(m_bLike[3]) 
    { 
        strTemp+="
游泳"
    } 
    pDC->TextOut(0,tm.tmHeight*2,strTemp); 
 
    strTemp="
你的薪資水平:"
    strTemp+=m_strSalary; 
    pDC->TextOut(0,tm.tmHeight*3,strTemp); 
 
    pDC->SelectObject(pOldFont);//
將字體選擇回來
  
}

 

運行,OK , ^_^

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章