?? visual c++ mfc 簡明教程.doc
字號(hào):
// 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);
}
主要修改了三個(gè)方面:
CButtonWindow的類說明現(xiàn)在包含了一個(gè)新的成員函數(shù)和一個(gè)新的表示消息映射的宏。HandleButton函數(shù)是正常的C++函數(shù),它通過afx_msg標(biāo)簽確定為消息處理函數(shù)。該函數(shù)需要一些特殊的約束,例如,它必須是void型并且它不能接收任何參數(shù)。DECLARE_MESSAGE_MAP宏建立了消息映射。函數(shù)和宏都必須是public型的。
HandleButton函數(shù)作為成員函數(shù)以同樣的方式來建立。在該函數(shù)中,我們調(diào)用了Windows API中的MessageBeep函數(shù)。
用宏來建立消息映射。在代碼中,你可以看見BEGIN_MESSAGE_MAP宏接收兩各參數(shù)。第一個(gè)指定了使用消息映射的類的名稱。第二個(gè)是基類。然后是ON_BN_CLICKED宏,接受兩個(gè)參數(shù)控制的ID和該ID發(fā)送命令消息時(shí)所調(diào)用的函數(shù)。最后,消息映射用END_MESSAGE_MAP來結(jié)束。
當(dāng)用戶單擊按鈕時(shí),它向其包含該按鈕的父窗口發(fā)送了一個(gè)包含其ID的命令消息。那是按鈕的缺省行為,這就是該代碼工作的原因。按鈕向其父窗口發(fā)送消息,是因?yàn)樗亲哟翱?。父窗口截取該消息并用消息映射來確定所要調(diào)用的函數(shù)。MFC來安排,只要指定的消息一出現(xiàn),相應(yīng)的函數(shù)就會(huì)被調(diào)用。
ON_BN_CLICKED消息是CButton發(fā)送的唯一感興趣的消息。它等同于CWnd中的ON_COMMAND消息,只是一個(gè)更簡單方便的同義詞而已。
改變大小的消息
在上面的代碼中,由于有了消息映射,從CFrameWnd繼承來的應(yīng)用程序窗口認(rèn)出按鈕有按鈕產(chǎn)生的單擊消息并響應(yīng)之。加入消息映射的ON_BN_CLICKED宏指定了按鈕的ID和窗口在接收到來自按鈕的命令消息時(shí)應(yīng)調(diào)用的函數(shù)。因?yàn)橹灰脩魡螕袅税粹o,按鈕就會(huì)自動(dòng)把其ID發(fā)送父窗口,這樣才能允許代碼正確地處理按鈕事件。
作為該應(yīng)用程序的主窗口的框架窗口自己也有傳遞消息的能力。大約有100不同的消息可用,它們都是從CWnd類繼承來的。從MFC幫助文件中瀏覽CWnd類的成員函數(shù),你就會(huì)看到所有的這些消息。查看所有以“On”開頭的成員函數(shù)。
你可能已經(jīng)注意到了,至今為止所有的代碼都不能很好地處理尺寸變化。當(dāng)窗口變化大小時(shí),窗口的框架會(huì)做相應(yīng)的調(diào)整,但是窗口中調(diào)的內(nèi)容仍原處不動(dòng)??梢酝ㄟ^處理尺寸變化的事件來更好的處理這一問題。任何窗口發(fā)送的消息之一就是變尺寸消息。該消息是當(dāng)改變形狀時(shí)發(fā)出的。我們可以使用該消息來控制框架中子窗口的大小,如下所示:
// 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);
}
為了理解上面的代碼,從窗口的消息映射開始。你會(huì)發(fā)現(xiàn)入口ON_WM_SIZE。該入口表示消息映射是對(duì)來自CButtonWindow對(duì)象的變尺寸消息發(fā)生響應(yīng)。變尺寸消息是當(dāng)用戶改變窗口的大小時(shí)產(chǎn)生的。該消息來自窗口本身,而不是作為ON_COMMAND消息由按鈕向其父窗口發(fā)送的。這是因?yàn)榇翱诳蚣懿皇亲哟翱凇?要注意的是消息映射中的ON_WM_SIZE入口沒有參數(shù)。你在MFC文檔中CWnd類,消息映射中的ON_WM_SIZE入口總是調(diào)用OnSize函數(shù),并且該函數(shù)必須接收三個(gè)參數(shù)。OnSize函數(shù)必須是消息映射所屬類的成員函數(shù),并且該函數(shù)必須用afx_msg來說明(正如上面在CButtonWindow的定義中所見到的一樣)。
如果你查看MFC文檔,就會(huì)發(fā)現(xiàn)CWnd中有近100名為“On...”的函數(shù)。CWnd::OnSize是其中之一。所有這些函數(shù)都在消息映射中有形如ON_WM_對(duì)應(yīng)的標(biāo)簽。例如,ON_WM_SIZE對(duì)應(yīng)OnSize。ON_WM_入口不接收任何參數(shù),如ON_BN_CLICKED一樣。參數(shù)是假設(shè)的并自動(dòng)傳遞給相應(yīng)的如OnSize的“On...”函數(shù)。
重復(fù)一遍,因?yàn)樗苤匾? OnSize函數(shù)總是與消息映射中的ON_WM_SIZE入口想對(duì)應(yīng)。你必須命名處理函數(shù)OnSize, 并且它必須接收三個(gè)參數(shù)。不同的函數(shù)的參數(shù)會(huì)有所不同。
上面的代碼中在OnSize函數(shù)自身的內(nèi)部,有三行代碼修改了按鈕在窗口中的尺寸。你可以在該函數(shù)中輸入任何你想要的代碼。
調(diào)用GetClientRect是為了恢復(fù)窗口用戶區(qū)域的新尺寸。該矩形會(huì)被縮小,并調(diào)用按鈕的MoveWindow函數(shù)。MoveWindow是從CWnd繼承來的,改變尺寸和移動(dòng)子窗口是在一步完成的。
當(dāng)你執(zhí)行上面改變窗口大小的程序時(shí),你就會(huì)發(fā)現(xiàn)按鈕自己能正確地改變大小。在代碼中,變尺寸事件他國消息映射中的OnSize函數(shù)而產(chǎn)生一調(diào)用,它調(diào)用MoveWindow函數(shù)來改變按鈕的大小。
窗口消息
查看MFC文檔,你可以看到主窗口處理的各種各樣的CWnd消息。有些與我們上面介紹的類似。例如,ON_WM_MOVE消息是當(dāng)用戶移動(dòng)窗口時(shí)發(fā)送的消息,ON_WM_PAINT消息是當(dāng)窗口的任何部分需要重畫時(shí)發(fā)出的。至今為止,我們的所有程序,重畫工作都是自動(dòng)完成的,因?yàn)槭强刂谱约簛碡?fù)責(zé)其外觀。如果你自己使用GDI命令來在用戶區(qū)域中繪制,應(yīng)用程序就應(yīng)負(fù)責(zé)重畫工作。因此ON_WM_PAINT就變得重要了。
還有一些發(fā)送給窗口的事件消息更深?yuàn)W。例如,你可以使用ON_WM_TIMER消息與SetTimer函數(shù)來使接收預(yù)先設(shè)置的時(shí)間間隔。下面的代碼給出了該過程。當(dāng)你運(yùn)行該代碼時(shí),程序會(huì)每隔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
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -