Win32控件-------Tab控件基本架构

来源:互联网 发布:js math函数 编辑:程序博客网 时间:2024/06/04 01:05

窗口的子类化-------------------SetWindowsLongPtr(),GetWindowLongPtr()

窗口的超类化-------------------SetClassLongPtr(),GetClassLongPtr()

所谓子类化,通过同一个WNDCLASS创建窗口,这个WNDCLASS集中了一类窗口的共同特征(如背景,外观等),在CreateWindows过后,通过SetWindowLongPtr()更改响应的窗口处理函数,实现各自的功能。

顺便说一句:SetWindowLongPtr()函数可以兼容32位和64位模式,而SetWindowLong()只能是32位模式

以下是实现了一个Tab和Page,程序的结构:

WndProc()------>

InitTabControl()------->

InitPage()

RegisterWndClass()---------注册窗口类,该函数只调用一次

addPage()-----------------------每添加一个Tab页面,调用一次

InsertTabItem()-----添加标签

CreatePageWnd()---创建窗口。




#define UNICODE#define _UNICODE#include <windows.h>#include <objidl.h>#include <gdiplus.h>using namespace Gdiplus;//控件库以及相关宏#include <windowsx.h>//有HANDLE_MSG宏+标准控件功能函数宏#include <commctrl.h>//高级控件函数宏#include<stdio.h>#include<tchar.h>//依赖库#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];//资源区#pragma region Page1#pragma region PageLRESULT CALLBACK Page2Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){HDC          hdc;PAINTSTRUCT  ps;switch (message){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, message, wParam, lParam);}}LRESULT CALLBACK Page1Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){HDC          hdc;PAINTSTRUCT  ps;switch (message){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, message, 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, WNDPROC PageWndProc){RECT rcTabDisplay;//获取Tab控件客户区的的大小(Tab窗口坐标系)GetClientRect(hTab, &rcTabDisplay);//获取Tab窗口的大小(而不是在屏幕坐标系中)TabCtrl_AdjustRect(hTab, FALSE, &rcTabDisplay);//通过窗口大小,获取客户区大小。//创建与Tab控件客户区大小的画布HWND hPage = CreateWindowEx(NULL,//window extend StyleTEXT("Page"),   // window class nameNULL,  // window captionWS_CHILD,      // window stylercTabDisplay.left,            // initial x positionrcTabDisplay.top,            // initial y positionrcTabDisplay.right,            // initial x sizercTabDisplay.bottom,            // initial y sizehTab,                     // parent window handleNULL,                     // window menu handlehInst,                // program instance handleNULL);                    // creation parametersSetWindowLongPtr(hPage, GWLP_WNDPROC, (LONG_PTR)PageWndProc);//子类化窗口return hPage;}/*功能:向Tab中添加页面实现原理:一个窗口多个窗口处理函数,每个窗口处理函数负责一个页面的布局和处理注意:该添加方式是顺序添加,即AddAfter,在当前页面后添加*/BOOL addPage(HWND hTab, LPTSTR strPageLabel, WNDPROC 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, TEXT("Page1"), Page1Proc);addPage(hTab, TEXT("Page2"), Page2Proc);addPage(hTab, TEXT("Page3"), Page2Proc);return TRUE;}#pragma endregion#pragma region TabControlHWND 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 fontSendMessage(hTab, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);//根据页面来初始化页面InitPages(hTab);ShowWindow(Page[0], SW_SHOW);//显示第一个页面return hTab;}//三种窗口状态:SIZE_MINIMIZE,SIZE_MAXIMIZE,SIZE_RESTOREDLRESULT 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); //客户区HeightLOWORD(lParam);//WidthRECT rcTab;// 缩放Tab//HIWORD(lParam)-----hWnd height,LOWORD(lParam)-----hWnd widthMoveWindow(hTab, 0, 0, LOWORD(lParam),HIWORD(lParam), TRUE);//缩放PageGetClientRect(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是发出通知的窗口Handleswitch (((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){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 nameTEXT("Getting Started"),  // window captionWS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,      // window styleCW_USEDEFAULT,            // initial x positionCW_USEDEFAULT,            // initial y positionCW_USEDEFAULT,            // initial x sizeCW_USEDEFAULT,            // initial y sizeNULL,                     // parent window handleNULL,                     // window menu handlehInstance,                // program instance handleNULL);                    // creation parametersShowWindow(hWnd, iCmdShow);UpdateWindow(hWnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}GdiplusShutdown(gdiplusToken);return msg.wParam;}



0 0