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,找到保存窗口数据的那块内存,然后再根据内存中的数据绘制窗口图像(往显存中写数据)。

posted @ 2016-06-11 17:43  甩锅侠  阅读(353)  评论(0编辑  收藏  举报