VC++对话框学习总结

VC++中如何复制对话框资源

http://www.cnblogs.com/Yogurshine/p/3710566.html

法1:

在你的工程中添加另一个工程的rc文件,这时资源视图中就会出现两个rc,从后加的rc中拷贝资源到你自己工程的rc中就可以了。
 
法2:vc中如何拷贝一个工程的对话框资源到另一个工程中?
 
这是一个很专业也很有用的问题。其实VC的设计者早就为我们考虑了这个问题。
在VC6环境下,选择Class视图,选中想要克隆的对话框所对应的类,例如CAboutDlg,点击鼠标右键,选择Add to gallery。在新工程中选择Project菜单,选择Add Component and ActivX,你会看到多了一个文件夹(与上一个工程同名),进入该文件夹,选择*.ogx。选择Insert,你会发现原来的对话框被加入到新的工程中了!
 
补充:
.net下更简单,将原来的工程加到新的工程中,直接将对话框拷贝过去就行了!
 
法3:
VC++中如何复制对话框资源
第一步:用记事本打开原工程的.rc文件,找到想复制的对话框的信息,如下所示
 
IDD_UGMS_DIALOGDIALOGEX 0, 0, 320, 230
STYLE WS_CHILD | WS_VISIBLE
EXSTYLE WS_EX_APPWINDOW
FONT 9, "宋体"
BEGIN
  GROUPBOX      "学生信息",IDC_STATIC,10,8,290,200
  GROUPBOX      "",IDC_STATIC,25,55,205,120
  PUSHBUTTON    "最前(&F)",IDC_BUTTON_FIRST,30,30,35,15
  PUSHBUTTON    "向前(&B)",IDC_BUTTON_PRE,82,30,35,15
  PUSHBUTTON    "向后(&N)",IDC_BUTTON_NEXT,134,30,35,15
  PUSHBUTTON    "最后(&L)",IDC_BUTTON_LAST,186,30,35,15
  PUSHBUTTON    "查询(&Q)",IDC_BUTTON_QUERY,246,70,40,15
  PUSHBUTTON    "增加(&A)",IDC_BUTTON_ADD,246,96,40,15
  PUSHBUTTON    "修改(&M)",IDC_BUTTON_MODIFY,246,122,40,15
  PUSHBUTTON    "删除(&D)",IDC_BUTTON_DELETE,246,148,40,15
  PUSHBUTTON    "确定(&O)",IDC_BUTTON_OK,58,183,40,15
  PUSHBUTTON    "取消(&C)",IDC_BUTTON_CANCEL,150,183,40,15
  LTEXT          "学号:",IDC_STATIC,52,75,25,8
  LTEXT          "姓名:",IDC_STATIC,52,100,25,8
  LTEXT          "性别:",IDC_STATIC,52,125,25,8
  LTEXT          "入学时间:",IDC_STATIC,44,151,41,8
  EDITTEXT      IDC_EDIT_SID,91,72,95,15,ES_AUTOHSCROLL
  EDITTEXT      IDC_EDIT_SNAME,91,96,95,15,ES_AUTOHSCROLL
  EDITTEXT      IDC_EDIT_SSEX,91,120,95,15,ES_AUTOHSCROLL
  CONTROL        "DateTimePicker1",IDC_DATETIMEPICKER_SCOMEDATE,
                  "SysDateTimePick32",DTS_RIGHTALIGN | WS_TABSTOP,91,144,
                  95,15
  GROUPBOX      "",IDC_STATIC,25,19,205,35
END

 上面代码中绿色背景代表的是要复制的对话框资源的ID,此段代码也就是.rc文件中记录的此对话框的信息,黄色背景中间的代码就是
 相应对话框中添加的控件信息,只需将相应代码拷到新工程的相应.rc文件相应的ID对话框资源的BEGIN 和END之间即可;
 
第二步:打开原工程的FileView视图下的Header Files 下的resource.h文件,将其中相应ID的信息复制到新工程的resource.h中即可;
 例如:
 
//复制的资源ID
#define IDC_BUTTON_FIRST              1000
#define IDC_BUTTON_PRE                1001
#define IDC_BUTTON_NEXT              1002
#define IDC_BUTTON_LAST              1003
#define IDC_BUTTON_QUERY              1004
#define IDC_BUTTON_ADD                1005
#define IDC_BUTTON_MODIFY              1006
#define IDC_BUTTON_DELETE              1007
#define IDC_BUTTON_OK                1008
#define IDC_BUTTON_CANCEL              1009
#define IDC_EDIT_SID                  1010
#define IDC_EDIT_SNAME                1011
#define IDC_EDIT_SSEX                1012
#define IDC_DATETIMEPICKER_SCOMEDATE    1013

 
第三步:记得不要遗漏啊,如有ID重复,可以更改一下即可!
  
法4:
 今天碰到模块移植问题了,自己做的对话框类(继承于CDialog)要移植到目标工程中.在网上搜了几个帖子发现都说的很生涩.问了我们的技术总监之后总算解决这个问题了.
       问题:把一个MFC SDI工程中的一个对话框资源和类拷贝到另一个MFC SDI中.
       1.在VC6中打开老的工程,在工作区Resource标签页中选中Dialog文件夹下的资源文件(就是双击后会出现编辑窗口界面的那个东西),按Ctrl+C(Edit->Copy也一样).
       2.关闭当前工程,注意不要关闭VC6,打开目标工程(File->OpenWorkspace),然后选中工作区的Resource标签页中的Dialog文件夹,然后按Ctrl+V(Edit->Paste也一样).好了,对话框拷贝过来了.
       3.将对话框类的cpp h文件拷贝到目标工程中(不详细说了,往当前工程添加文件)
       4.打开复制过来的类cpp和h文件,删除没用的头文件(老工程相关的),并且在.h文件中添加文件包含
 
#include "Resource.h"
第四步很关键,老工程中根本就没有这个文件包含,可是移植之后必须手动添加头文件包含.因为这个问题卡了10几分钟...
当你用资源ID时(通常资源编辑器编辑的资源ID都在resource.h中),如果没有包含CWinApp的派生类所在的头文件就会出错,你看一下它的头文件里,包含了这个文件, 而向导生成的类,它的实现文件都有包含CWinApp派生类所在的头文件的
然后在新工程中就可以使用这个类了,主要就是这个类的对话框中的资源复制头一次遇到.不敢独享,拿出来跟新手们一起学习.
 
