├── .clang-format
├── .editorconfig
├── .gitignore
├── .gitmodules
├── .tgitconfig
├── README.md
├── SendMessage.sln
├── azure-pipelines.yml
├── default.build
├── default.build.user.tmpl
├── src
├── AboutDlg.cpp
├── AboutDlg.h
├── AccessibleName.h
├── MainDlg.cpp
├── MainDlg.h
├── SendMessage.cpp
├── SendMessage.h
├── SendMessage.rc
├── SendMessage.rc2
├── SendMessage.vcxproj
├── SendMessage.vcxproj.filters
├── WinMessage.cpp
├── WinMessage.h
├── WindowTreeDlg.cpp
├── WindowTreeDlg.h
├── XMLite.cpp
├── XMLite.h
├── auto_buffer.h
├── compatibility.manifest
├── last
│ └── version.h
├── resource.h
├── resources
│ ├── SendMessage.ico
│ ├── searchw.cur
│ ├── searchw.ico
│ └── windowmessages.xml
├── stdafx.cpp
├── stdafx.h
└── version.in
├── tools
├── checkyear.js
└── coverity.bat
├── version.build.in
└── versioninfo.build
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | AccessModifierOffset: -4
4 | AlignAfterOpenBracket: Align
5 | AlignConsecutiveAssignments: AcrossEmptyLinesAndComments
6 | AlignConsecutiveBitFields: AcrossEmptyLinesAndComments
7 | AlignConsecutiveDeclarations: AcrossEmptyLinesAndComments
8 | AlignConsecutiveMacros: AcrossEmptyLinesAndComments
9 | AlignEscapedNewlines: Right
10 | AlignOperands: true
11 | AlignTrailingComments: true
12 | AllowAllParametersOfDeclarationOnNextLine: true
13 | AllowShortBlocksOnASingleLine: false
14 | AllowShortCaseLabelsOnASingleLine: false
15 | AllowShortFunctionsOnASingleLine: All
16 | AllowShortIfStatementsOnASingleLine: false
17 | AllowShortLoopsOnASingleLine: false
18 | AlwaysBreakAfterDefinitionReturnType: None
19 | AlwaysBreakAfterReturnType: None
20 | AlwaysBreakBeforeMultilineStrings: false
21 | AlwaysBreakTemplateDeclarations: false
22 | BinPackArguments: true
23 | BinPackParameters: true
24 | BraceWrapping:
25 | AfterClass: true
26 | AfterControlStatement: true
27 | AfterEnum: true
28 | AfterFunction: true
29 | AfterNamespace: true
30 | AfterObjCDeclaration: true
31 | AfterStruct: true
32 | AfterUnion: true
33 | BeforeCatch: true
34 | BeforeElse: true
35 | IndentBraces: false
36 | SplitEmptyFunction: true
37 | SplitEmptyRecord: true
38 | SplitEmptyNamespace: true
39 | BreakBeforeBinaryOperators: None
40 | BreakBeforeBraces: Custom
41 | BreakBeforeInheritanceComma: true
42 | BreakBeforeTernaryOperators: true
43 | BreakConstructorInitializersBeforeComma: true
44 | BreakConstructorInitializers: BeforeColon
45 | BreakAfterJavaFieldAnnotations: false
46 | BreakStringLiterals: true
47 | ColumnLimit: 0
48 | CommentPragmas: '^ IWYU pragma:'
49 | CompactNamespaces: false
50 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
51 | ConstructorInitializerIndentWidth: 4
52 | ContinuationIndentWidth: 4
53 | Cpp11BracedListStyle: true
54 | DerivePointerAlignment: true
55 | DisableFormat: false
56 | ExperimentalAutoDetectBinPacking: false
57 | FixNamespaceComments: true
58 | ForEachMacros:
59 | - foreach
60 | - Q_FOREACH
61 | - BOOST_FOREACH
62 | IncludeCategories:
63 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
64 | Priority: 2
65 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
66 | Priority: 3
67 | - Regex: '.*'
68 | Priority: 1
69 | IncludeIsMainRegex: '(Test)?$'
70 | IndentCaseLabels: true
71 | #IndentPPDirectives: AfterHash
72 | IndentWidth: 4
73 | IndentWrappedFunctionNames: true
74 | JavaScriptQuotes: Leave
75 | JavaScriptWrapImports: true
76 | KeepEmptyLinesAtTheStartOfBlocks: false
77 | MacroBlockBegin: "^\
78 | BEGIN_MSG_MAP|\
79 | BEGIN_MESSAGE_MAP|\
80 | BEGIN_MSG_MAP_EX|\
81 | BEGIN_MESSAGE_MAP_EX|\
82 | BEGIN_SAFE_MSG_MAP_EX|\
83 | CR_BEGIN_MSG_MAP_EX|\
84 | IPC_BEGIN_MESSAGE_MAP|\
85 | IPC_BEGIN_MESSAGE_MAP_WITH_PARAM|\
86 | IPC_PROTOBUF_MESSAGE_TRAITS_BEGIN|\
87 | IPC_STRUCT_BEGIN|\
88 | IPC_STRUCT_BEGIN_WITH_PARENT|\
89 | IPC_STRUCT_TRAITS_BEGIN|\
90 | POLPARAMS_BEGIN|\
91 | PPAPI_BEGIN_MESSAGE_MAP$"
92 | MacroBlockEnd: "^\
93 | CR_END_MSG_MAP|\
94 | END_MSG_MAP|\
95 | END_MESSAGE_MAP|\
96 | IPC_END_MESSAGE_MAP|\
97 | IPC_PROTOBUF_MESSAGE_TRAITS_END|\
98 | IPC_STRUCT_END|\
99 | IPC_STRUCT_TRAITS_END|\
100 | POLPARAMS_END|\
101 | PPAPI_END_MESSAGE_MAP$"
102 | MaxEmptyLinesToKeep: 1
103 | NamespaceIndentation: None
104 | ObjCBlockIndentWidth: 2
105 | ObjCSpaceAfterProperty: false
106 | ObjCSpaceBeforeProtocolList: true
107 | PenaltyBreakAssignment: 2
108 | PenaltyBreakBeforeFirstCallParameter: 19
109 | PenaltyBreakComment: 300
110 | PenaltyBreakFirstLessLess: 120
111 | PenaltyBreakString: 1000
112 | PenaltyExcessCharacter: 1000000
113 | PenaltyReturnTypeOnItsOwnLine: 60
114 | PointerAlignment: Left
115 | ReflowComments: true
116 | SortIncludes: false
117 | SortUsingDeclarations: true
118 | SpaceAfterCStyleCast: false
119 | SpaceAfterTemplateKeyword: true
120 | SpaceBeforeAssignmentOperators: true
121 | SpaceBeforeParens: ControlStatements
122 | SpaceInEmptyParentheses: false
123 | SpacesBeforeTrailingComments: 1
124 | SpacesInAngles: false
125 | SpacesInContainerLiterals: false
126 | SpacesInCStyleCastParentheses: false
127 | SpacesInParentheses: false
128 | SpacesInSquareBrackets: false
129 | Standard: Cpp11
130 | TabWidth: 4
131 | UseTab: Never
132 | ...
133 |
134 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{cpp,cxx,h,hpp,c,txt,build}]
2 | end_of_line = crlf
3 | indent_style = space
4 | indent_size = 4
5 | charset = utf-8-bom
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /default.build.user
2 | /src/SendMessage.vcxproj.user
3 | /src/version.h
4 | /version.build
5 | /bin
6 | /obj
7 | /.vs
8 | /signinfo.txt
9 | /_ReSharper.Caches
10 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "sktoolslib"]
2 | path = sktoolslib
3 | url = https://github.com/stefankueng/sktoolslib.git
4 |
--------------------------------------------------------------------------------
/.tgitconfig:
--------------------------------------------------------------------------------
1 | [hook "precommit"]
2 | cmdline = WScript %root%\\\\tools\\\\checkyear.js
3 | wait = true
4 | show = false
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SendMessage
2 | SendMessage is a little tool to send Windows messages to any window.
3 |
4 | [](https://tortoisesvn.visualstudio.com/tortoisesvnGitHub/_build/latest?definitionId=9)
5 |
6 | Ever wondered how you should test whether your application correctly
7 | responds to certain system messages like WM_ENDSESSION or WM_POWERBROADCAST?
8 | Of course you can test your application by actually triggering those messages,
9 | but especially the WM_ENDSESSION message and its purpose makes it impossible
10 | to attach a debugger to your application once Windows sends you that message.
11 |
12 | With this tool, you can send that message and any other message you
13 | like to your application window. And you can do that while you have
14 | a debugger attached to your application!
15 |
16 | Please visit the [homepage](https://tools.stefankueng.com/SendMessage.html) of SendMessage for more information.
17 |
--------------------------------------------------------------------------------
/SendMessage.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 17
3 | VisualStudioVersion = 17.0.32002.185
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SendMessage", "src\SendMessage.vcxproj", "{D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Win32 = Debug|Win32
10 | Debug|x64 = Debug|x64
11 | Release|Win32 = Release|Win32
12 | Release|x64 = Release|x64
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Debug|Win32.ActiveCfg = Debug|Win32
16 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Debug|Win32.Build.0 = Debug|Win32
17 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Debug|x64.ActiveCfg = Debug|x64
18 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Debug|x64.Build.0 = Debug|x64
19 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Release|Win32.ActiveCfg = Release|Win32
20 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Release|Win32.Build.0 = Release|Win32
21 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Release|x64.ActiveCfg = Release|x64
22 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}.Release|x64.Build.0 = Release|x64
23 | EndGlobalSection
24 | GlobalSection(SolutionProperties) = preSolution
25 | HideSolutionNode = FALSE
26 | EndGlobalSection
27 | GlobalSection(ExtensibilityGlobals) = postSolution
28 | SolutionGuid = {498585C1-D9A2-4A0F-8BB1-AA5B4670C34C}
29 | EndGlobalSection
30 | EndGlobal
31 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # .NET Desktop
2 | # Build and run tests for .NET Desktop or Windows classic desktop solutions.
3 | # Add steps that publish symbols, save build artifacts, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
5 |
6 | pool:
7 | vmImage: 'VS2017-Win2016'
8 |
9 | variables:
10 | solution: '**/*.sln'
11 | buildPlatform: 'x64'
12 | buildConfiguration: 'Release'
13 |
14 | steps:
15 | - task: NuGetToolInstaller@0
16 |
17 | - task: NuGetCommand@2
18 | inputs:
19 | restoreSolution: '$(solution)'
20 |
21 | - task: VSBuild@1
22 | inputs:
23 | solution: '$(solution)'
24 | platform: '$(buildPlatform)'
25 | configuration: '$(buildConfiguration)'
26 |
27 | - task: VSTest@2
28 | inputs:
29 | platform: '$(buildPlatform)'
30 | configuration: '$(buildConfiguration)'
31 |
--------------------------------------------------------------------------------
/default.build:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Sets the environment up to build the debug versions.
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Cleans every subproject.
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | Sets the version information as properties, env variables
52 | and sets up the different version specific files.
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Builds SendMessage.
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/default.build.user.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | You must first call "%VS140COMNTOOLS%\vsvars32.bat"
24 |
25 |
26 |
27 |
28 |
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
52 |
53 |
54 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/AboutDlg.cpp:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010-2013, 2018, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #include "stdafx.h"
21 | #include "resource.h"
22 | #include "AboutDlg.h"
23 | #include "version.h"
24 | #include
25 |
26 | CAboutDlg::CAboutDlg(HWND hParent)
27 | : m_hParent(hParent)
28 | {
29 | }
30 |
31 | CAboutDlg::~CAboutDlg()
32 | {
33 | }
34 |
35 | LRESULT CAboutDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
36 | {
37 | UNREFERENCED_PARAMETER(lParam);
38 | switch (uMsg)
39 | {
40 | case WM_INITDIALOG: {
41 | InitDialog(hwndDlg, IDI_SENDMESSAGE);
42 | TCHAR buf[MAX_PATH] = {0};
43 | _stprintf_s(buf, _countof(buf), _T("SendMessage version %ld.%ld.%ld.%ld"), SM_VERMAJOR, SM_VERMINOR, SM_VERMICRO, SM_VERBUILD);
44 | SetDlgItemText(*this, IDC_VERSIONINFO, buf);
45 | SetDlgItemText(*this, IDC_DATE, _T(SM_VERDATE));
46 | m_link.ConvertStaticToHyperlink(hwndDlg, IDC_WEBLINK, L"https://tools.stefankueng.com");
47 | }
48 | return TRUE;
49 | case WM_COMMAND:
50 | return DoCommand(LOWORD(wParam), HIWORD(wParam));
51 | default:
52 | return FALSE;
53 | }
54 | }
55 |
56 | LRESULT CAboutDlg::DoCommand(int id, int /*msg*/)
57 | {
58 | switch (id)
59 | {
60 | case IDOK:
61 | // fall through
62 | case IDCANCEL:
63 | EndDialog(*this, id);
64 | break;
65 | }
66 | return 1;
67 | }
68 |
--------------------------------------------------------------------------------
/src/AboutDlg.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 | #include "BaseDialog.h"
22 | #include "hyperlink.h"
23 |
24 | class CAboutDlg : public CDialog
25 | {
26 | public:
27 | CAboutDlg(HWND hParent);
28 | ~CAboutDlg() override;
29 |
30 | protected:
31 | LRESULT CALLBACK DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
32 | LRESULT DoCommand(int id, int msg);
33 |
34 | private:
35 | HWND m_hParent;
36 | CHyperLink m_link;
37 | };
38 |
--------------------------------------------------------------------------------
/src/AccessibleName.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2018 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 | #pragma comment(lib, "Oleacc.lib")
22 | class CAccessibleName
23 | {
24 | BSTR m_str;
25 | public:
26 | explicit CAccessibleName(HWND hwnd): m_str(NULL)
27 | {
28 | IAccessible *lpAccessible = NULL;
29 | if (SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void **)&lpAccessible)))
30 | {
31 | VARIANT varChild;
32 | varChild.vt = VT_I4;
33 | varChild.lVal = 0;
34 | lpAccessible->get_accName(varChild, &m_str);
35 | lpAccessible->Release();
36 | }
37 | }
38 | ~CAccessibleName()
39 | {
40 | SysFreeString(m_str);
41 | }
42 | LPCWSTR c_str() const
43 | {
44 | return m_str ? m_str : L"";
45 | }
46 | };
47 |
--------------------------------------------------------------------------------
/src/MainDlg.cpp:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010, 2012-2015, 2018-2019, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #include "stdafx.h"
21 | #include "resource.h"
22 | #include "MainDlg.h"
23 |
24 | #include
25 |
26 | #include "AboutDlg.h"
27 | #include "WindowTreeDlg.h"
28 | #include "WinMessage.h"
29 | #include "AccessibleName.h"
30 | #include "StringUtils.h"
31 |
32 | CMainDlg::CMainDlg(HWND hParent)
33 | : m_hParent(hParent)
34 | , m_bStartSearchWindow(false)
35 | , m_hwndFoundWindow(nullptr)
36 | , m_hRectanglePen(nullptr)
37 | {
38 | }
39 |
40 | CMainDlg::~CMainDlg()
41 | {
42 | }
43 |
44 | LRESULT CMainDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
45 | {
46 | UNREFERENCED_PARAMETER(lParam);
47 | switch (uMsg)
48 | {
49 | case WM_INITDIALOG: {
50 | InitDialog(hwndDlg, IDI_SENDMESSAGE);
51 |
52 | // add an "About" entry to the system menu
53 | HMENU hSysMenu = GetSystemMenu(hwndDlg, FALSE);
54 | if (hSysMenu)
55 | {
56 | int menuItemsCount = GetMenuItemCount(hSysMenu);
57 | if (menuItemsCount > 2)
58 | {
59 | InsertMenu(hSysMenu, menuItemsCount - 2, MF_STRING | MF_BYPOSITION, ID_ABOUTBOX, _T("&About SendMessage..."));
60 | InsertMenu(hSysMenu, menuItemsCount - 2, MF_SEPARATOR | MF_BYPOSITION, NULL, nullptr);
61 | }
62 | else
63 | {
64 | AppendMenu(hSysMenu, MF_SEPARATOR, NULL, nullptr);
65 | AppendMenu(hSysMenu, MF_STRING, ID_ABOUTBOX, _T("&About SendMessage..."));
66 | }
67 |
68 | MENUITEMINFO stItem;
69 | stItem.cbSize = sizeof(MENUITEMINFO);
70 | stItem.fMask = MIIM_STRING;
71 | stItem.dwTypeData = (LPTSTR)TEXT("Always On Top");
72 | SetMenuItemInfo(hSysMenu, SC_MAXIMIZE, FALSE, &stItem);
73 | }
74 | m_link.ConvertStaticToHyperlink(hwndDlg, IDC_ABOUTLINK, _T(""));
75 |
76 | m_hRectanglePen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
77 |
78 | // now fill the window message combo box
79 | for (size_t i = 0; i < WinMessages::Instance().GetCount(); ++i)
80 | {
81 | WinMessage msg = WinMessages::Instance().At(i);
82 | LRESULT index = SendDlgItemMessage(*this, IDC_MESSAGE, CB_ADDSTRING, 0, reinterpret_cast(msg.messagename.c_str()));
83 | SendDlgItemMessage(*this, IDC_MESSAGE, CB_SETITEMDATA, index, msg.message);
84 | }
85 |
86 | WINDOWPLACEMENT wpl = {0};
87 | DWORD size = sizeof(wpl);
88 | if (SHGetValue(HKEY_CURRENT_USER, _T("Software\\SendMessage"), _T("windowpos"), REG_NONE, &wpl, &size) == ERROR_SUCCESS)
89 | SetWindowPlacement(*this, &wpl);
90 | else
91 | ShowWindow(*this, SW_SHOW);
92 |
93 | ExtendFrameIntoClientArea(IDC_SENDGROUP, IDC_SENDGROUP, IDC_SENDGROUP, IDC_SENDGROUP);
94 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDC_SEARCHW));
95 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDC_ABOUTLINK));
96 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDC_POS));
97 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDC_STATIC_X_POS));
98 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDC_STATIC_Y_POS));
99 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDC_EDIT_STATUS));
100 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDC_WINDOWTREE));
101 | m_aerocontrols.SubclassControl(GetDlgItem(*this, IDOK));
102 |
103 | if (HWND hCmdShow = GetDlgItem(*this, IDC_CMDSHOW))
104 | {
105 | ComboBox_AddString(hCmdShow, TEXT("SW_HIDE"));
106 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOWNORMAL"));
107 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOWMINIMIZED"));
108 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOWMAXIMIZED"));
109 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOWNOACTIVATE"));
110 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOW"));
111 | ComboBox_AddString(hCmdShow, TEXT("SW_MINIMIZE"));
112 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOWMINNOACTIVE"));
113 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOWNA"));
114 | ComboBox_AddString(hCmdShow, TEXT("SW_RESTORE"));
115 | ComboBox_AddString(hCmdShow, TEXT("SW_SHOWDEFAULT"));
116 | ComboBox_AddString(hCmdShow, TEXT("SW_FORCEMINIMIZE"));
117 | ComboBox_SetCurSel(hCmdShow, 0);
118 | }
119 | }
120 | return FALSE;
121 | case WM_COMMAND:
122 | return DoCommand(LOWORD(wParam), HIWORD(wParam));
123 | case WM_SYSCOMMAND:
124 | switch (wParam & 0xFFF0)
125 | {
126 | case ID_ABOUTBOX:
127 | CAboutDlg(*this).DoModal(hResource, IDD_ABOUTBOX, *this);
128 | break;
129 | case SC_MINIMIZE:
130 | SetWindowLongPtr(hwndDlg, GWL_STYLE, GetWindowLongPtr(hwndDlg, GWL_STYLE) & ~WS_MAXIMIZE);
131 | break;
132 | case SC_MAXIMIZE:
133 | SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
134 | return TRUE;
135 | case SC_RESTORE:
136 | if (!IsIconic(hwndDlg))
137 | {
138 | SetWindowPos(hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
139 | return TRUE;
140 | }
141 | break;
142 | }
143 | break;
144 | case WM_WINDOWPOSCHANGED:
145 | if (GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & WS_EX_TOPMOST)
146 | SetWindowLongPtr(hwndDlg, GWL_STYLE, GetWindowLongPtr(hwndDlg, GWL_STYLE) | WS_MAXIMIZE);
147 | else
148 | SetWindowLongPtr(hwndDlg, GWL_STYLE, GetWindowLongPtr(hwndDlg, GWL_STYLE) & ~WS_MAXIMIZE);
149 | break;
150 | case WM_MOUSEMOVE:
151 | if (m_bStartSearchWindow)
152 | DoMouseMove(uMsg, wParam, lParam);
153 | break;
154 | case WM_LBUTTONUP:
155 | if (m_bStartSearchWindow)
156 | DoMouseUp(uMsg, wParam, lParam);
157 | break;
158 | case WM_SETCURSOR:
159 | if (m_bStartSearchWindow)
160 | {
161 | SetCursor(LoadCursor(hResource, MAKEINTRESOURCE(IDC_SEARCHW)));
162 | return TRUE;
163 | }
164 | break;
165 | default:
166 | return FALSE;
167 | }
168 | return FALSE;
169 | }
170 |
171 | LRESULT CMainDlg::DoCommand(int id, int msg)
172 | {
173 | switch (id)
174 | {
175 | case IDOK:
176 | case IDCANCEL:
177 | DeleteObject(m_hRectanglePen);
178 | EndDialog(*this, id);
179 | break;
180 | case IDC_SEARCHW:
181 | SearchWindow();
182 | break;
183 | case IDC_WINDOWTREE: {
184 | CWindowTreeDlg treeDlg(*this, GetSelectedHandle());
185 | if (treeDlg.DoModal(hResource, IDD_WINDOWSTREE, *this) == IDOK)
186 | {
187 | m_hwndFoundWindow = treeDlg.GetSelectedWindow();
188 | DisplayInfoOnFoundWindow(m_hwndFoundWindow);
189 | TCHAR szText[256];
190 | _stprintf_s(szText, _countof(szText), _T("0x%p"), m_hwndFoundWindow);
191 | SetDlgItemText(*this, IDC_WINDOW, szText);
192 | }
193 | }
194 | break;
195 | case IDC_SENDMESSAGE:
196 | case IDC_POSTMESSAGE:
197 | if (!SendPostMessage(id))
198 | {
199 | SetDlgItemText(*this, IDC_ERROR, _T("Message not recognized"));
200 | }
201 | break;
202 | case IDC_PINWINDOW:
203 | case IDC_UNPINWINDOW:
204 | if (HWND hWnd = GetSelectedHandle())
205 | {
206 | HWND hWndInsertAfter = id == IDC_PINWINDOW ? HWND_TOPMOST : HWND_NOTOPMOST;
207 | int res = SetWindowPos(hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
208 | TCHAR buf[MAX_PATH]{};
209 | _stprintf_s(buf, _countof(buf), _T("0x%08x (%d)"), res, res);
210 | SetDlgItemText(*this, IDC_RETVALUE, buf);
211 | SetDlgItemText(*this, IDC_ERROR, _T(""));
212 | }
213 | else
214 | {
215 | SetDlgItemText(*this, IDC_RETVALUE, _T(""));
216 | SetDlgItemText(*this, IDC_ERROR, _T("Window not found"));
217 | }
218 | break;
219 | case IDC_SHOWWINDOW:
220 | if (HWND hWnd = GetSelectedHandle())
221 | {
222 | int nCmdShow = ComboBox_GetCurSel(GetDlgItem(*this, IDC_CMDSHOW));
223 | int res = ShowWindow(hWnd, nCmdShow);
224 | TCHAR buf[MAX_PATH]{};
225 | _stprintf_s(buf, _countof(buf), _T("0x%08x (%d)"), res, res);
226 | SetDlgItemText(*this, IDC_RETVALUE, buf);
227 | SetDlgItemText(*this, IDC_ERROR, _T(""));
228 | }
229 | else
230 | {
231 | SetDlgItemText(*this, IDC_RETVALUE, _T(""));
232 | SetDlgItemText(*this, IDC_ERROR, _T("Window not found"));
233 | }
234 | break;
235 | case IDC_ABOUTLINK: {
236 | CAboutDlg dlgAbout(*this);
237 | dlgAbout.DoModal(hResource, IDD_ABOUTBOX, *this);
238 | }
239 | break;
240 | case IDC_MESSAGE: {
241 | switch (msg)
242 | {
243 | case CBN_EDITCHANGE:
244 | case CBN_SELCHANGE: {
245 | // the selected window message has changed, adjust the wparam and lparam comboboxes
246 | LRESULT selIndex = SendDlgItemMessage(*this, IDC_MESSAGE, CB_GETCURSEL, 0, 0);
247 | SendDlgItemMessage(*this, IDC_WPARAM, CB_RESETCONTENT, 0, 0);
248 | SendDlgItemMessage(*this, IDC_LPARAM, CB_RESETCONTENT, 0, 0);
249 | if (selIndex != CB_ERR)
250 | {
251 | LRESULT textlen = SendDlgItemMessage(*this, IDC_MESSAGE, CB_GETLBTEXTLEN, selIndex, 0);
252 | auto textbuf = std::make_unique(textlen + 1);
253 | SendDlgItemMessage(*this, IDC_MESSAGE, CB_GETLBTEXT, selIndex, reinterpret_cast(textbuf.get()));
254 | for (size_t i = 0; i < WinMessages::Instance().GetCount(); ++i)
255 | {
256 | WinMessage wmsg = WinMessages::Instance().At(i);
257 | if (wmsg.messagename.compare(textbuf.get()) == 0)
258 | {
259 | for (size_t j = 0; j < wmsg.wparams.size(); ++j)
260 | {
261 | std::wstring desc = std::get<0>(wmsg.wparams[j]);
262 | LRESULT index = SendDlgItemMessage(*this, IDC_WPARAM, CB_ADDSTRING, 0, reinterpret_cast(desc.c_str()));
263 | SendDlgItemMessage(*this, IDC_WPARAM, CB_SETITEMDATA, index, std::get<1>(wmsg.wparams[j]));
264 | }
265 | for (size_t j = 0; j < wmsg.lparams.size(); ++j)
266 | {
267 | std::wstring desc = std::get<0>(wmsg.lparams[j]);
268 | LRESULT index = SendDlgItemMessage(*this, IDC_LPARAM, CB_ADDSTRING, 0, reinterpret_cast(desc.c_str()));
269 | SendDlgItemMessage(*this, IDC_LPARAM, CB_SETITEMDATA, index, std::get<1>(wmsg.lparams[j]));
270 | }
271 | }
272 | }
273 | }
274 | }
275 | break;
276 | }
277 | }
278 | break;
279 | }
280 | return 1;
281 | }
282 |
283 | void CMainDlg::SaveWndPosition()
284 | {
285 | WINDOWPLACEMENT wpl = {0};
286 | wpl.length = sizeof(WINDOWPLACEMENT);
287 | GetWindowPlacement(*this, &wpl);
288 | SHSetValue(HKEY_CURRENT_USER, _T("Software\\SendMessage"), _T("windowpos"), REG_NONE, &wpl, sizeof(wpl));
289 | }
290 |
291 | bool CMainDlg::PreTranslateMessage(MSG* pMsg)
292 | {
293 | if (pMsg->message == WM_KEYDOWN)
294 | {
295 | }
296 | return false;
297 | }
298 |
299 | bool CMainDlg::SearchWindow()
300 | {
301 | m_bStartSearchWindow = true;
302 | SetCapture(*this);
303 |
304 | return true;
305 | }
306 |
307 | bool CMainDlg::DoMouseMove(UINT /*message*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
308 | {
309 | POINT screenpoint{};
310 | HWND hwndFoundWindow = nullptr;
311 | TCHAR szText[256]{};
312 |
313 | // Must use GetCursorPos() instead of calculating from "lParam".
314 | GetCursorPos(&screenpoint);
315 |
316 | // Display global positioning in the dialog box.
317 | _stprintf_s(szText, _countof(szText), _T("%d"), screenpoint.x);
318 | SetDlgItemText(*this, IDC_STATIC_X_POS, szText);
319 |
320 | _stprintf_s(szText, _countof(szText), _T("%d"), screenpoint.y);
321 | SetDlgItemText(*this, IDC_STATIC_Y_POS, szText);
322 |
323 | // Determine the window that lies underneath the mouse cursor.
324 | hwndFoundWindow = WindowFromPoint(screenpoint);
325 |
326 | if (CheckWindowValidity(hwndFoundWindow))
327 | {
328 | // We have just found a new window.
329 |
330 | // If there was a previously found window, we must instruct it to refresh itself.
331 | // This is done to remove any highlighting effects drawn by us.
332 | if (m_hwndFoundWindow)
333 | {
334 | RefreshWindow(m_hwndFoundWindow);
335 | }
336 |
337 | m_hwndFoundWindow = hwndFoundWindow;
338 |
339 | // Display some information on this found window.
340 | DisplayInfoOnFoundWindow(hwndFoundWindow);
341 |
342 | // We now highlight the found window.
343 | HighlightFoundWindow(m_hwndFoundWindow);
344 | }
345 | SetCursor(LoadCursor(hResource, MAKEINTRESOURCE(IDC_SEARCHW)));
346 |
347 | return true;
348 | }
349 |
350 | bool CMainDlg::DoMouseUp(UINT /*message*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
351 | {
352 | // If there was a found window, refresh it so that its highlighting is erased.
353 | if (m_hwndFoundWindow)
354 | {
355 | RefreshWindow(m_hwndFoundWindow);
356 | }
357 |
358 | ReleaseCapture();
359 |
360 | m_bStartSearchWindow = false;
361 |
362 | if (m_hwndFoundWindow == nullptr)
363 | return false;
364 | if (IsWindow(m_hwndFoundWindow) == FALSE)
365 | return false;
366 | if (m_hwndFoundWindow == *this)
367 | return false;
368 |
369 | HWND hwndTemp = GetParent(m_hwndFoundWindow);
370 | if (hwndTemp == *this)
371 | return false;
372 |
373 | hwndTemp = GetParent(hwndTemp);
374 | if (hwndTemp == *this)
375 | return false;
376 |
377 | TCHAR szText[256]{};
378 | _stprintf_s(szText, _countof(szText), _T("0x%p"), m_hwndFoundWindow);
379 | SetDlgItemText(*this, IDC_WINDOW, szText);
380 |
381 | return true;
382 | }
383 |
384 | bool CMainDlg::CheckWindowValidity(HWND hwndToCheck)
385 | {
386 | HWND hwndTemp = nullptr;
387 |
388 | // The window must not be NULL.
389 | if (hwndToCheck == nullptr)
390 | {
391 | return false;
392 | }
393 |
394 | // Ensure that the window is not the current one which has already been found.
395 | if (hwndToCheck == m_hwndFoundWindow)
396 | {
397 | return false;
398 | }
399 |
400 | // It must also be a valid window as far as the OS is concerned.
401 | if (IsWindow(hwndToCheck) == FALSE)
402 | {
403 | return false;
404 | }
405 |
406 | // It must also not be the main window itself.
407 | if (hwndToCheck == *this)
408 | {
409 | return false;
410 | }
411 |
412 | // It also must not be one of the dialog box's children...
413 | hwndTemp = GetParent(hwndToCheck);
414 | if (hwndTemp == *this)
415 | {
416 | return false;
417 | }
418 | hwndTemp = GetParent(hwndTemp);
419 | if (hwndTemp == *this)
420 | {
421 | return false;
422 | }
423 |
424 | return true;
425 | }
426 |
427 | bool CMainDlg::DisplayInfoOnFoundWindow(HWND hwndFoundWindow)
428 | {
429 | RECT rect{}; // Rectangle area of the found window.
430 | TCHAR szClassName[100]{};
431 |
432 | // Get the screen coordinates of the rectangle of the found window.
433 | GetWindowRect(hwndFoundWindow, &rect);
434 |
435 | // Get the class name of the found window.
436 | GetClassName(hwndFoundWindow, szClassName, _countof(szClassName));
437 |
438 | // Display some information on the found window.
439 | auto sText = CStringUtils::Format(L"Window Handle == 0x%p\r\nClass Name : %s\r\nAccessible Name : %s\r\nRECT == { Left: %d, Top: %d, Right: %d, Bottom: %d } [ %d x %d ]\r\n",
440 | hwndFoundWindow,
441 | szClassName,
442 | CAccessibleName(hwndFoundWindow).c_str(),
443 | rect.left,
444 | rect.top,
445 | rect.right,
446 | rect.bottom,
447 | rect.right - rect.left,
448 | rect.bottom - rect.top);
449 |
450 | SetDlgItemText(*this, IDC_EDIT_STATUS, sText.c_str());
451 |
452 | return true;
453 | }
454 |
455 | bool CMainDlg::RefreshWindow(HWND hwndWindowToBeRefreshed)
456 | {
457 | InvalidateRect(hwndWindowToBeRefreshed, nullptr, TRUE);
458 | UpdateWindow(hwndWindowToBeRefreshed);
459 | RedrawWindow(hwndWindowToBeRefreshed, nullptr, nullptr, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
460 |
461 | return true;
462 | }
463 |
464 | bool CMainDlg::HighlightFoundWindow(HWND hwndFoundWindow) const
465 | {
466 | HDC hWindowDC = nullptr; // The DC of the found window.
467 | RECT rect{}; // Rectangle area of the found window.
468 |
469 | GetWindowRect(hwndFoundWindow, &rect);
470 | hWindowDC = GetWindowDC(hwndFoundWindow);
471 |
472 | if (hWindowDC)
473 | {
474 | HGDIOBJ hPrevPen = SelectObject(hWindowDC, m_hRectanglePen); // Handle of the existing pen in the DC of the found window.
475 | HGDIOBJ hPrevBrush = SelectObject(hWindowDC, GetStockObject(HOLLOW_BRUSH)); // Handle of the existing brush in the DC of the found window.
476 |
477 | // Draw a rectangle in the DC covering the entire window area of the found window.
478 | Rectangle(hWindowDC, 1, 1, rect.right - rect.left - 2, rect.bottom - rect.top - 2);
479 |
480 | SelectObject(hWindowDC, hPrevPen);
481 | SelectObject(hWindowDC, hPrevBrush);
482 | ReleaseDC(hwndFoundWindow, hWindowDC);
483 | }
484 |
485 | return true;
486 | }
487 |
488 | HWND CMainDlg::GetSelectedHandle()
489 | {
490 | TCHAR buf[MAX_PATH]{};
491 |
492 | ::GetDlgItemText(*this, IDC_WINDOW, buf, _countof(buf));
493 |
494 | TCHAR* endptr = nullptr;
495 | return reinterpret_cast(_tcstoui64(buf, &endptr, 0));
496 | }
497 |
498 | bool CMainDlg::SendPostMessage(UINT id)
499 | {
500 | HWND hTargetWnd = GetSelectedHandle();
501 | if (hTargetWnd == nullptr)
502 | return false;
503 | SetDlgItemText(*this, IDC_RETVALUE, _T(""));
504 |
505 | UINT msg = 0;
506 | WPARAM wparam = 0;
507 | LPARAM lparam = 0;
508 | TCHAR buf[MAX_PATH]{};
509 | TCHAR* endptr = nullptr;
510 |
511 | ::GetDlgItemText(*this, IDC_MESSAGE, buf, _countof(buf));
512 | msg = _tcstol(buf, &endptr, 0);
513 | if (msg == 0)
514 | {
515 | LRESULT selIndex = SendDlgItemMessage(*this, IDC_MESSAGE, CB_GETCURSEL, 0, 0);
516 | if (selIndex != CB_ERR)
517 | msg = static_cast(SendDlgItemMessage(*this, IDC_MESSAGE, CB_GETITEMDATA, selIndex, 0));
518 | }
519 | if (msg == 0)
520 | {
521 | msg = WinMessages::Instance().ParseMsg(buf);
522 | }
523 | DWORD err = 0;
524 | if (msg == 0)
525 | {
526 | err = ::GetLastError();
527 | }
528 |
529 | if (!err)
530 | {
531 | ::GetDlgItemText(*this, IDC_WPARAM, buf, _countof(buf));
532 | wparam = static_cast(_tcstol(buf, &endptr, 0));
533 | if (wparam == 0)
534 | {
535 | LRESULT selIndex = SendDlgItemMessage(*this, IDC_WPARAM, CB_GETCURSEL, 0, 0);
536 | if (selIndex != CB_ERR)
537 | wparam = SendDlgItemMessage(*this, IDC_WPARAM, CB_GETITEMDATA, selIndex, 0);
538 | }
539 |
540 | ::GetDlgItemText(*this, IDC_LPARAM, buf, _countof(buf));
541 | lparam = static_cast(_tcstol(buf, &endptr, 0));
542 | if (lparam == 0)
543 | {
544 | LRESULT selIndex = SendDlgItemMessage(*this, IDC_LPARAM, CB_GETCURSEL, 0, 0);
545 | if (selIndex != CB_ERR)
546 | lparam = SendDlgItemMessage(*this, IDC_LPARAM, CB_GETITEMDATA, selIndex, 0);
547 | }
548 |
549 | LRESULT res = 0;
550 | if (id == IDC_SENDMESSAGE)
551 | {
552 | res = SendMessage(hTargetWnd, msg, wparam, lparam);
553 | }
554 | else
555 | {
556 | res = PostMessage(hTargetWnd, msg, wparam, lparam);
557 | }
558 | _stprintf_s(buf, _countof(buf), _T("0x%08Ix (%Id)"), res, res);
559 | SetDlgItemText(*this, IDC_RETVALUE, buf);
560 |
561 | err = GetLastError();
562 | }
563 |
564 | if (err)
565 | {
566 | LPVOID lpMsgBuf = nullptr;
567 | LPVOID lpDisplayBuf = nullptr;
568 |
569 | if (FormatMessage(
570 | FORMAT_MESSAGE_ALLOCATE_BUFFER |
571 | FORMAT_MESSAGE_FROM_SYSTEM |
572 | FORMAT_MESSAGE_IGNORE_INSERTS,
573 | nullptr,
574 | err,
575 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
576 | reinterpret_cast(&lpMsgBuf),
577 | 0,
578 | nullptr))
579 | {
580 | lpDisplayBuf = LocalAlloc(LMEM_ZEROINIT, (lstrlen(static_cast(lpMsgBuf)) + 40LL) * sizeof(TCHAR));
581 | if (lpDisplayBuf)
582 | {
583 | _stprintf_s(static_cast(lpDisplayBuf), LocalSize(lpDisplayBuf) / sizeof(TCHAR), _T("error %lu: %s"), err, (LPTSTR)lpMsgBuf);
584 | SetDlgItemText(*this, IDC_ERROR, static_cast(lpDisplayBuf));
585 | LocalFree(lpDisplayBuf);
586 | }
587 |
588 | LocalFree(lpMsgBuf);
589 | }
590 | }
591 | else
592 | SetDlgItemText(*this, IDC_ERROR, _T(""));
593 |
594 | return true;
595 | }
596 |
--------------------------------------------------------------------------------
/src/MainDlg.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010, 2012-2013, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 | #include "BaseDialog.h"
22 | #include "AeroControls.h"
23 | #include "HyperLink.h"
24 | #include
25 |
26 | #define ID_ABOUTBOX 0x0010
27 |
28 | /**
29 | * main dialog.
30 | */
31 | class CMainDlg : public CDialog
32 | {
33 | public:
34 | CMainDlg(HWND hParent);
35 | ~CMainDlg(void) override;
36 |
37 | protected:
38 | LRESULT CALLBACK DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
39 | LRESULT DoCommand(int id, int msg);
40 | bool PreTranslateMessage(MSG* pMsg) override;
41 |
42 | void SaveWndPosition();
43 | bool SearchWindow();
44 | bool DoMouseMove(UINT message, WPARAM wParam, LPARAM lParam);
45 | bool DoMouseUp(UINT message, WPARAM wParam, LPARAM lParam);
46 | bool CheckWindowValidity(HWND hwndToCheck);
47 | bool DisplayInfoOnFoundWindow(HWND hwndFoundWindow);
48 | static bool RefreshWindow(HWND hwndWindowToBeRefreshed);
49 | bool HighlightFoundWindow(HWND hwndFoundWindow) const;
50 | bool SendPostMessage(UINT id);
51 | HWND GetSelectedHandle();
52 |
53 | private:
54 | HWND m_hParent;
55 | CHyperLink m_link;
56 | AeroControlBase m_aerocontrols;
57 | bool m_bStartSearchWindow;
58 | HWND m_hwndFoundWindow;
59 | HPEN m_hRectanglePen;
60 | };
61 |
--------------------------------------------------------------------------------
/src/SendMessage.cpp:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010, 2012-2013, 2018, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #include "stdafx.h"
21 | #include "SendMessage.h"
22 | #include "MainDlg.h"
23 | #include "AboutDlg.h"
24 | #include "WinMessage.h"
25 | #include "CmdLineParser.h"
26 | #include "SmartHandle.h"
27 | #include "AccessibleName.h"
28 | #include
29 | #include
30 |
31 | // Global Variables:
32 | HINSTANCE hInst = nullptr; // current instance
33 | std::wstring windowTitle;
34 | std::wstring windowClass;
35 | std::wstring windowAccessiblename;
36 | std::wstring windowProcessname;
37 |
38 | BOOL CALLBACK ChildWindowEnumerator(HWND hwnd, LPARAM lParam)
39 | {
40 | auto* pSet = reinterpret_cast*>(lParam);
41 |
42 | if (!windowTitle.empty())
43 | {
44 | TCHAR buf[4096]{};
45 | GetWindowText(hwnd, buf, _countof(buf));
46 | if (windowTitle.substr(0, 4096).compare(buf) != 0)
47 | return TRUE;
48 | }
49 | if (!windowClass.empty())
50 | {
51 | TCHAR szClassName[100]{};
52 | GetClassName(hwnd, szClassName, _countof(szClassName));
53 | if (windowClass.compare(szClassName) != 0)
54 | return TRUE;
55 | }
56 | if (!windowAccessiblename.empty())
57 | {
58 | if (windowAccessiblename.compare(CAccessibleName(hwnd).c_str()) != 0)
59 | return TRUE;
60 | }
61 | if (!windowProcessname.empty())
62 | {
63 | DWORD pid = 0;
64 | GetWindowThreadProcessId(hwnd, &pid);
65 | if (pid)
66 | {
67 | CAutoGeneralHandle hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
68 | if (hProc)
69 | {
70 | TCHAR szProcName[MAX_PATH] = {0};
71 | TCHAR* pProcName = szProcName;
72 | if (GetProcessImageFileName(hProc, szProcName, _countof(szProcName)))
73 | {
74 | pProcName = _tcsrchr(szProcName, '\\');
75 | if (pProcName)
76 | pProcName++;
77 | else
78 | pProcName = szProcName;
79 | if (windowProcessname.compare(pProcName) != 0)
80 | return TRUE;
81 | }
82 | }
83 | }
84 | }
85 |
86 | pSet->insert(hwnd);
87 |
88 | return TRUE;
89 | }
90 |
91 | BOOL CALLBACK WindowEnumerator(HWND hwnd, LPARAM lParam)
92 | {
93 | auto* pSet = reinterpret_cast*>(lParam);
94 |
95 | bool bMatches = true;
96 | if (!windowTitle.empty())
97 | {
98 | TCHAR buf[4096]{};
99 | GetWindowText(hwnd, buf, _countof(buf));
100 | if (windowTitle.substr(0, 4096).compare(buf) != 0)
101 | bMatches = false;
102 | }
103 | if (!windowClass.empty())
104 | {
105 | TCHAR szClassName[100] = {0};
106 | GetClassName(hwnd, szClassName, _countof(szClassName));
107 | if (windowClass.compare(szClassName) != 0)
108 | bMatches = false;
109 | }
110 | if (!windowAccessiblename.empty())
111 | {
112 | if (windowAccessiblename.compare(CAccessibleName(hwnd).c_str()) != 0)
113 | bMatches = false;
114 | }
115 | if (!windowProcessname.empty())
116 | {
117 | DWORD pid = 0;
118 | GetWindowThreadProcessId(hwnd, &pid);
119 | if (pid)
120 | {
121 | CAutoGeneralHandle hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
122 | if (hProc)
123 | {
124 | TCHAR szProcName[MAX_PATH] = {0};
125 | TCHAR* pProcName = szProcName;
126 | if (GetProcessImageFileName(hProc, szProcName, _countof(szProcName)))
127 | {
128 | pProcName = _tcsrchr(szProcName, '\\');
129 | if (pProcName)
130 | pProcName++;
131 | else
132 | pProcName = szProcName;
133 | if (windowProcessname.compare(pProcName) != 0)
134 | bMatches = false;
135 | }
136 | else
137 | bMatches = false;
138 | }
139 | else
140 | bMatches = false;
141 | }
142 | else
143 | bMatches = false;
144 | }
145 | if (bMatches)
146 | pSet->insert(hwnd);
147 |
148 | if (windowProcessname.empty() || !windowTitle.empty() || !windowClass.empty() || !windowAccessiblename.empty())
149 | EnumChildWindows(hwnd, ChildWindowEnumerator, lParam);
150 |
151 | return TRUE;
152 | }
153 |
154 | int APIENTRY _tWinMain(HINSTANCE hInstance,
155 | HINSTANCE hPrevInstance,
156 | LPTSTR lpCmdLine,
157 | int nCmdShow)
158 | {
159 | UNREFERENCED_PARAMETER(hPrevInstance);
160 | UNREFERENCED_PARAMETER(lpCmdLine);
161 | UNREFERENCED_PARAMETER(nCmdShow);
162 |
163 | ::OleInitialize(nullptr);
164 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
165 | // we need some of the common controls
166 | INITCOMMONCONTROLSEX icex{};
167 | icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
168 | icex.dwICC = ICC_LINK_CLASS | ICC_LISTVIEW_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES | ICC_WIN95_CLASSES;
169 | InitCommonControlsEx(&icex);
170 |
171 | CCmdLineParser parser(lpCmdLine);
172 |
173 | INT_PTR ret = 0;
174 | if (parser.HasKey(_T("about")) || parser.HasKey(_T("?")) || parser.HasKey(_T("help")))
175 | {
176 | CAboutDlg aboutDlg(nullptr);
177 | ret = aboutDlg.DoModal(hInstance, IDD_ABOUTBOX, nullptr, NULL);
178 | }
179 | else if (parser.HasKey(L"message"))
180 | {
181 | UINT msg = 0;
182 | WPARAM wParam = 0;
183 | LPARAM lParam = 0;
184 |
185 | if (parser.HasVal(L"message"))
186 | {
187 | msg = WinMessages::Instance().ParseMsg(parser.GetVal(L"message"));
188 | }
189 | if (parser.HasVal(L"wparam"))
190 | wParam = parser.GetLongVal(L"wparam");
191 | if (parser.HasVal(L"lparam"))
192 | lParam = (LPARAM)parser.GetLongLongVal(L"lparam");
193 |
194 | bool bSend = !parser.HasKey(L"post");
195 |
196 | std::set hwndset;
197 |
198 | if (parser.HasVal(L"windowhandle"))
199 | hwndset.insert(reinterpret_cast(parser.GetLongLongVal(L"windowhandle")));
200 | else
201 | {
202 | if (parser.HasVal(L"windowtitle"))
203 | windowTitle = parser.GetVal(L"windowtitle");
204 | if (parser.HasVal(L"windowclass"))
205 | windowClass = parser.GetVal(L"windowclass");
206 | if (parser.HasVal(L"accessiblename"))
207 | windowAccessiblename = parser.GetVal(L"accessiblename");
208 | if (parser.HasVal(L"processname"))
209 | windowProcessname = parser.GetVal(L"processname");
210 |
211 | EnumWindows(WindowEnumerator, reinterpret_cast(&hwndset));
212 | }
213 |
214 | for (auto it = hwndset.cbegin(); it != hwndset.cend(); ++it)
215 | {
216 | if (bSend)
217 | ret = static_cast(SendMessage(*it, msg, wParam, lParam));
218 | else
219 | ret = PostMessage(*it, msg, wParam, lParam);
220 | }
221 | }
222 | else
223 | {
224 | CMainDlg mainDlg(nullptr);
225 | ret = mainDlg.DoModal(hInstance, IDD_MAINDLG, nullptr, IDR_MAINDLG);
226 | }
227 |
228 | ::CoUninitialize();
229 | ::OleUninitialize();
230 | return static_cast(ret);
231 | }
232 |
--------------------------------------------------------------------------------
/src/SendMessage.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010, 2018 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 |
22 | #include "resource.h"
23 |
--------------------------------------------------------------------------------
/src/SendMessage.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #pragma code_page(65001)
4 |
5 | #include "resource.h"
6 |
7 | #define APSTUDIO_READONLY_SYMBOLS
8 | /////////////////////////////////////////////////////////////////////////////
9 | //
10 | // Generated from the TEXTINCLUDE 2 resource.
11 | //
12 | #define APSTUDIO_HIDDEN_SYMBOLS
13 | #include "windows.h"
14 | #undef APSTUDIO_HIDDEN_SYMBOLS
15 | #ifndef APSTUDIO_INVOKED
16 | #include "SendMessage.rc2"
17 | #endif
18 | /////////////////////////////////////////////////////////////////////////////
19 | #undef APSTUDIO_READONLY_SYMBOLS
20 |
21 | /////////////////////////////////////////////////////////////////////////////
22 | // English (United States) resources
23 |
24 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
25 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
26 |
27 | /////////////////////////////////////////////////////////////////////////////
28 | //
29 | // Icon
30 | //
31 |
32 | // Icon with lowest ID value placed first to ensure application icon
33 | // remains consistent on all systems.
34 | IDI_SENDMESSAGE ICON "resources\\SendMessage.ico"
35 | IDI_SEARCHW ICON "resources\\searchw.ico"
36 |
37 | /////////////////////////////////////////////////////////////////////////////
38 | //
39 | // Cursor
40 | //
41 |
42 | IDC_SEARCHW CURSOR "resources\\searchw.cur"
43 |
44 | /////////////////////////////////////////////////////////////////////////////
45 | //
46 | // TEXT
47 | //
48 |
49 | IDR_WINDOWMESSAGESXML TEXT "resources\\windowmessages.xml"
50 |
51 |
52 | /////////////////////////////////////////////////////////////////////////////
53 | //
54 | // Dialog
55 | //
56 |
57 | IDD_ABOUTBOX DIALOGEX 0, 0, 267, 67
58 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
59 | CAPTION "About SendMessage"
60 | FONT 8, "MS Shell Dlg", 0, 0, 0x1
61 | BEGIN
62 | ICON IDI_SENDMESSAGE,IDC_STATIC,14,14,20,20
63 | LTEXT "",IDC_VERSIONINFO,42,14,218,8,SS_NOPREFIX
64 | LTEXT "",IDC_DATE,42,26,114,8
65 | DEFPUSHBUTTON "OK",IDOK,210,46,50,14,WS_GROUP
66 | LTEXT "Visit our website",IDC_WEBLINK,41,52,53,8
67 | END
68 |
69 | IDD_MAINDLG DIALOGEX 0, 0, 400, 187
70 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
71 | EXSTYLE WS_EX_TOPMOST
72 | CAPTION "SendMessage"
73 | FONT 8, "MS Shell Dlg", 400, 0, 0x1
74 | BEGIN
75 | DEFPUSHBUTTON "&Quit",IDOK,343,166,50,14
76 | ICON IDI_SEARCHW,IDC_SEARCHW,7,7,20,20,SS_NOTIFY | SS_CENTERIMAGE
77 | LTEXT "Pos:",IDC_POS,34,7,15,8
78 | LTEXT "0",IDC_STATIC_X_POS,57,7,15,8
79 | LTEXT "0",IDC_STATIC_Y_POS,75,7,17,8
80 | LTEXT "",IDC_EDIT_STATUS,72,18,321,50
81 | GROUPBOX "Send Message",IDC_SENDGROUP,7,76,386,84
82 | LTEXT "Window:",IDC_STATIC,12,92,36,8
83 | LTEXT "Message:",IDC_STATIC,12,109,32,8
84 | LTEXT "WPARAM:",IDC_STATIC,12,125,34,8
85 | LTEXT "LPARAM:",IDC_STATIC,12,140,30,8
86 | PUSHBUTTON "SendMessage",IDC_SENDMESSAGE,198,89,75,14
87 | PUSHBUTTON "PostMessage",IDC_POSTMESSAGE,198,108,75,14
88 | LTEXT "Return value:",IDC_STATIC,281,92,45,8
89 | EDITTEXT IDC_RETVALUE,280,104,106,8,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
90 | LTEXT "&About SendMessage",IDC_ABOUTLINK,319,0,81,8
91 | EDITTEXT IDC_WINDOW,72,90,115,14,ES_AUTOHSCROLL
92 | COMBOBOX IDC_MESSAGE,72,107,115,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
93 | COMBOBOX IDC_WPARAM,72,123,115,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
94 | COMBOBOX IDC_LPARAM,72,139,115,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
95 | LTEXT "",IDC_ERROR,281,122,105,30
96 | PUSHBUTTON "Windows",IDC_WINDOWTREE,7,39,50,14
97 | PUSHBUTTON "Pin",IDC_PINWINDOW,198,127,35,14
98 | PUSHBUTTON "UnPin",IDC_UNPINWINDOW,238,127,35,14
99 | LTEXT "nCmdShow:",IDC_STATIC,12,169,41,8
100 | PUSHBUTTON "ShowWindow",IDC_SHOWWINDOW,198,166,75,14
101 | COMBOBOX IDC_CMDSHOW,72,167,115,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
102 | END
103 |
104 | IDD_WINDOWSTREE DIALOGEX 0, 0, 315, 261
105 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
106 | CAPTION "Windows"
107 | FONT 8, "MS Shell Dlg", 400, 0, 0x1
108 | BEGIN
109 | LTEXT "Filter",IDC_STATIC,8,10,17,8
110 | EDITTEXT IDC_FILTER,36,7,272,14,ES_AUTOHSCROLL
111 | CONTROL "",IDC_WINDOWTREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,26,301,204
112 | DEFPUSHBUTTON "OK",IDOK,205,240,50,14
113 | PUSHBUTTON "Cancel",IDCANCEL,258,240,50,14
114 | PUSHBUTTON "Refresh",IDC_REFRESH,147,240,50,14
115 | END
116 |
117 |
118 | /////////////////////////////////////////////////////////////////////////////
119 | //
120 | // DESIGNINFO
121 | //
122 |
123 | #ifdef APSTUDIO_INVOKED
124 | GUIDELINES DESIGNINFO
125 | BEGIN
126 | IDD_ABOUTBOX, DIALOG
127 | BEGIN
128 | LEFTMARGIN, 7
129 | RIGHTMARGIN, 260
130 | TOPMARGIN, 7
131 | BOTTOMMARGIN, 60
132 | END
133 |
134 | IDD_MAINDLG, DIALOG
135 | BEGIN
136 | LEFTMARGIN, 7
137 | RIGHTMARGIN, 393
138 | VERTGUIDE, 12
139 | VERTGUIDE, 34
140 | VERTGUIDE, 72
141 | VERTGUIDE, 187
142 | VERTGUIDE, 198
143 | VERTGUIDE, 273
144 | TOPMARGIN, 7
145 | BOTTOMMARGIN, 180
146 | HORZGUIDE, 76
147 | HORZGUIDE, 160
148 | END
149 |
150 | IDD_WINDOWSTREE, DIALOG
151 | BEGIN
152 | LEFTMARGIN, 7
153 | RIGHTMARGIN, 308
154 | TOPMARGIN, 7
155 | BOTTOMMARGIN, 254
156 | END
157 | END
158 | #endif // APSTUDIO_INVOKED
159 |
160 |
161 | #ifdef APSTUDIO_INVOKED
162 | /////////////////////////////////////////////////////////////////////////////
163 | //
164 | // TEXTINCLUDE
165 | //
166 |
167 | 1 TEXTINCLUDE
168 | BEGIN
169 | "resource.h\0"
170 | END
171 |
172 | 2 TEXTINCLUDE
173 | BEGIN
174 | "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
175 | "#include ""windows.h""\r\n"
176 | "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
177 | "#ifndef APSTUDIO_INVOKED\r\n"
178 | "#include ""SendMessage.rc2""\r\n"
179 | "#endif\0"
180 | END
181 |
182 | 3 TEXTINCLUDE
183 | BEGIN
184 | "\r\n"
185 | "\0"
186 | END
187 |
188 | #endif // APSTUDIO_INVOKED
189 |
190 | #endif // English (United States) resources
191 | /////////////////////////////////////////////////////////////////////////////
192 |
193 |
194 |
195 | #ifndef APSTUDIO_INVOKED
196 | /////////////////////////////////////////////////////////////////////////////
197 | //
198 | // Generated from the TEXTINCLUDE 3 resource.
199 | //
200 |
201 |
202 | /////////////////////////////////////////////////////////////////////////////
203 | #endif // not APSTUDIO_INVOKED
204 |
205 |
--------------------------------------------------------------------------------
/src/SendMessage.rc2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefankueng/sendmessage/9c546bc59fb5473646b93d05b69923d9a5de5245/src/SendMessage.rc2
--------------------------------------------------------------------------------
/src/SendMessage.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {D1CCDBC4-3C7C-4E14-B980-73FCF457A4C1}
23 | Win32Proj
24 | SendMessage
25 |
26 |
27 |
28 | Application
29 | Unicode
30 | v143
31 |
32 |
33 | Application
34 | Unicode
35 | v143
36 |
37 |
38 | Application
39 | true
40 | Unicode
41 | v143
42 |
43 |
44 | Application
45 | true
46 | Unicode
47 | v143
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | true
67 | $(SolutionDir)bin\$(Configuration)\$(Platform)\
68 | $(SolutionDir)obj\$(Configuration)\$(Platform)\
69 | false
70 |
71 |
72 | true
73 | $(SolutionDir)bin\$(Configuration)\$(Platform)\
74 | $(SolutionDir)obj\$(Configuration)\$(Platform)\
75 | false
76 | $(ProjectName)64
77 |
78 |
79 | false
80 | $(SolutionDir)bin\$(Configuration)\$(Platform)\
81 | $(SolutionDir)obj\$(Configuration)\$(Platform)\
82 | false
83 |
84 |
85 | false
86 | $(SolutionDir)bin\$(Configuration)\$(Platform)\
87 | $(SolutionDir)obj\$(Configuration)\$(Platform)\
88 | false
89 | $(ProjectName)64
90 |
91 |
92 |
93 | ..\sktoolslib;last
94 | EnableFastChecks
95 | EditAndContinue
96 | false
97 | true
98 | false
99 | Disabled
100 | Use
101 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
102 | MultiThreadedDebug
103 | Level4
104 | stdcpp20
105 |
106 |
107 | true
108 | Windows
109 | Psapi.lib;comctl32.lib;%(AdditionalDependencies)
110 |
111 |
112 | last
113 |
114 |
115 | true
116 |
117 |
118 |
119 |
120 | ..\sktoolslib;last
121 | EnableFastChecks
122 | ProgramDatabase
123 | false
124 | false
125 | Disabled
126 | Use
127 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
128 | MultiThreadedDebug
129 | Level4
130 | stdcpp20
131 |
132 |
133 | true
134 | Windows
135 | Psapi.lib;comctl32.lib;%(AdditionalDependencies)
136 |
137 |
138 | last
139 |
140 |
141 | true
142 |
143 |
144 |
145 |
146 | ..\sktoolslib;last
147 | ProgramDatabase
148 | NoExtensions
149 | true
150 | true
151 | true
152 | MaxSpeed
153 | Use
154 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
155 | MultiThreaded
156 | Level4
157 | stdcpp20
158 |
159 |
160 | true
161 | true
162 | true
163 | true
164 | Windows
165 | Psapi.lib;comctl32.lib;%(AdditionalDependencies)
166 | false
167 |
168 |
169 | last
170 |
171 |
172 | true
173 |
174 |
175 |
176 |
177 | ..\sktoolslib;last
178 | ProgramDatabase
179 | true
180 | true
181 | true
182 | MaxSpeed
183 | Use
184 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
185 | MultiThreaded
186 | Level4
187 | stdcpp20
188 |
189 |
190 | true
191 | true
192 | true
193 | true
194 | Windows
195 | Psapi.lib;comctl32.lib;%(AdditionalDependencies)
196 |
197 |
198 | last
199 |
200 |
201 | true
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 | Create
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 | Designer
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
--------------------------------------------------------------------------------
/src/SendMessage.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
6 | h;hpp;hxx;hm;inl;inc;xsd
7 |
8 |
9 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
10 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
11 |
12 |
13 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
14 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
15 |
16 |
17 | {fc6ae0b6-4b38-49c1-ac99-5379a4821f54}
18 |
19 |
20 | {a6a0cbfc-4cb9-481d-b366-cfb8e263ecdf}
21 |
22 |
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Header Files
47 |
48 |
49 | sktoolslib
50 |
51 |
52 | sktoolslib
53 |
54 |
55 | sktoolslib
56 |
57 |
58 | sktoolslib
59 |
60 |
61 | sktoolslib
62 |
63 |
64 | sktoolslib
65 |
66 |
67 | sktoolslib
68 |
69 |
70 | sktoolslib
71 |
72 |
73 | sktoolslib
74 |
75 |
76 | sktoolslib
77 |
78 |
79 | sktoolslib
80 |
81 |
82 | sktoolslib
83 |
84 |
85 | sktoolslib
86 |
87 |
88 | sktoolslib
89 |
90 |
91 | Header Files
92 |
93 |
94 |
95 |
96 | Source Files
97 |
98 |
99 | Source Files
100 |
101 |
102 | Source Files
103 |
104 |
105 | Source Files
106 |
107 |
108 | Source Files
109 |
110 |
111 | Source Files
112 |
113 |
114 | sktoolslib
115 |
116 |
117 | sktoolslib
118 |
119 |
120 | sktoolslib
121 |
122 |
123 | sktoolslib
124 |
125 |
126 | sktoolslib
127 |
128 |
129 | sktoolslib
130 |
131 |
132 | sktoolslib
133 |
134 |
135 | sktoolslib
136 |
137 |
138 | sktoolslib
139 |
140 |
141 | sktoolslib
142 |
143 |
144 | sktoolslib
145 |
146 |
147 | sktoolslib
148 |
149 |
150 | Source Files
151 |
152 |
153 |
154 |
155 | Resource Files
156 |
157 |
158 | Resource Files
159 |
160 |
161 | Resource Files
162 |
163 |
164 | Resource Files
165 |
166 |
167 | Resource Files
168 |
169 |
170 | Build
171 |
172 |
173 | Build
174 |
175 |
176 | Build
177 |
178 |
179 | Build
180 |
181 |
182 |
183 |
184 | Resource Files
185 |
186 |
187 |
188 |
189 | Resource Files
190 |
191 |
192 |
--------------------------------------------------------------------------------
/src/WinMessage.cpp:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2013, 2015, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 | #include "stdafx.h"
20 | #include "WinMessage.h"
21 | #include "resource.h"
22 |
23 | extern HINSTANCE hInst;
24 |
25 | UINT WinMessages::GetApiMessageCode(LPCTSTR text) const
26 | {
27 | for (const auto& it : m_messages)
28 | {
29 | if (_wcsicmp(it.messagename.c_str(), text) == 0)
30 | return it.message;
31 | }
32 | return 0;
33 | }
34 |
35 | UINT WinMessages::ParseMsg(LPCTSTR text) const
36 | {
37 | UINT msg = 0;
38 | TCHAR* endptr = nullptr;
39 |
40 | msg = _tcstol(text, &endptr, 0);
41 | if (msg == 0)
42 | {
43 | // Find API Message
44 | msg = GetApiMessageCode(text);
45 | }
46 | if (msg == 0)
47 | {
48 | // Get custom message
49 | msg = ::RegisterWindowMessage(text);
50 | }
51 | return msg;
52 | }
53 |
54 | WinMessages& WinMessages::Instance()
55 | {
56 | static WinMessages instance;
57 | if (!instance.m_bInit)
58 | instance.Init();
59 | return instance;
60 | }
61 |
62 | void WinMessages::Init()
63 | {
64 | m_xmlResource.Open(hInst, MAKEINTRESOURCE(IDR_WINDOWMESSAGESXML), _T("TEXT"), CResourceTextFile::ConvertToUnicode);
65 | m_xml.Load(m_xmlResource.GetTextBuffer());
66 | // now fill the window message combo box
67 | XNodes childs = m_xml.GetChilds(_T("Message"));
68 | for (size_t i = 0; i < childs.size(); ++i)
69 | {
70 | WinMessage msg;
71 | msg.messagename = childs[i]->GetAttrValue(_T("description"));
72 | TCHAR* endptr = nullptr;
73 | msg.message = _tcstol(childs[i]->GetAttrValue(_T("value")), &endptr, 0);
74 |
75 | XNodes wparams = childs[i]->GetChilds(_T("wparam"));
76 | for (size_t j = 0; j < wparams.size(); ++j)
77 | {
78 | std::wstring desc = wparams[j]->GetAttrValue(_T("description"));
79 | WPARAM m = _tcstol(wparams[j]->GetAttrValue(_T("value")), &endptr, 0);
80 | msg.wparams.push_back(std::make_tuple(desc, m));
81 | }
82 | XNodes lparams = childs[i]->GetChilds(_T("lparam"));
83 | for (size_t j = 0; j < lparams.size(); ++j)
84 | {
85 | std::wstring desc = lparams[j]->GetAttrValue(_T("description"));
86 | UINT m = _tcstol(lparams[j]->GetAttrValue(_T("value")), &endptr, 0);
87 | msg.lparams.push_back(std::make_tuple(desc, m));
88 | }
89 |
90 | m_messages.push_back(msg);
91 | }
92 | m_bInit = true;
93 | }
94 |
--------------------------------------------------------------------------------
/src/WinMessage.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2013, 2015, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 | #pragma once
20 | #include "ResourceTextFile.h"
21 | #include "XMLite.h"
22 |
23 | struct WinMessage
24 | {
25 | std::wstring messagename;
26 | UINT message;
27 | std::vector> wparams;
28 | std::vector> lparams;
29 | };
30 |
31 | class WinMessages
32 | {
33 | private:
34 | WinMessages()
35 | : m_bInit(false)
36 | {
37 | }
38 | ~WinMessages()
39 | {
40 | }
41 |
42 | public:
43 | static WinMessages& Instance();
44 |
45 | size_t GetCount() const { return m_messages.size(); }
46 | WinMessage At(size_t index) const { return m_messages[index]; }
47 | UINT ParseMsg(LPCTSTR text) const;
48 | UINT GetApiMessageCode(LPCTSTR text) const;
49 |
50 | private:
51 | void Init();
52 | bool m_bInit;
53 | CResourceTextFile m_xmlResource;
54 | XNode m_xml;
55 |
56 | std::vector m_messages;
57 | };
58 |
--------------------------------------------------------------------------------
/src/WindowTreeDlg.cpp:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010, 2012, 2014-2015, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #include "stdafx.h"
21 | #include "resource.h"
22 | #include "WindowTreeDlg.h"
23 | #include
24 | #include
25 |
26 | CWindowTreeDlg::CWindowTreeDlg(HWND hParent, HWND actualHandle)
27 | : m_hParent(hParent)
28 | , m_lastTreeItem(nullptr)
29 | , m_selectedWindow(actualHandle)
30 | {
31 | }
32 |
33 | CWindowTreeDlg::~CWindowTreeDlg()
34 | {
35 | }
36 |
37 | LRESULT CWindowTreeDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
38 | {
39 | UNREFERENCED_PARAMETER(lParam);
40 | switch (uMsg)
41 | {
42 | case WM_INITDIALOG: {
43 | InitDialog(hwndDlg, IDI_SENDMESSAGE);
44 |
45 | m_resizer.Init(hwndDlg);
46 | m_resizer.AddControl(hwndDlg, IDC_FILTER, RESIZER_TOPLEFTRIGHT);
47 | m_resizer.AddControl(hwndDlg, IDC_WINDOWTREE, RESIZER_TOPLEFTBOTTOMRIGHT);
48 | m_resizer.AddControl(hwndDlg, IDC_REFRESH, RESIZER_BOTTOMRIGHT);
49 | m_resizer.AddControl(hwndDlg, IDOK, RESIZER_BOTTOMRIGHT);
50 | m_resizer.AddControl(hwndDlg, IDCANCEL, RESIZER_BOTTOMRIGHT);
51 |
52 | ExtendFrameIntoClientArea(IDC_WINDOWTREE, IDC_WINDOWTREE, IDC_WINDOWTREE, IDC_WINDOWTREE);
53 | m_aeroControls.SubclassControl(GetDlgItem(*this, IDC_REFRESH));
54 | m_aeroControls.SubclassControl(GetDlgItem(*this, IDOK));
55 | m_aeroControls.SubclassControl(GetDlgItem(*this, IDCANCEL));
56 | if (m_dwm.IsDwmCompositionEnabled())
57 | m_resizer.UseSizeGrip(false);
58 |
59 | RefreshTree();
60 | }
61 | return FALSE;
62 | case WM_DESTROY:
63 | KillTimer(*this, 0);
64 | break;
65 | case WM_TIMER:
66 | KillTimer(*this, 0);
67 | RefreshTree();
68 | return TRUE;
69 | case WM_COMMAND:
70 | return DoCommand(LOWORD(wParam), HIWORD(wParam));
71 | case WM_SIZE: {
72 | m_resizer.DoResize(LOWORD(lParam), HIWORD(lParam));
73 | }
74 | break;
75 | case WM_GETMINMAXINFO: {
76 | MINMAXINFO* mmi = reinterpret_cast(lParam);
77 | mmi->ptMinTrackSize.x = m_resizer.GetDlgRect()->right;
78 | mmi->ptMinTrackSize.y = m_resizer.GetDlgRect()->bottom;
79 | return 0;
80 | }
81 | default:
82 | return FALSE;
83 | }
84 | return FALSE;
85 | }
86 |
87 | LRESULT CWindowTreeDlg::DoCommand(int id, int msg)
88 | {
89 | switch (id)
90 | {
91 | case IDOK:
92 | m_selectedWindow = GetSelectedWindowHandle();
93 | [[fallthrough]];
94 | case IDCANCEL:
95 | EndDialog(*this, id);
96 | break;
97 | case IDC_FILTER:
98 | switch (msg)
99 | {
100 | case EN_CHANGE:
101 | SetTimer(*this, 0, 500, nullptr);
102 | }
103 | break;
104 | case IDC_REFRESH:
105 | RefreshTree();
106 | break;
107 | }
108 | return 1;
109 | }
110 |
111 | bool CWindowTreeDlg::PreTranslateMessage(MSG* pMsg)
112 | {
113 | if (pMsg->message == WM_KEYDOWN)
114 | {
115 | }
116 | return false;
117 | }
118 |
119 | bool CWindowTreeDlg::RefreshTree()
120 | {
121 | auto hTree = GetDlgItem(*this, IDC_WINDOWTREE);
122 | SendMessage(hTree, WM_SETREDRAW, FALSE, 0);
123 | TreeView_DeleteAllItems(hTree);
124 | m_lastTreeItem = TVI_ROOT;
125 | EnumWindows(WindowEnumerator, reinterpret_cast(this));
126 | SendMessage(hTree, WM_SETREDRAW, TRUE, 0);
127 | SelectTreeItem(m_selectedWindow);
128 | return true;
129 | }
130 |
131 | BOOL CWindowTreeDlg::WindowEnumerator(HWND hwnd, LPARAM lParam)
132 | {
133 | auto* pThis = reinterpret_cast(lParam);
134 |
135 | TCHAR buf[4096]{};
136 | GetWindowString(hwnd, buf, _countof(buf));
137 |
138 | TCHAR filter[MAX_PATH]{};
139 | ::GetDlgItemText(*pThis, IDC_FILTER, filter, _countof(filter));
140 | if (filter[0] == '\0' || StrStrI(buf, filter) != nullptr)
141 | {
142 | TVINSERTSTRUCT is = {nullptr};
143 | is.hParent = TVI_ROOT;
144 | is.hInsertAfter = TVI_SORT;
145 | is.itemex.mask = TVIF_TEXT | TVIF_PARAM;
146 | is.itemex.pszText = buf;
147 | is.itemex.lParam = reinterpret_cast(hwnd);
148 |
149 | pThis->m_lastTreeItem = TreeView_InsertItem(GetDlgItem(*pThis, IDC_WINDOWTREE), &is);
150 | }
151 | else
152 | {
153 | pThis->m_lastTreeItem = TVI_ROOT;
154 | }
155 | EnumChildWindows(hwnd, ChildWindowEnumerator, lParam);
156 | return TRUE;
157 | }
158 |
159 | BOOL CWindowTreeDlg::ChildWindowEnumerator(HWND hwnd, LPARAM lParam)
160 | {
161 | auto* pThis = reinterpret_cast(lParam);
162 |
163 | TCHAR buf[4096]{};
164 | GetWindowString(hwnd, buf, _countof(buf));
165 |
166 | TCHAR filter[MAX_PATH]{};
167 | ::GetDlgItemText(*pThis, IDC_FILTER, filter, _countof(filter));
168 | if (filter[0] == '\0' || (StrStrI(buf, filter) != nullptr && GetDlgItem(*pThis, IDC_FILTER) != hwnd))
169 | {
170 | TVINSERTSTRUCT is = {nullptr};
171 | is.hParent = pThis->m_lastTreeItem;
172 | is.hInsertAfter = TVI_SORT;
173 | is.itemex.mask = TVIF_TEXT | TVIF_PARAM;
174 | is.itemex.pszText = buf;
175 | is.itemex.lParam = reinterpret_cast(hwnd);
176 |
177 | TreeView_InsertItem(GetDlgItem(*pThis, IDC_WINDOWTREE), &is);
178 | }
179 | return TRUE;
180 | }
181 |
182 | void CWindowTreeDlg::GetWindowString(HWND hwnd, TCHAR* buf, int bufsize)
183 | {
184 | TCHAR tmpbuf[4096] = {0};
185 | TCHAR szClassName[100] = {0};
186 | TCHAR szProcName[MAX_PATH] = {0};
187 | TCHAR* pProcName = szProcName;
188 |
189 | GetWindowText(hwnd, tmpbuf, _countof(tmpbuf));
190 | if (GetClassName(hwnd, szClassName, _countof(szClassName)) == 0)
191 | szClassName[0] = 0;
192 | DWORD pid = 0;
193 | GetWindowThreadProcessId(hwnd, &pid);
194 | if (pid)
195 | {
196 | HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
197 | if (hProc)
198 | {
199 | if (GetProcessImageFileName(hProc, szProcName, _countof(szProcName)))
200 | {
201 | pProcName = _tcsrchr(szProcName, '\\');
202 | if (pProcName)
203 | pProcName++;
204 | else
205 | pProcName = szProcName;
206 | }
207 | CloseHandle(hProc);
208 | }
209 | }
210 | _sntprintf_s(buf, bufsize, _TRUNCATE, _T("Window 0x%p : Process \"%s\" : class \"%s\" : title \"%s\""), hwnd, pProcName, szClassName, tmpbuf);
211 | }
212 |
213 | HWND CWindowTreeDlg::GetSelectedWindowHandle()
214 | {
215 | HTREEITEM selItem = TreeView_GetSelection(GetDlgItem(*this, IDC_WINDOWTREE));
216 | if (selItem == nullptr)
217 | return nullptr;
218 |
219 | TVITEM tvi = {0};
220 | tvi.hItem = selItem;
221 | tvi.mask = TVIF_PARAM;
222 | TreeView_GetItem(GetDlgItem(*this, IDC_WINDOWTREE), &tvi);
223 | return reinterpret_cast(tvi.lParam);
224 | }
225 |
226 | void CWindowTreeDlg::SelectTreeItem(HWND windowHwnd)
227 | {
228 | HWND windowTreeHwnd = GetDlgItem(*this, IDC_WINDOWTREE);
229 | HTREEITEM actualItem = TreeView_GetFirstVisible(windowTreeHwnd);
230 |
231 | // Search by the item into the list
232 | while (actualItem != nullptr)
233 | {
234 | TVITEM tvi = {0};
235 | tvi.hItem = actualItem;
236 | tvi.mask = TVIF_PARAM;
237 | TreeView_GetItem(windowTreeHwnd, &tvi);
238 |
239 | // If it is the item, select it and break the search
240 | if (reinterpret_cast(tvi.lParam) == windowHwnd)
241 | {
242 | TreeView_SelectItem(windowTreeHwnd, actualItem);
243 | break;
244 | }
245 |
246 | // Find the next item in the TreeView
247 | HTREEITEM nextItem = TreeView_GetChild(windowTreeHwnd, actualItem);
248 | if (nextItem == nullptr)
249 | nextItem = TreeView_GetNextSibling(windowTreeHwnd, actualItem);
250 |
251 | HTREEITEM parentItem = actualItem;
252 | while ((nextItem == nullptr) && (parentItem != nullptr))
253 | {
254 | parentItem = TreeView_GetParent(windowTreeHwnd, parentItem);
255 | nextItem = TreeView_GetNextSibling(windowTreeHwnd, parentItem);
256 | }
257 | actualItem = nextItem;
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/src/WindowTreeDlg.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010, 2012, 2021 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 | #include "BaseDialog.h"
22 | #include "AeroControls.h"
23 | #include "DlgResizer.h"
24 |
25 | /**
26 | * dialog showing a tree of all windows
27 | */
28 | class CWindowTreeDlg : public CDialog
29 | {
30 | public:
31 | CWindowTreeDlg(HWND hParent, HWND actualHandle);
32 | ~CWindowTreeDlg() override;
33 |
34 | HWND GetSelectedWindow() const { return m_selectedWindow; }
35 |
36 | protected:
37 | LRESULT CALLBACK DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
38 | LRESULT DoCommand(int id, int msg);
39 | bool PreTranslateMessage(MSG* pMsg) override;
40 | static void GetWindowString(HWND hwnd, TCHAR* buf, int bufsize);
41 | bool RefreshTree();
42 | static BOOL CALLBACK WindowEnumerator(HWND hwnd, LPARAM lParam);
43 | static BOOL CALLBACK ChildWindowEnumerator(HWND hwnd, LPARAM lParam);
44 | HWND GetSelectedWindowHandle();
45 | void SelectTreeItem(HWND windowHwnd);
46 |
47 | private:
48 | HWND m_hParent;
49 | AeroControlBase m_aeroControls;
50 | CDlgResizer m_resizer;
51 | HTREEITEM m_lastTreeItem;
52 | HWND m_selectedWindow;
53 | };
54 |
--------------------------------------------------------------------------------
/src/XMLite.cpp:
--------------------------------------------------------------------------------
1 | // XMLite.cpp: implementation of the XMLite class.
2 | //
3 | //////////////////////////////////////////////////////////////////////
4 |
5 | // ReSharper disable All
6 | #include "stdafx.h"
7 | #include "XMLite.h"
8 | #include "auto_buffer.h"
9 | #include
10 | #include
11 | #include
12 |
13 | static const TCHAR chXMLTagOpen = '<';
14 | static const TCHAR chXMLTagClose = '>';
15 | static const TCHAR chXMLTagPre = '/';
16 | static const TCHAR chXMLEscape = '\\'; // for value field escape
17 |
18 | static const TCHAR szXMLPIOpen[] = _T("");
19 | static const TCHAR szXMLPIClose[] = _T("?>");
20 | static const TCHAR szXMLCommentOpen[] = _T("");
22 | static const TCHAR szXMLCDATAOpen[] = _T("");
24 |
25 | static const XENTITY x_EntityTable[] = {
26 | { '&', _T("&"), 5 } ,
27 | { '\"', _T("""), 6 } ,
28 | { '\'', _T("'"), 6 } ,
29 | { '<', _T("<"), 4 } ,
30 | { '>', _T(">"), 4 }
31 | };
32 |
33 | PARSEINFO piDefault;
34 | DISP_OPT optDefault;
35 | XENTITYS entityDefault((LPXENTITY)x_EntityTable, sizeof(x_EntityTable)/sizeof(x_EntityTable[0]) );
36 |
37 | LPTSTR _tcschrs( LPCTSTR psz, LPCTSTR pszchs )
38 | {
39 | while( psz && *psz )
40 | {
41 | if( _tcschr( pszchs, *psz ) )
42 | return (LPTSTR)psz;
43 | psz++;
44 | }
45 | return NULL;
46 | }
47 |
48 | LPTSTR _tcsskip( LPCTSTR psz )
49 | {
50 | //while( psz && *psz == ' ' && *psz == 13 && *psz == 10 ) psz++;
51 | while( psz && isspace(*psz) ) psz++;
52 |
53 | return (LPTSTR)psz;
54 | }
55 |
56 | LPTSTR _tcsechr( LPCTSTR psz, int ch, int escape )
57 | {
58 | LPTSTR pch = (LPTSTR)psz;
59 |
60 | while( pch && *pch )
61 | {
62 | if( escape != 0 && *pch == escape )
63 | pch++;
64 | else
65 | if( *pch == ch )
66 | return (LPTSTR)pch;
67 | pch++;
68 | }
69 | return pch;
70 | }
71 |
72 | int _tcselen( int escape, LPTSTR srt, LPTSTR end = NULL )
73 | {
74 | int len = 0;
75 | LPTSTR pch = srt;
76 | if( end==NULL ) end = (LPTSTR)sizeof(long);
77 | LPTSTR prev_escape = NULL;
78 | while( pch && *pch && pch des[i] )
157 | return 1;
158 | return -1;
159 | }
160 |
161 | LPTSTR _tcsenistr( LPCTSTR psz, LPCTSTR str, int len, int escape )
162 | {
163 | LPTSTR pch = (LPTSTR)psz;
164 | LPTSTR prev_escape = NULL;
165 |
166 | while( pch && *pch )
167 | {
168 | if( escape != 0 && *pch == escape && prev_escape == NULL )
169 | prev_escape = pch;
170 | else
171 | {
172 | prev_escape = NULL;
173 | if( _tcsenicmp( pch, str, len, escape ) == 0 )
174 | return (LPTSTR)pch;
175 | }
176 | pch++;
177 | }
178 | return pch;
179 | }
180 |
181 | LPTSTR _tcseistr( LPCTSTR psz, LPCTSTR str, int escape )
182 | {
183 | size_t len = _tcslen( str );
184 | return _tcsenistr( psz, str, (int)len, escape );
185 | }
186 |
187 | void _SetString( LPTSTR psz, LPTSTR end, std::wstring* ps, bool trim = FALSE, int escape = 0 )
188 | {
189 | //trim
190 | if( trim )
191 | {
192 | while( psz && psz < end && _istspace(*psz) ) psz++;
193 | while( (end-1) && psz < (end-1) && _istspace(*(end-1)) ) end--;
194 | }
195 | size_t len = end - psz;
196 | if( len <= 0 ) return;
197 | if( escape )
198 | {
199 | len = _tcselen( escape, psz, end );
200 | auto_buffer pss (len + 1);
201 | _tcsecpy( pss, escape, psz, end );
202 | ps->assign(pss);
203 | }
204 | else
205 | {
206 | auto_buffer pss (len + 1);
207 | memcpy( pss, psz, len*sizeof(TCHAR) );
208 | pss[len] = '\0';
209 | ps->assign(pss);
210 | }
211 | }
212 |
213 | _tagXMLNode::~_tagXMLNode()
214 | {
215 | Close();
216 | }
217 |
218 | void _tagXMLNode::Close()
219 | {
220 | for( size_t i = 0 ; i < childs.size(); i ++)
221 | {
222 | LPXNode p = childs[i];
223 | if( p )
224 | {
225 | delete p; childs[i] = NULL;
226 | }
227 | }
228 | childs.clear();
229 |
230 | for( size_t i = 0 ; i < attrs.size(); i ++)
231 | {
232 | LPXAttr p = attrs[i];
233 | if( p )
234 | {
235 | delete p; attrs[i] = NULL;
236 | }
237 | }
238 | attrs.clear();
239 | }
240 |
241 | LPTSTR _tagXMLNode::LoadAttributes( LPCTSTR pszAttrs , LPPARSEINFO pi /*= &piDefault*/)
242 | {
243 | LPTSTR xml = (LPTSTR)pszAttrs;
244 |
245 | while( xml && *xml )
246 | {
247 | if(( xml = _tcsskip( xml ) ) != NULL)
248 | {
249 | // close tag
250 | if( *xml == chXMLTagClose || *xml == chXMLTagPre )
251 | // wel-formed tag
252 | return xml;
253 |
254 | // XML Attr Name
255 | TCHAR* pEnd = _tcspbrk( xml, _T(" =") );
256 | if( pEnd == NULL )
257 | {
258 | // error
259 | if( pi->error_occur == false )
260 | {
261 | pi->error_occur = true;
262 | pi->error_pointer = xml;
263 | pi->error_code = PIE_ATTR_NO_VALUE;
264 |
265 | auto_buffer sbuf (100 + name.size());
266 | _stprintf_s(sbuf, 100 + name.size(), _T("<%s> attribute has error "), name.c_str());
267 | pi->error_string = sbuf.get();
268 | }
269 | return NULL;
270 | }
271 |
272 | LPXAttr attr = new XAttr;
273 | attr->parent = this;
274 |
275 | // XML Attr Name
276 | _SetString( xml, pEnd, &attr->name );
277 |
278 | // add new attribute
279 | attrs.push_back( attr );
280 | xml = pEnd;
281 |
282 | // XML Attr Value
283 | if( ( xml = _tcsskip( xml ) ) != NULL )
284 | {
285 | //if( xml = _tcschr( xml, '=' ) )
286 | if( *xml == '=' )
287 | {
288 | if( ( xml = _tcsskip( ++xml ) ) != NULL )
289 | {
290 | // if " or '
291 | // or none quote
292 | int quote = *xml;
293 | if( quote == '"' || quote == '\'' )
294 | pEnd = _tcsechr( ++xml, quote, chXMLEscape );
295 | else
296 | {
297 | //attr= value>
298 | // none quote mode
299 | //pEnd = _tcsechr( xml, ' ', '\\' );
300 | pEnd = _tcsepbrk( xml, _T(" >"), chXMLEscape );
301 | }
302 |
303 | bool trim = pi->trim_value;
304 | TCHAR escape = pi->escape_value;
305 | //_SetString( xml, pEnd, &attr->value, trim, chXMLEscape );
306 | _SetString( xml, pEnd, &attr->value, trim, escape );
307 | xml = pEnd;
308 | // ATTRVALUE
309 | if( pi->entity_value && pi->entities )
310 | attr->value = pi->entities->Ref2Entity(attr->value.c_str());
311 |
312 | if( quote == '"' || quote == '\'' )
313 | xml++;
314 | }
315 | }
316 | }
317 | }
318 | }
319 |
320 | // not wel-formed tag
321 | return NULL;
322 | }
323 |
324 | LPTSTR _tagXMLNode::LoadAttributes( LPCTSTR pszAttrs, LPCTSTR pszEnd, LPPARSEINFO pi /*= &piDefault*/ )
325 | {
326 | LPTSTR xml = (LPTSTR)pszAttrs;
327 |
328 | while( xml && *xml )
329 | {
330 | if( ( xml = _tcsskip( xml ) ) != NULL )
331 | {
332 | // close tag
333 | if( xml >= pszEnd )
334 | // wel-formed tag
335 | return xml;
336 |
337 | // XML Attr Name
338 | TCHAR* pEnd = _tcspbrk( xml, _T(" =") );
339 | if( pEnd == NULL )
340 | {
341 | // error
342 | if( pi->error_occur == false )
343 | {
344 | pi->error_occur = true;
345 | pi->error_pointer = xml;
346 | pi->error_code = PIE_ATTR_NO_VALUE;
347 | auto_buffer sbuf (100 + name.size());
348 | _stprintf_s(sbuf, 100 + name.size(), _T("<%s> attribute has error "), name.c_str());
349 | pi->error_string = sbuf.get();
350 | }
351 | return NULL;
352 | }
353 |
354 | LPXAttr attr = new XAttr;
355 | attr->parent = this;
356 |
357 | // XML Attr Name
358 | _SetString( xml, pEnd, &attr->name );
359 |
360 | // add new attribute
361 | attrs.push_back( attr );
362 | xml = pEnd;
363 |
364 | // XML Attr Value
365 | if( ( xml = _tcsskip( xml ) ) != NULL )
366 | {
367 | //if( xml = _tcschr( xml, '=' ) )
368 | if( *xml == '=' )
369 | {
370 | if( ( xml = _tcsskip( ++xml ) ) != NULL )
371 | {
372 | // if " or '
373 | // or none quote
374 | int quote = *xml;
375 | if( quote == '"' || quote == '\'' )
376 | pEnd = _tcsechr( ++xml, quote, chXMLEscape );
377 | else
378 | {
379 | //attr= value>
380 | // none quote mode
381 | //pEnd = _tcsechr( xml, ' ', '\\' );
382 | pEnd = _tcsepbrk( xml, _T(" >"), chXMLEscape );
383 | }
384 |
385 | bool trim = pi->trim_value;
386 | TCHAR escape = pi->escape_value;
387 | //_SetString( xml, pEnd, &attr->value, trim, chXMLEscape );
388 | _SetString( xml, pEnd, &attr->value, trim, escape );
389 | xml = pEnd;
390 | // ATTRVALUE
391 | if( pi->entity_value && pi->entities )
392 | attr->value = pi->entities->Ref2Entity(attr->value.c_str());
393 |
394 | if( quote == '"' || quote == '\'' )
395 | xml++;
396 | }
397 | }
398 | }
399 | }
400 | }
401 |
402 | // not wel-formed tag
403 | return NULL;
404 | }
405 |
406 | LPTSTR _tagXMLNode::LoadProcessingInstrunction( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ )
407 | {
408 | // find the end of pi
409 | LPTSTR end = _tcsenistr( pszXml, szXMLPIClose, sizeof(szXMLPIClose)-1, pi ? pi->escape_value : 0 );
410 | if( end == NULL )
411 | return NULL;
412 |
413 | // process pi
414 | if( doc )
415 | {
416 | LPTSTR xml = (LPTSTR)pszXml;
417 |
418 | LPXNode node = new XNode;
419 | node->parent = this;
420 | node->doc = doc;
421 | node->type = XNODE_PI;
422 |
423 | xml += _countof(szXMLPIOpen) - 1;
424 | TCHAR* pTagEnd = _tcspbrk( xml, _T(" ?>") );
425 | _SetString( xml, pTagEnd, &node->name );
426 | xml = pTagEnd;
427 |
428 | node->LoadAttributes( xml, end, pi );
429 |
430 | doc->childs.push_back( node );
431 | }
432 |
433 | end += _countof(szXMLPIClose) - 1;
434 | return end;
435 | }
436 |
437 | LPTSTR _tagXMLNode::LoadComment( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ )
438 | {
439 | // find the end of comment
440 | LPTSTR end = _tcsenistr( pszXml, szXMLCommentClose, sizeof(szXMLCommentClose)-1, pi ? pi->escape_value : 0 );
441 | if( end == NULL )
442 | return NULL;
443 |
444 | // process comment
445 | LPXNode par = parent;
446 | if( parent == NULL && doc )
447 | par = (LPXNode)&doc;
448 | if( par )
449 | {
450 | LPTSTR xml = (LPTSTR)pszXml;
451 | xml += _countof(szXMLCommentOpen) - 1;
452 |
453 | LPXNode node = new XNode;
454 | node->parent = this;
455 | node->doc = doc;
456 | node->type = XNODE_COMMENT;
457 | node->name = _T("#COMMENT");
458 | _SetString( xml, end, &node->value, FALSE );
459 |
460 | par->childs.push_back( node );
461 | }
462 |
463 | end += _countof(szXMLCommentClose) - 1;
464 | return end;
465 | }
466 |
467 | LPTSTR _tagXMLNode::LoadCDATA( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ )
468 | {
469 | // find the end of CDATA
470 | LPTSTR end = _tcsenistr( pszXml, szXMLCDATAClose, sizeof(szXMLCDATAClose)-1, pi ? pi->escape_value : 0 );
471 | if( end == NULL )
472 | return NULL;
473 |
474 | // process CDATA
475 | LPXNode par = parent;
476 | if( parent == NULL && doc )
477 | par = (LPXNode)&doc;
478 | if( par )
479 | {
480 | LPTSTR xml = (LPTSTR)pszXml;
481 | xml += _countof(szXMLCDATAOpen) - 1;
482 |
483 | LPXNode node = new XNode;
484 | node->parent = this;
485 | node->doc = doc;
486 | node->type = XNODE_CDATA;
487 | node->name = _T("#CDATA");
488 | _SetString( xml, end, &node->value, FALSE );
489 |
490 | par->childs.push_back( node );
491 | }
492 |
493 | end += _countof(szXMLCDATAClose) - 1;
494 | return end;
495 | }
496 |
497 | LPTSTR LoadOtherNodes( LPXNode node, bool* pbRet, LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ )
498 | {
499 | LPTSTR xml = (LPTSTR)pszXml;
500 | bool do_other_type = true;
501 | *pbRet = false;
502 |
503 | while( xml && do_other_type )
504 | {
505 | do_other_type = false;
506 |
507 | xml = _tcsskip( xml );
508 | LPTSTR prev = xml;
509 | // is PI( Processing Instruction ) Node?
510 | if( _tcsnicmp( xml, szXMLPIOpen, sizeof(szXMLPIOpen)-1 ) == 0 )
511 | {
512 | // processing instrunction parse
513 | // return pointer is next node of pi
514 | xml = node->LoadProcessingInstrunction( xml, pi );
515 | //if( xml == NULL )
516 | // return NULL;
517 | // restart xml parse
518 | }
519 |
520 | if( xml != prev )
521 | do_other_type = true;
522 | xml = _tcsskip( xml );
523 | prev = xml;
524 |
525 | // is comment Node?
526 | if( _tcsnicmp( xml, szXMLCommentOpen, sizeof(szXMLCommentOpen)-1 ) == 0 )
527 | {
528 | // processing comment parse
529 | // return pointer is next node of comment
530 | xml = node->LoadComment( xml, pi );
531 | // comment node is terminal node
532 | if( node->parent && node->parent->type != XNODE_DOC
533 | && xml != prev )
534 | {
535 | *pbRet = true;
536 | return xml;
537 | }
538 | // restart xml parse when this node is root doc node
539 | }
540 |
541 | if( xml != prev )
542 | do_other_type = true;
543 |
544 | xml = _tcsskip( xml );
545 | prev = xml;
546 | // is CDATA Node?
547 | if( _tcsnicmp( xml, szXMLCDATAOpen, sizeof(szXMLCDATAOpen)-1 ) == 0 )
548 | {
549 | // processing CDATA parse
550 | // return pointer is next node of CDATA
551 | xml = node->LoadCDATA( xml, pi );
552 | // CDATA node is terminal node
553 | if( node->parent && node->parent->type != XNODE_DOC
554 | && xml != prev )
555 | {
556 | *pbRet = true;
557 | return xml;
558 | }
559 | // restart xml parse when this node is root doc node
560 | }
561 |
562 | if( xml != prev )
563 | do_other_type = true;
564 | }
565 |
566 | return xml;
567 | }
568 |
569 | LPTSTR _tagXMLNode::Load( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ )
570 | {
571 | // Close it
572 | Close();
573 |
574 | LPTSTR xml = (LPTSTR)pszXml;
575 |
576 | xml = _tcschr( xml, chXMLTagOpen );
577 | if( xml == NULL )
578 | return NULL;
579 |
580 | // Close Tag
581 | if( *(xml+1) == chXMLTagPre ) // (pi, comment, CDATA etc)
585 | bool bRet = false;
586 | LPTSTR ret = NULL;
587 | ret = LoadOtherNodes( this, &bRet, xml, pi );
588 | if( ret != NULL )
589 | xml = ret;
590 | if( bRet )
591 | return xml;
592 |
593 | // XML Node Tag Name Open
594 | xml++;
595 | TCHAR* pTagEnd = _tcspbrk( xml, _T(" />\t\r\n") );
596 | _SetString( xml, pTagEnd, &name );
597 | xml = pTagEnd;
598 | // Generate XML Attributte List
599 | if( ( xml = LoadAttributes( xml, pi ) ) != NULL )
600 | {
601 | // alone tag
602 | if( *xml == chXMLTagPre )
603 | {
604 | xml++;
605 | if( *xml == chXMLTagClose )
606 | // wel-formed tag
607 | return ++xml;
608 | else
609 | {
610 | // error:
611 | if( pi->error_occur == false )
612 | {
613 | pi->error_occur = true;
614 | pi->error_pointer = xml;
615 | pi->error_code = PIE_ALONE_NOT_CLOSED;
616 | pi->error_string = _T("Element must be closed.");
617 | }
618 | // not wel-formed tag
619 | return NULL;
620 | }
621 | }
622 | else
623 | // open/close tag ...
624 | // ^- current pointer
625 | {
626 | // if text value is not exist, then assign value
627 | //if( this->value.IsEmpty() || this->value == _T("") )
628 | if( XIsEmptyString( value.c_str() ) )
629 | {
630 | // Text Value
631 | TCHAR* pEnd = _tcsechr( ++xml, chXMLTagOpen, chXMLEscape );
632 | if( pEnd == NULL )
633 | {
634 | if( pi->error_occur == false )
635 | {
636 | pi->error_occur = true;
637 | pi->error_pointer = xml;
638 | pi->error_code = PIE_NOT_CLOSED;
639 | auto_buffer sbuf (100 + name.size() + value.size());
640 | _stprintf_s(sbuf, 100 + name.size() + value.size(), _T("%s must be closed with %s>"), name.c_str(), value.c_str());
641 | pi->error_string = sbuf.get();
642 | }
643 | // error cos not exist CloseTag
644 | return NULL;
645 | }
646 |
647 | bool trim = pi->trim_value;
648 | TCHAR escape = pi->escape_value;
649 | //_SetString( xml, pEnd, &value, trim, chXMLEscape );
650 | _SetString( xml, pEnd, &value, trim, escape );
651 |
652 | xml = pEnd;
653 | // TEXTVALUE reference
654 | if( pi->entity_value && pi->entities )
655 | value = pi->entities->Ref2Entity(value.c_str());
656 | }
657 |
658 | // generate child nodes
659 | while( xml && *xml )
660 | {
661 | LPXNode node = new XNode;
662 | node->parent = this;
663 | node->doc = doc;
664 | node->type = type;
665 |
666 | xml = node->Load( xml,pi );
667 | if( node->name.empty() == FALSE )
668 | {
669 | childs.push_back( node );
670 |
671 | }
672 | else
673 | {
674 | delete node;
675 | }
676 |
677 | // open/close tag ...
678 | // ^- current pointer
679 | // CloseTag case
680 | if( xml && *xml && *(xml+1) && *xml == chXMLTagOpen && *(xml+1) == chXMLTagPre )
681 | {
682 | //
683 | xml+=2; // C
684 |
685 | if( ( xml = _tcsskip( xml ) ) != NULL )
686 | {
687 | std::wstring closename;
688 | TCHAR* pEnd = _tcspbrk( xml, _T(" >") );
689 | if( pEnd == NULL )
690 | {
691 | if( pi->error_occur == false )
692 | {
693 | pi->error_occur = true;
694 | pi->error_pointer = xml;
695 | pi->error_code = PIE_NOT_CLOSED;
696 | auto_buffer sbuf (100 + name.size() + value.size());
697 | _stprintf_s(sbuf, 100 + name.size() + value.size(), _T("%s must be closed with %s>"), name.c_str(), value.c_str());
698 | pi->error_string = sbuf.get();
699 | }
700 | // error
701 | return NULL;
702 | }
703 | _SetString( xml, pEnd, &closename );
704 | if( closename == this->name )
705 | {
706 | // wel-formed open/close
707 | xml = pEnd+1;
708 | // return '>' or ' ' after pointer
709 | return xml;
710 | }
711 | else
712 | {
713 | xml = pEnd+1;
714 | // 2004.6.15 - example alone tag
715 | // now it can parse with attribute 'force_arse'
716 | if( pi->force_parse == false )
717 | {
718 | // not welformed open/close
719 | if( pi->error_occur == false )
720 | {
721 | pi->error_occur = true;
722 | pi->error_pointer = xml;
723 | pi->error_code = PIE_NOT_NESTED;
724 | auto_buffer sbuf (100 + name.size() + closename.size());
725 | _stprintf_s(sbuf, 100 + name.size(), _T("'<%s> ... %s>' is not wel-formed."), name.c_str(), closename.c_str());
726 | pi->error_string = sbuf.get();
727 | }
728 | return NULL;
729 | }
730 | }
731 | }
732 | }
733 | else // Alone child Tag Loaded
734 | // else ÇØ¾ßÇÏ´ÂÁö ¸»¾Æ¾ßÇÏ´ÂÁö Àǽɰ£´Ù.
735 | {
736 |
737 | //if( xml && this->value.IsEmpty() && *xml !=chXMLTagOpen )
738 | if( xml && XIsEmptyString( value.c_str() ) && *xml !=chXMLTagOpen )
739 | {
740 | // Text Value
741 | TCHAR* pEnd = _tcsechr( xml, chXMLTagOpen, chXMLEscape );
742 | if( pEnd == NULL )
743 | {
744 | // error cos not exist CloseTag
745 | if( pi->error_occur == false )
746 | {
747 | pi->error_occur = true;
748 | pi->error_pointer = xml;
749 | pi->error_code = PIE_NOT_CLOSED;
750 | auto_buffer sbuf (100 + name.size() + value.size());
751 | _stprintf_s(sbuf, 100 + name.size() + value.size(), _T("%s must be closed with %s>"), name.c_str(), value.c_str());
752 | pi->error_string = sbuf.get();
753 | }
754 | return NULL;
755 | }
756 |
757 | bool trim = pi->trim_value;
758 | TCHAR escape = pi->escape_value;
759 | //_SetString( xml, pEnd, &value, trim, chXMLEscape );
760 | _SetString( xml, pEnd, &value, trim, escape );
761 |
762 | xml = pEnd;
763 | //TEXTVALUE
764 | if( pi->entity_value && pi->entities )
765 | value = pi->entities->Ref2Entity(value.c_str());
766 | }
767 | }
768 | }
769 | }
770 | }
771 |
772 | return xml;
773 | }
774 |
775 | LPTSTR _tagXMLDocument::Load( LPCTSTR pszXml, LPPARSEINFO pi /*= NULL*/ )
776 | {
777 | LPXNode node = new XNode;
778 | node->parent = (LPXNode)this;
779 | node->type = XNODE_ELEMENT;
780 | node->doc = this;
781 | LPTSTR end;
782 |
783 | if( pi == NULL )
784 | pi = &parse_info;
785 |
786 | if( (end = node->Load( pszXml, pi )) == NULL )
787 | {
788 | delete node;
789 | return NULL;
790 | }
791 |
792 | childs.push_back( node );
793 |
794 | // Load Other Node after (pi, comment, CDATA etc)
795 | LPTSTR ret;
796 | bool bRet = false;
797 | ret = LoadOtherNodes( node, &bRet, end, pi );
798 | if( ret != NULL )
799 | end = ret;
800 |
801 | return end;
802 | }
803 |
804 | LPXNode _tagXMLDocument::GetRoot()
805 | {
806 | XNodes::iterator it = childs.begin();
807 | for( ; it != childs.end() ; ++(it) )
808 | {
809 | LPXNode node = *it;
810 | if( node->type == XNODE_ELEMENT )
811 | return node;
812 | }
813 | return NULL;
814 | }
815 |
816 | std::wstring _tagXMLAttr::GetXML( LPDISP_OPT opt /*= &optDefault*/ )
817 | {
818 | std::wostringstream os;
819 | //os << (LPCTSTR)name << "='" << (LPCTSTR)value << "' ";
820 |
821 | os << (LPCTSTR)name.c_str() << _T("=") << (TCHAR)opt->value_quotation_mark
822 | << (LPCTSTR)(opt->reference_value&&opt->entities?opt->entities->Entity2Ref(value.c_str()).c_str():value.c_str())
823 | << (TCHAR)opt->value_quotation_mark << _T(" ");
824 | return os.str();
825 | }
826 |
827 | std::wstring _tagXMLNode::GetXML( LPDISP_OPT opt /*= &optDefault*/ )
828 | {
829 | std::wostringstream os;
830 |
831 | // tab
832 | if( opt && opt->newline )
833 | {
834 | os << "\r\n";
835 | for( int i = 0 ; i < opt->tab_base ; i++)
836 | os << '\t';
837 | }
838 |
839 | if( type == XNODE_DOC )
840 | {
841 | for( size_t i = 0 ; i < childs.size(); i++ )
842 | os << (LPCTSTR)childs[i]->GetXML( opt ).c_str();
843 | return os.str();
844 | }
845 | else
846 | if( type == XNODE_PI )
847 | {
848 | // GetXML(opt).c_str();
855 | }
856 | //?>
857 | os << szXMLPIClose;
858 | return os.str();
859 | }
860 | else
861 | if( type == XNODE_COMMENT )
862 | {
863 | // <--comment
864 | os << szXMLCommentOpen << (LPCTSTR)value.c_str();
865 | //-->
866 | os << szXMLCommentClose;
867 | return os.str();
868 | }
869 | else
870 | if( type == XNODE_CDATA )
871 | {
872 | // <--comment
873 | os << szXMLCDATAOpen << (LPCTSTR)value.c_str();
874 | //-->
875 | os << szXMLCDATAClose;
876 | return os.str();
877 | }
878 |
879 | // GetXML(opt).c_str();
887 | }
888 |
889 | if( childs.empty() && value.empty() )
890 | {
891 | // alone tag
892 | os << "/>";
893 | }
894 | else
895 | {
896 | // and get child
897 | os << '>';
898 | if( opt && opt->newline && !childs.empty() )
899 | {
900 | opt->tab_base++;
901 | }
902 |
903 | for( size_t i = 0 ; i < childs.size(); i++ )
904 | os << (LPCTSTR)childs[i]->GetXML( opt ).c_str();
905 |
906 | // Text Value
907 | if( value != _T("") )
908 | {
909 | if( opt && opt->newline && !childs.empty() )
910 | {
911 | if( opt && opt->newline )
912 | os << _T("\r\n");
913 | if( opt )
914 | for( int i = 0 ; i < opt->tab_base ; i++)
915 | os << '\t';
916 | }
917 | if( opt )
918 | os << (LPCTSTR)(opt->reference_value&&opt->entities?opt->entities->Entity2Ref(value.c_str()).c_str():value.c_str());
919 | }
920 |
921 | // CloseTag
922 | if( opt && opt->newline && !childs.empty() )
923 | {
924 | os << "\r\n";
925 | for( int i = 0 ; i < opt->tab_base-1 ; i++)
926 | os << '\t';
927 | }
928 | os << "" << (LPCTSTR)name.c_str() << '>';
929 |
930 | if( opt && opt->newline )
931 | {
932 | if( !childs.empty() )
933 | opt->tab_base--;
934 | }
935 | }
936 |
937 | return os.str();
938 | }
939 |
940 | std::wstring _tagXMLNode::GetText( LPDISP_OPT opt /*= &optDefault*/ )
941 | {
942 | std::wostringstream os;
943 |
944 | if( type == XNODE_DOC )
945 | {
946 | for( size_t i = 0 ; i < childs.size(); i++ )
947 | os << (LPCTSTR)childs[i]->GetText( opt ).c_str();
948 | }
949 | else
950 | if( type == XNODE_PI )
951 | {
952 | // no text
953 | }
954 | else
955 | if( type == XNODE_COMMENT )
956 | {
957 | // no text
958 | }
959 | else
960 | if( type == XNODE_CDATA )
961 | {
962 | os << (LPCTSTR)value.c_str();
963 | }
964 | else
965 | if( type == XNODE_ELEMENT )
966 | {
967 | if( childs.empty() && value.empty() )
968 | {
969 | // no text
970 | }
971 | else
972 | {
973 | // childs text
974 | for( size_t i = 0 ; i < childs.size(); i++ )
975 | os << (LPCTSTR)childs[i]->GetText().c_str();
976 |
977 | // Text Value
978 | os << (LPCTSTR)(opt->reference_value&&opt->entities?opt->entities->Entity2Ref(value.c_str()).c_str():value.c_str());
979 | }
980 | }
981 |
982 | return os.str();
983 | }
984 |
985 | LPXAttr _tagXMLNode::GetAttr( LPCTSTR attrname )
986 | {
987 | for( size_t i = 0 ; i < attrs.size(); i++ )
988 | {
989 | LPXAttr attr = attrs[i];
990 | if( attr )
991 | {
992 | if( attr->name == attrname )
993 | return attr;
994 | }
995 | }
996 | return NULL;
997 | }
998 |
999 | XAttrs _tagXMLNode::GetAttrs( LPCTSTR nam )
1000 | {
1001 | XAttrs attr;
1002 | for( size_t i = 0 ; i < attr.size(); i++ )
1003 | {
1004 | LPXAttr att = attr[i];
1005 | if( att )
1006 | {
1007 | if( att->name == nam )
1008 | attr.push_back( att );
1009 | }
1010 | }
1011 | return attr;
1012 | }
1013 |
1014 | LPCTSTR _tagXMLNode::GetAttrValue( LPCTSTR attrname )
1015 | {
1016 | LPXAttr attr = GetAttr( attrname );
1017 | return attr ? (LPCTSTR)attr->value.c_str() : NULL;
1018 | }
1019 |
1020 | XNodes _tagXMLNode::GetChilds()
1021 | {
1022 | return childs;
1023 | }
1024 |
1025 | XNodes _tagXMLNode::GetChilds( LPCTSTR nam )
1026 | {
1027 | XNodes nodes;
1028 | for( size_t i = 0 ; i < childs.size(); i++ )
1029 | {
1030 | LPXNode node = childs[i];
1031 | if( node )
1032 | {
1033 | if( node->name == nam )
1034 | nodes.push_back( node );
1035 | }
1036 | }
1037 | return nodes;
1038 | }
1039 |
1040 | LPXNode _tagXMLNode::GetChild( int i )
1041 | {
1042 | if( i >= 0 && i < (int)childs.size() )
1043 | return childs[i];
1044 | return NULL;
1045 | }
1046 |
1047 | size_t _tagXMLNode::GetChildCount()
1048 | {
1049 | return childs.size();
1050 | }
1051 |
1052 | LPXNode _tagXMLNode::GetChild( LPCTSTR nam )
1053 | {
1054 | for( size_t i = 0 ; i < childs.size(); i++ )
1055 | {
1056 | LPXNode node = childs[i];
1057 | if( node )
1058 | {
1059 | if( node->name == nam )
1060 | return node;
1061 | }
1062 | }
1063 | return NULL;
1064 | }
1065 |
1066 | LPCTSTR _tagXMLNode::GetChildValue( LPCTSTR nam )
1067 | {
1068 | LPXNode node = GetChild( nam );
1069 | return (node != NULL)? (LPCTSTR)node->value.c_str() : NULL;
1070 | }
1071 |
1072 | std::wstring _tagXMLNode::GetChildText( LPCTSTR nam, LPDISP_OPT opt /*= &optDefault*/ )
1073 | {
1074 | LPXNode node = GetChild( nam );
1075 | return (node != NULL)? node->GetText(opt) : _T("");
1076 | }
1077 |
1078 | LPXAttr _tagXMLNode::GetChildAttr( LPCTSTR nam, LPCTSTR attrname )
1079 | {
1080 | LPXNode node = GetChild(nam);
1081 | return node ? node->GetAttr(attrname) : NULL;
1082 | }
1083 |
1084 | LPCTSTR _tagXMLNode::GetChildAttrValue( LPCTSTR nam, LPCTSTR attrname )
1085 | {
1086 | LPXAttr attr = GetChildAttr( nam, attrname );
1087 | return attr ? (LPCTSTR)attr->value.c_str() : NULL;
1088 | }
1089 |
1090 | LPXNode _tagXMLNode::Find( LPCTSTR nam )
1091 | {
1092 | XNodes::iterator it = childs.begin();
1093 | for( ; it != childs.end(); ++(it))
1094 | {
1095 | LPXNode child = *it;
1096 | if( child->name == nam )
1097 | return child;
1098 |
1099 | XNodes::iterator childit = child->childs.begin();
1100 | for( ; childit != child->childs.end(); ++(childit))
1101 | {
1102 | LPXNode find = child->Find( nam );
1103 | if( find != NULL )
1104 | return find;
1105 | }
1106 | }
1107 |
1108 | return NULL;
1109 | }
1110 |
1111 | XNodes::iterator _tagXMLNode::GetChildIterator( LPXNode node )
1112 | {
1113 | XNodes::iterator it = childs.begin();
1114 | for( ; it != childs.end() ; ++(it) )
1115 | {
1116 | if( *it == node )
1117 | return it;
1118 | }
1119 | return childs.end();
1120 | }
1121 |
1122 | LPXNode _tagXMLNode::AppendChild( LPCTSTR nam /*= NULL*/, LPCTSTR val /*= NULL*/ )
1123 | {
1124 | return AppendChild( CreateNode( nam, val ) );
1125 | }
1126 |
1127 | LPXNode _tagXMLNode::AppendChild( LPXNode node )
1128 | {
1129 | node->parent = this;
1130 | node->doc = doc;
1131 | childs.push_back( node );
1132 | return node;
1133 | }
1134 |
1135 | bool _tagXMLNode::RemoveChild( LPXNode node )
1136 | {
1137 | XNodes::iterator it = GetChildIterator( node );
1138 | if( it != childs.end() )
1139 | {
1140 | delete *it;
1141 | childs.erase( it );
1142 | return true;
1143 | }
1144 | return false;
1145 | }
1146 |
1147 | LPXAttr _tagXMLNode::GetAttr( int i )
1148 | {
1149 | if( i >= 0 && i < (int)attrs.size() )
1150 | return attrs[i];
1151 | return NULL;
1152 | }
1153 |
1154 | XAttrs::iterator _tagXMLNode::GetAttrIterator( LPXAttr attr )
1155 | {
1156 | XAttrs::iterator it = attrs.begin();
1157 | for( ; it != attrs.end() ; ++(it) )
1158 | {
1159 | if( *it == attr )
1160 | return it;
1161 | }
1162 | return attrs.end();
1163 | }
1164 |
1165 | LPXAttr _tagXMLNode::AppendAttr( LPXAttr attr )
1166 | {
1167 | attr->parent = this;
1168 | attrs.push_back( attr );
1169 | return attr;
1170 | }
1171 |
1172 | bool _tagXMLNode::RemoveAttr( LPXAttr attr )
1173 | {
1174 | XAttrs::iterator it = GetAttrIterator( attr );
1175 | if( it != attrs.end() )
1176 | {
1177 | delete *it;
1178 | attrs.erase( it );
1179 | return true;
1180 | }
1181 | return false;
1182 | }
1183 |
1184 | LPXNode _tagXMLNode::CreateNode( LPCTSTR nam /*= NULL*/, LPCTSTR val /*= NULL*/ )
1185 | {
1186 | LPXNode node = new XNode;
1187 | node->name = nam;
1188 | node->value = val;
1189 | return node;
1190 | }
1191 |
1192 | LPXAttr _tagXMLNode::CreateAttr( LPCTSTR nam /*= NULL*/, LPCTSTR val /*= NULL*/ )
1193 | {
1194 | LPXAttr attr = new XAttr;
1195 | attr->name = nam;
1196 | attr->value = val;
1197 | return attr;
1198 | }
1199 |
1200 | LPXAttr _tagXMLNode::AppendAttr( LPCTSTR nam /*= NULL*/, LPCTSTR val /*= NULL*/ )
1201 | {
1202 | return AppendAttr( CreateAttr( nam, val ) );
1203 | }
1204 |
1205 | LPXNode _tagXMLNode::DetachChild( LPXNode node )
1206 | {
1207 | XNodes::iterator it = GetChildIterator( node );
1208 | if( it != childs.end() )
1209 | {
1210 | childs.erase( it );
1211 | return node;
1212 | }
1213 | return NULL;
1214 | }
1215 |
1216 | LPXAttr _tagXMLNode::DetachAttr( LPXAttr attr )
1217 | {
1218 | XAttrs::iterator it = GetAttrIterator( attr );
1219 | if( it != attrs.end() )
1220 | {
1221 | attrs.erase( it );
1222 | return attr;
1223 | }
1224 | return NULL;
1225 | }
1226 |
1227 | void _tagXMLNode::CopyNode( LPXNode node )
1228 | {
1229 | Close();
1230 |
1231 | doc = node->doc;
1232 | parent = node->parent;
1233 | name = node->name;
1234 | value = node->value;
1235 | type = node->type;
1236 |
1237 | // copy attributes
1238 | for( size_t i = 0 ; i < node->attrs.size(); i++)
1239 | {
1240 | LPXAttr attr = node->attrs[i];
1241 | if( attr )
1242 | AppendAttr( attr->name.c_str(), attr->value.c_str() );
1243 | }
1244 | }
1245 |
1246 | void _tagXMLNode::_CopyBranch( LPXNode node )
1247 | {
1248 | CopyNode( node );
1249 |
1250 | for( size_t i = 0 ; i < node->childs.size(); i++)
1251 | {
1252 | LPXNode child = node->childs[i];
1253 | if( child )
1254 | {
1255 | LPXNode mychild = new XNode;
1256 | mychild->CopyNode( child );
1257 | AppendChild( mychild );
1258 |
1259 | mychild->_CopyBranch( child );
1260 | }
1261 | }
1262 | }
1263 |
1264 | LPXNode _tagXMLNode::AppendChildBranch( LPXNode node )
1265 | {
1266 | LPXNode child = new XNode;
1267 | child->CopyBranch( node );
1268 |
1269 | return AppendChild( child );
1270 | }
1271 |
1272 | void _tagXMLNode::CopyBranch( LPXNode branch )
1273 | {
1274 | Close();
1275 |
1276 | _CopyBranch( branch );
1277 | }
1278 |
1279 |
1280 | _tagXMLEntitys::_tagXMLEntitys( LPXENTITY entities, int count )
1281 | {
1282 | for( int i = 0; i < count; i++)
1283 | push_back( entities[i] );
1284 | }
1285 |
1286 | LPXENTITY _tagXMLEntitys::GetEntity( int entity )
1287 | {
1288 | for( size_t i = 0 ; i < size(); i ++ )
1289 | {
1290 | if( at(i).entity == entity )
1291 | return LPXENTITY(&at(i));
1292 | }
1293 | return NULL;
1294 | }
1295 |
1296 | LPXENTITY _tagXMLEntitys::GetEntity( LPTSTR entity )
1297 | {
1298 | for( size_t i = 0 ; i < size(); i ++ )
1299 | {
1300 | LPTSTR ref = (LPTSTR)at(i).ref;
1301 | LPTSTR ps = entity;
1302 | while( ref && *ref )
1303 | if( *ref++ != *ps++ )
1304 | break;
1305 | if( ref && !*ref ) // found!
1306 | return LPXENTITY(&at(i));
1307 | }
1308 | return NULL;
1309 | }
1310 |
1311 | size_t _tagXMLEntitys::GetEntityCount( LPCTSTR str )
1312 | {
1313 | int nCount = 0;
1314 | LPTSTR ps = (LPTSTR)str;
1315 | while( ps && *ps )
1316 | if( GetEntity( *ps++ ) ) nCount ++;
1317 | return nCount;
1318 | }
1319 |
1320 | size_t _tagXMLEntitys::Ref2Entity( LPCTSTR estr, LPTSTR str, size_t strlen )
1321 | {
1322 | LPTSTR pes = (LPTSTR)estr;
1323 | LPTSTR ps = str;
1324 | LPTSTR ps_end = ps+strlen;
1325 | while( pes && *pes && ps < ps_end )
1326 | {
1327 | LPXENTITY ent = GetEntity( pes );
1328 | if( ent )
1329 | {
1330 | // copy entity meanning char
1331 | *ps = ent->entity;
1332 | pes += ent->ref_len;
1333 | }
1334 | else
1335 | *ps = *pes++; // default character copy
1336 | ps++;
1337 | }
1338 | *ps = '\0';
1339 |
1340 | // total copied characters
1341 | return ps-str;
1342 | }
1343 |
1344 | size_t _tagXMLEntitys::Entity2Ref( LPCTSTR str, LPTSTR estr, size_t estrlen )
1345 | {
1346 | LPTSTR ps = (LPTSTR)str;
1347 | LPTSTR pes = (LPTSTR)estr;
1348 | LPTSTR pes_end = pes+estrlen;
1349 | while( ps && *ps && pes < pes_end )
1350 | {
1351 | LPXENTITY ent = GetEntity( *ps );
1352 | if( ent )
1353 | {
1354 | // copy entity string
1355 | LPTSTR ref = (LPTSTR)ent->ref;
1356 | while( ref && *ref )
1357 | *pes++ = *ref++;
1358 | }
1359 | else
1360 | *pes++ = *ps; // default character copy
1361 | ps++;
1362 | }
1363 | *pes = '\0';
1364 |
1365 | // total copied characters
1366 | return pes-estr;
1367 | }
1368 |
1369 | std::wstring _tagXMLEntitys::Ref2Entity( LPCTSTR estr )
1370 | {
1371 | std::wstring es;
1372 | if( estr )
1373 | {
1374 | size_t len = _tcslen(estr);
1375 | auto_buffer esbuf (len + 1);
1376 | if( esbuf )
1377 | {
1378 | Ref2Entity( estr, esbuf, len );
1379 | es = esbuf.get();
1380 | }
1381 | }
1382 | return es;
1383 | }
1384 |
1385 | std::wstring _tagXMLEntitys::Entity2Ref( LPCTSTR str )
1386 | {
1387 | std::wstring s;
1388 | if( str )
1389 | {
1390 | size_t nEntityCount = GetEntityCount(str);
1391 | if( nEntityCount == 0 )
1392 | return std::wstring(str);
1393 | size_t len = _tcslen(str) + nEntityCount*10 ;
1394 | auto_buffer sbuf (len + 1);
1395 | if( sbuf )
1396 | {
1397 | Entity2Ref( str, sbuf, len );
1398 | s = sbuf.get();
1399 | }
1400 | }
1401 | return s;
1402 | }
1403 |
1404 | std::wstring XRef2Entity( LPCTSTR estr )
1405 | {
1406 | return entityDefault.Ref2Entity( estr );
1407 | }
1408 |
1409 | std::wstring XEntity2Ref( LPCTSTR str )
1410 | {
1411 | return entityDefault.Entity2Ref( str );
1412 | }
1413 |
--------------------------------------------------------------------------------
/src/XMLite.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "StringUtils.h"
3 | #include
4 | #include
5 | #include
6 |
7 | struct _tagXMLAttr;
8 | typedef _tagXMLAttr XAttr, *LPXAttr;
9 | typedef std::vector XAttrs;
10 |
11 | struct _tagXMLNode;
12 | typedef _tagXMLNode XNode, *LPXNode;
13 | typedef std::vector XNodes, *LPXNodes;
14 |
15 | struct _tagXMLDocument;
16 | typedef struct _tagXMLDocument XDoc, *LPXDoc;
17 |
18 | // Entity Encode/Decode Support
19 | typedef struct _tagXmlEntity
20 | {
21 | TCHAR entity; // entity ( & " ' < > )
22 | TCHAR ref[10]; // entity reference ( & " etc )
23 | int ref_len; // entity reference length
24 | }XENTITY,*LPXENTITY;
25 |
26 | typedef struct _tagXMLEntitys : public std::vector
27 | {
28 | LPXENTITY GetEntity( int entity );
29 | LPXENTITY GetEntity( LPTSTR entity );
30 | size_t GetEntityCount( LPCTSTR str );
31 | size_t Ref2Entity( LPCTSTR estr, LPTSTR str, size_t strlen );
32 | size_t Entity2Ref( LPCTSTR str, LPTSTR estr, size_t estrlen );
33 | std::wstring Ref2Entity( LPCTSTR estr );
34 | std::wstring Entity2Ref( LPCTSTR str );
35 |
36 | _tagXMLEntitys(){};
37 | _tagXMLEntitys( LPXENTITY entities, int count );
38 | }XENTITYS,*LPXENTITYS;
39 | extern XENTITYS entityDefault;
40 | std::wstring XRef2Entity( LPCTSTR estr );
41 | std::wstring XEntity2Ref( LPCTSTR str );
42 |
43 | typedef enum
44 | {
45 | PIE_PARSE_WELFORMED = 0,
46 | PIE_ALONE_NOT_CLOSED,
47 | PIE_NOT_CLOSED,
48 | PIE_NOT_NESTED,
49 | PIE_ATTR_NO_VALUE
50 | }PCODE;
51 |
52 | // Parse info.
53 | typedef struct _tagParseInfo
54 | {
55 | bool trim_value; // [set] do trim when parse?
56 | bool entity_value; // [set] do convert from reference to entity? ( < -> < )
57 | LPXENTITYS entities; // [set] entity table for entity decode
58 | TCHAR escape_value; // [set] escape value (default '\\')
59 | bool force_parse; // [set] force parse even if xml is not welformed
60 |
61 | LPTSTR xml; // [get] xml source
62 | bool error_occur; // [get] is occurance of error?
63 | LPTSTR error_pointer; // [get] error position of xml source
64 | PCODE error_code; // [get] error code
65 | std::wstring error_string; // [get] error string
66 |
67 | LPXDoc doc;
68 | _tagParseInfo() { trim_value = false; entity_value = true; force_parse = false; entities = &entityDefault; xml = NULL; doc = NULL; error_occur = false; error_pointer = NULL; error_code = PIE_PARSE_WELFORMED; escape_value = '\\'; }
69 | }PARSEINFO,*LPPARSEINFO;
70 | extern PARSEINFO piDefault;
71 |
72 | // display optional environment
73 | typedef struct _tagDispOption
74 | {
75 | bool newline; // newline when new tag
76 | bool reference_value; // do convert from entity to reference ( < -> < )
77 | TCHAR value_quotation_mark; // val="" (default value quotation mark "
78 | LPXENTITYS entities; // entity table for entity encode
79 |
80 | int tab_base; // internal usage
81 | _tagDispOption() { newline = true; reference_value = true; entities = &entityDefault; tab_base = 0; value_quotation_mark = '"'; }
82 | }DISP_OPT, *LPDISP_OPT;
83 | extern DISP_OPT optDefault;
84 |
85 | // XAttr : Attribute Implementation
86 | typedef struct _tagXMLAttr
87 | {
88 | std::wstring name;
89 | std::wstring value;
90 |
91 | _tagXMLNode* parent;
92 |
93 | std::wstring GetXML( LPDISP_OPT opt = &optDefault );
94 | }XAttr, *LPXAttr;
95 |
96 | typedef enum
97 | {
98 | XNODE_ELEMENT, // general node '...' or
99 | XNODE_PI, //
100 | XNODE_COMMENT, //
101 | XNODE_CDATA, //
102 | XNODE_DOC, // internal virtual root
103 | }NODE_TYPE;
104 |
105 | // XMLNode structure
106 | typedef struct _tagXMLNode
107 | {
108 | // name and value
109 | std::wstring name;
110 | std::wstring value;
111 |
112 | // internal variables
113 | LPXNode parent; // parent node
114 | XNodes childs; // child node
115 | XAttrs attrs; // attributes
116 | NODE_TYPE type; // node type
117 | LPXDoc doc; // document
118 |
119 | // Load/Save XML
120 | LPTSTR Load( LPCTSTR pszXml, LPPARSEINFO pi = &piDefault );
121 | std::wstring GetXML( LPDISP_OPT opt = &optDefault );
122 | std::wstring GetText( LPDISP_OPT opt = &optDefault );
123 |
124 | // internal load functions
125 | LPTSTR LoadAttributes( LPCTSTR pszAttrs, LPPARSEINFO pi = &piDefault );
126 | LPTSTR LoadAttributes( LPCTSTR pszAttrs, LPCTSTR pszEnd, LPPARSEINFO pi = &piDefault );
127 | LPTSTR LoadProcessingInstrunction( LPCTSTR pszXml, LPPARSEINFO pi = &piDefault );
128 | LPTSTR LoadComment( LPCTSTR pszXml, LPPARSEINFO pi = &piDefault );
129 | LPTSTR LoadCDATA( LPCTSTR pszXml, LPPARSEINFO pi = &piDefault );
130 |
131 | // in own attribute list
132 | LPXAttr GetAttr( LPCTSTR attrname );
133 | LPCTSTR GetAttrValue( LPCTSTR attrname );
134 | XAttrs GetAttrs( LPCTSTR name );
135 |
136 | // in one level child nodes
137 | LPXNode GetChild( LPCTSTR name );
138 | LPCTSTR GetChildValue( LPCTSTR name );
139 | std::wstring GetChildText( LPCTSTR name, LPDISP_OPT opt = &optDefault );
140 | XNodes GetChilds( LPCTSTR name );
141 | XNodes GetChilds();
142 |
143 | LPXAttr GetChildAttr( LPCTSTR name, LPCTSTR attrname );
144 | LPCTSTR GetChildAttrValue( LPCTSTR name, LPCTSTR attrname );
145 |
146 | // search node
147 | LPXNode Find( LPCTSTR name );
148 |
149 | // modify DOM
150 | size_t GetChildCount();
151 | LPXNode GetChild( int i );
152 | XNodes::iterator GetChildIterator( LPXNode node );
153 | LPXNode CreateNode( LPCTSTR name = NULL, LPCTSTR value = NULL );
154 | LPXNode AppendChild( LPCTSTR name = NULL, LPCTSTR value = NULL );
155 | LPXNode AppendChild( LPXNode node );
156 | bool RemoveChild( LPXNode node );
157 | LPXNode DetachChild( LPXNode node );
158 |
159 | // node/branch copy
160 | void CopyNode( LPXNode node );
161 | void CopyBranch( LPXNode branch );
162 | void _CopyBranch( LPXNode node );
163 | LPXNode AppendChildBranch( LPXNode node );
164 |
165 | // modify attribute
166 | LPXAttr GetAttr( int i );
167 | XAttrs::iterator GetAttrIterator( LPXAttr node );
168 | LPXAttr CreateAttr( LPCTSTR anem = NULL, LPCTSTR value = NULL );
169 | LPXAttr AppendAttr( LPCTSTR name = NULL, LPCTSTR value = NULL );
170 | LPXAttr AppendAttr( LPXAttr attr );
171 | bool RemoveAttr( LPXAttr attr );
172 | LPXAttr DetachAttr( LPXAttr attr );
173 |
174 | // operator overloads
175 | LPXNode operator [] ( int i ) { return GetChild(i); }
176 | XNode& operator = ( XNode& node ) { CopyBranch(&node); return *this; }
177 |
178 | _tagXMLNode() { parent = NULL; doc = NULL; type = XNODE_ELEMENT; }
179 | ~_tagXMLNode();
180 |
181 | void Close();
182 | }XNode, *LPXNode;
183 |
184 | // XMLDocument structure
185 | typedef struct _tagXMLDocument : public XNode
186 | {
187 | PARSEINFO parse_info;
188 |
189 | _tagXMLDocument() { parent = NULL; doc = this; type = XNODE_DOC; }
190 |
191 | LPTSTR Load( LPCTSTR pszXml, LPPARSEINFO pi = NULL );
192 | LPXNode GetRoot();
193 |
194 | }XDoc, *LPXDoc;
195 |
196 | // Helper Funtion
197 | inline long XStr2Int( LPCTSTR str, long default_value = 0 )
198 | {
199 | return ( str && *str ) ? _ttol(str) : default_value;
200 | }
201 |
202 | inline bool XIsEmptyString( LPCTSTR str )
203 | {
204 | std::wstring s(str);
205 | CStringUtils::trim(s);
206 |
207 | return ( s.empty() || s == _T("") );
208 | }
209 |
--------------------------------------------------------------------------------
/src/auto_buffer.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 |
22 | /**
23 | * A simplified analog to std::auto_ptr<> that encapsulates
24 | * an array allocated dynamically via new[].
25 | *
26 | * Use this where you could not use a std::auto_ptr<> (works
27 | * for single elements only) nor a std::vector<> (no guarantees
28 | * w.r.t. to internal organization, i.e. no access to mem buffer).
29 | */
30 |
31 | template
32 | class auto_buffer
33 | {
34 | private:
35 |
36 | T* buffer;
37 |
38 | /// no copy nor assignment
39 |
40 | auto_buffer(const auto_buffer&);
41 | auto_buffer& operator=(const auto_buffer&);
42 |
43 | public:
44 |
45 | explicit auto_buffer (size_t size = 0) throw()
46 | : buffer (size == 0 ? NULL : new T[size])
47 | {
48 | }
49 |
50 | ~auto_buffer()
51 | {
52 | delete[] buffer;
53 | }
54 |
55 | operator T*() const throw()
56 | {
57 | return buffer;
58 | }
59 |
60 | operator void*() const throw()
61 | {
62 | return buffer;
63 | }
64 |
65 | operator bool() const throw()
66 | {
67 | return buffer != NULL;
68 | }
69 |
70 | T* operator->() const throw()
71 | {
72 | return buffer;
73 | }
74 |
75 | T *get() const throw()
76 | {
77 | return buffer;
78 | }
79 |
80 | T* release() throw()
81 | {
82 | T* temp = buffer;
83 | buffer = NULL;
84 | return temp;
85 | }
86 |
87 | void reset (size_t newSize = 0)
88 | {
89 | delete[] buffer;
90 | buffer = (newSize == 0 ? NULL : new T[newSize]);
91 | }
92 | };
93 |
--------------------------------------------------------------------------------
/src/compatibility.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/last/version.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2018 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 |
22 | // this file is used if the NAnt script didn't run and
23 | // didn't create the real version.h file.
24 | // only needed if users don't need correct version info
25 | // or for the continuous integration servers where NAnt and TGit isn't available
26 |
27 | #define FILEVER 1, 0, 0, 0
28 | #define PRODUCTVER 1, 0, 0, 0
29 | #define STRFILEVER "1.0.0.0\0"
30 | #define STRPRODUCTVER "1.0.0.0\0"
31 |
32 | #define SM_VERMAJOR 1
33 | #define SM_VERMINOR 0
34 | #define SM_VERMICRO 0
35 | #define SM_VERBUILD 0
36 | #define SM_VERDATE "2000/01/01 00:00:00"
37 |
--------------------------------------------------------------------------------
/src/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by SendMessage.rc
4 | //
5 | #define IDC_MYICON 2
6 | #define IDD_SENDMESSAGE_DIALOG 102
7 | #define IDD_ABOUTBOX 103
8 | #define IDM_ABOUT 104
9 | #define IDI_SENDMESSAGE 107
10 | #define IDC_SENDMESSAGE 109
11 | #define IDR_MAINFRAME 128
12 | #define IDD_MAINDLG 129
13 | #define IDR_ACCELERATOR1 130
14 | #define IDR_MAINDLG 130
15 | #define IDI_SEARCHW 131
16 | #define IDR_WINDOWMESSAGESXML 133
17 | #define IDD_WINDOWSTREE 134
18 | #define IDC_WEBLINK 1000
19 | #define IDC_VERSIONINFO 1001
20 | #define IDC_DATE 1002
21 | #define IDC_SEARCHW 1003
22 | #define IDC_STATIC_X_POS 1004
23 | #define IDC_STATIC_Y_POS 1005
24 | #define IDC_EDIT_STATUS 1006
25 | #define IDC_WINDOW 1007
26 | #define IDC_MESSAGE 1008
27 | #define IDC_WPARAM 1009
28 | #define IDC_LPARAM 1010
29 | #define IDC_POSTMESSAGE 1012
30 | #define IDC_RETVALUE 1013
31 | #define IDC_SENDGROUP 1014
32 | #define IDC_ABOUTLINK 1015
33 | #define IDC_POS 1016
34 | #define IDC_PINWINDOW 1017
35 | #define IDC_UNPINWINDOW 1018
36 | #define IDC_SHOWWINDOW 1019
37 | #define IDC_CMDSHOW 1020
38 | #define IDC_ERROR 1024
39 | #define IDC_WINDOWTREE 1025
40 | #define IDC_REFRESH 1026
41 | #define IDC_FILTER 1027
42 | #define IDC_STATIC -1
43 |
44 | // Next default values for new objects
45 | //
46 | #ifdef APSTUDIO_INVOKED
47 | #ifndef APSTUDIO_READONLY_SYMBOLS
48 | #define _APS_NO_MFC 1
49 | #define _APS_NEXT_RESOURCE_VALUE 135
50 | #define _APS_NEXT_COMMAND_VALUE 32772
51 | #define _APS_NEXT_CONTROL_VALUE 1028
52 | #define _APS_NEXT_SYMED_VALUE 110
53 | #endif
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/resources/SendMessage.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefankueng/sendmessage/9c546bc59fb5473646b93d05b69923d9a5de5245/src/resources/SendMessage.ico
--------------------------------------------------------------------------------
/src/resources/searchw.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefankueng/sendmessage/9c546bc59fb5473646b93d05b69923d9a5de5245/src/resources/searchw.cur
--------------------------------------------------------------------------------
/src/resources/searchw.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefankueng/sendmessage/9c546bc59fb5473646b93d05b69923d9a5de5245/src/resources/searchw.ico
--------------------------------------------------------------------------------
/src/resources/windowmessages.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
--------------------------------------------------------------------------------
/src/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #include "stdafx.h"
21 |
--------------------------------------------------------------------------------
/src/stdafx.h:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 |
22 |
23 | // Including SDKDDKVer.h defines the highest available Windows platform.
24 |
25 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
26 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
27 |
28 | #include
29 |
30 |
31 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
32 | // Windows Header Files:
33 | #include
34 | #include
35 | #include
36 |
37 | // C RunTime Header Files
38 | #include
39 | #include
40 | #include
41 | #include
42 |
43 |
44 | #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
45 |
--------------------------------------------------------------------------------
/src/version.in:
--------------------------------------------------------------------------------
1 | // SendMessage - a tool to send custom messages
2 |
3 | // Copyright (C) 2010-2012 - Stefan Kueng
4 |
5 | // This program is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU General Public License
7 | // as published by the Free Software Foundation; either version 2
8 | // of the License, or (at your option) any later version.
9 |
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 |
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software Foundation,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | //
19 |
20 | #pragma once
21 |
22 | #define FILEVER $MajorVersion$, $MinorVersion$, $MicroVersion$, $WCREV$
23 | #define PRODUCTVER $MajorVersion$, $MinorVersion$, $MicroVersion$, $WCREV$
24 | #define STRFILEVER "$MajorVersion$.$MinorVersion$.$MicroVersion$.$WCREV$\0"
25 | #define STRPRODUCTVER "$MajorVersion$.$MinorVersion$.$MicroVersion$.$WCREV$\0"
26 |
27 | #define SM_VERMAJOR $MajorVersion$
28 | #define SM_VERMINOR $MinorVersion$
29 | #define SM_VERMICRO $MicroVersion$
30 | #define SM_VERBUILD $WCREV$
31 | #define SM_VERDATE "$WCDATE$"
32 |
--------------------------------------------------------------------------------
/tools/checkyear.js:
--------------------------------------------------------------------------------
1 | /* This script is a local pre-commit hook script.
2 | * It's used to check whether the copyright year of modified files has been
3 | * bumped up to the current year.
4 | *
5 | * Only *.cpp, *.h and *.idl files are checked
6 | *
7 | * Set the local hook scripts like this (pre-commit hook):
8 | * WScript path/to/this/script/file.js
9 | * and set "Wait for the script to finish"
10 | */
11 |
12 | var forReading = 1;
13 | var objArgs = WScript.Arguments;
14 | var num = objArgs.length;
15 |
16 | if (num !== 4 && num !== 3)
17 | {
18 | WScript.Echo("Usage: [CScript | WScript] checkyear.js path/to/pathsfile depth path/to/messagefile path/to/CWD");
19 | WScript.Quit(1);
20 | }
21 |
22 | var currentyear = new Date().getFullYear();
23 | var re = new RegExp('^(\\\/\\\/|#) Copyright.+(' + currentyear + ')(.*)');
24 | var basere = /^\/\/ Copyright(.*)/;
25 | var filere = /(\.cpp$)|(\.h$)|(\.idl$)/;
26 |
27 | // readFileLines
28 | function readPaths(path)
29 | {
30 | var retPaths = [];
31 | var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
32 |
33 | if (fileSystem.FileExists(path))
34 | {
35 | var textFile = fileSystem.OpenTextFile(path, forReading);
36 |
37 | while (!textFile.AtEndOfStream)
38 | {
39 | var line = textFile.ReadLine();
40 |
41 | retPaths.push(line);
42 | }
43 | textFile.Close();
44 | }
45 | return retPaths;
46 | }
47 |
48 | var found = true;
49 | var files = readPaths(objArgs(0));
50 | var fileIndex = files.length;
51 | var errorMessage = "";
52 |
53 | while (fileIndex--)
54 | {
55 | var f = files[fileIndex];
56 | var fso = new ActiveXObject("Scripting.FileSystemObject");
57 |
58 | if (f.match(filere) !== null)
59 | {
60 | if (fso.FileExists(f))
61 | {
62 | var a = fso.OpenTextFile(f, forReading, false);
63 | var copyrightFound = false;
64 | var yearFound = false;
65 |
66 | while (!a.AtEndOfStream && !yearFound)
67 | {
68 | var r = a.ReadLine();
69 | var rv = r.match(basere);
70 |
71 | if (rv !== null)
72 | {
73 | rv = r.match(re);
74 | if (rv !== null)
75 | {
76 | yearFound = true;
77 | }
78 |
79 | copyrightFound = true;
80 | }
81 | }
82 | a.Close();
83 |
84 | if (copyrightFound && !yearFound)
85 | {
86 | if (errorMessage !== "")
87 | {
88 | errorMessage += "\n";
89 | }
90 | errorMessage += f;
91 | found = false;
92 | }
93 | }
94 | }
95 | }
96 |
97 | if (found === false)
98 | {
99 | errorMessage = "the file(s):\n" + errorMessage + "\nhave not the correct copyright year!";
100 | WScript.stderr.writeLine(errorMessage);
101 | }
102 |
103 | WScript.Quit(!found);
104 |
--------------------------------------------------------------------------------
/tools/coverity.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | pushd %~dp0
5 |
6 | rem you can set the COVDIR variable to your coverity path
7 | if not defined COVDIR set "COVDIR=C:\cov-analysis"
8 | if defined COVDIR if not exist "%COVDIR%" (
9 | echo.
10 | echo ERROR: Coverity not found in "%COVDIR%"
11 | goto End
12 | )
13 |
14 | rem add the tools paths in PATH
15 | set "NANT_PATH=C:\nant\bin"
16 | set "PERL_PATH=C:\Perl\perl\bin"
17 | set "PYTHON_PATH=C:\Python27"
18 | set "PATH=%NANT_PATH%;%PERL_PATH%;%PYTHON_PATH%;%PATH%"
19 |
20 |
21 | :cleanup
22 | if exist "cov-int" rd /q /s "cov-int"
23 | if exist "SendMessage.lzma" del "SendMessage.lzma"
24 | if exist "SendMessage.tar" del "SendMessage.tar"
25 | if exist "SendMessage.tgz" del "SendMessage.tgz"
26 |
27 |
28 | :main
29 | call "%VS140COMNTOOLS%\vsvars32.bat"
30 | if %ERRORLEVEL% neq 0 (
31 | echo vsvars32.bat call failed.
32 | goto End
33 | )
34 |
35 | rem the actual coverity command
36 | title "%COVDIR%\bin\cov-build.exe" --dir "cov-int" nant -buildfile:..\default.build SendMessage
37 | "%COVDIR%\bin\cov-build.exe" --dir "cov-int" nant -buildfile:..\default.build SendMessage
38 |
39 |
40 | :tar
41 | rem try the tar tool in case it's in PATH
42 | set PATH=C:\MSYS\bin;%PATH%
43 | tar --version 1>&2 2>nul || (echo. & echo ERROR: tar not found & goto SevenZip)
44 | title Creating "SendMessage.lzma"...
45 | tar caf "SendMessage.lzma" "cov-int"
46 | goto End
47 |
48 |
49 | :SevenZip
50 | call :SubDetectSevenzipPath
51 |
52 | rem Coverity is totally bogus with lzma...
53 | rem And since I cannot replicate the arguments with 7-Zip, just use tar/gzip.
54 | if exist "%SEVENZIP%" (
55 | title Creating "SendMessage.tar"...
56 | "%SEVENZIP%" a -ttar "SendMessage.tar" "cov-int"
57 | "%SEVENZIP%" a -tgzip "SendMessage.tgz" "SendMessage.tar"
58 | if exist "SendMessage.tar" del "SendMessage.tar"
59 | goto End
60 | )
61 |
62 |
63 | :SubDetectSevenzipPath
64 | for %%g in (7z.exe) do (set "SEVENZIP_PATH=%%~$path:g")
65 | if exist "%SEVENZIP_PATH%" (set "SEVENZIP=%SEVENZIP_PATH%" & exit /b)
66 |
67 | for %%g in (7za.exe) do (set "SEVENZIP_PATH=%%~$path:g")
68 | if exist "%SEVENZIP_PATH%" (set "SEVENZIP=%SEVENZIP_PATH%" & exit /b)
69 |
70 | for /f "tokens=2*" %%a in (
71 | 'reg query "HKLM\SOFTWARE\7-Zip" /v "path" 2^>nul ^| find "REG_SZ" ^|^|
72 | reg query "HKLM\SOFTWARE\Wow6432Node\7-Zip" /v "path" 2^>nul ^| find "REG_SZ"') do set "SEVENZIP=%%b\7z.exe"
73 | exit /b
74 |
75 |
76 | :End
77 | popd
78 | echo. & echo Press any key to close this window...
79 | pause >nul
80 | endlocal
81 | exit /b
82 |
--------------------------------------------------------------------------------
/version.build.in:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/versioninfo.build:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------