Toolstatus: fixed searchbox subclass

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@5290 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
dmex
2013-04-08 18:16:56 +00:00
parent f172b83b68
commit 4abbb3fed6
+220 -119
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
* 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 <http://www.gnu.org/licenses/>.
*/
// 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 <uxtheme.h>
#include <vsstyle.h>
#include <vssym32.h>
#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)
{