我们我们在菜单中添加一个菜单项,然后在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();
}