MFC 对话框程序设计

1.1 CDialog简单笔记

MFC 对话框程序设计_第1张图片

用来管理对话框控件的CWnd成员函数 

 函数名 

 功能 

 CheckDlgButton 

 选中或不选中按钮控件。 

 CheckRadioButton 

 选择一个指定的单选按钮并使同组内的其它单选按钮不被选择。 

 DlgDirList 

 往一个列表框中添加文件、目录或驱动器的列表。 

 DlgDirListComboBox 

 往一个组合框中的列表框内添加文件、目录或驱动器的列表。 

 DlgDirSelect 

 从一个列表框中获得当前选择的文件、目录或驱动器。 

 DlgDirSelectBomboBox 

 从一个组合框中获得当前选择的文件、目录或驱动器。 

 GetCheckedRadioButton 

 返回指定的单选按钮组中被选择的单选按钮的ID。 

 GetDlgItem 

 返回一个指向一给定的控件的临时对象的指针。 

 GetDlgItemInt 

 返回在一个指定的控件中由正文表示的数字值。 

 GetDlgItemText 

 获得在一个控件内显示的正文。 

 GetNextDlgGroupItem 

 返回一个指向一组控件内的下一个或上一个控件的临时对象的指针。 

 GetNextDlgTabItem 

 返回下一个tab顺序的控件的临时对象的指针。 

 IsDlgButtonChecked 

 返回一个按钮控件的状态。 

 SendDlgItemMessage 

 把一个消息传送给一个控件。 

 SetDlgItemInt 

 将一个整数转换为正文,并将此正文赋给控件。 

 SetDlgItemText 

 设置一个控件显示的正文。 

1.2 对话框消息处理技巧

有时,为了处理方便,需要把多个ID连续的控件发出的相同消息映射到同一个处理函数上.这就要用到ON_CONTROL_RANGE宏.ON_CONTROL_RANGE消息映射宏的第一个参数是控件消息码,第二和第三个参数分别指明了一组连续的控件ID中的头一个和最后一个ID,最后一个参数是消息处理函数名。例如,要处理一组单选按钮发出的BN_CLICKED消息,相应的消息映射如下所示: 

ON_CONTROL_RANGE(BN_CLICKED, IDC_FIRST, IDC_LAST,OnRadioClicked) 

函数OnRadioClicked的声明如下,该函数比上面的OnAdd多了一个参数nID以说明发送通知消息的控件ID. 

afx_msg void OnRadioClicked(UINT nID); 

ClassWizard不支持ON_CONTROL_RANGE宏,所以需要手工建立消息映射和消息处理函数. 

 

提示:事实上,在使用ClassWizard时只要运用一个小小的技巧,就可以把不同控件的通知消息映射到同一个处理函数上,也可以把一个控件的不同通知消息映射到同一个处理函数上.这个技巧就是在用ClassWizard创建消息处理函数时,指定相同的函数名即可.此方法的优点在于控件的ID不必是连续的,缺点是处理函数没有nID参数,因而不能确定是哪一个控件发送的消息.

1.3 动态创建按钮(CButton-Create)

CButton::Create

 

xxx.h

 

private:

       CButtonm_Btn;

        BOOL m_IsbCreated;//判断是否创建,开始一定要在构造函数中设置为FALSE

///

 

xxx.cpp

 

void CCDialogTestDlg::OnBnClickedButton1()

{

       //TODO:  在此添加控件通知处理程序代码

       if(m_IsbCreated == FALSE)

       {

              m_Btn.Create(_T("动态创建的按钮"), WS_VISIBLE | WS_CHILD |BS_DEFPUSHBUTTON, CRect(0, 0, 150, 50), this, 12333);

              m_IsbCreated= TRUE;

       }

       else

       {

              m_Btn.DestroyWindow();

              m_IsbCreated= FALSE;

       }

       //m_Btn.ShowWindow(SW_SHOW);

}

--------------------------------------------------------------------------------------------------

1.4 对话框伸缩功能的实现

添加图片控件并设置ID为IDC_SEPARATOR,属性中Sunken为TRUE。

 

