MFC入门(一)

摘要:
2) Windows和句柄窗口是Windows应用程序中非常重要的元素。应用程序窗口通常包含标题栏、菜单栏、系统菜单、最小化框、最大化框和可调整边框。应用程序通常在客户端区域显示文本或绘制图形。3) 消息和消息队列Windows编程是一种与传统DOS模式完全不同的编程方法。系统将为程序创建一个消息队列,用于存储程序创建的窗口的消息。
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 应用程序与用户进行交互的接口。利用窗口可以接收用户的输入、以及显示输出。

一个应用程序窗口通常都包含标题栏、菜单栏、系统菜单、最小化框、最大化框、 可调边框,有的还有滚动条。如下图:

MFC入门(一)第1张

窗口可以分为客户区和非客户区, 如上图。 客户区是窗口的一部分, 应用程序通常在客户区中显示文字或者绘制图形。

标题栏、 菜单栏、 系统菜单、 最小化框和最大化框、 可调边框统称为窗口的非客户区, 它们由 Windows 系统来管理, 而应用程序则主要管理客户区的外观及操作。

窗口可以有一个父窗口, 有父窗口的窗口称为子窗口。除了上图所示类型的窗口外, 对话框和消息框也是一种窗口。 在对话框上通常还包含许多子窗口, 这些子窗口的形式有按钮、 单选按钮、 复选框、 组框、 文本编辑框等。

 

Windows 应用程序中, 窗口是通过窗口句柄( HWND) 来标识的。 我们要对某个窗口进行操作, 首先就要得到这个窗口的句柄

 

句柄( HANDLE) 是 Windows 程序中一个重要的概念, 使用也非常频繁。 在 Windows 程序中, 有各种各样的资源( 窗口、 图标、光标,画刷等), 系统在创建这些资源时会为它们分配内存, 并返回标识这些资源的标识号, 即句柄。

在后面的内容中我们还会看到图标句柄( HICON)、 光标句柄( HCURSOR) 和画刷句柄( HBRUSH)。

 

3) 消息与消息队列

Windows 程序设计是一种完全不同于传统的 DOS 方式的程序设计方法。它是一种事件驱动方式的程序设计模式,主要是基于消息的。

每一个 Windows 应用程序开始执行后, 系统都会为该程序创建一个消息队列, 这个消息队列用来存放该程序创建的窗口的消息。

例如,当用户在窗口中画图的时候,按下鼠标左键,此时,操作系统会感知到这一事件,于是将这个事件包装成一个消息,投递到应用程序的消息队列中,等待应用程序的处理。

然后应用程序通过一个消息循环不断地从消息队列中取出消息,并进行响应。

在这个处理过程中,操作系统也会给应用程序“ 发送消息”。所谓“ 发送消息”,实际上是操作系统调用程序中一个专门负责处理消息的函数,这个函数称为窗口过程。

MFC入门(一)第2张

 鼠标操作窗口时,操作系统先捕获到消息,把消息放到消息队列中,应用程序捕获消息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>头文件

 MFC入门(一)第3张

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的调用之间处理消息。

MFC入门(一)第4张

3) 对应消息处理函数分别在类中声明,类外定义:

 MFC入门(一)第5张

声明宏  写到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入门(一)第6张

应用程序类的一个虚函数,MFC应用程序的入口。

 

2) PreCreateWindow函数

MFC入门(一)第7张

 

当框架调用CreateEx函数创建窗口时,会首先调用PreCreateWindow函数。

通过修改传递给PreCreateWindow的结构体类型参数CREATESTRUCT,应用程序可以更改用于创建窗口的属性。

在产生窗口之前让程序员有机会修改窗口的外观。

最后再调用CreateWindowEx函数完成窗口的创建。

 

3) OnCreate函数

 MFC入门(一)第8张

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

 MFC入门(一)第9张

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覆盖掉

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

免责声明:文章转载自《MFC入门(一)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Python小代码_13_生成两个参数的最小公倍数和最大公因数使用mysqldump批量导出建表语句 规格严格下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Ubuntu下双显示器设定

自8.10后的版本,系统自带了xrandr工具,可以很好的实现双显示器。配置与使用如下: 介绍    X Windows 中有一个显示分辨率的概念,在默认情况下,这个显示分辨率为 max*max ,max等于你的所有连接上的显示器中最大分辨率中的最大值。例如我的笔记本液晶屏最大分辨率为 1024*768,外接显示器最大分辨率为 1280*1024,则...

Android自动化测试工具——monkey简介及入门

记得第二家单位的安卓开发在上线前都用monkey压几个小时,确实也能发现些问题,崩溃率低了些,没测过的确实可以压一压 搜了下资料,monkey确实很简单,发现问题自己搜下是什么问题,别一发现什么就跑去问开发 下面介绍下monkey的原理 Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流(如按键输...

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十) 之 自定义系统消息和总结

前言   本篇主要讲解一个东西,就是我们自定义系统消息。效果如下:   首先我们要做的准备工作就是改写 layim 的消息模板,如果不改的话就成为某个用户发送的消息了,那么体验就稍微差一些。找到模板我们看一下。   注意,红框部分是我更改后的,简单读一下可以看出来,我只是给聊天消息加了个参数 system,如果有这个参数,那么我们直接给加一个div就...

搭建websocket消息推送服务,必须要考虑的几个问题

近年,不论是正在快速增长的直播,远程教育以及IM聊天场景,还是在常规企业级系统中用到的系统提醒,对websocket的需求越来越大,对websocket的要求也越来越高。从早期对websocket的应用仅限于少部分功能和IM等特殊场景,逐步发展为追求支持高并发,百万、千万级每秒通讯的高可用websocket服务。   面对各种新场景对websocket功能...

免安装,直接复制VM虚拟机磁盘文件vmx,遇到的各种问题解决

今天在拷贝centOS虚拟机的时候, 意外遇到centOS复制时候的兼容性问题. 在这里插入图片描述 配置文件 .vmx 是由VMware产品创建,但该产品与此版 VMware workstation 不兼容,因此无法使用。 根据这个提示,初步怀疑是虚拟机创建时的版本和我安装的workstation版本不兼容,由于软件一般会有向下兼容的特性,所以虚拟机的版...

时序图学习4_组成元素之生命线和激活(控制焦点)

注:本文中的时序图均使用Astah工具制作。 一、生命线(Lifeline) 生命线代表时序图中的对象在一段时期内的存在。 时序图中每个对象和底部中心都有一条垂直的虚线,这就是对象的生命线,对象间的消息存在于两条虚线间。 生命线是一个时间线, 从时序图顶部一直到底部都存在, 其长度取决于交互的时间。 二、激活(Activation) 代表生命线上的窄矩...