TreeView 和 Header 控件配合成表结构
作者:互联网
1.利用TreeView和Header控件配合,对TreeView进行部分重绘,做成一个可以展开的表结构。
2.重绘要注意先后顺序。
效果如图。
程序如下:
HeaderTest.cpp
// HeaderTest.cpp : Defines the entry point for the application. // TreeView 和 Header 控件配合成表结构 // XGZ 2022-05-15 SZ #include "stdafx.h" #include "HeaderTest.h" #include "Commctrl.h" #pragma comment(lib,"comctl32.lib") #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int PRINT(TCHAR *fmt, ...); int OnCreate(HWND, UINT, WPARAM, LPARAM); int OnSize(HWND, UINT, WPARAM, LPARAM); int OnDestroy(HWND, UINT, WPARAM, LPARAM); int OnNotify(HWND, UINT, WPARAM, LPARAM); HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel); HWND CreateTreeView (HWND hwndParent); HTREEITEM InsertTreeNode(HWND hWndTV, HTREEITEM hPrev, LPTSTR lpszItem); int InitTreetView (HWND hTreeView); HTREEITEM m_hNodeDevice; HTREEITEM m_hNodeDataBase; HTREEITEM m_hNodeTest; #define IDC_HHEAD 1001 #define IDM_VIEW_TREEVIEW1 1002 #define IDC_EDIT 1003 HWND hWndHead; HWND hWndEdit; HWND hWndTree; int OnTreePaint(HWND, UINT, WPARAM, LPARAM); LONG lpfnDefTree = 0; LRESULT CALLBACK TreeWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { TCHAR wBuf[1024]; switch (message) { case WM_PAINT: OnTreePaint(hWnd, message, wParam, lParam); break; default: break; } return CallWindowProc((WNDPROC)lpfnDefTree, hWnd, message, wParam, lParam); } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_HEADERTEST, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HEADERTEST)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HEADERTEST)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HEADERTEST); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: OnCreate(hWnd, message, wParam, lParam); break; case WM_SIZE: OnSize(hWnd, message, wParam, lParam); break; case WM_DESTROY: OnDestroy(hWnd, message, wParam, lParam); break; case WM_NOTIFY: OnNotify(hWnd, message, wParam, lParam); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for about box. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } int HeadInsertItem(HWND hwndHeader, int iInsertAfter, int nWidth, LPTSTR lpsz) { HDITEM hdi; int index; hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH; hdi.cxy = nWidth; hdi.pszText = lpsz; hdi.cchTextMax = sizeof(hdi.pszText)/sizeof(hdi.pszText[0]); hdi.fmt = HDF_LEFT | HDF_STRING; index = SendMessage(hwndHeader, HDM_INSERTITEM, (WPARAM) iInsertAfter, (LPARAM) &hdi); return index; } int OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i=0; InitCommonControls(); RECT rcParent; HDLAYOUT hdl; WINDOWPOS wp; hWndHead = CreateWindow(WC_HEADER, NULL, WS_CHILD | WS_BORDER |WS_VISIBLE| HDS_BUTTONS | HDS_HORZ, 0,0,0,0, hWnd, (HMENU) IDC_EDIT, hInst, NULL); GetClientRect(hWnd, &rcParent); hdl.prc = &rcParent; hdl.pwpos = ℘ SendMessage(hWndHead, HDM_LAYOUT, 0, (LPARAM) &hdl);
// Set the size, position, and visibility of the header control. SetWindowPos(hWndHead, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_SHOWWINDOW); HeadInsertItem( hWndHead, 0,100, _T("First")); HeadInsertItem( hWndHead, 1,100, _T("Second")); HeadInsertItem( hWndHead, 2,100, _T("Third")); TCHAR strBuf[1024]; hWndEdit = CreateWindow(TEXT("edit"),NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|ES_MULTILINE|WS_VSCROLL, 10,130,600,400, hWnd, (HMENU) IDC_EDIT, hInst, NULL); hWndTree = CreateTreeView(hWnd); InitTreetView(hWndTree); SendMessage(hWndTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)m_hNodeDataBase); lpfnDefTree = SetWindowLong(hWndTree, GWL_WNDPROC, (LONG)TreeWndProc); return 1; } int OnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int cxClient,cyClient; cxClient = LOWORD (lParam); cyClient = HIWORD (lParam); MoveWindow(hWndHead, 5, 5, cxClient-10, 20, TRUE); MoveWindow(hWndTree, 5, 25, cxClient-10, 200, TRUE); //MoveWindow(hWndTree, 5, 25, 100, 200, TRUE); MoveWindow(hWndEdit, 5, 280, cxClient-10, cyClient-290, TRUE); return DefWindowProc(hWnd, message, wParam, lParam); } int OnDestroy(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PostQuitMessage(0); return 1; } int PRINT(TCHAR *fmt, ...) { TCHAR buffer[1024]; va_list argptr; int cnt; int iEditTextLength; HWND hWnd = hWndEdit; if(NULL == hWnd) return 0; va_start(argptr, fmt); //cnt = vsprintf(buffer, fmt, argptr); cnt = vswprintf_s(buffer, fmt, argptr); va_end(argptr); iEditTextLength = GetWindowTextLength(hWnd); if(iEditTextLength + cnt > 30000) // edit text max length is 30000 { SendMessage(hWnd, EM_SETSEL, 0, 10000); SendMessage(hWnd, WM_CLEAR, 0, 0); iEditTextLength = iEditTextLength - 10000; } SendMessage(hWnd, EM_SETSEL, iEditTextLength, iEditTextLength); SendMessage(hWnd, EM_REPLACESEL,0, (LPARAM) buffer); return(cnt); } int OnNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rt; int i; int ItemCount; HTREEITEM hti; TVITEM tvi; TCHAR text[1024]; LPNMHDR lphr = (LPNMHDR)lParam; if (lphr->hwndFrom == hWndHead) { switch (lphr->code) { case HDN_ITEMCLICK: PRINT(_T("\r\n HDN_ITEMCLICK ")); break; case HDN_ITEMCHANGED: PRINT(_T("\r\n HDN_ITEMCHANGED")); ItemCount = Header_GetItemCount(hWndHead); for( i=0; i<ItemCount;i++) { Header_GetItemRect( hWndHead, i, &rt ); PRINT(_T("\r\n hWndHead %d, [%d,%d]"), i, rt.left, rt.right); } InvalidateRect(hWndTree, NULL, TRUE); break; default: break; } } return DefWindowProc(hWnd, message, wParam, lParam); } HWND CreateTreeView (HWND hwndParent) { InitCommonControls(); HINSTANCE app_hInst = (HINSTANCE)GetWindowLong(hwndParent,GWL_HINSTANCE); HWND hWndTreeView = CreateWindow(WC_TREEVIEW, NULL, WS_CHILD|WS_VISIBLE|TVS_HASBUTTONS|TVS_HASLINES|TVS_SHOWSELALWAYS|TVS_LINESATROOT|WS_BORDER, 0, 0,0,0, hwndParent, (HMENU)IDM_VIEW_TREEVIEW1, app_hInst, NULL); return (hWndTreeView); } HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel) { TVITEM tvi; TVINSERTSTRUCT tvins; static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST; static HTREEITEM hPrevRootItem = NULL; static HTREEITEM hPrevLev2Item = NULL; HTREEITEM hti; tvi.mask = TVIF_TEXT | TVIF_PARAM|TVIF_STATE; // Set the text of the item. tvi.pszText = lpszItem; tvi.cchTextMax = sizeof(tvi.pszText)/sizeof(tvi.pszText[0]); tvi.lParam = (LPARAM)nLevel; tvins.item = tvi; tvins.hInsertAfter = hPrev; hPrev = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins); if (hPrev == NULL) return NULL; return hPrev; } HTREEITEM InsertTreeNode(HWND hWndTV, HTREEITEM hPrev, LPTSTR lpszItem) { TVINSERTSTRUCT tvins; TVITEM tvi; tvins.item.mask = TVIF_TEXT ; tvins.item.pszText = lpszItem; tvins.hParent = hPrev; tvins.hInsertAfter = TVI_LAST; return (HTREEITEM)SendMessage(hWndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins); } int InitTreetView(HWND hTreeView) { HTREEITEM hti; m_hNodeDevice = InsertTreeNode(hTreeView, NULL, _T("Device")); m_hNodeDataBase = InsertTreeNode(hTreeView, NULL, _T("DataBase")); m_hNodeTest = InsertTreeNode(hTreeView, NULL, _T("Test")); hti = InsertTreeNode(hTreeView, m_hNodeDevice, _T("IO1")); hti = InsertTreeNode(hTreeView, m_hNodeDevice, _T("IO2")); hti = InsertTreeNode(hTreeView, m_hNodeDevice, _T("Option")); hti = InsertTreeNode(hTreeView, m_hNodeDataBase, _T("SQLite3")); hti = InsertTreeNode(hTreeView, m_hNodeDataBase, _T("Company")); hti = InsertTreeNode(hTreeView, hti, _T("SubCompany")); hti = InsertTreeNode(hTreeView, m_hNodeTest, _T("XTMusic")); hti = InsertTreeNode(hTreeView, m_hNodeTest, _T("XTVideo")); hti = InsertTreeNode(hTreeView, m_hNodeTest, _T("XTCipher")); return 1; } int OnTreePaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; RECT rt; HTREEITEM hti; TVITEM tvi; int iPos[10]; CallWindowProc((WNDPROC)lpfnDefTree, hWnd, message, wParam, lParam); //先画好原来的 //hdc = BeginPaint(hWnd, &ps); //会无效化之前的区域,如使用需指定区域 hdc = GetDC(hWnd); // 保留原先的 int ItemCount = Header_GetItemCount(hWndHead); for( int i=0; i<ItemCount;i++) { Header_GetItemRect( hWndHead, i, &rt ); iPos[i] = rt.right; } TCHAR szText[20]; hti = TreeView_GetFirstVisible(hWndTree ); while(hti) { memset(&tvi, 0, sizeof(tvi)); tvi.mask = TVIF_TEXT | TVIF_PARAM; tvi.hItem = hti; tvi.pszText = szText; tvi.cchTextMax = sizeof(szText); TreeView_GetItem(hWndTree, &tvi); TreeView_GetItemRect(hWnd, hti, &rt, TRUE); //TRUE only Tesxt rt.left = iPos[0]; rt.right = iPos[1]; DrawText(hdc, szText, wcslen(szText), &rt, DT_LEFT); rt.left = iPos[1]; rt.right = iPos[2]; Rectangle(hdc, iPos[1],rt.top+1,iPos[2],rt.bottom-1); DrawText(hdc, _T("50%"),wcslen(_T("50%")), &rt, DT_CENTER); int iDrawMode = SetROP2(hdc, R2_NOT); //画笔取反 Rectangle(hdc, iPos[1], rt.top+1, iPos[1]+(iPos[2]-iPos[1]) * 0.5,rt.bottom-1); SetROP2(hdc, iDrawMode); hti =TreeView_GetNextVisible(hWndTree,hti); } //EndPaint(hWnd, &ps); ReleaseDC(hWnd, hdc); return 1; }
标签:wParam,控件,lParam,int,hWnd,Header,HWND,成表,message 来源: https://www.cnblogs.com/xgz21/p/16273412.html