于是,当有已经创建好的对话框资源要添加到新工程中时:
(1)右键单击新工程所在的解决方案添加“现有项目”把旧工程添加进来;
(2)切换到“资源视图”并在旧工程对话框资源上右键“复制”;
(3)在新工程对话框资源上右键“粘贴”;
(4)现在就可以为新对话框添加类了,顺便把旧工程的响应函数拷贝过来;
(5)切换回“解决方案资源管理器”,右键旧工程“移除”。
========

VS2010/MFC编程入门之十六(对话框:消息对话框)


http://www.jizhuomi.com/software/171.html
       前面几节鸡啄米讲了属性页对话框,我们可以根据所讲内容方便的建立自己的属性页对话框。本节讲解Windows系统中最常用最简单的一类对话框--消息对话框。

       我们在使用Windows系统的过程中经常会见到消息对话框,提示我们有异常发生或提出询问等。因为在软件开发中经常用到消息对话框,所以MFC提供了两个函数可以直接生成指定风格的消息对话框,而不需要我们在每次使用的时候都要去创建对话框资源和生成对话框类等。这两个函数就是CWnd类的成员函数MessageBox()和全局函数AfxMessageBox()。

       一.CWnd::MessageBox()函数和AfxMessageBox()函数的用法

       下面鸡啄米就分别讲解两个函数的用法。

       1.CWnd::MessageBox()函数

       CWnd::MessageBox()的函数原型如下:

       int MessageBox(
           LPCTSTR lpszText,
           LPCTSTR lpszCaption = NULL,
           UINT nType = MB_OK 
       );

       参数说明:

       lpszText:需要显示的消息字符串。

       lpszCaption:消息对话框的标题字符串。默认值为NULL。取值为NULL时使用默认标题。

       nType:消息对话框的风格和属性。默认为MB_OK风格,即只有“确定”按钮。

       nType的取值可以是下面两个表中任取一个值,也可以是各取一个值的任意组合。即可以指定一个对话框类型,也可以指定一个对话框图标,还可以两者都设定。

nType 取值 参数说明
MB_ABORTRETRY 有“终止”、“重试”和“忽略”按钮
MB_OK 有“确定”按钮
MB_OKCANCEL 有“确定”和“取消”按钮
MB_RETRYCANCEL 有“重试”和“取消”按钮
MB_YESNO 有“是”和“否”按钮
MB_YESNOCANCEL 有“是”、“否”和“取消”按钮

对话框类型表

nType 取值 显示图标
MB_ICONEXCLAMTION
MB_ICONWARNING VS2010/MFC编程入门之十六(对话框:消息对话框)
MB_ICONASTERISK
MB_ICONINFORMATION VS2010/MFC编程入门之十六(对话框:消息对话框)
MB_ICONQUESTION VS2010/MFC编程入门之十六(对话框:消息对话框)
MB_ICONHAND
MB_ICONSTOP

MB_ICONERROR VS2010/MFC编程入门之十六(对话框:消息对话框)


 对话框图标表

       如果想要设置nType的值为类型和图标的组合,可以像这样取值:MB_OKCANCEL | MB_ICONQUESTION。按位取或就可以了。

VS2010/MFC编程入门之十六(对话框:消息对话框)

       2.AfxMessageBox()函数

       AfxMessageBox()的函数原型为:

       int AfxMessageBox(
           LPCTSTR lpszText,
           UINT nType = MB_OK,
           UINT nIDHelp = 0 
       );

       参数说明:

       lpszText:同CWnd::MessageBox()函数

       nType:CWnd::MessageBox()函数

       nIDHelp:此消息的帮助的上下文ID。默认值为0,取0时表示要使用应用程序的默认帮助上下文。

       二.CWnd::MessageBox()和AfxMessageBox()的返回值

      我们在调用了上面两个函数后,都可以弹出模态消息对话框。消息对话框关闭后,我们也都可以得到它们的返回值。两者的返回值就是用户在消息对话框上单击的按钮的ID,可以是以下值:

      IDABORT:单击“终止”按钮。
      IDCANCEL:单击“取消”按钮。
      IDIGNORE:单击“忽略”按钮。
      IDNO:单击“否”按钮。
      IDOK:单击“确定”按钮。
      IDRETRY:单击“重试”按钮。
      IDYES:单击“是”按钮。

      三.应用举例

     我们还是拿前面加法计算器的程序做例子。

       大家是否记得,在模态对话框及其弹出过程中我们修改了CAdditionDlg::OnBnClickedAddButton()函数,在点了“计算”按钮以后先弹出了一个模态对话框,询问用户是否确定要进行加法计算,并通过模态对话框DoModal函数的返回值判断用户选择了“确定”还是“取消”。这些功能很明显消息对话框完全能够实现,鸡啄米就使用消息对话框来替代原来的模态对话框。

       在非模态对话框的创建及显示中,鸡啄米注释了模态对话框的相关代码,加入了非模态对话框的创建和显示代码,我们在加入消息对话框之前将非模态对话框的代码也注释或删除掉,确保此函数中不再生成原来的模态对话框或非模态对话框。

       修改后的CAdditionDlg::OnBnClickedAddButton()函数如下:

C++代码
void CAdditionDlg::OnBnClickedAddButton()   
{   
    // TODO: Add your control notification handler code here   
 
    INT_PTR nRes;   
  
    // 显示消息对话框   
    nRes = MessageBox(_T("您确定要进行加法计算吗?"), _T("加法计算器"), MB_OKCANCEL | MB_ICONQUESTION);   
    // 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行   
    if (IDCANCEL == nRes)   
        return;   
  
    // 将各控件中的数据保存到相应的变量   
    UpdateData(TRUE);   
  
    // 将被加数和加数的加和赋值给m_editSum   
    m_editSum = m_editSummand + m_editAddend;   
  
    // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    UpdateData(FALSE);   
    // 设置属性对话框为向导对话框   
    //sheet.SetWizardMode();   
} 

        编译运行,在运行结果对话框上点“计算”按钮弹出以下消息对话框:

VS2010/MFC编程入门之十六(对话框:消息对话框)

       大家也可以将MessageBox函数换为AfxMessageBox()函数,同时参数进行相应修改,运行下看看效果。

========

VC++创建对话框(转)  

http://blog.163.com/yx_xie2007/blog/static/102464253201002904022375/

 对话框有模式对话框和非模式对话框两种。以下用基于Visual Studio 2008的MFC为例,创建一个程序。

 首先创建一个MFC单文档应用程序,名称为DialogTest.打开资源视图——Menu——IDR_MAINFRAME,在菜单栏中添加一个标签“对话框测试”,ID设置为IDM_DIALOGTEST,在属性中把popup属性设置为false.添加两个子菜单,分别是“模式对话框”,ID为IDM_DIALOG1;“非模式对话框”,ID为IDM_DIALOG2.

 之后在资源视图中的Dialog中添加一个对话框,并添加一个静态文本控件,Caption设置为“模式对话框”,ID为IDD_DIALOG1,双击对话框空白处,在弹出的MFC类向导中命名类名为CTestDlg1,基类选择CDialog,之后完成。同理添加另一个对话框,ID为IDD_DIALOG2。在MFC类向导中的类名设置为CTestDlg2,基类同样为CDialog.

 完成资源的添加后,我们就要完善代码。再次打开IDR_MAINFRAME,右键选择“模式对话框”,在弹出的右键菜单中选择“添加事件处理程序”,在弹出的对话框中的“消息类型”选择COMMAND,类列表选择CDialogTestView,点击“添加编辑”,输入代码:

 CTestDlg1 dlg;

 dlg.DoModal();

此时,模式对话框创建完毕。相对于模式对话框来说,非模式对话框的创建相对复杂一点。同样是再次打开IDR_MAINFRAME,右键选择“非模式对话框”,在弹出的右键菜单中选择“添加事件处理程序”,在弹出的对话框中的“消息类型”选择COMMAND,类列表选择CDialogTestView,点击“添加编辑”,输入代码:

 CTestDlg2 *pDlg=new CTestDlg2;

 pDlg->Create(IDD_DIALOG2,this);

 pDlg->ShowWindow(SW_SHOW);

在这里,我将对话框对象定义为指针,在堆上分配内存,使其与程序的生命周期一致。之后用Creat()函数创建一个对话框,并用ShowWindow()将其显示出来。这里用到了指针指向操作符,只因为定义的对话框对象为指针类型,且调用了其成员函数(有C++基础的都会明白这一点吧......)。由于pDlg这个指针变量为局部对象,当其生命周期结束后,其保存的内存地址就会丢失。所以我们应该在CTestDlg2类中重载PostNcDestroy这个虚函数来释放this指针指向的内存。只需在这个函数中添加一句:

 delete this;

 CDialog::PostNcDestroy();

因为我们在程序中使用了CTestDlg1,CTestDlg2,CDialogTestView类并不清楚其数据类型。因此我们要在DialogTestView.cpp开始出添加:

#include "TestDlg1.h"

#include "TestDlg2.h"

编译运行程序,结果如下所示:VC++创建对话框(转)
========

VC++如何最大化对话框

一打开一个对话框程序,对话框就最大化,并且要求没有标题栏,没有右上角的关闭,最大化,最小化等按钮,总之就是全屏显示的对话框

如何实现?
1. API方式:
    可以通过 ShowWindow 函数改变窗口的显示状态。语法为:
  BOOL ShowWindow(          HWND hWnd,
  int nCmdShow
  );
  hWnd 表示窗口句柄
  nCmdShow 表示想要显示的状态。SW_MAXIMIZE表示最大化,SW_HIDE表示隐藏等等。
2. MFC方式:
  如果是MFC程序,可以使用 CWnd类的 ShowWindow(  int nCmdShow ) 方法,状态参数与API一致。
状态参数还可以取以下数值(详情也可参考MSDN):
SW_HIDE   Hides this window and passes activation to another 
window.
SW_MINIMIZE   Minimizes the window and activates the top-level window 
in the system's list.
SW_RESTORE   Activates and displays the window. If the window is 
minimized or maximized, Windows restores it to its original size and 
position.
SW_SHOW   Activates the window and displays it in its current size and 
position.
SW_SHOWMAXIMIZED   Activates the window and displays it as a maximized 
window.
SW_SHOWMINIMIZED   Activates the window and displays it as an 
icon.
SW_SHOWMINNOACTIVE   Displays the window as an icon. The window that 
is currently active remains active.
SW_SHOWNA   Displays the window in its current state. The window that 
is currently active remains active.
SW_SHOWNOACTIVATE   Displays the window in its most recent size and 
position. The window that is currently active remains active.
SW_SHOWNORMAL   Activates and displays the window. If the window is 
minimized or maximized, Windows restores it to its original size and 
position.  
 
资源视图,选中你的对话框,在修改外观的Title Bar为False,这一步是去掉对话框的标题栏以及关闭按钮;然后进入类视图,选中要执行最大化的对话框类,为其重载OnInitDialog函数,在该函数中增加语句ShowWindow(SW_MAXIMIZE);(要保证在return语句之前)。如果这个对话框是用mfc向导建立的主对话框,那么可能OnInitDialog函数已被重载,只需要在源代码中的该函数中增加这一语句即可。
========

VC++深入详解(5):MFC对话框(一)

http://blog.csdn.net/thefutureisour/article/details/8072873

对话框可以分为两大类:模态对话框和非模态对话框。模态对话框是指,当其显示时,程序会暂停执行,直到关闭这个对话框之后,才能继续执行程序中的其他任务。非模态对话框是指,当对话框显示时,允许转而执行程序中的其他任务,而可以不理会这个对话框。
对话框也是一种资源,可以在资源视图中新建一个对话框来实现。新建的对话框已经包含了2个按钮,确定和取消。
在MFC中,对资源的操作都是通过一个与资源相关的类来完成的。与话框通相关的是CDialog类。当我们使用类向导时,编译器自动检测出我们添加了一个资源,提示我们是否需要为他创建一个类,然后编译器会自动将我们的资源,以及基类选择好,我们只需要填写类名就可以了,我们起名为CTestDlg。编译器会自动的帮我们填写对应的源文件和头文件名,如果我们的类名很长,那么文件名也很长,可以改变。
此时,编译器为这个类编写了两个函数:1.构造函数2.DoDataExchange,用来完成数据的交换和校验。
下面我们希望在程序中显示这个对话框,最简单的做法:增加一个菜单项,点击菜单显示对话框。
我们我们在菜单中添加一个菜单项,然后在VIEW类中为其添加消息响应函数:建立一个CTestDlg对象,调用DoModal函数来实现模态对话框:

void CCH_7_DialogView::OnDialog()   
{  
    // TODO: Add your command handler code here  
    CTestDlg dlg;  
    dlg.DoModal();  
} 

注意,我们还得自己包含#include "TestDlg.h",因为这句代码类向导并没有帮我们添加。
非模态对话框使用的是Create 创建的,注意,创建完成后必须调用ShowWindow函数来显示对话框。

CTestDlg dlg;  
dlg.Create(IDD_DIALOG1,this);  
dlg.ShowWindow(SW_SHOW)

可是程序编译后依然没有显示,这是为什么呢?因为这里的dlg是一个局部变量,程序执行完以后,就析构了。那为什么前面的模态对话框就可以呢?因为模态对话框创建之后,程序就停在了这里,所以他的生命周期并没有结束。那么怎么解决呢?
1.把这个对话框变量定义为局部变量。
2.定义一个指针,指向堆上的数据:

CTestDlg *pDlg = new CTestDlg;  
pDlg->Create(IDD_DIALOG1,this);  
pDlg->ShowWindow(SW_SHOW); 

虽然这样做可以实现功能,但是并不好,因为pDlg会在程序结束时被释放,所以我们以后就拿不到这个指针了,自然也就无法释放它,会造成内存泄露。这个问题可以通过将指针定义为类的成员变量来解决。
还有一点区别在于:对于模态对话框,点击“确定”后,对话框是被“销毁了”;而对于非模态对话框,则是“隐藏了”,你需要重写虚函数OnOK,并在其中调用DestroyWindow ,基类的OnOK只是调用了EndDialog来隐藏对话框。

下面实现一个功能:单击对话框的按钮时,在对话框中动态的创建一个新的按钮。
这里为了方便,使用模态对话框。我们回到资源视图,打开原来的对话框,从工具箱中托一个按钮到对话框上,修改的它的ID为IDC_BTN_ADD,名字为Add。然后右键点击它,选择类向导,然后为其添加消息响应函数OnBtnAdd:

void CTestDlg::OnBtnAdd()   
{  
    // TODO: Add your control notification handler code here  
    m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD,  
        CRect(0,0,100,100),this,123);  
} 

我们发现,程序运行时,当我们点击Add按钮,的确会显示一个新的按钮,但是我们再次点击,程序就会错误,这是因为,当点击时,会调用OnBtnAdd,这个函数调用Create函数创建了一个按钮;但是如果你又点击一次,那么还会调用Create函数将按钮与m_btn关联,可是m_btn已经和第一次创建的按钮相关联了,所以会出错。为此,我们可以增加一个成员变量m_bIsCreate来记录窗口是否已经创建,如果创建,那么就会销毁窗口,而在下一次点击时,又能创建了:

void CTestDlg::OnBtnAdd()   
{  
    // TODO: Add your control notification handler code here  
    if(m_bIsCreate == FALSE)  
    {  
        m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD,  
            CRect(0,0,100,100),this,123);  
        m_bIsCreate = TRUE;  
    }  
    else  
    {  
        m_btn.DestroyWindow();  
        m_bIsCreate = FALSE;  
    }    
} 


其实这里还有一个简单的办法,并不使用成员变量,而是用静态局部变量也能解决这个问题。
实际上,有一种更为直接的方法解决这个问题:CWnd有一个成员变量m_hWnd指向窗口句柄,我们可以利用这个句柄是否为空来判断:

if(!m_btn.m_hWnd)  
{  
    m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD,  
        CRect(0,0,100,100),this,123);  
}  
else  
{  
    m_btn.DestroyWindow();  
}

下面我们我们看看控件的访问:
我们给对话框上添加3个静态文本框没把他们改名为Number1,Number2,Number3;再添加3个编辑框。我们可以通过Layout菜单提供的功能来将它们对其。
首先我们实现一个简单的功能:当点击Number1以后,将它的显示变为“数字1”:
大的思路肯定是对这个控件响应BN_CLICKED消息。可是我们发现,这个控件的ID是IDC_STATIC,但是却在类向导中根本找不见这个ID,原因是因为这个所有的静态文本框都是这个ID。实际上,这个控件一般是用来当做标签用的,并不是用来响应消息的。但是如果我们非要让它响应消息,也是可以的,但是需要改变它的标签,我们改为IDC_NUMBER1,然后为其添加消息响应函数:
首先,按钮也是一个窗口,我们先要获得这个静态文本框,然后再获得它上面的文本。然后把文本重新设置一下:

void CTestDlg::OnNumber1()   
{  
    // TODO: Add your control notification handler code here  
    CString str;  
    if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str == "Number1")  
    {  
        GetDlgItem(IDC_NUMBER1)->SetWindowText("数值1");  
    }  
    else  
    {  
        GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1");  
    }  
} 

但是程序运行以后并没有反应,原因是因为静态文本控件在默认状态下,是不接收通告消息的:我们得在这个控件的属性->样式中,把通知选上,就行了。可见,为了让静态文本框响应消息,需要两个特殊的步骤:1.改变它的ID。2.在它的样式中,选择通知消息。

下面实现一个稍微复杂一点的功能:在两个编辑框中输入数字,然后点击Add按钮,在第三个编辑框中显示结果。
实现的方法有很多种,我们一种一种介绍:
第1种:
void CTestDlg::OnBtnAdd()   
{  
    // TODO: Add your control notification handler code here  
    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);  
} 

这种方法思路清晰:定义的3个字符串和3个int。将编辑框中的字符串获取出来以后转化为int,然后做加法,做完以后转化回去,然后显示在编辑框上。

第二种:

int num1,num2,num3;  
char ch1[10],ch2[10],ch3[10];  
GetDlgItemText(IDC_EDIT1,ch1,10);  
GetDlgItemText(IDC_EDIT2,ch2,10);  
num1 = atoi(ch1);  
num2 = atoi(ch2);  
num3 = num1 + num2;  
itoa(num3,ch3,10);  
SetDlgItemText(IDC_EDIT3,ch3);  


其实跟第一种差不多,但是通过GetDlgItemText和SetDlgItemText完成了第一种中需要两步才能完成工作。

第三种:
使用GetDlgItemInt 函数,这个函数直接通过控件ID获取空间的文本,并把它转化为int类型,然后使用SetDlgItemInt函数:

int num1,num2,num3;  
num1 = GetDlgItemInt(IDC_EDIT1);  
num2 = GetDlgItemInt(IDC_EDIT2);  
num3 = num1 + num2;  
SetDlgItemInt(IDC_EDIT3,num3);  

第四种:
将编辑框分对话框类的三个成员变量相关,然后通过成员变量来检索和设置编辑框的文本。
首先,先要为这三个编辑框关联3个成员变量:在类视图下的建立向导类中,选择CTestDlg类,依次选择
IDC_EDIT1、IDC_EDIT2、IDC_EDIT3,为它们添加int型的变量m_num1、m_num2、m_num3。我们发现classWizzard为我们添加3处代码:
在头文件中,注释宏之间:

