《VC++深入详解》学习笔记 第七章 对话框(一)

来源:互联网 发布:java websocket 心跳 编辑:程序博客网 时间:2024/05/01 21:24

1.实际上对话框就是一个窗口,也可以将它看成是一个大容器,可以放置各种控件

2.对话框的创建和显示

    (1)在MFC中,所有的控件类都是由CWnd派生来的,因此,控件实际上也是窗口

    (2)对话框的种类:模态对话框和非模态对话框

    (3)创建对话框资源

    (4)在MFC中,对资源的操作通常都是通过一个与资源相关的类来完成的,创建一个与对话框资源相关联的类

   (5)CTestDlg的DoDataExchange函数用来完成对话框数据的交换和校验

   (6)在程序中显示对话框窗口

          1.模态对话框的创建:CDialog类的成员函数DoModal,该函数的作用是创建并显示一个模态对话框,其返回值将作为CDialog类的另一成员函数EndDialog的参数,后者的功能是关闭模态对话框。

       CTestDlg dlg; //必须包含头文件TestDlg.h

       dlg.DoModal();

         2.非模态对话框的创建:CDialog类的成员函数Create()

         (1)   函数声明:

                  1.BOOL Create(LPCTSTR lpszTemplateName,CWnd* pParentWnd = NULL);

                  2.BOOL Create(UINT nIDTemplate,CWnd* pParentWnd = NULL);

                     //Create函数的第一个参数可以是对话框资源的ID,或者也可以是对话框模板的名称

                 //第二个参数指定了对话框的父窗口,若为NULL,对话框的父窗口就是主应用程序窗口。

        (2)当利用Create函数创建非模态对话框后,还需要调用ShowWindow函数将这个对话框显示出来

              dlg.Create(IDD_DIALOG1,this);

              dlg.ShowWindow(SW_SHOW);(dlg要设置为视类成员变量或在堆上分配内存)

       (3) 对非模态对话框来说,要重写基类的OnOk函数和OnCancel函数,并在重写的函数中调用DestroyWindow函数,销毁对话框

3.动态创建按钮

     (1)添加按钮ADD,通过ClassWizard添加消息响应函数

     (2)在CTestDlg中添加成员变量 CButton m_btn,

     (3)在ADD的响应函数中动态创建按钮NEW    

m_btn.Create("new",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD,CRect(0,0,100,100),this,123);//如果在创建按钮时没有指定WS_VISIBLE风格,一定要调用这个按钮的ShowWindow函数,将该按钮控件显示出来。

     (4)点击ADD会创建按钮NEW,再次点击ADD会报错,因为m_btn已经与一个按钮窗口关联,再次创建窗口并试图与m_btn关联会出现非法操作,解决办法是:判断m_btn是否已经与一个按钮关联,若是,销毁先前按钮,关联新的按钮。

         if(m_bIsCreated == false)

        {

m_btn.Create("new",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD,CRect(0,0,\

100,100),this,123);

         m_bIsCreated = true;

       }

       else

      {

          m_btn.DestroyWindow();

          m_bIsCreated = false;

      }

     (5)上面问题的另一中解决办法:判断m_btn的窗口句柄是否为空,若为空,则没有关联按钮窗口;if(!m_btn.m_hWnd){}else{}

4.控件的访问

     (1)静态文本控件

           1.添加控件

           2.调整控件位置(Layout菜单)

           3.修改控件ID(IDC_NUMBER1)、Caption (Number1) 

           4.为控件添加BN_CLICKED消息响应函数

           5.获得静态文本控件对象:CWnd成员函数GetDlgItem()

             函数原型:CWnd* GetDlgItem(int nID)const;//这个函数返回一个由参数nID指定的控件或子窗口的指针

           6.获取静态文本控件上显示的文本:CWnd类的成员函数GetWindowText()

           7.设置控件的文本:CWnd类的成员函数:SetWindowText()

           CString str;

          if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str=="Number1:")

          {

              GetDlgItem(IDC_NUMBER1)->SetWindowText("数值1:");

          }

          else

          {

              GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1:");

          }

          8.静态文本控件在默认状态下是不发送通告信息的,打开静态文本控件的属性——Styles选项卡——选中Notify这个选项

