SDK implements partitionables

xiaoxiao2021-03-06  19

The separator in Windows is a widely used control, and most of the Explorer models use this control. However, there are very few relevant information to introduce it's full implementation, so I realize one, I hope to help SDK's enthusiasts. In fact, the separator is also a very ordinary window, which also has its own window class, its own window process - just like all predefined controls. That is, to create a partition, you also need to perform the creation of the registration and window of the window class. The following sample code demonstrates how to register a window class: WNDCLASS WC; wc.cbclsextra = 0; wc.cbwndextra = 0; wc.hbrbackground = (HBRUSH) color_btnshadow; // 1 wc.hcursor = loadingcursor (null, IDC_SIZEWE); // 2 wc.hicon = null; wc.hinstance = hinstance; wc.lpfnwndproc = (wndproc) procsplitter; // 3 wc.lpszclassName = "mysplitter"; // 4 wc.lpszMenuname = null; wc.style = 0; RegisterClass (& WC); this code believes that everyone is already very familiar, so I only briefly explain four points: 1, the background color of the partition, here I take the default dialog box background color; 2, partition strip Mouse pointer, here I take the level of adjustment size pointer; 3, this is the window process of the separator, all the secrets are in this callback function; 4, the partition of the window class name, you can just take a one you like name. After successfully registering the window class, you can create a separator. The following is my example interface, which consists of a tree view, a partition, a list view, and a status bar, all code below is based on this interface.

