• win32编程day03 学习笔记


    一 窗口注册和创建

      1 Win32窗口程序创建步骤
     
        1.1 WinMain入口函数的定义
        1.2 WindowProc函数的定义
        1.3 注册窗口类
          RegisterClass/RegisterClassEx
        1.4 创建窗口
          CreateWindow/CreateWindowEx
        1.5 窗口的显示和刷新
          ShowWindow/UpdateWindow
        1.6 消息处理
          GetMessage/DispatchMessage
        1.7 窗口退出
          WM_DESTROY/PostQuitMessage

      2 窗口的注册
       
       2.1 窗口类的分类
         2.1.1 系统全局的窗口类.比如按钮("BUTTON")、文本编辑框("EDIT")等。
         2.1.2 应用程序的全局窗口类。可以在一个应用程序中EXE、DLL等所有模块中使用的窗口类。
         2.1.3 局部窗口类。只能在本模块中使用的窗口类。

      2.2 实现窗口类的注册
         2.2.1 系统全局的窗口类,无需注册直接使用。使用CreateWindow函数,在CLASSNAME中指定系统已经定义好的窗口类型名称即可。

    View Code
    #include <windows.h>
    #include "stdio.h"
    
    HINSTANCE g_hInst = NULL;
    LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, 
                             WPARAM wParam, LPARAM lParam)
    {
        switch(nMsg) {
        case WM_DESTROY: PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hWnd, nMsg, wParam, lParam);
    }
    
    HWND CreateButton()
    {
        HWND hWnd = CreateWindow("BUTTON", "Button", WS_OVERLAPPEDWINDOW, 
            0, 0, 500, 600, NULL, NULL, g_hInst, NULL);
        return hWnd;
    }
    
    void DisplayWnd(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    
    void Message()
    {
        MSG msg = {0};
        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    int WINAPI WinMain(HINSTANCE hInst,
                       HINSTANCE hPrevInt,
                       LPSTR lpCmdLine,
                       int nShowCmd)
    {
        g_hInst = hInst;
        HWND hWndBtn = CreateButton();
        DisplayWnd(hWndBtn);
        Message();
        return 0;
    }

         2.2.2 应用程序的全局窗口类,需要用代码实现注册,在注册时需要增加CS_GLOBALCLASS定义。
           实现方式:

                 WNDCLASS wc = {0};
                 wc.style = CS_GLOBALCLASS|CS_HREDRAW..;
                 ....
                 RegisterClass( &wc );

         2.2.3 局部窗口类,不是增加CS_GLOBALCLASS定义。使用RegisterClass和RegisterClassEx注册

                    typedef struct _WNDCLASSEX { 
                        UINT    cbSize; //结构体的大小
                          UINT    style; 
                          WNDPROC lpfnWndProc; 
                          int     cbClsExtra; 
                          int     cbWndExtra; 
                          HANDLE  hInstance; 
                          HICON   hIcon; 
                          HCURSOR hCursor; 
                          HBRUSH  hbrBackground; 
                          LPCTSTR lpszMenuName; 
                          LPCTSTR lpszClassName; 
                          HICON   hIconSm; //小图标
                        } WNDCLASSEX; 

        2.2.4 窗口类风格

                    CS_HREDRAW 窗口水平变化,重新绘制窗口。
                       CS_VREDRAW 窗口垂直变化,重新绘制窗口。
                       CS_DBCLICK 窗口可以接收鼠标双击消息
                       CS_GLOBALCLASS 创建应用程序全局窗口类。
                       CS_BYTEALIGNWINDOW 窗口对齐方式,以8的倍数对齐
                       CS_BYTEALIGNCLIENT 窗口客户区对齐方式,以8的倍数对齐
                       CS_CLASSDC 所有这种类型的窗口使用同一个DC(设备描述表,绘图使用)
                    CS_OWNDC 每个窗口拥有自己的DC
                    CS_PARENTDC 使用父窗口的DC
                    CS_SAVEBITS 是用位图保存窗口界面,可以提高窗口界面的刷新性能
                       CS_NOCLOSE 禁止关闭命令.
    View Code
    #include <windows.h>
    #include "stdio.h"
    
    HINSTANCE g_hInst = NULL;
    LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, 
                             WPARAM wParam, LPARAM lParam)
    {
        switch(nMsg) {
        case WM_DESTROY: PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hWnd, nMsg, wParam, lParam);
    }
    
    BOOL RegisterWnd(LPSTR pszClassName)
    {
        WNDCLASSEX wce = {0};
        wce.cbSize = sizeof(wce);
        wce.style = CS_VREDRAW|CS_HREDRAW;
        wce.lpfnWndProc = WndProc;
        wce.cbClsExtra = 0;
        wce.cbWndExtra = 0;
        wce.hCursor = NULL;
        wce.hIcon = NULL;
        wce.hbrBackground = HBRUSH(COLOR_BTNFACE+1);
        wce.lpszClassName = pszClassName;
        wce.lpszMenuName = NULL;
        wce.hInstance = g_hInst;
        ATOM nAtom = RegisterClassEx(&wce);
        if(0 == nAtom)
        {
            MessageBox(NULL, "registerError", "Error", MB_OK);
            return FALSE;
        }
        return TRUE;
    }
    
    HWND CreateWnd(LPSTR pszClassName)
    {
        HWND hWnd = CreateWindow(pszClassName,
            "MyWnd", WS_OVERLAPPEDWINDOW, 0, 0, 400, 500,
            NULL, NULL, g_hInst, NULL);
        return hWnd;
    }
    
    void DisplayWnd(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    
    void Message()
    {
        MSG msg = {0};
        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    int WINAPI WinMain(HINSTANCE hInst,
                       HINSTANCE hPrevInt,
                       LPSTR lpCmdLine,
                       int nShowCmd)
    {
        g_hInst = hInst;
        RegisterWnd("MyWnd1");
        HWND hMyWnd = CreateWnd("MyWnd1");
    
        DisplayWnd(hMyWnd);
        Message();
        return 0;
    }

        2.2.5 窗口类的附加数据 cbClsExtra
          在窗口类的数据信息中添加自己信息.
           cbClsExtra 用于添加信息的内存的大小
           SetClassLong 将信息保存到内存中
           GetClassLong 将信息从内存中取出

                         DWORD SetClassLong(
                                  HWND hWnd,//窗口的句柄
                                  int nIndex, //值的索引号
                                  LONG dwNewLong   //
                                );
                          DWORD GetClassLong(
                                  HWND hWnd,//窗口的句柄
                                  int nIndex, //值的索引号
                                );

         cbClsExtra的长度一般是4字节的倍数
        2.2.6 窗口附加数据 cbWndExtra
           在窗口的数据信息中添加自己信息.
             cbWndExtra 用于添加信息的内存的大小
             SetWindowLong 将信息保存到内存中
             GetWindowLong 将信息从内存中取出

    View Code
    #include <windows.h>
    #include "stdio.h"
    
    HINSTANCE g_hInst = NULL;
    LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, 
                             WPARAM wParam, LPARAM lParam)
    {
        switch(nMsg) {
        case WM_DESTROY: PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hWnd, nMsg, wParam, lParam);
    }
    
    BOOL RegisterWnd(LPSTR pszClassName)
    {
        WNDCLASSEX wce = {0};
        wce.cbSize = sizeof(wce);
        wce.style = CS_VREDRAW|CS_HREDRAW;
        wce.lpfnWndProc = WndProc;
        wce.cbClsExtra = 100;
        wce.cbWndExtra = 100;
        wce.hCursor = NULL;
        wce.hIcon = NULL;
        wce.hbrBackground = HBRUSH(COLOR_BTNFACE+1);
        wce.lpszClassName = pszClassName;
        wce.lpszMenuName = NULL;
        wce.hInstance = g_hInst;
        ATOM nAtom = RegisterClassEx(&wce);
        if(0 == nAtom)
        {
            MessageBox(NULL, "registerError", "Error", MB_OK);
            return FALSE;
        }
        return TRUE;
    }
    
    HWND CreateWnd(LPSTR pszClassName)
    {
        HWND hWnd = CreateWindow(pszClassName,
            "MyWnd", WS_OVERLAPPEDWINDOW, 0, 0, 400, 500,
            NULL, NULL, g_hInst, NULL);
        return hWnd;
    }
    
    void SetExtra(HWND hWnd)
    {
        SetClassLong(hWnd, 1, 100);
        SetWindowLong(hWnd, 1, 200);
    }
    
    void GetExtra(HWND hWnd)
    {
        DWORD nClass = GetClassLong(hWnd, 1);
        DWORD nWnd = GetWindowLong(hWnd, 1);
    
        CHAR szText[256] = {0};
        sprintf(szText, "CLS:%d WND:%d", nClass, nWnd);
        MessageBox(NULL, szText, "Extra", MB_OK);
    }
    
    void DisplayWnd(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    
    void Message()
    {
        MSG msg = {0};
        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    int WINAPI WinMain(HINSTANCE hInst,
                       HINSTANCE hPrevInt,
                       LPSTR lpCmdLine,
                       int nShowCmd)
    {
        g_hInst = hInst;
        RegisterWnd("MyWnd1");
        HWND hMyWnd1 = CreateWnd("MyWnd1");
        HWND hMyWnd2 = CreateWnd("MyWnd1");
    
        SetExtra(hMyWnd1);
        GetExtra(hMyWnd1);
        GetExtra(hMyWnd2);
    
        DisplayWnd(hMyWnd1);
        Message();
        return 0;
    }

       2.3 窗口类的相关函数
        RegisterClass/RegisterClassEx 注册
         UnregisterClass 注销
         GetClassInfo/GetClassInfoEx 获取信息
         GetClassName 获取窗口的窗口类名称
         GetClassLong/SetClassLong 窗口类附加数据的设置和获取
         GetWindowLong/SetWindowLong 窗口的附加数据的设置和获取
       
        2.4 创建窗口时如何定位窗口类
       
          2.4.1 查找应用程序局部的窗口类。如果找到,执行2.4.2,否则执行2.4.3
          2.4.2 如果找到名称一致的窗口类,会比较HISNTANCE句柄。如果相等,就使用找到的窗口类信息创建窗口,如果不同,继续查找,执行2.4.3。
          2.4.3 如果未找到名称一致的窗口类,会继续在应用程序全局窗口类中查找。如果找到,执行2.4.4,否则执行2.4.5
          2.4.4 全局窗口类找到一致的,使用找到的窗口类信息创建窗口。
          2.4.5 系统全局窗口类中查找。如果找到,创建窗口,否则返回失败。

      3 窗口创建
      
        3.1 窗口创建函数

          CreateWindow/CreateWindowEx
          HWND CreateWindowEx(
                      DWORD dwExStyle,//窗口的扩展样式
                      LPCTSTR lpClassName,  // pointer to registered class name
                      LPCTSTR lpWindowName, // pointer to window name
                      DWORD dwStyle,        // window style
                      int x,                // horizontal position of window
                      int y,                // vertical position of window
                      int nWidth,           // window width
                      int nHeight,          // window height
                      HWND hWndParent,      // handle to parent or owner window
                      HMENU hMenu,          // handle to menu, or child-window identifier
                      HINSTANCE hInstance,  // handle to application instance
                      LPVOID lpParam );     // pointer to window-creation data

       3.2 窗口风格和扩展风格
      
          窗口风格: WS_XXXX定义的风格,是窗口的基本风格.
          扩展风格: WS_EX_XXXXX 定义的风格,是窗口的扩展风格.比如: ToolWindow窗口等等.
          在CreateWindow可以使用基本窗口风格,扩展的窗口风格,需要使用CreateWindowEx设置.
         
          WS_OVERLAPPED窗口,层叠式窗口
          WS_POPUP窗口,弹出式窗口
          WS_CHILD窗口,子窗口
         
         3.3 父窗口和子窗口
            3.3.1 CreateWindow时,指定父窗口
            3.3.2 将窗口的风格增加WS_CHILD
            3.3.3 可以使用SetParent和GetParent函数设置和获取指定窗口的父窗口.
              
            其他: MoveWindow 移动窗口.

         3.4 MDI窗口的创建
            3.4.1 创建主窗口
               注册主窗口类型,创建主窗口.

                            HWND hWnd = CreateWindowEx( 0,
                                pszClassName, "MainWnd", 
                                WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
                                CW_USEDEFAULT, CW_USEDEFAULT,
                                CW_USEDEFAULT, NULL, NULL, g_hInst,
                                NULL );

            3.4.2 MDICLIENT窗口
              1 添加CLIENTCREATESTRUCT结构,作为附加数据
          CLIENTCREATESTRUCT cs = { 0 };
          cs.idFirstChild = 1000;//MDI第一个子窗口的ID
          2 创建时,使用"MDICLIENT"窗口类型.
          3 它的父窗口是主窗口

                            HWND hWnd = CreateWindowEx( 0,
                                "MDICLIENT", "MainWnd", 
                                WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,
                                CW_USEDEFAULT, CW_USEDEFAULT,
                                CW_USEDEFAULT, hParent, NULL, g_hInst,
                                &cs );

            3.4.3 创建一个MDI子窗口
                1 注册主窗口类型,创建子窗口
                2 它的父窗口为MDICLIENT窗口
                3 增加WS_EX_MDICHILD的风格

                          HWND hWnd = 
                          CreateWindowEx( WS_EX_MDICHILD,
                            pszClassName, "ChildWnd", 
                            WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, hParent, NULL, 
                            g_hInst, NULL );
    View Code
    // WinMDI.cpp : Defines the entry point for the application.
    //
    
    #include "stdafx.h"
    
    HINSTANCE g_hInst = NULL;
    HWND g_hMDIClient = NULL;
    
    //主窗口的窗口处理函数
    LRESULT CALLBACK MainProc( HWND hWnd,
                               UINT nMsg,
                               WPARAM wParam,
                               LPARAM lParam )
    {
        switch( nMsg )
        {
        case WM_DESTROY:
            PostQuitMessage( 0 );
            return 0;
        }
        return DefFrameProc( hWnd, g_hMDIClient,
            nMsg, wParam, lParam );
    }
    //子窗口的窗口处理函数
    LRESULT CALLBACK ChildProc( HWND hWnd,
                                UINT nMsg,
                                WPARAM wParam,
                                LPARAM lParam )
    {
        return DefMDIChildProc( hWnd, nMsg,
            wParam, lParam );
    }
    //窗口注册函数
    BOOL RegisterWnd( LPSTR   pszClassName,
                      WNDPROC Proc,
                      int     nBrush )
    {
        WNDCLASSEX wce = { 0 };
        wce.cbSize     = sizeof( wce );
        wce.style      = CS_HREDRAW|CS_VREDRAW;
        wce.cbClsExtra = 0;
        wce.cbWndExtra = 0;
        wce.lpfnWndProc= Proc;
        wce.hInstance  = g_hInst;
        wce.hCursor    = NULL;
        wce.hIcon      = NULL;
        wce.hbrBackground = HBRUSH(nBrush);
        wce.lpszClassName = pszClassName;
        wce.lpszMenuName  = NULL;
        wce.hIconSm       = NULL;
    
        ATOM nAtom = RegisterClassEx( &wce );
        if( nAtom == 0 )
        {
            return FALSE;
        }
        return TRUE;
    }
    //显示窗口
    void DisplayWnd( HWND hWnd )
    {
        ShowWindow( hWnd, SW_SHOW );
        UpdateWindow( hWnd );
    }
    //消息循环
    void Message( )
    {
        MSG msg = { 0 };
        while( GetMessage( &msg, NULL, 0, 0 ) )
        {
            DispatchMessage( &msg );
        }
    }
    //创建主窗口
    HWND CreateMainWnd( LPSTR pszClassName )
    {
        HWND hWnd = CreateWindowEx( 0,
            pszClassName, "MainWnd", 
            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, NULL, NULL, g_hInst,
            NULL );
        return hWnd;
    }
    //创建MDICLIENT窗口
    HWND CreateMDIClient( HWND hParent )
    {
        CLIENTCREATESTRUCT cs = { 0 };
        cs.idFirstChild = 1000;
        HWND hWnd = CreateWindowEx( 0,
            "MDICLIENT", "MainWnd", 
            WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, hParent, NULL, g_hInst,
            &cs );
        return hWnd;
    }
    //创建MDI子窗口
    HWND CreateChildWnd( LPSTR pszClassName, 
                         HWND hParent )
    {
        HWND hWnd = CreateWindowEx( WS_EX_MDICHILD,
            pszClassName, "ChildWnd", 
            WS_CHILD|WS_VISIBLE, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, hParent, NULL, g_hInst,
            NULL );
        return hWnd;
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {    //注册主窗口
        RegisterWnd( "MainWnd", MainProc, 
            COLOR_BTNFACE+1 );
        //注册子窗口
        RegisterWnd( "ChildWnd", ChildProc,
            COLOR_WINDOW );
        //创建MDI主窗口
        HWND hMain = CreateMainWnd( "MainWnd" );
        //创建MDICLIENT窗口
        g_hMDIClient = CreateMDIClient( hMain );
        MoveWindow( g_hMDIClient, 0, 0, 500, 
            500, TRUE );
        //创建MDI子窗口
        CreateChildWnd( "ChildWnd", 
            g_hMDIClient );
        CreateChildWnd( "ChildWnd", 
            g_hMDIClient );
        CreateChildWnd( "ChildWnd", 
            g_hMDIClient );
    
        //显示和消息处理
        DisplayWnd( hMain );
        Message( );
        return 0;
    }
    View Code
    // WinCreate.cpp : Defines the entry point for the application.
    //
    
    #include "stdafx.h"
    
    HINSTANCE g_hInst = NULL;
    // 父窗口的处理函数
    LRESULT CALLBACK WndProc( HWND hWnd,
                              UINT nMsg,
                              WPARAM wParam,
                              LPARAM lParam )
    {
        switch( nMsg )
        {
        case WM_DESTROY:
            PostQuitMessage( 0 );
            return 0;
        }
        return DefWindowProc( hWnd, nMsg, 
            wParam, lParam );
    }
    //子窗口的处理函数
    LRESULT CALLBACK ChildProc( HWND hWnd,
                                UINT nMsg,
                                WPARAM wParam,
                                LPARAM lParam )
    {
        return DefWindowProc( hWnd, nMsg, 
            wParam, lParam );
    }
    //消息处理函数
    void Message( )
    {
        MSG msg = { 0 };
        while( GetMessage( &msg, NULL, 0, 0 ) )
        {
            DispatchMessage( &msg );
        }
    }
    //显示窗口
    void DisplayWnd( HWND hWnd )
    {
        ShowWindow( hWnd, SW_SHOW );
        UpdateWindow( hWnd );
    }
    //创建窗口
    HWND CreateWnd( LPSTR pszClassName, 
                    DWORD nStyle,
                    HWND  hParent )
    {
        HWND hWnd = CreateWindowEx( 
            0,
            pszClassName, 
            "MyWnd", 
            nStyle,
            CW_USEDEFAULT, 
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            hParent,NULL,g_hInst,NULL );
        return hWnd;
    }
    //注册窗口
    BOOL RegisterWnd( LPSTR      pszClassName, 
                      WNDPROC proc,
                      int     nBrush )
    {
        WNDCLASSEX wce = { 0 };
        wce.cbSize      = sizeof( wce );
        wce.style       = CS_HREDRAW|CS_VREDRAW;
        wce.cbClsExtra  = 0;
        wce.cbWndExtra  = 0;
        wce.lpfnWndProc = proc;
        wce.hIcon        = NULL;
        wce.hCursor     = NULL;
        wce.hbrBackground = HBRUSH( nBrush );
        wce.hInstance     = g_hInst;
        wce.lpszClassName = pszClassName;
        wce.lpszMenuName  = NULL;
        wce.hIconSm       = NULL;
        ATOM nAtom = RegisterClassEx( &wce );
        if( 0 == nAtom )
        {
            return FALSE;
        }
        return TRUE;
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
        g_hInst = hInstance;
        //注册父窗口类
        RegisterWnd( "MyWnd", WndProc, 
            COLOR_BTNFACE+1 );
        //注册子窗口类
        RegisterWnd( "Child", ChildProc,
            COLOR_WINDOW );
        //创建父窗口
        HWND hWnd = CreateWnd( "MyWnd", 
            WS_OVERLAPPEDWINDOW, NULL );
        //创建子窗口
        HWND hChild1 = CreateWnd( "Child", 
            WS_CHILD|WS_VISIBLE|WS_BORDER|
            WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|
            WS_MINIMIZEBOX|WS_MAXIMIZEBOX, 
            hWnd );
        HWND hChild2 = CreateWnd( "Child", 
            WS_POPUP|WS_VISIBLE|
            WS_THICKFRAME|WS_CAPTION|WS_SYSMENU, 
            hWnd );
        HWND hChild3 = CreateWnd( "Child", 
            WS_CHILD|WS_VISIBLE|WS_BORDER, 
            hWnd );
        //移动窗口位置
        MoveWindow( hChild1, 100, 100, 
            200, 200, TRUE );
        MoveWindow( hChild2, 100, 200, 
            200, 200, TRUE );
        MoveWindow( hChild3, 100, 300, 
            200, 200, TRUE );
        //显示父窗口
        DisplayWnd( hWnd );
        Message( );
        return 0;
    }
  • 相关阅读:
    [Tensorflow2.0] 入门
    重新开始深度学习
    大秦小记三
    大秦小记二
    大秦小记一
    大秦小记初始篇
    js事件高级
    jsDOM
    css样式
    c#压缩文件和批量压缩文件
  • 原文地址:https://www.cnblogs.com/tangzhengyue/p/2633933.html
Copyright © 2020-2023  润新知