(2)编辑框控件

     1.获得编辑框中的内容:GetWindowText()函数

       设置编辑框中的内容:SetWindowText()函数

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

       2.另一种实现方法:CWnd成员函数GetDlgItemText(这个函数返回对话框中指定ID的控件上的文本(相当于GetDlgItem和GetWindowText的组合))和SetDlgItemText()

        GetDlgItemText(IDC_EDIT1,ch1,10);

        GetDlgItemText(IDC_EDIT2,ch2,10);

        SetDlgItemText(IDC_EDIT3,ch3);

     3.第三种实现方法:CWnd的成员函数GetDlgItemInt()和SetDlgItemInt()

//功能:GetDlgItemInt()返回指定控件的文本,并转换为一个整型数值

函数原型:UINT GetDlgItemInt(int nID,BOOL* lpTrans =NULL,BOOL bSigned =TRUE)const;

//1.控件ID   2.接受转换标识(错误警告)   3.指定被检索的值是否有符号

函数原型:UINT SetDlgItemInt(int nID,UINT nValue,BOOL bSigned =TRUE);

//1.控件ID   2.产生控件上文本的整型数值   3.指定被检索的值是否有符号

     4.第四种实现方法:将三个编辑框分别与对话框类的三个成员变量相关联,然后通过这些成员变量来检索和设置编辑框的文本,这时最简单的访问控件的方式。

ClassWizard—Member Variables—Class name中选CTestDlg—选中控件—add Variable

    (1)在DoDataExchange函数内部实现了对话框控件与类成员变量的关联(自动)

    (2)在程序代码中从来不直接调用 DoDataExchange函数,而是通过CWnd类的成员函数UpdateDate来调用,通过调用后者来初始化对话框控件或从对话框获取数据。

函数原型:BOOL UpdateData(BOOL bSaveAndValidata = TRUE);

//参数值为TRUE说明函数正在获取对话框的数据,FALSE说明函数正在初始化对话框控件

           UpdateData(true);

           m_value3 = m_value1 + m_value2;

           UpdateData(false);

    (3)在关联控件和类成员变量时不仅可以设置变量类型,还可以设置取值范围

MFC提供了多个以DDV_为前缀的数据校验函数。(DDX对话框数据交换  DDV对话框数据校验)

     5.第五种实现方式:把编辑框控件再与一个变量相关联,与上面不同的是,此次关联的是一个控件变量,即代表控件本身

       (1)ClassWizard打开增加成员变量对话框,这次变量的类别不选Value,选Control,变量类型自动成为CEdit(派生于CWnd)

       (2)利用控件变量调用GetWindowText和SetWindowText函数

            m_edit1.GetWindowText(ch1,10);

     6.第六种实现方式:通过获取或设置窗口文本的消息,获取或设置窗口文本

    (1)获取窗口文本的消息是WM_GETTEXT,发送该消息后,系统将把指定窗口的文本复制到调用者提供的一个缓冲中,在这个消息的两个附加参数中,wParam指定将复制的字符数,lParam就是调用者提供的用来保存窗口文本的缓存地址

    (2)设置窗口文本的消息是WM_SETTEXT,这个消息的wParam参数没有使用,值为0,lParam指定了用来设置窗口文本的字符串地址

    (3)利用SDK的SendMessage函数实现(先获得按钮窗口对象成员变量—句柄)

int num1,num2,num3;

   char ch1[10],ch2[10],ch3[10];

::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);

::SendMessage(GetDlgItem(IDC_EDIT2)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch2);

   num1 = atoi(ch1);

   num2 = atoi(ch2);

   num3 = num1 + num2;

   itoa(num3,ch3,10);

::SendMessage(GetDlgItem(IDC_EDIT3)->m_hWnd,WM_SETTEXT,0,(LPARAM)ch3);

        7.第七种方法:也是通过发送消息来完成对控件的访问,但是直接给对话框的子控件发送消息,使用函数SendDlgItemMessage()(不是全局函数,是类成员函数)

           函数原型:LRESULT SendDlgItemMessage(int nID,UINT message,WPARAM wParam = 0,LPARAM lParam = 0);

//第一个参数指定将接受当前发送的这条消息的对话框控件,后三个参数和SendMessage

//相同,实际上,这个函数功能相当于把SendMessage函数和GetDlgItem函数组合起来

          SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1);

   (1)   EM_GETSET消息,获取编辑框中复选内容(EM_开头的都是编辑框消息)

   (2)   SetFocus函数将焦点转移到所选的控件上

5.对话框伸缩功能的实现

      (1)添加一个按钮  收缩<<

      (2)添加消息响应函数

      (3)添加分割条(图片画线实现,选择Styles选项卡中的Sunken,下陷效果)

      (4)添加代码

    CString str;

    if(GetDlgItem(IDC_BUTTON1)->GetWindowText(str),str=="收缩<<")

    {

        GetDlgItem(IDC_BUTTON1)->SetWindowText("展开>>");

    }

    else

    {

        GetDlgItem(IDC_BUTTON1)->SetWindowText("收缩<<");

    }

    static CRect rectLarge;//静态变量,坐标都初始化为零

    static CRect rectSmall;

 

    if(rectLarge.IsRectNull())

    {

        CRect rectSeparator;

        GetWindowRect(&rectLarge);

        GetDlgItem(IDC_SEPERATOR)->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)CRect类有两个成员函数可以用来判断一个矩形是否为空IsRectEmpty():检测矩形区域是否为空,为空返回非零值;IsRectNull():如果矩形的左上角和右下角的四个坐标值都为零,则返回一个非零值。

          (2)GetWindowRect()获取对话框窗口或控件窗口尺寸(调用该函数得到一个矩形)

          (3)SetWindowPos函数设置对话框的大小

          函数原型:BOOL SetWindowPos(const CWnd* pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags)   //该函数的作用是设置窗口的位置和大小 

// pWndInsertAfter,标识一个CWnd对象(窗口的Z次序排序-窗口重叠),这个参数可以是//指向某个CWnd对象的指针也可以是wndBottom,wndtop等

//x,y,窗口左上角坐标   cx,cy窗口的宽度和高度

//nFlags设定窗口的尺寸和定位(各种预定义值的组合)

6.输入焦点的传递

     (1)对话框默认按钮(styles选项卡 Default button)如事先不选择任何按钮,在对话框中按下回车键,默认按钮的消息响应函数会来处理这一事件

     (2)实现在第一个编辑框中按下回车键后,输入焦点转移到第二个编辑框的功能:可以捕获键盘按键消息,在消息响应函数中把焦点移动到下一编辑框控件

          两种实现方式:

1.为编辑框控件生成一个相关联的类,然后利用这个类来捕获键盘按键消息

2.修改编辑框控件的窗口过程函数(窗口过程是在定义窗口类时设置的,当窗口

创建之后怎样去修改?SetWindowLong()函数可以实现

     函数原型:LONG SetWindowLong(HWND hWnd,int nIndex,LONG dwNewLong);

//该函数的作用是改变指定窗口的属性

// hWnd 想要改变其属性的窗口句柄

// nIndex 要设置的属性值的偏移地址,若取值SWL_WNDPROC:设置一个新的窗口过程

// dwNewLong指定设置的新值

//若调用成功,函数将返回原先为窗口指定的属性(32位整型)    

         (1)当对话框及其上的控件创建完成后,显示前,会发送一个消息WM_INITDIALOG

         (2)添加消息响应函数,在其中调用SetWindowLong()改变控件窗口过程         prevProc=(WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd,GWL_WNDPROC,

(LONG)NewEditProc);

         (3)定义全局变量和全局函数

WNDPROC  prevProc;  

    LRESULT CALLBACK NewEditProc(HWND hwnd,UINT uMsg,WPARAM wParam, LPARAM lParam)   

    {                                             

         if(uMsg == WM_CHAR && wParam == 0x0d)                        

         {

             ::SetFocus(GetNextWindow(hwnd,GW_HWNDNEXT));

             return 1;

         }

         else

         {

             return prevProc(hwnd,uMsg,wParam,lParam);

         }

     }

      (4)设置焦点可以用SetFocus实现:HWND SetFocus(HWND hwnd);因为NewEditProc这个窗口过程是全局函数,所以不能调用CWnd的成员函数,只能用相应的SDK函数

      (5)获得对话框中某个控件的下一个控件的句柄:GetNextWindow()函数

  函数原型:HWND GetNextWindow(HWND hWnd,UINT wCmd);

//这个函数返回指定窗口的下一个窗口的句柄,参数中第一个是当前窗口句柄

//第二个参数是查找的方向  CW_HWNDNEXT:下一个   CW_HWNDPREV:上一个

//layout  tab order菜单项可以设置各控件的Tab顺序

     3. 另一中获得窗口句柄的方法: GetWindow()

函数声明:HWND GetWindow(HWND hWnd,UINT uCMD);//该函数返回与指定窗口有特定关系的窗口句柄 (Z次序)

     4.第三种得到窗口句柄的方法:GetNextDlgTabItem(),该函数将返回指定控件前面或后面的一个具有WS_TABSTOP风格的按钮(属性)

原创粉丝点击