// Dialog Data  
    //{{AFX_DATA(CTestDlg)  
    enum { IDD = IDD_DIALOG1 };  
    int     m_num1;  
    int     m_num2;  
    int     m_num3;  
    //}}AFX_DATA

  
源文件的构造函数中:
[cpp] view plain copy
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)  
    : CDialog(CTestDlg::IDD, pParent)  
{  
    //{{AFX_DATA_INIT(CTestDlg)  
    m_num1 = 0;  
    m_num2 = 0;  
    m_num3 = 0;  
    //}}AFX_DATA_INIT  
}  
在源文件的DoDataExchange中:
[cpp] view plain copy
void CTestDlg::DoDataExchange(CDataExchange* pDX)  
{  
    CDialog::DoDataExchange(pDX);  
    //{{AFX_DATA_MAP(CTestDlg)  
    DDX_Text(pDX, IDC_EDIT1, m_num1);  
    DDX_Text(pDX, IDC_EDIT2, m_num2);  
    DDX_Text(pDX, IDC_EDIT3, m_num3);  
    //}}AFX_DATA_MAP  
}  


其中DDX_Text函数完成数据转化的功能。
我们发现,程序运行时,编辑框里的值被自动的设为0了。这个映射关系时通过DoDataExchange函数来实现的。如果这么方便,我们在OnBtnAdd函数中添加一句代码就够了:
[cpp] view plain copy
void CTestDlg::OnBtnAdd()   
{  
    m_num3 = m_num1 + m_num2;  
}  


可是编译后发现运行时不能显示正确的结果,这是为什么呢?通过单步调试,我们可以发现:不论我们的输入是多少,执行到m_num3 = m_num1 + m_num2时,m_num1 和 m_num2的值总是为0!看来我们有必要仔细看看DoDataExchange函数,通过MSDN,我们可以看出,这个函数不是直接调用的,而是通过UpdateData 函数调用的。而UpdateData 函数有一个参数:当他为true时(默认值),是从对话框获取数据,当他为false时,向对话框写数据。于是我们只要改为下面的代码就行了:
[cpp] view plain copy
UpdateData();  
m_num3 = m_num1 + m_num2;  
UpdateData(FALSE);  


假设我们向带画框输入一个字符,那么点击Add的时候,它会提示你请输入一个整数;甚至,在类向导中,你可以设置整数的范围。如果越界也会提示错误。




第五种方式:
将编辑框与控件变量相关联。我们这里选择的是CEdit类型。有了这些成员变量,我们就不需要第一种方法中的GetDlgItem(IDC_EDIT1)步骤了,直接用这些变量来调用GetWindowText或者SetWindowText就行了。
[cpp] view plain copy
int num1,num2,num3;  
char ch1[10],ch2[10],ch3[10];  
m_edit1.GetWindowText(ch1,10);  
m_edit2.GetWindowText(ch2,10);  
  
num1 = atoi(ch1);  
num2 = atoi(ch2);  
num3 = num1 + num2;  
itoa(num3,ch3,10);  
  
m_edit3.SetWindowText(ch3);  
第六种方式:
通过消息。通过向编辑框发送指定的消息(获取文本WM_GETTEXT、设置文本WM_SETTEXT),来实现:
[cpp] view plain copy
int num1,num2,num3;  
char ch1[10],ch2[10],ch3[10];  
::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10,  
    (LPARAM)ch1);  
::SendMessage(m_edit2.m_hWnd,WM_GETTEXT,10,  
    (LPARAM)ch2);  
num1 = atoi(ch1);  
num2 = atoi(ch2);  
num3 = num1 + num2;  
itoa(num3,ch3,10);  
m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3);  


注意:
1.SendMessage是SDK下的函数,所以调用前需要加上::.
2.发送WM_GETTEXT消息时,wParam指明最大字节数,lParam填字符串的地址,但是需要强制类型转化。
3.发送WM_SETTEXT消息时,wParam不使用,填为0,lParam填字符串的地址,但是需要强制类型转化。
第七种方式:
直接给对画框的子控件发送消息:
[cpp] view plain copy
int num1,num2,num3;  
char ch1[10],ch2[10],ch3[10];  
  
SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10, (LPARAM)ch1);  
SendDlgItemMessage(IDC_EDIT2,WM_GETTEXT,10, (LPARAM)ch2);  
num1 = atoi(ch1);  
num2 = atoi(ch2);  
num3 = num1 + num2;  
itoa(num3,ch3,10);  
SendDlgItemMessage(IDC_EDIT3,WM_SETTEXT,0,  (LPARAM)ch3);  
使用成员函数,就省去了获取编辑框的工作。


如果想获取编辑框中的一部分文本,可以通过发送EM_SETSEL消息来获得,其中wParam表示起始位置,lParam表示结束位置。但是如果你想获取一部分文本,那么你的焦点必须设在这个文本框上:
[cpp] view plain copy
SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,2);  
m_edit3.SetFocus();  


总结起来,7中方法中:1、4、5比较常用。




下面我们看另外一个例子:对话框伸缩功能的实现。
这个功能其实也很常见,比如windowsXP下的画图中的颜色菜单中的编辑颜色,点击规定自定义颜色时,这个对话框就被扩充起来了。通常对于一些用户不太需要的功能,可以把它们放在隐藏的区域内,这样能让用户考虑主要的问题。
我们考虑如何设计这个问题:首先肯定是有一个按钮(名字为“收缩”),点击一下以后之后,对话框收缩一部分,按钮的名字改为“扩张”。我们先搞定点击之后名字转化的问题:
[cpp] view plain copy
void CTestDlg::OnButton1()   
{  
    // TODO: Add your control notification handler code here  
    CString str;  
    if(GetDlgItemText(IDC_BUTTON1,str), str == "收缩")  
    {  
        SetDlgItemText(IDC_BUTTON1,"扩张");  
    }  
    else  
    {  
        SetDlgItemText(IDC_BUTTON1,"收缩");  
    }  
}  
接下来的才是重头戏,这种对话框分割的秘密在于:在原来的对话框上添加了一个看不见的,比较细的图像控件(一般是矩形),通过这个矩形确定点击收缩、扩张之后,对话框的位置。
我们先将这个图像控件改名为IDC_SEPERATOR,然后将它的样式改为下陷。
[cpp] view plain copy
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 );          
}  


