diff --git a/2.x/trunk/plugins/ToolStatus/searchbox.c b/2.x/trunk/plugins/ToolStatus/searchbox.c
index 0d5a87637..1960143ea 100644
--- a/2.x/trunk/plugins/ToolStatus/searchbox.c
+++ b/2.x/trunk/plugins/ToolStatus/searchbox.c
@@ -1,24 +1,24 @@
/*
- * Process Hacker -
- * Subclassed Edit control
- *
- * Copyright (C) 2012-2013 dmex
- *
- * 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 .
- */
+* Process Hacker -
+* Subclassed Edit control
+*
+* Copyright (C) 2012-2013 dmex
+*
+* 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 .
+*/
// dmex: The non-client area subclassing code has been modified based on the following guide:
// http://www.catch22.net/tuts/insert-buttons-edit-control
@@ -28,8 +28,11 @@
#include
#include
+#include
#pragma comment(lib, "uxtheme.lib")
+#define HRGN_FULL ((HRGN)1) // passed by WM_NCPAINT even though it's completely undocumented
+
typedef struct _NC_CONTROL
{
UINT CommandID; // sent in a WM_COMMAND message
@@ -46,15 +49,14 @@ typedef struct _NC_CONTROL
RECT rect;
RECT oldrect;
RECT* prect;
-
+
HBRUSH BorderBrush;
HBRUSH DcBrush;
HTHEME WndHTheme;
HIMAGELIST ImageList;
HWND ParentWindow;
- WNDPROC NCAreaWndProc;
} NC_CONTROL;
-
+
static VOID GetButtonRect(
__inout NC_CONTROL* nc,
__in RECT* rect
@@ -92,7 +94,7 @@ static VOID DrawInsertedButton(
0, 0,
CLR_NONE,
CLR_NONE,
- ILD_NORMAL | ILD_TRANSPARENT | ILD_SCALE
+ ILD_NORMAL | ILD_SCALE
);
}
else
@@ -106,21 +108,118 @@ static VOID DrawInsertedButton(
0, 0,
CLR_NONE,
CLR_NONE,
- ILD_NORMAL | ILD_TRANSPARENT | ILD_SCALE
+ ILD_NORMAL | ILD_SCALE
);
}
}
+VOID PhTnpDrawThemedBorder(
+ __in HWND hwnd,
+ __in NC_CONTROL* Context,
+ __in HDC hdc
+ )
+{
+ RECT windowRect;
+ RECT clientRect;
+ LONG sizingBorderWidth;
+ LONG borderX;
+ LONG borderY;
+
+ GetWindowRect(hwnd, &windowRect);
+ windowRect.right -= windowRect.left;
+ windowRect.bottom -= windowRect.top;
+ windowRect.left = 0;
+ windowRect.top = 0;
+
+ clientRect.left = windowRect.left + GetSystemMetrics(SM_CXEDGE);
+ clientRect.top = windowRect.top + GetSystemMetrics(SM_CYEDGE);
+ clientRect.right = windowRect.right - GetSystemMetrics(SM_CXEDGE);
+ clientRect.bottom = windowRect.bottom - GetSystemMetrics(SM_CYEDGE);
+
+ // Make sure we don't paint in the client area.
+ //ExcludeClipRect(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom);
+
+ // Draw the themed border.
+ DrawThemeBackground(Context->WndHTheme, hdc, 0, 0, &windowRect, NULL);
+
+ // Calculate the size of the border we just drew, and fill in the rest of the space if we didn't fully paint the region.
+ if (SUCCEEDED(GetThemeInt(Context->WndHTheme, 0, 0, TMT_SIZINGBORDERWIDTH, &sizingBorderWidth)))
+ {
+ borderX = sizingBorderWidth;
+ borderY = sizingBorderWidth;
+ }
+ else
+ {
+ borderX = GetSystemMetrics(SM_CXBORDER);
+ borderY = GetSystemMetrics(SM_CYBORDER);
+ }
+
+ if (borderX < GetSystemMetrics(SM_CXEDGE) || borderY < GetSystemMetrics(SM_CYEDGE))
+ {
+ windowRect.left += GetSystemMetrics(SM_CXEDGE) - borderX;
+ windowRect.top += GetSystemMetrics(SM_CYEDGE) - borderY;
+ windowRect.right -= GetSystemMetrics(SM_CXEDGE) - borderX;
+ windowRect.bottom -= GetSystemMetrics(SM_CYEDGE) - borderY;
+
+ FillRect(hdc, &windowRect, GetSysColorBrush(COLOR_WINDOW));
+ }
+
+ //IntersectClipRect(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom);
+
+ {
+ // get the screen coordinates of the window
+ GetWindowRect(hwnd, &Context->rect);
+ // adjust the coordinates - start from 0,0
+ OffsetRect(&Context->rect, -Context->rect.left, -Context->rect.top);
+
+ // work out where to draw the button
+ GetButtonRect(Context, &Context->rect);
+ DrawInsertedButton(hwnd, Context, hdc, &Context->rect);
+ }
+}
+
+BOOLEAN PhTnpOnNcPaint(
+ __in HWND hwnd,
+ __in NC_CONTROL* Context,
+ __in_opt HRGN UpdateRegion
+ )
+{
+ // Themed border
+ //if ((Context->ExtendedStyle & WS_EX_CLIENTEDGE) && Context->ThemeData)
+ HDC hdc;
+ ULONG flags;
+
+ if (UpdateRegion == HRGN_FULL)
+ UpdateRegion = NULL;
+
+ // Note the use of undocumented flags below. GetDCEx doesn't work without these.
+ flags = DCX_WINDOW | DCX_LOCKWINDOWUPDATE | 0x10000;
+
+ if (UpdateRegion)
+ flags |= DCX_INTERSECTRGN | 0x40000;
+
+ if (hdc = GetDCEx(hwnd, UpdateRegion, flags))
+ {
+ PhTnpDrawThemedBorder(hwnd, Context, hdc);
+ ReleaseDC(hwnd, hdc);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
LRESULT CALLBACK NcAreaWndSubclassProc(
__in HWND hwndDlg,
__in UINT uMsg,
__in WPARAM wParam,
- __in LPARAM lParam
+ __in LPARAM lParam,
+ __in UINT_PTR uIdSubclass,
+ __in DWORD_PTR dwRefData
)
{
NC_CONTROL* context = (NC_CONTROL*)GetProp(hwndDlg, L"Context");
- if (!context || !context->NCAreaWndProc)
+ if (!context)
return FALSE;
if (uMsg == WM_DESTROY)
@@ -133,13 +232,11 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
RemoveProp(hwndDlg, L"Context");
PhFree(context);
-
return FALSE;
}
-
+
switch (uMsg)
{
- case WM_NCACTIVATE:
case WM_ERASEBKGND:
return TRUE;
case WM_NCCALCSIZE:
@@ -156,7 +253,8 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
nccsp->rgrc[0].bottom -= 1;
// let the old wndproc allocate space for the borders, or any other non-client space.
- CallWindowProc(context->NCAreaWndProc, hwndDlg, uMsg, wParam, lParam);
+ //CallWindowProc(context->NCAreaWndProc, hwndDlg, uMsg, wParam, lParam);
+ DefSubclassProc(hwndDlg, uMsg, wParam, lParam);
// calculate what the size of each window border is,
// we need to know where the button is going to live.
@@ -170,46 +268,51 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
// and will be the same width as a scrollbar button
context->prect->right -= context->nButSize;
}
- return FALSE;
+ return FALSE;
case WM_NCPAINT:
- {
- HDC hdc;
-
- if (hdc = GetWindowDC(hwndDlg))
- {
- // get the screen coordinates of the window
- GetWindowRect(hwndDlg, &context->rect);
- // adjust the coordinates - start from 0,0
- OffsetRect(&context->rect, -context->rect.left, -context->rect.top);
-
- if (context->WndHTheme)
- {
- DrawThemeBackground(
- context->WndHTheme,
- hdc,
- EP_BACKGROUNDWITHBORDER,
- EBWBS_NORMAL,
- &context->rect,
- 0
- );
- }
- else
- {
- // Clear the draw region
- FillRect(hdc, &context->rect, context->DcBrush);
- // Set border color
- FrameRect(hdc, &context->rect, context->BorderBrush);
- }
-
- // work out where to draw the button
- GetButtonRect(context, &context->rect);
- DrawInsertedButton(hwndDlg, context, hdc, &context->rect);
-
- // cleanup
- ReleaseDC(hwndDlg, hdc);
- }
+ {
+ if (!PhTnpOnNcPaint(hwndDlg, context, (HRGN)wParam))
+ return 0;
}
- return FALSE;
+ break;
+ //case WM_NCPAINT:
+ // {
+ // HDC hdc;
+ // if (hdc = GetWindowDC(hwndDlg))
+ // {
+ // // get the screen coordinates of the window
+ // GetWindowRect(hwndDlg, &context->rect);
+ // // adjust the coordinates - start from 0,0
+ // OffsetRect(&context->rect, -context->rect.left, -context->rect.top);
+
+ // if (context->WndHTheme)
+ // {
+ // DrawThemeBackground(
+ // context->WndHTheme,
+ // hdc,
+ // EP_BACKGROUNDWITHBORDER,
+ // EBWBS_NORMAL,
+ // &context->rect,
+ // 0
+ // );
+ // }
+ // else
+ // {
+ // // Clear the draw region
+ // FillRect(hdc, &context->rect, context->DcBrush);
+ // // Set border color
+ // FrameRect(hdc, &context->rect, context->BorderBrush);
+ // }
+
+ // // work out where to draw the button
+ // GetButtonRect(context, &context->rect);
+ // DrawInsertedButton(hwndDlg, context, hdc, &context->rect);
+
+ // // cleanup
+ // ReleaseDC(hwndDlg, hdc);
+ // }
+ // }
+ // return FALSE;
case WM_NCHITTEST:
{
// get the screen coordinates of the mouse
@@ -234,7 +337,7 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
// get the position of the inserted button
GetWindowRect(hwndDlg, &context->rect);
-
+
context->pt.x -= context->rect.left;
context->pt.y -= context->rect.top;
@@ -247,7 +350,7 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
if (PtInRect(&context->rect, context->pt))
{
SetCapture(hwndDlg);
-
+
// Send the click notification to the parent window
PostMessage(
context->ParentWindow,
@@ -257,42 +360,42 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
);
// invalidate the nonclient area
- //RedrawWindow(
- // hwndDlg,
- // NULL, NULL,
- // RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN
- // );
+ SetWindowPos(
+ hwndDlg,
+ 0, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
+ );
}
}
return FALSE;
- //case WM_NCMOUSEMOVE:
- //case WM_NCMOUSELEAVE:
- // {
- // // get the screen coordinates of the mouse
- // context->pt.x = GET_X_LPARAM(lParam);
- // context->pt.y = GET_Y_LPARAM(lParam);
- // // get the position of the inserted button
- // GetWindowRect(hwndDlg, &context->rect);
- // context->pt.x -= context->rect.left;
- // context->pt.y -= context->rect.top;
- // // adjust the coordinates so they start from 0,0
- // OffsetRect(&context->rect, -context->rect.left, -context->rect.top);
- // GetButtonRect(context, &context->rect);
- // context->oldstate = context->IsMouseActive;
- // //check that the mouse is within the inserted button
- // if (PtInRect(&context->rect, context->pt))
- // {
- // context->IsMouseActive = TRUE;
- // }
- // else
- // {
- // context->IsMouseActive = FALSE;
- // }
- // // to prevent flicker, we only redraw the button if its state has changed
- // if (context->oldstate != context->IsMouseActive)
- // DrawInsertedButton(hwndDlg, context, NULL, &context->rect);
- // }
- // break;
+ //case WM_NCMOUSEMOVE:
+ //case WM_NCMOUSELEAVE:
+ // {
+ // // get the screen coordinates of the mouse
+ // context->pt.x = GET_X_LPARAM(lParam);
+ // context->pt.y = GET_Y_LPARAM(lParam);
+ // // get the position of the inserted button
+ // GetWindowRect(hwndDlg, &context->rect);
+ // context->pt.x -= context->rect.left;
+ // context->pt.y -= context->rect.top;
+ // // adjust the coordinates so they start from 0,0
+ // OffsetRect(&context->rect, -context->rect.left, -context->rect.top);
+ // GetButtonRect(context, &context->rect);
+ // context->oldstate = context->IsMouseActive;
+ // //check that the mouse is within the inserted button
+ // if (PtInRect(&context->rect, context->pt))
+ // {
+ // context->IsMouseActive = TRUE;
+ // }
+ // else
+ // {
+ // context->IsMouseActive = FALSE;
+ // }
+ // // to prevent flicker, we only redraw the button if its state has changed
+ // if (context->oldstate != context->IsMouseActive)
+ // DrawInsertedButton(hwndDlg, context, NULL, &context->rect);
+ // }
+ // break;
case WM_LBUTTONUP:
{
// get the SCREEN coordinates of the mouse
@@ -317,11 +420,11 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
{
context->TextLength = Edit_GetTextLength(hwndDlg) > 0;
- //RedrawWindow(
- // hwndDlg,
- // NULL, NULL,
- // RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN
- // );
+ SetWindowPos(
+ hwndDlg,
+ 0, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
+ );
}
}
return FALSE;
@@ -330,16 +433,16 @@ LRESULT CALLBACK NcAreaWndSubclassProc(
context->TextLength = Edit_GetTextLength(hwndDlg) > 0;
// invalidate the nonclient area
- RedrawWindow(
- hwndDlg,
- NULL, NULL,
- RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN
+ SetWindowPos(
+ hwndDlg,
+ 0, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
);
}
break;
}
- return CallWindowProc(context->NCAreaWndProc, hwndDlg, uMsg, wParam, lParam);
+ return DefSubclassProc(hwndDlg, uMsg, wParam, lParam);
}
BOOLEAN InsertButton(
@@ -347,12 +450,10 @@ BOOLEAN InsertButton(
__in UINT CommandID
)
{
- NC_CONTROL* context = (NC_CONTROL*)PhAllocate(
- sizeof(NC_CONTROL)
- );
+ NC_CONTROL* context = (NC_CONTROL*)PhAllocate(sizeof(NC_CONTROL));
memset(context, 0, sizeof(NC_CONTROL));
-
+
context->CommandID = CommandID;
context->ParentWindow = GetParent(hwndDlg);
context->BorderBrush = (HBRUSH)CreateSolidBrush(RGB(0x8f, 0x8f, 0x8f));
@@ -381,7 +482,7 @@ BOOLEAN InsertButton(
SetProp(hwndDlg, L"Context", (HANDLE)context);
// replace the old window procedure with our new one
- context->NCAreaWndProc = SubclassWindow(hwndDlg, NcAreaWndSubclassProc);
+ SetWindowSubclass(hwndDlg, NcAreaWndSubclassProc, 0, 0);
if (!context->WndHTheme)
{