MFC入門(一)


Windows消息機制

基本概念解釋

1) SDKAPI

SDK 軟件開發工具包(Software Development Kit),一般都是一些被軟件工程師用於為特定的軟件包、軟件框架、硬件平台、操作系統等建立應用軟件的開發工具的集合。

API函數 Windows操作系統提供給應用程序編程的接口(Application Programming Interface)。

                 Windows應用程序API函數是通過C語言實現的,所有主要的 Windows 函數都在 Windows.h 頭文件中進行了聲明Windows 操作系統提供了 1000 多種 API函數。

 

2) 窗口和句柄

窗口是 Windows 應用程序中一個非常重要的元素,一個 Windows 應用程序至少要有一個窗口,稱為主窗口。

窗口是屏幕上的一塊矩形區域,是 Windows 應用程序與用戶進行交互的接口。利用窗口可以接收用戶的輸入、以及顯示輸出。

一個應用程序窗口通常都包含標題欄、菜單欄、系統菜單、最小化框、最大化框、 可調邊框,有的還有滾動條。如下圖:

窗口可以分為客戶區和非客戶區, 如上圖。 客戶區是窗口的一部分, 應用程序通常在客戶區中顯示文字或者繪制圖形。

標題欄、 菜單欄、 系統菜單、 最小化框和最大化框、 可調邊框統稱為窗口的非客戶區, 它們由 Windows 系統來管理, 而應用程序則主要管理客戶區的外觀及操作。

窗口可以有一個父窗口, 有父窗口的窗口稱為子窗口。除了上圖所示類型的窗口外, 對話框和消息框也是一種窗口。 在對話框上通常還包含許多子窗口, 這些子窗口的形式有按鈕、 單選按鈕、 復選框、 組框、 文本編輯框等。

 

Windows 應用程序中, 窗口是通過窗口句柄( HWND) 來標識的。 我們要對某個窗口進行操作, 首先就要得到這個窗口的句柄

 

句柄( HANDLE) 是 Windows 程序中一個重要的概念, 使用也非常頻繁。 在 Windows 程序中, 有各種各樣的資源( 窗口、 圖標、光標,畫刷等), 系統在創建這些資源時會為它們分配內存, 並返回標識這些資源的標識號, 即句柄。

在后面的內容中我們還會看到圖標句柄( HICON)、 光標句柄( HCURSOR) 和畫刷句柄( HBRUSH)。

 

3) 消息與消息隊列

Windows 程序設計是一種完全不同於傳統的 DOS 方式的程序設計方法。它是一種事件驅動方式的程序設計模式,主要是基於消息的。

每一個 Windows 應用程序開始執行后, 系統都會為該程序創建一個消息隊列, 這個消息隊列用來存放該程序創建的窗口的消息。

例如,當用戶在窗口中畫圖的時候,按下鼠標左鍵,此時,操作系統會感知到這一事件,於是將這個事件包裝成一個消息,投遞到應用程序的消息隊列中,等待應用程序的處理。

然后應用程序通過一個消息循環不斷地從消息隊列中取出消息,並進行響應。

在這個處理過程中,操作系統也會給應用程序“ 發送消息”。所謂“ 發送消息”,實際上是操作系統調用程序中一個專門負責處理消息的函數,這個函數稱為窗口過程。

 

 鼠標操作窗口時,操作系統先捕獲到消息,把消息放到消息隊列中,應用程序捕獲消息GetMessage(),然后DispatchMessage()分發消息給操作系統,操作系統調用回調函數----窗口過程

 

 

4) WinMain函數

Windows操作系統啟動一個程序時,它調用的就是該程序的WinMain函數( 實際是由插入到可執行文件中的啟動代碼調用的)。

WinMain是Windows程序的入口點函數,與DOS程序的入口點函數main的作用相同,當WinMain 函數結束或返回時,Windows應用程序結束。

 

 Windows 編程模型

一個完整的Win32程序(#include <windows.h>),該程序實現的功能是創建一個窗口,並在該窗口中響應鍵盤及鼠標消息,程序的實現步驟為:

1) WinMain函數的定義

2) 創建一個窗口

3) 進行消息循環

4) 編寫窗口過程函數

 

1) WinMain函數的定義

int WINAPI WinMain(

                         HINSTANCE hInstance, //應用程序實例

                         HINSTANCE hPrevInstance, //上一個應用程序實例

                         LPSTR lpCmdLine, //命令行參數

                         int nShowCmd); //窗口顯示的樣式

                   );