在处理函数中,我们定义了3个矩形,rectLarge是对话框的原始尺寸,rectSmall是点击收缩以后对话框的尺寸,而rectSeparator则是我们添加的一条细线的尺寸。rectSmall的left、top、right都等于rectLarge,只是把它的button改为rectSeparator的button即可。
获取了窗口的大小,我们只需要使用SetWindowPos重新设置窗口的位置,大小就行了。


我们的程序有一点小瑕疵,当输入一个数字以后,按一下回车结果程序就窗口就关闭了,我们希望按下回车后能转到第二编辑框继续输入。这该怎么办呢?
首先解决第一个问题,为什么按一下回车就关闭了。我们看一下确定按钮的属性,在style里面看到,它是默认选中的。所以如果我们按了回车,就会由确定键的消息响应函数来处理。虽然我们没有写,但是基类中OnOK函数却写了,作用就是关闭对话框。
所以,如果我们希望实现自己的功能,那么得在派生类中重写OK的消息响应函数。我们为其添加响应函数时,类向导会默认的帮我们添加函数,调用基类的成分:
[cpp] view plain copy
void CTestDlg::OnOK()   
{  
    // TODO: Add extra validation here  
      
    CDialog::OnOK();  
}  


如果我们把它注释起来,点击ok就不会关闭窗口了。
那么如何实现回车以后把输入焦点转移到第二个编辑框中呢?
有两种大的思路:1.让编辑框控件生成一个相关联的类,然后利用这个类来出来键盘消息;2.修改编辑框控件的窗口过程函数,在这个函数中判断,如果输入回车,则移动到下一个编辑框。
我们采用第二种思路。首先,改变窗口的消息处理函数的代码应该放在哪里?肯定不能放在create下面,因为此时对话框还没有创建完成呢。实际上,当对话框及其子控件创建完成,显示之前会发送消息:WM_INITDIALOG,我们为CTestDlg添加这个消息的响应函数。
[cpp] view plain copy
WNDPROC prevProc;//声明先前的消息响应函数  
  
//新的消息处理函数  
LRESULT CALLBACK NewEditProc(  
  HWND hwnd,      // handle to window  
  UINT uMsg,      // message identifier  
  WPARAM wParam,  // first message parameter  
  LPARAM lParam   // second message parameter  
)  
{  
    if(uMsg == WM_CHAR && wParam == 0x0d)  
    {  
        ::SetFocus(GetNextWindow(hwnd,GW_HWNDNEXT));  
        return 1;  
    }  
    else  
    {  
        return prevProc(hwnd,uMsg,wParam,lParam);  
    }  
}  


其实这个函数并不复杂,如果消息是回车,那么把焦点设置为下一个窗口。如果不是,则调用原来的消息处理函数来处理。原来的处理函数是哪里来的呢?
[cpp] view plain copy
BOOL CTestDlg::OnInitDialog()   
{  
    CDialog::OnInitDialog();  
      
    // TODO: Add extra initialization here  
    prevProc = (WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd,  
        GWL_WNDPROC,(LONG)NewEditProc);  
    return TRUE;  // return TRUE unless you set the focus to a control  
                  // EXCEPTION: OCX Property Pages should return FALSE  
}  
SetWindowLong函数的返回值就是了!
唯一需要注意的是得给编辑框选上多行选项。因为没有这个选项,编辑框就只能接受一行消息,所以就不能接受回车键了。
我们也注意到,我们只是为第一个编辑框写了代码,所以第二个编辑框下按回车是不起作用的。下面介绍另一种获得窗口句柄的方法:GetWindow它返回与指定窗口有关系的窗口,所以也可以这样写:
[cpp] view plain copy
::SetFocus(::GetWindow(hwnd,GW_HWNDNEXT));  
最后介绍一种获得获得窗口句柄的方法:GetNextDlgTabItem。这个函数返回一个指定控件前面后者后面的一个具有WS_TABSTOP风格的控件。那么什么是WS_TABSTOP风格呢?对于按钮的属性,都有制表站这一项,如果选上了,就有这个风格,如果没选,就没有。
[cpp] view plain copy
::SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE));  
说了这么多,其实这些方法都很麻烦:你得为每个控件写一推代码,有没有简单的方法呢?
很简单,我们把响应回车键的默认函数改了就行了:
[cpp] view plain copy
void CTestDlg::OnOK()   
{  
    // TODO: Add extra validation here  
    GetFocus()->GetNextWindow()->SetFocus();  
//  CDialog::OnOK();  
}  


获取当前焦点,获取这个焦点的下个窗口,将焦点设置在这个窗口,一目了然。
但这个程序是有问题的:当你多输入几次回车以后,就崩溃了,因为最后一个窗口调用GetNextWindow()时,会得到一个空指针,对它进行SetFocus();就会出错。为了解决这个问题,可以使用GetNextDlgTabItem来代替。这个函数的作用是按照顺序查找具有tabstop属性的控件。在layout菜单的taborder下,可以看到他们的顺序。
[cpp] view plain copy
void CTestDlg::OnOK()   
{  
    // TODO: Add extra validation here  
    GetNextDlgTabItem(GetFocus())->GetNextWindow()->SetFocus();  
//  CDialog::OnOK();  
}  


最后再看看默认按钮:对于这个对话框,默认按钮时确定,但是可以通过修改属性来让别的按钮响应。
========

VC++:对话框

http://www.cnblogs.com/huan7550/archive/2013/03/21/2973104.html
《VC++深入详解:第七章》 孙鑫
 
在MFC中,对资源的操作通常都是通过一个与资源相关的类来完成的。


DoDataExchange:主要用来完成对话框数据的交换和校验。
CWnd对象都有一个成员变量m_hWnd,用来保存与窗口对象相关联的窗口句柄,如果窗口对象没有与任何一个窗口相关联,此句柄为NULL。
atoi——将char[]转换为int,用法:num1 = atoi(ch1);
itoa——将数值转换为文本,用法:itoa(num3,ch3,10);
CWnd类还提供了一个成员函数:GetDlgItemText,这个函数将返回对话框中指定ID的控件上的文本,即组合了GetDlgItem和GetWindowText两个函数的功能;同样对应的也有SetDlgItemText。
CWnd类还有另一对成员函数:GetDlgItemInt和SetDlgItemInt。GetDlgItemInt函数返回指定控件的文本,并将其转换为一个整形数值。
 
在DoDataExchange函数内部实现了对话框控件与类成员变量的关联。MFC提供了多种以DDX_为前缀的函数,这些函数分别用于不同控件的数据交换;MFC也提供了多个以DDV_为前缀的数据校验函数。
DoDataExchange
DDX——Dialog Data Exchange,对话框数据交换;
DDV——Dialog Data Validation,对话框数据校验。
Windows程序都是基于消息的系统,因此,为了获取或设置窗口的文本,只要知道获取或设置窗口文本的消息,就可以通过SendMessage来发送这条消息,从而获取或设置窗口的文本。
Windows系统中,获取窗口文本的消息是WM_GETEXT,发送该消息后,系统将把指定窗口的文本复制到调用者提供的一个缓存中;设置窗口文本的消息是WM_SETTEXT。
WM_GETTEXT消息与WM_SETTEXT消息的附加信息
WM_GETTEXT
wParam指定将复制的字符数
lParam就是调用者提供的用来保存窗口文本的缓存地址
WM_SETTEXT
wParam没使用,值为0
lParam参数指定了用来设置窗口文本的字符串地址
SendMessage消息说明
Platform SDK和CWnd类都提供SendMessage函数;所以,如果想要调用Platform SDK的函数,前面必须加双冒号(::)
每个窗口类对象都有一个保存了窗口句柄的成员m_hWnd。获取编辑框控件窗口句柄的方法:可以通过调用GetDlgItem函数获取编辑框窗口对应的C++对象指针,然后通过该指针获得窗口句柄。
对话框的创建
模态对话框的创建
DoModal
代码
CTestDlg dlg;
dlg.DoModal();
非模态对话框的创建
Create
注意:创建非模态对话框时,不能把对话框对象定义为局部对象。
将对话框对象定义为视类的成员变量
将它定义为指针,在堆上分配内存(在堆上分配的内存与程序的整个生命周期是一致的)
错误代码(dlg是局部对象、无法显示)
CTestDlg dlg;
dlg.Create(IDD_DIALOG1,this);
dlg.ShowWindow(SW_SHOW);
正确代码
CTestDlg *pDlg = new CTestDlg;
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);
解决内存丢失问题
方法1:将这个指针变量定义为视类的成员变量,然后在视类的析构函数中调用delete;
方法2:在CTestDlg中重载PostNcDestory虚函数,释放this指针所指向的内存
void CTestDlg::PostNcDestroy()
{
    delete this;
    CDialog::PostNcDestroy();
}
动态创建按钮
想法:为对话框创建一个CButton类的对象m_btn?
做法
先为CTestDlg类添加一个私有的CButton成员变量m_btn
之后,m_btn.Create("New",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123);
解决多次创建按钮非法操作问题
为CTestDlg类增加一个私有的BOOL成员变量m_bIsCreated(标识是否已经创建过按钮窗口了),之后调用Create函数时对变量进行判断
在OnBtnAdd函数中将m_bIsCreated设置为static的(static BOOL bIsCreated = FALSE;)
直接判断与窗口关联的句柄m_hWnd,代码
void CTestDlg::OnBtnAdd()
{
    if(!m_btn.m_hWnd)
    {
         m_btn.Create( "New",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123);
    }
    else
    {
        m_btn.DestroyWindow();
     }
}
静态文本控件
操作静态文本控件
获取静态文本框控件
函数:CWnd *GetDlgItem(int nID) const;
获取静态文本控件的文本
函数:GetWindowText
设置静态文本控件的文本
函数:SetWindowText
代码
CString str;
if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str), str == "Number1:")
 {
    GetDlgItem(IDC_NUMBER1)->SetWindowText("数值1:");
  }
else
  {
    GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1:");
  }
注意:静态文本控件在默认状态下不发送通告消息,需要在其属性对话框中选择Notify选项
编辑框控件
求和:第三个编辑框显示前两个编辑框的和。
七种实现方式(即:七种访问对话框控件的方式)
用CWnd的GetDlgItem和GetWindowText/SetWindowText、itoa/atoi
用GetDlgItemText/SetDlgItemText、itoa/atoi
用GetDlgItemInt/SetDlgItemInt
将三个编辑框分别与对话框类的三个成员变量相关联,然后通过这些成员变量来检索和设置编辑框的文本
添加值变量:int型,Value
使用UpdateData(FALSE)更新显示;UpdataData(TRUE)更新数据。
说明:添加值变量之后程序的变化
类的头文件,两个AFX_DATA注释宏之间增加了成员变量int m_num1;
CTestDlg类构造函数中增加了初始化代码m_num1 = 0;
CTestDlg类的DoDataExchange函数内部调用了三个DDX_Text函数,类似DDX_Text(pDX,IDC_EDIT1,m_num1);
这种方式可以设置输入框数值范围。设置范围后程序变化:DoDataExchange函数中增加了下述代码:
DDV_MinMaxInt(pDX,m_num1,0,100);
DDV_MinMaxInt(pDX,m_num2,0,100);
将编辑框控件关联控件变量
添加控件变量,Control, CEdit
添加控件变量之后程序的变化
类的头文件,连个AFX_DATA注释宏之间增加了成员变量CEdit m_edit1;
DoDataExchange函数中增加了三个DDX_Control函数,分别将一个对话框控件与一个控件变量相关联,类似DDX_Control(pDX,IDC_EDIT1,m_edit1);
说明:这些控件变量代表的就是控件本身,并且CEdit类派生于CWnd类,因此,可以利用这些控件变量调用GetWindowText和SetWindowText来获取和设置编辑框的文本。
通过SendMessage发送消息,从而获取或设置窗口的文本
::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
::SengMessage(m_edit2.m_hWnd,WM_GETTEXT,10,(LPARAM)ch2);
m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3);
通过直接给对话框的子控件发送消息来完成对控件的访问
函数:SendDlgItemMessage,相当于GetDlgItem和SendMessage的结合
SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1);
SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch2);
SendDlgItemMessage(IDC_EDIT3,WM_SETTEXT,0,(LPARAM)ch3);
7种方式总结:


