孙鑫VC++深入详解(6):对话框1

1、对话框中的控件

      基本控件:

孙鑫VC++深入详解(6):对话框1_第1张图片

     常用控件:

2、对话框的创建和显示

         对话框分为两种:模态对话框和非模态对话框。模态对话框指当其显示时,其它程序会暂停执行,即不能进行其它操作,直到关闭这个对话框。非模态对话框则没有这个限制。

         要创建一个对话框,需要先创建一个对话框资源:在“资源视图”中插入对话框资源,可以在其属性中设置其ID。

       在MFC中,对资源的操作是通过对应的类来完成的,对话框资源类为CDialog。对话框资源创建完成后就可以为该资源添加一个相关联的类:右击对话框资源-添加类-输入类名(也可以直接双击对话框资源)。

       CDialog::DoModal()用来创建一个模态对话框,eg:

       CTestDlg dlg;

       dlg.DoModal();

       CDialog::Create()用来创建非模态对话框,函数原型:

virtual BOOL Create(
   LPCTSTR lpszTemplateName,
   CWnd* pParentWnd = NULL 
);
virtual BOOL Create(
   UINT nIDTemplate,
   CWnd* pParentWnd = NULL 
);
       第一个参数为对话框模板的名称或对话框资源ID,第二个参数指定对话框的父窗口。

       创建非模态对话框后还要调用ShowWindow()函数将对话框显示出来,eg:

       CTestDlg* pDlg = new CTestDlg;

       dlg.create(IDD_DIALOG1, this);

       dlg.ShowWindow(SW_SHOW);

       对话框资内存的销毁动作可以重载CDialog(CWnd)类的PostNcDestroy()函数,在其中添加代码:

       delete this;

3、为按钮控件添加单击消息响应函数

右击按钮,选择添加事件处理函数,消息类型选择BN_CLICKED,选择按钮所在对话框类,编辑函数名。

CWnd对象都有一个public成员变量m_hWnd,其用来保存与窗口对象相关联的窗口的句柄,如果CWnd对象没有与任何窗口相关联,m_hWnd即为NULL。可依据此来进行相关判断。

4、控件的调整

      复制控件:按住Ctrl,用鼠标拖动相应控件到目的位置即可;调整各控件的位置及间距:可利用工具栏上相关工具实现。

        静态控件的ID都是IDC_STATIC,如果想要其来响应鼠标点击事件,则需要更改其ID,还需要设置其Notify属性,使其可以像父窗口发送通告消息。

5、控件的访问

        1、CWnd::GetDlgItem()用来获得对话框上指定控件的指针,参数为控件ID。函数原型:

CWnd* GetDlgItem(int nID) const;
void GetDlgItem(int nID,HWND* phWnd) const;

                CWnd::GetDlgCtrlID()返回指定控件的ID,因为顶层窗口不具有ID值,所以如果是顶层控件窗口则返回值为NULL。

                CWnd::GetWindowText() /SetWindowText() 用来获得 /设置控件上的文本。

                CWnd::GetDlgItemText() /SetDlgItemText() 用来获得 /设置指定控件上的文本,相当于:GetDlgItem() + GetWindowText()。

                CWnd::GetDlgItemInt() /SetDlgItemInt() 用来获得 /设置指定控件上的数值。

      2、将编辑框控件与对话框的成员变量相关联,实现对控件的访问:

            将编辑框控件与对话框的成员变量相关联然后通过这些成员变量来获取或设置编辑框控件上的文本,这是最简单的访问控件的方法。具体实现为:右击对话框—添加变量—控件变量—选择指定编辑框控件的ID—控件类别选择Value值类型—设置其最大、最小值—根据需要设置变量的访问方式、变量类型、名称—还可以在对话框类的构造函数中设置其初始显示值。

            控件与其关联的成员变量的数据交换是通过对话框的DoDataExchange()函数完成的,可以看到为一个控件关联变量后在DoDataExchange()函数中会自动添加一个以DDX_开头的函数,如果设置了变量的最大、最小值,则会自动添加一个以DDV_开头的函数(DDX:Dialog Data Exchange即数据交换,DDV:Dialog Data Validation即数据校验)。在程序中并不直接调用DoDataExchange()函数,而是通过调用UpdateData()来调用它,当其参数为TRUE时,是从控件得到成员变量的值,当参数为FALSE时,是用成员变量的值来初始化控件。

            故在使用与控件相关联的成员变量前,还需先调用UpdateData()来获得对话框上控件的数据;在改变了与控件相关联的成员变量的值以后,还需再调用UpdateData(FALSE)来初始化对话框上控件的内容。eg:

	UpdateData();
	m_iNum1 = m_iNum2 + m_iNum3;//与编辑框控件相关联的三个整形类型的成员变量
	UpdateData(FALSE);

           还可以将编辑框控件与控件变量相关联,即在控件类别中不选择Value而是选择Control,变量类别会自动变成CEdit。这个时候这个控件变量即代表了控件本身,调用控件变量的成员函数即为调用这个控件的成员函数。

           需要注意的是向单选按钮添加空间变量的时候要将单选按钮的Group属性选择。
       3、可以通过向控件发送WM_GETTEXE消息来获得控件上的文本;向控件发送WM_SETTEXT消息来设置控件上的文本。

       3、可以通过向控件发送WM_GETTEXE消息来获得控件上的文本;向控件发送WM_SETTEXT消息来设置控件上的文本。

                 SendDlgItemMessage()函数可以直接向对话框指定控件发送消息。