void CCDialogTestDlg::OnBnClickedButton2()

{

       // TODO:  在此添加控件通知处理程序代码

       CString str;

       GetDlgItemText(IDC_BUTTON2, str);

       if (str == "扩展窗口>>")

       {

              SetDlgItemText(IDC_BUTTON2, _T("收缩窗口<<"));

       }

       else

       {

              SetDlgItemText(IDC_BUTTON2, _T("扩展窗口>>"));

       }

       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);

       }

}

--------------------------------------------------------------------------------------------------

附加:

1.5 属性表单和向导的创建

使用类CpropertyPage、

CObject

 └CCmdTarget

    └CWnd

       └CDialog

          └CpropertyPage

步骤:

根据属性页页数插入多个资源CDialog,属性页资源有三种类型(大、中、小)

备注:分别为各个页创建对话框模板,去掉缺省的OK和Cancel按钮。每页的模板最好具有相同的尺寸,如果尺寸不统一,则框架将根据最大的页来确定标签对话框的大小。

属性页的设置(与普通对话框属性不同)

指定标题(Caption)的内容。标题的内容将显示在该页对应的标签中。 

选择System menu—False、TitleBar---True、Style--Child、Border--ThinBorder和Disable ---True。 

根据各个页的模板,用ClassWizard分别为每个页创建CPropertyPage类的派生类。这一过程与创建普通对话框类的过程类似,不同的是在创建新类对话框中应在Base class一栏中选择CPropertyPage而不是CDialog。 

用ClassWizard为每页加入与控件对应的成员变量,这个过程与为普通对话框类加入成员变量类似。

注意:为了构建一个属性表单,首先需创建一个Cproperty Sheet对象,在该对象头文件中添加

// CPropSheet

#include "Prop1.h"

#include "Prop2.h"

#include "Prop3.h"

.........................

public:

       CProp1 m_prop1;

       CProp2 m_prop2;

CProp3 m_prop3;

--------------------------------------------------------------------------------------------------

然后在构造函数中调用AddPage添加属性页

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);

}

--------------------------------------------------------------------------------------------------

注意:有两个构造函数,参数不一样。

典型的标签式对话框创建代码:

void CMyView::DoModalPropertySheet() 

 { 

 CPropertySheet propsheet; 

 CMyFirstPage pageFirst; // derived from CPropertyPage 

 CMySecondPage pageSecond; // derived fromCPropertyPage 

 

 // Move member data from the view (or from thecurrently 

 // selected object in the view, for example). 

 pageFirst.m_nMember1 = m_nMember1;  

 pageFirst.m_nMember2 = m_nMember2; 

 pageSecond.m_strMember3 = m_strMember3; 

 pageSecond.m_strMember4 = m_strMember4;  

 propsheet.AddPage(&pageFirst); 

 propsheet.AddPage(&pageSecond); 

 if (propsheet.DoModal() == IDOK) 

 { 

 m_nMember1 = pageFirst.m_nMember1; 

 m_nMember2 = pageFirst.m_nMember2; 

 m_strMember3 = pageSecond.m_strMember3; 

 m_strMember4 = pageSecond.m_strMember4;  

 . . .  

 } 

 }

--------------------------------------------------------------------------------------------------

向导的创建

但是步骤5创建的表单有问题,比如第一个属性页就不应该有“上一步”的按钮,所以还要设置如下:

// CProp2 message handlers

BOOL CProp2::OnSetActive()

{

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

       ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);

       return CPropertyPage::OnSetActive();

}

--------------------------------------------------------------------------------------------------

1.   处理各个属性页(注意判断用户是否选中各个属性页的选项)

LRESULT CProp2::OnWizardNext()

{

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

       UpdateData();

       if(    m_football || m_basketball || m_volleyball|| m_swim)

              return CPropertyPage::OnWizardNext();

       else

       {

              MessageBox("请选择你的兴趣爱好!");

              return -1;

       }

}

--------------------------------------------------------------------------------------------------

2.   完成向导:在最后一个属性页中最后调用函数

BOOL CProp3::OnWizardFinish()