WINAPI是一個宏,它代表的是__stdcall(注意是兩個下划線)

                表示的是參數傳遞的順序:從右往左依次入棧,同時在函數返回前自動清空堆棧

hInstance表示該程序當前運行的實例的句柄,這是一個數值。當程序在Windows下運行時,它唯一標識運行中的實例(注意,只有運行中的程序實例, 才有實例句柄)。一個應用程序可以運行多個實例,每運行一個實例,系統都會給該實例分配一個句柄值,並通過hInstance參數傳遞給                           WinMain 函數。

hPrevInstance表示當前實例的前一個實例的句柄。在Win32環境下,這個參數總是NULL,即在Win32環境下,這個參數不再起作用。

lpCmdLine是一個以空終止的字符串, 指定傳遞給應用程序的命令行參數,相當於C或C++中的main函數中的參數char *argv[]。

nShowCmd表示一個窗口的顯示,表示它是要最大化顯示、最小化顯示、正常大小顯示還是隱藏顯示。

 

2) 創建一個窗口

創建一個完整的窗口,需要經過下面幾個步驟:

1. 設計一個窗口類

    一個完整的窗口具有許多特征, 包括光標(鼠標進入該窗口時的形狀)、圖標、背景色等。窗口的創建過程類似於汽車的制造過程。

    我們在生產一個型號的汽車之前, 首先要對該型號的汽車進行設計, 在圖紙上畫出汽車的結構圖, 設計各個零部件, 同時還要給該型號的汽車取一個響亮的名字, 例如“寶馬 x6”。

    類似地, 在創建一個窗口前, 也必須對該類型的窗口進行設計, 指定窗口的特征。

    在Windows中,窗口的特征就是由WNDCLASS結構體來定義的,我們只需給WNDCLASS結構體對應的成員賦值,即可完成窗口類的設計。

 

WNDCLASS結構體的定義如下:

typedef struct _WNDCLASS{
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCWSTR     lpszMenuName;
    LPCWSTR     lpszClassName;
} WNDCLASS;

style:指定窗口的樣式(風格),常用的樣式如下:

類型

含義

CS_HREDRAW

當窗口水平方向上的寬度發生變化時, 將重新繪制整個窗口。 當窗口發生重繪時, 窗口中的文字和圖形將被擦除。如果沒有指定這一樣式,那么在水平方向上調整窗口寬度時,將不會重繪窗口。

CS_VREDRAW

當窗口垂直方向上的高度發生變化時,將重新繪制整個窗口。如果沒有指定這一樣式,那么在垂直方向上調整窗口高度時,將不會重繪窗口。

CS_NOCLOSE

禁用系統菜單的 Close 命令,這將導致窗口沒有關閉按鈕。

CS_DBLCLKS

當用戶在窗口中雙擊鼠標時,向窗口過程發送鼠標雙擊消息。

lpfnWndProc:指定一個窗口回調函數,是一個函數的指針。

當應用程序收到給某一窗口的消息時,就應該調用某一函數來處理這條消息。這一調用過程不用應用程序自己來實施,而由操作系統來完成,但是,回調函數本身的代碼必須由應用程序自己完成

對於一條消息,操作系統調用的是接受消息的窗口所屬的類型中的lpfnWndProc成員指定的函數。每一種不同類型的窗口都有自己專用的回調函數,該函數就是通過lpfnWndProc成員指定的。

回調函數的定義形式如下:

LRESULT CALLBACK WindowProc(
    HWND hWnd,        //信息所屬的窗口句柄
    UINT uMsg,        //消息類型
    WPARAM wParam,    //附加信息(如鍵盤哪個鍵按下)
    LPARAM lParam    //附加信息(如鼠標點擊坐標)
    );

cbClsExtra:類的附加內存,通常數情況下為0。

cbWndExtra:窗口附加內存,通常情況下為0。

hInstance:當前實例句柄,用WinMain中的形參hInstance為其賦值。

hIcon:指定窗口類的圖標句柄,設置為NULL,則使用默認圖標,也可用如下函數進行賦值:

HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName);
如:LoadIcon(NULL, IDI_WARNING); //第一個參數為NULL,加載系統默認圖標

hCursor:指定窗口類的光標句柄,設置為NULL,則使用默認圖標,也可用如下函數進行賦值:

HCURSOR LoadCursor(HINSTANCE hInstance, LPCTSTR lpCursorName);
如:LoadCursor(NULL, IDC_HELP); //第一個參數為NULL,加載系統默認光標

