Showing preview only (240K chars total). Download the full file or copy to clipboard to get everything.
Repository: zodiacon/WinSpy
Branch: master
Commit: da6a441695fa
Files: 63
Total size: 224.8 KB
Directory structure:
gitextract_xjr65t7e/
├── .gitattributes
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── WinSpy/
│ ├── AboutDlg.cpp
│ ├── AboutDlg.h
│ ├── AutomationTreeView.cpp
│ ├── AutomationTreeView.h
│ ├── DialogHelper.h
│ ├── FindWindowDlg.cpp
│ ├── FindWindowDlg.h
│ ├── FormatHelper.cpp
│ ├── FormatHelper.h
│ ├── FrameWindowHelper.h
│ ├── HookHelper.cpp
│ ├── HookHelper.h
│ ├── IconHelper.cpp
│ ├── IconHelper.h
│ ├── ImageIconCache.cpp
│ ├── ImageIconCache.h
│ ├── Interfaces.h
│ ├── MainFrm.cpp
│ ├── MainFrm.h
│ ├── MessageDecoder.cpp
│ ├── MessageDecoder.h
│ ├── MessagesView.cpp
│ ├── MessagesView.h
│ ├── ProcessHelper.cpp
│ ├── ProcessHelper.h
│ ├── ProcessesView.cpp
│ ├── ProcessesView.h
│ ├── SecurityHelper.cpp
│ ├── SecurityHelper.h
│ ├── TreeViewManager.h
│ ├── ViewBase.h
│ ├── WinSpy.cpp
│ ├── WinSpy.h
│ ├── WinSpy.rc
│ ├── WinSpy.vcxproj
│ ├── WinSpy.vcxproj.filters
│ ├── WindowGeneralPage.cpp
│ ├── WindowGeneralPage.h
│ ├── WindowHelper.cpp
│ ├── WindowHelper.h
│ ├── WindowWindowsPage.cpp
│ ├── WindowWindowsPage.h
│ ├── WindowsListView.cpp
│ ├── WindowsListView.h
│ ├── WindowsView.cpp
│ ├── WindowsView.h
│ ├── pch.cpp
│ ├── pch.h
│ └── resource.h
├── WinSpy.sln
└── WinSpyHook/
├── WinSpyHook.def
├── WinSpyHook.vcxproj
├── WinSpyHook.vcxproj.filters
├── dllmain.cpp
├── hooks.cpp
├── hooks.h
├── pch.cpp
└── pch.h
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
================================================
FILE: .gitmodules
================================================
[submodule "WTLHelper"]
path = WTLHelper
url = https://github.com/zodiacon/WTLHelper.git
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Pavel Yosifovich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# WinSpy
Enhanced version of the classic Spy++ tool (WIP)
================================================
FILE: WinSpy/AboutDlg.cpp
================================================
// aboutdlg.cpp : implementation of the CAboutDlg class
//
/////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#include "resource.h"
#include "aboutdlg.h"
LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
CenterWindow(GetParent());
return TRUE;
}
LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
EndDialog(wID);
return 0;
}
================================================
FILE: WinSpy/AboutDlg.h
================================================
// aboutdlg.h : interface of the CAboutDlg class
//
/////////////////////////////////////////////////////////////////////////////
#pragma once
class CAboutDlg : public CDialogImpl<CAboutDlg> {
public:
enum { IDD = IDD_ABOUTBOX };
BEGIN_MSG_MAP(CAboutDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
};
================================================
FILE: WinSpy/AutomationTreeView.cpp
================================================
#include "pch.h"
#include "AutomationTreeView.h"
#include "WindowHelper.h"
#pragma comment(lib, "oleacc")
LRESULT CAutomationTreeView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
m_hWndClient = m_Splitter.Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_Tree.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, 0, IDC_TREE);
m_List.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
LVS_REPORT | LVS_OWNERDATA | LVS_SINGLESEL);
m_List.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT);
m_List.InsertColumn(0, L"Property", 0, 180);
m_List.InsertColumn(1, L"Value", 0, 350);
m_Tree.SetExtendedStyle(TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER);
m_Tree.SetImageList(WindowHelper::GetImageList(), TVSIL_NORMAL);
m_Splitter.SetSplitterPanes(m_Tree, m_List);
m_Splitter.SetSplitterPosPct(35);
InitTree();
return 0;
}
LRESULT CAutomationTreeView::OnNodeExpanding(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
if (tv->action != TVE_EXPAND)
return FALSE;
auto hItem = tv->itemNew.hItem;
if (m_Tree.GetChildItem(hItem))
return FALSE;
auto elem = (IUIAutomationElement*)m_Tree.GetItemData(hItem);
if (elem) {
EnumChildElements(m_spUIWalker, elem, hItem);
return FALSE;
}
return TRUE;
}
LRESULT CAutomationTreeView::OnNodeExpanded(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
if (tv->action != TVE_COLLAPSE)
return FALSE;
//
// delete child nodes
//
auto hItem = tv->itemNew.hItem;
HTREEITEM hChild;
while (hChild = m_Tree.GetChildItem(hItem))
m_Tree.DeleteItem(hChild);
TVITEM tvi{ sizeof(tvi) };
tvi.cChildren = 1;
tvi.mask = TVIF_CHILDREN;
tvi.hItem = hItem;
m_Tree.SetItem(&tvi);
return FALSE;
}
LRESULT CAutomationTreeView::OnNodeSelected(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
auto hItem = tv->itemNew.hItem;
auto data = (IUIAutomationElement*)m_Tree.GetItemData(tv->itemNew.hItem);
UpdateProperties(data);
return 0;
}
LRESULT CAutomationTreeView::OnNodeDeleted(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
auto data = (IUIAutomationElement*)m_Tree.GetItemData(tv->itemOld.hItem);
if (data)
data->Release();
return 0;
}
void CAutomationTreeView::OnActivate(bool active) {
if (active) {
UpdateUI();
}
}
CString CAutomationTreeView::GetColumnText(HWND, int row, int col) const {
auto& p = m_Properties[row];
switch (col) {
case 0: return p.Name;
case 1: return p.Value.c_str();
}
return L"";
}
HTREEITEM CAutomationTreeView::AddElement(IUIAutomationElement* e, HTREEITEM hParent, HTREEITEM hAfter) {
CComBSTR name, cls, id;
e->get_CurrentName(&name);
e->get_CurrentClassName(&cls);
CString text;
text.Format(L"%s [%s]", name.m_str, cls.m_str);
auto hItem = m_Tree.InsertItem(text, hParent, hAfter);
e->AddRef();
m_Tree.SetItemData(hItem, (DWORD_PTR)e);
return hItem;
}
void CAutomationTreeView::EnumChildElements(IUIAutomationTreeWalker* pWalker, IUIAutomationElement* root, HTREEITEM hParent, HTREEITEM hAfter) {
CComPtr<IUIAutomationElement> spElem;
pWalker->GetFirstChildElement(root, &spElem);
int pid = 0;
while (spElem) {
spElem->get_CurrentProcessId(&pid);
if (pid != ::GetCurrentProcessId()) {
auto node = AddElement(spElem, hParent, hAfter);
CComPtr<IUIAutomationElement> spChild;
pWalker->GetFirstChildElement(spElem, &spChild);
if (spChild) {
TVITEM tvi{ sizeof(tvi) };
tvi.cChildren = 1;
tvi.mask = TVIF_CHILDREN;
tvi.hItem = node;
m_Tree.SetItem(&tvi);
}
}
CComPtr<IUIAutomationElement> spNext;
pWalker->GetNextSiblingElement(spElem, &spNext);
spElem = spNext;
}
}
void CAutomationTreeView::InitTree() {
CWaitCursor wait;
if (m_spUI == nullptr) {
m_spUI.CoCreateInstance(__uuidof(CUIAutomation));
if (m_spUI == nullptr)
return;
}
m_Tree.SetRedraw(FALSE);
m_Tree.DeleteAllItems();
CComPtr<IUIAutomationTreeWalker> spWalker;
m_spUI->get_RawViewWalker(&spWalker);
ATLASSERT(spWalker);
m_spUIWalker = spWalker;
CComPtr<IUIAutomationElement> spRoot;
m_spUI->GetRootElement(&spRoot);
auto node = AddElement(spRoot);
EnumChildElements(spWalker, spRoot, node);
m_Tree.Expand(node, TVE_EXPAND);
m_Tree.SetRedraw(TRUE);
}
void CAutomationTreeView::UpdateUI() {
}
void CAutomationTreeView::UpdateProperties(IUIAutomationElement* elem) {
m_Properties.clear();
if (elem) {
static const struct {
PROPERTYID id;
PCWSTR text;
} props[] = {
{ UIA_NamePropertyId, L"Name" },
{ UIA_RuntimeIdPropertyId, L"Runtime ID" },
{ UIA_ClassNamePropertyId, L"Class Name" },
{ UIA_ControlTypePropertyId, L"Control Type" },
{ UIA_LocalizedControlTypePropertyId, L"Localized Control Type" },
{ UIA_FullDescriptionPropertyId, L"Full Description" },
{ UIA_AcceleratorKeyPropertyId, L"Accelerator Key" },
{ UIA_AccessKeyPropertyId, L"Access Key" },
{ UIA_AutomationIdPropertyId, L"Automation ID" },
{ UIA_BoundingRectanglePropertyId, L"Bounding Rectangle" },
{ UIA_CenterPointPropertyId, L"Center Point" },
{ UIA_HasKeyboardFocusPropertyId, L"Has Focus" },
{ UIA_HelpTextPropertyId, L"Help Text" },
{ UIA_ItemStatusPropertyId, L"Item Status" },
{ UIA_NativeWindowHandlePropertyId, L"Window Handle" },
{ UIA_ProcessIdPropertyId, L"Process ID" },
{ UIA_SizePropertyId, L"Size" },
{ UIA_OrientationPropertyId, L"Orientation" },
{ UIA_OutlineColorPropertyId, L"Outline Color" },
{ UIA_FillColorPropertyId, L"Fill Color" },
{ UIA_PositionInSetPropertyId, L"Position in Set" },
{ UIA_OutlineThicknessPropertyId, L"Outline Thickness" },
{ UIA_IsEnabledPropertyId, L"Enabled" },
{ UIA_IsOffscreenPropertyId, L"Off Screen" },
{ UIA_IsPasswordPropertyId, L"Password" },
{ UIA_IsEnabledPropertyId, L"Editable" },
{ UIA_ItemTypePropertyId, L"Item Type" },
{ UIA_SizeOfSetPropertyId, L"Size of Set" },
{ UIA_VisualEffectsPropertyId, L"Visual Effects" },
{ UIA_LiveSettingPropertyId, L"Live Setting" },
{ UIA_LevelPropertyId, L"Level" },
{ UIA_IsPeripheralPropertyId, L"Peripheral" },
{ UIA_IsKeyboardFocusablePropertyId, L"Keyboard Focusable" },
{ UIA_IsDialogPropertyId, L"Dialog" },
{ UIA_IsControlElementPropertyId, L"Control Element" },
{ UIA_FrameworkIdPropertyId, L"Framework ID" },
};
for (auto& p : props) {
CComVariant value;
if (S_OK == elem->GetCurrentPropertyValue(p.id, &value)) {
ItemData data;
data.Value = FormatValue(m_spUI, value);
if (data.Value.empty() && S_OK == value.ChangeType(VT_BSTR)) {
data.Value = value.bstrVal;
}
if (!data.Value.empty()) {
data.Name = p.text;
m_Properties.push_back(std::move(data));
}
}
}
}
m_List.SetItemCount((int)m_Properties.size());
}
std::wstring CAutomationTreeView::FormatValue(IUIAutomation* pUI, VARIANT const& value) {
switch (value.vt) {
case VT_I4: return std::format(L"{} (0x{:X})", value.intVal, value.intVal);
case VT_UI4: return std::format(L"{} (0x{:X})", value.uintVal, value.uintVal);
case VT_BOOL: return value.boolVal ? L"True" : L"False";
case VT_I4 | VT_ARRAY:
{
int* data, count;
if (S_OK == pUI->IntSafeArrayToNativeArray(value.parray, &data, &count)) {
std::wstring result(L"(");
for (int i = 0; i < count; i++) {
result += std::format(L"{}", data[i]);
if (i < count - 1)
result += L", ";
}
result += L")";
return result;
}
break;
}
case VT_R8 | VT_ARRAY:
{
RECT* rc;
int count;
if (S_OK == pUI->SafeArrayToRectNativeArray(value.parray, &rc, &count) && count > 0) {
std::wstring result(L"(");
for (int i = 0; i < count; i++) {
result += std::format(L"[{},{}-{},{}]", rc[i].left, rc[i].top, rc[i].right, rc[i].bottom);
if (i < count - 1)
result += L", ";
}
result += L")";
return result;
}
else {
double* data;
count = value.parray->rgsabound[0].cElements;
if (S_OK == ::SafeArrayAccessData(value.parray, (void**)&data)) {
std::wstring result(L"(");
for (int i = 0; i < count; i++) {
result += std::format(L"{}", data[i]);
if (i < count - 1)
result += L", ";
}
::SafeArrayUnaccessData(value.parray);
result += L")";
return result;
}
}
break;
}
}
return L"";
}
================================================
FILE: WinSpy/AutomationTreeView.h
================================================
#pragma once
#include "ViewBase.h"
#include <TreeViewHelper.h>
#include <VirtualListView.h>
#include <CustomSplitterWindow.h>
#include <UIAutomation.h>
struct IUIAutomationElement;
struct IUIAutomationTreeWalker;
class CAutomationTreeView :
public CViewBase<CAutomationTreeView>,
public CVirtualListView<CAutomationTreeView>,
public CTreeViewHelper<CAutomationTreeView> {
public:
explicit CAutomationTreeView(IMainFrame* frame) : CViewBase(frame) {}
void OnActivate(bool active);
CString GetColumnText(HWND, int row, int col) const;
protected:
enum { IDC_TREE = 123 };
BEGIN_MSG_MAP(CAutomationTreeView)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING, OnNodeExpanding)
NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDED, OnNodeExpanded)
NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnNodeSelected)
NOTIFY_CODE_HANDLER(TVN_DELETEITEM, OnNodeDeleted)
CHAIN_MSG_MAP(CTreeViewHelper<CAutomationTreeView>)
CHAIN_MSG_MAP(CVirtualListView<CAutomationTreeView>)
CHAIN_MSG_MAP(CViewBase<CAutomationTreeView>)
END_MSG_MAP()
LRESULT OnTreeNodeRightClick(HTREEITEM hItem, CPoint const& pt);
LRESULT OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint const& pt);
private:
HTREEITEM AddElement(IUIAutomationElement* element, HTREEITEM hParent = TVI_ROOT, HTREEITEM hAfter = TVI_SORT);
void EnumChildElements(IUIAutomationTreeWalker* pWalker, IUIAutomationElement* root, HTREEITEM hParent = TVI_ROOT, HTREEITEM hAfter = TVI_SORT);
void InitTree();
void UpdateUI();
void UpdateProperties(IUIAutomationElement* elem);
static std::wstring FormatValue(IUIAutomation* pUI, VARIANT const& value);
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnNodeExpanding(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnNodeExpanded(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnNodeSelected(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnRefresh(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnNodeDeleted(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
struct ItemData {
PCWSTR Name;
std::wstring Value;
};
CCustomSplitterWindow m_Splitter;
CTreeViewCtrl m_Tree;
CListViewCtrl m_List;
CComPtr<IUIAutomationTreeWalker> m_spUIWalker;
CComPtr<IUIAutomation> m_spUI;
std::vector<ItemData> m_Properties;
};
================================================
FILE: WinSpy/DialogHelper.h
================================================
#pragma once
template<typename T>
class CDialogHelper {
public:
#ifdef IDI_OK
void AdjustOKCancelButtons() {
auto dlg = static_cast<T*>(this);
CButton ok(dlg->GetDlgItem(IDOK));
if (ok) {
CString text;
ok.GetWindowText(text);
ok.SetWindowText(L" " + text);
ok.SetIcon(AtlLoadIconImage(IDI_OK, 0, 16, 16));
}
CButton cancel(dlg->GetDlgItem(IDCANCEL));
if (cancel) {
cancel.SetWindowText(L" Cancel");
cancel.SetIcon(AtlLoadIconImage(IDI_CANCEL, 0, 16, 16));
}
}
#endif
bool AddIconToButton(WORD id, WORD icon, int size = 16) {
auto dlg = static_cast<T*>(this);
CButton button(dlg->GetDlgItem(id));
if (button) {
button.SetIcon(AtlLoadIconImage(icon, 0, size, size));
CString text;
button.GetWindowText(text);
button.SetWindowText(L" " + text);
}
return (bool)button;
}
void SetDialogIcon(UINT icon) {
auto dlg = static_cast<T*>(this);
dlg->SetIcon(AtlLoadIconImage(icon, 0, 16, 16), FALSE);
dlg->SetIcon(AtlLoadIconImage(icon, 0, 32, 32), TRUE);
}
void SetDialogIcon(HICON icon) {
auto dlg = static_cast<T*>(this);
dlg->SetIcon(icon, FALSE);
dlg->SetIcon(icon, TRUE);
}
};
================================================
FILE: WinSpy/FindWindowDlg.cpp
================================================
#include "pch.h"
#include "resource.h"
#include "FindWindowDlg.h"
#include "WindowHelper.h"
#include "ProcessHelper.h"
#include "FormatHelper.h"
HWND CFindWindowDlg::GetSelectedHwnd() const {
return m_SelectedHwnd;
}
void CFindWindowDlg::ClearWindowDetails() {
SetDlgItemText(IDC_HANDLE, L"");
SetDlgItemText(IDC_TEXT, L"");
SetDlgItemText(IDC_CLASSNAME, L"");
SetDlgItemText(IDC_THREAD, L"");
SetDlgItemText(IDC_PROCESS, L"");
if (m_hCursorWnd)
WindowHelper::HighlightBorder(m_hCursorWnd, false);
m_WinDrag.ShowWindow(SW_SHOW);
if (IsDlgButtonChecked(IDC_HIDE) == BST_CHECKED) {
::ShowWindow(m_pFrame->GetHwnd(), SW_SHOW);
}
}
void CFindWindowDlg::SelectWindow(HWND hWnd) {
CString text;
text.Format(L"0x%zX", DWORD_PTR(hWnd));
SetDlgItemText(IDC_HANDLE, text);
WCHAR clsName[128];
m_SelectedHwnd = hWnd;
if (::GetClassName(hWnd, clsName, _countof(clsName)))
SetDlgItemText(IDC_CLASSNAME, clsName);
CWindow win(hWnd);
win.GetWindowText(text);
SetDlgItemText(IDC_TEXT, text);
DWORD pid;
auto tid = ::GetWindowThreadProcessId(hWnd, &pid);
SetDlgItemInt(IDC_THREAD, tid, FALSE);
text.Format(L"%s (%d)", (PCWSTR)ProcessHelper::GetProcessImageName(pid), pid);
SetDlgItemText(IDC_PROCESS, text);
}
LRESULT CFindWindowDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
InitDynamicLayout();
SetDialogIcon(IDI_WINDOWSEARCH);
m_WinDrag.SubclassWindow(GetDlgItem(IDC_TARGET));
m_WinDrag.SetIcon(AtlLoadIconImage(IDI_TARGET, 0, 32, 32));
m_DragCursor = AtlLoadIconImage(IDI_TARGET, 0, ::GetSystemMetrics(SM_CXCURSOR), ::GetSystemMetrics(SM_CYCURSOR));
return 0;
}
LRESULT CFindWindowDlg::OnCloseCmd(WORD, WORD id, HWND, BOOL&) {
if (id == IDCANCEL && m_Capture) {
ReleaseCapture();
m_Capture = false;
ClearWindowDetails();
return 0;
}
if (id == IDOK) {
CString text;
GetDlgItemText(IDC_HANDLE, text);
m_SelectedHwnd = (HWND)FormatHelper::ParseHex(text);
}
EndDialog(id);
return 0;
}
LRESULT CFindWindowDlg::OnSearch(WORD, WORD id, HWND, BOOL&) {
CString handle;
GetDlgItemText(IDC_HANDLE, handle);
if (!handle.IsEmpty()) {
auto hWnd = (HWND)FormatHelper::ParseHex(handle);
if (::IsWindow(hWnd)) {
SelectWindow(hWnd);
}
else {
AtlMessageBox(m_hWnd, (PCWSTR)(L"Cannot locate window with handle " + handle), L"Window Finder", MB_ICONERROR);
}
return 0;
}
CString text, cls;
GetDlgItemText(IDC_TEXT, text);
GetDlgItemText(IDC_CLASSNAME, cls);
if (text.IsEmpty() && cls.IsEmpty()) {
AtlMessageBox(m_hWnd, L"Specify handle, class and/or text to search", L"Window Finder", MB_ICONWARNING);
return 0;
}
auto hWnd = ::FindWindowEx(nullptr, nullptr, cls, text);
if (hWnd)
SelectWindow(hWnd);
else
AtlMessageBox(m_hWnd, L"Cannot locate window with this class/text", L"Window Finder", MB_ICONERROR);
return 0;
}
LRESULT CFindWindowDlg::OnMouseDown(UINT, WPARAM, LPARAM, BOOL&) {
m_WinDrag.SetCapture();
m_Capture = true;
m_WinDrag.ShowWindow(SW_HIDE);
if (IsDlgButtonChecked(IDC_HIDE) == BST_CHECKED) {
::ShowWindow(m_pFrame->GetHwnd(), SW_HIDE);
}
return 0;
}
LRESULT CFindWindowDlg::OnMouseUp(UINT, WPARAM, LPARAM, BOOL&) {
ReleaseCapture();
m_Capture = false;
m_WinDrag.ShowWindow(SW_SHOW);
SetCursor(AtlLoadSysCursor(IDC_ARROW));
if(m_hCursorWnd)
WindowHelper::HighlightBorder(m_hCursorWnd, false);
if (IsDlgButtonChecked(IDC_HIDE) == BST_CHECKED) {
::ShowWindow(m_pFrame->GetHwnd(), SW_SHOW);
}
return 0;
}
LRESULT CFindWindowDlg::OnMouseMove(UINT, WPARAM, LPARAM lp, BOOL&) {
if (m_Capture) {
::SetCursor(m_DragCursor);
CPoint pt{ GET_X_LPARAM(lp), GET_Y_LPARAM(lp) };
m_WinDrag.ClientToScreen(&pt);
auto hWnd = ::WindowFromPoint(pt);
DWORD pid, tid;
if ((tid = ::GetWindowThreadProcessId(hWnd, &pid)) && pid == ::GetCurrentProcessId())
return 0;
if (m_hCursorWnd && m_hCursorWnd != hWnd)
WindowHelper::HighlightBorder(m_hCursorWnd, false);
if (hWnd != m_hCursorWnd) {
WindowHelper::HighlightBorder(hWnd);
m_hCursorWnd.Detach();
m_hCursorWnd.Attach(hWnd);
SelectWindow(hWnd);
}
}
return 0;
}
================================================
FILE: WinSpy/FindWindowDlg.h
================================================
#pragma once
#include "Interfaces.h"
#include "DialogHelper.h"
class CFindWindowDlg :
public CDialogImpl<CFindWindowDlg>,
public CDynamicDialogLayout<CFindWindowDlg>,
public CDialogHelper<CFindWindowDlg> {
public:
enum { IDD = IDD_FINDWINDOW };
CFindWindowDlg(IMainFrame* frame) : m_pFrame(frame), m_WinDrag(this, 1) {}
HWND GetSelectedHwnd() const;
protected:
BEGIN_MSG_MAP(CFindWindowDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDC_SEARCH, OnSearch)
COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
CHAIN_MSG_MAP(CDynamicDialogLayout<CFindWindowDlg>)
ALT_MSG_MAP(1)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONUP, OnMouseUp)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnMouseDown)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
private:
void ClearWindowDetails();
void SelectWindow(HWND hWnd);
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnSearch(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnMouseDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnMouseUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
CContainedWindowT<CStatic> m_WinDrag;
CIcon m_DragCursor;
CWindow m_hCursorWnd;
IMainFrame* m_pFrame;
HWND m_SelectedHwnd{ nullptr };
bool m_Capture{ false };
};
================================================
FILE: WinSpy/FormatHelper.cpp
================================================
#include "pch.h"
#include "FormatHelper.h"
#include <sstream>
CString FormatHelper::FormatHWndOrNone(HWND hWnd) {
CString text;
if (hWnd)
text.Format(L"0x%zX", (DWORD_PTR)hWnd);
else
text = L"(None)";
return text;
}
CString FormatHelper::RectToString(CRect const& rc) {
CString text;
text.Format(L"(%d,%d)-(%d,%d) [%d x %d]", rc.left, rc.top, rc.right, rc.bottom, rc.Width(), rc.Height());
return text;
}
DWORD_PTR FormatHelper::ParseHex(CString const& text) {
std::wstringstream ss;
ss << std::hex;
if (text.Left(2).CompareNoCase(L"0x") == 0)
ss << (PCWSTR)text.Mid(2);
else
ss << (PCWSTR)text;
DWORD_PTR value;
ss >> value;
return value;
}
CString FormatHelper::FormatPoint(POINT const& pt) {
CString text;
text.Format(L"(%d,%d)", pt.x, pt.y);
return text;
}
================================================
FILE: WinSpy/FormatHelper.h
================================================
#pragma once
struct FormatHelper {
static CString FormatHWndOrNone(HWND hWnd);
static CString RectToString(CRect const& rc);
static DWORD_PTR ParseHex(CString const& text);
static CString FormatPoint(POINT const& pt);
};
================================================
FILE: WinSpy/FrameWindowHelper.h
================================================
#pragma once
#include "Interfaces.h"
template<typename T>
struct CFrameWindowHelper : CIdleHandler {
HWND CreateAndInitToolBar(const ToolBarButtonInfo* buttons, int count) {
auto pT = static_cast<T*>(this);
CToolBarCtrl tb;
auto hWndToolBar = tb.Create(pT->m_hWnd, CWindow::rcDefault, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST, 0, ATL_IDW_TOOLBAR);
tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS);
CImageList tbImages;
tbImages.Create(24, 24, ILC_COLOR32 | ILC_COLOR | ILC_MASK, 4, 4);
tb.SetImageList(tbImages);
for (int i = 0; i < count; i++) {
auto& b = buttons[i];
if (b.id == 0)
tb.AddSeparator(0);
else {
int image = b.image == 0 ? I_IMAGENONE : tbImages.AddIcon(AtlLoadIconImage(b.image, 0, 24, 24));
tb.AddButton(b.id, b.style | (b.text ? BTNS_SHOWTEXT : 0), TBSTATE_ENABLED, image, b.text, 0);
}
}
pT->CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
pT->AddSimpleReBarBand(tb);
pT->UIAddToolBar(hWndToolBar);
_Module.GetMessageLoop()->AddIdleHandler(this);
return hWndToolBar;
}
BOOL OnIdle() override {
auto pT = static_cast<T*>(this);
pT->UIUpdateToolBar();
return FALSE;
}
};
================================================
FILE: WinSpy/HookHelper.cpp
================================================
#include "pch.h"
#include "HookHelper.h"
decltype(AddHook)* pAddHook;
decltype(RemoveHook)* pRemoveHook;
bool HookHelper::InitHookLib() {
if (!pAddHook) {
auto hLib = ::LoadLibrary(L"WinSpyHook.dll");
if (hLib) {
pAddHook = (decltype(pAddHook))::GetProcAddress(hLib, "AddHook");
pRemoveHook = (decltype(pRemoveHook))::GetProcAddress(hLib, "RemoveHook");
}
}
return pAddHook != nullptr;
}
bool __stdcall HookHelper::AddHook(DWORD hookType, HookConfig const& config) {
if (!InitHookLib())
return false;
return pAddHook(hookType, config);
}
bool __stdcall HookHelper::RemoveHook(DWORD tid) {
if (!InitHookLib())
return false;
return pRemoveHook(tid);
}
================================================
FILE: WinSpy/HookHelper.h
================================================
#pragma once
#include "hooks.h"
struct HookHelper abstract final {
static bool InitHookLib();
static bool WINAPI AddHook(DWORD hookType, HookConfig const& config);
static bool WINAPI RemoveHook(DWORD tid);
};
================================================
FILE: WinSpy/IconHelper.cpp
================================================
#include "pch.h"
#include "IconHelper.h"
HICON IconHelper::GetShieldIcon() {
return GetStockIcon(SIID_SHIELD);
}
HICON IconHelper::GetStockIcon(SHSTOCKICONID id, bool big) {
SHSTOCKICONINFO ssii = { sizeof(ssii) };
if (FAILED(::SHGetStockIconInfo(id, (big ? 0 : SHGSI_SMALLICON) | SHGSI_ICON, &ssii)))
return nullptr;
return ssii.hIcon;
}
================================================
FILE: WinSpy/IconHelper.h
================================================
#pragma once
struct IconHelper {
static HICON GetStockIcon(SHSTOCKICONID id, bool big = false);
static HICON GetShieldIcon();
};
================================================
FILE: WinSpy/ImageIconCache.cpp
================================================
#include "pch.h"
#include "ImageIconCache.h"
#include "resource.h"
int ImageIconCache::GetIcon(const CString& path, HICON* phIcon) const {
if (path.IsEmpty() || path.Find(L'\\') < 0)
return _defIcon;
std::wstring wspath(path);
{
auto it = _icons.find(wspath);
if (it != _icons.end()) {
int index = it->second;
if (phIcon)
*phIcon = _images.GetIcon(index);
return index;
}
}
WORD index = 0;
CString spath(path);
auto hIcon = ::ExtractAssociatedIcon(_Module.GetModuleInstance(), spath.GetBufferSetLength(MAX_PATH), &index);
if (hIcon) {
int index = _images.AddIcon(hIcon);
if (phIcon)
*phIcon = hIcon;
_icons.insert({ wspath, index });
return index;
}
return _defIcon;
}
ImageIconCache::Map::const_iterator ImageIconCache::begin() const {
return _icons.begin();
}
ImageIconCache::Map::const_iterator ImageIconCache::end() const {
return _icons.end();
}
ImageIconCache::ImageIconCache() {
}
void ImageIconCache::SetImageList(HIMAGELIST hil) {
_images.Attach(hil);
_defIcon = _images.AddIcon(AtlLoadSysIcon(IDI_APPLICATION));
}
HIMAGELIST ImageIconCache::GetImageList() const {
return _images;
}
ImageIconCache& ImageIconCache::Get() {
static ImageIconCache cache;
return cache;
}
================================================
FILE: WinSpy/ImageIconCache.h
================================================
#pragma once
struct ImageIconCache {
static ImageIconCache& Get();
HIMAGELIST GetImageList() const;
void SetImageList(HIMAGELIST hil);
int GetIcon(const CString& path, HICON* phIcon = nullptr) const;
using Map = std::unordered_map<std::wstring, int>;
Map::const_iterator begin() const;
Map::const_iterator end() const;
private:
ImageIconCache();
ImageIconCache(const ImageIconCache&) = delete;
ImageIconCache& operator=(const ImageIconCache&) = delete;
private:
mutable CImageList _images;
mutable Map _icons;
int _defIcon;
};
================================================
FILE: WinSpy/Interfaces.h
================================================
#pragma once
struct CMessagesView;
struct IMainFrame {
virtual CUpdateUIBase& GetUIUpdate() = 0;
virtual UINT ShowPopupMenu(HMENU hMenu, const POINT& pt, DWORD flags = 0) = 0;
virtual HWND GetHwnd() const = 0;
virtual CMessagesView* CreateMessagesView() = 0;
virtual void CloseTab(CWindow* win) = 0;
};
struct ToolBarButtonInfo {
UINT id;
int image;
BYTE style = BTNS_BUTTON;
PCWSTR text = nullptr;
};
================================================
FILE: WinSpy/MainFrm.cpp
================================================
// MainFrm.cpp : implmentation of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#include "resource.h"
#include "aboutdlg.h"
#include "WindowsView.h"
#include "MainFrm.h"
#include "FindWindowDlg.h"
#include "IconHelper.h"
#include "ImageIconCache.h"
#include "ProcessesView.h"
#include "SecurityHelper.h"
#include "MessagesView.h"
#include "AutomationTreeView.h"
const int WINDOW_MENU_POSITION = 5;
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) {
if (CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
return TRUE;
return m_view.PreTranslateMessage(pMsg);
}
BOOL CMainFrame::OnIdle() {
UIUpdateToolBar();
return FALSE;
}
LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
if (SecurityHelper::IsRunningElevated()) {
CMenuHandle menu = GetMenu();
menu.GetSubMenu(0).DeleteMenu(0, MF_BYPOSITION);
menu.GetSubMenu(0).DeleteMenu(0, MF_BYPOSITION);
}
InitMenu();
CToolBarCtrl tb;
auto hWndToolBar = tb.Create(m_hWnd, nullptr, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST, 0, ATL_IDW_TOOLBAR);
tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS);
InitToolBar(tb);
CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
AddSimpleReBarBand(hWndToolBar, nullptr, TRUE);
CReBarCtrl rb(m_hWndToolBar);
rb.LockBands(true);
CreateSimpleStatusBar();
//m_view.m_bTabCloseButton = false;
m_hWndClient = m_view.Create(m_hWnd, rcDefault, nullptr,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
UIAddToolBar(hWndToolBar);
UISetCheck(ID_VIEW_TOOLBAR, 1);
UISetCheck(ID_VIEW_STATUS_BAR, 1);
ImageIconCache::Get().SetImageList(WindowHelper::GetImageList());
// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);
CImageList images;
images.Create(16, 16, ILC_COLOR32, 4, 4);
UINT icons[] = { IDI_WINDOWS, IDI_PROCESSES, IDI_MESSAGES, IDI_AUTOMATION };
for (auto icon : icons) {
images.AddIcon(AtlLoadIconImage(icon, 0, 16, 16));
}
m_view.SetImageList(images);
m_view.SetWindowMenu(((CMenuHandle)GetMenu()).GetSubMenu(WINDOW_MENU_POSITION));
PostMessage(WM_COMMAND, ID_VIEW_ALLWINDOWS);
return 0;
}
LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
// unregister message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->RemoveMessageFilter(this);
pLoop->RemoveIdleHandler(this);
bHandled = FALSE;
return 1;
}
LRESULT CMainFrame::OnMenuSelect(UINT, WPARAM, LPARAM, BOOL&) {
return 0;
}
LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
PostMessage(WM_CLOSE);
return 0;
}
LRESULT CMainFrame::OnViewAllWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
auto pView = new CWindowsView(this);
{
CWaitCursor wait;
pView->Create(m_view, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
m_view.AddPage(pView->m_hWnd, _T("Windows Tree"), 0, pView);
}
pView->OnActivate(true);
return 0;
}
LRESULT CMainFrame::OnViewAllProcesses(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
auto pView = new CProcessesView(this);
{
CWaitCursor wait;
pView->Create(m_view, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
m_view.AddPage(pView->m_hWnd, _T("Processes"), 1, pView);
}
pView->OnActivate(true);
return 0;
}
LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
static BOOL bVisible = TRUE; // initially visible
bVisible = !bVisible;
CReBarCtrl rebar = m_hWndToolBar;
int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1); // toolbar is 2nd added band
rebar.ShowBand(nBandIndex, bVisible);
UISetCheck(ID_VIEW_TOOLBAR, bVisible);
UpdateLayout();
return 0;
}
LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
UpdateLayout();
return 0;
}
LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
CAboutDlg dlg;
dlg.DoModal();
return 0;
}
LRESULT CMainFrame::OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
int nActivePage = m_view.GetActivePage();
if (nActivePage != -1)
m_view.RemovePage(nActivePage);
else
::MessageBeep((UINT)-1);
return 0;
}
LRESULT CMainFrame::OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
m_view.RemoveAllPages();
return 0;
}
LRESULT CMainFrame::OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
int nPage = wID - ID_WINDOW_TABFIRST;
m_view.SetActivePage(nPage);
return 0;
}
LRESULT CMainFrame::OnCommandToActiveView(WORD code, WORD id, HWND h, BOOL&) {
auto page = m_view.GetActivePage();
if (page < 0)
return 0;
return ::SendMessage(m_view.GetPageHWND(page), WM_COMMAND, MAKELONG(id, code), reinterpret_cast<LPARAM>(h));
}
LRESULT CMainFrame::OnFindWindow(WORD, WORD, HWND, BOOL&) {
CFindWindowDlg dlg(this);
if (IDOK == dlg.DoModal()) {
WindowHelper::ShowWindowProperties(dlg.GetSelectedHwnd());
}
return 0;
}
LRESULT CMainFrame::OnRunAsAdmin(WORD, WORD, HWND, BOOL&) {
if (SecurityHelper::RunElevated()) {
SendMessage(WM_CLOSE);
}
return 0;
}
LRESULT CMainFrame::OnTabCloseButton(int, LPNMHDR, BOOL&) {
return 0;
}
LRESULT CMainFrame::OnViewAutomationTree(WORD, WORD, HWND, BOOL&) {
auto pView = new CAutomationTreeView(this);
pView->Create(m_view, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
m_view.AddPage(pView->m_hWnd, L"UI Automation", 2, pView);
pView->OnActivate(true);
return 0;
}
CUpdateUIBase& CMainFrame::GetUIUpdate() {
return *this;
}
UINT CMainFrame::ShowPopupMenu(HMENU hMenu, const POINT& pt, DWORD flags) {
return (UINT)ShowContextMenu(hMenu, 0, pt.x, pt.y);
}
CMessagesView* CMainFrame::CreateMessagesView() {
auto pView = new CMessagesView(this);
pView->Create(m_view, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
m_view.AddPage(pView->m_hWnd, L"Messages", 2, pView);
pView->OnActivate(true);
return pView;
}
void CMainFrame::CloseTab(CWindow* win) {
m_view.RemovePage(m_view.GetActivePage());
}
void CMainFrame::InitToolBar(CToolBarCtrl& tb) {
CImageList tbImages;
tbImages.Create(24, 24, ILC_COLOR32, 8, 4);
tb.SetImageList(tbImages);
struct {
UINT id;
int image;
int style = BTNS_BUTTON;
PCWSTR text = nullptr;
} buttons[] = {
{ ID_VIEW_REFRESH, IDI_REFRESH },
{ 0 },
{ ID_VIEW_ALLWINDOWS, IDI_WINDOWS },
{ ID_VIEW_ALLPROCESSES, IDI_PROCESSES },
{ ID_WINDOW_FIND, IDI_WINDOWSEARCH },
{ 0 },
{ ID_VIEW_HIDDENWINDOWS, IDI_WINDOW_HIDDEN },
{ ID_VIEW_EMPTYTITLEWINDOWS, IDI_WINDOW_NOTEXT },
{ ID_WINDOW_PROPERTIES, IDI_WINPROP },
};
for (auto& b : buttons) {
if (b.id == 0)
tb.AddSeparator(0);
else {
int image = tbImages.AddIcon(AtlLoadIconImage(b.image, 0, 24, 24));
tb.AddButton(b.id, b.style, TBSTATE_ENABLED, image, b.text, 0);
}
}
}
void CMainFrame::InitMenu() {
AddMenu(GetMenu());
struct {
UINT id, icon;
HICON hIcon = nullptr;
} cmds[] = {
{ ID_FILE_RUNASADMINISTRATOR, 0, IconHelper::GetShieldIcon() },
{ ID_VIEW_REFRESH, IDI_REFRESH },
{ ID_VIEW_ALLWINDOWS, IDI_WINDOWS },
{ ID_VIEW_HIDDENWINDOWS, IDI_WINDOW_HIDDEN },
{ ID_VIEW_EMPTYTITLEWINDOWS, IDI_WINDOW_NOTEXT },
{ ID_WINDOW_CLOSE, IDI_WINDOW_CLOSE },
{ ID_STATE_CLOSE, IDI_WINDOW_CLOSE },
{ ID_WINDOW_MINIMIZE, IDI_WINDOW_MINIMIZE },
{ ID_WINDOW_MAXIMIZE, IDI_WINDOW_MAXIMIZE },
{ ID_VIEW_ALLPROCESSES, IDI_PROCESSES },
{ ID_WINDOW_PROPERTIES, IDI_WINPROP },
{ ID_PROCESS_PROPERTIES, IDI_PROCESS_INFO },
{ ID_WINDOW_FIND, IDI_WINDOWSEARCH },
{ ID_WINDOW_RESTORE, IDI_RESTORE },
{ ID_TREE_SENDTOBACK, IDI_WINDOW_SENDTOBACK },
{ ID_WINDOW_BRINGTOFRONT, IDI_SENDTOFRONT },
};
for (auto& cmd : cmds) {
if (cmd.icon)
AddCommand(cmd.id, cmd.icon);
else
AddCommand(cmd.id, cmd.hIcon);
}
}
LRESULT CMainFrame::OnTabActivated(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) {
if (m_ActivePage >= 0 && m_ActivePage < m_view.GetPageCount())
::SendMessage(m_view.GetPageHWND(m_ActivePage), TBVN_PAGEACTIVATED, 0, 0);
m_ActivePage = m_view.GetActivePage();
if (m_ActivePage < 0)
return 0;
return ::SendMessage(m_view.GetPageHWND(m_ActivePage), TBVN_PAGEACTIVATED, 1, 0);
}
================================================
FILE: WinSpy/MainFrm.h
================================================
// MainFrm.h : interface of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Interfaces.h"
#include <CustomTabView.h>
#include <OwnerDrawnMenu.h>
class CMainFrame :
public CFrameWindowImpl<CMainFrame>,
public CAutoUpdateUI<CMainFrame>,
public COwnerDrawnMenu<CMainFrame>,
public CMessageFilter,
public CIdleHandler,
public IMainFrame {
public:
DECLARE_FRAME_WND_CLASS(L"WinSpyMainWindowClass", IDR_MAINFRAME)
BOOL PreTranslateMessage(MSG* pMsg) override;
BOOL OnIdle() override;
BEGIN_MSG_MAP(CMainFrame)
//NOTIFY_CODE_HANDLER(TBVN_TABCLOSEBTN, OnTabCloseButton)
COMMAND_ID_HANDLER(ID_VIEW_ALLWINDOWS, OnViewAllWindows)
COMMAND_ID_HANDLER(ID_VIEW_ALLPROCESSES, OnViewAllProcesses)
COMMAND_ID_HANDLER(ID_VIEW_AUTOMATIONTREE, OnViewAutomationTree)
COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(ID_WINDOW_FIND, OnFindWindow)
COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
COMMAND_ID_HANDLER(ID_FILE_RUNASADMINISTRATOR, OnRunAsAdmin)
MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
CHAIN_MSG_MAP(CAutoUpdateUI<CMainFrame>)
CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
COMMAND_RANGE_HANDLER(1, 0xffff, OnCommandToActiveView)
NOTIFY_CODE_HANDLER(TBVN_PAGEACTIVATED, OnTabActivated)
CHAIN_MSG_MAP(COwnerDrawnMenu<CMainFrame>)
END_MSG_MAP()
private:
// IMainFrame
CUpdateUIBase& GetUIUpdate() override;
UINT ShowPopupMenu(HMENU hMenu, const POINT& pt, DWORD flags = 0) override;
HWND GetHwnd() const override {
return m_hWnd;
}
CMessagesView* CreateMessagesView() override;
void CloseTab(CWindow* win) override;
void InitToolBar(CToolBarCtrl& tb);
void InitMenu();
// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnTabActivated(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewAllWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewAllProcesses(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnCommandToActiveView(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnFindWindow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnRunAsAdmin(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnTabCloseButton(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnViewAutomationTree(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
int m_ActivePage = -1;
CCustomTabView m_view;
};
================================================
FILE: WinSpy/MessageDecoder.cpp
================================================
#include "pch.h"
#include "MessageDecoder.h"
#include "FormatHelper.h"
#define CASE_STR(x) case x: return L#x
CString MessageDecoder::Decode(UINT msg, WPARAM wp, LPARAM lp) {
if (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) {
CPoint pt(GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
return L"Keys: [" + MouseKey((int)wp) + L"] Pos: " + FormatHelper::FormatPoint(pt);
}
if (msg >= WM_KEYFIRST && msg <= WM_KEYLAST) {
CString text;
text.Format(L"VK: %u", (DWORD)wp);
return text;
}
switch (msg) {
case WM_SYSCOMMAND:
{
CPoint pt(GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
auto cmd = SysCommandToString((DWORD)wp);
CString pos;
if (pt.y > 1) {
pos = L"Cursor: " + FormatHelper::FormatPoint(pt);
}
return L"Cmd: " + cmd + L" " + pos;
}
case WM_SETREDRAW:
return CString(L"Redraw: ") + (wp ? L"True" : L"False");
case WM_SIZE:
{
CPoint pt(GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
auto size = L" Size: " + FormatHelper::FormatPoint(pt);
return L"Type: " + SizeParamToString((DWORD)wp) + size;
}
}
return L"";
}
CString MessageDecoder::MouseKey(int key) {
static const struct {
int key;
PCWSTR name;
} keys[] = {
{ MK_SHIFT, L"Shift" },
{ MK_CONTROL, L"Ctrl" },
{ MK_LBUTTON, L"LButton" },
{ MK_RBUTTON, L"RButton" },
{ MK_MBUTTON, L"MButton" },
{ MK_XBUTTON1, L"XButton1" },
{ MK_XBUTTON2, L"XButton2" },
};
CString text;
for (auto& item : keys) {
if ((key & item.key) == item.key)
text += item.name + CString(L", ");
}
if (!text.IsEmpty())
text = text.Left(text.GetLength() - 2);
else
text = L"None";
return text;
}
CString MessageDecoder::SysCommandToString(DWORD cmd) {
switch (cmd) {
CASE_STR(SC_CLOSE);
CASE_STR(SC_CONTEXTHELP);
CASE_STR(SC_DEFAULT);
CASE_STR(SC_HOTKEY);
CASE_STR(SC_HSCROLL);
CASE_STR(SCF_ISSECURE);
CASE_STR(SC_KEYMENU);
CASE_STR(SC_MAXIMIZE);
CASE_STR(SC_MINIMIZE);
CASE_STR(SC_MONITORPOWER);
CASE_STR(SC_MOUSEMENU);
CASE_STR(SC_MOVE);
CASE_STR(SC_NEXTWINDOW);
CASE_STR(SC_PREVWINDOW);
CASE_STR(SC_RESTORE);
CASE_STR(SC_SCREENSAVE);
CASE_STR(SC_SIZE);
CASE_STR(SC_TASKLIST);
CASE_STR(SC_VSCROLL);
}
CString text;
text.Format(L"0x%X", cmd);
return text;
}
CString MessageDecoder::SizeParamToString(DWORD type) {
switch (type) {
CASE_STR(SIZE_MAXHIDE);
CASE_STR(SIZE_MAXIMIZED);
CASE_STR(SIZE_MAXSHOW);
CASE_STR(SIZE_MINIMIZED);
CASE_STR(SIZE_RESTORED);
}
CString text;
text.Format(L"%u", type);
return text;
}
================================================
FILE: WinSpy/MessageDecoder.h
================================================
#pragma once
struct MessageDecoder final abstract {
static CString Decode(UINT msg, WPARAM wp, LPARAM lp);
static CString MouseKey(int key);
static CString SysCommandToString(DWORD cmd);
static CString SizeParamToString(DWORD type);
};
================================================
FILE: WinSpy/MessagesView.cpp
================================================
#include "pch.h"
#include "MessagesView.h"
#include "hooks.h"
#include "FormatHelper.h"
#include "WindowHelper.h"
#include "MessageDecoder.h"
#include "HookHelper.h"
bool CMessagesView::CaptureWindow(HWND hWnd) {
if (!m_hReadyEvent)
m_hReadyEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
m_CaptureHwnd = hWnd;
m_CaptureOptions = CaptureOptions::Window;
m_CaptureTid = ::GetWindowThreadProcessId(hWnd, nullptr);
if (m_hThread) {
::PostThreadMessage(::GetThreadId(m_hThread), WM_QUIT, 0, 0);
::CloseHandle(m_hThread);
}
m_hThread = ::CreateThread(nullptr, 0, [](auto param) {
return ((CMessagesView*)param)->ProcessHook();
}, this, 0, nullptr);
if (!m_hThread)
return false;
ATLVERIFY(WAIT_OBJECT_0 == ::WaitForSingleObject(m_hReadyEvent, INFINITE));
ATLASSERT(m_CallbackWnd);
HookConfig config{};
config.CallbackWnd = m_CallbackWnd;
config.TargetWnd = hWnd;
config.Options = HookOptions::Window | HookOptions::ChildWindows;
config.ThreadId = m_CaptureTid;
return HookHelper::AddHook(WH_GETMESSAGE, config);
}
void CMessagesView::HookCallbackMsg(DWORD hookType, HookDataHeader* header) {
switch (header->HookType) {
case WH_GETMESSAGE:
auto data = reinterpret_cast<GetMessageData*>(header);
if (data->wParam == PM_REMOVE) {
MessageInfo mi(data->Msg);
mi.ThreadId = ::GetWindowThreadProcessId(mi.hwnd, &mi.ProcessId);
std::lock_guard locker(m_TempMessagesLock);
m_TempMessages.push_back(mi);
}
break;
}
}
void CMessagesView::OnFinalMessage(HWND) {
delete this;
}
CString CMessagesView::GetColumnText(HWND hWnd, int row, int col) const {
auto& item = m_Messages[row];
CString text;
switch (GetColumnManager(hWnd)->GetColumnTag<ColumnType>(col)) {
case ColumnType::Window:
return FormatHelper::FormatHWndOrNone(item.hwnd);
case ColumnType::Message:
text.Format(L"%s (0x%X)", (PCWSTR)WindowHelper::WindowMessageToString(item.message), item.message);
break;
case ColumnType::Thread:
text.Format(L"%u", item.ThreadId);
break;
case ColumnType::Process:
text.Format(L"%u", item.ProcessId);
break;
case ColumnType::wParam:
text.Format(L"0x%zX", item.wParam);
break;
case ColumnType::lParam:
text.Format(L"0x%zX", item.lParam);
break;
case ColumnType::Time:
text.Format(L"0x%X", item.time);
break;
case ColumnType::Point:
return FormatHelper::FormatPoint(item.pt);
case ColumnType::DecodedMessage:
return MessageDecoder::Decode(item.message, item.wParam, item.lParam);
}
return text;
}
void CMessagesView::UpdateList() {
m_List.SetItemCountEx((int)m_Messages.size(), LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL);
m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage());
}
DWORD CMessagesView::ProcessHook() {
m_CallbackWnd.Create(HWND_MESSAGE, nullptr, nullptr);
ATLASSERT(m_CallbackWnd);
::SetEvent(m_hReadyEvent);
MSG msg;
while (::GetMessage(&msg, nullptr, 0, 0))
::DispatchMessage(&msg);
m_CallbackWnd.DestroyWindow();
return 0;
}
LRESULT CMessagesView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
m_hWndClient = m_List.Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
| LVS_REPORT | LVS_OWNERDATA | LVS_SINGLESEL | LVS_SHAREIMAGELISTS, WS_EX_CLIENTEDGE);
m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP);
auto cm = GetColumnManager(m_List);
struct {
PCWSTR text;
ColumnType type;
int width = 100;
int format = LVCFMT_LEFT;
ColumnFlags flags = ColumnFlags::Visible;
} columns[] = {
// { L"Type", ColumnType::Type, 70 },
{ L"Time", ColumnType::Time, 120, LVCFMT_LEFT },
{ L"Window", ColumnType::Window, 100, LVCFMT_RIGHT },
{ L"Message", ColumnType::Message, 140, LVCFMT_LEFT },
{ L"WPARAM", ColumnType::wParam, 100, LVCFMT_RIGHT },
{ L"LPARAM", ColumnType::lParam, 100, LVCFMT_RIGHT },
{ L"Thread", ColumnType::Thread, 100, LVCFMT_RIGHT },
{ L"Decoded Message", ColumnType::DecodedMessage, 250 },
{ L"Process", ColumnType::Process, 100, LVCFMT_RIGHT },
{ L"Point", ColumnType::Point, 100, LVCFMT_RIGHT },
};
for (auto& col : columns) {
cm->AddColumn(col.text, col.format, col.width, col.type, col.flags);
}
cm->UpdateColumns();
SetTimer(1, 1200);
return 0;
}
LRESULT CMessagesView::OnTimer(UINT, WPARAM id, LPARAM, BOOL&) {
if (id == 1) {
{
std::lock_guard locker(m_TempMessagesLock);
if (m_TempMessages.empty())
return 0;
m_Messages.insert(m_Messages.end(), m_TempMessages.begin(), m_TempMessages.end());
m_TempMessages.clear();
}
UpdateList();
}
return 0;
}
LRESULT CMessagesView::OnDestroy(UINT, WPARAM, LPARAM, BOOL&) {
if (m_hThread) {
::PostThreadMessage(::GetThreadId(m_hThread), WM_QUIT, 0, 0);
::CloseHandle(m_hThread);
HookHelper::RemoveHook(m_CaptureTid);
}
if (m_hReadyEvent)
::CloseHandle(m_hReadyEvent);
return LRESULT();
}
LRESULT CHookCallbackWnd::OnHookCallback(UINT msg, WPARAM wp, LPARAM lp, BOOL&) {
auto cds = reinterpret_cast<COPYDATASTRUCT*>(lp);
auto header = reinterpret_cast<HookDataHeader*>(cds->lpData);
m_pView->HookCallbackMsg(header->HookType, header);
return TRUE;
}
================================================
FILE: WinSpy/MessagesView.h
================================================
#pragma once
#include "ViewBase.h"
#include "VirtualListView.h"
#include "hooks.h"
struct CMessagesView;
struct CHookCallbackWnd : CWindowImpl<CHookCallbackWnd> {
CHookCallbackWnd(CMessagesView* pView) : m_pView(pView) {}
BEGIN_MSG_MAP(CHookCallbackWnd)
MESSAGE_HANDLER(WM_COPYDATA, OnHookCallback)
END_MSG_MAP()
LRESULT OnHookCallback(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
private:
CMessagesView* m_pView;
};
struct CMessagesView : CViewBase<CMessagesView>, CVirtualListView<CMessagesView> {
CMessagesView(IMainFrame* frame) : CViewBase(frame), m_CallbackWnd(this) {}
bool CaptureWindow(HWND hWnd);
bool CaptureThread(DWORD tid);
bool CaptureProcess(DWORD tid);
void HookCallbackMsg(DWORD hookType, HookDataHeader* header);
void OnFinalMessage(HWND) override;
CString GetColumnText(HWND, int row, int col) const;
protected:
BEGIN_MSG_MAP(CMessagesView)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
CHAIN_MSG_MAP(CVirtualListView<CMessagesView>)
CHAIN_MSG_MAP(CViewBase<CMessagesView>)
END_MSG_MAP()
private:
enum class ColumnType {
Type,
Window,
Thread,
Process,
Message,
DecodedMessage,
wParam,
lParam,
Time,
Point
};
enum class CaptureOptions {
Window,
Thread,
Process
};
enum class MessageInfoFlags {
None = 0,
Result = 1,
};
struct MessageInfo : MSG {
MessageInfoFlags Flags;
DWORD ThreadId;
DWORD ProcessId;
};
void UpdateUI();
void UpdateList();
DWORD ProcessHook();
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
CListViewCtrl m_List;
std::vector<MessageInfo> m_Messages;
std::vector<MessageInfo> m_TempMessages;
std::mutex m_TempMessagesLock;
CaptureOptions m_CaptureOptions;
DWORD m_CaptureTid;
HWND m_CaptureHwnd;
HANDLE m_hThread{ nullptr };
CHookCallbackWnd m_CallbackWnd;
HANDLE m_hReadyEvent{ nullptr };
};
================================================
FILE: WinSpy/ProcessHelper.cpp
================================================
#include "pch.h"
#include "ProcessHelper.h"
#include "WindowHelper.h"
#include <TlHelp32.h>
#include <unordered_set>
CString ProcessHelper::GetProcessImageName(DWORD pid, bool fullPath) {
if (_names.empty())
EnumProcesses();
auto hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
CString result;
if (hProcess) {
WCHAR name[MAX_PATH];
DWORD size = _countof(name);
if (::QueryFullProcessImageName(hProcess, 0, name, &size)) {
result = fullPath ? name : ::wcsrchr(name, L'\\') + 1;
}
::CloseHandle(hProcess);
}
else if (auto it = _names.find(pid); it != _names.end())
return it->second;
return result;
}
ProcessesInfo ProcessHelper::EnumProcessesAndThreads(EnumProcessesOptions options) {
ProcessesInfo info;
auto& processes = info.Processes;
processes.reserve(512);
auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return info;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
std::unordered_map<DWORD, int> processMap;
processMap.reserve(512);
::Process32First(hSnapshot, &pe);
while (::Process32Next(hSnapshot, &pe)) {
ProcessInfo pi;
pi.ProcessId = pe.th32ProcessID;
pi.Threads.reserve(pe.cntThreads);
pi.ProcessName = pe.szExeFile;
auto hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pi.ProcessId);
if (hProcess) {
DWORD size = MAX_PATH;
::QueryFullProcessImageName(hProcess, 0, pi.FullPath.GetBufferSetLength(size), &size);
::CloseHandle(hProcess);
}
processes.push_back(pi);
processMap.insert({ pi.ProcessId, (int)processes.size() - 1 });
}
std::unordered_set<DWORD> msgOnly;
if ((options & EnumProcessesOptions::IncludeMessageOnly) == EnumProcessesOptions::IncludeMessageOnly) {
HWND hWnd = nullptr;
for (;;) {
hWnd = ::FindWindowEx(HWND_MESSAGE, hWnd, nullptr, nullptr);
if (!hWnd)
break;
auto tid = ::GetWindowThreadProcessId(hWnd, nullptr);
msgOnly.insert(tid);
if (auto it = info.MessageOnly.find(tid); it != info.MessageOnly.end()) {
it->second.push_back(hWnd);
}
else {
info.MessageOnly.insert({ tid, { hWnd } });
}
}
}
THREADENTRY32 te;
te.dwSize = sizeof(te);
::Thread32First(hSnapshot, &te);
do {
//
// skip idle process
//
if (te.th32OwnerProcessID == 0)
continue;
auto& pi = processes[processMap[te.th32OwnerProcessID]];
if ((options & EnumProcessesOptions::UIThreadsOnly) == EnumProcessesOptions::UIThreadsOnly) {
if (!WindowHelper::ThreadHasWindows(te.th32ThreadID) && !msgOnly.contains(te.th32ThreadID))
continue;
}
pi.Threads.push_back(te.th32ThreadID);
} while (::Thread32Next(hSnapshot, &te));
if ((options & EnumProcessesOptions::SkipProcessesWithNoUI) == EnumProcessesOptions::SkipProcessesWithNoUI) {
for (int i = 0; i < (int)processes.size(); i++) {
if (processes[i].Threads.empty()) {
processes.erase(processes.begin() + i);
i--;
}
}
}
return info;
}
void ProcessHelper::ShowProcessProperties(ProcessInfo const& pi) {
}
void ProcessHelper::EnumProcesses() {
auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
ATLASSERT(hSnapshot != INVALID_HANDLE_VALUE);
if (hSnapshot == INVALID_HANDLE_VALUE) {
_names.insert({ 0, L"(Idle)" });
return;
}
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
::Process32First(hSnapshot, &pe);
_names.reserve(512);
while (::Process32Next(hSnapshot, &pe)) {
auto hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID);
if (!hProcess) {
_names.insert({ pe.th32ProcessID, pe.szExeFile });
}
else {
::CloseHandle(hProcess);
}
}
}
================================================
FILE: WinSpy/ProcessHelper.h
================================================
#pragma once
struct ProcessInfo {
DWORD ProcessId;
std::vector<DWORD> Threads;
CString ProcessName;
CString FullPath;
};
enum class EnumProcessesOptions {
None = 0,
UIThreadsOnly = 1,
SkipProcessesWithNoUI = 2,
IncludeMessageOnly = 4,
};
DEFINE_ENUM_FLAG_OPERATORS(EnumProcessesOptions);
struct ProcessesInfo {
std::vector<ProcessInfo> Processes;
std::unordered_map<DWORD, std::vector<HWND>> MessageOnly;
};
struct ProcessHelper {
static CString GetProcessImageName(DWORD pid, bool fullPath = false);
static ProcessesInfo EnumProcessesAndThreads(EnumProcessesOptions options);
static void ShowProcessProperties(ProcessInfo const& pi);
static void EnumProcesses();
private:
inline static std::unordered_map<DWORD, CString> _names;
};
================================================
FILE: WinSpy/ProcessesView.cpp
================================================
#include "pch.h"
#include "resource.h"
#include "ProcessesView.h"
#include "ImageIconCache.h"
LRESULT CProcessesView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
m_Splitter.SetSplitterExtendedStyle(SPLIT_FLATBAR | SPLIT_PROPORTIONAL);
m_hWndClient = m_Splitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_Tree.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, 0, IDC_TREE);
m_WindowsView.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_Tree.SetExtendedStyle(TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER);
m_Tree.SetImageList(WindowHelper::GetImageList(), TVSIL_NORMAL);
m_Splitter.SetSplitterPanes(m_Tree, m_WindowsView);
UpdateLayout();
m_Splitter.SetSplitterPosPct(35);
InitTree();
return 0;
}
void CProcessesView::OnActivate(bool active) {
if (active) {
UpdateUI();
}
}
LRESULT CProcessesView::OnTimer(UINT /*uMsg*/, WPARAM id, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
if (id == 3) {
KillTimer(3);
ChangeSelection(m_Tree.GetSelectedItem());
}
return 0;
}
void CProcessesView::InitTree() {
m_Tree.LockWindowUpdate();
m_Tree.DeleteAllItems();
m_Processes.clear();
m_WindowMap.clear();
m_Threads.clear();
m_TotalWindows = m_TotalVisibleWindows = m_TopLevelWindows = 0;
CString text;
auto info = ProcessHelper::EnumProcessesAndThreads(
EnumProcessesOptions::UIThreadsOnly | EnumProcessesOptions::SkipProcessesWithNoUI | EnumProcessesOptions::IncludeMessageOnly);
for (auto& pi : info.Processes) {
auto icon = ImageIconCache::Get().GetIcon(pi.FullPath);
text.Format(L"%s (%u)", (PCWSTR)pi.ProcessName, pi.ProcessId);
auto node = m_Tree.InsertItem(text, icon, icon, TVI_ROOT, TVI_SORT);
node.SetData((DWORD_PTR)ItemType::Process);
m_Processes.insert({ node, pi });
for (auto tid : pi.Threads) {
text.Format(L"Thread %u (0x%X)", tid, tid);
auto tnode = m_Tree.InsertItem(text, icon, icon, node, TVI_LAST);
if (!WindowHelper::ThreadHasWindows(tid))
tnode.SetState(TVIS_CUT, TVIS_CUT);
tnode.SetData((DWORD_PTR)ItemType::Thread);
m_Threads.insert({ tnode, tid });
struct LocalData {
CProcessesView* pThis;
HTREEITEM hParent;
};
LocalData data = { this, tnode };
::EnumThreadWindows(tid, [](auto hWnd, auto param) {
auto data = (LocalData*)param;
data->pThis->AddNode(hWnd, data->hParent);
return TRUE;
}, reinterpret_cast<LPARAM>(&data));
//
// add message-only windows
//
if (auto it = info.MessageOnly.find(tid); it != info.MessageOnly.end()) {
for (auto hWnd : it->second) {
AddNode(hWnd, tnode);
}
}
}
}
m_Tree.LockWindowUpdate(FALSE);
}
CTreeItem CProcessesView::AddNode(HWND hWnd, HTREEITEM hParent) {
CString text, name;
CWindow win(hWnd);
m_TotalWindows++;
if (win.IsWindowVisible())
m_TotalVisibleWindows++;
m_TopLevelWindows++;
if (!m_ShowHiddenWindows && !win.IsWindowVisible())
return nullptr;
win.GetWindowText(name);
if (!m_ShowNoTitleWindows && name.IsEmpty())
return nullptr;
if (name.GetLength() > 64)
name = name.Left(64) + L"...";
if (!name.IsEmpty())
name = L"[" + name + L"]";
WCHAR className[64] = { 0 };
::GetClassName(hWnd, className, _countof(className));
text.Format(L"0x%zX (%s) %s", (DWORD_PTR)hWnd, className, (PCWSTR)name);
HICON hIcon{ nullptr };
int image = 0;
if ((win.GetStyle() & WS_CHILD) == 0) {
auto& icons = WindowHelper::GetIconMap();
if (auto it = icons.find(hWnd); it == icons.end()) {
hIcon = WindowHelper::GetWindowOrProcessIcon(hWnd);
if (hIcon) {
icons.insert({ hWnd, image = WindowHelper::GetImageList().AddIcon(hIcon) });
}
}
else {
image = it->second;
}
}
auto node = m_Tree.InsertItem(text, image, image, hParent, TVI_LAST);
node.SetData((DWORD_PTR)hWnd);
m_WindowMap.insert({ hWnd, node });
if (!win.IsWindowVisible())
node.SetState(TVIS_CUT, TVIS_CUT);
if (win.GetWindow(GW_CHILD)) {
// add a "plus" button
node.AddTail(L"*", 0);
}
return node;
}
LRESULT CProcessesView::OnNodeExpanding(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
if (tv->action == TVE_EXPAND) {
auto hItem = tv->itemNew.hItem;
auto child = m_Tree.GetChildItem(hItem);
if (child.GetData() == 0) {
child.Delete();
AddChildWindows(hItem);
}
}
return 0;
}
void CProcessesView::AddChildWindows(HTREEITEM hParent) {
auto hWnd = (HWND)m_Tree.GetItemData(hParent);
ATLASSERT(hWnd);
m_hCurrentNode = hParent;
::EnumChildWindows(hWnd, [](auto hChild, auto p) -> BOOL {
auto pThis = (CProcessesView*)p;
return pThis->AddChildNode(hChild);
}, reinterpret_cast<LPARAM>(this));
}
BOOL CProcessesView::AddChildNode(HWND hChild) {
if (::GetAncestor(hChild, GA_PARENT) == (HWND)m_Tree.GetItemData(m_hCurrentNode)) {
AddNode(hChild, m_hCurrentNode);
}
return TRUE;
}
LRESULT CProcessesView::OnTreeNodeRightClick(HTREEITEM hItem, CPoint const& pt) {
ATLASSERT(m_Selected);
auto data = static_cast<ItemType>(m_Selected.GetData());
int index = 0;
if (data == ItemType::Thread)
index = 3;
else if (data == ItemType::Process)
index = 2;
CMenu menu;
menu.LoadMenu(IDR_CONTEXT);
return GetFrame()->ShowPopupMenu(menu.GetSubMenu(index), pt);
}
LRESULT CProcessesView::OnWindowShow(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_Selected);
m_SelectedHwnd.ShowWindow(SW_SHOW);
return 0;
}
LRESULT CProcessesView::OnWindowHide(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_Selected);
m_SelectedHwnd.ShowWindow(SW_HIDE);
return 0;
}
LRESULT CProcessesView::OnWindowMinimize(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_Selected);
m_SelectedHwnd.ShowWindow(SW_MINIMIZE);
return 0;
}
LRESULT CProcessesView::OnWindowMaximize(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_Selected);
m_SelectedHwnd.ShowWindow(SW_MAXIMIZE);
return 0;
}
LRESULT CProcessesView::OnWindowRestore(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_Selected);
m_SelectedHwnd.ShowWindow(SW_RESTORE);
return 0;
}
LRESULT CProcessesView::OnWindowFlash(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_Selected);
WindowHelper::Flash((HWND)m_Selected.GetData());
return 0;
}
LRESULT CProcessesView::OnWindowBringToFront(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_Selected);
m_SelectedHwnd.BringWindowToTop();
return 0;
}
LRESULT CProcessesView::OnNodeSelected(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
if (tv->action == TVC_BYKEYBOARD) {
// short delay before update in case the user moves quickly through the tree
SetTimer(3, 250, nullptr);
}
else {
ChangeSelection(tv->itemNew.hItem);
}
return 0;
}
LRESULT CProcessesView::OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint const& pt) {
auto data = m_Tree.GetItemData(hItem);
switch (static_cast<ItemType>(data)) {
case ItemType::Process:
ProcessHelper::ShowProcessProperties(m_Processes[hItem]);
break;
case ItemType::Thread:
break;
default:
auto hWnd = reinterpret_cast<HWND>(data);
WindowHelper::ShowWindowProperties(hWnd);
break;
}
return 0;
}
LRESULT CProcessesView::OnWindowProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
ATLASSERT(m_SelectedHwnd);
WindowHelper::ShowWindowProperties(m_SelectedHwnd);
return 0;
}
LRESULT CProcessesView::OnProcessProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
auto hItem = m_Tree.GetSelectedItem();
ProcessHelper::ShowProcessProperties(m_Processes[hItem]);
return 0;
}
void CProcessesView::ChangeSelection(HTREEITEM hItem) {
m_Selected = hItem;
m_Selected.m_pTreeView = &m_Tree;
auto data = static_cast<ItemType>(m_Selected.GetData());
switch (data) {
case ItemType::Process:
m_WindowsView.UpdateListByProcess(m_Processes[m_Selected]);
break;
case ItemType::Thread:
m_WindowsView.UpdateListByThread(m_Threads[m_Selected]);
break;
default:
auto hWnd = (HWND)m_Selected.GetData();
m_SelectedHwnd = hWnd;
if (!::IsWindow(hWnd)) // window is probably destroyed
m_Selected.Delete();
else {
m_WindowsView.UpdateList(hWnd);
}
break;
}
}
LRESULT CProcessesView::OnToggleHiddenWindows(WORD, WORD, HWND, BOOL&) {
m_ShowHiddenWindows = !m_ShowHiddenWindows;
UpdateUI();
InitTree();
return 0;
}
LRESULT CProcessesView::OnToggleEmptyTitleWindows(WORD, WORD, HWND, BOOL&) {
m_ShowNoTitleWindows = !m_ShowNoTitleWindows;
UpdateUI();
InitTree();
return 0;
}
void CProcessesView::UpdateUI() {
auto& ui = GetFrame()->GetUIUpdate();
if (::GetFocus() == m_Tree) {
ui.UISetCheck(ID_VIEW_HIDDENWINDOWS, m_ShowHiddenWindows);
ui.UISetCheck(ID_VIEW_EMPTYTITLEWINDOWS, m_ShowNoTitleWindows);
ui.UIEnable(ID_WINDOW_PROPERTIES, m_SelectedHwnd != nullptr);
}
else {
m_WindowsView.UpdateUI(ui);
}
}
================================================
FILE: WinSpy/ProcessesView.h
================================================
#pragma once
#include "ViewBase.h"
#include "WindowsListView.h"
#include "TreeViewManager.h"
#include "ProcessHelper.h"
class CProcessesView :
public CViewBase<CProcessesView>,
public CTreeViewManager<CProcessesView> {
public:
CProcessesView(IMainFrame* frame) : CViewBase(frame), m_WindowsView(frame) {}
void OnActivate(bool active);
protected:
enum { IDC_TREE = 123 };
BEGIN_MSG_MAP(CProcessesView)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING, OnNodeExpanding)
//NOTIFY_CODE_HANDLER(TVN_DELETEITEM, OnNodeDeleted)
COMMAND_ID_HANDLER(ID_VIEW_HIDDENWINDOWS, OnToggleHiddenWindows)
COMMAND_ID_HANDLER(ID_VIEW_EMPTYTITLEWINDOWS, OnToggleEmptyTitleWindows)
NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnNodeSelected)
COMMAND_ID_HANDLER(ID_WINDOW_SHOW, OnWindowShow)
COMMAND_ID_HANDLER(ID_WINDOW_HIDE, OnWindowHide)
COMMAND_ID_HANDLER(ID_WINDOW_BRINGTOFRONT, OnWindowBringToFront)
COMMAND_ID_HANDLER(ID_WINDOW_MINIMIZE, OnWindowMinimize)
COMMAND_ID_HANDLER(ID_WINDOW_MAXIMIZE, OnWindowMaximize)
COMMAND_ID_HANDLER(ID_STATE_FLASH, OnWindowFlash)
COMMAND_ID_HANDLER(ID_WINDOW_RESTORE, OnWindowRestore)
COMMAND_ID_HANDLER(ID_WINDOW_PROPERTIES, OnWindowProperties)
COMMAND_ID_HANDLER(ID_PROCESS_PROPERTIES, OnProcessProperties)
CHAIN_MSG_MAP(CTreeViewManager<CProcessesView>)
CHAIN_MSG_MAP(CViewBase<CProcessesView>)
if (m_WindowsView) {
CHAIN_MSG_MAP_ALT_MEMBER(m_WindowsView, 1)
}
END_MSG_MAP()
LRESULT OnTreeNodeRightClick(HTREEITEM hItem, CPoint const& pt);
LRESULT OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint const& pt);
private:
enum class ItemType {
Process,
Thread,
Window
};
void InitTree();
void UpdateUI();
CTreeItem AddNode(HWND hWnd, HTREEITEM hParent);
void AddChildWindows(HTREEITEM hParent);
BOOL AddChildNode(HWND hChild);
void ChangeSelection(HTREEITEM hItem);
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnNodeExpanding(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnNodeDeleted(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnNodeSelected(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
LRESULT OnWindowShow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowHide(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowMinimize(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowMaximize(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowRestore(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnToggleHiddenWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnRefresh(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnToggleEmptyTitleWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnToggleChildWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowFlash(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowBringToFront(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnProcessProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
CWindowsListView m_WindowsView;
CSplitterWindow m_Splitter;
CTreeViewCtrlEx m_Tree;
std::unordered_map<HTREEITEM, ProcessInfo> m_Processes;
std::unordered_map<HTREEITEM, DWORD> m_Threads;
std::unordered_map<HWND, HTREEITEM> m_WindowMap;
CTreeItem m_hCurrentNode;
CTreeItem m_Selected;
CWindow m_SelectedHwnd;
int m_TotalWindows, m_TotalVisibleWindows, m_TopLevelWindows;
bool m_ShowHiddenWindows : 1 { true };
bool m_ShowNoTitleWindows : 1 { true };
bool m_ShowChildWindows : 1 { true };
};
================================================
FILE: WinSpy/SecurityHelper.cpp
================================================
#include "pch.h"
#include "SecurityHelper.h"
bool SecurityHelper::IsRunningElevated() {
static bool runningElevated = false;
static bool runningElevatedCheck = false;
if (runningElevatedCheck)
return runningElevated;
runningElevatedCheck = true;
HANDLE hToken;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
return false;
TOKEN_ELEVATION te;
DWORD len;
if (::GetTokenInformation(hToken, TokenElevation, &te, sizeof(te), &len)) {
runningElevated = te.TokenIsElevated ? true : false;
}
::CloseHandle(hToken);
return runningElevated;
}
bool SecurityHelper::RunElevated() {
WCHAR path[MAX_PATH];
::GetModuleFileName(nullptr, path, _countof(path));
return (INT_PTR)::ShellExecute(nullptr, L"runas", path, nullptr, nullptr, SW_SHOWDEFAULT) > 31;
}
bool SecurityHelper::EnablePrivilege(PCWSTR privName, bool enable) {
HANDLE hToken;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
return false;
bool result = false;
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
if (::LookupPrivilegeValue(nullptr, privName,
&tp.Privileges[0].Luid)) {
if (::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp),
nullptr, nullptr))
result = ::GetLastError() == ERROR_SUCCESS;
}
::CloseHandle(hToken);
return result;
}
================================================
FILE: WinSpy/SecurityHelper.h
================================================
#pragma once
struct SecurityHelper abstract final {
static bool IsRunningElevated();
static bool RunElevated();
static bool EnablePrivilege(PCWSTR privName, bool enable = true);
};
================================================
FILE: WinSpy/TreeViewManager.h
================================================
#pragma once
template<typename T>
class CTreeViewManager {
protected:
BEGIN_MSG_MAP(CTreeViewManager)
NOTIFY_CODE_HANDLER(NM_RCLICK, OnRightClick)
NOTIFY_CODE_HANDLER(NM_DBLCLK, OnDoubleClick)
NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnTreeSelectionChanged)
END_MSG_MAP()
LRESULT OnTreeSelectionChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) {
return 0;
}
LRESULT OnRightClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) {
CTreeViewCtrl tv(pnmh->hwndFrom);
CPoint pt;
::GetCursorPos(&pt);
CPoint pt2(pt);
tv.ScreenToClient(&pt2);
auto hItem = tv.HitTest(pt2, nullptr);
if (!hItem)
return 0;
tv.SelectItem(hItem);
auto pT = static_cast<T*>(this);
return pT->OnTreeNodeRightClick(hItem, pt);
}
LRESULT OnDoubleClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) {
CTreeViewCtrl tv(pnmh->hwndFrom);
CPoint pt;
::GetCursorPos(&pt);
CPoint pt2(pt);
tv.ScreenToClient(&pt2);
auto hItem = tv.HitTest(pt2, nullptr);
if (!hItem)
return 0;
auto pT = static_cast<T*>(this);
return pT->OnTreeNodeDoubleClick(hItem, pt);
}
private:
//
// overridables
//
LRESULT OnTreeNodeRightClick(HTREEITEM hItem, CPoint const& pt) {
return 0;
}
LRESULT OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint const& pt) {
return 0;
}
};
================================================
FILE: WinSpy/ViewBase.h
================================================
#pragma once
#include "Interfaces.h"
template<typename T, typename TBase = CFrameWindowImpl<T, CWindow, CControlWinTraits>>
class CViewBase abstract :
public TBase,
public CAutoUpdateUI<T>,
public CIdleHandler {
public:
CViewBase(IMainFrame* frame) : m_pFrame(frame) {}
protected:
BEGIN_MSG_MAP(CViewBase)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(TBVN_PAGEACTIVATED, OnTabActivated)
CHAIN_MSG_MAP(TBase)
END_MSG_MAP()
IMainFrame* GetFrame() {
return m_pFrame;
}
void OnFinalMessage(HWND) override {
delete this;
}
BOOL OnIdle() override {
CAutoUpdateUI<T>::UIUpdateToolBar();
return FALSE;
}
LRESULT OnTabActivated(UINT /*uMsg*/, WPARAM wParam, LPARAM, BOOL& bHandled) {
auto pT = static_cast<T*>(this);
pT->OnActivate(wParam ? true : false);
return 0;
}
void OnActivate(bool activate) {}
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
auto pT = static_cast<T*>(this);
bHandled = FALSE;
if (pT->m_hWndToolBar)
_Module.GetMessageLoop()->RemoveIdleHandler(this);
return 0;
}
HWND CreateAndInitToolBar(const ToolBarButtonInfo* buttons, int count) {
auto pT = static_cast<T*>(this);
CToolBarCtrl tb;
auto hWndToolBar = tb.Create(pT->m_hWnd, pT->rcDefault, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST, 0, ATL_IDW_TOOLBAR);
tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS);
CImageList tbImages;
tbImages.Create(24, 24, ILC_COLOR32 | ILC_COLOR | ILC_MASK, 4, 4);
tb.SetImageList(tbImages);
for (int i = 0; i < count; i++) {
auto& b = buttons[i];
if (b.id == 0)
tb.AddSeparator(0);
else {
int image = b.image == 0 ? I_IMAGENONE : tbImages.AddIcon(AtlLoadIconImage(b.image, 0, 24, 24));
tb.AddButton(b.id, b.style | (b.text ? BTNS_SHOWTEXT : 0), TBSTATE_ENABLED, image, b.text, 0);
}
}
pT->CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
pT->AddSimpleReBarBand(tb);
UIAddToolBar(hWndToolBar);
_Module.GetMessageLoop()->AddIdleHandler(this);
return hWndToolBar;
}
IMainFrame* m_pFrame;
};
================================================
FILE: WinSpy/WinSpy.cpp
================================================
// WinSpy.cpp : main source file for WinSpy.exe
//
#include "pch.h"
#include "resource.h"
#include "MainFrm.h"
#include <ThemeHelper.h>
CAppModule _Module;
int Run(LPCTSTR /*lpstrCmdLine*/ = nullptr, int nCmdShow = SW_SHOWDEFAULT) {
CMessageLoop theLoop;
_Module.AddMessageLoop(&theLoop);
CMainFrame wndMain;
if (wndMain.CreateEx() == nullptr) {
ATLTRACE(_T("Main window creation failed!\n"));
return 0;
}
wndMain.ShowWindow(nCmdShow);
int nRet = theLoop.Run();
_Module.RemoveMessageLoop();
return nRet;
}
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) {
HRESULT hRes = ::CoInitialize(nullptr);
ATLASSERT(SUCCEEDED(hRes));
AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES);
hRes = _Module.Init(nullptr, hInstance);
ATLASSERT(SUCCEEDED(hRes));
ThemeHelper::Init();
int nRet = Run(lpstrCmdLine, nCmdShow);
_Module.Term();
::CoUninitialize();
return nRet;
}
================================================
FILE: WinSpy/WinSpy.h
================================================
// WinSpy.h
================================================
FILE: WinSpy/WinSpy.rc
================================================
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "atlres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""atlres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MAINFRAME MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Run As Administrator...", ID_FILE_RUNASADMINISTRATOR
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
END
POPUP "&View"
BEGIN
MENUITEM "&Refresh", ID_VIEW_REFRESH
MENUITEM SEPARATOR
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
MENUITEM SEPARATOR
MENUITEM "&Windows Tree", ID_VIEW_ALLWINDOWS
MENUITEM "&Processes Tree", ID_VIEW_ALLPROCESSES
MENUITEM "Windows &List", ID_VIEW_WINDOWSLIST
MENUITEM "&Automation Tree", ID_VIEW_AUTOMATIONTREE
MENUITEM SEPARATOR
MENUITEM "&Hidden Windows", ID_VIEW_HIDDENWINDOWS
MENUITEM "EmptyTitle Windows", ID_VIEW_EMPTYTITLEWINDOWS
END
POPUP "&Window"
BEGIN
MENUITEM "&Find...\tCtrl+W", ID_WINDOW_FIND
MENUITEM "&Messages...", ID_WINDOW_MESSAGES
MENUITEM SEPARATOR
MENUITEM "Locate in &Tree", ID_WINDOW_LOCATEINTREE
POPUP "&Action"
BEGIN
MENUITEM "&Show", ID_WINDOW_SHOW
MENUITEM "&Hide", ID_WINDOW_HIDE
MENUITEM "&Highlight", ID_WINDOW_HIGHLIGHT
MENUITEM "&Minimize", ID_WINDOW_MINIMIZE
MENUITEM "Ma&ximize", ID_WINDOW_MAXIMIZE
MENUITEM "&Restore", ID_WINDOW_RESTORE
MENUITEM "&Bring To Front", ID_WINDOW_BRINGTOFRONT
MENUITEM "&Close", ID_STATE_CLOSE
MENUITEM "&Flash", ID_STATE_FLASH
END
MENUITEM SEPARATOR
MENUITEM "&Properties...", ID_WINDOW_PROPERTIES
END
POPUP "&Options"
BEGIN
MENUITEM "&Always On Top", ID_OPTIONS_ALWAYSONTOP
MENUITEM "&Fonts...", ID_OPTIONS_FONTS
END
POPUP "&Tab"
BEGIN
MENUITEM "&Close\tCtrl+F4", ID_WINDOW_CLOSE
MENUITEM "Close &All", ID_WINDOW_CLOSE_ALL
END
POPUP "&Help"
BEGIN
MENUITEM "&About WinSpy...", ID_APP_ABOUT
END
END
IDR_CONTEXT MENU
BEGIN
POPUP "tree"
BEGIN
MENUITEM "&Show", ID_WINDOW_SHOW
MENUITEM "&Hide", ID_WINDOW_HIDE
MENUITEM "&Highlight", ID_WINDOW_HIGHLIGHT
MENUITEM "&Minimize", ID_WINDOW_MINIMIZE
MENUITEM "Ma&ximize", ID_WINDOW_MAXIMIZE
MENUITEM "&Restore", ID_WINDOW_RESTORE
MENUITEM "&Bring To Front", ID_WINDOW_BRINGTOFRONT
MENUITEM "Send to &Back", ID_TREE_SENDTOBACK
MENUITEM "&Close", ID_STATE_CLOSE
MENUITEM "&Flash", ID_STATE_FLASH
MENUITEM "&Messages...", ID_WINDOW_MESSAGES
MENUITEM SEPARATOR
MENUITEM "&Properties...", ID_WINDOW_PROPERTIES
END
POPUP "list"
BEGIN
POPUP "&State"
BEGIN
MENUITEM "&Show", ID_WINDOW_SHOW
MENUITEM "&Hide", ID_WINDOW_HIDE
MENUITEM "&Highlight", ID_WINDOW_HIGHLIGHT
MENUITEM "&Minimize", ID_WINDOW_MINIMIZE
MENUITEM "Ma&ximize", ID_WINDOW_MAXIMIZE
MENUITEM "&Restore", ID_WINDOW_RESTORE
MENUITEM "&Bring To Front", ID_WINDOW_BRINGTOFRONT
MENUITEM "&Close", ID_STATE_CLOSE
MENUITEM "&Flash", ID_STATE_FLASH
END
MENUITEM SEPARATOR
MENUITEM "&Properties...", ID_WINDOW_PROPERTIES
MENUITEM SEPARATOR
MENUITEM "Locate in &Tree", ID_WINDOW_LOCATEINTREE
END
POPUP "process"
BEGIN
MENUITEM "&Terminate", ID_PROCESS_TERMINATE
MENUITEM SEPARATOR
MENUITEM "&Properties...", ID_PROCESS_PROPERTIES
END
POPUP "thread"
BEGIN
MENUITEM "&Properties...", ID_THREAD_PROPERTIES
MENUITEM SEPARATOR
MENUITEM "&Messages...", ID_WINDOW_MESSAGES
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON "res\\WinSpy.ico"
IDI_WINDOW ICON "res\\window.ico"
IDI_WINDOW_HIDDEN ICON "res\\window-hidden.ico"
IDI_WINDOW_DELETE ICON "res\\window_delete.ico"
IDI_WINDOW_NEW ICON "res\\window_new.ico"
IDI_WINDOWS ICON "res\\windows.ico"
IDI_REFRESH ICON "res\\refresh.ico"
IDI_WINDOW_CLOSE ICON "res\\close-window.ico"
IDI_WINDOW_MAXIMIZE ICON "res\\maximize.ico"
IDI_WINDOW_NOTEXT ICON "res\\window-notext.ico"
IDI_WINDOW_MINIMIZE ICON "res\\Minimize.ico"
IDI_WINDOW_SENDTOBACK ICON "res\\WindowSendToBack.ico"
IDI_TARGET ICON "res\\Target.ico"
IDI_PROCESSES ICON "res\\gears.ico"
IDI_WINPROP ICON "res\\window-properties.ico"
IDI_PROCESS_INFO ICON "res\\gear_information.ico"
IDI_MESSAGE ICON "res\\message.ico"
IDI_MESSAGES ICON "res\\messages.ico"
IDI_WINDOWSEARCH ICON "res\\WindowSearch.ico"
IDI_SENDTOFRONT ICON "res\\WindowSendToFront.ico"
IDI_RESTORE ICON "res\\restore.ico"
IDI_AUTOMATION ICON "res\\Automation.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 187, 85
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About WinSpy"
FONT 9, "Segoe UI", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,70,64,48,14
CTEXT "WinSpy v0.3\n\n2020-2024 Pavel Yosifovich",IDC_STATIC,46,14,103,32
ICON IDR_MAINFRAME,IDC_STATIC,6,6,20,20
END
IDD_FINDWINDOW DIALOGEX 0, 0, 333, 146
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Find Window"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Handle:",IDC_STATIC,9,9,26,8
EDITTEXT IDC_HANDLE,41,7,69,14,ES_AUTOHSCROLL
LTEXT "Class:",IDC_STATIC,9,30,20,8
EDITTEXT IDC_CLASSNAME,41,27,285,14,ES_AUTOHSCROLL
LTEXT "Text:",IDC_STATIC,16,50,18,8
EDITTEXT IDC_TEXT,41,48,285,14,ES_AUTOHSCROLL
LTEXT "Drag and drop over a window",IDC_STATIC,12,78,96,8
ICON IDI_TARGET,IDC_TARGET,119,72,20,20,SS_NOTIFY | SS_CENTERIMAGE
PUSHBUTTON "Search",IDC_SEARCH,163,75,50,14
PUSHBUTTON "Cancel",IDCANCEL,174,125,50,14
PUSHBUTTON "OK",IDOK,108,125,50,14
CONTROL "Hide main window while dragging",IDC_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,95,123,10
LTEXT "Thread:",IDC_STATIC,116,9,26,8
EDITTEXT IDC_THREAD,145,7,40,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Process:",IDC_STATIC,195,9,28,8
EDITTEXT IDC_PROCESS,228,7,98,14,ES_AUTOHSCROLL | ES_READONLY
END
IDD_WINPROP DIALOGEX 0, 0, 433, 243
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD | WS_CAPTION | WS_SYSMENU
CAPTION "General"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Handle:",IDC_STATIC,7,9,26,8
EDITTEXT IDC_HANDLE,35,7,69,14,ES_AUTOHSCROLL
LTEXT "Class:",IDC_STATIC,10,30,20,8
EDITTEXT IDC_CLASSNAME,35,27,306,14,ES_AUTOHSCROLL
LTEXT "Text:",IDC_STATIC,12,50,18,8
EDITTEXT IDC_TEXT,35,48,388,14,ES_AUTOHSCROLL
LTEXT "Thread:",IDC_STATIC,116,9,26,8
EDITTEXT IDC_THREAD,145,7,43,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Process:",IDC_STATIC,203,9,28,8
EDITTEXT IDC_PROCESS,239,7,151,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Window Rect:",IDC_STATIC,7,71,46,8
EDITTEXT IDC_RECT,7,82,129,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Client Rect:",IDC_STATIC,155,71,38,8
EDITTEXT IDC_CLIENTRECT,153,81,129,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Style:",IDC_STATIC,16,129,20,8
EDITTEXT IDC_STYLE,42,126,61,14,ES_AUTOHSCROLL | ES_READONLY
LISTBOX IDC_STYLES,7,145,138,94,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
LTEXT "Extended Style:",IDC_STATIC,166,129,52,8
EDITTEXT IDC_STYLEEX,222,126,61,14,ES_AUTOHSCROLL | ES_READONLY
LISTBOX IDC_STYLESEX,150,145,160,93,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
LTEXT "Atom:",IDC_STATIC,361,31,20,8
EDITTEXT IDC_ATOM,385,28,42,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Restore Rect:",IDC_STATIC,298,71,46,8
EDITTEXT IDC_RESTORE_RECT,297,82,129,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Menu / ID:",IDC_STATIC,7,105,35,8
EDITTEXT IDC_MENU,45,102,69,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "User Data:",IDC_STATIC,135,106,36,8
EDITTEXT IDC_USERDATA,178,103,80,14,ES_AUTOHSCROLL | ES_READONLY
LTEXT "Class Style:",IDC_STATIC,320,129,38,8
EDITTEXT IDC_STYLECLASS,364,127,61,14,ES_AUTOHSCROLL | ES_READONLY
LISTBOX IDC_CLASSSTYLE,322,146,109,93,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
END
IDD_PROPWINDOWS DIALOGEX 0, 0, 401, 247
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
CAPTION "Windows"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
GROUPBOX "Parent Window",IDC_STATIC,7,7,387,56
LTEXT "Handle:",IDC_STATIC,15,23,26,8
LTEXT "Class:",IDC_STATIC,118,22,20,8
EDITTEXT IDC_CLASS,148,20,246,14,ES_AUTOHSCROLL | ES_READONLY
CONTROL "<a>SysLink1</a>",IDC_HANDLE,"SysLink",LWS_RIGHT | WS_TABSTOP,45,23,60,10
LTEXT "Text:",IDC_STATIC,15,43,18,8
EDITTEXT IDC_TEXT,39,41,355,14,ES_AUTOHSCROLL | ES_READONLY
GROUPBOX "Next Window",IDC_STATIC,7,66,387,56
LTEXT "Handle:",IDC_STATIC,15,82,26,8
LTEXT "Class:",IDC_STATIC,118,81,20,8
EDITTEXT IDC_CLASS2,148,79,246,14,ES_AUTOHSCROLL | ES_READONLY
CONTROL "<a>SysLink1</a>",IDC_HANDLE2,"SysLink",LWS_RIGHT | WS_TABSTOP,45,82,60,10
LTEXT "Text:",IDC_STATIC,15,102,18,8
EDITTEXT IDC_TEXT2,39,100,355,14,ES_AUTOHSCROLL | ES_READONLY
GROUPBOX "Previous Window",IDC_STATIC,7,126,387,56
LTEXT "Handle:",IDC_STATIC,15,142,26,8
LTEXT "Class:",IDC_STATIC,118,142,20,8
EDITTEXT IDC_CLASS3,148,139,246,14,ES_AUTOHSCROLL | ES_READONLY
CONTROL "<a>SysLink1</a>",IDC_HANDLE3,"SysLink",LWS_RIGHT | WS_TABSTOP,45,142,60,10
LTEXT "Text:",IDC_STATIC,15,162,18,8
EDITTEXT IDC_TEXT3,39,161,355,14,ES_AUTOHSCROLL | ES_READONLY
GROUPBOX "First Child Window",IDC_STATIC,7,184,387,56
LTEXT "Handle:",IDC_STATIC,15,200,26,8
LTEXT "Class:",IDC_STATIC,118,200,20,8
EDITTEXT IDC_CLASS4,148,197,246,14,ES_AUTOHSCROLL | ES_READONLY
CONTROL "<a>SysLink1</a>",IDC_HANDLE4,"SysLink",LWS_RIGHT | WS_TABSTOP,45,200,60,10
LTEXT "Text:",IDC_STATIC,15,220,18,8
EDITTEXT IDC_TEXT4,39,219,355,14,ES_AUTOHSCROLL | ES_READONLY
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 180
TOPMARGIN, 7
BOTTOMMARGIN, 78
END
IDD_FINDWINDOW, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 326
TOPMARGIN, 7
BOTTOMMARGIN, 139
END
IDD_WINPROP, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 426
TOPMARGIN, 7
BOTTOMMARGIN, 236
END
IDD_PROPWINDOWS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 394
TOPMARGIN, 7
BOTTOMMARGIN, 240
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_MAINFRAME ACCELERATORS
BEGIN
"N", ID_FILE_NEW, VIRTKEY, CONTROL
"O", ID_FILE_OPEN, VIRTKEY, CONTROL
"S", ID_FILE_SAVE, VIRTKEY, CONTROL
"P", ID_FILE_PRINT, VIRTKEY, CONTROL
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL
"X", ID_EDIT_CUT, VIRTKEY, CONTROL
"C", ID_EDIT_COPY, VIRTKEY, CONTROL
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL
VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT
VK_F6, ID_NEXT_PANE, VIRTKEY
VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,3,0,0
PRODUCTVERSION 0,3,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Scorpio Software"
VALUE "FileDescription", "WinSpy - UI Windows Properties and Messages"
VALUE "FileVersion", "0.3.0.0"
VALUE "InternalName", "WinSpy"
VALUE "LegalCopyright", "2021-2024 Pavel Yosifovich"
VALUE "OriginalFilename", "WinSpy.exe"
VALUE "ProductName", "WinSpy"
VALUE "ProductVersion", "0.3.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_ABOUTBOX AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_FINDWINDOW AFX_DIALOG_LAYOUT
BEGIN
0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 100, 0,
0, 0, 0, 0,
0, 0, 100, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
50, 100, 0, 0,
50, 100, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 100, 0
END
IDD_WINPROP AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_PROPWINDOWS AFX_DIALOG_LAYOUT
BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDR_MAINFRAME "WinSpy v0.3"
IDS_TITLE "WinSpy"
END
STRINGTABLE
BEGIN
ID_FILE_NEW "Create a new document\nNew"
ID_FILE_OPEN "Open an existing document\nOpen"
ID_FILE_CLOSE "Close the active document\nClose"
ID_FILE_SAVE "Save the active document\nSave"
ID_FILE_SAVE_AS "Save the active document with a new name\nSave As"
ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup"
ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup"
ID_FILE_PRINT "Print the active document\nPrint"
ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview"
END
STRINGTABLE
BEGIN
ID_APP_ABOUT "Display program information, version number and copyright\nAbout"
ID_APP_EXIT "Quit the application; prompts to save documents\nExit"
END
STRINGTABLE
BEGIN
ID_NEXT_PANE "Switch to the next window pane\nNext Pane"
ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane"
END
STRINGTABLE
BEGIN
ID_WINDOW_NEW "Open another window for the active document\nNew Window"
ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons"
ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows"
ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows"
ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows"
ID_WINDOW_SPLIT "Split the active window into panes\nSplit"
END
STRINGTABLE
BEGIN
ID_EDIT_CLEAR "Erase the selection\nErase"
ID_EDIT_CLEAR_ALL "Erase everything\nErase All"
ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy"
ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut"
ID_EDIT_FIND "Find the specified text\nFind"
ID_EDIT_PASTE "Insert Clipboard contents\nPaste"
ID_EDIT_REPEAT "Repeat the last action\nRepeat"
ID_EDIT_REPLACE "Replace specific text with different text\nReplace"
ID_EDIT_SELECT_ALL "Select the entire document\nSelect All"
ID_EDIT_UNDO "Undo the last action\nUndo"
ID_EDIT_REDO "Redo the previously undone action\nRedo"
END
STRINGTABLE
BEGIN
ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar"
ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar"
ID_VIEW_REFRESH "\nRefresh"
END
STRINGTABLE
BEGIN
ATL_IDS_SCSIZE "Change the window size"
ATL_IDS_SCMOVE "Change the window position"
ATL_IDS_SCMINIMIZE "Reduce the window to an icon"
ATL_IDS_SCMAXIMIZE "Enlarge the window to full size"
ATL_IDS_SCNEXTWINDOW "Switch to the next document window"
ATL_IDS_SCPREVWINDOW "Switch to the previous document window"
ATL_IDS_SCCLOSE "Close the active window and prompts to save the documents"
END
STRINGTABLE
BEGIN
ATL_IDS_SCRESTORE "Restore the window to normal size"
ATL_IDS_SCTASKLIST "Activate Task List"
ATL_IDS_MDICHILD "Activate this window"
END
STRINGTABLE
BEGIN
ATL_IDS_IDLEMESSAGE "Ready"
END
STRINGTABLE
BEGIN
ATL_IDS_MRU_FILE "Open this document"
END
STRINGTABLE
BEGIN
ID_WINDOW_CLOSE "\nClose Tab"
ID_WINDOW_CLOSE_ALL "\nClose All Tabs"
ID_VIEW_ALLWINDOWS "\nWindow Tree"
ID_VIEW_ALLPROCESSES "\nProcesses, Threads && Windows"
ID_WINDOW_SHOW "\nShow Window"
ID_WINDOW_HIDE "\nHide Window"
ID_WINDOW_HIGHLIGHT "\nHighlight Window"
END
STRINGTABLE
BEGIN
ID_WINDOW_PROPERTIES "\nWindow Properties"
ID_WINDOW_FIND "\nFind Window"
ID_VIEW_HIDDENWINDOWS "\nHidden Windows"
ID_VIEW_EMPTYTITLEWINDOWS "\nWindows with no Titles"
END
STRINGTABLE
BEGIN
ID_WINDOW_MESSAGES "\nMonitor Messages"
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
================================================
FILE: WinSpy/WinSpy.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseSigned|Win32">
<Configuration>ReleaseSigned</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseSigned|x64">
<Configuration>ReleaseSigned</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{3988E48D-F582-4E0F-B1AF-FC70A4D0B4D7}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\WTL;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\WTL;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\WTL;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\WTL;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\WTL;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\WTL;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<ExceptionHandling>false</ExceptionHandling>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>..\WinSpyHook;..\WTLHelper\WTLHelper</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>WinSpy.h</HeaderFileName>
<InterfaceIdentifierFileName>WinSpy_i.c</InterfaceIdentifierFileName>
<ProxyFileName>WinSpy_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)/WinSpy.tlb</TypeLibraryName>
<DllDataFileName />
</Midl>
<Manifest>
<EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<ExceptionHandling>false</ExceptionHandling>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>..\WinSpyHook;..\WTLHelper\WTLHelper</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>WinSpy.h</HeaderFileName>
<InterfaceIdentifierFileName>WinSpy_i.c</InterfaceIdentifierFileName>
<ProxyFileName>WinSpy_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)/WinSpy.tlb</TypeLibraryName>
<DllDataFileName />
</Midl>
<Manifest>
<EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling>
<DebugInformationFormat />
<PreprocessorDefinitions>WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>..\WinSpyHook;..\WTLHelper\WTLHelper</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>WinSpy.h</HeaderFileName>
<InterfaceIdentifierFileName>WinSpy_i.c</InterfaceIdentifierFileName>
<ProxyFileName>WinSpy_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)/WinSpy.tlb</TypeLibraryName>
<DllDataFileName />
</Midl>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
<Manifest>
<EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling>
<DebugInformationFormat>
</DebugInformationFormat>
<PreprocessorDefinitions>WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>..\WinSpyHook;..\WTLHelper\WTLHelper</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>WinSpy.h</HeaderFileName>
<InterfaceIdentifierFileName>WinSpy_i.c</InterfaceIdentifierFileName>
<ProxyFileName>WinSpy_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)/WinSpy.tlb</TypeLibraryName>
<DllDataFileName>
</DllDataFileName>
</Midl>
<PostBuildEvent>
<Command>signtool sign /i DigiCert /fd sha256 $(TargetPath)</Command>
</PostBuildEvent>
<Manifest>
<EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling>
<DebugInformationFormat />
<PreprocessorDefinitions>_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>..\WinSpyHook;..\WTLHelper\WTLHelper</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>WinSpy.h</HeaderFileName>
<InterfaceIdentifierFileName>WinSpy_i.c</InterfaceIdentifierFileName>
<ProxyFileName>WinSpy_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)/WinSpy.tlb</TypeLibraryName>
<DllDataFileName />
</Midl>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
<Manifest>
<EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling>
<DebugInformationFormat>
</DebugInformationFormat>
<PreprocessorDefinitions>_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>..\WinSpyHook;..\WTLHelper\WTLHelper</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>WinSpy.h</HeaderFileName>
<InterfaceIdentifierFileName>WinSpy_i.c</InterfaceIdentifierFileName>
<ProxyFileName>WinSpy_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)/WinSpy.tlb</TypeLibraryName>
<DllDataFileName>
</DllDataFileName>
</Midl>
<PostBuildEvent>
<Command>signtool sign /a /n Scorpio /t http://timestamp.digicert.com /fd sha256 $(TargetPath)</Command>
</PostBuildEvent>
<Manifest>
<EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AboutDlg.cpp" />
<ClCompile Include="AutomationTreeView.cpp" />
<ClCompile Include="HookHelper.cpp" />
<ClCompile Include="IconHelper.cpp" />
<ClCompile Include="ImageIconCache.cpp" />
<ClCompile Include="MessageDecoder.cpp" />
<ClCompile Include="MessagesView.cpp" />
<ClCompile Include="ProcessesView.cpp" />
<ClCompile Include="SecurityHelper.cpp" />
<ClCompile Include="WindowGeneralPage.cpp" />
<ClCompile Include="WindowsListView.cpp" />
<ClCompile Include="FindWindowDlg.cpp" />
<ClCompile Include="FormatHelper.cpp" />
<ClCompile Include="MainFrm.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ProcessHelper.cpp" />
<ClCompile Include="WindowHelper.cpp" />
<ClCompile Include="WindowsView.cpp" />
<ClCompile Include="WindowWindowsPage.cpp" />
<ClCompile Include="WinSpy.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AboutDlg.h" />
<ClInclude Include="AutomationTreeView.h" />
<ClInclude Include="DialogHelper.h" />
<ClInclude Include="HookHelper.h" />
<ClInclude Include="IconHelper.h" />
<ClInclude Include="ImageIconCache.h" />
<ClInclude Include="MessageDecoder.h" />
<ClInclude Include="MessagesView.h" />
<ClInclude Include="SecurityHelper.h" />
<ClInclude Include="FrameWindowHelper.h" />
<ClInclude Include="WindowGeneralPage.h" />
<ClInclude Include="WindowsListView.h" />
<ClInclude Include="FindWindowDlg.h" />
<ClInclude Include="FormatHelper.h" />
<ClInclude Include="Interfaces.h" />
<ClInclude Include="MainFrm.h" />
<ClInclude Include="ProcessesView.h" />
<ClInclude Include="ProcessHelper.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="TreeViewManager.h" />
<ClInclude Include="ViewBase.h" />
<ClInclude Include="WindowHelper.h" />
<ClInclude Include="WindowsView.h" />
<ClInclude Include="WindowWindowsPage.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WinSpy.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="res\Automation.ico" />
<Image Include="res\close-window.ico" />
<Image Include="res\gears.ico" />
<Image Include="res\gear_information.ico" />
<Image Include="res\maximize.ico" />
<Image Include="res\message.ico" />
<Image Include="res\messages.ico" />
<Image Include="res\Minimize.ico" />
<Image Include="res\refresh.ico" />
<Image Include="res\restore.ico" />
<Image Include="res\Target.ico" />
<Image Include="res\window-close.ico" />
<Image Include="res\window-hidden.ico" />
<Image Include="res\window-notext.ico" />
<Image Include="res\window-properties.ico" />
<Image Include="res\window.ico" />
<Image Include="res\windows.ico" />
<Image Include="res\WindowSearch.ico" />
<Image Include="res\WindowSendToBack.ico" />
<Image Include="res\WindowSendToFront.ico" />
<Image Include="res\window_delete.ico" />
<Image Include="res\window_new.ico" />
<Image Include="res\WinSpy.ico" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WTLHelper\WTLHelper\WTLHelper.vcxproj">
<Project>{ae53419f-a769-4548-8e15-e311904df7df}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
================================================
FILE: WinSpy/WinSpy.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{f871bb5c-f151-4e10-8bbb-10019ddd6a72}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{47fb17d7-d54c-4fc7-85b2-7c653d04b30a}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{9c7daf0d-2916-49f7-872d-30cf5e95725d}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest</Extensions>
</Filter>
<Filter Include="Resource Files\Icons">
<UniqueIdentifier>{ff137a25-faa3-4d88-af38-5c1bc296546b}</UniqueIdentifier>
</Filter>
<Filter Include="Dialogs">
<UniqueIdentifier>{96be1941-f83d-4366-ad55-930da999a2eb}</UniqueIdentifier>
</Filter>
<Filter Include="Views">
<UniqueIdentifier>{9a542756-dfdb-4a47-b231-2b2ae2aef120}</UniqueIdentifier>
</Filter>
<Filter Include="Helpers">
<UniqueIdentifier>{3b473b33-73a4-4bd6-a469-d86318a53f81}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="WinSpy.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MainFrm.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AboutDlg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FindWindowDlg.cpp">
<Filter>Dialogs</Filter>
</ClCompile>
<ClCompile Include="WindowsView.cpp">
<Filter>Views</Filter>
</ClCompile>
<ClCompile Include="ProcessHelper.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="FormatHelper.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="WindowHelper.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="WindowsListView.cpp">
<Filter>Views</Filter>
</ClCompile>
<ClCompile Include="IconHelper.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="ProcessesView.cpp">
<Filter>Views</Filter>
</ClCompile>
<ClCompile Include="ImageIconCache.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="WindowGeneralPage.cpp">
<Filter>Dialogs</Filter>
</ClCompile>
<ClCompile Include="WindowWindowsPage.cpp">
<Filter>Dialogs</Filter>
</ClCompile>
<ClCompile Include="SecurityHelper.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="MessagesView.cpp">
<Filter>Views</Filter>
</ClCompile>
<ClCompile Include="MessageDecoder.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="HookHelper.cpp">
<Filter>Helpers</Filter>
</ClCompile>
<ClCompile Include="AutomationTreeView.cpp">
<Filter>Views</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="MainFrm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AboutDlg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ViewBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Interfaces.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TreeViewManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FindWindowDlg.h">
<Filter>Dialogs</Filter>
</ClInclude>
<ClInclude Include="WindowsView.h">
<Filter>Views</Filter>
</ClInclude>
<ClInclude Include="ProcessesView.h">
<Filter>Views</Filter>
</ClInclude>
<ClInclude Include="WindowHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="ProcessHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Resource Files</Filter>
</ClInclude>
<ClInclude Include="FormatHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="WindowsListView.h">
<Filter>Views</Filter>
</ClInclude>
<ClInclude Include="IconHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="ImageIconCache.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="WindowGeneralPage.h">
<Filter>Dialogs</Filter>
</ClInclude>
<ClInclude Include="DialogHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="WindowWindowsPage.h">
<Filter>Dialogs</Filter>
</ClInclude>
<ClInclude Include="SecurityHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="MessagesView.h">
<Filter>Views</Filter>
</ClInclude>
<ClInclude Include="FrameWindowHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="MessageDecoder.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="HookHelper.h">
<Filter>Helpers</Filter>
</ClInclude>
<ClInclude Include="AutomationTreeView.h">
<Filter>Views</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WinSpy.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="res\window.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\window-hidden.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\WinSpy.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\window_delete.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\window_new.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\windows.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\refresh.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\window-close.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\window-notext.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\WindowSendToBack.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\Minimize.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\maximize.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\close-window.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\Target.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\window-properties.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\gears.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\gear_information.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\message.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\messages.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\WindowSearch.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\WindowSendToFront.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\restore.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
<Image Include="res\Automation.ico">
<Filter>Resource Files\Icons</Filter>
</Image>
</ItemGroup>
</Project>
================================================
FILE: WinSpy/WindowGeneralPage.cpp
================================================
#include "pch.h"
#include "resource.h"
#include "WindowGeneralPage.h"
#include "FormatHelper.h"
#include "ProcessHelper.h"
#include "WindowHelper.h"
void CWindowGeneralPage::UpdateData() {
WINDOWINFO wi{ sizeof(wi) };
::GetWindowInfo(m_Win, &wi);
GetParent().SetIcon(WindowHelper::GetWindowIcon(m_Win));
SetDlgItemText(IDC_RECT, FormatHelper::RectToString(wi.rcWindow));
SetDlgItemText(IDC_CLIENTRECT, FormatHelper::RectToString(wi.rcClient));
DWORD pid;
auto tid = ::GetWindowThreadProcessId(m_Win, &pid);
SetDlgItemInt(IDC_THREAD, tid, FALSE);
CString text;
text.Format(L"0x%zX", DWORD_PTR(m_Win.m_hWnd));
SetDlgItemText(IDC_HANDLE, text);
if (tid) {
text.Format(L"%s (%u)", (PCWSTR)ProcessHelper::GetProcessImageName(pid), pid);
SetDlgItemText(IDC_PROCESS, text);
}
WINDOWPLACEMENT wp{ sizeof(wp) };
m_Win.GetWindowPlacement(&wp);
SetDlgItemText(IDC_RESTORE_RECT, FormatHelper::RectToString(wp.rcNormalPosition));
m_Win.GetWindowText(text);
SetDlgItemText(IDC_TEXT, text);
text.Format(L"0x%04X\n", wi.atomWindowType);
SetDlgItemText(IDC_ATOM, text);
text.Format(L"0x%08X\n", wi.dwStyle);
SetDlgItemText(IDC_STYLE, text);
text.Format(L"0x%08X\n", wi.dwExStyle);
SetDlgItemText(IDC_STYLEEX, text);
text.Format(L"0x%zX", m_Win.GetMenu() ? (ULONG_PTR)m_Win.GetMenu() : WindowHelper::GetID(m_Win));
SetDlgItemText(IDC_MENU, text);
text.Format(L"0x%zX", m_Win.GetWindowLongPtr(GWLP_USERDATA));
SetDlgItemText(IDC_USERDATA, text);
WCHAR className[128];
if (::GetClassName(m_Win, className, _countof(className)))
SetDlgItemText(IDC_CLASSNAME, className);
auto clsStyle = (DWORD)::GetClassLongPtr(m_Win, GCL_STYLE);
text.Format(L"0x%08X", clsStyle);
SetDlgItemText(IDC_STYLECLASS, text);
FillStyleList(wi.dwStyle, WindowHelper::GetWindowStyleArray(), IDC_STYLES, L"", L"WS_OVERLAPPED");
FillSpecificControlStyles();
FillStyleList(wi.dwExStyle, WindowHelper::GetWindowStyleExArray(), IDC_STYLESEX, L"", L"WS_EX_LEFT");
FillStyleList(clsStyle, WindowHelper::GetClassStyleArray(), IDC_CLASSSTYLE, L"", nullptr);
}
void CWindowGeneralPage::FillStyleList(DWORD style, std::pair<StyleItem const*, int> styles, UINT id, PCWSTR prefix, PCWSTR defaultStyle, bool clear) {
auto const [items, count] = styles;
CListBox lb(GetDlgItem(id));
ATLASSERT(lb);
if(clear)
lb.ResetContent();
CString text;
for (int i = 0; i < count; i++) {
if ((style & items[i].Mask) == items[i].Value) {
text.Format(L"%s%s (0x%X)", prefix, (PCWSTR)items[i].Text, items[i].Value);
lb.AddString(text);
}
}
if (style == 0 && defaultStyle)
lb.AddString(CString(defaultStyle) + L" (0)");
}
void CWindowGeneralPage::FillSpecificControlStyles() {
WCHAR name[64];
if (!::GetClassName(m_Win, name, _countof(name)))
return;
auto style = m_Win.GetStyle() & 0xffff;
const CString ATLPrefix = L"ATL:";
static const struct {
PCWSTR className;
std::pair<StyleItem const*, int> items;
PCWSTR def = L"";
} controls[] = {
{ WC_LISTVIEW, WindowHelper::GetListViewStyleArray(), L"LVS_ALIGNTOP" },
{ WC_TREEVIEW, WindowHelper::GetTreeViewStyleArray() },
{ WC_TABCONTROL, WindowHelper::GetTabCtrlStyleArray(), L"TCS_TABS" },
{ WC_LISTBOX, WindowHelper::GetListBoxStyleArray() },
{ WC_COMBOBOX, WindowHelper::GetComboBoxStyleArray() },
{ WC_EDIT, WindowHelper::GetEditStyleArray(), L"ES_LEFT" },
{ WC_BUTTON, WindowHelper::GetButtonStyleArray(), L"BS_TEXT" },
{ WC_HEADER, WindowHelper::GetHeaderStyleArray(), L"HDS_HORZ" },
{ WC_STATIC, WindowHelper::GetStaticStyleArray(), L"SS_LEFT" },
{ TOOLTIPS_CLASS, WindowHelper::GetToolTipStyleArray() },
{ STATUSCLASSNAME, WindowHelper::GetStatusBarStyleArray() },
{ TOOLBARCLASSNAME, WindowHelper::GetToolBarStyleArray() },
{ REBARCLASSNAME, WindowHelper::GetRebarStyleArray() },
{ WC_SCROLLBAR, WindowHelper::GetScrollBarStyleArray(), L"SBS_HORZ" },
};
for (auto& item : controls) {
if (_wcsicmp(name, item.className) == 0 || _wcsicmp(name, ATLPrefix + item.className) == 0) {
FillStyleList(style, item.items, IDC_STYLES, L"", item.def, false);
break;
}
}
}
LRESULT CWindowGeneralPage::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
UpdateData();
return 0;
}
LRESULT CWindowGeneralPage::OnUpdate(UINT, WPARAM, LPARAM lp, BOOL&) {
ATLASSERT(lp);
m_Win.Detach();
m_Win.Attach(reinterpret_cast<HWND>(lp));
UpdateData();
return 0;
}
================================================
FILE: WinSpy/WindowGeneralPage.h
================================================
#pragma once
#include "DialogHelper.h"
struct StyleItem;
class CWindowGeneralPage :
public CDialogHelper<CWindowGeneralPage>,
public CPropertyPageImpl<CWindowGeneralPage> {
public:
enum { IDD = IDD_WINPROP };
const UINT WM_UPDATE = WM_USER + 300;
CWindowGeneralPage(HWND hWnd) : m_Win(hWnd) {
m_psp.dwFlags |= PSP_USEICONID;
m_psp.pszIcon = MAKEINTRESOURCE(IDI_WINPROP);
}
void UpdateData();
protected:
BEGIN_MSG_MAP(CWindowGeneralPage)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_UPDATE, OnUpdate)
END_MSG_MAP()
private:
void FillStyleList(DWORD style, std::pair<StyleItem const*, int> styles, UINT id, PCWSTR prefix, PCWSTR defaultStyle, bool clear = true);
void FillSpecificControlStyles();
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnUpdate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
CWindow m_Win;
};
================================================
FILE: WinSpy/WindowHelper.cpp
================================================
#include "pch.h"
#include "resource.h"
#include "WindowHelper.h"
#include "ProcessHelper.h"
#include "FormatHelper.h"
#include "WindowGeneralPage.h"
#include "WindowWindowsPage.h"
#define CASE_STR(x) case x: return L#x
#define PAIR_STR(x) { x, L#x }
#define PAIR_STR2(x, mask) { x, L#x, mask }
CString WindowHelper::WindowStyleToString(HWND hWnd) {
auto style = CWindow(hWnd).GetStyle();
CString text;
auto const [styles, count] = GetWindowStyleArray();
for (int i = 0; i < count; i++) {
auto& item = styles[i];
if ((style & item.Value) == item.Value)
text += CString(item.Text) += L", ";
}
if (text.IsEmpty())
text = L"OVERLAPPED, ";
return L"(WS_) " + text.Left(text.GetLength() - 2);
}
CString WindowHelper::ClassStyleToString(HWND hWnd) {
auto style = ::GetClassLongPtr(hWnd, GCL_STYLE);
CString text;
auto const [styles, count] = GetWindowStyleArray();
for (int i = 0; i < count; i++) {
auto& item = styles[i];
if ((style & item.Value) == item.Value)
text += CString(item.Text) += L", ";
}
if (text.IsEmpty())
return L"";
return L"(CS_) " + text.Left(text.GetLength() - 2);
}
CString WindowHelper::WindowExtendedStyleToString(HWND hWnd) {
auto style = CWindow(hWnd).GetExStyle();
CString text;
auto const [styles, count] = GetWindowStyleArray();
for (int i = 0; i < count; i++) {
auto& item = styles[i];
if ((style & item.Value) == item.Value)
text += CString(item.Text) += L", ";
}
if (text.IsEmpty())
text = L"LEFT, RIGHTSCROLLBAR, ";
return L"(WS_EX_) " + text.Left(text.GetLength() - 2);
}
CString WindowHelper::WindowRectToString(HWND hWnd) {
CWindow win(hWnd);
CRect rc;
win.GetWindowRect(&rc);
return FormatHelper::RectToString(rc);
}
CString WindowHelper::GetWindowClassName(HWND hWnd) {
WCHAR name[128];
::GetClassName(hWnd, name, _countof(name));
return name;
}
CString WindowHelper::GetWindowText(HWND hWnd) {
CString text;
CWindow(hWnd).GetWindowText(text);
return text;
}
HICON WindowHelper::GetWindowOrProcessIcon(HWND hWnd) {
auto hIcon = GetWindowIcon(hWnd);
if (!hIcon) {
DWORD pid = 0;
::GetWindowThreadProcessId(hWnd, &pid);
if (pid) {
::ExtractIconEx(ProcessHelper::GetProcessImageName(pid, true), 0, nullptr, &hIcon, 1);
}
}
return hIcon;
}
bool WindowHelper::Flash(HWND hWnd) {
FLASHWINFO info = { sizeof(info) };
info.dwFlags = FLASHW_CAPTION;
info.uCount = 3;
info.hwnd = hWnd;
return ::FlashWindowEx(&info);
}
void WindowHelper::HighlightBorder(HWND hWnd, bool highlight) {
CRect rc;
::GetWindowRect(hWnd, &rc);
rc.OffsetRect(-rc.left, -rc.top);
CRgn rgn1;
rc.InflateRect(2, 2);
rgn1.CreateRectRgnIndirect(&rc);
rc.DeflateRect(5, 5);
CRgn rgn2;
rgn2.CreateRectRgnIndirect(&rc);
CRgn rgn;
rgn.CreateRectRgn(0, 0, 1, 1);
rgn.CombineRgn(rgn1, rgn2, RGN_DIFF);
if (!highlight) {
::RedrawWindow(hWnd, nullptr, rgn, RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME);
return;
}
CWindowDC dc(hWnd);
CBrush b;
b.CreateSolidBrush(RGB(255, 0, 0));
dc.FillRgn(rgn, b);
}
HICON WindowHelper::GetWindowIcon(HWND hWnd) {
HICON hIcon{ nullptr };
::SendMessageTimeout(hWnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG | SMTO_ERRORONEXIT, 100, (DWORD_PTR*)&hIcon);
if (!hIcon) {
hIcon = (HICON)::GetClassLongPtr(hWnd, GCLP_HICONSM);
}
return hIcon;
}
CString WindowHelper::GetWindowClassAndTitle(HWND hWnd) {
if (hWnd == nullptr || !::IsWindow(hWnd))
return L"";
WCHAR className[64];
CString text;
if (::GetClassName(hWnd, className, _countof(className)))
text.Format(L"[%s]", className);
CString title;
CWindow(hWnd).GetWindowText(title);
if (!title.IsEmpty())
text.Format(L"%s (%s)", (PCWSTR)text, (PCWSTR)title);
return text;
}
std::unordered_map<HWND, int>& WindowHelper::GetIconMap() {
static std::unordered_map<HWND, int> s_IconMap;
return s_IconMap;
}
CImageList& WindowHelper::GetImageList() {
static CImageList images;
if (!images) {
images.Create(16, 16, ILC_COLOR32, 64, 16);
images.AddIcon(AtlLoadIconImage(IDI_WINDOW, 0, 16, 16));
}
return images;
}
WindowItem WindowHelper::GetWindowInfo(HWND hWnd) {
WindowItem wi;
wi.hWnd = hWnd;
wi.ThreadId = ::GetWindowThreadProcessId(hWnd, &wi.ProcessId);
wi.ProcessName = ProcessHelper::GetProcessImageName(wi.ProcessId);
return wi;
}
bool WindowHelper::ThreadHasWindows(DWORD tid) {
bool hasWindows = false;
::EnumThreadWindows(tid, [](auto, auto param) {
*reinterpret_cast<bool*>(param) = true;
return FALSE;
}, reinterpret_cast<LPARAM>(&hasWindows));
return hasWindows;
}
int WindowHelper::ShowWindowProperties(HWND hWnd) {
CString text;
text.Format(L"Window 0x%X Properties", PtrToUlong(hWnd));
CPropertySheet sheet((PCWSTR)text);
sheet.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP;
CWindowGeneralPage general(hWnd);
CWindowWindowsPage windows(hWnd);
sheet.AddPage(general);
sheet.AddPage(windows);
sheet.DoModal();
return 0;
}
std::pair<StyleItem const*, int> WindowHelper::GetWindowStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(WS_POPUP),
PAIR_STR(WS_CHILD),
PAIR_STR(WS_MINIMIZE),
PAIR_STR(WS_VISIBLE),
PAIR_STR(WS_DISABLED),
PAIR_STR(WS_CLIPSIBLINGS),
PAIR_STR(WS_CLIPCHILDREN),
PAIR_STR(WS_MAXIMIZE),
PAIR_STR(WS_BORDER),
PAIR_STR(WS_DLGFRAME),
PAIR_STR(WS_VSCROLL),
PAIR_STR(WS_HSCROLL),
PAIR_STR(WS_SYSMENU),
PAIR_STR(WS_THICKFRAME),
PAIR_STR(WS_MINIMIZEBOX),
PAIR_STR(WS_MAXIMIZEBOX),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetListViewStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(LVS_ALIGNLEFT),
PAIR_STR(LVS_AUTOARRANGE),
PAIR_STR(LVS_EDITLABELS),
PAIR_STR(LVS_ICON),
PAIR_STR(LVS_LIST),
PAIR_STR(LVS_NOCOLUMNHEADER),
PAIR_STR(LVS_NOLABELWRAP),
PAIR_STR(LVS_SINGLESEL),
PAIR_STR(LVS_REPORT),
PAIR_STR(LVS_SMALLICON),
PAIR_STR(LVS_SORTASCENDING),
PAIR_STR(LVS_SORTDESCENDING),
PAIR_STR(LVS_SHOWSELALWAYS),
PAIR_STR(LVS_SHAREIMAGELISTS),
PAIR_STR(LVS_OWNERDATA),
PAIR_STR(LVS_OWNERDRAWFIXED),
PAIR_STR(LVS_NOSCROLL),
PAIR_STR(LVS_NOSORTHEADER),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetTreeViewStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(TVS_CHECKBOXES),
PAIR_STR(TVS_DISABLEDRAGDROP),
PAIR_STR(TVS_EDITLABELS),
PAIR_STR(TVS_FULLROWSELECT),
PAIR_STR(TVS_HASBUTTONS),
PAIR_STR(TVS_HASLINES),
PAIR_STR(TVS_LINESATROOT),
PAIR_STR(TVS_NOHSCROLL),
PAIR_STR(TVS_INFOTIP),
PAIR_STR(TVS_NONEVENHEIGHT),
PAIR_STR(TVS_NOTOOLTIPS),
PAIR_STR(TVS_RTLREADING),
PAIR_STR(TVS_SHOWSELALWAYS),
PAIR_STR(TVS_SINGLEEXPAND),
PAIR_STR(TVS_TRACKSELECT),
PAIR_STR(TVS_NOSCROLL),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetTabCtrlStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(TCS_BOTTOM),
PAIR_STR(TCS_BUTTONS),
PAIR_STR(TCS_FIXEDWIDTH),
PAIR_STR(TCS_FLATBUTTONS),
PAIR_STR(TCS_FOCUSNEVER),
PAIR_STR(TCS_FOCUSONBUTTONDOWN),
PAIR_STR(TCS_FORCEICONLEFT),
PAIR_STR(TCS_FORCELABELLEFT),
PAIR_STR(TCS_HOTTRACK),
PAIR_STR(TCS_MULTILINE),
PAIR_STR(TCS_MULTISELECT),
PAIR_STR(TCS_OWNERDRAWFIXED),
PAIR_STR(TCS_RAGGEDRIGHT),
PAIR_STR(TCS_RIGHT),
PAIR_STR(TCS_RIGHTJUSTIFY),
PAIR_STR(TCS_SCROLLOPPOSITE),
PAIR_STR(TCS_SINGLELINE),
PAIR_STR(TCS_TOOLTIPS),
PAIR_STR(TCS_VERTICAL),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetWindowStyleExArray() {
static const StyleItem styles[] = {
PAIR_STR(WS_EX_DLGMODALFRAME),
PAIR_STR(WS_EX_NOPARENTNOTIFY),
PAIR_STR(WS_EX_TOPMOST),
PAIR_STR(WS_EX_ACCEPTFILES),
PAIR_STR(WS_EX_TRANSPARENT),
PAIR_STR(WS_EX_TOOLWINDOW),
PAIR_STR(WS_EX_WINDOWEDGE),
PAIR_STR(WS_EX_CLIENTEDGE),
PAIR_STR(WS_EX_CONTEXTHELP),
PAIR_STR(WS_EX_RIGHT),
PAIR_STR(WS_EX_RTLREADING),
PAIR_STR(WS_EX_LEFTSCROLLBAR),
PAIR_STR(WS_EX_CONTROLPARENT),
PAIR_STR(WS_EX_STATICEDGE),
PAIR_STR(WS_EX_APPWINDOW),
PAIR_STR(WS_EX_LAYERED),
PAIR_STR(WS_EX_NOINHERITLAYOUT),
PAIR_STR(WS_EX_NOREDIRECTIONBITMAP),
PAIR_STR(WS_EX_LAYOUTRTL),
PAIR_STR(WS_EX_COMPOSITED),
PAIR_STR(WS_EX_NOACTIVATE),
{ 0x8000, L"WS_EX_FEEDBACK" },
{ 0x80000000, L"WS_EX_ANSICREATOR" },
{ 0x800000, L"WS_EX_NOPADDEDBORDER" },
{ 0x2, L"WS_EX_DRAGOBJECT" },
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetClassStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(CS_HREDRAW),
PAIR_STR(CS_VREDRAW),
PAIR_STR(CS_DBLCLKS),
PAIR_STR(CS_OWNDC),
PAIR_STR(CS_CLASSDC),
PAIR_STR(CS_PARENTDC),
PAIR_STR(CS_SAVEBITS),
PAIR_STR(CS_GLOBALCLASS),
PAIR_STR(CS_BYTEALIGNCLIENT),
PAIR_STR(CS_BYTEALIGNWINDOW),
PAIR_STR(CS_IME),
PAIR_STR(CS_NOCLOSE),
PAIR_STR(CS_DROPSHADOW),
{ 0x8000, L"CS_SYSTEM" },
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetEditStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(ES_AUTOHSCROLL),
PAIR_STR(ES_AUTOVSCROLL),
PAIR_STR(ES_READONLY),
PAIR_STR(ES_CENTER),
PAIR_STR(ES_RIGHT),
PAIR_STR(ES_NOHIDESEL),
PAIR_STR(ES_LOWERCASE),
PAIR_STR(ES_UPPERCASE),
PAIR_STR(ES_WANTRETURN),
PAIR_STR(ES_MULTILINE),
PAIR_STR(ES_PASSWORD),
PAIR_STR(ES_NUMBER),
PAIR_STR(ES_OEMCONVERT),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetToolTipStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(TTS_ALWAYSTIP),
PAIR_STR(TTS_BALLOON),
PAIR_STR(TTS_CLOSE),
PAIR_STR(TTS_NOANIMATE),
PAIR_STR(TTS_NOFADE),
PAIR_STR(TTS_NOPREFIX),
PAIR_STR(TTS_USEVISUALSTYLE),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetScrollBarStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(SBS_VERT),
PAIR_STR(SBS_SIZEBOX),
PAIR_STR(SBS_SIZEGRIP),
PAIR_STR(SBS_RIGHTALIGN),
PAIR_STR(SBS_BOTTOMALIGN),
PAIR_STR(SBS_TOPALIGN),
PAIR_STR(SBS_LEFTALIGN),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetStatusBarStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(SBARS_SIZEGRIP),
PAIR_STR(SBARS_TOOLTIPS),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetToolBarStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(TBSTYLE_ALTDRAG),
PAIR_STR(TBSTYLE_FLAT),
PAIR_STR(TBSTYLE_LIST),
PAIR_STR(TBSTYLE_WRAPABLE),
PAIR_STR(TBSTYLE_CUSTOMERASE),
PAIR_STR(TBSTYLE_REGISTERDROP),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetRebarStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(RBS_AUTOSIZE),
PAIR_STR(RBS_BANDBORDERS),
PAIR_STR(RBS_DBLCLKTOGGLE),
PAIR_STR(RBS_FIXEDORDER),
PAIR_STR(RBS_VERTICALGRIPPER),
PAIR_STR(RBS_REGISTERDROP),
PAIR_STR(RBS_VARHEIGHT),
PAIR_STR(RBS_TOOLTIPS),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetStaticStyleArray() {
static const StyleItem styles[] = {
PAIR_STR2(SS_RIGHT, SS_TYPEMASK),
PAIR_STR2(SS_BLACKFRAME, SS_TYPEMASK),
PAIR_STR2(SS_GRAYFRAME, SS_TYPEMASK),
PAIR_STR2(SS_SIMPLE, SS_TYPEMASK),
PAIR_STR2(SS_GRAYRECT, SS_TYPEMASK),
PAIR_STR2(SS_BLACKRECT, SS_TYPEMASK),
PAIR_STR2(SS_ICON, SS_TYPEMASK),
PAIR_STR2(SS_BITMAP, SS_TYPEMASK),
PAIR_STR2(SS_OWNERDRAW, SS_TYPEMASK),
PAIR_STR2(SS_ENHMETAFILE, SS_TYPEMASK),
PAIR_STR2(SS_ETCHEDFRAME, SS_TYPEMASK),
PAIR_STR2(SS_ETCHEDHORZ, SS_TYPEMASK),
PAIR_STR2(SS_ETCHEDVERT, SS_TYPEMASK),
PAIR_STR2(SS_WHITEFRAME, SS_TYPEMASK),
PAIR_STR2(SS_LEFTNOWORDWRAP, SS_TYPEMASK),
PAIR_STR2(SS_CENTER, SS_TYPEMASK),
PAIR_STR(SS_NOPREFIX),
PAIR_STR(SS_NOTIFY),
PAIR_STR(SS_CENTERIMAGE),
PAIR_STR(SS_SUNKEN),
PAIR_STR(SS_EDITCONTROL),
PAIR_STR(SS_RIGHTJUST),
PAIR_STR(SS_REALSIZEIMAGE),
PAIR_STR2(SS_PATHELLIPSIS, SS_ELLIPSISMASK),
PAIR_STR2(SS_WORDELLIPSIS, SS_ELLIPSISMASK),
PAIR_STR2(SS_ENDELLIPSIS, SS_ELLIPSISMASK),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetHeaderStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(HDS_BUTTONS),
PAIR_STR(HDS_CHECKBOXES),
PAIR_STR(HDS_DRAGDROP),
PAIR_STR(HDS_FILTERBAR),
PAIR_STR(HDS_FLAT),
PAIR_STR(HDS_FULLDRAG),
PAIR_STR(HDS_HIDDEN),
PAIR_STR(HDS_HOTTRACK),
PAIR_STR(HDS_NOSIZING),
PAIR_STR(HDS_OVERFLOW),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetButtonStyleArray() {
static const StyleItem styles[] = {
PAIR_STR2(BS_AUTO3STATE, BS_TYPEMASK),
PAIR_STR2(BS_AUTOCHECKBOX, BS_TYPEMASK),
PAIR_STR2(BS_AUTORADIOBUTTON, BS_TYPEMASK),
PAIR_STR2(BS_GROUPBOX, BS_TYPEMASK),
PAIR_STR2(BS_OWNERDRAW, BS_TYPEMASK),
PAIR_STR2(BS_PUSHBOX, BS_TYPEMASK),
PAIR_STR2(BS_CHECKBOX, BS_TYPEMASK),
PAIR_STR2(BS_DEFPUSHBUTTON, BS_TYPEMASK),
PAIR_STR2(BS_DEFSPLITBUTTON, BS_TYPEMASK),
PAIR_STR(BS_CENTER),
PAIR_STR(BS_RIGHT),
PAIR_STR(BS_BITMAP),
PAIR_STR(BS_BOTTOM),
PAIR_STR(BS_COMMANDLINK),
PAIR_STR(BS_FLAT),
PAIR_STR(BS_NOTIFY),
PAIR_STR(BS_MULTILINE),
PAIR_STR(BS_TOP),
PAIR_STR(BS_FLAT),
PAIR_STR(BS_LEFTTEXT),
PAIR_STR2(BS_USERBUTTON, BS_TYPEMASK),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetListBoxStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(LBS_COMBOBOX),
PAIR_STR(LBS_NOSEL),
PAIR_STR(LBS_SORT),
PAIR_STR(LBS_NOTIFY),
PAIR_STR(LBS_NOREDRAW),
PAIR_STR(LBS_MULTICOLUMN),
PAIR_STR(LBS_MULTIPLESEL),
PAIR_STR(LBS_HASSTRINGS),
PAIR_STR(LBS_USETABSTOPS),
PAIR_STR(LBS_NOINTEGRALHEIGHT),
PAIR_STR(LBS_OWNERDRAWFIXED),
PAIR_STR(LBS_OWNERDRAWVARIABLE),
PAIR_STR(LBS_WANTKEYBOARDINPUT),
PAIR_STR(LBS_EXTENDEDSEL),
PAIR_STR(LBS_DISABLENOSCROLL),
};
return std::make_pair(styles, (int)_countof(styles));
}
std::pair<StyleItem const*, int> WindowHelper::GetComboBoxStyleArray() {
static const StyleItem styles[] = {
PAIR_STR(CBS_AUTOHSCROLL),
PAIR_STR(CBS_SIMPLE),
PAIR_STR(CBS_SORT),
PAIR_STR(CBS_DROPDOWN),
PAIR_STR(CBS_DROPDOWNLIST),
PAIR_STR(CBS_HASSTRINGS),
PAIR_STR(CBS_HASSTRINGS),
PAIR_STR(CBS_UPPERCASE),
PAIR_STR(CBS_LOWERCASE),
PAIR_STR(CBS_OWNERDRAWFIXED),
PAIR_STR(CBS_OWNERDRAWVARIABLE),
};
return std::make_pair(styles, (int)_countof(styles));
}
CString WindowHelper::WindowMessageToString(DWORD msg) {
switch (msg) {
CASE_STR(WM_NULL);
CASE_STR(WM_CREATE);
CASE_STR(WM_DESTROY);
CASE_STR(WM_MOVE);
CASE_STR(WM_SIZE);
CASE_STR(WM_ACTIVATE);
CASE_STR(WM_SETFOCUS);
CASE_STR(WM_KILLFOCUS);
CASE_STR(WM_ENABLE);
CASE_STR(WM_SETREDRAW);
CASE_STR(WM_SETTEXT);
CASE_STR(WM_GETTEXT);
CASE_STR(WM_GETTEXTLENGTH);
CASE_STR(WM_PAINT);
CASE_STR(WM_CLOSE);
CASE_STR(WM_QUERYENDSESSION);
CASE_STR(WM_QUIT);
CASE_STR(WM_QUERYOPEN);
CASE_STR(WM_ERASEBKGND);
CASE_STR(WM_SYSCOLORCHANGE);
CASE_STR(WM_ENDSESSION);
CASE_STR(WM_SHOWWINDOW);
CASE_STR(WM_SETTINGCHANGE);
CASE_STR(WM_DEVMODECHANGE);
CASE_STR(WM_ACTIVATEAPP);
CASE_STR(WM_FONTCHANGE);
CASE_STR(WM_TIMECHANGE);
CASE_STR(WM_CANCELMODE);
CASE_STR(WM_SETCURSOR);
CASE_STR(WM_MOUSEACTIVATE);
CASE_STR(WM_CHILDACTIVATE);
CASE_STR(WM_QUEUESYNC);
CASE_STR(WM_GETMINMAXINFO);
CASE_STR(WM_PAINTICON);
CASE_STR(WM_ICONERASEBKGND);
CASE_STR(WM_NEXTDLGCTL);
CASE_STR(WM_SPOOLERSTATUS);
CASE_STR(WM_DRAWITEM);
CASE_STR(WM_MEASUREITEM);
CASE_STR(WM_DELETEITEM);
CASE_STR(WM_VKEYTOITEM);
CASE_STR(WM_CHARTOITEM);
CASE_STR(WM_SETFONT);
CASE_STR(WM_GETFONT);
CASE_STR(WM_SETHOTKEY);
CASE_STR(WM_GETHOTKEY);
CASE_STR(WM_QUERYDRAGICON);
CASE_STR(WM_COMPAREITEM);
CASE_STR(WM_GETOBJECT);
CASE_STR(WM_COMPACTING);
CASE_STR(WM_COMMNOTIFY);
CASE_STR(WM_WINDOWPOSCHANGING);
CASE_STR(WM_WINDOWPOSCHANGED);
CASE_STR(WM_POWER);
CASE_STR(WM_COPYDATA);
CASE_STR(WM_CANCELJOURNAL);
CASE_STR(WM_NOTIFY);
CASE_STR(WM_INPUTLANGCHANGEREQUEST);
CASE_STR(WM_INPUTLANGCHANGE);
CASE_STR(WM_TCARD);
CASE_STR(WM_HELP);
CASE_STR(WM_USERCHANGED);
CASE_STR(WM_NOTIFYFORMAT);
CASE_STR(WM_CONTEXTMENU);
CASE_STR(WM_STYLECHANGING);
CASE_STR(WM_STYLECHANGED);
CASE_STR(WM_DISPLAYCHANGE);
CASE_STR(WM_GETICON);
CASE_STR(WM_SETICON);
CASE_STR(WM_NCCREATE);
CASE_STR(WM_NCDESTROY);
CASE_STR(WM_NCCALCSIZE);
CASE_STR(WM_NCHITTEST);
CASE_STR(WM_NCPAINT);
CASE_STR(WM_NCACTIVATE);
CASE_STR(WM_GETDLGCODE);
CASE_STR(WM_SYNCPAINT);
CASE_STR(WM_NCMOUSEMOVE);
CASE_STR(WM_NCLBUTTONDOWN);
CASE_STR(WM_NCLBUTTONUP);
CASE_STR(WM_NCLBUTTONDBLCLK);
CASE_STR(WM_NCRBUTTONDOWN);
CASE_STR(WM_NCRBUTTONUP);
CASE_STR(WM_NCRBUTTONDBLCLK);
CASE_STR(WM_NCMBUTTONDOWN);
CASE_STR(WM_NCMBUTTONUP);
CASE_STR(WM_NCMBUTTONDBLCLK);
CASE_STR(WM_NCXBUTTONDOWN);
CASE_STR(WM_NCXBUTTONUP);
CASE_STR(WM_NCXBUTTONDBLCLK);
CASE_STR(WM_INPUT);
CASE_STR(WM_KEYDOWN);
CASE_STR(WM_KEYUP);
CASE_STR(WM_CHAR);
CASE_STR(WM_DEADCHAR);
CASE_STR(WM_SYSKEYDOWN);
CASE_STR(WM_SYSKEYUP);
CASE_STR(WM_SYSCHAR);
CASE_STR(WM_SYSDEADCHAR);
CASE_STR(WM_KEYLAST);
CASE_STR(WM_IME_STARTCOMPOSITION);
CASE_STR(WM_IME_ENDCOMPOSITION);
CASE_STR(WM_IME_COMPOSITION);
CASE_STR(WM_INITDIALOG);
CASE_STR(WM_COMMAND);
CASE_STR(WM_SYSCOMMAND);
CASE_STR(WM_TIMER);
CASE_STR(WM_HSCROLL);
CASE_STR(WM_VSCROLL);
CASE_STR(WM_INITMENU);
CASE_STR(WM_INITMENUPOPUP);
CASE_STR(WM_GESTURE);
CASE_STR(WM_GESTURENOTIFY);
CASE_STR(WM_MENUSELECT);
CASE_STR(WM_MENUCHAR);
CASE_STR(WM_ENTERIDLE);
CASE_STR(WM_UNINITMENUPOPUP);
CASE_STR(WM_CHANGEUISTATE);
CASE_STR(WM_UPDATEUISTATE);
CASE_STR(WM_QUERYUISTATE);
CASE_STR(WM_CTLCOLORMSGBOX);
CASE_STR(WM_CTLCOLOREDIT);
CASE_STR(WM_CTLCOLORLISTBOX);
CASE_STR(WM_CTLCOLORBTN);
CASE_STR(WM_CTLCOLORDLG);
CASE_STR(WM_CTLCOLORSCROLLBAR);
CASE_STR(WM_CTLCOLORSTATIC);
CASE_STR(WM_MOUSEMOVE);
CASE_STR(WM_LBUTTONDOWN);
CASE_STR(WM_LBUTTONUP);
CASE_STR(WM_LBUTTONDBLCLK);
CASE_STR(WM_RBUTTONDOWN);
CASE_STR(WM_RBUTTONUP);
CASE_STR(WM_RBUTTONDBLCLK);
CASE_STR(WM_MBUTTONDOWN);
CASE_STR(WM_MBUTTONUP);
CASE_STR(WM_MBUTTONDBLCLK);
CASE_STR(WM_MOUSEWHEEL);
CASE_STR(WM_XBUTTONDOWN);
CASE_STR(WM_XBUTTONUP);
CASE_STR(WM_XBUTTONDBLCLK);
CASE_STR(WM_MOUSEHWHEEL);
CASE_STR(WM_PARENTNOTIFY);
CASE_STR(WM_ENTERMENULOOP);
CASE_STR(WM_EXITMENULOOP);
CASE_STR(WM_NEXTMENU);
CASE_STR(WM_SIZING);
CASE_STR(WM_CAPTURECHANGED);
CASE_STR(WM_MOVING);
CASE_STR(WM_POWERBROADCAST);
CASE_STR(WM_DEVICECHANGE);
CASE_STR(WM_POINTERDEVICECHANGE);
CASE_STR(WM_POINTERDEVICEINRANGE);
CASE_STR(WM_POINTERDEVICEOUTOFRANGE);
CASE_STR(WM_POINTERUPDATE);
CASE_STR(WM_POINTERDOWN);
CASE_STR(WM_POINTERUP);
CASE_STR(WM_POINTERENTER);
CASE_STR(WM_POINTERLEAVE);
CASE_STR(WM_POINTERACTIVATE);
CASE_STR(WM_POINTERCAPTURECHANGED);
CASE_STR(WM_IME_SETCONTEXT);
CASE_STR(WM_IME_NOTIFY);
CASE_STR(WM_IME_CONTROL);
CASE_STR(WM_IME_COMPOSITIONFULL);
CASE_STR(WM_IME_SELECT);
CASE_STR(WM_IME_CHAR);
CASE_STR(WM_IME_REQUEST);
CASE_STR(WM_IME_KEYDOWN);
CASE_STR(WM_IME_KEYUP);
CASE_STR(WM_MDICREATE);
CASE_STR(WM_MDIDESTROY);
CASE_STR(WM_MDIACTIVATE);
CASE_STR(WM_MDIRESTORE);
CASE_STR(WM_MDINEXT);
CASE_STR(WM_MDIMAXIMIZE);
CASE_STR(WM_MDITILE);
CASE_STR(WM_MDICASCADE);
CASE_STR(WM_MDIICONARRANGE);
CASE_STR(WM_MDIGETACTIVE);
CASE_STR(WM_MDISETMENU);
CASE_STR(WM_ENTERSIZEMOVE);
CASE_STR(WM_EXITSIZEMOVE);
CASE_STR(WM_DROPFILES);
CASE_STR(WM_MDIREFRESHMENU);
CASE_STR(WM_MOUSEHOVER);
CASE_STR(WM_NCMOUSELEAVE);
CASE_STR(WM_MOUSELEAVE);
CASE_STR(WM_WTSSESSION_CHANGE);
CASE_STR(WM_DPICHANGED);
CASE_STR(WM_DPICHANGED_BEFOREPARENT);
CASE_STR(WM_DPICHANGED_AFTERPARENT);
CASE_STR(WM_CUT);
CASE_STR(WM_COPY);
CASE_STR(WM_PASTE);
CASE_STR(WM_CLEAR);
CASE_STR(WM_UNDO);
CASE_STR(WM_RENDERFORMAT);
CASE_STR(WM_RENDERALLFORMATS);
CASE_STR(WM_DESTROYCLIPBOARD);
CASE_STR(WM_DRAWCLIPBOARD);
CASE_STR(WM_PAINTCLIPBOARD);
CASE_STR(WM_VSCROLLCLIPBOARD);
CASE_STR(WM_SIZECLIPBOARD);
CASE_STR(WM_ASKCBFORMATNAME);
CASE_STR(WM_CHANGECBCHAIN);
CASE_STR(WM_HSCROLLCLIPBOARD);
CASE_STR(WM_QUERYNEWPALETTE);
CASE_STR(WM_PALETTEISCHANGING);
CASE_STR(WM_PALETTECHANGED);
CASE_STR(WM_HOTKEY);
CASE_STR(WM_PRINT);
CASE_STR(WM_PRINTCLIENT);
CASE_STR(WM_APPCOMMAND);
CASE_STR(WM_THEMECHANGED);
CASE_STR(WM_DWMCOMPOSITIONCHANGED);
CASE_STR(WM_DWMNCRENDERINGCHANGED);
CASE_STR(WM_DWMCOLORIZATIONCOLORCHANGED);
CASE_STR(WM_DWMWINDOWMAXIMIZEDCHANGE);
CASE_STR(WM_HANDHELDFIRST);
CASE_STR(WM_HANDHELDLAST);
CASE_STR(WM_AFXFIRST);
CASE_STR(WM_AFXLAST);
CASE_STR(WM_PENWINFIRST);
CASE_STR(WM_PENWINLAST);
CASE_STR(WM_DWMSENDICONICTHUMBNAIL);
CASE_STR(WM_DWMSENDICONICLIVEPREVIEWBITMAP);
CASE_STR(WM_USER);
CASE_STR(WM_APP);
case 0x0118: return L"WM_SYSTIMER";
default:
if (msg > WM_USER && msg < WM_APP) {
CString text;
text.Format(L"WM_USER + %d", msg - WM_USER);
return text;
}
if (msg > WM_APP) {
CString text;
text.Format(L"WM_APP + %d", msg - WM_APP);
return text;
}
break;
}
return L"";
}
ULONG_PTR WindowHelper::GetID(HWND hWnd) {
return ::GetWindowLongPtr(hWnd, GWLP_ID);
}
ULONG_PTR WindowHelper::GetUserData(HWND hWnd) {
return ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
}
================================================
FILE: WinSpy/WindowHelper.h
================================================
#pragma once
struct WindowItem {
HWND hWnd;
DWORD ThreadId;
DWORD ProcessId;
CString ProcessName;
};
struct StyleItem {
DWORD Value;
PCWSTR Text;
DWORD Mask{ Value };
};
struct WindowHelper abstract final {
static CString WindowStyleToString(HWND hWnd);
static CString ClassStyleToString(HWND hWnd);
static CString WindowExtendedStyleToString(HWND hWnd);
static CString WindowRectToString(HWND hWnd);
static CString GetWindowClassName(HWND hWnd);
static CString GetWindowText(HWND hWnd);
static HICON GetWindowIcon(HWND hWnd);
static HICON GetWindowOrProcessIcon(HWND hWnd);
static bool Flash(HWND hWnd);
static void HighlightBorder(HWND hWnd, bool highlight = true);
static CString GetWindowClassAndTitle(HWND hWnd);
static std::unordered_map<HWND, int>& GetIconMap();
static CImageList& GetImageList();
static WindowItem GetWindowInfo(HWND hWnd);
static bool ThreadHasWindows(DWORD tid);
static int ShowWindowProperties(HWND hWnd);
static CString WindowMessageToString(DWORD msg);
static ULONG_PTR GetID(HWND hWnd);
static ULONG_PTR GetUserData(HWND hWnd);
static std::pair<StyleItem const*, int> GetWindowStyleArray();
static std::pair<StyleItem const*, int> GetListViewStyleArray();
static std::pair<StyleItem const*, int> GetTreeViewStyleArray();
static std::pair<StyleItem const*, int> GetTabCtrlStyleArray();
static std::pair<StyleItem const*, int> GetWindowStyleExArray();
static std::pair<StyleItem const*, int> GetClassStyleArray();
static std::pair<StyleItem const*, int> GetEditStyleArray();
static std::pair<StyleItem const*, int> GetListBoxStyleArray();
static std::pair<StyleItem const*, int> GetComboBoxStyleArray();
static std::pair<StyleItem const*, int> GetHeaderStyleArray();
static std::pair<StyleItem const*, int> GetButtonStyleArray();
static std::pair<StyleItem const*, int> GetStaticStyleArray();
static std::pair<StyleItem const*, int> GetToolTipStyleArray();
static std::pair<StyleItem const*, int> GetStatusBarStyleArray();
static std::pair<StyleItem const*, int> GetToolBarStyleArray();
static std::pair<StyleItem const*, int> GetRebarStyleArray();
static std::pair<StyleItem const*, int> GetScrollBarStyleArray();
};
================================================
FILE: WinSpy/WindowWindowsPage.cpp
================================================
#include "pch.h"
#include "resource.h"
#include "WindowWindowsPage.h"
#include "FormatHelper.h"
const UINT WM_UPDATE = WM_USER + 300;
void CWindowWindowsPage::UpdateData() {
const struct {
CWindow win;
UINT idHandle, idClass, idText;
} windows[] = {
{ m_Win.GetParent(), IDC_HANDLE, IDC_CLASS, IDC_TEXT },
{ m_Win.GetWindow(GW_HWNDNEXT), IDC_HANDLE2, IDC_CLASS2, IDC_TEXT2 },
{ m_Win.GetWindow(GW_HWNDPREV), IDC_HANDLE3, IDC_CLASS3, IDC_TEXT3 },
{ m_Win.GetWindow(GW_CHILD), IDC_HANDLE4, IDC_CLASS4, IDC_TEXT4 },
};
CString text;
for (auto& item : windows) {
if (!::IsWindow(item.win.m_hWnd)) {
SetDlgItemText(item.idHandle, L"(none) ");
continue;
}
text.Format(L"<a>0x%zX</a>", (ULONG_PTR)item.win.m_hWnd);
SetDlgItemText(item.idHandle, text);
if (::GetClassName(item.win, text.GetBufferSetLength(128), 128))
SetDlgItemText(item.idClass, text);
item.win.GetWindowText(text);
SetDlgItemText(item.idText, text);
}
}
LRESULT CWindowWindowsPage::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
UpdateData();
return 0;
}
LRESULT CWindowWindowsPage::OnClickHandle(int, LPNMHDR hdr, BOOL&) {
auto id = (UINT)hdr->idFrom;
CString text;
GetDlgItemText(id, text);
auto hWnd = (HWND)FormatHelper::ParseHex(text.Mid(3, text.GetLength() - 6));
m_Win.Detach();
m_Win.Attach(hWnd);
UpdateData();
GetParent().SendMessageToDescendants(WM_UPDATE, 0, reinterpret_cast<LPARAM>(hWnd));
return 0;
}
================================================
FILE: WinSpy/WindowWindowsPage.h
================================================
#pragma once
#include "DialogHelper.h"
class CWindowWindowsPage :
public CDialogHelper<CWindowWindowsPage>,
public CPropertyPageImpl<CWindowWindowsPage> {
public:
enum { IDD = IDD_PROPWINDOWS };
CWindowWindowsPage(HWND hWnd) : m_Win(hWnd) {
m_psp.dwFlags |= PSP_USEICONID;
m_psp.pszIcon = MAKEINTRESOURCE(IDI_WINDOWS);
}
protected:
BEGIN_MSG_MAP(CWindowWindowsPage)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
NOTIFY_CODE_HANDLER(NM_CLICK, OnClickHandle)
NOTIFY_CODE_HANDLER(NM_RETURN, OnClickHandle)
END_MSG_MAP()
private:
void UpdateData();
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnClickHandle(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
CWindow m_Win;
};
================================================
FILE: WinSpy/WindowsListView.cpp
================================================
#include "pch.h"
#include "resource.h"
#include "WindowsListView.h"
#include "FormatHelper.h"
#include "SortHelper.h"
#include "ProcessHelper.h"
void CWindowsListView::SetSelectedHwnd(HWND hWnd) {
m_SelectedHwnd.Detach();
m_SelectedHwnd.Attach(hWnd);
}
LRESULT CWindowsListView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
m_hWndClient = m_List.Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
| LVS_REPORT | LVS_OWNERDATA | LVS_SINGLESEL | LVS_SHAREIMAGELISTS, 0);
m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP);
m_List.SetImageList(WindowHelper::GetImageList(), LVSIL_SMALL);
auto cm = GetColumnManager(m_List);
struct {
PCWSTR text;
DataItemType type;
int width = 100;
int format = LVCFMT_LEFT;
ColumnFlags flags = ColumnFlags::Visible;
} columns[] = {
{ L"Class Name", DataItemType::ClassName, 140 },
{ L"Handle", DataItemType::Handle, 80, LVCFMT_RIGHT },
{ L"Text", DataItemType::Text, 150 },
{ L"Style", DataItemType::Style, 80, LVCFMT_RIGHT },
{ L"Ex Style", DataItemType::ExtendedStyle, 80, LVCFMT_RIGHT },
{ L"PID", DataItemType::ProcessId, 70, LVCFMT_RIGHT },
{ L"Process Name", DataItemType::ProcessName, 120 },
{ L"TID", DataItemType::ThreadId, 70, LVCFMT_RIGHT },
{ L"Rectangle", DataItemType::Rectangle, 170, LVCFMT_LEFT, ColumnFlags::None },
{ L"Parent HWND", DataItemType::ParentWindow, 100, LVCFMT_RIGHT, ColumnFlags::Fixed | ColumnFlags::Visible },
{ L"Owner HWND", DataItemType::OwnerWindow, 100, LVCFMT_RIGHT, ColumnFlags::Fixed | ColumnFlags::Visible },
{ L"Next HWND", DataItemType::NextWindow, 100, LVCFMT_RIGHT, ColumnFlags::Fixed | ColumnFlags::Visible },
{ L"Prev HWND", DataItemType::PrevWindow, 100, LVCFMT_RIGHT, ColumnFlags::Fixed | ColumnFlags::Visible },
{ L"Child HWND", DataItemType::FirstChildWindow, 100, LVCFMT_RIGHT, ColumnFlags::Fixed | ColumnFlags::Visible },
{ L"WndProc", DataItemType::WindowProc, 100, LVCFMT_RIGHT, ColumnFlags::Fixed },
{ L"User Data", DataItemType::UserData, 100, LVCFMT_RIGHT },
{ L"ID", DataItemType::ID, 80, LVCFMT_RIGHT },
{ L"Class Atom", DataItemType::ClassAtom, 90, LVCFMT_RIGHT },
{ L"Class Style", DataItemType::ClassStyle, 80, LVCFMT_RIGHT, ColumnFlags::Fixed },
{ L"Class Extra Bytes", DataItemType::ClassExtra, 70, LVCFMT_RIGHT, ColumnFlags::Fixed },
{ L"Window Extra Bytes", DataItemType::WindowExtra, 70, LVCFMT_RIGHT, ColumnFlags::Fixed },
};
for (auto& col : columns) {
cm->AddColumn(col.text, col.format, col.width, col.type, col.flags);
}
cm->UpdateColumns();
return 0;
}
LRESULT CWindowsListView::OnWindowShow(WORD, WORD, HWND, BOOL&) {
CWindow win(m_Items[m_List.GetSelectionMark()].hWnd);
win.ShowWindowAsync(SW_SHOW);
return 0;
}
LRESULT CWindowsListView::OnWindowHide(WORD, WORD, HWND, BOOL&) {
ATLASSERT(m_SelectedHwnd);
m_SelectedHwnd.ShowWindowAsync(SW_HIDE);
return 0;
}
LRESULT CWindowsListView::OnWindowMinimize(WORD, WORD, HWND, BOOL&) {
CWindow win(m_Items[m_List.GetSelectionMark()].hWnd);
win.ShowWindowAsync(SW_MINIMIZE);
return 0;
}
LRESULT CWindowsListView::OnWindowMaximize(WORD, WORD, HWND, BOOL&) {
CWindow win(m_Items[m_List.GetSelectionMark()].hWnd);
win.ShowWindowAsync(SW_MAXIMIZE);
return 0;
}
CString CWindowsListView::GetColumnText(HWND, int row, int col) const {
auto& item = m_Items[row];
if (!::IsWindow(item.hWnd)) {
return L"";
}
CWindow win(item.hWnd);
auto h = item.hWnd;
CString text;
switch (GetColumnManager(m_List)->GetColumnTag<DataItemType>(col)) {
case DataItemType::Handle:
text.Format(L"0x%zX", (ULONG_PTR)h);
break;
case DataItemType::Style:
text.Format(L"0x%08X", win.GetStyle());
break;
case DataItemType::ProcessId:
text.Format(L"%u", item.ProcessId);
break;
case DataItemType::ProcessName:
return item.ProcessName;
case DataItemType::ThreadId:
text.Format(L"%u", item.ThreadId);
break;
case DataItemType::Rectangle:
return WindowHelper::WindowRectToString(h);
case DataItemType::ExtendedStyle:
text.Format(L"0x%08X", win.GetExStyle());
break;
case DataItemType::ClassName:
return WindowHelper::GetWindowClassName(h);
case DataItemType::Text:
win.GetWindowText(text);
if (text.GetLength() > 256)
text = text.Left(256) + L"...";
break;
case DataItemType::WindowProc:
text.Format(L"0x%zX", win.GetWindowLongPtr(GWLP_WNDPROC));
break;
case DataItemType::UserData:
text.Format(L"0x%zX", win.GetWindowLongPtr(GWLP_USERDATA));
break;
case DataItemType::ID:
text.Format(L"0x%zX", win.GetWindowLongPtr(GWLP_ID));
break;
case DataItemType::ParentWindow: return FormatHelper::FormatHWndOrNone(::GetAncestor(win, GA_PARENT));
case DataItemType::NextWindow: return FormatHelper::FormatHWndOrNone(win.GetWindow(GW_HWNDNEXT));
case DataItemType::PrevWindow: return FormatHelper::FormatHWndOrNone(win.GetWindow(GW_HWNDPREV));
case DataItemType::OwnerWindow: return FormatHelper::FormatHWndOrNone(win.GetWindow(GW_OWNER));
case DataItemType::FirstChildWindow: return FormatHelper::FormatHWndOrNone(win.GetWindow(GW_CHILD));
case DataItemType::ClassAtom:
text.Format(L"0x%04X", (DWORD)::GetClassLongPtr(win, GCW_ATOM));
break;
case DataItemType::ClassStyle:
text.Format(L"0x%04X", (DWORD)::GetClassLongPtr(win, GCL_STYLE));
break;
case DataItemType::ClassExtra:
text.Format(L"%u", (ULONG)::GetClassLongPtr(win, GCL_CBCLSEXTRA));
break;
case DataItemType::WindowExtra:
text.Format(L"%u", (ULONG)::GetClassLongPtr(win, GCL_CBWNDEXTRA));
break;
}
return text;
}
int CWindowsListView::GetRowImage(HWND, int row, int col) const {
auto& item = m_Items[row];
auto h = item.hWnd;
auto& icons = WindowHelper::GetIconMap();
if (auto it = icons.find(h); it != icons.end()) {
return it->second;
}
auto hIcon = WindowHelper::GetWindowIcon(h);
if (hIcon) {
int image = WindowHelper::GetImageList().AddIcon(hIcon);
icons.insert({ h, image });
return image;
}
return 0;
}
void CWindowsListView::DoSort(const SortInfo* si) {
if (si == nullptr)
return;
std::sort(m_Items.begin(), m_Items.end(), [&](const auto& h1, const auto& h2) -> bool {
switch (GetColumnManager(m_List)->GetColumnTag<DataItemType>(si->SortColumn)) {
case DataItemType::ClassName: return SortHelper::Sort(WindowHelper::GetWindowClassName(h1.hWnd), WindowHelper::GetWindowClassName(h2.hWnd), si->SortAscending);
case DataItemType::Text: return SortHelper::Sort(WindowHelper::GetWindowText(h1.hWnd), WindowHelper::GetWindowText(h2.hWnd), si->SortAscending);
case DataItemType::Handle: return SortHelper::Sort(h1.hWnd, h2.hWnd, si->SortAscending);
case DataItemType::FirstChildWindow: return SortHelper::Sort(::GetWindow(h1.hWnd, GW_CHILD), ::GetWindow(h2.hWnd, GW_CHILD), si->SortAscending);
case DataItemType::PrevWindow: return SortHelper::Sort(::GetWindow(h1.hWnd, GW_HWNDPREV), ::GetWindow(h2.hWnd, GW_HWNDPREV), si->SortAscending);
case DataItemType::NextWindow: return SortHelper::Sort(::GetWindow(h1.hWnd, GW_HWNDNEXT), ::GetWindow(h2.hWnd, GW_HWNDNEXT), si->SortAscending);
case DataItemType::OwnerWindow: return SortHelper::Sort(::GetWindow(h1.hWnd, GW_OWNER), ::GetWindow(h2.hWnd, GW_OWNER), si->SortAscending);
case DataItemType::ParentWindow: return SortHelper::Sort(::GetParent(h1.hWnd), ::GetParent(h2.hWnd), si->SortAscending);
case DataItemType::Style: return SortHelper::Sort(CWindow(h1.hWnd).GetStyle(), CWindow(h2.hWnd).GetStyle(), si->SortAscending);
case DataItemType::ExtendedStyle: return SortHelper::Sort(CWindow(h1.hWnd).GetExStyle(), CWindow(h2.hWnd).GetExStyle(), si->SortAscending);
case DataItemType::ThreadId: return SortHelper::Sort(h1.ThreadId, h2.ThreadId, si->SortAscending);
case DataItemType::ProcessId: return SortHelper::Sort(h1.ProcessId, h2.ProcessId, si->SortAscending);
case DataItemType::ProcessName: return SortHelper::Sort(h1.ProcessName, h2.ProcessName, si->SortAscending);
case DataItemType::ID: return SortHelper::Sort(WindowHelper::GetID(h1.hWnd), WindowHelper::GetID(h2.hWnd), si->SortAscending);
case DataItemType::UserData: return SortHelper::Sort(WindowHelper::GetUserData(h1.hWnd), WindowHelper::GetUserData(h2.hWnd), si->SortAscending);
}
return false;
});
}
bool CWindowsListView::OnRightClickList(HWND, int row, int col, CPoint const& pt) {
CMenu menu;
menu.LoadMenu(IDR_CONTEXT);
m_ContextMenuOpen = true;
auto cmd = m_pFrame->ShowPopupMenu(menu.GetSubMenu(0), pt, TPM_RETURNCMD);
m_ContextMenuOpen = false;
if (cmd) {
LRESULT result;
return ProcessWindowMessage(m_hWnd, WM_COMMAND, cmd, 0, result, 1);
}
return false;
}
bool CWindowsListView::IsSortable(HWND, int col) const {
return true;
}
DWORD CWindowsListView::OnPrePaint(int, LPNMCUSTOMDRAW cd) {
if (cd->hdr.hwndFrom == m_List)
return CDRF_NOTIFYITEMDRAW;
return CDRF_DODEFAULT;
}
DWORD CWindowsListView::OnItemPrePaint(int, LPNMCUSTOMDRAW cd) {
ATLASSERT(cd->hdr.hwndFrom == m_List);
auto& h = m_Items[(int)cd->dwItemSpec];
auto lv = (LPNMLVCUSTOMDRAW)cd;
lv->clrTextBk = m_SelectedHwnd == nullptr || ::IsWindowVisible(h.hWnd) ? CLR_INVALID : RGB(224, 224, 224);
return CDRF_DODEFAULT;
}
void CWindowsListView::AddMessageOnlyWindows() {
HWND hWnd = nullptr;
for (;;) {
hWnd = ::FindWindowEx(HWND_MESSAGE, hWnd, nullptr, nullptr);
if (!hWnd)
break;
m_Items.push_back(WindowHelper::GetWindowInfo(hWnd));
}
}
void CWindowsListView::UpdateList(HWND hWnd) {
if (m_ContextMenuOpen)
return;
m_Items.clear();
m_SelectedHwnd = hWnd;
if (hWnd == nullptr) {
//
// message only windows
//
AddMessageOnlyWindows();
}
else {
m_Items.push_back(WindowHelper::GetWindowInfo(m_SelectedHwnd));
AddChildWindows(m_Items, m_SelectedHwnd, true);
}
m_List.SetItemCountEx((int)m_Items.size(), LVSICF_NOSCROLL);
UpdateList();
}
void CWindowsListView::UpdateListByThread(DWORD tid) {
m_SelectedHwnd.Detach();
m_Items.clear();
AddThreadWindows(tid);
m_List.SetItemCountEx((int)m_Items.size(), LVSICF_NOSCROLL);
UpdateList();
}
void CWindowsListView::UpdateListByProcess(ProcessInfo const& pi) {
m_Items.clear();
for (auto tid : pi.Threads)
AddThreadWindows(tid);
m_List.SetItemCountEx((int)m_Items.size(), LVSICF_NOSCROLL);
UpdateList();
}
void CWindowsListView::UpdateUI(CUpdateUIBase& ui) {
if (::GetFocus() != m_List)
return;
int first = m_List.GetSelectionMark();
int selected = m_List.GetSelectedCount();
ui.UIEnable(ID_WINDOW_PROPERTIES, selected == 1);
}
void CWindowsListView::AddThreadWindows(DWORD tid) {
::EnumThreadWindows(tid, [](auto hWnd, auto param) {
auto p = reinterpret_cast<CWindowsListView*>(param);
p->m_Items.push_back(WindowHelper::GetWindowInfo(hWnd));
return TRUE;
}, reinterpret_cast<LPARAM>(this));
}
void CWindowsListView::Refresh() {
}
void CWindowsListView::AddChildWindows(std::vector<WindowItem>& v, HWND hParent, bool directOnly) {
struct LocalInfo {
std::vector<WindowItem>& v;
CWindowsListView* pThis;
bool directOnly;
};
LocalInfo info{ v, this, directOnly };
::EnumChildWindows(hParent, [](auto hWnd, auto param) {
auto info = reinterpret_cast<LocalInfo*>(param);
if (info->pThis->m_ShowHiddenWindows || ::IsWindowVisible(hWnd)) {
info->v.push_back(WindowHelper::GetWindowInfo(hWnd));
if (!info->directOnly)
info->pThis->AddChildWindows(info->v, hWnd, false);
}
return TRUE;
}, reinterpret_cast<LPARAM>(&info));
}
CString CWindowsListView::GetDetails(const DataItem& item) const {
CString text;
switch (item.Type) {
case DataItemType::ProcessId:
{
DWORD pid = 0;
::GetWindowThreadProcessId(m_SelectedHwnd, &pid);
return ProcessHelper::GetProcessImageName(pid);
}
case DataItemType::Text:
text.Format(L"Length: %d", m_SelectedHwnd.GetWindowTextLength());
break;
return WindowHelper::WindowStyleToString(m_SelectedHwnd);
case DataItemType::Style: return WindowHelper::WindowStyleToString(m_SelectedHwnd);
case DataItemType::ClassStyle: return WindowHelper::ClassStyleToString(m_SelectedHwnd);
case DataItemType::ExtendedStyle: return WindowHelper::WindowExtendedStyleToString(m_SelectedHwnd);
case DataItemType::Rectangle:
if (m_SelectedHwnd.IsZoomed())
return L"Maximized";
if (m_SelectedHwnd.IsIconic())
return L"Minimized";
break;
case DataItemType::NextWindow: return WindowHelper::GetWindowClassAndTitle(m_SelectedHwnd.GetWindow(GW_HWNDNEXT));
case DataItemType::PrevWindow: return WindowHelper::GetWindowClassAndTitle(m_SelectedHwnd.GetWindow(GW_HWNDPREV));
case DataItemType::OwnerWindow: return WindowHelper::GetWindowClassAndTitle(m_SelectedHwnd.GetWindow(GW_OWNER));
case DataItemType::ParentWindow: return WindowHelper::GetWindowClassAndTitle(::GetAncestor(m_SelectedHwnd, GA_PARENT));
case DataItemType::FirstChildWindow: return WindowHelper::GetWindowClassAndTitle(m_SelectedHwnd.GetWindow(GW_CHILD));
}
return text;
}
void CWindowsListView::UpdateList() {
DoSort(GetSortInfo(m_List));
m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetCountPerPage() + m_List.GetTopIndex());
}
LRESULT CWindowsListView::OnToggleEmptyTitleWindows(WORD, WORD, HWND, BOOL&) {
m_ShowNoTitleWindows = !m_ShowNoTitleWindows;
UpdateList(m_SelectedHwnd);
return 0;
}
LRESULT CWindowsListView::OnToggleChildWindows(WORD, WORD, HWND, BOOL&) {
m_ShowChildWindows = !m_ShowChildWindows;
UpdateList(m_SelectedHwnd);
return 0;
}
LRESULT CWindowsListView::OnWindowRestore(WORD, WORD, HWND, BOOL&) {
CWindow win(m_Items[m_List.GetSelectionMark()].hWnd);
win.ShowWindowAsync(SW_RESTORE);
return 0;
}
LRESULT CWindowsListView::OnWindowBringToFront(WORD, WORD, HWND, BOOL&) {
CWindow win(m_Items[m_List.GetSelectionMark()].hWnd);
win.BringWindowToTop();
return 0;
}
LRESULT CWindowsListView::OnWindowProperties(WORD, WORD, HWND, BOOL&) {
auto& item = m_Items[m_List.GetSelectionMark()];
WindowHelper::ShowWindowProperties(item.hWnd);
return LRESULT();
}
LRESULT CWindowsListView::OnItemChanged(int, LPNMHDR, BOOL&) {
UpdateUI(m_pFrame->GetUIUpdate());
return 0;
}
LRESULT CWindowsListView::OnWindowFlash(WORD, WORD, HWND, BOOL&) {
auto& item = m_Items[m_List.GetSelectionMark()];
WindowHelper::Flash(item.hWnd);
return 0;
}
LRESULT CWindowsListView::OnToggleHiddenWindows(WORD, WORD, HWND, BOOL&) {
m_ShowHiddenWindows = !m_ShowHiddenWindows;
UpdateList(m_SelectedHwnd);
return 0;
}
bool CWindowsListView::OnDoubleClickList(HWND, int row, int col, CPoint const&) {
if (row >= 0) {
WindowHelper::ShowWindowProperties(m_Items[row].hWnd);
return true;
}
return false;
}
================================================
FILE: WinSpy/WindowsListView.h
================================================
#pragma once
#include <VirtualListView.h>
#include "Interfaces.h"
#include "WindowHelper.h"
#include "ProcessHelper.h"
class CWindowsListView :
public CFrameWindowImpl<CWindowsListView, CWindow, CControlWinTraits>,
public CVirtualListView<CWindowsListView>,
public CCustomDraw<CWindowsListView> {
public:
using BaseFrame = CFrameWindowImpl<CWindowsListView, CWindow, CControlWinTraits>;
CWindowsListView(IMainFrame* frame) : m_pFrame(frame) {}
CString GetColumnText(HWND, int row, int col) const;
int GetRowImage(HWND, int row, int col) const;
bool IsSortable(HWND, int col) const;
void DoSort(const SortInfo* si);
bool OnRightClickList(HWND, int row, int col, CPoint const&);
bool OnDoubleClickList(HWND, int row, int col, CPoint const&);
DWORD OnPrePaint(int, LPNMCUSTOMDRAW cd);
DWORD OnItemPrePaint(int, LPNMCUSTOMDRAW cd);
void SetSelectedHwnd(HWND hWnd);
void UpdateList(HWND hWnd);
void UpdateListByThread(DWORD tid);
void UpdateListByProcess(ProcessInfo const& pi);
void UpdateUI(CUpdateUIBase& ui);
void Refresh();
enum class DataItemType {
Handle, ClassName, Text, Style, ExtendedStyle, ProcessName,
ProcessId, ThreadId, ParentWindow, FirstChildWindow, NextWindow, PrevWindow, OwnerWindow,
WindowProc, UserData, ID, Rectangle,
ClassAtom, ClassStyle, ClassExtra, WindowExtra,
};
struct DataItem {
CString Property;
DataItemType Type;
};
protected:
BEGIN_MSG_MAP(CWindowsListView)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnItemChanged)
CHAIN_MSG_MAP(CVirtualListView<CWindowsListView>)
CHAIN_MSG_MAP(CCustomDraw<CWindowsListView>)
CHAIN_MSG_MAP(BaseFrame)
ALT_MSG_MAP(1)
if (::GetFocus() != m_List)
return FALSE;
COMMAND_ID_HANDLER(ID_WINDOW_SHOW, OnWindowShow)
COMMAND_ID_HANDLER(ID_WINDOW_HIDE, OnWindowHide)
COMMAND_ID_HANDLER(ID_WINDOW_BRINGTOFRONT, OnWindowBringToFront)
COMMAND_ID_HANDLER(ID_WINDOW_MINIMIZE, OnWindowMinimize)
COMMAND_ID_HANDLER(ID_WINDOW_MAXIMIZE, OnWindowMaximize)
COMMAND_ID_HANDLER(ID_STATE_FLASH, OnWindowFlash)
COMMAND_ID_HANDLER(ID_WINDOW_RESTORE, OnWindowRestore)
COMMAND_ID_HANDLER(ID_VIEW_HIDDENWINDOWS, OnToggleHiddenWindows)
COMMAND_ID_HANDLER(ID_VIEW_EMPTYTITLEWINDOWS, OnToggleEmptyTitleWindows)
COMMAND_ID_HANDLER(ID_VIEW_CHILDWINDOWS, OnToggleChildWindows)
COMMAND_ID_HANDLER(ID_WINDOW_PROPERTIES, OnWindowProperties)
END_MSG_MAP()
private:
void AddChildWindows(std::vector<WindowItem>& v, HWND hParent, bool directOnly);
void AddThreadWindows(DWORD tid);
CString GetDetails(const DataItem& item) const;
void UpdateList();
void AddMessageOnlyWindows();
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnWindowShow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowHide(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowMinimize(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowMaximize(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowRestore(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowFlash(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnRefresh(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnToggleHiddenWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnToggleEmptyTitleWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnToggleChildWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowBringToFront(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnWindowProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnItemChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
private:
CListViewCtrl m_List;
std::vector<WindowItem> m_Items;
DWORD m_TotalWindows, m_TotalVisibleWindows, m_TopLevelWindows;
CWindow m_SelectedHwnd;
IMainFrame* m_pFrame;
bool m_ShowHiddenWindows : 1 { false };
bool m_ShowNoTitleWindows : 1 { true };
bool m_ShowChildWindows : 1 { true };
bool m_Deleting : 1{ false };
bool m_ContextMenuOpen : 1{ false };
};
================================================
FILE: WinSpy/WindowsView.cpp
================================================
// View.cpp : implementation of the CWindowsView class
//
/////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#include "resource.h"
#include "FormatHelper.h"
#include "WindowsView.h"
#include "ProcessHelper.h"
#include "WindowHelper.h"
#include "SortHelper.h"
#include "MessagesView.h"
BOOL CWindowsView::PreTranslateMessage(MSG* pMsg) {
pMsg;
return FALSE;
}
void CWindowsView::OnActivate(bool activate) {
if (activate) {
UpdateUI();
SetTimer(1, 2000, nullptr);
}
else {
KillTimer(1);
}
}
void CWindowsView::UpdateUI() {
auto& ui = GetFrame()->GetUIUpdate();
if (::GetFocus() == m_Tree) {
ui.UISetCheck(ID_VIEW_HIDDENWINDOWS, m_ShowHiddenWindows);
ui.UISetCheck(ID_VIEW_EMPTYTITLEWINDOWS, m_ShowNoTitleWindows);
ui.UIEnable(ID_WINDOW_PROPERTIES, m_SelectedHwnd != nullptr);
//ui.UISetCheck(ID_VIEW_CHILDWINDOWS, m_ShowChildWindows);
}
else {
m_WindowsView.UpdateUI(ui);
}
}
void CWindowsView::Refresh() {
if (m_SelectedHwnd != nullptr && !m_SelectedHwnd.IsWindow()) {
m_Tree.DeleteItem(m_Selected);
return;
}
m_WindowsView.UpdateList(m_SelectedHwnd);
}
LRESULT CWindowsView::OnRefreshAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
InitTree();
return 0;
}
void CWindowsView::InitTree() {
m_TotalVisibleWindows = m_TotalWindows = m_TopLevelWindows = 0;
m_DesktopNode = nullptr;
HWND hDesktop = ::GetDesktopWindow();
if (!hDesktop)
return;
CWaitCursor wait;
m_Tree.LockWindowUpdate(TRUE);
m_Deleting = true;
m_Tree.DeleteAllItems();
m_WindowMap.clear();
m_Deleting = false;
m_DesktopNode = AddNode(hDesktop, TVI_ROOT);
::EnumWindows([](auto hWnd, auto lp) -> BOOL {
auto pThis = (CWindowsView*)lp;
pThis->AddNode(hWnd, pThis->m_DesktopNode);
return TRUE;
}, reinterpret_cast<LPARAM>(this));
AddMessageOnlyWindows();
m_DesktopNode.Expand(TVE_EXPAND);
m_Tree.LockWindowUpdate(FALSE);
m_DesktopNode.Select();
m_DesktopNode.EnsureVisible();
m_Tree.SetScrollPos(SB_HORZ, 0);
}
void CWindowsView::AddChildWindows(HTREEITEM hParent) {
auto hWnd = (HWND)m_Tree.GetItemData(hParent);
ATLASSERT(hWnd);
m_hCurrentNode = hParent;
::EnumChildWindows(hWnd, [](auto hChild, auto p) -> BOOL {
auto pThis = (CWindowsView*)p;
return pThis->AddChildNode(hChild);
}, reinterpret_cast<LPARAM>(this));
}
CTreeItem CWindowsView::AddNode(HWND hWnd, HTREEITEM hParent) {
CString text, name;
CWindow win(hWnd);
m_TotalWindows++;
if (win.IsWindowVisible())
m_TotalVisibleWindows++;
if (m_DesktopNode) {
if (::GetAncestor(hWnd, GA_PARENT) == (HWND)m_DesktopNode.GetData())
m_TopLevelWindows++;
if (!m_ShowHiddenWindows && !win.IsWindowVisible())
return nullptr;
win.GetWindowText(name);
if (!m_ShowNoTitleWindows && name.IsEmpty())
return nullptr;
}
if (name.GetLength() > 64)
name = name.Left(64) + L"...";
if (!name.IsEmpty())
name = L"[" + name + L"]";
WCHAR className[64] = { 0 };
::GetClassName(hWnd, className, _countof(className));
text.Format(L"0x%zX (%s) %s", (DWORD_PTR)hWnd, className, (PCWSTR)name);
HICON hIcon{ nullptr };
int image = 0;
if ((win.GetStyle() & WS_CHILD) == 0) {
auto& icons = WindowHelper::GetIconMap();
if (auto it = icons.find(hWnd); it == icons.end()) {
hIcon = WindowHelper::GetWindowOrProcessIcon(hWnd);
if (hIcon) {
icons.insert({ hWnd, image = WindowHelper::GetImageList().AddIcon(hIcon) });
}
}
else {
image = it->second;
}
}
auto node = m_Tree.InsertItem(text, image, image, hParent, TVI_LAST);
node.SetData((DWORD_PTR)hWnd);
m_WindowMap.insert({ hWnd, node });
if (!win.IsWindowVisible())
node.SetState(TVIS_CUT, TVIS_CUT);
if (m_DesktopNode && win.GetWindow(GW_CHILD)) {
// add a "plus" button
node.AddTail(L"*", 0);
}
return node;
}
BOOL CWindowsView::AddChildNode(HWND hChild) {
if (::GetAncestor(hChild, GA_PARENT) == (HWND)m_Tree.GetItemData(m_hCurrentNode)) {
AddNode(hChild, m_hCurrentNode);
}
return TRUE;
}
LRESULT CWindowsView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
m_Splitter.SetSplitterExtendedStyle(SPLIT_FLATBAR | SPLIT_PROPORTIONAL);
m_hWndClient = m_Splitter.Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
//m_TreeFrame.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
//m_Tree.Attach(m_TreeFrame.m_hWndClient);
//ToolBarButtonInfo buttons[] = {
// { ID_VIEW_REFRESH, IDI_REFRESH },
// { 0 },
// { ID_VIEW_HIDDENWINDOWS, IDI_WINDOW_HIDDEN },
// { ID_VIEW_EMPTYTITLEWINDOWS, IDI_WINDOW_NOTEXT },
// { ID_WINDOW_PROPERTIES, IDI_WINPROP },
//};
//m_TreeFrame.CreateAndInitToolBar(buttons, _countof(buttons));
m_Tree.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, 0);
m_Tree.SetExtendedStyle(TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER);
m_Tree.SetImageList(WindowHelper::GetImageList(), TVSIL_NORMAL);
m_WindowsView.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_Splitter.SetSplitterPanes(m_Tree, m_WindowsView);
UpdateLayout();
m_Splitter.SetSplitterPosPct(35);
InitTree();
m_WindowMap.reserve(256);
SetTimer(1, 2000, nullptr);
return 0;
}
LRESULT CWindowsView::OnTimer(UINT, WPARAM id, LPARAM, BOOL&) {
if (id == 1)
Refresh();
else if (id == 3) {
KillTimer(3);
m_Selected = m_Tree.GetSelectedItem();
NodeSelected();
}
return 0;
}
void CWindowsView::NodeSelected() {
m_SelectedHwnd.Detach();
auto data = m_Selected.GetData();
auto hWnd = (HWND)data;
if (data != MessageOnlyWindowsNode && !::IsWindow(hWnd)) // window is probably destroyed
m_Selected.Delete();
else {
if (data == MessageOnlyWindowsNode)
m_WindowsView.UpdateList(nullptr);
else {
m_SelectedHwnd.Attach(hWnd);
m_WindowsView.UpdateList(hWnd);
}
}
UpdateUI();
}
LRESULT CWindowsView::OnNodeExpanding(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
if (tv->action == TVE_EXPAND) {
auto hItem = tv->itemNew.hItem;
auto child = m_Tree.GetChildItem(hItem);
if (child.GetData() == 0) {
child.Delete();
AddChildWindows(hItem);
}
}
return 0;
}
LRESULT CWindowsView::OnNodeDeleted(int, LPNMHDR hdr, BOOL&) {
if (!m_Deleting) {
auto tv = (NMTREEVIEW*)hdr;
m_WindowMap.erase((HWND)tv->itemOld.lParam);
}
return 0;
}
LRESULT CWindowsView::OnNodeSelected(int, LPNMHDR hdr, BOOL&) {
auto tv = (NMTREEVIEW*)hdr;
if (tv->action == TVC_BYKEYBOARD) {
// short delay before update in case the user moves quickly through the tree
SetTimer(3, 250, nullptr);
}
else {
m_Selected.m_hTreeItem = tv->itemNew.hItem;
m_Selected.m_pTreeView = &m_Tree;
NodeSelected();
}
return 0;
}
LRESULT CWindowsView::OnWindowShow(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
m_SelectedHwnd.ShowWindowAsync(SW_SHOW);
return 0;
}
LRESULT CWindowsView::OnWindowHide(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
m_SelectedHwnd.ShowWindowAsync(SW_HIDE);
return 0;
}
LRESULT CWindowsView::OnWindowClose(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
m_SelectedHwnd.PostMessage(WM_CLOSE);
return 0;
}
LRESULT CWindowsView::OnWindowMinimize(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
m_SelectedHwnd.ShowWindowAsync(SW_MINIMIZE);
return 0;
}
LRESULT CWindowsView::OnWindowMaximize(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
m_SelectedHwnd.ShowWindowAsync(SW_MAXIMIZE);
return 0;
}
LRESULT CWindowsView::OnWindowRestore(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
m_SelectedHwnd.ShowWindowAsync(SW_RESTORE);
return 0;
}
LRESULT CWindowsView::OnWindowBringToFront(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
m_SelectedHwnd.BringWindowToTop();
return 0;
}
LRESULT CWindowsView::OnRefresh(WORD, WORD, HWND, BOOL&) {
InitTree();
return 0;
}
LRESULT CWindowsView::OnToggleHiddenWindows(WORD, WORD, HWND, BOOL&) {
m_ShowHiddenWindows = !m_ShowHiddenWindows;
UpdateUI();
InitTree();
return 0;
}
LRESULT CWindowsView::OnToggleEmptyTitleWindows(WORD, WORD, HWND, BOOL&) {
m_ShowNoTitleWindows = !m_ShowNoTitleWindows;
UpdateUI();
InitTree();
return 0;
}
LRESULT CWindowsView::OnToggleChildWindows(WORD, WORD, HWND, BOOL&) {
m_ShowChildWindows = !m_ShowChildWindows;
UpdateUI();
InitTree();
return 0;
}
LRESULT CWindowsView::OnTreeNodeRightClick(HTREEITEM hItem, CPoint const& pt) {
ATLASSERT(m_Selected);
if (!m_Selected)
return 0;
CMenu menu;
menu.LoadMenu(IDR_CONTEXT);
return GetFrame()->ShowPopupMenu(menu.GetSubMenu(0), pt);
}
LRESULT CWindowsView::OnWindowFlash(WORD, WORD, HWND, BOOL&) {
if (m_SelectedHwnd)
WindowHelper::Flash(m_SelectedHwnd);
return 0;
}
LRESULT CWindowsView::OnWindowHighlight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
if (m_SelectedHwnd) {
::TrySubmitThreadpoolCallback([](auto, auto p) {
auto hWnd = (HWND)p;
for (int i = 0; i < 3; i++) {
WindowHelper::HighlightBorder(hWnd);
::Sleep(500);
WindowHelper::HighlightBorder(hWnd, false);
::Sleep(500);
}
}, m_SelectedHwnd, nullptr);
}
return 0;
}
LRESULT CWindowsView::OnWindowProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& handled) {
if (::GetFocus() != m_Tree) {
handled = FALSE;
return 0;
}
if (m_SelectedHwnd) {
WindowHelper::ShowWindowProperties(m_SelectedHwnd);
}
return 0;
}
LRESULT CWindowsView::OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint const& pt) {
WindowHelper::ShowWindowProperties((HWND)m_Tree.GetItemData(hItem));
return 1;
}
LRESULT CWindowsView::OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
m_Tree.SetFocus();
return 0;
}
CTreeItem CWindowsView::AddMessageOnlyWindows() {
m_MsgOnlyNode = m_Tree.InsertItem(L"Message Only Windows", TVI_ROOT, TVI_LAST);
m_MsgOnlyNode.SetData(MessageOnlyWindowsNode);
return m_MsgOnlyNode;
}
LRESULT CWindowsView::OnCaptureMessages(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
if (m_SelectedHwnd) {
auto view = GetFrame()->CreateMessagesView();
if (!view->CaptureWindow(m_SelectedHwnd)) {
AtlMessageBox(m_hWnd, L"Failed to register hook", IDS_TITLE, MB_ICONERROR);
GetFrame()->CloseTab(view);
}
}
return 0;
}
================================================
FILE: WinSpy/WindowsView.h
================================================
gitextract_xjr65t7e/
├── .gitattributes
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── WinSpy/
│ ├── AboutDlg.cpp
│ ├── AboutDlg.h
│ ├── AutomationTreeView.cpp
│ ├── AutomationTreeView.h
│ ├── DialogHelper.h
│ ├── FindWindowDlg.cpp
│ ├── FindWindowDlg.h
│ ├── FormatHelper.cpp
│ ├── FormatHelper.h
│ ├── FrameWindowHelper.h
│ ├── HookHelper.cpp
│ ├── HookHelper.h
│ ├── IconHelper.cpp
│ ├── IconHelper.h
│ ├── ImageIconCache.cpp
│ ├── ImageIconCache.h
│ ├── Interfaces.h
│ ├── MainFrm.cpp
│ ├── MainFrm.h
│ ├── MessageDecoder.cpp
│ ├── MessageDecoder.h
│ ├── MessagesView.cpp
│ ├── MessagesView.h
│ ├── ProcessHelper.cpp
│ ├── ProcessHelper.h
│ ├── ProcessesView.cpp
│ ├── ProcessesView.h
│ ├── SecurityHelper.cpp
│ ├── SecurityHelper.h
│ ├── TreeViewManager.h
│ ├── ViewBase.h
│ ├── WinSpy.cpp
│ ├── WinSpy.h
│ ├── WinSpy.rc
│ ├── WinSpy.vcxproj
│ ├── WinSpy.vcxproj.filters
│ ├── WindowGeneralPage.cpp
│ ├── WindowGeneralPage.h
│ ├── WindowHelper.cpp
│ ├── WindowHelper.h
│ ├── WindowWindowsPage.cpp
│ ├── WindowWindowsPage.h
│ ├── WindowsListView.cpp
│ ├── WindowsListView.h
│ ├── WindowsView.cpp
│ ├── WindowsView.h
│ ├── pch.cpp
│ ├── pch.h
│ └── resource.h
├── WinSpy.sln
└── WinSpyHook/
├── WinSpyHook.def
├── WinSpyHook.vcxproj
├── WinSpyHook.vcxproj.filters
├── dllmain.cpp
├── hooks.cpp
├── hooks.h
├── pch.cpp
└── pch.h
SYMBOL INDEX (193 symbols across 38 files)
FILE: WinSpy/AboutDlg.cpp
function LRESULT (line 10) | LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM...
function LRESULT (line 15) | LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWn...
FILE: WinSpy/AutomationTreeView.cpp
function LRESULT (line 7) | LRESULT CAutomationTreeView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, ...
function LRESULT (line 31) | LRESULT CAutomationTreeView::OnNodeExpanding(int, LPNMHDR hdr, BOOL&) {
function LRESULT (line 48) | LRESULT CAutomationTreeView::OnNodeExpanded(int, LPNMHDR hdr, BOOL&) {
function LRESULT (line 70) | LRESULT CAutomationTreeView::OnNodeSelected(int, LPNMHDR hdr, BOOL&) {
function LRESULT (line 78) | LRESULT CAutomationTreeView::OnNodeDeleted(int, LPNMHDR hdr, BOOL&) {
function CString (line 93) | CString CAutomationTreeView::GetColumnText(HWND, int row, int col) const {
function HTREEITEM (line 102) | HTREEITEM CAutomationTreeView::AddElement(IUIAutomationElement* e, HTREE...
FILE: WinSpy/AutomationTreeView.h
type IUIAutomationElement (line 9) | struct IUIAutomationElement
type IUIAutomationTreeWalker (line 10) | struct IUIAutomationTreeWalker
FILE: WinSpy/DialogHelper.h
function AdjustOKCancelButtons (line 7) | void AdjustOKCancelButtons() {
function SetDialogIcon (line 37) | void SetDialogIcon(UINT icon) {
function SetDialogIcon (line 42) | void SetDialogIcon(HICON icon) {
FILE: WinSpy/FindWindowDlg.cpp
function HWND (line 8) | HWND CFindWindowDlg::GetSelectedHwnd() const {
function LRESULT (line 44) | LRESULT CFindWindowDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 54) | LRESULT CFindWindowDlg::OnCloseCmd(WORD, WORD id, HWND, BOOL&) {
function LRESULT (line 71) | LRESULT CFindWindowDlg::OnSearch(WORD, WORD id, HWND, BOOL&) {
function LRESULT (line 100) | LRESULT CFindWindowDlg::OnMouseDown(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 110) | LRESULT CFindWindowDlg::OnMouseUp(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 123) | LRESULT CFindWindowDlg::OnMouseMove(UINT, WPARAM, LPARAM lp, BOOL&) {
FILE: WinSpy/FindWindowDlg.h
function LRESULT (line 39) | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/...
FILE: WinSpy/FormatHelper.cpp
function CString (line 5) | CString FormatHelper::FormatHWndOrNone(HWND hWnd) {
function CString (line 14) | CString FormatHelper::RectToString(CRect const& rc) {
function DWORD_PTR (line 20) | DWORD_PTR FormatHelper::ParseHex(CString const& text) {
function CString (line 32) | CString FormatHelper::FormatPoint(POINT const& pt) {
FILE: WinSpy/FormatHelper.h
type FormatHelper (line 3) | struct FormatHelper {
FILE: WinSpy/FrameWindowHelper.h
function HWND (line 7) | HWND CreateAndInitToolBar(const ToolBarButtonInfo* buttons, int count) {
function BOOL (line 36) | BOOL OnIdle() override {
FILE: WinSpy/HookHelper.h
function abstract (line 5) | struct HookHelper abstract final {
FILE: WinSpy/IconHelper.cpp
function HICON (line 4) | HICON IconHelper::GetShieldIcon() {
function HICON (line 8) | HICON IconHelper::GetStockIcon(SHSTOCKICONID id, bool big) {
FILE: WinSpy/IconHelper.h
type IconHelper (line 3) | struct IconHelper {
FILE: WinSpy/ImageIconCache.cpp
function HIMAGELIST (line 49) | HIMAGELIST ImageIconCache::GetImageList() const {
function ImageIconCache (line 53) | ImageIconCache& ImageIconCache::Get() {
FILE: WinSpy/ImageIconCache.h
type ImageIconCache (line 3) | struct ImageIconCache {
FILE: WinSpy/Interfaces.h
type CMessagesView (line 3) | struct CMessagesView
type IMainFrame (line 5) | struct IMainFrame {
type ToolBarButtonInfo (line 13) | struct ToolBarButtonInfo {
FILE: WinSpy/MainFrm.cpp
function BOOL (line 20) | BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) {
function BOOL (line 27) | BOOL CMainFrame::OnIdle() {
function LRESULT (line 32) | LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*...
function LRESULT (line 83) | LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /...
function LRESULT (line 94) | LRESULT CMainFrame::OnMenuSelect(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 98) | LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND ...
function LRESULT (line 103) | LRESULT CMainFrame::OnViewAllWindows(WORD /*wNotifyCode*/, WORD /*wID*/,...
function LRESULT (line 115) | LRESULT CMainFrame::OnViewAllProcesses(WORD /*wNotifyCode*/, WORD /*wID*...
function LRESULT (line 127) | LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HW...
function LRESULT (line 138) | LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, ...
function LRESULT (line 146) | LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND ...
function LRESULT (line 152) | LRESULT CMainFrame::OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HW...
function LRESULT (line 162) | LRESULT CMainFrame::OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/,...
function LRESULT (line 168) | LRESULT CMainFrame::OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWN...
function LRESULT (line 175) | LRESULT CMainFrame::OnCommandToActiveView(WORD code, WORD id, HWND h, BO...
function LRESULT (line 183) | LRESULT CMainFrame::OnFindWindow(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 192) | LRESULT CMainFrame::OnRunAsAdmin(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 199) | LRESULT CMainFrame::OnTabCloseButton(int, LPNMHDR, BOOL&) {
function LRESULT (line 203) | LRESULT CMainFrame::OnViewAutomationTree(WORD, WORD, HWND, BOOL&) {
function CUpdateUIBase (line 211) | CUpdateUIBase& CMainFrame::GetUIUpdate() {
function UINT (line 215) | UINT CMainFrame::ShowPopupMenu(HMENU hMenu, const POINT& pt, DWORD flags) {
function CMessagesView (line 219) | CMessagesView* CMainFrame::CreateMessagesView() {
function LRESULT (line 295) | LRESULT CMainFrame::OnTabActivated(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOO...
FILE: WinSpy/MessageDecoder.cpp
function CString (line 7) | CString MessageDecoder::Decode(UINT msg, WPARAM wp, LPARAM lp) {
function CString (line 43) | CString MessageDecoder::MouseKey(int key) {
function CString (line 70) | CString MessageDecoder::SysCommandToString(DWORD cmd) {
function CString (line 97) | CString MessageDecoder::SizeParamToString(DWORD type) {
FILE: WinSpy/MessageDecoder.h
function abstract (line 3) | struct MessageDecoder final abstract {
FILE: WinSpy/MessagesView.cpp
function CString (line 57) | CString CMessagesView::GetColumnText(HWND hWnd, int row, int col) const {
function DWORD (line 102) | DWORD CMessagesView::ProcessHook() {
function LRESULT (line 116) | LRESULT CMessagesView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 153) | LRESULT CMessagesView::OnTimer(UINT, WPARAM id, LPARAM, BOOL&) {
function LRESULT (line 167) | LRESULT CMessagesView::OnDestroy(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 179) | LRESULT CHookCallbackWnd::OnHookCallback(UINT msg, WPARAM wp, LPARAM lp,...
FILE: WinSpy/MessagesView.h
type CMessagesView (line 7) | struct CMessagesView
type CHookCallbackWnd (line 9) | struct CHookCallbackWnd
function m_pView (line 10) | m_pView(pView) {}
function MESSAGE_HANDLER (line 12) | BEGIN_MSG_MAP(CHookCallbackWnd)
FILE: WinSpy/ProcessHelper.cpp
function CString (line 7) | CString ProcessHelper::GetProcessImageName(DWORD pid, bool fullPath) {
function ProcessesInfo (line 27) | ProcessesInfo ProcessHelper::EnumProcessesAndThreads(EnumProcessesOption...
FILE: WinSpy/ProcessHelper.h
type ProcessInfo (line 3) | struct ProcessInfo {
function EnumProcessesOptions (line 10) | enum class EnumProcessesOptions {
FILE: WinSpy/ProcessesView.cpp
function LRESULT (line 6) | LRESULT CProcessesView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARA...
function LRESULT (line 33) | LRESULT CProcessesView::OnTimer(UINT /*uMsg*/, WPARAM id, LPARAM /*lPara...
type LocalData (line 66) | struct LocalData {
function CTreeItem (line 90) | CTreeItem CProcessesView::AddNode(HWND hWnd, HTREEITEM hParent) {
function LRESULT (line 142) | LRESULT CProcessesView::OnNodeExpanding(int, LPNMHDR hdr, BOOL&) {
function BOOL (line 167) | BOOL CProcessesView::AddChildNode(HWND hChild) {
function LRESULT (line 174) | LRESULT CProcessesView::OnTreeNodeRightClick(HTREEITEM hItem, CPoint con...
function LRESULT (line 189) | LRESULT CProcessesView::OnWindowShow(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 196) | LRESULT CProcessesView::OnWindowHide(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 202) | LRESULT CProcessesView::OnWindowMinimize(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 208) | LRESULT CProcessesView::OnWindowMaximize(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 215) | LRESULT CProcessesView::OnWindowRestore(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 221) | LRESULT CProcessesView::OnWindowFlash(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 228) | LRESULT CProcessesView::OnWindowBringToFront(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 234) | LRESULT CProcessesView::OnNodeSelected(int, LPNMHDR hdr, BOOL&) {
function LRESULT (line 246) | LRESULT CProcessesView::OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint co...
function LRESULT (line 264) | LRESULT CProcessesView::OnWindowProperties(WORD /*wNotifyCode*/, WORD /*...
function LRESULT (line 270) | LRESULT CProcessesView::OnProcessProperties(WORD /*wNotifyCode*/, WORD /...
function LRESULT (line 301) | LRESULT CProcessesView::OnToggleHiddenWindows(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 308) | LRESULT CProcessesView::OnToggleEmptyTitleWindows(WORD, WORD, HWND, BOOL...
FILE: WinSpy/SecurityHelper.h
function abstract (line 3) | struct SecurityHelper abstract final {
FILE: WinSpy/TreeViewManager.h
function LRESULT (line 31) | LRESULT OnDoubleClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) {
function LRESULT (line 52) | LRESULT OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint const& pt) {
FILE: WinSpy/ViewBase.h
function OnFinalMessage (line 24) | void OnFinalMessage(HWND) override {
function BOOL (line 28) | BOOL OnIdle() override {
function LRESULT (line 33) | LRESULT OnTabActivated(UINT /*uMsg*/, WPARAM wParam, LPARAM, BOOL& bHand...
function OnActivate (line 39) | void OnActivate(bool activate) {}
function LRESULT (line 41) | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL&...
function HWND (line 50) | HWND CreateAndInitToolBar(const ToolBarButtonInfo* buttons, int count) {
FILE: WinSpy/WinSpy.cpp
function Run (line 11) | int Run(LPCTSTR /*lpstrCmdLine*/ = nullptr, int nCmdShow = SW_SHOWDEFAUL...
function _tWinMain (line 30) | int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, L...
FILE: WinSpy/WindowGeneralPage.cpp
function LRESULT (line 111) | LRESULT CWindowGeneralPage::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 117) | LRESULT CWindowGeneralPage::OnUpdate(UINT, WPARAM, LPARAM lp, BOOL&) {
FILE: WinSpy/WindowGeneralPage.h
type StyleItem (line 5) | struct StyleItem
function m_Win (line 15) | CWindowGeneralPage(HWND hWnd) : m_Win(hWnd) {
FILE: WinSpy/WindowHelper.cpp
function CString (line 13) | CString WindowHelper::WindowStyleToString(HWND hWnd) {
function CString (line 28) | CString WindowHelper::ClassStyleToString(HWND hWnd) {
function CString (line 44) | CString WindowHelper::WindowExtendedStyleToString(HWND hWnd) {
function CString (line 61) | CString WindowHelper::WindowRectToString(HWND hWnd) {
function CString (line 68) | CString WindowHelper::GetWindowClassName(HWND hWnd) {
function CString (line 74) | CString WindowHelper::GetWindowText(HWND hWnd) {
function HICON (line 80) | HICON WindowHelper::GetWindowOrProcessIcon(HWND hWnd) {
function HICON (line 126) | HICON WindowHelper::GetWindowIcon(HWND hWnd) {
function CString (line 135) | CString WindowHelper::GetWindowClassAndTitle(HWND hWnd) {
function CImageList (line 155) | CImageList& WindowHelper::GetImageList() {
function WindowItem (line 164) | WindowItem WindowHelper::GetWindowInfo(HWND hWnd) {
function CString (line 537) | CString WindowHelper::WindowMessageToString(DWORD msg) {
function ULONG_PTR (line 785) | ULONG_PTR WindowHelper::GetID(HWND hWnd) {
function ULONG_PTR (line 789) | ULONG_PTR WindowHelper::GetUserData(HWND hWnd) {
FILE: WinSpy/WindowHelper.h
type WindowItem (line 3) | struct WindowItem {
type StyleItem (line 10) | struct StyleItem {
function abstract (line 16) | struct WindowHelper abstract final {
FILE: WinSpy/WindowWindowsPage.cpp
function LRESULT (line 34) | LRESULT CWindowWindowsPage::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 40) | LRESULT CWindowWindowsPage::OnClickHandle(int, LPNMHDR hdr, BOOL&) {
FILE: WinSpy/WindowsListView.cpp
function LRESULT (line 13) | LRESULT CWindowsListView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
function LRESULT (line 61) | LRESULT CWindowsListView::OnWindowShow(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 68) | LRESULT CWindowsListView::OnWindowHide(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 74) | LRESULT CWindowsListView::OnWindowMinimize(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 80) | LRESULT CWindowsListView::OnWindowMaximize(WORD, WORD, HWND, BOOL&) {
function CString (line 87) | CString CWindowsListView::GetColumnText(HWND, int row, int col) const {
function DWORD (line 229) | DWORD CWindowsListView::OnPrePaint(int, LPNMCUSTOMDRAW cd) {
function DWORD (line 236) | DWORD CWindowsListView::OnItemPrePaint(int, LPNMCUSTOMDRAW cd) {
type LocalInfo (line 316) | struct LocalInfo {
function CString (line 335) | CString CWindowsListView::GetDetails(const DataItem& item) const {
function LRESULT (line 373) | LRESULT CWindowsListView::OnToggleEmptyTitleWindows(WORD, WORD, HWND, BO...
function LRESULT (line 380) | LRESULT CWindowsListView::OnToggleChildWindows(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 387) | LRESULT CWindowsListView::OnWindowRestore(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 393) | LRESULT CWindowsListView::OnWindowBringToFront(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 399) | LRESULT CWindowsListView::OnWindowProperties(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 405) | LRESULT CWindowsListView::OnItemChanged(int, LPNMHDR, BOOL&) {
function LRESULT (line 410) | LRESULT CWindowsListView::OnWindowFlash(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 417) | LRESULT CWindowsListView::OnToggleHiddenWindows(WORD, WORD, HWND, BOOL&) {
FILE: WinSpy/WindowsListView.h
function m_pFrame (line 15) | m_pFrame(frame) {}
type class (line 35) | enum class
type DataItem (line 41) | struct DataItem {
FILE: WinSpy/WindowsView.cpp
function BOOL (line 15) | BOOL CWindowsView::PreTranslateMessage(MSG* pMsg) {
function LRESULT (line 51) | LRESULT CWindowsView::OnRefreshAll(WORD /*wNotifyCode*/, WORD /*wID*/, H...
function CTreeItem (line 100) | CTreeItem CWindowsView::AddNode(HWND hWnd, HTREEITEM hParent) {
function BOOL (line 155) | BOOL CWindowsView::AddChildNode(HWND hChild) {
function LRESULT (line 162) | LRESULT CWindowsView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM ...
function LRESULT (line 198) | LRESULT CWindowsView::OnTimer(UINT, WPARAM id, LPARAM, BOOL&) {
function LRESULT (line 226) | LRESULT CWindowsView::OnNodeExpanding(int, LPNMHDR hdr, BOOL&) {
function LRESULT (line 240) | LRESULT CWindowsView::OnNodeDeleted(int, LPNMHDR hdr, BOOL&) {
function LRESULT (line 248) | LRESULT CWindowsView::OnNodeSelected(int, LPNMHDR hdr, BOOL&) {
function LRESULT (line 263) | LRESULT CWindowsView::OnWindowShow(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 270) | LRESULT CWindowsView::OnWindowHide(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 276) | LRESULT CWindowsView::OnWindowClose(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 282) | LRESULT CWindowsView::OnWindowMinimize(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 288) | LRESULT CWindowsView::OnWindowMaximize(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 295) | LRESULT CWindowsView::OnWindowRestore(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 301) | LRESULT CWindowsView::OnWindowBringToFront(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 307) | LRESULT CWindowsView::OnRefresh(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 312) | LRESULT CWindowsView::OnToggleHiddenWindows(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 319) | LRESULT CWindowsView::OnToggleEmptyTitleWindows(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 326) | LRESULT CWindowsView::OnToggleChildWindows(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 333) | LRESULT CWindowsView::OnTreeNodeRightClick(HTREEITEM hItem, CPoint const...
function LRESULT (line 344) | LRESULT CWindowsView::OnWindowFlash(WORD, WORD, HWND, BOOL&) {
function LRESULT (line 351) | LRESULT CWindowsView::OnWindowHighlight(WORD /*wNotifyCode*/, WORD /*wID...
function LRESULT (line 366) | LRESULT CWindowsView::OnWindowProperties(WORD /*wNotifyCode*/, WORD /*wI...
function LRESULT (line 378) | LRESULT CWindowsView::OnTreeNodeDoubleClick(HTREEITEM hItem, CPoint cons...
function LRESULT (line 383) | LRESULT CWindowsView::OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARA...
function CTreeItem (line 388) | CTreeItem CWindowsView::AddMessageOnlyWindows() {
function LRESULT (line 394) | LRESULT CWindowsView::OnCaptureMessages(WORD /*wNotifyCode*/, WORD /*wID...
FILE: WinSpyHook/dllmain.cpp
function BOOL (line 6) | BOOL WINAPI DllMain(HMODULE hModule, DWORD reason, PVOID lpReserved) {
FILE: WinSpyHook/hooks.cpp
type HookEntry (line 6) | struct HookEntry {
function IsNotify (line 20) | bool IsNotify(HWND hTarget, HookEntry const& entry) {
function LRESULT (line 33) | LRESULT WINAPI HookFunc3(int code, WPARAM wParam, LPARAM lParam) {
function LRESULT (line 58) | LRESULT WINAPI HookFunc4(int code, WPARAM wParam, LPARAM lParam) {
function LRESULT (line 63) | LRESULT WINAPI HookFunc12(int code, WPARAM wParam, LPARAM lParam) {
function AddHook (line 68) | bool WINAPI AddHook(DWORD hookType, HookConfig const& config) {
function RemoveHook (line 99) | bool WINAPI RemoveHook(DWORD tid) {
FILE: WinSpyHook/hooks.h
function HookOptions (line 5) | enum class HookOptions {
Condensed preview — 63 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (248K chars).
[
{
"path": ".gitattributes",
"chars": 2518,
"preview": "###############################################################################\n# Set default behavior to automatically "
},
{
"path": ".gitignore",
"chars": 5745,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
},
{
"path": ".gitmodules",
"chars": 91,
"preview": "[submodule \"WTLHelper\"]\n\tpath = WTLHelper\n\turl = https://github.com/zodiacon/WTLHelper.git\n"
},
{
"path": "LICENSE",
"chars": 1073,
"preview": "MIT License\n\nCopyright (c) 2021 Pavel Yosifovich\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "README.md",
"chars": 59,
"preview": "# WinSpy\n\nEnhanced version of the classic Spy++ tool (WIP)\n"
},
{
"path": "WinSpy/AboutDlg.cpp",
"chars": 485,
"preview": "// aboutdlg.cpp : implementation of the CAboutDlg class\n//\n/////////////////////////////////////////////////////////////"
},
{
"path": "WinSpy/AboutDlg.h",
"chars": 933,
"preview": "// aboutdlg.h : interface of the CAboutDlg class\n//\n////////////////////////////////////////////////////////////////////"
},
{
"path": "WinSpy/AutomationTreeView.cpp",
"chars": 8459,
"preview": "#include \"pch.h\"\n#include \"AutomationTreeView.h\"\n#include \"WindowHelper.h\"\n\n#pragma comment(lib, \"oleacc\")\n\nLRESULT CAut"
},
{
"path": "WinSpy/AutomationTreeView.h",
"chars": 2385,
"preview": "#pragma once\n\n#include \"ViewBase.h\"\n#include <TreeViewHelper.h>\n#include <VirtualListView.h>\n#include <CustomSplitterWin"
},
{
"path": "WinSpy/DialogHelper.h",
"chars": 1153,
"preview": "#pragma once\n\ntemplate<typename T>\nclass CDialogHelper {\npublic:\n#ifdef IDI_OK\n\tvoid AdjustOKCancelButtons() {\n\t\tauto dl"
},
{
"path": "WinSpy/FindWindowDlg.cpp",
"chars": 4040,
"preview": "#include \"pch.h\"\n#include \"resource.h\"\n#include \"FindWindowDlg.h\"\n#include \"WindowHelper.h\"\n#include \"ProcessHelper.h\"\n#"
},
{
"path": "WinSpy/FindWindowDlg.h",
"chars": 1929,
"preview": "#pragma once\n\n#include \"Interfaces.h\"\n#include \"DialogHelper.h\"\n\nclass CFindWindowDlg : \n\tpublic CDialogImpl<CFindWindow"
},
{
"path": "WinSpy/FormatHelper.cpp",
"chars": 790,
"preview": "#include \"pch.h\"\n#include \"FormatHelper.h\"\n#include <sstream>\n\nCString FormatHelper::FormatHWndOrNone(HWND hWnd) {\n\tCStr"
},
{
"path": "WinSpy/FormatHelper.h",
"chars": 227,
"preview": "#pragma once\n\nstruct FormatHelper {\n\tstatic CString FormatHWndOrNone(HWND hWnd);\n\tstatic CString RectToString(CRect cons"
},
{
"path": "WinSpy/FrameWindowHelper.h",
"chars": 1171,
"preview": "#pragma once\n\n#include \"Interfaces.h\"\n\ntemplate<typename T>\nstruct CFrameWindowHelper : CIdleHandler {\n\tHWND CreateAndIn"
},
{
"path": "WinSpy/HookHelper.cpp",
"chars": 748,
"preview": "#include \"pch.h\"\n#include \"HookHelper.h\"\n\ndecltype(AddHook)* pAddHook;\ndecltype(RemoveHook)* pRemoveHook;\n\nbool HookHelp"
},
{
"path": "WinSpy/HookHelper.h",
"chars": 216,
"preview": "#pragma once\n\n#include \"hooks.h\"\n\nstruct HookHelper abstract final {\n\tstatic bool InitHookLib();\n\tstatic bool WINAPI Add"
},
{
"path": "WinSpy/IconHelper.cpp",
"chars": 348,
"preview": "#include \"pch.h\"\n#include \"IconHelper.h\"\n\nHICON IconHelper::GetShieldIcon() {\n\treturn GetStockIcon(SIID_SHIELD);\n}\n\nHICO"
},
{
"path": "WinSpy/IconHelper.h",
"chars": 132,
"preview": "#pragma once\n\nstruct IconHelper {\n\tstatic HICON GetStockIcon(SHSTOCKICONID id, bool big = false);\n\tstatic HICON GetShiel"
},
{
"path": "WinSpy/ImageIconCache.cpp",
"chars": 1236,
"preview": "#include \"pch.h\"\n#include \"ImageIconCache.h\"\n#include \"resource.h\"\n\nint ImageIconCache::GetIcon(const CString& path, HIC"
},
{
"path": "WinSpy/ImageIconCache.h",
"chars": 545,
"preview": "#pragma once\n\nstruct ImageIconCache {\n\tstatic ImageIconCache& Get();\n\n\tHIMAGELIST GetImageList() const;\n\tvoid SetImageLi"
},
{
"path": "WinSpy/Interfaces.h",
"chars": 414,
"preview": "#pragma once\n\nstruct CMessagesView;\n\nstruct IMainFrame {\n\tvirtual CUpdateUIBase& GetUIUpdate() = 0;\n\tvirtual UINT ShowPo"
},
{
"path": "WinSpy/MainFrm.cpp",
"chars": 8851,
"preview": "// MainFrm.cpp : implmentation of the CMainFrame class\n//\n//////////////////////////////////////////////////////////////"
},
{
"path": "WinSpy/MainFrm.h",
"chars": 4210,
"preview": "// MainFrm.h : interface of the CMainFrame class\n//\n////////////////////////////////////////////////////////////////////"
},
{
"path": "WinSpy/MessageDecoder.cpp",
"chars": 2955,
"preview": "#include \"pch.h\"\n#include \"MessageDecoder.h\"\n#include \"FormatHelper.h\"\n\n#define CASE_STR(x) case x: return L#x \n\nCString"
},
{
"path": "WinSpy/MessageDecoder.h",
"chars": 240,
"preview": "#pragma once\n\nstruct MessageDecoder final abstract {\n\tstatic CString Decode(UINT msg, WPARAM wp, LPARAM lp);\n\tstatic CSt"
},
{
"path": "WinSpy/MessagesView.cpp",
"chars": 5175,
"preview": "#include \"pch.h\"\n#include \"MessagesView.h\"\n#include \"hooks.h\"\n#include \"FormatHelper.h\"\n#include \"WindowHelper.h\"\n#inclu"
},
{
"path": "WinSpy/MessagesView.h",
"chars": 2155,
"preview": "#pragma once\n\n#include \"ViewBase.h\"\n#include \"VirtualListView.h\"\n#include \"hooks.h\"\n\nstruct CMessagesView;\n\nstruct CHook"
},
{
"path": "WinSpy/ProcessHelper.cpp",
"chars": 3649,
"preview": "#include \"pch.h\"\n#include \"ProcessHelper.h\"\n#include \"WindowHelper.h\"\n#include <TlHelp32.h>\n#include <unordered_set>\n\nCS"
},
{
"path": "WinSpy/ProcessHelper.h",
"chars": 754,
"preview": "#pragma once\n\nstruct ProcessInfo {\n\tDWORD ProcessId;\n\tstd::vector<DWORD> Threads;\n\tCString ProcessName;\n\tCString FullPat"
},
{
"path": "WinSpy/ProcessesView.cpp",
"chars": 8848,
"preview": "#include \"pch.h\"\n#include \"resource.h\"\n#include \"ProcessesView.h\"\n#include \"ImageIconCache.h\"\n\nLRESULT CProcessesView::O"
},
{
"path": "WinSpy/ProcessesView.h",
"chars": 4154,
"preview": "#pragma once\n\n#include \"ViewBase.h\"\n#include \"WindowsListView.h\"\n#include \"TreeViewManager.h\"\n#include \"ProcessHelper.h\""
},
{
"path": "WinSpy/SecurityHelper.cpp",
"chars": 1363,
"preview": "#include \"pch.h\"\n#include \"SecurityHelper.h\"\n\nbool SecurityHelper::IsRunningElevated() {\n\tstatic bool runningElevated = "
},
{
"path": "WinSpy/SecurityHelper.h",
"chars": 185,
"preview": "#pragma once\n\nstruct SecurityHelper abstract final {\n\tstatic bool IsRunningElevated();\n\tstatic bool RunElevated();\n\tstat"
},
{
"path": "WinSpy/TreeViewManager.h",
"chars": 1300,
"preview": "#pragma once\n\ntemplate<typename T>\nclass CTreeViewManager {\nprotected:\n\tBEGIN_MSG_MAP(CTreeViewManager)\n\t\tNOTIFY_CODE_HA"
},
{
"path": "WinSpy/ViewBase.h",
"chars": 2062,
"preview": "#pragma once\n\n#include \"Interfaces.h\"\n\ntemplate<typename T, typename TBase = CFrameWindowImpl<T, CWindow, CControlWinTra"
},
{
"path": "WinSpy/WinSpy.cpp",
"chars": 1005,
"preview": "// WinSpy.cpp : main source file for WinSpy.exe\n//\n\n#include \"pch.h\"\n#include \"resource.h\"\n#include \"MainFrm.h\"\n#include"
},
{
"path": "WinSpy/WinSpy.h",
"chars": 12,
"preview": "// WinSpy.h\n"
},
{
"path": "WinSpy/WinSpy.rc",
"chars": 21034,
"preview": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////"
},
{
"path": "WinSpy/WinSpy.vcxproj",
"chars": 21514,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msb"
},
{
"path": "WinSpy/WinSpy.vcxproj.filters",
"chars": 7853,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
},
{
"path": "WinSpy/WindowGeneralPage.cpp",
"chars": 4350,
"preview": "#include \"pch.h\"\n#include \"resource.h\"\n#include \"WindowGeneralPage.h\"\n#include \"FormatHelper.h\"\n#include \"ProcessHelper."
},
{
"path": "WinSpy/WindowGeneralPage.h",
"chars": 1229,
"preview": "#pragma once\n\n#include \"DialogHelper.h\"\n\nstruct StyleItem;\n\nclass CWindowGeneralPage :\n\tpublic CDialogHelper<CWindowGene"
},
{
"path": "WinSpy/WindowHelper.cpp",
"chars": 21688,
"preview": "#include \"pch.h\"\n#include \"resource.h\"\n#include \"WindowHelper.h\"\n#include \"ProcessHelper.h\"\n#include \"FormatHelper.h\"\n#i"
},
{
"path": "WinSpy/WindowHelper.h",
"chars": 2196,
"preview": "#pragma once\n\nstruct WindowItem {\n\tHWND hWnd;\n\tDWORD ThreadId;\n\tDWORD ProcessId;\n\tCString ProcessName;\n};\n\nstruct StyleI"
},
{
"path": "WinSpy/WindowWindowsPage.cpp",
"chars": 1592,
"preview": "#include \"pch.h\"\n#include \"resource.h\"\n#include \"WindowWindowsPage.h\"\n#include \"FormatHelper.h\"\n\nconst UINT WM_UPDATE = "
},
{
"path": "WinSpy/WindowWindowsPage.h",
"chars": 1044,
"preview": "#pragma once\n\n#include \"DialogHelper.h\"\n\nclass CWindowWindowsPage :\n\tpublic CDialogHelper<CWindowWindowsPage>,\n\tpublic C"
},
{
"path": "WinSpy/WindowsListView.cpp",
"chars": 14611,
"preview": "#include \"pch.h\"\n#include \"resource.h\"\n#include \"WindowsListView.h\"\n#include \"FormatHelper.h\"\n#include \"SortHelper.h\"\n#i"
},
{
"path": "WinSpy/WindowsListView.h",
"chars": 4388,
"preview": "#pragma once\n\n#include <VirtualListView.h>\n#include \"Interfaces.h\"\n#include \"WindowHelper.h\"\n#include \"ProcessHelper.h\"\n"
},
{
"path": "WinSpy/WindowsView.cpp",
"chars": 10355,
"preview": "// View.cpp : implementation of the CWindowsView class\n//\n//////////////////////////////////////////////////////////////"
},
{
"path": "WinSpy/WindowsView.h",
"chars": 5268,
"preview": "// View.h : interface of the CView class\n//\n////////////////////////////////////////////////////////////////////////////"
},
{
"path": "WinSpy/pch.cpp",
"chars": 194,
"preview": "// stdafx.cpp : source file that includes just the standard includes\n//\tWinSpy.pch will be the pre-compiled header\n//\tst"
},
{
"path": "WinSpy/pch.h",
"chars": 1636,
"preview": "// stdafx.h : include file for standard system include files,\n// or project specific include files that are used freque"
},
{
"path": "WinSpy/resource.h",
"chars": 4578,
"preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by WinSpy.rc\n//\n#define IDD_ABOUTBOX "
},
{
"path": "WinSpy.sln",
"chars": 5631,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.3.3251"
},
{
"path": "WinSpyHook/WinSpyHook.def",
"chars": 98,
"preview": "LIBRARY\nEXPORTS\n\tHookFunc3\t\tPRIVATE\n\tHookFunc4\t\tPRIVATE\n\tHookFunc12\t\tPRIVATE\n\tAddHook\n\tRemoveHook\n"
},
{
"path": "WinSpyHook/WinSpyHook.vcxproj",
"chars": 13333,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msb"
},
{
"path": "WinSpyHook/WinSpyHook.vcxproj.filters",
"chars": 1447,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
},
{
"path": "WinSpyHook/dllmain.cpp",
"chars": 320,
"preview": "// dllmain.cpp : Defines the entry point for the DLL application.\n#include \"pch.h\"\n\nHINSTANCE g_hInstDll;\n\nBOOL WINAPI D"
},
{
"path": "WinSpyHook/hooks.cpp",
"chars": 2882,
"preview": "#include \"pch.h\"\n#include \"hooks.h\"\n\nconst unsigned MaxHooks = 8;\n\nstruct HookEntry {\n\tHHOOK hHook;\n\tHWND CallbackWnd;\n\t"
},
{
"path": "WinSpyHook/hooks.h",
"chars": 498,
"preview": "#pragma once\n\nconst UINT WM_HOOKCALLBACK = WM_USER + 333;\n\nenum class HookOptions {\n\tNone = 0,\n\tWindow = 1,\n\tChildWindow"
},
{
"path": "WinSpyHook/pch.cpp",
"chars": 186,
"preview": "// pch.cpp: source file corresponding to the pre-compiled header\n\n#include \"pch.h\"\n\n// When you are using pre-compiled h"
},
{
"path": "WinSpyHook/pch.h",
"chars": 610,
"preview": "// pch.h: This is a precompiled header file.\n// Files listed below are compiled only once, improving build performance f"
}
]
About this extraction
This page contains the full source code of the zodiacon/WinSpy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 63 files (224.8 KB), approximately 67.5k tokens, and a symbol index with 193 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.