现在的位置: 首页 > 综合 > 正文

VC窗口类的相关问题

2017年12月04日 ⁄ 综合 ⁄ 共 11450字 ⁄ 字号 评论关闭

一 窗口注册和创建

  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;
}

抱歉!评论已关闭.