Before writing the window procedure of the separator, I will first process the WM_SIZE message of the dialog as a warm-up process. The code is as follows (you will find that I don't have any declarations for htree, hstatus, hsplitter, and hlist in the entire code, because I declare all these things in order for global variables): Case WM_SIZE : {hDWP hdwp; RECT rect, rectStatus, rectTree; hdwp = BeginDeferWindowPos (4); GetClientRect (hDlg, & rect); GetClientRect (hStatus, & rectStatus); GetWindowRect (hTree, & rectTree); DeferWindowPos (hdwp, hStatus, NULL, 0, rect.bottom - rectStatus.bottom, rect.right, rectStatus.bottom, SWP_NOZORDER); DeferWindowPos (hdwp, hTree, NULL, 0, 0, rectTree.right - rectTree.left, rect.bottom - rectStatus.bottom, SWP_NOMOVE | SWP_NOZORDER ); DeferWindowPos (hdwp, hSplitter, NULL, rectTree.right - rectTree.left, 0, 2, rect.bottom - rectStatus.bottom, SWP_NOZORDER); DeferWindowPos (hdwp, hList, NULL, rectTree.right - rectTree.left 2 , 0, Rect.right RectTree.Left - 2, Rect.Bottom - RectStatus.Bottom, SWP_NOZORDER; EnddeferWindowPos (HDWP);} Break; You have already noticed that most of this code is It is playing games with rectangles. This is indeed because the process of adjusting the window size is a process of changing the location and size of each sub-window. This process is described by: 1. First, place the status bar at the bottom of the dialog; 2. Step 2, does not change the position and width of the tree view, reset it; 3, do not change the separator The position and width, reset it; 4, make the list view account for the remaining customer area.

If you understand the above code, then the separator window has no difficulty: LRESULT CALLBACK PROCSPLITER (HWND HWND, UINT MSG, WPARAM WPARAM, LPARAM LPARAM) {Switch (MSG) {Case WM_LButtondown: SetCapture (hwnd ); break; case WM_LBUTTONUP: ReleaseCapture (); break; case WM_MOUSEMOVE: {if ((wParam & MK_LBUTTON) == MK_LBUTTON && GetCapture () == hwnd) {hDWP hdwp; RECT rect, rectStatus, rectTree; hdwp = BeginDeferWindowPos ( 3); GetClientRect (GetParent (hwnd), & rect); GetClientRect (hStatus, & rectStatus); GetWindowRect (hTree, & rectTree); DeferWindowPos (hdwp, hTree, NULL, 0, 0, rectTree.right - rectTree.left (short) LOWORD (lParam), rect.bottom - rectStatus.bottom, SWP_NOMOVE | SWP_NOZORDER); DeferWindowPos (hdwp, hSplitter, NULL, rectTree.right - rectTree.left (short) LOWORD (lParam), 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER); DeferWindowPos (HDWP, HLIST, NULL, RectTree.right - RectTree.Left (Short) 2, 0, Rect.right - RectTree.right RectTree.Left - (Short) LO WORD (lParam) - 2, rect.bottom - rectStatus.bottom, SWP_NOZORDER); EndDeferWindowPos (hdwp);}} break; default: return DefWindowProc (hwnd, Msg, wParam, lParam);} return 0;} SetCapture and are ReleaseCapture Capture and release the mouse when the left mouse button is pressed and released, which is the general requirement of the separator. The core part of this code is the event that the mouse movement is handled, that is, when the left mouse button is pressed and the separator captures the position and width of the three related windows. The specific rectangular operation is similar to the principle of code of the main window WM_SIZE, I will not say much. The reason why I don't use MoveWindow's function is changed, that is, because these functions make the form's multiple redrawing, causing the entire form of flashing - and in fact I don't want the status bar to flash. The sliding strip on the upper side is a "dynamic" separator, that is, the size of the window has also changed while moving the separator. I will introduce a "static" partition, that is, a vertical line appears when dragging the separator, indicating the separation result of the separator. If the dynamic separator is playing games with the rectangle, the static separator is playing with graphics.

First of all please look at my code: LRESULT CALLBACK ProcSplitter (HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {static int x; switch (Msg) {case WM_LBUTTONDOWN: {HDC hdc; RECT rectTree; SetCapture (hwnd); GetWindowRect (HTREE, & Recttree); HDC = getdc (getParent (hwnd)); SelectObject (HDC, Createpen (PS_SOLID, 2, 0)); SETROP2 (HDC, R2_NOTXORPEN); x = RectTree.right - RectTree.Left; MoveToex (HDC , X, 0, NULL; LINETO (HDC, X, RectTree.bottom - RectTree.top); ReleaseDC (GetParent (HWND), HDC);} Break; Case WM_LButtonup: {HDWP HDWP; HDC HDC; Rect Rect, RectTree , rectStatus; GetClientRect (GetParent (hwnd), & rect); GetWindowRect (hTree, & rectTree); GetClientRect (hStatus, & rectStatus); hdc = GetDC (GetParent (hwnd)); SelectObject (hdc, CreatePen (PS_SOLID, 2, 0)) SETROP2 (HDC, R2_NOTXORPEN); MoveToex (HDC, X, 0, Null); Lineto (HDC, X, RectTree.bottom - RectTree.top); ReleaseDC (GetParent (HWND), HDC); ReleaseCapture (); HDWP = BegindeferWindowPOS (3); DeferWindowPOS (HDWP, Htree, NULL, 0, 0, X, Rect.bottom - RectStatus.Bottom, SWP_Nomove | SWP_NOZORDER); DeferWindowPos (HDWP, HSplitter, Null, X, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER ); DeferWindowPOS (HDWP, HLIST, NULL, X 2, 0, Rect.right - X - 2, Rect.Bottom - RectStatus.bottom, SWP_NOZORDER); EnddeferWindowPos (HDWP);} Break; Case WM_MouseMove: {IF ( wParam & MK_LBUTTON) == MK_LBUTTON && GetCapture () == hwnd) {HDC hdc; RECT rectTree; GetWindowRect (hTree, & rectTree); hdc = GetDC (GetParent (hwnd)); SelectObject (hdc, CreatePen (PS_SOLID, 2, 0 ))); SETROP2 (HDC, R2_NOTXORPEN); MoveToex (HDC, X, 0, NULL);

转载请注明原文地址:https://www.9cbs.com/read-56647.html

New Post(0)