Windows程序设计__孙鑫C++Lesson7《对话框操作1》
本节要点
1.对话框分类
2.对话框的产生
3.动态创建按钮
4.7种方法实现编辑框加法运算
5.伸缩对话框实现
6.编辑框输入焦点切换
//*****************************************************************************************************************
1.对话框分类
对话框分为模态和非模态对话框.
对话框资源和一个类相关联
对话框类的构造函数中CTestDlg::IDD=IDD_DIALOG1;
2.对话框的产生
模态对话框的产生 DoModal;EndDialog结束一个对话框。
非模态对话框创建用Create并用ShowWindow显示。注意对话框对象应该定义为成员变量而不是局部变量。点击OK时窗口并没有销毁,只是隐藏
非模态对话框显示:
CTestDlg* pDlg=new CTestDlg();
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);//pDlg指针应该声明为成员变量
3.动态创建按钮
重复创建Button出现错误,因为这个button已经和窗口绑定。
解决方法:
(1).设置一个布尔型成员变量或者静态局部布尔变量判断是否已经创建了。
(2).判断button的句柄是否为空(高级实现方法,理解句柄)。
动态创建按钮实验代码如下:
//**********************************************************************************
void CTestDlg::OnBtnAdd()
{
// TODO: Add your control notification handler code here
//重复创建解决方法一
/*
static BOOL m_bIsBtnCreate=FALSE;//静态局部变量
if(!m_bIsBtnCreate)
{
m_btn.Create("ButtonTest",WS_CHILD|WS_VISIBLE,CRect(0,0,50,50),this,111);
m_bIsBtnCreate=TRUE;
}
else
{
m_btn.DestroyWindow();
m_bIsBtnCreate=FALSE;
}
*/
//重复创建解决方法二 利用m_btn自己的成员变量m_hWnd
if(!m_btn.m_hWnd)
m_btn.Create("ButtonTest",WS_CHILD|WS_VISIBLE,CRect(0,0,50,50),this,111);
else
m_btn.DestroyWindow();
}
//**********************************************************************************************
4.7种方法实现编辑框加法运算
(1). 静态文本框起标记作用,控件ID默认为IDC_STATIC,特殊用途时需要改变其ID并且选中静态文本框的属性表中的Notify选项,然后添加消息响应。
(2).获取静态文本框的文本 首先获取指定控件的指针用GetDlgItem()函数,然后调用CWnd::GetWindowText函数。
(3).获取编辑框的数值 将数值字符装换为数值int型 使用atoi函数。
关联成员变量在DoDataExchange函数(被框架调用用来交换和验证数据的)中用DDX_Text(pDX, IDC_EDIT1, m_num1);实现关联
用DDV_MinMaxInt(pDX, m_num2, 0, 100);实现数据校验
(4)注意调用UpdateData函数获取和设置编辑框的值。
(5)编辑框文本全选 EM_SETSEL开始位置设置为0 未位置设置为-1.
编辑框加法运算的实现7中方法,实验代码如下:
//*******************************************************************************
//方法一
/*
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);//以10进制将数值转换到字符串中
GetDlgItem(IDC_EDIT3)->SetWindowText(ch3);
*/
//方法二
/*
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);
*/
//方法三
/*
int num1,num2,num3;
num1=(int)GetDlgItemInt(IDC_EDIT1,NULL,TRUE);
num2=(int)GetDlgItemInt(IDC_EDIT2,NULL,TRUE);
num3=num1+num2;
SetDlgItemInt(IDC_EDIT3,num3,TRUE);
*/
//方法四 关联变量
/*
UpdateData();
m_num3=m_num1+m_num2;
UpdateData(FALSE);
*/
//方法五
/*
int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
m_ctlEdit1.GetWindowText(ch1,10);
m_ctlEdit2.GetWindowText(ch2,10);
num1=atoi(ch1);
num2=atoi(ch2);
num3=num1+num2;
_itoa(num3,ch3,10);
m_ctlEdit3.SetWindowText(ch3);
*/
//方法六 消息方法
/*
int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
//发送消息方法
//::SendMessage(GetDlgItemText(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
//::SendMessage(m_ctlEdit1.m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
//GetDlgItemText(IDC_EDIT1)->SendMessage(WM_GETTEXT,10,(LPARAM)ch1);
m_ctlEdit1.SendMessage(WM_GETTEXT,10,(LPARAM)ch1);
m_ctlEdit2.SendMessage(WM_GETTEXT,10,(LPARAM)ch2);
num1=atoi(ch1);
num2=atoi(ch2);
num3=num1+num2;
_itoa(num3,ch3,10);
m_ctlEdit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3);
*/
//方法七 SendDlgItemMessage
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_ctlEdit3.SetFocus();
//*******************************************************************************
上述7种方法的总结,参见下图:
5.伸缩对话框实现(对话框切除与展开操作)
所谓的切除即在显示时重置其窗口区域大小
(1)Z-Order窗口次序
关于Z-Order窗口次序理解见下图:
(2)窗口分类
关于窗口分类理解见下图:
(3)重设窗口位置和大小
使用SetWindowPos函数实现对话框的位置和大小重置。
GetWindowRect和GetClientRect函数功能不同,在下面的OnBtnFold()函数中调用结果分别为,
GetWindowRect dialog 290,100,784,482;
GetWindowRect separator 309,371,769,373;//屏幕坐标
GetClientRect dialog 0,0,488,354;
GetClientRect separator 0,0,458,0;//客户区坐标
伸缩对话框实验代码如下:
//******************************************************************
void CTestDlg::OnBtnFold()
{
// TODO: Add your control notification handler code here
CString str;
static CRect rectLarge(0,0,0,0),rectSmall;
//初次操作时 对静态成员赋初值 这些值在后续操作中将不再改变
if(rectLarge.IsRectNull())
{
GetWindowRect(&rectLarge);
CRect rectSeparator;
GetDlgItem(IDC_SEPARATOR)->GetWindowRect(&rectSeparator);
rectSmall.left=rectLarge.left;
rectSmall.top=rectLarge.top;
rectSmall.right=rectLarge.right;
rectSmall.bottom=rectSeparator.bottom;
}
//根据 收缩或者扩展决定相应的操作
if( GetDlgItem(IDC_BTN_FOLD)->GetWindowText(str),str=="收缩<<" )
{
GetDlgItem(IDC_BTN_FOLD)->SetWindowText("扩展>>");
SetWindowPos(NULL,rectSmall.left,rectSmall.top,rectSmall.right-rectSmall.left,
rectSmall.bottom-rectSmall.top,SWP_NOMOVE|SWP_NOOWNERZORDER);//收缩对话框
}
else
{
GetDlgItem(IDC_BTN_FOLD)->SetWindowText("收缩<<");
SetWindowPos(NULL,rectLarge.left,rectLarge.top,rectLarge.right-rectLarge.left,
rectLarge.bottom-rectLarge.top,SWP_NOMOVE|SWP_NOOWNERZORDER);//扩展对话框
}
}
//*************************************************************************************
收缩状态运行效果如下图:
展开状态运行效果如下图:
6.编辑框输入焦点切换
方法一:SetWindowLong改变一个指定窗口的属性 重新设定窗口过程函数
代码如下:
//******************************************************************
WNDPROC prevproc;//指向窗口回调函数的指针 全局变量
LRESULT CALLBACK EditProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
prevproc=(WNDPROC)SetWindowLong(m_ctlEdit1.m_hWnd,GWL_WNDPROC,(LONG)EditProc);//重设窗口过程地址同时保存先前窗口过程地址
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//重载的窗口过程函数
LRESULT CALLBACK EditProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
if(WM_CHAR==uMsg && 0x0d ==wParam)
//::SetFocus(GetNextWindow(hwnd,GW_HWNDNEXT));
//::SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE) );
else
return prevproc(hwnd,uMsg,wParam,lParam);//调用原处理函数 注意return
return 0;
}
//**************************************************************************
:
方法二:在缺省按钮OK中重载OnOk函数
代码如下:
//******************************************************************
void CTestDlg::OnOK()
{
// TODO: Add extra validation here
//m_ctlEdit1.GetNextWindow()->SetFocus();
//GetFocus()->GetNextWindow()->SetFocus();
//GetFocus()->GetWindow(GW_HWNDNEXT)->SetFocus();
//GetNextDlgTabItem(GetFocus())->SetFocus();//查找具有Tabstop属性的控件 一次找 注意取消编辑框多行属性
//CDialog::OnOK();
}
//***********************************************************************************************************************************
本节小结:
1.认识模态与非模态对话框,能够产生。
2.能动态创建按钮,类推到动态创建其他控件。
3.通过编辑框7中方法实现加法,尤其是通过消息方法来实现平常比较少见。注意深刻体会MFC编程的方法和技巧,举一反三,此路不同另辟蹊径。
4.伸缩对话框的实现,了解窗口位置和种类。
5.通过SetWindowLong来实现更改窗口属性,重载窗口回调函数,这点很重要,注意在以后应用,再次理解回调函数的使用和消息机制。