对话框1

本文详细介绍了MFC中模态对话框和非模态对话框的创建方法,以及动态创建和删除按钮的三种策略。此外,还讲解了如何通过点击事件改变静态文本框内容,并提供了多种访问控件内容的方式,包括编辑框中的加法运算。最后,讨论了对话框的收缩与扩展功能,以及如何处理回车键焦点转移和焦点依次传递的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.模态对话框的创建:


void CMyboleView::OnDialog() 
{
// TODO: Add your command handler code here
CTestDlg dlg;
//DoModal本来就有显示对话框的作用
dlg.DoModal();
//当程序执行到这,就不再继续往下执行,知道我们点击“OK”或者“Cancel”
        //我们就可以执行程序中的其他功能
}


2.非模态对话框的创建:
void CMyboleView::OnDialog() 
{
// TODO: Add your command handler code here


//非模态对话框


//我们在创建非模态对话框的时候,将dlg定义成一个局部变量是不可以的
//有两种方式去解决:1.将dlg定义成View类的成员变量;
//2.定义指针,在堆上分配一个内存,在堆上所分配的内存和我们整个程序的生命周期是一致的
    
//当我们在创建非模态对话框的时候它会顺序往下执行,程序的执行并不会停顿在某条语句的
//执行上,也就是我们的OnDialog这个函数执行完成了,它就可以执行其他的任务了
        //当然这里有一个问题,我们定义的指针变量本身就是一个局部变量
  //当它的生命周期结束的时候,它所保存的内存地址也就丢失了,他所指向的这块内存
//我们就没有办法再引用到了。这里我们可以将它变成成员变量,然后在我们的析构函数当中
//去释放这个指针所指向的内存。以上就是在使用费模态对话框的时候要注意的地方
//     CTestDlg dlg;
CTestDlg *pDlg=new CTestDlg();
pDlg->Create(IDD_DIALOG1,this);
//调用ShowWindow将这个对话框显示出来
        pDlg->ShowWindow(SW_SHOW);
}


3.动态创建按钮:
“按钮的单击”属于通告消息
//方法一
 void CTestDlg::OnBtnAdd() 
{
// TODO: Add your control notification handler code here
/*方法一:
不能让它多次创建,因为它已经和一个窗口绑定在一起了,当我们已经判断它和一个
窗口绑定在一起的时候我们需要将它的窗口先把它销毁了,当它再一次点击的时候
我们再去创建它。在这个地方我们可以设置一个变量.
        当m_bIsCreate==FALSE,说明Button还没有创建,然后我们就去创建它
*/
if(m_bIsCreate==FALSE)
{
      m_btn.Create("维新",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
    CRect(0,0,100,100),this,123);
m_bIsCreate=TRUE;
}
//否则我们要销毁这个窗口
else
{
m_btn.DestroyWindow();
m_bIsCreate=FALSE;
}
}


//方法二:
void CTestDlg::OnBtnAdd() 
{
// TODO: Add your control notification handler code here
//如果我想通过定义一个局部的变量来判断可不可以呢
//为了让它在我们点击这个Button按钮的时候,它不再进行初始化,
//那么我们可以讲一个局部的变量设置为一个静态的局部变量
//一个静态的变量,当函数进入的时候,当它完成第一次初始化之后,
//以后再进入的时候,这个变量就不会再重新构造了。
//因为当你第一次进入OnBtnAdd这个函数的时候,已经为这个静态的变量
//分配了内存空间了,以后就不会再重新分配了。
static BOOL bIsCreate=FALSE;
if(bIsCreate==FALSE)
{
m_btn.Create("维新",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0,100,100),this,123);
bIsCreate=TRUE;
}
else
{
m_btn.DestroyWindow();
bIsCreate=FALSE;
}    
}


//方法三:
void CTestDlg::OnBtnAdd() 
{
//最简单,最直接的方法
//这个就要你对MFC的窗口类了解之后,你才会想到用这样的一种方式去做一个判断
//先判断m_btn.m_hWnd的句柄是否为空,如果m_btn.m_hWnd为空,再加上“!”就为真
if(!m_btn.m_hWnd)
{
//如果这个句柄却是为空,我们就可以创建一下
m_btn.Create("维新",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0,100,100),this,123);
}
//否则我们就可以销毁窗口
else
{
m_btn.DestroyWindow();
}
}


4.通过点击,来改变静态文本框的内容:


//要改变静态文本的内容,那么首先应该获取现在的文本内容
//要获取窗口的文本,因为静态的文本框它也是一个窗口
//要获取这个窗口的文本,我们可以通过一个函数
void CTestDlg::OnNumber1() 
{


// TODO: Add your control notification handler code here


//要获取静态文本框控件的文本,所以首先我要获取和这个静态的文本框相对应的一个类的一个指针
    //然后通过这个指针去调用GetWindowText,获取它的文本
//GetDlgItem是获得指定控件的一个指针
//先获取静态文本框的文本,看他是否等于Number1
    CString str;
if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str=="Number1:")
{
//如果它等于Number1,我们就要去改变这个静态文本框的文本内容
//也就是我们要设置它窗口的文本可以利用SetWindowText
GetDlgItem(IDC_NUMBER1)->SetWindowText("数值1:");
}
else
{
GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1:");
}
//ClassWizard中的Number1里面选择属性->Styles中的Notify勾选上
    //对于一个静态的文本框来说,他是不能够接收通告消息的,
//只有当我们这个复选项复选上之后,它才能够接收点击的事件
    //所以想要一个静态的文本框响应这个命令点击,第一步就是将它的ID号改变一下
//然后就是要将属性->Styles中的Notify复选上



5.访问控件的方式:
编辑框中的加法运算
   
方法一:
void CTestDlg::OnBtnAdd() 
{
int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
    //编辑框内容的获取
GetDlgItem(IDC_EDIT1)->GetWindowText(ch1,10);
GetDlgItem(IDC_EDIT2)->GetWindowText(ch2,10);
//现在两个编辑框是文本的形式,也就是字符的形式
//我们需要将字符的内容转化成一个数值
    //字符到数值的转化函数:atoi
num1=atoi(ch1);
num2=atoi(ch2);
num3=num1+num2;
    //因为要把num1+num2的和的数值放到编辑框中,要将数值转化为文本内容
    itoa(num3,ch3,10);//10指的是十进制
   
GetDlgItem(IDC_EDIT3)->SetWindowText(ch3);
}


方法二:
void CTestDlg::OnBtnAdd() 
{
//GetDlgItemText函数是通过对话框中子控件的ID,来获取它的文本
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);
}
方法三:
void CTestDlg::OnBtnAdd() 
{
//GetDlgItemInt这个函数可以获取一个控件的文本,然后将它转换成一个整形返回
int num1,num2,num3;
num1=GetDlgItemInt(IDC_EDIT1);
num2=GetDlgItemInt(IDC_EDIT2);
        num3=num1+num2;
SetDlgItemInt(IDC_EDIT3,num3);
}


方法四:(最简单)
/*DoDataExchange是什么时候被调用的呢?
主要是由框架类调用的,用来交换和校验对话框的数据。*/


/*框架自动调用UpdateData,将这个参数bSaveAndValidate设置为FALSE,
当一个模态对话框被创建的时候。
当这个模态对话框被创建的时候,框架自动调用了UpdateData这个函数将
它的参数设置成了FALSE,所以对话框的编辑框才能收到我们在成员变量
当中设置的值.那么现在我们要从这个编辑框中获取数据,我们就需要
调用这个函数将参数bSaveAndValidate设置为真
*/
void CTestDlg::OnBtnAdd() 
{
    //我们可以将对话框上的三个编辑框控件分别关联三个成员变量
    //这样我们就可以用成员变量来操纵编辑框上面的数据了


    UpdateData();
m_num3=m_num1+m_num2;
/*将它的值设置为FALSE,也就是告诉对话框的控件,让它初始化,实际上
就是把成员变量当中的值,放置到编辑框当中
*/
UpdateData(FALSE);
}


方法五:
void CTestDlg::OnBtnAdd() 
{
    //关联一个控件变量,也就是代表控件本身
     int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];


//直接利用控件变量,利用它的成员函数GetWindowText,去获取窗口文本
//这是将控件关联了一个控件变量,可以直接利用它的函数来完成加法运算
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);
}


获取一个文本的消息
方法六:
void CTestDlg::OnBtnAdd() 
{
     int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
 //加上“::”表示我们调用的Win32的API函数,而不是我们类中的成员函数
 
//我们要获取的文本时编辑框的文本,因此我们的句柄是编辑框的句柄 
//那么编辑框的句柄如何来获取呢?
     //如果我们直接获取编辑框的句柄不太方便,那么我们就可以先获取和这个编辑框
//相对应的C++类的一个指针。那么我们知道,所以跟窗口相关的类,都有一个数据
//成员m_hWnd保存了和这个窗口相关的句柄,因此呢,在这个地方我们就可以用GetDlgItem
//先获取控件的指针,然后呢,利用这个指针获取它的句柄,消息是WM_GETTEXT
//wParam是指定你要拷贝的字符数,lParam是表示文本buffer,ch1是我们定义的字符
//数组,而这里的类型要的是LPARAM这个类型,因此要强制转换一下
//::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);//1


//可以直接用控件变量m_edit1,去调用它的句柄m_hWnd
     //::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);//2
 
//如果我们不是用Win32的API函数,也可以直接用CWnd的成员函数SendMessage去发送这个消息
     //先获取编辑框的控件的一个指针GetDlgItem(IDC_EDIT1),然后去调用SendMessage
     //GetDlgItem(IDC_EDIT1)->SendMessage(WM_GETTEXT,10,(LPARAM)ch1);//3
     m_edit1.SendMessage(WM_GETTEXT,10,(LPARAM)ch1);//4
//发送消息用以上四种形式都可以完成


m_edit2.SendMessage(WM_GETTEXT,10,(LPARAM)ch2);


num1=atoi(ch1);
num2=atoi(ch2);
num3=num1+num2;
itoa(num3,ch3,10);


//然后用m_edit3发送消息,获取文本的时候我们用的是WM_GETTEXT,设置文本用WM_SETTEXT
//wParam没有使用,必须为0,lParam是你所要设置的字符串
m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3);
}




方法七:
void CTestDlg::OnBtnAdd() 
{
    //获取文本复选内容的一个消息。
    //这种方式也是发送消息,但是它是直接给一个对话框的子控件发送消息.
    //有时候我们要获取复选的内容而不是获取整个窗口的内容。
    //获取复选的内容的一个消息EM_GETSELEM_SETSEL设置复选的开始位置和结束位置.
    //我们可以给编辑框三发送一个EM_SETSEL这样一个消息,去设置一个复选的部分
    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);
SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,0,-1);
//将编辑框三设置为当前编辑框所在
m_edit3.SetFocus();
}


/*总结:
1.GetDlgItem()->Get(Set)WindowText();
 利用GetDlgItem()去调用Get(Set)WindowText()获取/设置窗口文本
2.GetDlgItemText()/SetDlgItemText();
          GetDlgItem直接获取/设置一个对话框控件的文本
3.GetDlgItemInt()/SetDlgItemInt();
 获取/设置一个整形值
4.将控件和整形变量相关联,
5.将控件和控件变量相关联,
 然后利用控件本身的成员变量函数GetWindowTex()t和SetWindowText()分别去
 获取它的窗口文本和设置窗口文本。
        6.SendMessage();
 利用SendMessage发送一个消息,可以用Win32的API函数去调用SendMessage()
 也可以用CWnd的成员函数调用SendMessage()来发送一个消息,
7.SendDlgItemMessage();
 直接给对话框上面的子控件发送一个消息,用SendDlgMessage(),它的作用就相当于
          先调用SendDlgItem,再调用SendMessage是一样的。
*/




6.完对话框的收缩与扩展功能。


//对按钮点击响应的函数
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,"收缩<<");
}


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


}




7.在第一个编辑框中按“回车”的时候,我们的输入焦点转向下一个编辑框中.
修改编辑框控件的窗口过程


//OnOK是一个缺损按钮,按回车键就会响应,在此应将它注释起来.
void CTestDlg::OnOK() 
{
// TODO: Add extra validation here

// CDialog::OnOK();
}




//按回车键之后,从第一个编辑框的焦点跳到第二个编辑框
//窗口过程函数
WNDPROC prevProc;
LRESULT CALLBACK WinSunProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
if(uMsg==WM_CHAR && wParam==0x0d)
{
// ::SetFocus(::GetNextWindow(hwnd,GW_HWNDNEXT));//1
//SetFocus(::GetWindow(hwnd,GW_HWNDNEXT));//2
SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE));//3


return 1;
}
else
{
return prevProc(hwnd,uMsg,wParam,lParam);
}


}


//我们可以首先定义一个窗口过程类型
//先前的窗口过程


//我们可不可以改变编辑框这个操作,把它放到响应WMCreate响应函数当中
//要改变编辑框的窗口过程
BOOL CTestDlg::OnInitDialog() 
{
CDialog::OnInitDialog();

// TODO: Add extra initialization here
//接收一下
prevProc=(WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd,GWL_WNDPROC,
(LONG)WinSunProc);
return TRUE;  // return TRUE unless you set the focus to a control
             // EXCEPTION: OCX Property Pages should return FALSE
}


8.要想让这个焦点依次传递下去。
主要是利用缺损按钮响应函数
//OnOK是一个缺损按钮,按回车键就会响应,在此应将它注释起来
void CTestDlg::OnOK() 
{
// TODO: Add extra validation here

//GetDlgItem(IDC_EDIT1)->GetNextWindow()->SetFocus();//1
//错误原因:我们要获取当前具有焦点的指针
//GetFocus()->GetNextWindow()->SetFocus();//2
//错误原因:到了最后一个窗口,再获取下一个窗口,就无法获取它的下一个窗口了
    //这时候它获取到的指针就是空指针
    GetNextDlgTabItem(GetFocus())->SetFocus();
    //GetNextDlgTabItem会按照序号循环的查找这个窗口
// CDialog::OnOK();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值