{

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

       int index;

       index=((CComboBox*)GetDlgItem(IDC_COMBO3))->GetCurSel();

       ((CComboBox*)GetDlgItem(IDC_COMBO3))->GetLBText(index,m_strSalary);

      

       return CPropertyPage::OnWizardFinish();//重点

}

--------------------------------------------------------------------------------------------------

1.6 对话框位置和大小设置

1.6.1 限制对话框大小

主要是afx_msg void OnSize(UINT nType, int cx, int cy);的使用

 

voidCRestrictRectDlg::OnSize(UINT nType, int cx, int cy)

{

       CDialog::OnSize(nType, cx, cy);

      

       // TODO: Add your message handler codehere

       CRect rect;

       GetWindowRect(&rect);//获取窗口矩形区

       if(cx > 400)

              rect.right = rect.left + 400;//窗体宽度不能大于400

       if(cy > 300)

              rect.bottom = rect.top + 300;//窗体高度不能大于300

       if(cx < 200)

              rect.right = rect.left + 200;//窗体宽度不能小于200

       if(cy < 150)

              rect.bottom = rect.top + 150;//窗体高度不能小于150

       MoveWindow(&rect);//修改窗体大小

}

--------------------------------------------------------------------------------------------------

1.6.2 限制最大化时窗体大小

主要是这个函数:afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);

 

voidCLimitSizeDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)

{

       lpMMI->ptMaxSize.x = 800;    //设置对话框最大化时的宽度

       lpMMI->ptMaxSize.y = 600;    //设置对话框最大化时的高度

 

       lpMMI->ptMaxPosition.x = 50; //设置对话框最大化时左边位置

       lpMMI->ptMaxPosition.y = 50; //设置对话框最大化时上访位置

       CDialog::OnGetMinMaxInfo(lpMMI);

}

--------------------------------------------------------------------------------------------------

注意,可类似制作最小化时窗体大小。

1.6.3 发送最大化或最小化消息

voidCMaxAndMinDlg::OnButton1()

{

       PostMessage(WM_SYSCOMMAND,SC_MAXIMIZE,0);

}

 

voidCMaxAndMinDlg::OnButton2()

{

       PostMessage(WM_SYSCOMMAND,SC_MINIMIZE,0);

}

-------------------------------------------------------------------------------------------------

1.6.4 对话框窗口变化时控件适应大小

使用从CDialog派生的一个类cdxCSizingDialog,用于实现可改变大小的对话框,具体要参见源代码。

1.6.5 始终在最上面的窗体

BOOLCTopWindowDlg::OnInitDialog()

{

       .....................

       SetIcon(m_hIcon, TRUE);               // Set big icon

       SetIcon(m_hIcon, FALSE);       // Set small icon

      

       //始终在最上面的窗体

::SetWindowPos(AfxGetMainWnd()->m_hWnd,HWND_TOPMOST,10,10,450,300,SWP_NOMOVE);

       return TRUE;  // return TRUE  unless you set the focus to a control

}

-------------------------------------------------------------------------------------------------

1.7 自绘对话框

可以根据具体的要求自己绘制美观的对话框,具体参见源代码。

1.8 换肤窗体

主要是一个组件库的使用,具体参见源代码。

1.9 对话框背景

1.9.1 位图背景

方法一:准备一张位图,主要是在OnPaint()中添加位图。

 

voidCBmpBKDlg::OnPaint()

{

       ................

       else

       {

              CPaintDC dc(this);      //窗体DC

              CBitmap m_bitmap;    //位图变量

              m_bitmap.LoadBitmap(IDB_BITMAP1);//载入位图资源

              CDC memdc;       //临时DC

              memdc.CreateCompatibleDC(&dc);//创建临时DC

              memdc.SelectObject(&m_bitmap);//选中位图对象

              int width,height;//定义位图宽度和高度

              BITMAP bmp;

              m_bitmap.GetBitmap(&bmp);//获取位图信息

              width = bmp.bmWidth;//位图宽度

              height = bmp.bmHeight;//位图高度

              CRect rect;

              this->GetClientRect(&rect);//获取窗体大小

              //将位图绘制在窗体上作为背景

       dc.StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memdc,0,0,width,height,SRCCOPY);       }

}

-------------------------------------------------------------------------------------------------

 

方法二:实现CWnd::OnEraseBkgnd消息函数

BOOLCShowImageDlgDlg::OnEraseBkgnd(CDC *pDC)

{    

      CRect rect;

      GetClientRect(&rect);

      CDC memDC;

      CBitmap cbmp;

      CBitmap* bmp = NULL;

      cbmp.LoadBitmap(IDB_MYBITMAP);//装载背景位图

      BITMAP bmInfo;

      cbmp.GetBitmap(&bmInfo);

      memDC.CreateCompatibleDC(pDC);

      bmp = memDC.SelectObject(&cbmp);

      //pDC->BitBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);

pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memDC,0,0,bmInfo.bmWidth,bmInfo.bmHeight,SRCCOPY);

      if (bmp) memDC.SelectObject(bmp);

      return TRUE;

}

-------------------------------------------------------------------------------------------------

注:还可使用第三方的类,具体见源代码。

 

1.9.2 使用笔刷绘制背景

HBRUSHCBrushBKDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

{

       HBRUSH hbr = CDialog::OnCtlColor(pDC,pWnd, nCtlColor);

      

       // TODO: Change any attributes of the DChere

       CBrush m_brush; //定义画刷

       m_brush.CreateSolidBrush(RGB(255,0,0));//指定画刷颜色

       CRect m_rect;

       GetClientRect(m_rect);//客户区矩形

       pDC->SelectObject(&m_brush);//选择画刷

       pDC->FillRect(m_rect,&m_brush);//填充矩形区

       return m_brush;

}

-------------------------------------------------------------------------------------------------

1.9.3 渐变色背景

修改OnPaint()函数即可。

voidCColorChangeDlg::OnPaint()

{

       CPaintDC dc(this);

       CBrush brush;

       CRect rect;

       GetClientRect(&rect);

       for(int m=255;m>0;m--)

       {

              int x,y;

              x = rect.Width() * m / 255;

              y = rect.Height() * m / 255;

              brush.DeleteObject();

              brush.CreateSolidBrush(RGB(255,m,0));

              dc.FillRect(CRect(0,0,x,y),&brush);

       }

}

-------------------------------------------------------------------------------------------------

1.9.3 使用CImage类动态加载图片背景

要使用CImage类,就在对话框类的头文件中定义一个:CImage类

 

CImagem_DlgBKImage;

 

再在此对话框的OnInitDialog中进行载入,方法为:

 charLoatFilePath[256] = "C://Documents and Settings//Administrator//桌面//20090728//20090728//23.jpg";
 HRESULT  ImageLoad;
 CRect rect;
 CWnd::GetClientRect(&rect);

 ImageLoad= m_DlgBKImage.Load(LoatFilePath);

if(0== ImageLoad)

{

  Messagebox("load file error!");

}
 InvalidateRect(&rect,TRUE);

 

再在对话框的OnPaint方法中:

 

 CPaintDCdc(this); // 用于绘制的设备上下文
 CRect rect;
 GetClientRect(&rect);
 if (!m_DlgBKImage.IsNull())
 {
  m_DlgBKImage.StretchBlt(dc,rect);
 }

 //当前目录

CString m_strPath;

    char chPath[MAX_PATH];

    GetModuleFileName(NULL, chPath, MAX_PATH);  //得到执行程序的文件名(包括路径);

    m_strPath.Format("%s", chPath);                 //转换成字符串;

    int nPos = m_strPath.ReverseFind('\\');     //从右边找到第一个“\\”字符,返回其数组下标的位置

    m_strPath = m_strPath.Left(nPos + 1);       //保留字符串的前nPos+1个字符(包括“\\”);

    m_strPath+= "test.bmp";

    //char LoatFilePath[256] =m_strPath+"test.bmp";

    HRESULT  ImageLoad;

    CRect rect;

    CWnd::GetClientRect(&rect);

    ImageLoad = m_DlgBKImage.Load(m_strPath);

你可能感兴趣的:(MFC)