hbrBackground:指示窗口的背景顏色,可用如下函數進行賦值:

HGDIOBJ GetStockObject(int fnObject);
如:GetStockObject(WHITE_BRUSH);

lpszMenuName指定菜單資源的名字。如果設置為NULL,那么基於這個窗口類創建的窗口將沒有默認菜單。

lpszClassName:指定窗口類的名字。

2. 注冊窗口類

設計完窗口類(WNDCLASS)后, 需要調用RegisterClass函數對其進行注冊,注冊成功后,才可以創建該類型的窗口。

注冊函數的原型聲明如下:

ATOM RegisterClass(CONST WNDCLASS *lpWndClass);

使用示例:RegisterClass(&wc);

3. 創建窗口

設計好窗口類並且將其成功注冊之后, 即可用CreateWindow函數產生這種類型的窗口了。 

CreateWindow函數的原型聲明如下:

HWND CreateWindow(
        LPCTSTR lpClassName,
        LPCTSTR lpWindowName,
        DWORD dwStyle,
        int x,
        int y,
        int nWidth,
        int nHeight,
        HWND hWndParent,
        HMENU hMenu,
        HINSTANCE hInstance,
        LPVOID lpParam
);

參數說明:

lpClassName指定窗口類的名稱,此名字必須和WNDCLASS的lpszClassName成員指定的名稱一樣。

lpWindowName:指定窗口的名字,即窗口的標題。

dwStyle指定創建的窗口的樣式,常指定為指WS_OVERLAPPEDWINDOW類型,這是一種多種窗口類型的組合類型。

x, y指定窗口左上角的x,y坐標。如果參數x被設為CW_USEDEFAULT,那么系統為窗口選擇默認的左上角坐標並忽略y參數。

nWidthnHeight指定窗口窗口的寬度,高度。如果參數nWidth被設為 CW_USEDEFAULT,那么系統為窗口選擇默認的寬度和高度,參數nHeight被忽略。

hWndParent:指定被創建窗口的父窗口句柄,沒有父窗口,則設置NULL。

hMenu:指定窗口菜單的句柄,沒有,則設置為NULL。

hInstance窗口所屬的應用程序實例的句柄,用WinMain中的形參hInstance為其賦值。

lpParam作為WM_CREATE消息的附加參數lParam傳入的數據指針。通常設置為NULL。

返回值說明:如果窗口創建成功,CreateWindow函數將返回系統為該窗口分配的句柄,否則,返回NULL。

示例代碼:

HWND  hWnd = CreateWindow(
TEXT("MyWin"),  //窗口類名字
TEXT("測試"),      //窗口標題
WS_OVERLAPPEDWINDOW,  //窗口風格    
CW_USEDEFAULT, CW_USEDEFAULT,  //窗口x,y坐標,使用默認值
CW_USEDEFAULT, CW_USEDEFAULT,  //窗口寬度,高度,使用默認值
NULL,      //無父窗口
NULL,     //無菜單
hInstance,     //應用程序實例句柄,為WinMain第1個形參
NULL);    //附件信息,通常設置為NULL

4. 顯示及更新窗口

顯示窗口函數原型:

BOOL ShowWindow(HWND hWnd, int nCmdShow);

更新窗口函數原型:

BOOL UpdateWindow(HWND hWnd);

示例代碼:

ShowWindow(hWnd, SW_SHOWNORMAL); //SW_SHOWNORMAL為普通模式
UpdateWindow(hWnd);

5. 通過循環取消息

6. 處理消息(窗口過程)

在完成上述步驟后,剩下的工作就是編寫一個窗口過程函數,用於處理發送給窗口的消息。

窗口過程函數的名字可以隨便取, 如WinProc, 但函數定義的形式必須和下面聲明的形式相同:

//CALLBACK __stdcall 參數的傳遞順序,從右到左,依次入棧,並且在函數返回前清空堆棧
LRESULT CALLBACK WindowProc(
     HWND hwnd,//消息所屬的窗口句柄
     UINT uMsg,//具體的消息名稱 WM__XXX消息名
     WPARAM wParam,//鍵盤的附加消息
     LPARAM lParam//鼠標的附加消息
    )

DefWindowProc函數DefWindowProc函數調用默認的窗口過程,對應用程序沒有處理的其他消息提供默認處理。

WM_CLOSE:對WM_CLOSE消息的響應並不是必須的,如果應用程序沒有對該消息進行響應,系統將把這條消息傳給DefWindowProc函數而 DefWindowProc函數則調用DestroyWindow函數來響應這條WM_CLOSE消息。

WM_DESTROYDestroyWindow函數在銷毀窗口后,會給窗口過程發送 WM_DESTROY消息,我們在該消息的響應代碼中調用PostQuitMessage函數。

PostQuitMessage函數向應用程序的消息隊列中投遞一條WM_QUIT消息並返回。

WinMain函數中GetMessage 函數只有在收到WM_QUIT消息時才返回0,此時消息循環才結束,程序退出傳遞給 PostQuitMessage函數的參數值將作為WM_QUIT消息的wParam參數,這個值通常用做WinMain函數的返回值。

//處理窗口過程
//CALLBACK __stdcall 參數的傳遞順序,從右到左,依次入棧,並且在函數返回前清空堆棧
LRESULT CALLBACK WindowProc(
     HWND hwnd,//消息所屬的窗口句柄
     UINT uMsg,//具體的消息名稱 WM__XXX消息名
     WPARAM wParam,//鍵盤的附加消息
     LPARAM lParam//鼠標的附加消息
    )
{
    switch(uMsg)
    {

    case WM_CLOSE:
//所有xxxWindow為結尾的方法,都不會進入消息隊列中,而是直接執行 DestroyWindow(hwnd);
//DestroyWindow發送另一個消息 WM_DESTROY break; case WM_DESTROY: PostQuitMessage(0); break; case WM_LBUTTONDOWN://鼠標左鍵按下 { int xPos=LOWORD(lParam); int yPos=HIWORD(lParam); char buf[1024]; wsprintf((LPWSTR)buf,TEXT("x=%d,y=%d"),xPos,yPos); MessageBox(hwnd,buf,TEXT("點擊"),MB_OK); break; } case WM_KEYDOWN://鍵盤 MessageBox(hwnd,TEXT("鍵盤按下"),TEXT("鍵盤按下"),MB_OK); break; case WM_PAINT://繪圖 { PAINTSTRUCT ps;//繪圖結構體 HDC hdc=BeginPaint(hwnd,&ps); TextOut(hdc,100,100,TEXT("hello world!"),strlen("hello world!")); EndPaint(hwnd,&ps); } break; } //返回值用默認處理方式 return DefWindowProc(hwnd,uMsg,wParam,lParam); }

 

#include<Windows.h>//底層實現窗口的頭文件

int WINAPI WinMain(
    HINSTANCE hInstance,//應用程序實例句柄 
    HINSTANCE hPrevInstance,//上一個應用程序句柄,在win32環境下,參數一般為NULL,不起作用了
    LPSTR lpCmdLine,
    int nShowCmd
    )
{
    //1. 設計窗口
    WNDCLASS wc;
    HWND hwnd;
    MSG msg;
    wc.cbClsExtra=0;//類的額外的內存
    wc.cbWndExtra=0;//窗口的額外內存
    wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//設置背景
    wc.hCursor=LoadCursor(NULL,IDC_HAND);//設置光標,如果第一個參數為NULL,代表使用系統提供的光標
    wc.hIcon=LoadIcon(NULL,IDI_INFORMATION);//圖標
    wc.hInstance=hInstance;//應用程序的實際句柄。傳入WinMain中的形參即可
    //wc.lpfnWndProc=WindowProc;//回調函數,窗口過程
    wc.lpszClassName=TEXT("WIN");//指定窗口類名稱
    wc.lpszMenuName=NULL;//菜單名稱
    wc.style=0;//顯示風格,0代表默認風格
    //2. 注冊窗口類
    RegisterClass(&wc);

    //3. 創建窗口
    /*
    lpClassName:類名
    lpWindowName:標題名
    dwStyle:風格
    x:顯示坐標
    y:顯示坐標CW_USEDEFAULT默認值
    nWidth:寬高
    nHeight
    hWndParent:父窗口
    hMenu:菜單NULL
    hInstance:實例句柄
    lpParam :附加值,鼠標附加值
    */
    hwnd = CreateWindow(wc.lpszClassName, TEXT("WINDOWS"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
    //4.顯示和更新
    ShowWindow(hwnd,SW_SHOWNORMAL);
    UpdateWindow(hwnd);
    //5. 通過循環取消息
    /*
    HWND        hwnd;主窗口句柄
    UINT        message;具體的消息名稱
    WPARAM      wParam;附加消息,鍵盤消息
    LPARAM      lParam;附加消息,鼠標消息
    DWORD       time;消息產生的時間
    POINT       pt;附加消息,鼠標消息 x y
    */
    
    while(1)
    {
        /*
        __out LPMSG lpMsg,消息
        __in_opt HWND hWnd,捕獲窗口,填NULL代表捕獲所有的窗口
        __in UINT wMsgFilterMin,最小和最大的過濾消息,一般填0
        __in UINT wMsgFilterMax 填0代表捕獲所有消息
        */
        if(GetMessage(&msg,NULL,0,0)==FALSE)
        {
            break;
        }
        //翻譯消息
        TranslateMessage(&msg);

        //不為false
        //分發消息
        DispatchMessage(&msg);

    }

    return 0;
}

注意:生成解決方案的時候出現“error C2275: “xxxxx”: 將此類型用作表達式非法”

           錯誤是由於:c的編譯器要求將變量的聲明放在一個函數塊的頭部,而c++沒有這樣的要求造成的;解決的辦法就是把變量的聲明全部放在變量的生存塊的開始。

           解決方法:將所有變量定義在代碼段的開頭

 

 

MFC入門

MFC是什么?

微軟基礎類庫(英語Microsoft Foundation Classes,簡稱MFC)是一個微軟公司提供的類庫class libraries),以C++類的形式封裝了Windows API,並且包含一個應用程序框架,以減少應用程序開發人員的工作量。其中包含的類包含大量Windows句柄封裝類和很多Windows的內建控件和組件的封裝類。

MFC把Windows SDK API函數包裝成了幾百個類,MFC給Windows操作系統提供了面向對象的接口,支持可重用性、自包含性以及其他OPP原則。MFC通過編寫類來封裝窗口、對話框以及其他對象,引入某些關鍵的虛函數(覆蓋這些虛函數可以改變派生類的功能)來完成,並且MFC設計者使類庫帶來的總開銷降到了最低。

 

編寫第一個MFC應用程序

1) 代碼的編寫

項目的創建和之前一樣,只是此次的源文件后綴為.cpp,因為MFC是由C++編寫的,編寫MFC程序需要包含#include <afxwin.h>頭文件

 

 

2) 程序執行流程

① 程序開始時,先實例化應用程序對象(有且只有一個)

② 執行程序的入口函數InitInstance()

③ 給框架類MyFrame對象動態分配空間(自動調用它的構造函數),在其構造函數內部,通過CWnd::Create創建窗口

④ 框架類對象顯示窗口CWnd::ShowWindow

⑤ 框架類對象更新窗口CWnd::UpdateWindow

⑥ 保存框架類對象指針CWinThread::m_pMainWnd

 自定義類 繼承與CWinApp應用程序類 MyApp app 應用程序對象,有且僅有一個

#include "mfc.h"

MyApp app;//全局應用程序對象,有且僅有一個
BOOL MyApp::InitInstance()
{
    //創建窗口
    MyFrame * frame=new MyFrame;
    //顯示和更新
    frame->ShowWindow(SW_SHOWNORMAL);
    frame->UpdateWindow();
    m_pMainWnd=frame;//保存指向應用程序的主窗口的指針
    return TRUE;//返回正常初始化

}

MyFrame::MyFrame()
{
    Create(NULL,TEXT("mfc"));
}

 

#include <afxwin.h> //mfc頭文件

class MyApp:public CWinApp///應用程序類
{
public:
    //程序入口
    virtual BOOL InitInstance();
};
class MyFrame:public CFrameWnd//窗口框架類
{
public:MyFrame();
};

 

消息映射

消息映射是一個將消息和成員函數相互關聯的表

比如,框架窗口接收到一個鼠標左擊消息,MFC將搜索該窗口的消息映射,如果存在一個處理WM_LBUTTONDOWN消息的處理程序,然后就調用OnLButtonDown

下面是是將消息映射添加到一個類中所做的全部工作:

1) 所操作類中,聲明消息映射宏。

