zoukankan      html  css  js  c++  java
  • 5.窗口类和窗口的附加数据

    附加数据的作用:

      注册窗口时,设置这两个数据的大小,可以提供窗口类和窗口存放自己的数据的空间。

    1.窗口类附加数据

      int cbClsExtra    //窗口类附加数据buff大小      

     (1)用法:

        a.申请缓冲区

          窗口对象.cbClsExtra = 200;  //一般赋4的倍数

        b.写入数据

          DWORD  SetClassLong ( HWND  hWnd,         //窗口句柄

                                          int       nIndex,        //字节索引号(从哪个字节开始存)

                                          LONG  dwNewLong);  //存入的数据

        c.读取数据

          DWORD  GetClassLong ( HWND  hWnd,  //窗口句柄

                                                         int       nIndex); //字节索引号(从哪个字节开始读)

                     //返回值获取读到的数据

    2.窗口附加数据缓冲区

      int cbWndExtra  //窗口附加数据buff大小

     (1)用法:

        a.申请缓冲区

          窗口对象.cbWndExtra = 200;  //一般是4的倍数

        b.写入数据

          LONG  SetWindowLong ( HWND  hWnd,         //窗口句柄

                                          int        nIndex,        //字节索引号(从哪个字节开始存)

                                          LONG   dwNewLong); //写入的数据

        c.读取数据

          LONG  GetWindowLong ( HWND  hWnd,   //窗口句柄

                                           int        nIndex);  //字节索引号(从哪个字节开始读)

          //返回值是读到的数据

    3.区别

      窗口类附加数据缓冲区:是所有基于该窗口类创建出来的窗口共享的缓冲区。

      窗口附加数据缓冲区:是窗口自己私有的缓冲区,即便是基于同一个窗口类创建出来的窗口,相互之间也不共享。

    下面是示例代码:

    #include "stdafx.h"
    #include "stdio.h"
    
    HINSTANCE g_hInstance = 0;  //接收当前程序实例句柄
    
    //窗口处理函数
    //CALLBACK即回调,我们定义函数我们不调用,操作系统调用,仅限windows系统
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);  //能够使GetMessage返回0
            break;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    //注册窗口类
    BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
    {
        WNDCLASSEX wce = { 0 };
    
        wce.cbSize        = sizeof(wce);
        wce.cbClsExtra    = 200;
        wce.cbClsExtra    = 200;
        wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wce.hCursor       = NULL;
        wce.hIcon         = NULL;
        wce.hIconSm       = NULL;
        wce.hInstance     = g_hInstance;
        wce.lpfnWndProc   = wndProc;
        wce.lpszClassName = lpClassName;
        wce.lpszMenuName  = NULL;
        wce.style         = CS_HREDRAW | CS_VREDRAW;
       
        ATOM nAtom = RegisterClassEx(&wce);
        if (0 == nAtom)
        {
            return FALSE;
        }
        return TRUE;
    }
    //创建主窗口
    HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName)
    {
        HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW, 
                                   CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                                   NULL, NULL, g_hInstance, NULL);
        return hWnd;
    }
    //创建子窗口
    HWND CreateChildWindow(LPSTR lpClassName, LPSTR lpWndName, HWND hParent)
    {
        HWND hChild = CreateWindowEx(0, lpClassName, lpWndName, WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
                                     100, 100, 200, 200, hParent, NULL, g_hInstance, NULL);
        return hChild;
    }
    //显示窗口
    void Display(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    //消息循环
    void Message()
    {
        MSG nMsg = { 0 };
        while (GetMessage(&nMsg, NULL, 0, 0))
        {
            TranslateMessage(&nMsg);
            DispatchMessage(&nMsg);
        }
    }
    //写入数据
    void SetExtra(HWND hWnd)
    {
        char* pszText = "Hello Data";
        SetClassLong(hWnd, 196, (LONG)pszText);
        SetWindowLong(hWnd, 0, 100);
    }
    //读取数据
    void GetExtra(HWND hWnd)
    {
        LONG nClass = GetClassLong(hWnd, 196);
        LONG nWnd = GetWindowLong(hWnd, 0);
        char szText[256] = { 0 };
        sprintf_s(szText, "窗口类:%s, 窗口:%d", nClass, nWnd);
        MessageBox(NULL, szText, "Info", MB_OK);
    }
    //APIENTRY也是回调函数,APIENTRY和CALLBACK一样,都是__stdcall的别名
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
        g_hInstance = hInstance;
        BOOL nBool = Register("Main", WndProc);
        if (nBool == FALSE)
        {
            MessageBox(NULL, "注册失败", "Info", MB_OK);
        }
        HWND hWnd = CreateMainWindow("Main", "window");    
        Display(hWnd);
    
        BOOL nChild = Register("Child", DefWindowProc);
        if (nChild == FALSE)
        {
            MessageBox(NULL, "注册失败", "Info", MB_OK);
        }
        HWND hChild1 = CreateChildWindow("Child", "c1", hWnd);
        HWND hChild2 = CreateChildWindow("Child", "c2", hWnd);
        MoveWindow(hChild1, 300, 100, 200, 200, TRUE);
        MoveWindow(hChild2, 500, 100, 200, 200, TRUE);
        Display(hChild1);
        Display(hChild2);
    
        SetExtra(hChild1);
        GetExtra(hChild2);
    
        Message();
    
        return 0;
    }
    View Code

    运行结果:

      

      到此为止,窗口的创建已经基本结束

    4.简单的说一下ShowWindow

      在这个函数的内部,我们可以猜想处理过程:

        通过传入的hWnd,找到保存窗口数据的那块内存,然后再根据内存中的数据绘制窗口图像(往显存中写数据)。

  • 相关阅读:
    我罗斯方块最终篇
    我罗斯汇报作业一
    11组-Alpha冲刺-2/6
    11组-Alpha冲刺-1/6
    结对编程作业
    11组 团队展示
    第一次个人编程作业
    第一次博客作业
    寒假作业3
    寒假作业2
  • 原文地址:https://www.cnblogs.com/csqtech/p/5575132.html
Copyright © 2011-2022 走看看