6、对话框分割线

         可以通过拖拽图像控件成一条线来显示一条分割线,将其Sunken属性选中,会出现下陷效果。通过图像控件的成员函数GetWindowRect()可以获得分割线的矩形区域坐标,再调用对话框的GetWindowRect()获得对话框的矩形区域坐标,通过这两个矩形区域坐标可以计算出分割线上下区域的矩形坐标。如果不想让用户看到这条分割线,可以将图像控件的Visible属性去掉。

7、对话框上输入焦点的传递

窗口过程函数是在定义窗口类时设置的,当窗口已经创建之后,可以调用SetWindowLong()函数修改指定窗口的窗口过程SetWindowLong()函数可以实现在窗口创建之后修改其属性,函数原型:

LONG WINAPI SetWindowLong(
        HWND hWnd,     
        int nIndex,    
        LONG dwNewLong
);
hWnd:要修改的窗口的句柄

nIndex:要设置的属性值的偏移地址,可以为以下值:

              GWL_STYLE:设置一个新的窗口样式(对应CreateWindow()函数的第三个参数)。

              GWL_EXSTYLE:设置一个新的扩展窗口样式,如WS_EX_TOOLWINDOW为让窗体不在任务栏中显示。

              GWL_WNDPROC:设置一个新的窗口过程函数。

              GWL_HINSTANCE:设置一个新的应用程序实例句柄。

              GWL_ID:为窗口设置一个新的标识。

              GWL_USERDATA:设置与窗口相关的32位值,每个窗口均有一个由创建该窗口的应用程序使用的32位值。

              若hWnd为一个对话框,则nIndex还可以是以下值:

              DWL_DLGPROC:设置新的对话框过程函数。

              DWL_MSGRESULT:设置在对话框过程函数中处理的消息返回值。

              DWL_USER:设置新的额外信息,该信息仅为应用程序所有,例如句柄或指针。

dwNewLong:指定设置的新值。

 SetWindowLong()调用成功会返回先前为窗口指定的32位整形值。如果是为窗口设置新的窗口过程,返回值即为窗口原来的窗口过程函数的地址。  

GetWindowLong()可以获得指定窗口的属性信息,其参数与SetWindowLong()前两个参数意义相同。函数原型:

LONG WINAPI GetWindowLong(
        HWND hWnd,
        int nIndex
);

SetFocus()函数用来设置指定窗口为输入焦点。

GetFocus()函数获得当前焦点所在的窗口。

GetNextWindow()函数可以获得指定窗口(控件)的上一个或下一个窗口(控件)的指针(全局函数返回为句柄),参数为GW_HWNDNEXT则返回下一个窗口,参数为GW_HWNDPREV返回上一个窗口。

GetWindow()函数返回与指定窗口具有特定关系的窗口,利用该函数同样可以查找指定窗口(控件)的上一个或下一个窗口(控件)。

如果想让对话框工具箱上的编辑控件支持多行输入,则需要将编辑框控件的Multiline属性选中,并且只有编辑框支持多行输入才能接收回车键。

下面的代码为为对话框上ID为IDC_EDIT1的编辑框控件设置新的窗口过程:

LRESULT CALLBACK NewProc(
        HWND hwnd,           //消息所属窗口的句柄 
        UINT uMsg,           //消息代码
        WPARAM wParam,       //消息附加参数
        LPARAM lParam        //消息附加参数
)
{
	if(uMsg == WM_CHAR && wParam == 0x0d)//遇到回车键消息
	{
		::SetFocus(GetNextWindow(hwnd, GW_HWNDNEXT));//将下一个控件窗口设为焦点

		return 1;
	}
	else
	{
		return OldProc(hwnd, uMsg, wParam, lParam);//其它消息使用原来的窗口过程处理
	}
}

BOOL CDlgDlg::OnInitDialog()
{
	......

	oldProc = (WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd, GWL_WNDPROC, (LONG)NewProc);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

GetNextDlgTabItem()函数可以获得指定控件的前一个或后一个具有WS_TABSTOP风格的控件。工具箱上的按钮控件、编辑框控件等控件的Tabstop属性默认是选中的,即它们默认具有WS_TABSTOP风格,静态控件默认是不具有WS_TABSTOP风格的。用户按下Tab键后,输入焦点可以转移到具有WS_TABSTOP风格的控件上。GetNextDlgTabItem()的第一个参数指定被搜索的对话框,第二个参数为搜索起始控件,第三个参数为搜索方向:TRUE为搜索对话框中上一个控件,FALSE为搜索对话框中下一个控件

调用GetNextWindow()或GetWindow()获得下一个窗口会有一个问题,那就是当对话框的最后一个控件调用此函数时,返回值为NULL。而调用GetNextDlgTabItem()则不会出现这个问题,因为它是按照对话框的Tab顺序来循环查找下一个控件的。对话框的Tab顺序可以点击菜单栏上"格式"下的"Tab键顺序"进行查看,可以自定义其顺序。




你可能感兴趣的:(孙鑫VC++深入详解)