2) 通過放置標識消息的宏來執行消息映射,相應的類將在對BEGIN_MESSAGE_MAP和END_MESSAGE_MAP的調用之間處理消息。

3) 對應消息處理函數分別在類中聲明,類外定義:

 

聲明宏  寫到h中

分界宏 寫到.cpp中

找到消息宏,寫到分界宏之間

把函數原型聲明寫到.h 中

函數的實現寫到.cpp中

鼠標,鍵盤,繪圖

 

#include "mfc.h"

MyApp app;//全局應用程序對象,有且僅有一個
BOOL MyApp::InitInstance()
{
    //創建窗口
    MyFrame * frame=new MyFrame;
    //顯示和更新
    frame->ShowWindow(SW_SHOWNORMAL);
    frame->UpdateWindow();
    m_pMainWnd=frame;//保存指向應用程序的主窗口的指針
    return TRUE;//返回正常初始化

}
//分界宏
BEGIN_MESSAGE_MAP(MyFrame,CFrameWnd)
    ON_WM_LBUTTONDOWN( )//鼠標左鍵按下
    ON_WM_CHAR( )//鍵盤
END_MESSAGE_MAP()


MyFrame::MyFrame()
{
    Create(NULL,TEXT("mfc"));
}

void MyFrame::OnLButtonDown( UINT nFlags, CPoint point )
{
    /*TCHAR buf[1024];
    wsprintf(buf,TEXT("x=%d,y=%d"),point.x,point.y);
    MessageBox(buf);*/

    //mfc中的字符串  CString
    CString str;
    str.Format(TEXT("x=%d,,,,y=%d"),point.x,point.y);
    MessageBox(str);
}

void MyFrame::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags )
{
    CString str;
    str.Format(TEXT("按下了%c 鍵"),nChar);
    MessageBox(str);
}
#include <afxwin.h> //mfc頭文件

class MyApp:public CWinApp///應用程序類
{
public:
    //程序入口
    virtual BOOL InitInstance();
};
class MyFrame:public CFrameWnd//窗口框架類
{
public:MyFrame();
       //聲明宏 提供消息映射機制
       DECLARE_MESSAGE_MAP()
       afx_msg void OnLButtonDown( UINT nFlags, CPoint point );
       afx_msg void OnChar( UINT nChar, UINT nRepCnt, UINT nFlags );

};

 

 Windows字符集

1. 多字節 字符串 轉寬字節 L

2. 聲明 寬字節字符串 wchar_t

3. 統計寬字節字符串 wcslen

4. TEXT做了自適應編碼的轉換

5. char * CString 之間轉換

    char*->CString

    char * p3='ccc';

    CString str=Cstring(p3);

    CString->char *

    CString tmp;

     tmp=str;

     char *pp=tmp.GetBuffer();

用向導生成一個MFC應用程序

MFC框架中一些重要的函數

1) InitInstance函數

應用程序類的一個虛函數,MFC應用程序的入口。

 

2) PreCreateWindow函數

 

當框架調用CreateEx函數創建窗口時,會首先調用PreCreateWindow函數。

通過修改傳遞給PreCreateWindow的結構體類型參數CREATESTRUCT,應用程序可以更改用於創建窗口的屬性。

在產生窗口之前讓程序員有機會修改窗口的外觀。

最后再調用CreateWindowEx函數完成窗口的創建。

 

3) OnCreate函數

 

OnCreate是一個消息響應函數,是響應WM_CREATE消息的一個函數,而WM_CREATE消息是由Create函數調用的。一個窗口創建(Create)之后,會向操作系統發送WM_CREATE消息,OnCreate()函數主要是用來響應此消息的。

onCreate與Create的區別:

1. Create()負責注冊並產生窗口,像動態創建控件中的Create()一樣,窗口創建之后會向操作系統發送WM_CREATE消息。

2. OnCreate()不產生窗口,只是在窗口顯示前設置窗口的屬性如風格、位置等。

3. OnCreate()是消息WM_CREATE的消息響應函數。 

 

4) OnDrawOnPaint

 

OnPaint是WM_PAINT消息的消息處理函數,在OnPaint中調用OnDraw,一般來說,用戶自己的繪圖代碼應放在OnDraw中。

1. OnPaint()是CWnd的類成員,負責響應WM_PAINT消息。

2. OnDraw()是CView的成員函數,沒有響應消息的功能。

當視圖變得無效時(包括大小的改變,移動,被遮蓋等等),Windows發送WM_PAINT消息。該視圖的OnPaint 處理函數通過創建CPaintDC類的DC對象來響應該消息並調用視圖的OnDraw成員函數。OnPaint最后也要調用OnDraw,因此一般在OnDraw函數中進行繪制。

通常我們不必編寫OnPaint處理函數。當在View類里添加了消息處理OnPaint()時,OnPaint()就會覆蓋掉OnDraw()。

如果有了OnDraw,不要再有OnPaint了,同時存在的話,OnPaint會把OnDraw覆蓋掉

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM