• MFC入门(一)


    Windows消息机制

    基本概念解释

    1) SDK和API

    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类型,这是一种多种窗口类型的组合类型。

    xy:指定窗口左上角的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_DESTROY:DestroyWindow函数在销毁窗口后,会给窗口过程发送 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) OnDraw和OnPaint

     

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

     

     

    转自:https://www.cnblogs.com/yangyuqing/p/10283641.html

  • 相关阅读:
    算法(一)—— 河内之塔(汉诺塔)
    JAVA爬取网页邮箱
    js中判断某字符串含有某字符出现的次数
    逻辑删除和物理删除的区别
    Forward和Redirect的区别
    Postman 传Map类型的参数
    Java基础
    【html-css】
    【HTML----】
    【python-while-以及字符串的相关操作和函数】
  • 原文地址:https://www.cnblogs.com/chenxuge/p/14142749.html
Copyright © 2020-2023  润新知