zoukankan      html  css  js  c++  java
  • 创建选项卡控件

    #define UNICODE
    #define _UNICODE
    #include <windows.h>
    #include <objidl.h>
    #include <gdiplus.h>
    #include <tchar.h>
    using namespace Gdiplus;
    //控件库以及相关宏
    #include <windowsx.h>//有HANDLE_MSG宏+标准控件功能函数宏
    #include <commctrl.h>//高级控件函数宏
    #include<stdio.h>
    #include<tchar.h>
    #include <string>
    
    #define main_edit 101
    //依赖库
    #pragma comment (lib,"user32.lib")
    #pragma comment(lib, "comctl32.lib")
    #pragma comment (lib,"gdi32.lib")
    #pragma comment (lib,"gdiplus.lib")
    
    #pragma comment (lib,"kernel32.lib")
    
    /*全局变量区*/
    HINSTANCE hInst;
    HWND Page[100];
    
    std::wstring strexepath1 = L"Page1";
    std::wstring strexepath2 = L"Page2";
    std::wstring strexepath3 = L"Page3";
    //资源区#pragma region Page1
    #pragma region Page
    
    LRESULT CALLBACK Page2Proc(HWND hWnd, UINT uMsg, WPARAM wParam,
        LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
    {
        HDC          hdc;
        PAINTSTRUCT  ps;
        switch (uMsg)
        {
        case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            //////////////代码位置/////////////////
            Graphics graphics(hdc);
            graphics.SetSmoothingMode(SmoothingModeAntiAlias);//反锯齿设置
            Pen      pen(Color(255, 255, 0, 255));
            graphics.DrawLine(&pen, 100, 200, 200, 100);
            //graphics.DrawRectangle(&pen, 100, 100, 200, 200);
            ////////////////////////////////////
            EndPaint(hWnd, &ps);
        }
        return 0;
        default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
    }
    
    LRESULT CALLBACK Page1Proc(HWND hWnd, UINT uMsg, WPARAM wParam,
        LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
    {
        HDC          hdc;
        PAINTSTRUCT  ps;
        switch (uMsg)
        {
        case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            //////////////代码位置/////////////////
            Graphics graphics(hdc);
            graphics.SetSmoothingMode(SmoothingModeAntiAlias);//反锯齿设置
            Pen blackPen(Color(255, 0, 0, 0), 3);
            RectF rect1(10.0f, 10.0f, 100.0f, 50.0f);
            RectF rect2(40.0f, 40.0f, 100.0f, 50.0f);
            RectF rect3(80.0f, 4.0f, 50.0f, 100.0f);
            RectF rects[] = { rect1, rect2, rect3 };
            RectF* pRects = rects;
            graphics.DrawRectangles(&blackPen, pRects, 3);
            ////////////////////////////////////
            EndPaint(hWnd, &ps);
        }
        return 0;
        default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
    }
    //功能:向Tab中添加标签
    int InsertTabItem(HWND hTab, LPTSTR pszText, int iid)
    {
        TCITEM ti = { 0 };
        ti.mask = TCIF_TEXT;
        ti.pszText = pszText;
        ti.cchTextMax = wcslen(pszText);
        return (int)SendMessage(hTab, TCM_INSERTITEM, iid, (LPARAM)&ti);
    }
    //Page自己的窗口类,通过SetWindowLongPtr()可以子类化
    ATOM RegisterPageClass()
    {
        WNDCLASSEX wcex;
    
        wcex.cbSize = sizeof(WNDCLASSEX);
        wcex.style = CS_HREDRAW | CS_VREDRAW;
        wcex.cbClsExtra = 0;
        wcex.cbWndExtra = 0;
        wcex.hInstance = hInst;
        wcex.hIcon = NULL;
        wcex.hIconSm = NULL;
        wcex.lpszMenuName = NULL;
        wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wcex.lpszClassName = TEXT("Page");
        wcex.lpfnWndProc = DefWindowProc;
        return RegisterClassEx(&wcex);
    }
    HWND CreatePageWnd(HWND hTab, SUBCLASSPROC PageWndProc)
    {
        RECT rcTabDisplay;
        //获取Tab控件客户区的的大小(Tab窗口坐标系)
        GetClientRect(hTab, &rcTabDisplay);//获取Tab窗口的大小(而不是在屏幕坐标系中)
        TabCtrl_AdjustRect(hTab, FALSE, &rcTabDisplay);//通过窗口大小,获取客户区大小。
        //创建与Tab控件客户区大小的画布
        HWND hPage = CreateWindowEx(
            NULL,        //window extend Style
            TEXT("Page"),   // window class name
            NULL,  // window caption
            WS_CHILD,      // window style
            rcTabDisplay.left,            // initial x position
            rcTabDisplay.top,            // initial y position
            rcTabDisplay.right,            // initial x size
            rcTabDisplay.bottom,            // initial y size
            hTab,                     // parent window handle
            NULL,                     // window menu handle
            hInst,                // program instance handle
            NULL);                    // creation parameters
        int err = GetLastError();
    //    SetWindowLongPtr(hPage, GWLP_WNDPROC, (LONG_PTR)PageWndProc);//子类化窗口
        SetWindowSubclass(hPage, PageWndProc, main_edit, 1);
        return hPage;
    }
    /*
        功能:向Tab中添加页面
        实现原理:一个窗口多个窗口处理函数,每个窗口处理函数负责一个页面的布局和处理
        注意:该添加方式是顺序添加,即AddAfter,在当前页面后添加
    */
    BOOL addPage(HWND hTab, LPTSTR strPageLabel, SUBCLASSPROC PageWndProc)
    {
    
        static int iPageIndex = 0;
        InsertTabItem(hTab, strPageLabel, iPageIndex);
        HWND hPage = CreatePageWnd(hTab, PageWndProc);
        Page[iPageIndex++] = hPage;
        return TRUE;
    }
    
    /*功能:初始化所有页面*/
    BOOL InitPages(HWND hTab)
    {
        RegisterPageClass();
        addPage(hTab, &strexepath1[0], Page1Proc);
        addPage(hTab, &strexepath2[0], Page2Proc);
        addPage(hTab, &strexepath3[0], Page2Proc);
        return TRUE;
    }
    #pragma endregion
    #pragma region TabControl
    HWND InitTabControl(HWND hParentWnd, HWND hWndFocus, LPARAM lParam)
    {
        INITCOMMONCONTROLSEX iccx;
        iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
        iccx.dwICC = ICC_TAB_CLASSES;
        if (!InitCommonControlsEx(&iccx))
            return FALSE;
        // 创建TabControl控件,其实就是一个子窗口和该窗口上的标签,这些标签是Tab控件具有的,但没有与具体的页面相连,只是Tab控件的特有属性而已。
        //////////////////////////////创建Tab控件/////////////////////////////////////////////////////
        RECT rc;
        GetClientRect(hParentWnd, &rc);
        HWND hTab = CreateWindowEx(0, WC_TABCONTROL, 0,
            TCS_FIXEDWIDTH | WS_CHILD | WS_VISIBLE,
            rc.left + 2, rc.top + 2, rc.right - 4, rc.bottom - 4,
            hParentWnd, NULL, hInst, 0);
    
        // Set the font of the tabs to a more typical system GUI font
        SendMessage(hTab, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
        //根据页面来初始化页面
        InitPages(hTab);
        ShowWindow(Page[0], SW_SHOW);//显示第一个页面
        return hTab;
    }
    
    //三种窗口状态:SIZE_MINIMIZE,SIZE_MAXIMIZE,SIZE_RESTORED
    LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HWND hTab;
    
        switch (message)
        {
        case WM_CREATE:
            hTab = InitTabControl(hWnd, NULL, lParam);//主窗口创建的时候,同时创建Tab子窗口
            break;
        case WM_SIZE://改变完成之后
            HIWORD(lParam); //客户区Height
            LOWORD(lParam);//Width
            RECT rcTab;
            // 缩放Tab
            //HIWORD(lParam)-----hWnd height,LOWORD(lParam)-----hWnd width
            MoveWindow(hTab, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
            //缩放Page
            GetClientRect(hTab, &rcTab);
            TabCtrl_AdjustRect(hTab, FALSE, &rcTab);
            for (int i = 0; i < TabCtrl_GetItemCount(hTab); i++)
                MoveWindow(Page[i], rcTab.left, rcTab.top, rcTab.right, rcTab.bottom, TRUE);
            break;
        case WM_NOTIFY://WM_NOTIFY消息中,lParam是一个NMHDR结构,code字段是具体通知消息,hwndFrom是发出通知的窗口Handle
            switch (((LPNMHDR)lParam)->code)
            {
            case TCN_SELCHANGING://Tab改变前
            {
                int iPage = TabCtrl_GetCurSel(hTab);
                ShowWindow(Page[iPage], SW_HIDE);
                return FALSE;
            }
            case TCN_SELCHANGE://Tab改变后
            {
                int iPage = TabCtrl_GetCurSel(hTab);
                ShowWindow(Page[iPage], SW_SHOW);
                return TRUE;
            }
            }
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
    {
        static HWND hWnd;
        MSG                 msg;
        WNDCLASS            wndClass;
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR           gdiplusToken;
        hInst = hInstance;
        // Initialize GDI+.
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
        wndClass.style = CS_HREDRAW | CS_VREDRAW;
        wndClass.lpfnWndProc = MainWndProc;
        wndClass.cbClsExtra = 0;
        wndClass.cbWndExtra = 0;
        wndClass.hInstance = hInstance;
        wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndClass.lpszMenuName = NULL;
        wndClass.lpszClassName = TEXT("GettingStarted");
    
        RegisterClass(&wndClass);
    
        hWnd = CreateWindow(
            TEXT("GettingStarted"),   // window class name
            TEXT("Getting Started"),  // window caption
            WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,      // window style
            CW_USEDEFAULT,            // initial x position
            CW_USEDEFAULT,            // initial y position
            CW_USEDEFAULT,            // initial x size
            CW_USEDEFAULT,            // initial y size
            NULL,                     // parent window handle
            NULL,                     // window menu handle
            hInstance,                // program instance handle
            NULL);                    // creation parameters
    
        ShowWindow(hWnd, iCmdShow);
        UpdateWindow(hWnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        GdiplusShutdown(gdiplusToken);
        return msg.wParam;
    }

    主要步骤:

    1. 创建主窗口, HWND hWnd = CreateWindow();
    2. 与此同时创建Tab子窗口,因为是放在WM_CREATE中,所以创建的过程等同于创建主窗口

                      (1)使用InitCommonControlsEx初始化Tab控件

                      (2)使用HWND hTab = CreateWindowEx(0, WC_TABCONTROL,,,,,)创建tab子窗口

             3. Tab窗口创建完之后,需要创建tab窗口下的页面窗口(选项卡各个窗口都是独立)

                        (1)需要注册页面窗口类,这步是为了后面创建页面提供条件,RegisterPageClass(),不然创建页面窗口会显示未注册

                        (2)然后往Tab子窗口中添加标签,即tab1,tab2,tab3选项卡 ,使用 SendMessage(hTab, TCM_INSERTITEM, iid, (LPARAM)&ti);

                        (3)创建与Tab控件客户区大小的画布,即选项卡下的页面窗口,可以展示自定义内容,HWND hPage = CreateWindowEx(NULL, TEXT("Page"), , , ,) 

             4. 子类化页面窗口,这样可以为每个页面窗口指定窗口回调函数, 使用SetWindowSubclass

    注意: WM_NOTIFY是在发生事件或控件需要某些信息时,由公共控件发送到其父窗口,在这个项目中是用作切换tab选项卡

                WM_SIZE 是用作确定tab窗口和页面窗口的位置

                TabCtrl_GetItemCount(hTab) 返回选项卡数,这里创建了3个选项卡,所以返回3

                TabCtrl_AdjustRect 给定窗口矩形,计算选项卡控件的显示区域,或计算与指定显示区域相对应的窗口矩形

     

                        

  • 相关阅读:
    异常及throw、与throws的介绍
    js数组
    正则表达式
    Date对象及toString方法
    js中函数与对象的使用
    js细节
    JavaScript介绍
    浮动、定位
    css背景样式
    盒子模型
  • 原文地址:https://www.cnblogs.com/strive-sun/p/12167377.html
Copyright © 2011-2022 走看看