diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj
index 576759a56..0bc77129f 100644
--- a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj
+++ b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj
@@ -231,6 +231,7 @@
+
diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters
index a40e51ae8..b2bb67aca 100644
--- a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters
+++ b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters
@@ -438,6 +438,9 @@
phlib
+
+ phlib
+
diff --git a/2.x/trunk/ProcessHacker/main.c b/2.x/trunk/ProcessHacker/main.c
index e91957f6c..2bc9bdb6e 100644
--- a/2.x/trunk/ProcessHacker/main.c
+++ b/2.x/trunk/ProcessHacker/main.c
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include
#include
@@ -204,6 +205,7 @@ INT WINAPI WinMain(
PhGuiSupportInitialization();
PhTreeListInitialization();
+ PhTreeNewInitialization();
PhGraphControlInitialization();
PhHexEditInitialization();
diff --git a/2.x/trunk/ProcessHacker/mainwnd.c b/2.x/trunk/ProcessHacker/mainwnd.c
index 75bebfb29..7f440d198 100644
--- a/2.x/trunk/ProcessHacker/mainwnd.c
+++ b/2.x/trunk/ProcessHacker/mainwnd.c
@@ -23,6 +23,7 @@
#define PH_MAINWND_PRIVATE
#include
#include
+#include
#include
#include
#include
@@ -3251,7 +3252,20 @@ VOID PhMainWndOnCreate()
NetworkTabIndex = PhAddTabControlTab(TabControlHandle, 2, L"Network");
MaxTabIndex = NetworkTabIndex;
- ProcessTreeListHandle = PhCreateTreeListControlEx(PhMainWndHandle, ID_MAINWND_PROCESSTL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TLSTYLE_BORDER | TLSTYLE_ICONS);
+ //ProcessTreeListHandle = PhCreateTreeListControlEx(PhMainWndHandle, ID_MAINWND_PROCESSTL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TLSTYLE_BORDER | TLSTYLE_ICONS);
+ ProcessTreeListHandle = CreateWindow(
+ PH_TREENEW_CLASSNAME,
+ L"",
+ WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_BORDER,
+ 0,
+ 0,
+ 3,
+ 3,
+ PhMainWndHandle,
+ (HMENU)ID_MAINWND_PROCESSTL,
+ PhLibImageBase,
+ NULL
+ );
BringWindowToTop(ProcessTreeListHandle);
ServiceTreeListHandle = PhCreateTreeListControlEx(PhMainWndHandle, ID_MAINWND_SERVICETL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TLSTYLE_BORDER | TLSTYLE_ICONS);
diff --git a/2.x/trunk/phlib/include/treenew.h b/2.x/trunk/phlib/include/treenew.h
new file mode 100644
index 000000000..459099200
--- /dev/null
+++ b/2.x/trunk/phlib/include/treenew.h
@@ -0,0 +1,8 @@
+#ifndef _PH_TREENEW_H
+#define _PH_TREENEW_H
+
+#define PH_TREENEW_CLASSNAME L"PhTreeNew"
+
+BOOLEAN PhTreeNewInitialization();
+
+#endif
diff --git a/2.x/trunk/phlib/include/treenewp.h b/2.x/trunk/phlib/include/treenewp.h
new file mode 100644
index 000000000..02af57add
--- /dev/null
+++ b/2.x/trunk/phlib/include/treenewp.h
@@ -0,0 +1,142 @@
+#ifndef _PH_TREENEWP_H
+#define _PH_TREENEWP_H
+
+typedef struct _PH_TREENEW_CONTEXT
+{
+ HWND Handle;
+ PVOID InstanceHandle;
+ HWND FixedHeaderHandle;
+ HWND HeaderHandle;
+ HWND VScrollHandle;
+ HWND HScrollHandle;
+ HWND FillerBoxHandle;
+
+ union
+ {
+ struct
+ {
+ ULONG FontOwned : 1;
+ ULONG Tracking : 1; // tracking for fixed divider
+ ULONG VScrollVisible : 1;
+ ULONG HScrollVisible : 1;
+ };
+ ULONG Flags;
+ };
+
+ HFONT Font;
+ HCURSOR Cursor;
+
+ LONG HeaderHeight;
+
+ LONG FixedWidth; // width of the fixed portion of the tree list
+ LONG FixedWidthMinimum;
+ LONG TrackStartX;
+ LONG TrackOldFixedWidth;
+
+ ULONG VScrollWidth;
+ ULONG HScrollHeight;
+} PH_TREENEW_CONTEXT, *PPH_TREENEW_CONTEXT;
+
+LRESULT CALLBACK PhTnpWndProc(
+ __in HWND hwnd,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ );
+
+VOID PhTnpCreateTreeNewContext(
+ __out PPH_TREENEW_CONTEXT *Context
+ );
+
+VOID PhTnpDestroyTreeNewContext(
+ __in PPH_TREENEW_CONTEXT Context
+ );
+
+VOID PhTnpOnCreate(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in CREATESTRUCT *CreateStruct
+ );
+
+VOID PhTnpOnSize(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context
+ );
+
+VOID PhTnpOnSetFont(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in HFONT Font,
+ __in LOGICAL Redraw
+ );
+
+BOOLEAN PhTnpOnSetCursor(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in HWND CursorWindowHandle
+ );
+
+VOID PhTnpOnPaint(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in PAINTSTRUCT *PaintStruct,
+ __in HDC hdc
+ );
+
+VOID PhTnpOnMouseMove(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG VirtualKeys,
+ __in LONG CursorX,
+ __in LONG CursorY
+ );
+
+VOID PhTnpOnXxxButtonXxx(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG Message,
+ __in ULONG VirtualKeys,
+ __in LONG CursorX,
+ __in LONG CursorY
+ );
+
+VOID PhTnpOnCaptureChanged(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context
+ );
+
+VOID PhTnpOnKeyDown(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG VirtualKey,
+ __in ULONG Data
+ );
+
+BOOLEAN PhTnpOnNotify(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in NMHDR *Header,
+ __out LRESULT *Result
+ );
+
+VOID PhTnpCancelTrack(
+ __in PPH_TREENEW_CONTEXT Context
+ );
+
+VOID PhTnpLayout(
+ __in PPH_TREENEW_CONTEXT Context
+ );
+
+VOID PhTnpSetFixedWidth(
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG FixedWidth
+ );
+
+VOID PhTnpGetMessagePos(
+ __in HWND hwnd,
+ __out PPOINT ClientPoint
+ );
+
+#define TNP_HIT_TEST_FIXED_DIVIDER(X, Context) ((X) >= (Context)->FixedWidth - 8 && (X) < (Context)->FixedWidth + 8)
+
+#endif
diff --git a/2.x/trunk/phlib/phlib.vcxproj b/2.x/trunk/phlib/phlib.vcxproj
index 1a177b017..3c1c812f9 100644
--- a/2.x/trunk/phlib/phlib.vcxproj
+++ b/2.x/trunk/phlib/phlib.vcxproj
@@ -211,6 +211,7 @@
+
@@ -228,6 +229,8 @@
+
+
diff --git a/2.x/trunk/phlib/phlib.vcxproj.filters b/2.x/trunk/phlib/phlib.vcxproj.filters
index 14cfc6fe8..a031a38fc 100644
--- a/2.x/trunk/phlib/phlib.vcxproj.filters
+++ b/2.x/trunk/phlib/phlib.vcxproj.filters
@@ -207,6 +207,9 @@
Source Files
+
+ Source Files
+
@@ -440,6 +443,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/2.x/trunk/phlib/treenew.c b/2.x/trunk/phlib/treenew.c
new file mode 100644
index 000000000..b860d942b
--- /dev/null
+++ b/2.x/trunk/phlib/treenew.c
@@ -0,0 +1,618 @@
+/*
+ * Process Hacker -
+ * tree list
+ *
+ * Copyright (C) 2011 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+static ULONG SmallIconWidth;
+static ULONG SmallIconHeight;
+
+BOOLEAN PhTreeNewInitialization()
+{
+ WNDCLASSEX c = { sizeof(c) };
+
+ c.style = CS_GLOBALCLASS;
+ c.lpfnWndProc = PhTnpWndProc;
+ c.cbClsExtra = 0;
+ c.cbWndExtra = sizeof(PVOID);
+ c.hInstance = PhLibImageBase;
+ c.hIcon = NULL;
+ c.hCursor = LoadCursor(NULL, IDC_ARROW);
+ c.hbrBackground = NULL;
+ c.lpszMenuName = NULL;
+ c.lpszClassName = PH_TREENEW_CLASSNAME;
+ c.hIconSm = NULL;
+
+ if (!RegisterClassEx(&c))
+ return FALSE;
+
+ SmallIconWidth = GetSystemMetrics(SM_CXSMICON);
+ SmallIconHeight = GetSystemMetrics(SM_CYSMICON);
+
+ return TRUE;
+}
+
+LRESULT CALLBACK PhTnpWndProc(
+ __in HWND hwnd,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ )
+{
+ PPH_TREENEW_CONTEXT context;
+
+ context = (PPH_TREENEW_CONTEXT)GetWindowLongPtr(hwnd, 0);
+
+ if (uMsg == WM_CREATE)
+ {
+ PhTnpCreateTreeNewContext(&context);
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)context);
+ }
+
+ if (!context)
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ {
+ PhTnpOnCreate(hwnd, context, (CREATESTRUCT *)lParam);
+ }
+ return 0;
+ case WM_DESTROY:
+ {
+ PhTnpDestroyTreeNewContext(context);
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL);
+ }
+ break;
+ case WM_SIZE:
+ {
+ PhTnpOnSize(hwnd, context);
+ }
+ break;
+ case WM_ERASEBKGND:
+ return TRUE;
+ case WM_PAINT:
+ {
+ PAINTSTRUCT paintStruct;
+ HDC hdc;
+
+ if (hdc = BeginPaint(hwnd, &paintStruct))
+ {
+ PhTnpOnPaint(hwnd, context, &paintStruct, hdc);
+ EndPaint(hwnd, &paintStruct);
+ }
+ }
+ break;
+ case WM_GETFONT:
+ {
+ return (LRESULT)context->Font;
+ }
+ break;
+ case WM_SETFONT:
+ {
+ PhTnpOnSetFont(hwnd, context, (HFONT)wParam, LOWORD(lParam));
+ }
+ break;
+ case WM_THEMECHANGED:
+ {
+ // TODO
+ }
+ break;
+ case WM_SETTINGCHANGE:
+ {
+ // TODO
+ }
+ break;
+ case WM_SETCURSOR:
+ {
+ if (PhTnpOnSetCursor(hwnd, context, (HWND)wParam))
+ return TRUE;
+ }
+ break;
+ case WM_SETFOCUS:
+ {
+ // TODO
+ }
+ break;
+ case WM_MOUSEMOVE:
+ {
+ PhTnpOnMouseMove(hwnd, context, (ULONG)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONUP:
+ case WM_MBUTTONDBLCLK:
+ {
+ PhTnpOnXxxButtonXxx(hwnd, context, uMsg, (ULONG)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ }
+ break;
+ case WM_CAPTURECHANGED:
+ {
+ PhTnpOnCaptureChanged(hwnd, context);
+ }
+ break;
+ case WM_KEYDOWN:
+ {
+ PhTnpOnKeyDown(hwnd, context, (ULONG)wParam, (ULONG)lParam);
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ LRESULT result;
+
+ if (PhTnpOnNotify(hwnd, context, (NMHDR *)lParam, &result))
+ return result;
+ }
+ break;
+ }
+
+ if (context->Tracking && (GetAsyncKeyState(VK_ESCAPE) & 0x1))
+ {
+ PhTnpCancelTrack(context);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+VOID PhTnpCreateTreeNewContext(
+ __out PPH_TREENEW_CONTEXT *Context
+ )
+{
+ PPH_TREENEW_CONTEXT context;
+
+ context = PhAllocate(sizeof(PH_TREENEW_CONTEXT));
+ memset(context, 0, sizeof(PH_TREENEW_CONTEXT));
+
+ context->FixedWidthMinimum = 20;
+
+ *Context = context;
+}
+
+VOID PhTnpDestroyTreeNewContext(
+ __in PPH_TREENEW_CONTEXT Context
+ )
+{
+ PhFree(Context);
+}
+
+VOID PhTnpOnCreate(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in CREATESTRUCT *CreateStruct
+ )
+{
+ Context->Handle = hwnd;
+ Context->InstanceHandle = CreateStruct->hInstance;
+ Context->FixedHeaderHandle = CreateWindow(
+ WC_HEADER,
+ NULL,
+ WS_CHILD | WS_VISIBLE | HDS_HORZ | HDS_FULLDRAG | HDS_BUTTONS,
+ 0,
+ 0,
+ 0,
+ 0,
+ hwnd,
+ NULL,
+ CreateStruct->hInstance,
+ NULL
+ );
+ Context->HeaderHandle = CreateWindow(
+ WC_HEADER,
+ NULL,
+ WS_CHILD | WS_VISIBLE | HDS_HORZ | HDS_FULLDRAG | HDS_BUTTONS | HDS_DRAGDROP,
+ 0,
+ 0,
+ 0,
+ 0,
+ hwnd,
+ NULL,
+ CreateStruct->hInstance,
+ NULL
+ );
+
+ Context->VScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
+ Context->HScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
+
+ Context->VScrollHandle = CreateWindow(
+ L"SCROLLBAR",
+ NULL,
+ WS_CHILD | WS_VISIBLE | SBS_VERT,
+ 0,
+ 0,
+ 0,
+ 0,
+ hwnd,
+ NULL,
+ CreateStruct->hInstance,
+ NULL
+ );
+ Context->HScrollHandle = CreateWindow(
+ L"SCROLLBAR",
+ NULL,
+ WS_CHILD | WS_VISIBLE | SBS_HORZ,
+ 0,
+ 0,
+ 0,
+ 0,
+ hwnd,
+ NULL,
+ CreateStruct->hInstance,
+ NULL
+ );
+ Context->FillerBoxHandle = CreateWindow(
+ L"STATIC",
+ NULL,
+ WS_CHILD | WS_VISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ hwnd,
+ NULL,
+ CreateStruct->hInstance,
+ NULL
+ );
+
+ Context->VScrollVisible = TRUE;
+ Context->HScrollVisible = TRUE;
+
+ {
+ HDITEM item = { 0 };
+
+ item.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
+ item.cxy = 101;
+ item.pszText = L"Test Column";
+ item.cchTextMax = sizeof(L"Test Column") / sizeof(WCHAR);
+ item.fmt = HDF_LEFT | HDF_STRING | HDF_SORTUP;
+
+ Header_InsertItem(Context->FixedHeaderHandle, 0, &item);
+
+ item.pszText = L"Others Test";
+ Header_InsertItem(Context->HeaderHandle, 0, &item);
+ }
+
+ Context->FixedWidth = 100;
+}
+
+VOID PhTnpOnSize(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context
+ )
+{
+ PhTnpLayout(Context);
+}
+
+VOID PhTnpOnSetFont(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in HFONT Font,
+ __in LOGICAL Redraw
+ )
+{
+ if (Context->FontOwned)
+ {
+ DeleteObject(Context->Font);
+ Context->FontOwned = FALSE;
+ }
+
+ Context->Font = Font;
+
+ if (!Context->Font)
+ {
+ LOGFONT logFont;
+
+ if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &logFont, 0))
+ {
+ Context->Font = CreateFontIndirect(&logFont);
+ Context->FontOwned = TRUE;
+ }
+ }
+
+ SendMessage(Context->FixedHeaderHandle, WM_SETFONT, (WPARAM)Context->Font, Redraw);
+ SendMessage(Context->HeaderHandle, WM_SETFONT, (WPARAM)Context->Font, Redraw);
+}
+
+BOOLEAN PhTnpOnSetCursor(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in HWND CursorWindowHandle
+ )
+{
+ POINT point;
+
+ PhTnpGetMessagePos(hwnd, &point);
+
+ if (TNP_HIT_TEST_FIXED_DIVIDER(point.x, Context))
+ {
+ SetCursor(LoadCursor(NULL, IDC_UPARROW)); // TODO: Use real divider cursor
+ return TRUE;
+ }
+
+ if (Context->Cursor)
+ {
+ SetCursor(Context->Cursor);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+VOID PhTnpOnPaint(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in PAINTSTRUCT *PaintStruct,
+ __in HDC hdc
+ )
+{
+ RECT clientRect;
+ POINT points[2];
+
+ GetClientRect(hwnd, &clientRect);
+
+ SetDCBrushColor(hdc, RGB(0xff, 0xff, 0xff));
+ FillRect(hdc, &PaintStruct->rcPaint, GetStockObject(DC_BRUSH));
+
+ points[0].x = Context->FixedWidth;
+ points[0].y = 0;
+ points[1].x = Context->FixedWidth;
+ points[1].y = clientRect.bottom;
+ SetDCPenColor(hdc, RGB(0x77, 0x77, 0x77));
+ SelectObject(hdc, GetStockObject(DC_PEN));
+ Polyline(hdc, points, 2);
+}
+
+VOID PhTnpOnMouseMove(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG VirtualKeys,
+ __in LONG CursorX,
+ __in LONG CursorY
+ )
+{
+ if (Context->Tracking)
+ {
+ ULONG newFixedWidth;
+
+ newFixedWidth = Context->TrackOldFixedWidth + (CursorX - Context->TrackStartX);
+ PhTnpSetFixedWidth(Context, newFixedWidth);
+ }
+}
+
+VOID PhTnpOnXxxButtonXxx(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG Message,
+ __in ULONG VirtualKeys,
+ __in LONG CursorX,
+ __in LONG CursorY
+ )
+{
+ switch (Message)
+ {
+ case WM_LBUTTONDOWN:
+ {
+ if (TNP_HIT_TEST_FIXED_DIVIDER(CursorX, Context))
+ {
+ Context->Tracking = TRUE;
+ Context->TrackStartX = CursorX;
+ Context->TrackOldFixedWidth = Context->FixedWidth;
+ SetCapture(hwnd);
+
+ SetTimer(hwnd, 1, 100, NULL); // make sure we get messages once in a while so we can detect the escape key
+ GetAsyncKeyState(VK_ESCAPE);
+ }
+ }
+ break;
+ case WM_LBUTTONUP:
+ {
+ if (Context->Tracking)
+ {
+ ReleaseCapture();
+ }
+ }
+ break;
+ case WM_RBUTTONDOWN:
+ {
+ if (Context->Tracking)
+ {
+ PhTnpCancelTrack(Context);
+ }
+ }
+ break;
+ }
+}
+
+VOID PhTnpOnCaptureChanged(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context
+ )
+{
+ Context->Tracking = FALSE;
+ KillTimer(hwnd, 1);
+}
+
+VOID PhTnpOnKeyDown(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG VirtualKey,
+ __in ULONG Data
+ )
+{
+ NOTHING;
+}
+
+BOOLEAN PhTnpOnNotify(
+ __in HWND hwnd,
+ __in PPH_TREENEW_CONTEXT Context,
+ __in NMHDR *Header,
+ __out LRESULT *Result
+ )
+{
+ switch (Header->code)
+ {
+ case HDN_ITEMCHANGING:
+ {
+ if (Header->hwndFrom == Context->FixedHeaderHandle)
+ {
+ NMHEADER *nmHeader = (NMHEADER *)Header;
+
+ Context->FixedWidth = nmHeader->pitem->cxy - 1;
+
+ if (Context->FixedWidth < Context->FixedWidthMinimum)
+ Context->FixedWidth = Context->FixedWidthMinimum;
+
+ nmHeader->pitem->cxy = Context->FixedWidth + 1;
+
+ PhTnpLayout(Context);
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
+ }
+ else if (Header->hwndFrom == Context->HeaderHandle)
+ {
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+VOID PhTnpCancelTrack(
+ __in PPH_TREENEW_CONTEXT Context
+ )
+{
+ PhTnpSetFixedWidth(Context, Context->TrackOldFixedWidth);
+ ReleaseCapture();
+}
+
+VOID PhTnpLayout(
+ __in PPH_TREENEW_CONTEXT Context
+ )
+{
+ RECT clientRect;
+ RECT rect;
+ HDLAYOUT hdl;
+ WINDOWPOS windowPos;
+
+ GetClientRect(Context->Handle, &clientRect);
+
+ hdl.prc = ▭
+ hdl.pwpos = &windowPos;
+
+ // Fixed portion header control
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = Context->FixedWidth + 1;
+ rect.bottom = clientRect.bottom;
+ Header_Layout(Context->FixedHeaderHandle, &hdl);
+ SetWindowPos(Context->FixedHeaderHandle, NULL, windowPos.x, windowPos.y, windowPos.cx, windowPos.cy, windowPos.flags);
+ Context->HeaderHeight = windowPos.cy;
+
+ // Normal portion header control
+ rect.left = Context->FixedWidth;
+ rect.top = 0;
+ rect.right = clientRect.right - Context->VScrollWidth;
+ rect.bottom = clientRect.bottom;
+ Header_Layout(Context->HeaderHandle, &hdl);
+ SetWindowPos(Context->HeaderHandle, NULL, windowPos.x, windowPos.y, windowPos.cx, windowPos.cy, windowPos.flags);
+
+ // Vertical scroll bar
+ if (Context->VScrollVisible)
+ {
+ MoveWindow(
+ Context->VScrollHandle,
+ clientRect.right - Context->VScrollWidth,
+ 0,
+ Context->VScrollWidth,
+ clientRect.bottom - (Context->HScrollVisible ? Context->HScrollHeight : 0),
+ TRUE
+ );
+ }
+
+ // Horizontal scroll bar
+ if (Context->HScrollVisible)
+ {
+ MoveWindow(
+ Context->HScrollHandle,
+ Context->FixedWidth + 1,
+ clientRect.bottom - Context->HScrollHeight,
+ clientRect.right - Context->FixedWidth - 1 - (Context->VScrollVisible ? Context->VScrollWidth : 0),
+ Context->HScrollHeight,
+ TRUE
+ );
+ }
+
+ // Filler box
+ if (Context->VScrollVisible && Context->HScrollVisible)
+ {
+ MoveWindow(
+ Context->FillerBoxHandle,
+ clientRect.right - Context->VScrollWidth,
+ clientRect.bottom - Context->HScrollHeight,
+ Context->VScrollWidth,
+ Context->HScrollHeight,
+ TRUE
+ );
+ }
+}
+
+VOID PhTnpSetFixedWidth(
+ __in PPH_TREENEW_CONTEXT Context,
+ __in ULONG FixedWidth
+ )
+{
+ HDITEM item;
+
+ Context->FixedWidth = FixedWidth;
+
+ if (Context->FixedWidth < Context->FixedWidthMinimum)
+ Context->FixedWidth = Context->FixedWidthMinimum;
+
+ item.mask = HDI_WIDTH;
+ item.cxy = Context->FixedWidth + 1;
+ Header_SetItem(Context->FixedHeaderHandle, 0, &item);
+}
+
+VOID PhTnpGetMessagePos(
+ __in HWND hwnd,
+ __out PPOINT ClientPoint
+ )
+{
+ ULONG position;
+ POINT point;
+
+ position = GetMessagePos();
+ point.x = GET_X_LPARAM(position);
+ point.y = GET_Y_LPARAM(position);
+ ScreenToClient(hwnd, &point);
+
+ *ClientPoint = point;
+}