获取和设置编辑框复选的内容
前提:如果要对编辑框控件的内容进行复选,当前焦点应该位于这个编辑框上
可以利用EM_GETSEL消息获得编辑框复选的内容
这个消息的wParam参数将接收复选内容的开始位置
lParam参数将接收复选内容的结束位置
这两个参数都要求是指向DWORD类型的指针
EM_SETSEL用来设置编辑框控件中的复选内容
例如:SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,3);
注意:为了看到第三个编辑框上的复选内容,需要把焦点转移到这个编辑框上,使用m_edit3.SetFocus();
注意2:如果这个消息wParam参数值为0,lParam参数值为-1,则所有内容将被复选
说明:EM_开头的消息是指编辑框控件消息(Edit Control Message)
对话框伸缩功能
几个重要函数及用法示例
rectLarge.IsRectNull();  //矩形几个坐标值是否都为零
rectLarge.IsRectEmpty();  //矩形区域是否为空
GetWindowRect(&rectLarge);  //获得当前窗口矩形
SetWindowPos(NULL,smallRect.left,smallRect.top,smallRect.Width(),smallRect.Height(),SWP_NOMOVE | SWP_NOZORDER);  //设置窗口的位置和大小
实现
定义两个矩形变量:rectLarge/rectSmall(静态变量)
判断对话框的原始尺寸是否已经赋值
IsRectEmpty——检测矩形区域是否为空,若宽度和高度为0或负值,说明矩形为空
IsRectNull——如果矩形左上角和右下角四个坐标值都是0,返回非零值;否则返回0
有了原始和切除后的矩形尺寸,利用SetWindowsPos函数来设置对话框的收缩和扩展之后的大小
SetWindowPos函数
作用:设置窗口的位置和大小
pWndInsertAfter:标识一个CWnd对象,该对象是在以Z次序排序的窗口中位于当前窗口前面的那个窗口对象;该对象可以是指向某个CWnd对象的指针,也可以是下面几个取值之一:
wndBottom
wndTop
wndTopMost
wndNoTopMost
x,y:左上角xy坐标
cx,xy:窗口宽度和高度
nFlags:设定窗口的尺寸和定位
代码示例
输入焦点的传递
主要内容
SetWindowLong():改变指定窗口的属性
OnInitDialog():替换之前的WM_INITDIALOG消息,在对话框及其子控件创建完成、显示之前执行
自定义窗口过程捕获回车字符
if (uMsg == WM_CHAR && wParam == 0x0d)
设置焦点至下一个控件
::SetFocus(GetNextWindow(hwnd, GW_HWNDNEXT));
SetFocus用来设置控件的焦点,参数为控件的句柄(HWND)
实现的功能
在测试对话框中第一个编辑框中按下回车键后,输入焦点被转移到第二个编辑框。
思路:可以通过捕获键盘按键消息,然后在此消息响应函数中把输入焦点移动到下一个编辑框控件来实现。
两种实现方式
为编辑框控件生成一个相关联的类,然后利用这个类来捕获键盘按键消息。
修改编辑框控件的窗口过程函数,即自己编写一个编辑框控件的窗口过程函数,然后替换MFC提供的默认的编辑框控件窗口过程函数。
SetWindowLong函数
改变指定窗口的属性。当一个窗口已经创建之后,修改该窗口已制定的过程函数可以通过此函数来实现。
参数取值及含义
hWnd:指定想要改变其属性的窗口句柄
nIndex:指定要设置的偏移地址
取值:
GWL_EXSIYLE:设置一个新的扩展窗口风格
GWL_STYLE:设置一个新的窗口风格
GWL_WNDPROC:设置一个新的窗口过程
GWL_HINSTANCE:设置一个新的应用程序实例句柄
GWL_ID:为窗口设置一个新的标识
GWL_USERDATA:设置与窗口相关的32位值
如果hWnd参数指定的是一个对话框,还可以取值:
DWL_DLGPROC:设置新的对话框过程
DWL_MSGRESULT:设置在对话框过程中处理的消息返回值
DWL_USER:设置新的额外信息,该信息仅为应用程序所有,例如句柄或指针
dwNewLong:指定设置的新值
修改时机,即在哪里调用SetWindowLong函数?
WM_CREATE消息的响应函数-不合适:在响应WM_CREATE消息时,对话框的子控件还未创建完成,只有在此消息处理完毕之后,对话框及其子控件才全部创建完成。
WM_INITDIALOG消息:当对话框及其上的子控件创建完成,将要显示之前,会发送此消息——在VS2005中,此消息被OnInitDialog函数替代。
所以:将SetWindowLong函数写到OnInitDialog函数中
获得窗口句柄的三种方式
1 GetNextWindow函数
SDK函数用法:GetNextWindow(hwnd, GW_HWNDNEXT);
CWnd的此函数:GetFocus()->GetNextWindow();
2 GetWindow函数
功能:该函数返回与指定窗口有特定关系的窗口句柄
SDK原型:HWND GetWindow(HWND hWnd,UINT uCmd);
第一个参数是开始查找的窗口的句柄
第二个参数指定hWnd参数指定的窗口与要获得的窗口之间的关系,取值
GW_HWNDNEXT,则查找在Z次序中位于指定窗口下面的窗口
GW_HWNDPREV,则查找在Z次序中位于指定窗口前面的窗口
CWnd的此函数:GetWindow(GW_HWNDNEXT);
3 GetNextDlgTabItem函数
该函数返回指定控件前面或后面的一个具有WS_TABSTOP风格的控件。
WS_TABSTOP风格:属性下选中“Tab stop”选项
原型:HWND GetNextDlgTabItem(HWND hDlg, HWND hCtl, BOOL bPrevious);
参数含义:
hDlg:指定将被搜索的对话框
HCtl:指定用来作为搜索开始点的控件
hPrevious:指定搜索的方向——TRUE:上一个;FALSE:下一个。
另一种简单的实现方式
在IDOK的响应函数中添加代码:
GetNextDlgTabItem(GetFocus())->SetFocus();
========

怎么实现VC登录对话框



MFC中如何添加登录对话框呢。VC做的管理系统,通常需要加一个登录界面,以便确认身份。今天和网友们说说,如何在VC中设计登录对话框 ^_^


怎么实现VC登录对话框


方法/步骤
1
新建MFC应用程序,程序类型选择基于对话框,其他默认即可


2
在资源视图下面的Dialog对话框文件夹上右击,选择插入 Dialog


3
在新建的对话框上右击,选择添加类


4
在类向导对话框中,输入类名,确定
这样就建立了类与对话框之间的关联,可以用这个类来创建这个对话框对象了


5
双击打开工程的Welcome.cpp文件,找到 InitInstance() 函数


6
在 Welcome.cpp 上面加上头文件 #include "Login.h"


7
在 CWelcomeApp::InitInstance() 函数中添加修改如下代码


8
运程程序,首先显示了登录对话框啦 #^_^#


END


可以将登录后的对话框在 Login.cpp 的按钮响应函数中显示 #^_^#
========
阅读更多
换一批

没有更多推荐了,返回首页