我们我们在菜单中添加一个菜单项,然后在VIEW类中为其添加消息响应函数:建立一个CTestDlg对象,调用DoModal函数来实现模态对话框:
void CCH_7_DialogView::OnDialog() { // TODO: Add your command handler code here CTestDlg dlg; dlg.DoModal(); }注意,我们还得自己包含#include "TestDlg.h",因为这句代码类向导并没有帮我们添加。
CTestDlg dlg; dlg.Create(IDD_DIALOG1,this); dlg.ShowWindow(SW_SHOW
CTestDlg *pDlg = new CTestDlg; pDlg->Create(IDD_DIALOG1,this); pDlg->ShowWindow(SW_SHOW);虽然这样做可以实现功能,但是并不好,因为pDlg会在程序结束时被释放,所以我们以后就拿不到这个指针了,自然也就无法释放它,会造成内存泄露。这个问题可以通过将指针定义为类的成员变量来解决。
void CTestDlg::OnBtnAdd() { // TODO: Add your control notification handler code here m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123); }我们发现,程序运行时,当我们点击Add按钮,的确会显示一个新的按钮,但是我们再次点击,程序就会错误,这是因为,当点击时,会调用OnBtnAdd,这个函数调用Create函数创建了一个按钮;但是如果你又点击一次,那么还会调用Create函数将按钮与m_btn关联,可是m_btn已经和第一次创建的按钮相关联了,所以会出错。为此,我们可以增加一个成员变量m_bIsCreate来记录窗口是否已经创建,如果创建,那么就会销毁窗口,而在下一次点击时,又能创建了:
void CTestDlg::OnBtnAdd() { // TODO: Add your control notification handler code here if(m_bIsCreate == FALSE) { m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123); m_bIsCreate = TRUE; } else { m_btn.DestroyWindow(); m_bIsCreate = FALSE; } }其实这里还有一个简单的办法,并不使用成员变量,而是用静态局部变量也能解决这个问题。
if(!m_btn.m_hWnd) { m_btn.Create("TEST",BS_DEFPUSHBUTTON | WS_VISIBLE|WS_CHILD, CRect(0,0,100,100),this,123); } else { m_btn.DestroyWindow(); }
void CTestDlg::OnNumber1() { // TODO: Add your control notification handler code here CString str; if(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str == "Number1") { GetDlgItem(IDC_NUMBER1)->SetWindowText("数值1"); } else { GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1"); } }但是程序运行以后并没有反应,原因是因为静态文本控件在默认状态下,是不接收通告消息的:我们得在这个控件的属性->样式中,把通知选上,就行了。可见,为了让静态文本框响应消息,需要两个特殊的步骤:1.改变它的ID。2.在它的样式中,选择通知消息。
void CTestDlg::OnBtnAdd() { // TODO: Add your control notification handler code here 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); GetDlgItem(IDC_EDIT3)->SetWindowText(ch3); }这种方法思路清晰:定义的3个字符串和3个int。将编辑框中的字符串获取出来以后转化为int,然后做加法,做完以后转化回去,然后显示在编辑框上。
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 = GetDlgItemInt(IDC_EDIT1); num2 = GetDlgItemInt(IDC_EDIT2); num3 = num1 + num2; SetDlgItemInt(IDC_EDIT3,num3);第四种:
// Dialog Data //{{AFX_DATA(CTestDlg) enum { IDD = IDD_DIALOG1 }; int m_num1; int m_num2; int m_num3; //}}AFX_DATA源文件的构造函数中:
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/) : CDialog(CTestDlg::IDD, pParent) { //{{AFX_DATA_INIT(CTestDlg) m_num1 = 0; m_num2 = 0; m_num3 = 0; //}}AFX_DATA_INIT }在源文件的DoDataExchange中:
void CTestDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CTestDlg) DDX_Text(pDX, IDC_EDIT1, m_num1); DDX_Text(pDX, IDC_EDIT2, m_num2); DDX_Text(pDX, IDC_EDIT3, m_num3); //}}AFX_DATA_MAP }
void CTestDlg::OnBtnAdd() { m_num3 = m_num1 + m_num2; }
UpdateData(); m_num3 = m_num1 + m_num2; UpdateData(FALSE);
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.SetWindowText(ch3);第六种方式:
int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; ::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10, (LPARAM)ch1); ::SendMessage(m_edit2.m_hWnd,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);
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,1,2); m_edit3.SetFocus();
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 ); }
void CTestDlg::OnOK() { // TODO: Add extra validation here CDialog::OnOK(); }
WNDPROC prevProc;//声明先前的消息响应函数 //新的消息处理函数 LRESULT CALLBACK NewEditProc( 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)); 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)NewEditProc); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }SetWindowLong函数的返回值就是了!
::SetFocus(::GetWindow(hwnd,GW_HWNDNEXT));最后介绍一种获得获得窗口句柄的方法:GetNextDlgTabItem。这个函数返回一个指定控件前面后者后面的一个具有WS_TABSTOP风格的控件。那么什么是WS_TABSTOP风格呢?对于按钮的属性,都有制表站这一项,如果选上了,就有这个风格,如果没选,就没有。
::SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,FALSE));说了这么多,其实这些方法都很麻烦:你得为每个控件写一推代码,有没有简单的方法呢?
void CTestDlg::OnOK() { // TODO: Add extra validation here GetFocus()->GetNextWindow()->SetFocus(); // CDialog::OnOK(); }
void CTestDlg::OnOK() { // TODO: Add extra validation here GetNextDlgTabItem(GetFocus())->GetNextWindow()->SetFocus(); // CDialog::OnOK(); }