对话框的创建
资源添加对话框,双击对话框创建对话框类。
在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到对话框中,将其名称改为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 ();
}
}
在对话框资源文件中从工具箱拖出三个静态文本框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
资源文件中控件上右击添加变量,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
资源文件中控件上右击添加变量,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);
在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);
在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);
在上面代码后面加上:
SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,3);
m_edit3.SetFocus ();
< xmlnamespace prefix ="v" ns ="urn:schemas-microsoft-com:vml" />
SendDlgItemMessage开始位置为0,结束位置为-1,可将整个框内数据复选上。
在对话框窗口资源上加一个picture control画一条线,更改其属性,他的ID是static的,不能接受notify消息,将其改为IDC_SEPARATOR,Sunken设置为true,visiable设置为false。
增加一个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);
}
}
Ok按钮是缺省的按钮,属性中Default button为true。当按下回车系统采用缺省的响应函数,处理回车消息,相当于按下Ok键。增加ok消息响应函数,在其中屏蔽对基类CDialogEx::OnOK();的调用。可以屏蔽掉回车的缺省实现。
传递输入焦点的方式,一种是为编辑框关联一个类,在类中捕获键盘按键消息,另外一种是自己编写过程函数,替换MFC默认的窗口过程函数。
窗口创建之后,利用
SetWindowLong()改变窗口过程函数。然后在窗口过程中,捕获按键消息,并判断,移动焦点。
SetWindowLong()函数
在窗口创建完成之后,利用该函数修改窗口过程函数。该函数可以改变指定窗口的属性。
WM_INITDIALOG消息,是窗口以及子类控件创建完成之后,显示之前发送的一个消息。因此在此消息响应函数中,方式setwindowlong函数比较合适。
改变控件的回调函数,注意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
}
在OnOK响应函数中加入代码
//GetDlgItem(IDC_EDIT1)->GetNextWindow()->SetFocus();
//GetFocus()->GetNextWindow()->SetFocus();
//GetFocus()->GetWindow(GW_HWNDNEXT)->SetFocus();
GetNextDlgTabItem(GetFocus())->SetFocus(); //焦点可以依次传递,查找完一遍不会出问题
#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]的形式