在MFC中,我们对资源的操作是通过对与之相关联的对象的操作来实现的。
CDialoge类是从CWnd类派生而来的。
不切模:如果我们不对模态对话框操作,程序将不往下执行。
CDialog::DoDataExchange()函数
一、模态对话框:其的创建:CDialog::DoModal()
其的关闭:CDialog::EndDialog() <其实是隐藏,直到其所在消息处理函数返回时才关闭。>
模态对话框注意事项:因为virtual void CDialog::OnOk()是虚函数,对于模态对话框,我们要重载OnOk()函数,并使其内部调用CDialog::DestroyWindow()函数,以销毁对话框;如果我们不重载它,点击ok则会调用基类的ONOK()函数,而基类的该函数中调用的是EndDialog()函数,它仅仅是隐藏该模态对话框。
二、非模态对话框:其的创建:CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
创建后还需显示之,应用CDialog::ShowWindow()
非模态对话框局部对象在函数返回时被析构的问题的解决:1、在堆中给非模态对话框对象分配一段内存;
2、将CTestDlg类对象定义成类的成员变量。
virtual void CWnd::DoDataExchange( CDataExchange* pDX)函数 ,是被框架调用的 ,用于交换和校验对话框数据的;该函数中包含着DDX_Text()、DDV_Text()等函数,其中DDX_函数用于将子控件和对象变量关联的,DDV_函数用于数据的校验,如限定数值的范围等;
BOOL CWnd::UpdateData( BOOL bSaveAndValidate = TRUE );参数为真,值从外向内传;参数为假时,值从内向外传;
虚函数:我们一般要重新定义基类的虚函数。
动态添加按钮:可调用函数BOOL CButton::Create( LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ),如果我们在第二个参数中没有设置WS_VISIBLE标记,则在紧挨的下面一行代码要调用ShowWindow()函数将创建的按钮显示出来。
注意:当我们多次创建同一个窗口资源和一个窗口对象相关联,即一个窗口对象只能和一个窗口资源相关联;即使是同一个窗口对象同一个窗口资源,他们也只能被关联一次。
(要想“多次关联”,在每次关联前,确保窗口的已被销毁)
资源ID号和资源的句柄是不同的;
每个窗口类CWnd的对象都有一个m_hWnd成员函数,其存放与之相关的窗口资源的句柄;如果窗口类对象还没有和任何窗口资源相关联,则其值为空(即NULL)。
按住ctrl键拖动控件,可以完成对该控件的复制;当我们改变静态文本框的ID
函数CWnd* CWnd::GetDlgItem(int nID)一般用于对话框类中,用于获取(通过资源的ID)对话框中子控件的对象的指针
void CWnd::GetWindowText( CString& rString )函数,得到窗口的文本。
函数BOOL CWnd::SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)用于改变窗口的尺寸、位置,z序。
函数SendDlgItemMessage()是给一个控件发送消息。
一个静态文本控件一般是不能接受通道消息的,为了使其能够接受并响应通道消息,我们需要做:1、改变默认的资源ID; 2、在其属性框中,选中Notify复选框;
atoi()函数用于将数字字符串转换成整型,如11=atoi("11");
itoa()函数用于将整型转换成数字字符串,如void itoa(num3,ch3,10)<第三个参数表示数的进制,ch3是一个缓冲区指针,num3是要转化的整形数据>
int CWnd::GetDlgItemText( int nID, LPTSTR lpStr, int nMaxCount )函数的作用相当于GetDlgItem(int nID)->GetWindowText(CString& rString) ;
而int CWnd::SetDlgItemText( int nID, LPTSTR lpStr, int nMaxCount )函数的作用相当于GetDlgItem(int nID)->SetWindowText(CString& rString)
UINT CWnd::GetDlgItemInt( int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE ) const,是获取(通过ID)对话框的子控件的(数字字符串)文本,并将其转化成整型数据;第一个参数是子控件的ID,第二个参数是用于是否有错误发生,例如当窗口的文本中含有非数字字符时,就将第二个参数指向的内容赋值为0,若没错误发生其值为非0;第三个参数用于标记我们要转换的数字字符串是否有'-'字符。
函数UINT CWnd::SetDlgItemInt( int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE )
让控件发送消息可以使用: 1、LRESULT CWnd::SendMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 ),即Cwnd的成员函数,其中UINT message是WM_GETTEXT,或WM_SETTEXT等;
(此处发送的是文本消息) 2、使用平台的函数,即 ::SendMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
(此处的机理是:给我们要获取文本的控件发送消息,并提供一个buffer,Windows的默认的消息处理机制,将会将我们需要的文本放入我们提供的buffer中)
注:此处完成消息发送的过成,就自动完成了相应的目的,如设置文本,得到文本等。
函数Cwnd::SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0 )相当于GetDlgItem(int nID)->SendMessage();
CRect::IsRectEmpty()和CRect::IsRectNull()都能判断矩形区域是否为空,但IsRectEmpty()是判断矩形的宽和高是否为空,而IsRectNull()是用于判断top, bottom, left, and right四个成员变量是否为零;有时IsRectEmpty()较IsRectNull()
void CWnd::GetWindowRect( LPRECT lpRect ) 用于获取窗口矩形的大小;
picture控件中的style属性中的sunken属性被选中,表明,此控件内嵌,下陷;
在对话框中,如果将某个按钮的属性设置为default button,我们在对话框中按回车,就触发该按钮的通道消息;
对于编辑框控件,如果我们不设置它的Multiline属性(多行输入),它是不会接受回车的;
函数CWnd::SetFocus()和CWnd::GetFocus()的区别:SetFocus()用于设置让某窗口获取输入焦点;GetFocus()函数是得到当前拥有输入焦点的窗口对象的指针;
要实现“当按下回车,输入提示符,从一个编辑框到另一个编辑框”功能,我们可以:1、通过捕获键盘消息来完成 2、窗口的消息处理函数是一个全局的函数,所以,我们不能使用Cwnd的成员函数,只能使用平台SDK的函数;所有的消息都要
每一个窗口都有自己的窗口过程函数,当然,编辑框也有;我们可以用自己定义的窗口过程函数来代替MFC为我们提供的窗口过程函数.
一个窗口过程函数是在窗口类定义的时候指定的,为了在窗口类定义后指定窗口过程函数,我们可以使用函数平台函数LONG SetWindowLong(HWND hWnd, // handle to window 要改变窗口过程函数的窗口的句柄
int nIndex, // offset of value to set 一个偏移量(也就是此函数一组功能的选择项)
LONG dwNewLong) // new value 当第二个参数是GWL_WNDPROC时,该参数为我们定义的窗口过程函数的地址
LONG SetWindowLong()函数的返回值是先前(一般情况下是MFC给我们提供的)的窗口处理函数的地址;该函数两处需要强制类型转换,第三个参数和返回值。
我们一般把改变窗口过程函数的代码放在OnInitDialog()函数中,而不放在OnCreate()函数中,因为在OnCreate()函数调用时,只是创建了对话框,而对话框上的子控件还没有创建,SetWindowLong()函数的第一个参数就无从谈起了;而调用OnInitDialog()函数时,对话框和其上控件已经在内存中创建完毕。
我们新定义的窗口过程函数只捕捉我们感兴趣的消息,而其余消息仍交由原窗口过程函数来处理。
GetDlgItem()->Get(Set)WindowText() GetDlgItemText()/SetDlgItemText() GetDlgItemInt()/SetDlgItemInt()
函数SetDlgItemText()获取对话框上子控件的文本;
void CWnd::GetDlgItem( int nID, HWND* phWnd )函数是,得到对话框上的子控件(即子窗口)的 指针;
A、平台SDK的几个函数:1、HWND SetFocus()要获取输入焦点的窗口的句柄;2、HWND GetNextWindow(HWND hWnd,UINT wCmd)函数用于获取当前窗口的下一个窗口的句柄,第一个参数是当前窗口的句柄,第二个是方向,或者向前(上一个),或者向后(下一个);
3、HWND GetWindow(HWND hWnd, // handle to original window
4、HWND GetNextDlgTabItem(HWND hDlg, // handle to dialog box
UINT uCmd) // relationship 因其第二个参数的供选项较多,其功能较第二个函数要强大的多
HWND hCtl, // handle to known control
BOOL bPrevious) // direction flag //函数说明:得到下一个具有Tab stop属性的窗口的句柄
B、以上几个函数在Cwnd类中也都有,一般情况下使用的都是类Cwnd的成员函数;而在窗口过程函数中,因窗口过程函数是全局函数,所以其中使用的函数都应是全局函数,或者是SDK函数。
C、只有当控件中的Tab Stop属性选中,才能参与GetNextDlgTabItem()函数"Next";且本函数是循环使用的。
应用平台的函数是我们在之前加::;而使用全局的函数时,我们用的是Afx××××();
回车的ASC码是0x0d
缺省的按键响应:不管我们的对话框上有没有缺省的OK按钮,系统都会调用ONOK()函数(此处的ONOK函数是ID为IDOK的缺省按钮的消息响应函数,刚创建的对话框上总是有此按钮的)对缺省的按键消息(即按下回车)进行响应;当让,对话框上的其他按钮的default button属性没被选中。
当我的当前窗口是对话框资源的编辑窗口是,vc的菜单中会动态的出现一个layout子菜单。
SetFocus 方法:将输入焦点设向控件; 函数GetFocus :取得当前具有焦点的那个窗口的句柄。
成员函数:
static CWnd* PASCAL CWnd::GetFocus( ); //当前拥有输入焦点的窗口的指针;
CWnd* CWnd::SetFocus( ); //返回值为先前拥有输入焦点的窗口指针;
平台函数:
HWND GetFocus(VOID);
HWND SetFocus(HWND hWnd); // handle to window
-------------------------------------------------------------------------------------------------
创建模态对话框
#include "TestDlg.h" //要添加进来
void CMyboleView::OnDialog()
{
// TODO: Add your command handler code here
//模态对话框的创建
CTestDlg dlg; //为我们创建得对话框添加类,需要为对话框建立一个单独的类,即一个新文件
dlg.DoModal(); //DoModal()函数具有在创建模态对话框的同时,显示对话框的功能
//非模态对话框的创建模态对话框和非模态对话框的区别有点像窗口的动、静态分割)
CTestDlg *pDlg=new CTestDlg(); //不能设为局部对象,指针会知道整个程序结束才结束生命周期,但p227
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);
}
------------------------------------------------------------------------------------------------
动态创建按钮——以模态对话框为例(非模态效果也一样)
void CTestDlg::OnBtnAdd()
{
// TODO: Add your control notification handler code here
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;
}
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();
}
//第二种方法
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();
}
}
------------------------------------------------------------------------------------------------
对静态文本控件进行消息处理--1.需将IDC_STATIC改名,例如改成IDC_NUMBER1 2。在属性中选中Notify
void CTestDlg::OnNumber1()
{
// TODO: Add your control notification handler code here
CString str;
if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str=="Number1:")//GetDlgItem获取控件对象,看逗号后
{ //GetWindowText获取控件上的文本
GetDlgItem(IDC_NUMBER1)->SetWindowText("数值1:"); //SetWindowText设置控件的文本
}
else
{
GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1:");
}
}
--------------------------------------------------------------------------------------------------
编辑框控件的七种访问方式——求两个数的和
void CTestDlg::OnBtnAdd()
{
// TODO: Add your control notification handler code here
//一、使用函数GetDlgItem()、GetWindowText()、SetWindowText()
int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
GetDlgItem(IDC_EDIT1)->GetWindowText(ch1,10); //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);
//二、使用函数GetDlgItemText()、SetDlgItemText()
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);
//三、使用函数GetDlgItemInt()、SetDlgItemInt()
int num1,num2,num3;
num1=GetDlgItemInt(IDC_EDIT1);
num2=GetDlgItemInt(IDC_EDIT2);
num3=num1+num2;
SetDlgItemInt(IDC_EDIT3,num3);
//四、直接将编辑框控件与一个整型变量相关联, 输入非数字会提示错误
UpdateData(); //使DoDataExchange生效
m_num3=m_num1+m_num2; //在DoDataExchange中进行关联,在构造函数里全初始化为0
UpdateData(FALSE);
//五、将编辑框控件与一个控件对象变量Control相关联
int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
m_edit1.GetWindowText(ch1,10); //在DoDataExchange中进行关联
m_edit2.GetWindowText(ch2,10);
num1=atoi(ch1);
num2=atoi(ch2);
num3=num1+num2;
itoa(num3,ch3,10);
m_edit3.SetWindowText(ch3);
//六、通过消息机制(1、使用平台函数;2、使用Cwnd的成员函数:a、通过GetDlgItem(),b、通过和控件相关的控件变量;) 一控件获取其他控件内容的方式
int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1); //使用平台的函数
::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
GetDlgItem(IDC_EDIT1)->SendMessage(WM_GETTEXT,10,(LPARAM)ch1); //或使用Cwnd的成员函数
m_edit1.SendMessage(WM_GETTEXT,10,(LPARAM)ch1);
m_edit2.SendMessage(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);
//七、使用Cwnd::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); //EM_SETSEL即,设置编辑框中文本被选中(即变蓝)),此处后两个参数设置为0,-1表明选中整个编辑框的文本;1,3则代表第二、三个数字
m_edit3.SetFocus(); */ //变蓝只能在获取输入焦点的情况下才能进行
}
-------------------------------------------------------------------------------------------------
对话框伸缩功能的实现
void CTestDlg::OnButton2()
{
// TODO: Add your control notification handler code here
CString str;
if(GetDlgItemText(IDC_BUTTON2,str),str=="收缩<<")
{
SetDlgItemText(IDC_BUTTON2,"扩展>>");
}
else
{
SetDlgItemText(IDC_BUTTON2,"收缩<<");
}
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);
}
}
-------------------------------------------------------------------------------------------------
输入焦点的传递:情形一:只能实现从第一个跳到第二个
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)); //方法一
SetFocus(::GetWindow(hwnd,GW_HWNDNEXT)); //方法二
SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE)); //方法三、此处hwnd是编辑框的句柄,通过GetParent()函数即可获取其父窗口对话框的句柄;
return 1;
}
else
{
return prevProc(hwnd,uMsg,wParam,lParam); //其它字符还是交给默认的处理函数
}
}
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
}
-------------------------------------------------------------------------------------------------
情形二:焦点依次向下传递
void CTestDlg::OnOK() //该函数是缺省的按键(按回车)响应函数
{
// TODO: Add extra validation here
//GetDlgItem(IDC_EDIT1)->GetNextWindow()->SetFocus(); //只能实现从第一个跳到第二个
//GetFocus()->GetNextWindow()->SetFocus(); 会出现非法访问
//GetFocus()->GetWindow(GW_HWNDNEXT)->SetFocus(); 会出现非法访问
GetNextDlgTabItem(GetFocus())->SetFocus();//注意此处是GetFocus(),只这一句就实现依次向下传递
CDialog::OnOK();
}
0 0