730 lines
24 KiB
C
730 lines
24 KiB
C
/*
|
|
* Process Hacker Window Explorer -
|
|
* window tree dialog
|
|
*
|
|
* Copyright (C) 2016 dmex
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "wndexp.h"
|
|
#include "resource.h"
|
|
#include <windowsx.h>
|
|
|
|
typedef struct _WINDOWS_CONTEXT
|
|
{
|
|
HWND TreeNewHandle;
|
|
WE_WINDOW_TREE_CONTEXT TreeContext;
|
|
WE_WINDOW_SELECTOR Selector;
|
|
|
|
PH_LAYOUT_MANAGER LayoutManager;
|
|
|
|
HWND HighlightingWindow;
|
|
ULONG HighlightingWindowCount;
|
|
} WINDOWS_CONTEXT, *PWINDOWS_CONTEXT;
|
|
|
|
VOID WepShowWindowsDialogCallback(
|
|
_In_ PVOID Parameter
|
|
);
|
|
|
|
INT_PTR CALLBACK WepWindowsDlgProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
);
|
|
|
|
static RECT MinimumSize = { -1, -1, -1, -1 };
|
|
|
|
VOID WeShowWindowsDialog(
|
|
_In_ HWND ParentWindowHandle,
|
|
_In_ PWE_WINDOW_SELECTOR Selector
|
|
)
|
|
{
|
|
PWINDOWS_CONTEXT context;
|
|
|
|
context = PhAllocate(sizeof(WINDOWS_CONTEXT));
|
|
memset(context, 0, sizeof(WINDOWS_CONTEXT));
|
|
memcpy(&context->Selector, Selector, sizeof(WE_WINDOW_SELECTOR));
|
|
|
|
ProcessHacker_Invoke(WE_PhMainWndHandle, WepShowWindowsDialogCallback, context);
|
|
}
|
|
|
|
VOID WepShowWindowsDialogCallback(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
HWND hwnd;
|
|
PWINDOWS_CONTEXT context = Parameter;
|
|
|
|
hwnd = CreateDialogParam(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_WNDLIST),
|
|
NULL,
|
|
WepWindowsDlgProc,
|
|
(LPARAM)context
|
|
);
|
|
ShowWindow(hwnd, SW_SHOW);
|
|
}
|
|
|
|
VOID WepDeleteWindowSelector(
|
|
_In_ PWE_WINDOW_SELECTOR Selector
|
|
)
|
|
{
|
|
switch (Selector->Type)
|
|
{
|
|
case WeWindowSelectorDesktop:
|
|
PhDereferenceObject(Selector->Desktop.DesktopName);
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID WepFillWindowInfo(
|
|
_In_ PWE_WINDOW_NODE Node
|
|
)
|
|
{
|
|
HWND hwnd;
|
|
ULONG threadId;
|
|
ULONG processId;
|
|
|
|
hwnd = Node->WindowHandle;
|
|
|
|
GetClassName(hwnd, Node->WindowClass, sizeof(Node->WindowClass) / sizeof(WCHAR));
|
|
Node->WindowText = PhGetWindowText(hwnd);
|
|
|
|
if (!Node->WindowText)
|
|
Node->WindowText = PhReferenceEmptyString();
|
|
|
|
threadId = GetWindowThreadProcessId(hwnd, &processId);
|
|
Node->ClientId.UniqueProcess = UlongToHandle(processId);
|
|
Node->ClientId.UniqueThread = UlongToHandle(threadId);
|
|
|
|
Node->WindowVisible = !!IsWindowVisible(hwnd);
|
|
Node->HasChildren = !!FindWindowEx(hwnd, NULL, NULL, NULL);
|
|
}
|
|
|
|
VOID WepAddChildWindowNode(
|
|
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
|
_In_opt_ PWE_WINDOW_NODE ParentNode,
|
|
_In_ HWND hwnd
|
|
)
|
|
{
|
|
PWE_WINDOW_NODE childNode;
|
|
|
|
childNode = WeAddWindowNode(Context);
|
|
childNode->WindowHandle = hwnd;
|
|
WepFillWindowInfo(childNode);
|
|
|
|
childNode->Node.Expanded = FALSE;
|
|
|
|
if (ParentNode)
|
|
{
|
|
// This is a child node.
|
|
childNode->Parent = ParentNode;
|
|
PhAddItemList(ParentNode->Children, childNode);
|
|
}
|
|
else
|
|
{
|
|
// This is a root node.
|
|
PhAddItemList(Context->NodeRootList, childNode);
|
|
}
|
|
}
|
|
|
|
VOID WepAddChildWindows(
|
|
_In_ PWINDOWS_CONTEXT Context,
|
|
_In_opt_ PWE_WINDOW_NODE ParentNode,
|
|
_In_ HWND hwnd,
|
|
_In_opt_ HANDLE FilterProcessId,
|
|
_In_opt_ HANDLE FilterThreadId
|
|
)
|
|
{
|
|
HWND childWindow = NULL;
|
|
ULONG i = 0;
|
|
|
|
// We use FindWindowEx because EnumWindows doesn't return Metro app windows.
|
|
// Set a reasonable limit to prevent infinite loops.
|
|
while (i < 0x800 && (childWindow = FindWindowEx(hwnd, childWindow, NULL, NULL)))
|
|
{
|
|
ULONG processId;
|
|
ULONG threadId;
|
|
|
|
threadId = GetWindowThreadProcessId(childWindow, &processId);
|
|
|
|
if (
|
|
(!FilterProcessId || UlongToHandle(processId) == FilterProcessId) &&
|
|
(!FilterThreadId || UlongToHandle(threadId) == FilterThreadId)
|
|
)
|
|
{
|
|
WepAddChildWindowNode(&Context->TreeContext, ParentNode, childWindow);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
BOOL CALLBACK WepEnumDesktopWindowsProc(
|
|
_In_ HWND hwnd,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
PWINDOWS_CONTEXT context = (PWINDOWS_CONTEXT)lParam;
|
|
|
|
WepAddChildWindowNode(&context->TreeContext, NULL, hwnd);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID WepAddDesktopWindows(
|
|
_In_ PWINDOWS_CONTEXT Context,
|
|
_In_ PWSTR DesktopName
|
|
)
|
|
{
|
|
HDESK desktopHandle;
|
|
|
|
if (desktopHandle = OpenDesktop(DesktopName, 0, FALSE, DESKTOP_ENUMERATE))
|
|
{
|
|
EnumDesktopWindows(desktopHandle, WepEnumDesktopWindowsProc, (LPARAM)Context);
|
|
CloseDesktop(desktopHandle);
|
|
}
|
|
}
|
|
|
|
VOID WepRefreshWindows(
|
|
_In_ PWINDOWS_CONTEXT Context
|
|
)
|
|
{
|
|
TreeNew_SetRedraw(Context->TreeNewHandle, FALSE);
|
|
WeClearWindowTree(&Context->TreeContext);
|
|
TreeNew_NodesStructured(Context->TreeNewHandle);
|
|
|
|
switch (Context->Selector.Type)
|
|
{
|
|
case WeWindowSelectorAll:
|
|
{
|
|
PWE_WINDOW_NODE desktopNode;
|
|
|
|
desktopNode = WeAddWindowNode(&Context->TreeContext);
|
|
desktopNode->WindowHandle = GetDesktopWindow();
|
|
WepFillWindowInfo(desktopNode);
|
|
|
|
PhAddItemList(Context->TreeContext.NodeRootList, desktopNode);
|
|
|
|
WepAddChildWindows(Context, desktopNode, desktopNode->WindowHandle, NULL, NULL);
|
|
|
|
desktopNode->HasChildren = TRUE;
|
|
desktopNode->Opened = TRUE;
|
|
}
|
|
break;
|
|
case WeWindowSelectorThread:
|
|
{
|
|
WepAddChildWindows(Context, NULL, GetDesktopWindow(), NULL, Context->Selector.Thread.ThreadId);
|
|
}
|
|
break;
|
|
case WeWindowSelectorProcess:
|
|
{
|
|
WepAddChildWindows(Context, NULL, GetDesktopWindow(), Context->Selector.Process.ProcessId, NULL);
|
|
}
|
|
break;
|
|
case WeWindowSelectorDesktop:
|
|
{
|
|
WepAddDesktopWindows(Context, Context->Selector.Desktop.DesktopName->Buffer);
|
|
}
|
|
break;
|
|
}
|
|
|
|
TreeNew_SetRedraw(Context->TreeNewHandle, TRUE);
|
|
}
|
|
|
|
PPH_STRING WepGetWindowTitleForSelector(
|
|
_In_ PWE_WINDOW_SELECTOR Selector
|
|
)
|
|
{
|
|
switch (Selector->Type)
|
|
{
|
|
case WeWindowSelectorAll:
|
|
{
|
|
return PhCreateString(L"Windows - All");
|
|
}
|
|
break;
|
|
case WeWindowSelectorThread:
|
|
{
|
|
return PhFormatString(L"Windows - Thread %lu", HandleToUlong(Selector->Thread.ThreadId));
|
|
}
|
|
break;
|
|
case WeWindowSelectorProcess:
|
|
{
|
|
CLIENT_ID clientId;
|
|
|
|
clientId.UniqueProcess = Selector->Process.ProcessId;
|
|
clientId.UniqueThread = NULL;
|
|
|
|
return PhConcatStrings2(L"Windows - ", PH_AUTO_T(PH_STRING, PhGetClientIdName(&clientId))->Buffer);
|
|
}
|
|
break;
|
|
case WeWindowSelectorDesktop:
|
|
{
|
|
return PhFormatString(L"Windows - Desktop \"%s\"", Selector->Desktop.DesktopName->Buffer);
|
|
}
|
|
break;
|
|
default:
|
|
return PhCreateString(L"Windows");
|
|
}
|
|
}
|
|
|
|
INT_PTR CALLBACK WepWindowsDlgProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
PWINDOWS_CONTEXT context;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
context = (PWINDOWS_CONTEXT)lParam;
|
|
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
|
}
|
|
else
|
|
{
|
|
context = (PWINDOWS_CONTEXT)GetProp(hwndDlg, L"Context");
|
|
|
|
if (uMsg == WM_DESTROY)
|
|
RemoveProp(hwndDlg, L"Context");
|
|
}
|
|
|
|
if (!context)
|
|
return FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
PPH_STRING windowTitle;
|
|
PH_RECTANGLE windowRectangle;
|
|
|
|
context->TreeNewHandle = GetDlgItem(hwndDlg, IDC_LIST);
|
|
WeInitializeWindowTree(hwndDlg, context->TreeNewHandle, &context->TreeContext);
|
|
|
|
PhRegisterDialog(hwndDlg);
|
|
|
|
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
|
|
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LIST), NULL, PH_ANCHOR_ALL);
|
|
|
|
if (MinimumSize.left == -1)
|
|
{
|
|
RECT rect;
|
|
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = 160;
|
|
rect.bottom = 100;
|
|
MapDialogRect(hwndDlg, &rect);
|
|
MinimumSize = rect;
|
|
MinimumSize.left = 0;
|
|
}
|
|
|
|
// Set up the window position and size.
|
|
|
|
windowRectangle.Position = PhGetIntegerPairSetting(SETTING_NAME_WINDOWS_WINDOW_POSITION);
|
|
windowRectangle.Size = PhGetScalableIntegerPairSetting(SETTING_NAME_WINDOWS_WINDOW_SIZE, TRUE).Pair;
|
|
PhAdjustRectangleToWorkingArea(NULL, &windowRectangle);
|
|
|
|
MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top,
|
|
windowRectangle.Width, windowRectangle.Height, FALSE);
|
|
|
|
// Implement cascading by saving an offsetted rectangle.
|
|
windowRectangle.Left += 20;
|
|
windowRectangle.Top += 20;
|
|
PhSetIntegerPairSetting(SETTING_NAME_WINDOWS_WINDOW_POSITION, windowRectangle.Position);
|
|
|
|
windowTitle = PH_AUTO(WepGetWindowTitleForSelector(&context->Selector));
|
|
SetWindowText(hwndDlg, windowTitle->Buffer);
|
|
|
|
WepRefreshWindows(context);
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOWS_WINDOW_POSITION, SETTING_NAME_WINDOWS_WINDOW_SIZE, hwndDlg);
|
|
|
|
PhDeleteLayoutManager(&context->LayoutManager);
|
|
PhUnregisterDialog(hwndDlg);
|
|
|
|
WeDeleteWindowTree(&context->TreeContext);
|
|
WepDeleteWindowSelector(&context->Selector);
|
|
PhFree(context);
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDCANCEL:
|
|
//case IDOK:
|
|
DestroyWindow(hwndDlg);
|
|
break;
|
|
case IDC_REFRESH:
|
|
WepRefreshWindows(context);
|
|
break;
|
|
case ID_SHOWCONTEXTMENU:
|
|
{
|
|
POINT point;
|
|
PWE_WINDOW_NODE *windows;
|
|
ULONG numberOfWindows;
|
|
PPH_EMENU menu;
|
|
|
|
point.x = (SHORT)LOWORD(lParam);
|
|
point.y = (SHORT)HIWORD(lParam);
|
|
|
|
WeGetSelectedWindowNodes(
|
|
&context->TreeContext,
|
|
&windows,
|
|
&numberOfWindows
|
|
);
|
|
|
|
if (numberOfWindows != 0)
|
|
{
|
|
menu = PhCreateEMenu();
|
|
PhLoadResourceEMenuItem(menu, PluginInstance->DllBase, MAKEINTRESOURCE(IDR_WINDOW), 0);
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
|
|
|
|
if (numberOfWindows == 1)
|
|
{
|
|
WINDOWPLACEMENT placement = { sizeof(placement) };
|
|
BYTE alpha;
|
|
ULONG flags;
|
|
ULONG i;
|
|
ULONG id;
|
|
|
|
// State
|
|
|
|
GetWindowPlacement(windows[0]->WindowHandle, &placement);
|
|
|
|
if (placement.showCmd == SW_MINIMIZE)
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_MINIMIZE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
|
else if (placement.showCmd == SW_MAXIMIZE)
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_MAXIMIZE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
|
else if (placement.showCmd == SW_NORMAL)
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_RESTORE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
|
|
|
// Visible
|
|
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_VISIBLE, PH_EMENU_CHECKED,
|
|
(GetWindowLong(windows[0]->WindowHandle, GWL_STYLE) & WS_VISIBLE) ? PH_EMENU_CHECKED : 0);
|
|
|
|
// Enabled
|
|
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_ENABLED, PH_EMENU_CHECKED,
|
|
!(GetWindowLong(windows[0]->WindowHandle, GWL_STYLE) & WS_DISABLED) ? PH_EMENU_CHECKED : 0);
|
|
|
|
// Always on Top
|
|
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_ALWAYSONTOP, PH_EMENU_CHECKED,
|
|
(GetWindowLong(windows[0]->WindowHandle, GWL_EXSTYLE) & WS_EX_TOPMOST) ? PH_EMENU_CHECKED : 0);
|
|
|
|
// Opacity
|
|
|
|
if (GetLayeredWindowAttributes(windows[0]->WindowHandle, NULL, &alpha, &flags))
|
|
{
|
|
if (!(flags & LWA_ALPHA))
|
|
alpha = 255;
|
|
}
|
|
else
|
|
{
|
|
alpha = 255;
|
|
}
|
|
|
|
if (alpha == 255)
|
|
{
|
|
id = ID_OPACITY_OPAQUE;
|
|
}
|
|
else
|
|
{
|
|
id = 0;
|
|
|
|
// Due to integer division, we cannot use simple arithmetic to calculate which menu item to check.
|
|
for (i = 0; i < 10; i++)
|
|
{
|
|
if (alpha == (BYTE)(255 * (i + 1) / 10))
|
|
{
|
|
id = ID_OPACITY_10 + i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (id != 0)
|
|
{
|
|
PhSetFlagsEMenuItem(menu, id, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK,
|
|
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PhSetFlagsAllEMenuItems(menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
|
PhSetFlagsEMenuItem(menu, ID_WINDOW_COPY, PH_EMENU_DISABLED, 0);
|
|
}
|
|
|
|
PhShowEMenu(menu, hwndDlg, PH_EMENU_SHOW_SEND_COMMAND | PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y);
|
|
PhDestroyEMenu(menu);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_BRINGTOFRONT:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
WINDOWPLACEMENT placement = { sizeof(placement) };
|
|
|
|
GetWindowPlacement(selectedNode->WindowHandle, &placement);
|
|
|
|
if (placement.showCmd == SW_MINIMIZE)
|
|
ShowWindowAsync(selectedNode->WindowHandle, SW_RESTORE);
|
|
else
|
|
SetForegroundWindow(selectedNode->WindowHandle);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_RESTORE:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
ShowWindowAsync(selectedNode->WindowHandle, SW_RESTORE);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_MINIMIZE:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
ShowWindowAsync(selectedNode->WindowHandle, SW_MINIMIZE);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_MAXIMIZE:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
ShowWindowAsync(selectedNode->WindowHandle, SW_MAXIMIZE);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_CLOSE:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
PostMessage(selectedNode->WindowHandle, WM_CLOSE, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_VISIBLE:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
if (IsWindowVisible(selectedNode->WindowHandle))
|
|
{
|
|
selectedNode->WindowVisible = FALSE;
|
|
ShowWindowAsync(selectedNode->WindowHandle, SW_HIDE);
|
|
}
|
|
else
|
|
{
|
|
selectedNode->WindowVisible = TRUE;
|
|
ShowWindowAsync(selectedNode->WindowHandle, SW_SHOW);
|
|
}
|
|
|
|
PhInvalidateTreeNewNode(&selectedNode->Node, TN_CACHE_COLOR);
|
|
TreeNew_InvalidateNode(context->TreeNewHandle, &selectedNode->Node);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_ENABLED:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
EnableWindow(selectedNode->WindowHandle, !IsWindowEnabled(selectedNode->WindowHandle));
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_ALWAYSONTOP:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
LOGICAL topMost;
|
|
|
|
topMost = GetWindowLong(selectedNode->WindowHandle, GWL_EXSTYLE) & WS_EX_TOPMOST;
|
|
SetWindowPos(selectedNode->WindowHandle, topMost ? HWND_NOTOPMOST : HWND_TOPMOST,
|
|
0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
}
|
|
}
|
|
break;
|
|
case ID_OPACITY_10:
|
|
case ID_OPACITY_20:
|
|
case ID_OPACITY_30:
|
|
case ID_OPACITY_40:
|
|
case ID_OPACITY_50:
|
|
case ID_OPACITY_60:
|
|
case ID_OPACITY_70:
|
|
case ID_OPACITY_80:
|
|
case ID_OPACITY_90:
|
|
case ID_OPACITY_OPAQUE:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
ULONG opacity;
|
|
|
|
opacity = ((ULONG)LOWORD(wParam) - ID_OPACITY_10) + 1;
|
|
|
|
if (opacity == 10)
|
|
{
|
|
// Remove the WS_EX_LAYERED bit since it is not needed.
|
|
PhSetWindowExStyle(selectedNode->WindowHandle, WS_EX_LAYERED, 0);
|
|
RedrawWindow(selectedNode->WindowHandle, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
|
|
}
|
|
else
|
|
{
|
|
// Add the WS_EX_LAYERED bit so opacity will work.
|
|
PhSetWindowExStyle(selectedNode->WindowHandle, WS_EX_LAYERED, WS_EX_LAYERED);
|
|
SetLayeredWindowAttributes(selectedNode->WindowHandle, 0, (BYTE)(255 * opacity / 10), LWA_ALPHA);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_HIGHLIGHT:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
if (context->HighlightingWindow)
|
|
{
|
|
if (context->HighlightingWindowCount & 1)
|
|
WeInvertWindowBorder(context->HighlightingWindow);
|
|
}
|
|
|
|
context->HighlightingWindow = selectedNode->WindowHandle;
|
|
context->HighlightingWindowCount = 10;
|
|
SetTimer(hwndDlg, 9, 100, NULL);
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_GOTOTHREAD:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
PPH_PROCESS_ITEM processItem;
|
|
PPH_PROCESS_PROPCONTEXT propContext;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
{
|
|
if (processItem = PhReferenceProcessItem(selectedNode->ClientId.UniqueProcess))
|
|
{
|
|
if (propContext = PhCreateProcessPropContext(WE_PhMainWndHandle, processItem))
|
|
{
|
|
PhSetSelectThreadIdProcessPropContext(propContext, selectedNode->ClientId.UniqueThread);
|
|
PhShowProcessProperties(propContext);
|
|
PhDereferenceObject(propContext);
|
|
}
|
|
|
|
PhDereferenceObject(processItem);
|
|
}
|
|
else
|
|
{
|
|
PhShowError(hwndDlg, L"The process does not exist.");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case ID_WINDOW_PROPERTIES:
|
|
{
|
|
PWE_WINDOW_NODE selectedNode;
|
|
|
|
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
|
WeShowWindowProperties(hwndDlg, selectedNode->WindowHandle);
|
|
}
|
|
break;
|
|
case ID_WINDOW_COPY:
|
|
{
|
|
PPH_STRING text;
|
|
|
|
text = PhGetTreeNewText(context->TreeNewHandle, 0);
|
|
PhSetClipboardString(hwndDlg, &text->sr);
|
|
PhDereferenceObject(text);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case WM_TIMER:
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case 9:
|
|
{
|
|
WeInvertWindowBorder(context->HighlightingWindow);
|
|
|
|
if (--context->HighlightingWindowCount == 0)
|
|
KillTimer(hwndDlg, 9);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case WM_SIZE:
|
|
{
|
|
PhLayoutManagerLayout(&context->LayoutManager);
|
|
}
|
|
break;
|
|
case WM_SIZING:
|
|
{
|
|
PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom);
|
|
}
|
|
break;
|
|
case WM_WE_PLUSMINUS:
|
|
{
|
|
PWE_WINDOW_NODE node = (PWE_WINDOW_NODE)lParam;
|
|
|
|
if (!node->Opened)
|
|
{
|
|
TreeNew_SetRedraw(context->TreeNewHandle, FALSE);
|
|
WepAddChildWindows(context, node, node->WindowHandle, NULL, NULL);
|
|
node->Opened = TRUE;
|
|
TreeNew_SetRedraw(context->TreeNewHandle, TRUE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|