VC窗口类的相关问题

来源:互联网 发布:西安旅游 知乎 编辑:程序博客网 时间:2024/06/08 10:55

一 窗口注册和创建

  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;}
原创粉丝点击