模态对话框
资源添加对话框,双击对话框创建对话框类。
在
menu
中增加对话框菜单项,将其设为非
popup
的,并为其在
view
类下添加响应函数。
View
类中增加
#include “TestDlg.h”
。
在响应函数
void
CMyboleView::OnDialog()
中:
CTestDlg dlg;
dlg.DoModal();
模态对话框即程序运行到此处被阻滞,停在此处,不可以执行其他内容。
非模态对话框
CTestDlg m_dlg;
m_dlg .Create (IDD_DIALOG1,
this
); //this
为对话框父窗口的指针
m_dlg .ShowWindow (SW_SHOW);
注意:这里非模态对话框要设置为成员变量。另外非模态对话框点击非模态对话框的
OnOK
按纽时,它并没有关闭,而是隐藏了。需要调用
destroyWindow()
。
在对话框上动态创建一个
button
对象
在对话框资源中从工具中拖一个
button
到对话框中,将其名称改为
ADD
,为其在
CTestDlg
类中添加响应函数。
void
CTestDlg::OnBnClickedBtnAdd()
{
if(m_blsCreate==false) // m_blsCreate
是
bool
型成员变量判断是否已经创建
{
m_btn.Create (_T(
”
维新
”
),BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD,
CRect(0,0,100,100),
this
,123); //
动态创建
button
,其中
m_btn
为
CBtton
类型的成员变量
m_blsCreate=true;
}
else
{
m_btn.DestroyWindow ();
m_blsCreate=false;
}
}
另外
m_blsCreate
可以不定义为成员变量,而定义为
static bool blsCreate=false;
每个窗口都有一个
m_hWnd
的成员变量,当窗口被创建后
m_hWnd
为非零值,当窗口被销毁后(窗口类对象仍然存在)值为零,因此可以通过判断
m_hWnd
的方式来判断
button
对象是否被创建。
void
CTestDlg::OnBnClickedBtnAdd()
{
if
(!m_btn.m_hWnd )
{
m_btn.Create (_T(
”
维新
”
), BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),
this
,123);
}
else
{
m_btn.DestroyWindow ();
}
}
2
对话框加法操作
静态文本框
在对话框资源文件中从工具箱拖出三个静态文本框
Static Text
,将其名称改为
Number1
,
Number2
,
Number3
,将
ID
号改为
IDC_NUMBER1, IDC_NUMBER2, IDC_NUMBER3,
将
Notify
项设为
True
,如果不这么设置则无法接受相应消息。
在
CTestDlg
类中给文本框添加点击响应函数:
CString str;
if
(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str==_T(
“Number1”
))
{
GetDlgItem(IDC_NUMBER1)->SetWindowText(_T(
”
数值:
”
));
}
else
{
GetDlgItem(IDC_NUMBER1)->SetWindowText(_T(
“Number1”
));
}
注释:
GetDlgItem(IDC_NUMBER1)
通过对话框中的控件
ID
获取控件句柄
Cwnd*
。
GetWindowText(str)
拷贝控件的名称到
str
。
SetWindowText(_T(
”
数值:
”
))
设置控件名称。
对话框实现加法操作
在
CTestDlg::OnBnClickedBtnAdd()
函数中添加如下响应函数:
方法一:使用
GetDlgItem(),GetWindowText(),SetWindowText()
int num1,num2,num3;
TCHAR ch1[10], ch2[10], ch3[10];
GetDlgItem(IDC_EDIT1)->GetWindowText(ch1, 10);
GetDlgItem(IDC_EDIT2)->GetWindowText(ch2, 10);
num1 = _ttoi(ch1);
num2 = _ttoi(ch2);
num3 = num1 + num2;
_itot(num3, ch3,10);
GetDlgItem(IDC_EDIT3)->SetWindowText(ch3);
注释:
atoi(ch1)
将
char*
类型转换为
int
,
itoa
将
int
转换为
char*
,最后一个参数为转换进制数。
在VS2008中,
char 改成TCHAR
atoi 改成 _ttoi
itoa 改成 _itot
方法二:使用
GetDlgItemText()
和
SetDlgItemText()
int num1,num2,num3;
TCHAR ch1[10], ch2[10], ch3[10];
GetDlgItemText(IDC_EDIT1, ch1, 10);
GetDlgItemText(IDC_EDIT2, ch2, 10);
num1 = _ttoi(ch1);
num2 = _ttoi(ch2);
num3 = num1 + num2;
_itot(num3, ch3,10);
SetDlgItemText(IDC_EDIT3, ch3);
注释:
GetDlgItemText()
相当于
GetDlgItem(),GetWindowText()
的组合。
方法三:使用
GetDlgItemInt()
,
SetDlgItemInt()
int num1,num2,num3;
num1 = GetDlgItemInt(IDC_EDIT1);
num2 = GetDlgItemInt(IDC_EDIT2);
num3 = num1 + num2;
SetDlgItemInt(IDC_EDIT3, num3);
SetDlgItemInt(IDC_EDIT3,num3);
注释:
GetDlgItemInt(
int
nIDDlgItem
,
//
控件
id
BOOL *
lpTranslated
,
// success state
,默认为
NULL
,不警告任何错误
BOOL
bSigned
//
有符号或无符号,默认为真有符号
);
BOOL SetDlgItemInt(int nIDDlgItem,UINT uValue,BOOL bSigned);
方法四:关联成员变量法
UpdateData();
m_edit3 = m_edit1 + m_edit2;
UpdateData(FALSE);
m_cEdit1.GetWindowText(ch1, 10);
m_cEdit2.GetWindowText(ch2, 10);
num1 = _ttoi(ch1);
num2 = _ttoi(ch2);
num3 = num1 + num2;
_itot(num3, ch3,10);
m_cEdit3.SetWindowText(ch3);
方法五:发送消息
SendMessage
方法六:发送消息
SendDlgItemMessage
3
关联成员变量
资源文件中控件上右击添加变量,
private
,变量类型
int
,变量名:
m_num1,
控件类别将
control
改为
value
。
可以看到在代码中增加了如下内容:
CTestDlg.h
中:
private:
//
控件关联成员变量
int m_num1;
int m_num2;
int m_num3;
CTestDlg.cpp
中:
void
CTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_num1);
DDX_Text(pDX, IDC_EDIT2, m_num2);
DDX_Text(pDX, IDC_EDIT3, m_num3);
}
在
CTestDlg::OnBnClickedBtnAdd()
函数中添加如下响应函数:
UpdateData();
m_num3=m_num1+m_num2;
UpdateData(
false
);
注释:
UpdateData()
参数只有一个,默认为
TRUE
。为
TRUE
时刷新控件的值到对应的变量
(
外部输入值交给内部变量
)
。为
false
时拷贝变量值到控件显示
(
变量的最终运算结果值交给外部输出显示
)
。即初始化
设定值的范围
在函数
DoDataExchange
中
DDX_Text(pDX, IDC_EDIT1, m_num1);
语句后添加:
DDV_MinMaxInt(pDX,m_num1,0,100); //m_num
限定在
0
到
100
4
关联控件变量
资源文件中控件上右击添加变量,
private
,变量类型
CEdit
,变量名:
m_edit1,
控件类别为
control
。
可以看到在代码中增加了如下内容:
CTestDlg.h
中:
private:
//
控件关联成员变量
CEdit m_edit1;
CEdit m_edit2;
CEdit m_edit3;
CTestDlg.cpp
中:
void
CTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_edit1);
DDX_Control(pDX, IDC_EDIT2, m_edit2);
DDX_Control(pDX, IDC_EDIT3, m_edit3);
}
由于
CEdit
类型也是从
Cwnd
继承的,所以在
CTestDlg::OnBnClickedBtnAdd()
函数中添加如下响应函数:
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.SetWindowTextA (ch3);
5
发送消息
使用
SendMessage
函数
WM_GETTEXT
和
WM_SETTEXT
消息
在
CTestDlg::OnBnClickedBtnAdd()
函数中添加如下响应函数:
int
num1,num2,num3;
char
ch1[10],ch2[10],ch3[10];
//::SendMessageA(GetDlgItem(IDC_EDIT1)->m_hWnd ,
WM_GETTEXT
,
10, (LPARAM)ch1 );
//::SendMessageA(m_edit1->m_hWnd , WM_GETTEXT ,10,(LPARAM)ch1);
//GetDlgItem(IDC_EDIT1)->SendMessage (WM_GETTEXT,10,(LPARAM)ch1);
m_edit1.SendMessage (WM_GETTEXT,10,(LPARAM)ch1);
m_edit2.SendMessage (WM_GETTEXT,10,(LPARAM)ch2); //
第二个参数为发送数据量,第三个为接受数据的
buffer
num1=atoi(ch1);
num2=atoi(ch2);
num3=num1+num2;
itoa(num3,ch3,10);
m_edit3.SendMessage (WM_SETTEXT,0,(LPARAM)ch3);
使用
SendDlgItemMessage
函数
在
CTestDlg::OnBnClickedBtnAdd()
函数中添加如下响应函数:
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,10,(LPARAM)ch3);
使用
EM_SETSEL
消息设置复选信息
在上面代码后面加上:
SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,3);
m_edit3.SetFocus ();
< xmlnamespace prefix =”v” ns =”urn:schemas-microsoft-com:vml” />
SendDlgItemMessage
开始位置为
0
,结束位置为
-1
,可将整个框内数据复选上。
6
收缩扩展功能
添加分割线
在对话框窗口资源上加一个
picture control
画一条线,更改其属性,他的
ID
是
static
的,不能接受
notify
消息,将其改为
IDC_SEPARATOR
,
Sunken
设置为
true
,
visiable
设置为
false
。
添加
button
控制收缩
增加一个
button
,命名为
”
收缩
<<”
,并对其添加消息处理函数。
void
CTestDlg::OnBnClickedButton2()
{
CString str;
if
(GetDlgItemText(IDC_BUTTON2,str),str==
”
收缩《
”
)
{
SetDlgItemText(IDC_BUTTON2,
”
扩展》
”
);
}
else
{
SetDlgItemText(IDC_BUTTON2,
”
收缩《
”
);
}
static
CRect rectLarge;
static
CRect rectSmall;
//判定矩形是否为空,有两个方法
isRectNull 不考虑是否复合逻辑
isRecgEmpty
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.top ;
}
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
按下回车键自动转到下一个输入框
Ok
按钮是缺省的按钮,属性中
Default button
为
true
。当按下回车系统采用缺省的响应函数,处理回车消息,相当于按下
Ok
键。增加
ok
消息响应函数,在其中屏蔽对基类
CDialogEx::OnOK();
的调用。可以屏蔽掉回车的缺省实现。
传递输入焦点的方式,一种是为编辑框关联一个类,在类中捕获键盘按键消息,另外一种是自己编写过程函数,替换MFC默认的窗口过程函数。
窗口创建之后,利用
SetWindowLong()
改变窗口过程函数。然后在窗口过程中,捕获按键消息,并判断,移动焦点。
SetWindowLong()函数
在窗口创建完成之后,利用该函数修改窗口过程函数。该函数可以改变指定窗口的属性。
WM_INITDIALOG消息,是窗口以及子类控件创建完成之后,显示之前发送的一个消息。因此在此消息响应函数中,方式setwindowlong函数比较合适。
方法
1
:
改变控件的回调函数,注意
IDC_EDIT1
的
MultiLine
要复选上,这样才能响应回车操作。
WNDPROC prevProc;
LRESULT CALLBACK WinSunProc(
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)); //获取窗口句柄方法1
//SetFocus(::GetWindow(hwnd,GW_HWNDNEXT)); 获取窗口句柄方法2
CString str;
str.Format(“%d”,hwnd);
AfxMessageBox(str);//, UINT nType = MB_OK, UINT nIDHelp = 0 );
// AfxGetApp()->
SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE));//获取窗口句柄方法3
return 1;
}
else
{
return prevProc(hwnd,uMsg,wParam,lParam);
}
}
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TOD 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
}
方法
2
:
在
OnOK
响应函数中加入代码
//GetDlgItem(IDC_EDIT1)->GetNextWindow()->SetFocus();
//GetFocus()->GetNextWindow()->SetFocus();
//GetFocus()->GetWindow(GW_HWNDNEXT)->SetFocus();
GetNextDlgTabItem(GetFocus())->SetFocus(); //
焦点可以依次传递,查找完一遍不会出问题
2.逃跑按纽的实现
1.从CButton派生一个类,CWeixinBtn
2.将IDC_EDIT1关联成员变量m_btn1,类型为CWeixinBtn,注意要包含头文件。
3.在CWeixinBtn中加一个指针成员变量CWeixinBtn *pWeixinBtn,然后将其地址初始化。
4.在新类中增加鼠标移动的消息处理。
3.属性表单
1.插入属性页资源。Insert->new Resource->Dialog
2.当选择Classwizard菜单时,系统提示是否为创建新的类,我们将其从CPropertyPage派生!这样可以为
3.插入新的从CPropertySheet派生的类,在类中增加3个CPropertyPage的实例。
4.在view中增加菜单项,当点击时显示属性表单,出现中文乱码,修改CPropertyPage属性为中文,另外将
5.在CPropertyPage中设置SetWizardButtons可将其属性改为上一步、完成!
6.为IDC_RADIO1关联成员变量,需要先设置Group属性才行。另外别忘记调用UpdateData().
7.为CPropertyPage增加虚函数,OnWizardNext,如果用户点击下一步时,不想让他进入下一步,刚返回-1!
8.将用户的选择输出到屏幕上,此时可以在View中增加几个成员变量,用来接收用户选择的数据。
在VS2008中,方法一样,思路一样。不同的是,按照相同方法设计出来后,会有所需资源不可用的错误。解决办法:
用记事本打开.rc文件,把跟属性页相关的如下部分代码 及其对应的#endif删除
#if defined(APSTUDIO_INVOKED) || defined(PAGE2)
#if defined(APSTUDIO_INVOKED)
IDD_PROP2$(PAGE2) DIALOGEX 0, 0, 235, 156
#else
切记,代码块后面的#endif也要删除。一起删除三次。
VS中,是不会出现乱码的。不用设置字体。
建立属性对象后,创建属性窗口前,添加setWiardMode函数,即可变成向导。
做向导的时候我们想改变属性页按钮的功能 需要在三个属性页类中分别重写OnSetActive函数 在其中添加((CPropSheet *)GetParent())->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
GetParent()得到父窗口的指针,然后转换为属性表单指针,调用设置按钮函数。
Radio Button 是通过GROUP属性来划分组的 通过在具有组属性的按钮上添加一个成员变量 根据该变量的值来判断组里有谁被选中 注意 被关联的变量与控件间的数据交换需要地用
UpdateData函数参数为TRUE时是从控件中取回指 参数为FALSE是将成员变量的值赋予控件
要在点击下一步的时候判断RadioButton是否被选中 需要在该属性页的类中重写OnWizardNext函数
对于要在属性页的list里添加了内容 可以在OnInitDialog函数中写 该函数是用来相应WM_INITDIALOG消息的 该消息是在对话框将要显示之前发送的 在VC6++中是通过添加消息映射函数建立该函数的 而在VS2008中 则是通过重写
MFC中对控件操作都是通过调用相关的类 比如list box控件 就要用CListBox类 然后可以通过得到控件指针的函数 GetDlgItem 来操作
如:
((CListBox *)GetDlgItem(IDC_LIST1))->AddString(L”枫江”);
判断list box中的选项是否被选择的方法 也是关联一个成员变量 CString类型的 如果为空 则未选择
Combo Box的Sort属性选FALSE 就不会自动排序了
可以用CComboBox的一个成员函数SetCurSel来进行缺省的设置
然后用getTBText函数,完成对索引值内容的读取。
*VS2008中 添加数组变量 方法举例
类型 int (&)[10]
名字 m
但是 添加进去之后最好还是改成 int m[10]的形式