📄 visual c++ mfc 简明教程.doc
字号:
// Create the window itself
Create(NULL,
"CButton Tests",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
// Get the size of the client rectangle
GetClientRect(&r);
r.InflateRect(-20,-20);
// Create a button
button = new CButton();
button->Create("Push me",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
r,
this,
IDB_BUTTON);
}
主要修改了三个方面:
CButtonWindow的类说明现在包含了一个新的成员函数和一个新的表示消息映射的宏。HandleButton函数是正常的C++函数,它通过afx_msg标签确定为消息处理函数。该函数需要一些特殊的约束,例如,它必须是void型并且它不能接收任何参数。DECLARE_MESSAGE_MAP宏建立了消息映射。函数和宏都必须是public型的。
HandleButton函数作为成员函数以同样的方式来建立。在该函数中,我们调用了Windows API中的MessageBeep函数。
用宏来建立消息映射。在代码中,你可以看见BEGIN_MESSAGE_MAP宏接收两各参数。第一个指定了使用消息映射的类的名称。第二个是基类。然后是ON_BN_CLICKED宏,接受两个参数控制的ID和该ID发送命令消息时所调用的函数。最后,消息映射用END_MESSAGE_MAP来结束。
当用户单击按钮时,它向其包含该按钮的父窗口发送了一个包含其ID的命令消息。那是按钮的缺省行为,这就是该代码工作的原因。按钮向其父窗口发送消息,是因为它是子窗口。父窗口截取该消息并用消息映射来确定所要调用的函数。MFC来安排,只要指定的消息一出现,相应的函数就会被调用。
ON_BN_CLICKED消息是CButton发送的唯一感兴趣的消息。它等同于CWnd中的ON_COMMAND消息,只是一个更简单方便的同义词而已。
改变大小的消息
在上面的代码中,由于有了消息映射,从CFrameWnd继承来的应用程序窗口认出按钮有按钮产生的单击消息并响应之。加入消息映射的ON_BN_CLICKED宏指定了按钮的ID和窗口在接收到来自按钮的命令消息时应调用的函数。因为只要用户单击了按钮,按钮就会自动把其ID发送父窗口,这样才能允许代码正确地处理按钮事件。
作为该应用程序的主窗口的框架窗口自己也有传递消息的能力。大约有100不同的消息可用,它们都是从CWnd类继承来的。从MFC帮助文件中浏览CWnd类的成员函数,你就会看到所有的这些消息。查看所有以“On”开头的成员函数。
你可能已经注意到了,至今为止所有的代码都不能很好地处理尺寸变化。当窗口变化大小时,窗口的框架会做相应的调整,但是窗口中调的内容仍原处不动。可以通过处理尺寸变化的事件来更好的处理这一问题。任何窗口发送的消息之一就是变尺寸消息。该消息是当改变形状时发出的。我们可以使用该消息来控制框架中子窗口的大小,如下所示:
// button3.cpp
#include <afxwin.h>
#define IDB_BUTTON 100
// Declare the application class
class CButtonApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
// Create an instance of the application class
CButtonApp ButtonApp;
// Declare the main window class
class CButtonWindow : public CFrameWnd
{
CButton *button;
public:
CButtonWindow();
afx_msg void HandleButton();
afx_msg void OnSize(UINT, int, int);
DECLARE_MESSAGE_MAP()
};
// A message handler function
void CButtonWindow::HandleButton()
{
MessageBeep(-1);
}
// A message handler function
void CButtonWindow::OnSize(UINT nType, int cx,
int cy)
{
CRect r;
GetClientRect(&r);
r.InflateRect(-20,-20);
button->MoveWindow(r);
}
// The message map
BEGIN_MESSAGE_MAP(CButtonWindow, CFrameWnd)
ON_BN_CLICKED(IDB_BUTTON, HandleButton)
ON_WM_SIZE()
END_MESSAGE_MAP()
// The InitInstance function is called once
// when the application first executes
BOOL CButtonApp::InitInstance()
{
m_pMainWnd = new CButtonWindow();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
// The constructor for the window class
CButtonWindow::CButtonWindow()
{
CRect r;
// Create the window itself
Create(NULL,
"CButton Tests",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
// Get the size of the client rectangle
GetClientRect(&r);
r.InflateRect(-20,-20);
// Create a button
button = new CButton();
button->Create("Push me",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
r,
this,
IDB_BUTTON);
}
为了理解上面的代码,从窗口的消息映射开始。你会发现入口ON_WM_SIZE。该入口表示消息映射是对来自CButtonWindow对象的变尺寸消息发生响应。变尺寸消息是当用户改变窗口的大小时产生的。该消息来自窗口本身,而不是作为ON_COMMAND消息由按钮向其父窗口发送的。这是因为窗口框架不是子窗口。
要注意的是消息映射中的ON_WM_SIZE入口没有参数。你在MFC文档中CWnd类,消息映射中的ON_WM_SIZE入口总是调用OnSize函数,并且该函数必须接收三个参数。OnSize函数必须是消息映射所属类的成员函数,并且该函数必须用afx_msg来说明(正如上面在CButtonWindow的定义中所见到的一样)。
如果你查看MFC文档,就会发现CWnd中有近100名为“On...”的函数。CWnd::OnSize是其中之一。所有这些函数都在消息映射中有形如ON_WM_对应的标签。例如,ON_WM_SIZE对应OnSize。ON_WM_入口不接收任何参数,如ON_BN_CLICKED一样。参数是假设的并自动传递给相应的如OnSize的“On...”函数。
重复一遍,因为它很重要: OnSize函数总是与消息映射中的ON_WM_SIZE入口想对应。你必须命名处理函数OnSize, 并且它必须接收三个参数。不同的函数的参数会有所不同。
上面的代码中在OnSize函数自身的内部,有三行代码修改了按钮在窗口中的尺寸。你可以在该函数中输入任何你想要的代码。
调用GetClientRect是为了恢复窗口用户区域的新尺寸。该矩形会被缩小,并调用按钮的MoveWindow函数。MoveWindow是从CWnd继承来的,改变尺寸和移动子窗口是在一步完成的。
当你执行上面改变窗口大小的程序时,你就会发现按钮自己能正确地改变大小。在代码中,变尺寸事件他国消息映射中的OnSize函数而产生一调用,它调用MoveWindow函数来改变按钮的大小。
窗口消息
查看MFC文档,你可以看到主窗口处理的各种各样的CWnd消息。有些与我们上面介绍的类似。例如,ON_WM_MOVE消息是当用户移动窗口时发送的消息,ON_WM_PAINT消息是当窗口的任何部分需要重画时发出的。至今为止,我们的所有程序,重画工作都是自动完成的,因为是控制自己来负责其外观。如果你自己使用GDI命令来在用户区域中绘制,应用程序就应负责重画工作。因此ON_WM_PAINT就变得重要了。
还有一些发送给窗口的事件消息更深奥。例如,你可以使用ON_WM_TIMER消息与SetTimer函数来使接收预先设置的时间间隔。下面的代码给出了该过程。当你运行该代码时,程序会每隔1秒钟鸣笛一声。你可以用其它更有用的功能来代替鸣笛。
// button4.cpp
#include <afxwin.h>
#define IDB_BUTTON 100
#define IDT_TIMER1 200
// Declare the application class
class CButtonApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
// Create an instance of the application class
CButtonApp ButtonApp;
// Declare the main window class
class CButtonWindow : public CFrameWnd
{
CButton *button;
public:
CButtonWindow();
afx_msg void HandleButton();
afx_msg void OnSize(UINT, int, int);
afx_msg void OnTimer(UINT);
DECLARE_MESSAGE_MAP()
};
// A message handler function
void CButtonWindow::HandleButton()
{
MessageBeep(-1);
}
// A message handler function
void CButtonWindow::OnSize(UINT nType, int cx,
int cy)
{
CRect r;
GetClientRect(&r);
r.InflateRect(-20,-20);
button->MoveWindow(r);
}
// A message handler function
void CButtonWindow::OnTimer(UINT id)
{
MessageBeep(-1);
}
// The message map
BEGIN_MESSAGE_MAP(CButtonWindow, CFrameWnd)
ON_BN_CLICKED(IDB_BUTTON, HandleButton)
ON_WM_SIZE()
ON_WM_TIMER()
E
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -