4.注册窗口类和创建窗口

1.注册窗口类函数

  (1)RegisterClass/RegisterClassEx

    ATOM RegisterClass(CONST WNDCLASS *lpWndClass);

    ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx);

    注册成功后,返回一个非0数字标识,失败返回0。

  (2)窗口类的风格

    CS_GLOBALCLASS - 应用程序全局窗口类

    CS_BYTEALIGNCLIENT - 窗口客户区的水平位置8整倍数据对齐

    CS_BYTEALIGNWINDOW - 窗口的水平位置8整倍数据对齐

    CS_HREDRAW - 当窗口水平变化时,窗口重新绘制

    CS_VREDRAW - 当窗口垂直变化时,窗口重新绘制

    CS_CLASSDC - 该类型的窗口,都是有同一个绘图(DC)设备

    CS_PARENTDC - 该类型的窗口,使用它的父窗口的绘图(DC)设备

    CS_OWNDC - 该类型的窗口,每个窗口都是用自己的绘图(DC)设备

    CS_SAVEBITS - 允许窗口保存成图(位图),提高窗口的绘图效率,但是耗费内存资源

    CS_DBLCLKS - 允许窗口接收鼠标双击

    CS_NOCLOSE - 窗口没有关闭按钮

下面是简单的示例代码:

#include "stdafx.h"


HINSTANCE g_hInstance = 0;

void AppReg()
{
    //注册窗口类
    WNDCLASSEX wce = { 0 };

    wce.cbSize        = sizeof(wce);               //大小
    wce.cbClsExtra    = 0;                         //窗口类附加数据buffer的大小
    wce.cbWndExtra    = 0;                         //窗口的附加数据buffer的大小
    wce.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);  //背景为白色
    wce.hCursor       = NULL;                      //默认光标
    wce.hIcon         = NULL;                      //默认大图标
    wce.hIconSm       = NULL;                      //默认小图标
    wce.hInstance     = g_hInstance;               //当前程序实例句柄
    wce.lpfnWndProc   = DefWindowProc;             //系统默认窗口处理函数
    wce.lpszClassName = "Main";                    //窗口类名
    wce.lpszMenuName  = NULL;                      //窗口菜单
    wce.style         = CS_HREDRAW | CS_VREDRAW;   //窗口风格

    //将以上赋值写入操作系统
    ATOM nAtom = RegisterClassEx(&wce);

    if (nAtom == 0)
    {
        MessageBox(NULL, "注册失败", "Info", MB_OK);
        return;
    }

    HWND hWnd = CreateWindow("Main", "Window", WS_OVERLAPPEDWINDOW,
                             100, 100, 500, 500, NULL, NULL, g_hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);

    MSG uMsg = { 0 };
    while (GetMessage(&uMsg, NULL, 0, 0))
    {
        TranslateMessage(&uMsg);
        DispatchMessage(&uMsg);
    }
}


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       cCmdShow)
{
    g_hInstance = hInstance;
    AppReg();
    return 0;
}
View Code

2.创建窗口

  (1)创建窗口函数CreateWindow/CreateWindowEx

    CreateWindowEx(

      DWORD      dwExStyle,          //窗口的扩展风格,CreateWindow没有这个参数

      LPCTSTR     lpClassName,      //窗口类名

      LPCTSTR     lpWindowName,  //窗口标题栏名

      DWORD      dwStyle,             //窗口基本风格

      int               x,                     //窗口左上角横坐标

      int               y,                      //窗口左上角纵坐标

      int               nWidth,             //窗口宽度

      int               nHeight,            //窗口高度

      HWND          hWndParent,     //窗口的父窗口句柄

      HMENU         hMenu,             //窗口菜单句柄

      HINSTANCE   hInstance,        //应用程序实例句柄

      LPVOID         lpParam           //窗口创建时附加参数

    );创建成功返回窗口句柄

  (2)子窗口的创建

    创建子窗口时要设置父窗口句柄和WS_CHILD | WS_VISIBLE风格。

  (3)内部执行过程

    CreateWindow用其中两个参数用来确定窗口,CreateWindow("Main", ..., g_hInstance, ...),即窗口类名和当前程序实例句柄。  

    a.系统根据传入的窗口类名称,在应用程序局部窗口类中查找,如果找到执行b,否则执行c。

    b.比较局部窗口类与创建窗口时传入的HINSTANCE变量。如果发现相等,创建和注册的窗口在同一模块,创建窗口返回。否则执行c。

    c.在应用程序全局窗口类中查找,如果找到,执行d,否则执行e。

    d.使用找到的窗口类的信息,创建窗口返回。

    e.在系统窗口类中查找,如果找到,创建窗口,否则窗口创建失败。

    若创建窗口成功,那么CreateWindow就申请内存,将传入的参数写入到内存中,返回这块内存的句柄。

  下面我们看一个比较完整的例子:

  创建了两个子窗口,并解决前面的遗留问题(关闭窗口后,进程并没有退出)

  相关代码: 

#include "stdafx.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    = 0;
    wce.cbClsExtra    = 0;
    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);
    }
}
//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);

    Message();

    return 0;
}
View Code

  运行结果为:

  

 

转载于:https://www.cnblogs.com/csqtech/p/5573809.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值