├── .gitattributes
├── .gitignore
├── AcrylicMenus.sln
├── AcrylicMenus
├── AcrylicHelper.h
├── AcrylicMenus.vcxproj
├── AcrylicMenus.vcxproj.filters
├── AppearanceConfiguration.h
├── DetoursHelper.h
├── MenuHandler.cpp
├── MenuHandler.h
├── MenuHooks.cpp
├── MenuHooks.h
├── MenuManager.cpp
├── MenuManager.h
├── Resource.rc
├── SettingsHelper.h
├── SystemHelper.h
├── ThemeHelper.h
├── WindowHelper.h
├── amapi.cpp
├── amapi.h
├── dllmain.cpp
├── packages.config
├── pch.cpp
├── pch.h
└── resource.h
├── AcrylicMenusLoader
├── AcrylicMenusLoader.cpp
├── AcrylicMenusLoader.vcxproj
├── AcrylicMenusLoader.vcxproj.filters
├── Resource.rc
└── resource.h
├── LICENSE
├── README.md
└── github-images
├── win10.png
└── win11.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/AcrylicMenus.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.32510.428
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AcrylicMenus", "AcrylicMenus\AcrylicMenus.vcxproj", "{97391729-9A04-40B0-9C0F-98FA395127AB}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AcrylicMenusLoader", "AcrylicMenusLoader\AcrylicMenusLoader.vcxproj", "{0179CDEA-F39C-453B-AE1D-01590BC9FE4A}"
9 | ProjectSection(ProjectDependencies) = postProject
10 | {97391729-9A04-40B0-9C0F-98FA395127AB} = {97391729-9A04-40B0-9C0F-98FA395127AB}
11 | EndProjectSection
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|x64 = Release|x64
18 | Release|x86 = Release|x86
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Debug|x64.ActiveCfg = Debug|x64
22 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Debug|x64.Build.0 = Debug|x64
23 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Debug|x86.ActiveCfg = Debug|Win32
24 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Debug|x86.Build.0 = Debug|Win32
25 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Release|x64.ActiveCfg = Release|x64
26 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Release|x64.Build.0 = Release|x64
27 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Release|x86.ActiveCfg = Release|Win32
28 | {97391729-9A04-40B0-9C0F-98FA395127AB}.Release|x86.Build.0 = Release|Win32
29 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Debug|x64.ActiveCfg = Debug|x64
30 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Debug|x64.Build.0 = Debug|x64
31 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Debug|x86.ActiveCfg = Debug|Win32
32 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Debug|x86.Build.0 = Debug|Win32
33 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Release|x64.ActiveCfg = Release|x64
34 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Release|x64.Build.0 = Release|x64
35 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Release|x86.ActiveCfg = Release|Win32
36 | {0179CDEA-F39C-453B-AE1D-01590BC9FE4A}.Release|x86.Build.0 = Release|Win32
37 | EndGlobalSection
38 | GlobalSection(SolutionProperties) = preSolution
39 | HideSolutionNode = FALSE
40 | EndGlobalSection
41 | GlobalSection(ExtensibilityGlobals) = postSolution
42 | SolutionGuid = {0A638377-CC3C-46C4-964C-31238394D52B}
43 | EndGlobalSection
44 | EndGlobal
45 |
--------------------------------------------------------------------------------
/AcrylicMenus/AcrylicHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 | #include "SystemHelper.h"
4 | #include "AppearanceConfiguration.h"
5 |
6 | namespace AcrylicMenus
7 | {
8 | namespace AcrylicHelper
9 | {
10 | typedef enum _WINDOWCOMPOSITIONATTRIBUTE
11 | {
12 | WCA_UNDEFINED,
13 | WCA_NCRENDERING_ENABLED,
14 | WCA_NCRENDERING_POLICY,
15 | WCA_TRANSITIONS_FORCEDISABLED,
16 | WCA_ALLOW_NCPAINT,
17 | WCA_CAPTION_BUTTON_BOUNDS,
18 | WCA_NONCLIENT_RTL_LAYOUT,
19 | WCA_FORCE_ICONIC_REPRESENTATION,
20 | WCA_EXTENDED_FRAME_BOUNDS,
21 | WCA_HAS_ICONIC_BITMAP,
22 | WCA_THEME_ATTRIBUTES,
23 | WCA_NCRENDERING_EXILED,
24 | WCA_NCADORNMENTINFO,
25 | WCA_EXCLUDED_FROM_LIVEPREVIEW,
26 | WCA_VIDEO_OVERLAY_ACTIVE,
27 | WCA_FORCE_ACTIVEWINDOW_APPEARANCE,
28 | WCA_DISALLOW_PEEK,
29 | WCA_CLOAK,
30 | WCA_CLOAKED,
31 | WCA_ACCENT_POLICY,
32 | WCA_FREEZE_REPRESENTATION,
33 | WCA_EVER_UNCLOAKED,
34 | WCA_VISUAL_OWNER,
35 | WCA_HOLOGRAPHIC,
36 | WCA_EXCLUDED_FROM_DDA,
37 | WCA_PASSIVEUPDATEMODE,
38 | WCA_USEDARKMODECOLORS,
39 | WCA_CORNER_STYLE,
40 | WCA_PART_COLOR,
41 | WCA_DISABLE_MOVESIZE_FEEDBACK,
42 | WCA_LAST
43 | } WINDOWCOMPOSITIONATTRIBUTE;
44 |
45 | typedef struct _WINDOWCOMPOSITIONATTRIBUTEDATA
46 | {
47 | WINDOWCOMPOSITIONATTRIBUTE Attribute;
48 | PVOID pvData;
49 | SIZE_T cbData;
50 | } WINDOWCOMPOSITIONATTRIBUTEDATA;
51 |
52 | typedef enum _ACCENT_STATE
53 | {
54 | ACCENT_DISABLED,
55 | ACCENT_ENABLE_GRADIENT,
56 | ACCENT_ENABLE_TRANSPARENTGRADIENT,
57 | ACCENT_ENABLE_BLURBEHIND,
58 | ACCENT_ENABLE_ACRYLICBLURBEHIND,
59 | ACCENT_ENABLE_HOSTBACKDROP,
60 | ACCENT_INVALID_STATE
61 | } ACCENT_STATE;
62 |
63 | typedef enum _ACCENT_FLAG
64 | {
65 | ACCENT_NONE,
66 | ACCENT_WINDOWS11_LUMINOSITY = 0x2,
67 | ACCENT_BORDER_LEFT = 0x20,
68 | ACCENT_BORDER_TOP = 0x40,
69 | ACCENT_BORDER_RIGHT = 0x80,
70 | ACCENT_BORDER_BOTTOM = 0x100,
71 | ACCENT_BORDER_ALL = (ACCENT_BORDER_LEFT | ACCENT_BORDER_TOP | ACCENT_BORDER_RIGHT | ACCENT_BORDER_BOTTOM)
72 | } ACCENT_FLAG;
73 |
74 | typedef struct _ACCENT_POLICY
75 | {
76 | ACCENT_STATE AccentState;
77 | DWORD AccentFlags;
78 | DWORD dwGradientColor;
79 | DWORD dwAnimationId;
80 | } ACCENT_POLICY;
81 |
82 | typedef BOOL(WINAPI* pfnSetWindowCompositionAttribute)(HWND, WINDOWCOMPOSITIONATTRIBUTEDATA*);
83 | static pfnSetWindowCompositionAttribute SetWindowCompositionAttribute
84 | = (pfnSetWindowCompositionAttribute)GetProcAddress(GetModuleHandle(L"User32"), "SetWindowCompositionAttribute");
85 |
86 | static BOOL SetAcrylicEffect(HWND hWnd, DWORD dwTintColor)
87 | {
88 | ACCENT_POLICY policy = {
89 | ACCENT_ENABLE_ACRYLICBLURBEHIND,
90 | ACCENT_WINDOWS11_LUMINOSITY | ACCENT_BORDER_ALL,
91 | dwTintColor,
92 | 0
93 | };
94 | WINDOWCOMPOSITIONATTRIBUTEDATA data = {
95 | WCA_ACCENT_POLICY,
96 | &policy,
97 | sizeof(ACCENT_POLICY)
98 | };
99 |
100 | return SetWindowCompositionAttribute(hWnd, &data);
101 | }
102 |
103 | static BOOL SetAcrylicEffect(HWND hWnd, DWORD dwTintColor, DWORD dwOpacity)
104 | {
105 | return SetAcrylicEffect(hWnd, (dwOpacity << 24) | (dwTintColor & 0xFFFFFF));
106 | }
107 | }
108 | }
--------------------------------------------------------------------------------
/AcrylicMenus/AcrylicMenus.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 15.0
23 | {97391729-9A04-40B0-9C0F-98FA395127AB}
24 | Win32Proj
25 | AcrylicMenus
26 | 10.0.19041.0
27 | AcrylicMenus
28 |
29 |
30 |
31 | DynamicLibrary
32 | true
33 | v142
34 | Unicode
35 |
36 |
37 | DynamicLibrary
38 | false
39 | v142
40 | true
41 | Unicode
42 |
43 |
44 | DynamicLibrary
45 | true
46 | v142
47 | Unicode
48 |
49 |
50 | DynamicLibrary
51 | false
52 | v142
53 | true
54 | Unicode
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | true
76 |
77 |
78 | true
79 |
80 |
81 | false
82 |
83 |
84 | false
85 |
86 |
87 |
88 | Use
89 | Level3
90 | Disabled
91 | true
92 | WIN32;_DEBUG;TRANSLUCENTFLYOUTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
93 | true
94 | pch.h
95 |
96 |
97 | Windows
98 | true
99 | false
100 |
101 |
102 |
103 |
104 | Use
105 | Level3
106 | Disabled
107 | true
108 | _DEBUG;TRANSLUCENTFLYOUTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
109 | true
110 | pch.h
111 |
112 |
113 | Windows
114 | true
115 | false
116 |
117 |
118 |
119 |
120 | Use
121 | Level3
122 | Full
123 | true
124 | true
125 | true
126 | WIN32;NDEBUG;TRANSLUCENTFLYOUTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
127 | true
128 | pch.h
129 |
130 |
131 | Windows
132 | true
133 | true
134 | true
135 | false
136 |
137 |
138 |
139 |
140 | Use
141 | Level3
142 | Full
143 | true
144 | true
145 | true
146 | NDEBUG;TRANSLUCENTFLYOUTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
147 | true
148 | pch.h
149 |
150 |
151 | Windows
152 | true
153 | true
154 | true
155 | false
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 | Create
181 | Create
182 | Create
183 | Create
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
199 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/AcrylicMenus/AcrylicMenus.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files
6 |
7 |
8 | Source Files
9 |
10 |
11 | Source Files
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Header Files
21 |
22 |
23 | Source Files
24 |
25 |
26 | Header Files
27 |
28 |
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 | Header Files
50 |
51 |
52 | Header Files
53 |
54 |
55 | Header Files
56 |
57 |
58 | Header Files
59 |
60 |
61 | Header Files
62 |
63 |
64 |
65 |
66 | {779589bf-9e2e-464c-b010-d9c8bf432dc8}
67 |
68 |
69 | {854ea3d3-0d7c-4109-9553-b4e42a4f90cd}
70 |
71 |
72 | {e15d5319-595d-4357-9f95-dcd8480962db}
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Resource Files
81 |
82 |
83 |
--------------------------------------------------------------------------------
/AcrylicMenus/AppearanceConfiguration.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define MENU_DATA_FORCE_BK_REDRAW 0xFEEE
4 | #define MENU_REDRAW_BORDER TRUE
5 |
6 | // ACRYLIC
7 |
8 | #define ACRYLIC_OPACITY_LIGHT 200
9 | #define ACRYLIC_OPACITY_DARK 190
10 |
11 | #define ACRYLIC_TINT_AUTO TRUE
12 |
13 | #define ACRYLIC_TINT_LIGHT 0xEEEEEE
14 | #define ACRYLIC_TINT_DARK 0x2B2B2B
15 |
16 | // POPUP_HOVER
17 |
18 | #define POPUP_HOVER_OPACITY_LIGHT 17
19 | #define POPUP_HOVER_OPACITY_DARK 65
20 |
21 | #define POPUP_HOVER_COLOR_LIGHT RGB(0, 0, 0)
22 | #define POPUP_HOVER_COLOR_DARK RGB(128, 128, 128)
23 |
24 | #define POPUP_HOVER_COLOR_OPAQUE_LIGHT RGB(POPUP_HOVER_OPACITY_LIGHT, POPUP_HOVER_OPACITY_LIGHT, POPUP_HOVER_OPACITY_LIGHT)
25 | #define POPUP_HOVER_COLOR_OPAQUE_DARK RGB(POPUP_HOVER_OPACITY_DARK, POPUP_HOVER_OPACITY_DARK, POPUP_HOVER_OPACITY_DARK)
26 |
27 | // POPUP_SEPARATOR
28 |
29 | #define POPUP_SEPARATOR_COLOR_LIGHT RGB(38, 38, 38)
30 | #define POPUP_SEPARATOR_COLOR_DARK RGB(217, 217, 217)
31 |
32 | #define POPUP_SEPARATOR_OPACITY_LIGHT 48
33 | #define POPUP_SEPARATOR_OPACITY_DARK 48
34 |
35 | ///////////////////////////////////////////////////////
36 |
37 | #define WIN11_SET_SMALL_CORNERS FALSE
38 | #define WIN11_SET_POPUP_BORDERS FALSE
39 |
40 | #define WIN11_POPUP_BORDER_LIGHT RGB(217, 217, 217)
41 | #define WIN11_POPUP_BORDER_DARK RGB(48, 48, 48)
42 |
43 | #define WIN11_OUTLINE_LIGHT RGB(0, 0, 0)
44 | #define WIN11_OUTLINE_DARK RGB(255, 255, 255)
45 |
46 | #define WIN11_LUMINOSITY_TINT_LIGHT 0x9EF9F9F9
47 | #define WIN11_LUMINOSITY_TINT_DARK 0x412B2B2B
48 |
49 | #define WIN11_LUMINOSITY_TINT_OPACITY_LIGHT 158
50 | #define WIN11_LUMINOSITY_TINT_OPACITY_DARK 65
51 |
52 | ///////////////////////////////////////////////////////
--------------------------------------------------------------------------------
/AcrylicMenus/DetoursHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 | #include "detours.h"
4 |
5 | namespace AcrylicMenus
6 | {
7 | static bool bBatchState = false;
8 | class Detours
9 | {
10 | public:
11 | template
12 | auto OldFunction(Args&&... args)
13 | {
14 | return reinterpret_cast(GetOldFunction())(args...);
15 | }
16 |
17 | static void Begin()
18 | {
19 | DetourSetIgnoreTooSmall(TRUE);
20 | DetourTransactionBegin();
21 | DetourUpdateThread(GetCurrentThread());
22 | }
23 | static void Commit()
24 | {
25 | DetourTransactionCommit();
26 | }
27 | void Initialize(PVOID OldAddr, PVOID NewAddr)
28 | {
29 | pvOldAddr = OldAddr;
30 | pvNewAddr = NewAddr;
31 | }
32 |
33 | template
34 | static void Batch(BOOL bBatchState, Args&&... args)
35 | {
36 | ::bBatchState = bBatchState;
37 | Batch(std::forward(args)...);
38 | }
39 | template
40 | static void Batch(T& t, Args&&... args)
41 | {
42 | t.SetHookState(bBatchState);
43 | Batch(args...);
44 | }
45 | static void Batch() {}
46 |
47 | Detours()
48 | {
49 |
50 | }
51 | Detours(LPCSTR pszModule, LPCSTR pszFunction, PVOID NewAddr = nullptr)
52 | {
53 | PVOID OldAddr = DetourFindFunction(pszModule, pszFunction);
54 | pvOldAddr = OldAddr;
55 | pvNewAddr = NewAddr;
56 | }
57 | Detours(PVOID OldAddr, PVOID NewAddr = nullptr)
58 | {
59 | pvOldAddr = OldAddr;
60 | pvNewAddr = NewAddr;
61 | }
62 |
63 | PVOID GetOldFunction() const
64 | {
65 | return pvOldAddr;
66 | }
67 | void SetHookState(BOOL bHookState = -1)
68 | {
69 | if (bHookState == -1)
70 | {
71 | bHookState = !bHookInstalled;
72 | }
73 | if (bHookState == TRUE and !bHookInstalled)
74 | {
75 | DetourAttach(&(PVOID &)pvOldAddr, pvNewAddr);
76 | bHookInstalled = true;
77 | }
78 | else if (bHookState == FALSE and bHookInstalled)
79 | {
80 | DetourDetach(&(PVOID&)pvOldAddr, pvNewAddr);
81 | bHookInstalled = false;
82 | }
83 | }
84 | bool IsHookInstalled()
85 | {
86 | return bHookInstalled;
87 | }
88 | private:
89 | PVOID pvNewAddr = nullptr;
90 | PVOID pvOldAddr = nullptr;
91 | bool bHookInstalled = false;
92 | };
93 |
94 | using DetoursHook = Detours;
95 |
96 | static inline bool VerifyCaller(LPCTSTR pszCallerModuleName, PVOID pvCaller = _ReturnAddress())
97 | {
98 | HMODULE hModule = DetourGetContainingModule(pvCaller);
99 | return hModule == GetModuleHandle(pszCallerModuleName);
100 | }
101 |
102 | static inline bool VerifyCaller(PVOID pvModule, PVOID pvCaller = _ReturnAddress())
103 | {
104 | HMODULE hModule = DetourGetContainingModule(pvCaller);
105 | return hModule == pvModule;
106 | }
107 |
108 | static inline bool VerifyProcessModule(LPCTSTR pszTargetModuleName)
109 | {
110 | HMODULE hModule = GetModuleHandle(nullptr);
111 | TCHAR pszModuleName[MAX_PATH + 1] = {};
112 | GetModuleFileName(hModule, pszModuleName, MAX_PATH);
113 | return _tcsicmp(pszModuleName, pszTargetModuleName);
114 | }
115 | }
--------------------------------------------------------------------------------
/AcrylicMenus/MenuHandler.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "MenuHandler.h"
3 | #include "MenuManager.h"
4 | #include "ThemeHelper.h"
5 | #include "AcrylicHelper.h"
6 | #include "WindowHelper.h"
7 | #include "SystemHelper.h"
8 | #include "SettingsHelper.h"
9 | #include "AppearanceConfiguration.h"
10 |
11 | #define MN_BUTTONDOWN 0x1ED
12 | #define MN_BUTTONUP 0x1EF
13 | #define WM_REDRAWBORDER WM_APP + 13
14 |
15 | #define DWMWA_WINDOW_CORNER_PREFERENCE 33
16 | #define DWMWA_BORDER_COLOR 34
17 |
18 | #define DWMWCP_ROUNDSMALL 3
19 |
20 | using namespace AcrylicMenus;
21 |
22 | thread_local HWND g_hWndPrimary = NULL;
23 |
24 | void CALLBACK MenuHandler::WinEventProc(
25 | HWINEVENTHOOK hWinEventHook,
26 | DWORD dwEvent,
27 | HWND hWnd,
28 | LONG idObject,
29 | LONG idChild,
30 | DWORD dwEventThread,
31 | DWORD dwmsEventTime
32 | )
33 | {
34 | if (!hWnd || !IsWindow(hWnd))
35 | {
36 | return;
37 | }
38 |
39 | switch (dwEvent)
40 | {
41 | case EVENT_OBJECT_CREATE:
42 | {
43 | if (SystemHelper::IsTransparencyEnabled() && ThemeHelper::IsPopupMenu(hWnd))
44 | {
45 | if (!g_hWndPrimary)
46 | {
47 | g_hWndPrimary = hWnd;
48 | }
49 |
50 | SetWindowSubclass(hWnd, SubclassProc, 0, 0);
51 | MenuManager::SetCurrentMenu(hWnd);
52 | }
53 | break;
54 | }
55 | case EVENT_OBJECT_SHOW:
56 | {
57 | if (g_hWndPrimary && SystemHelper::IsTransparencyEnabled() && ThemeHelper::IsPopupMenu(hWnd))
58 | {
59 | if (SystemHelper::g_bIsWindows11)
60 | {
61 | if (WIN11_SET_SMALL_CORNERS)
62 | {
63 | DWORD dwCornerPreference = DWMWCP_ROUNDSMALL;
64 | DwmSetWindowAttribute(hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &dwCornerPreference, sizeof(DWORD));
65 | }
66 | if (WIN11_SET_POPUP_BORDERS)
67 | {
68 | COLORREF dwColorBorder = MenuManager::g_bIsDarkMode ? WIN11_POPUP_BORDER_DARK : WIN11_POPUP_BORDER_LIGHT;
69 | DwmSetWindowAttribute(hWnd, DWMWA_BORDER_COLOR, &dwColorBorder, sizeof(COLORREF));
70 | }
71 | }
72 | }
73 | break;
74 | }
75 | case EVENT_OBJECT_DESTROY:
76 | {
77 | if (hWnd == g_hWndPrimary)
78 | {
79 | MenuManager::SetCurrentMenu(NULL);
80 | g_hWndPrimary = NULL;
81 | }
82 | break;
83 | }
84 | default:
85 | {
86 | break;
87 | }
88 | }
89 | }
90 |
91 | static constexpr int nonClientMarginSize{ 3 };
92 | static constexpr int systemOutlineSize{ 1 };
93 | LRESULT CALLBACK MenuHandler::SubclassProc(
94 | HWND hWnd,
95 | UINT uMsg,
96 | WPARAM wParam,
97 | LPARAM lParam,
98 | UINT_PTR uIdSubclass,
99 | DWORD_PTR dwRefData
100 | )
101 | {
102 | bool handled = false;
103 | LRESULT result{ 0 };
104 |
105 | switch (uMsg)
106 | {
107 | #if (MENU_REDRAW_BORDER == TRUE)
108 | ///
109 | /// Windows 10 has ugly white context menu borders
110 | /// As the borders are in the non-client area,
111 | /// we can't hook the painting event and need
112 | /// to redraw them manually
113 | ///
114 | /// This is enabled only for light mode menus,
115 | /// because it is noticeable, due to low contrast
116 | /// between menu background color and original white border,
117 | /// but this is very noticeable in dark mode
118 | ///
119 | /// On Windows 11, we change borders color
120 | /// natively using DwmSetWindowAttribute API
121 | ///
122 | case WM_PRINT:
123 | {
124 | handled = true;
125 |
126 | POINT pt;
127 |
128 | HDC wndDC = (HDC)wParam;
129 | SaveDC(wndDC);
130 |
131 | RECT rcPaint;
132 | GetClipBox(wndDC, &rcPaint);
133 | FillRect(wndDC, &rcPaint, GetStockBrush(BLACK_BRUSH));
134 |
135 | SetViewportOrgEx(wndDC, nonClientMarginSize, nonClientMarginSize, &pt);
136 | result = DefSubclassProc(hWnd, WM_PRINTCLIENT, wParam, lParam);
137 |
138 | SetViewportOrgEx(wndDC, pt.x, pt.y, nullptr);
139 |
140 | RestoreDC(wndDC, -1);
141 | }
142 | break;
143 | case WM_NCPAINT:
144 | {
145 | handled = true;
146 |
147 | HDC wndDC = GetWindowDC(hWnd);
148 |
149 | if (wParam != NULLREGION && wParam != ERROR)
150 | {
151 | SelectClipRgn(wndDC, reinterpret_cast(wParam));
152 | }
153 |
154 | RECT rcPaint;
155 | GetClipBox(wndDC, &rcPaint);
156 | FillRect(wndDC, &rcPaint, GetStockBrush(BLACK_BRUSH));
157 |
158 | ReleaseDC(hWnd, wndDC);
159 | }
160 | break;
161 | #endif
162 | case MN_BUTTONUP:
163 | {
164 | // We need to prevent the system default menu fade out animation
165 | // and begin a re-implemented one
166 | //
167 | // Windows does not show animation if the selection was done
168 | // with keyboard (i.e. Enter)
169 |
170 | int pvParam;
171 | SystemParametersInfoW(SPI_GETSELECTIONFADE, 0, &pvParam, 0);
172 | if (!pvParam)
173 | {
174 | // Fade out animation is disabled system-wide
175 | break;
176 | }
177 |
178 | HMENU hMenu = (HMENU)SendMessage(hWnd, MN_GETHMENU, 0, 0);
179 | int iPosition = (int)wParam;
180 |
181 | MENUITEMINFO mii;
182 | ZeroMemory(&mii, sizeof(MENUITEMINFO));
183 | mii.cbSize = sizeof(MENUITEMINFO);
184 | mii.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_FTYPE;
185 |
186 | GetMenuItemInfo(hMenu, iPosition, TRUE, &mii);
187 |
188 | // Animation will be shown if a menu item is selected
189 | //
190 | // We will ignore cases where user clicked on non-clickable item, i.e.:
191 | // a) separator
192 | // b) disabled item
193 | // c) item that has submenu
194 |
195 | if (!(mii.fType & MFT_SEPARATOR) && !(mii.fState & MFS_DISABLED) && !mii.hSubMenu)
196 | {
197 | MENUBARINFO pmbi;
198 | ZeroMemory(&pmbi, sizeof(MENUBARINFO)); // memset(&info, 0, sizeof(MENUBARINFO));
199 | pmbi.cbSize = sizeof(MENUBARINFO);
200 | ZeroMemory(&pmbi.rcBar, 0, sizeof(RECT));
201 |
202 | GetMenuBarInfo(hWnd, OBJID_CLIENT, wParam + 1, &pmbi);
203 |
204 | WindowHelper::BeginMenuFadeOutAnimation(pmbi);
205 |
206 | SystemParametersInfoW(SPI_SETSELECTIONFADE, 0, FALSE, 0);
207 | LRESULT lResult = DefSubclassProc(hWnd, uMsg, wParam, lParam);
208 | SystemParametersInfoW(SPI_SETSELECTIONFADE, 0, (PVOID)TRUE, 0);
209 |
210 | return lResult;
211 | }
212 | }
213 | break;
214 | }
215 |
216 | if (!handled)
217 | {
218 | result = DefSubclassProc(hWnd, uMsg, wParam, lParam);
219 | }
220 |
221 | return result;
222 | }
--------------------------------------------------------------------------------
/AcrylicMenus/MenuHandler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 | #include "MenuHooks.h"
4 |
5 | namespace AcrylicMenus
6 | {
7 | namespace MenuHandler
8 | {
9 | extern void CALLBACK WinEventProc(
10 | HWINEVENTHOOK hWinEventHook,
11 | DWORD dwEvent,
12 | HWND hWnd,
13 | LONG idObject,
14 | LONG idChild,
15 | DWORD dwEventThread,
16 | DWORD dwmsEventTime
17 | );
18 | LRESULT CALLBACK SubclassProc(
19 | HWND hWnd,
20 | UINT uMsg,
21 | WPARAM wParam,
22 | LPARAM lParam,
23 | UINT_PTR uIdSubclass,
24 | DWORD_PTR dwRefData
25 | );
26 | }
27 | };
--------------------------------------------------------------------------------
/AcrylicMenus/MenuHooks.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ThemeHelper.h"
3 | #include "MenuHooks.h"
4 | #include "MenuManager.h"
5 | #include "SystemHelper.h"
6 |
7 | using namespace AcrylicMenus;
8 | using namespace AcrylicMenus::MenuHooks;
9 | using namespace AcrylicMenus::MenuManager;
10 | using namespace AcrylicMenus::ThemeHelper;
11 |
12 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
13 |
14 | DetoursHook MenuHooks::DrawThemeBackgroundHook("Uxtheme", "DrawThemeBackground", MyDrawThemeBackground);
15 |
16 | DetoursHook MenuHooks::DrawThemeTextExHook("Uxtheme", "DrawThemeTextEx", MyDrawThemeTextEx);
17 | DetoursHook MenuHooks::DrawThemeTextHook("Uxtheme", "DrawThemeText", MyDrawThemeText);
18 | DetoursHook MenuHooks::DrawTextWHook("User32", "DrawTextW", MyDrawTextW);
19 | DetoursHook MenuHooks::DrawTextExWHook("User32", "DrawTextExW", MyDrawTextExW);
20 |
21 | DetoursHook MenuHooks::SetMenuInfoHook("User32", "SetMenuInfo", MySetMenuInfo);
22 | DetoursHook MenuHooks::SetMenuItemBitmapsHook("User32", "SetMenuItemBitmaps", MySetMenuItemBitmaps);
23 | DetoursHook MenuHooks::InsertMenuItemWHook("User32", "InsertMenuItemW", MyInsertMenuItemW);
24 | DetoursHook MenuHooks::SetMenuItemInfoWHook("User32", "SetMenuItemInfoW", MySetMenuItemInfoW);
25 |
26 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
27 |
28 | void Win32HookBatch(BOOL bBatchState)
29 | {
30 | Detours::Batch(
31 | bBatchState,
32 | DrawThemeBackgroundHook,
33 | DrawThemeTextExHook,
34 | DrawThemeTextHook,
35 | DrawTextWHook,
36 | DrawTextExWHook,
37 | SetMenuInfoHook,
38 | SetMenuItemBitmapsHook,
39 | InsertMenuItemWHook,
40 | SetMenuItemInfoWHook
41 | );
42 | }
43 | void MenuHooks::Win32HookStartup()
44 | {
45 | Win32HookBatch(TRUE);
46 | }
47 |
48 | void MenuHooks::Win32HookShutdown()
49 | {
50 | Win32HookBatch(FALSE);
51 | }
52 |
53 | bool VerifyThemeBackgroundTransparency(HDC hdc, HTHEME hTheme, int iPartId, int iStateId)
54 | {
55 | RECT rc = { 0, 0, 1, 1 };
56 | bool bResult = false;
57 | auto f = [&](HDC hMemDC, HPAINTBUFFER hPaintBuffer)
58 | {
59 | HRESULT hr = DrawThemeBackgroundHook.OldFunction(
60 | hTheme,
61 | hMemDC,
62 | iPartId,
63 | iStateId,
64 | &rc,
65 | nullptr
66 | );
67 |
68 | if (SUCCEEDED(hr))
69 | {
70 | auto verify = [&](int y, int x, RGBQUAD* pRGBAInfo)
71 | {
72 | if (pRGBAInfo->rgbReserved != 0xFF)
73 | {
74 | bResult = true;
75 | return false;
76 | }
77 | return true;
78 | };
79 |
80 | BufferedPaintWalkBits(hPaintBuffer, verify);
81 | }
82 | };
83 |
84 | MARGINS mr = {};
85 | if (SUCCEEDED(GetThemeMargins(hTheme, hdc, iPartId, iStateId, TMT_SIZINGMARGINS, nullptr, &mr)))
86 | {
87 | rc.right = max(mr.cxLeftWidth + mr.cxRightWidth, 1);
88 | rc.bottom = max(mr.cyTopHeight + mr.cyBottomHeight, 1);
89 | }
90 | DoBufferedPaint(hdc, &rc, f, 0xFF, BPPF_ERASE | BPPF_NOCLIP, FALSE, FALSE);
91 |
92 | return bResult;
93 | };
94 |
95 | inline bool VerifyMenuTheme(HTHEME hTheme)
96 | {
97 | return VerifyThemeData(hTheme, L"Menu");
98 | }
99 |
100 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101 |
102 | HRESULT WINAPI MenuHooks::MyDrawThemeBackground(
103 | HTHEME hTheme,
104 | HDC hdc,
105 | int iPartId,
106 | int iStateId,
107 | LPCRECT pRect,
108 | LPCRECT pClipRect
109 | )
110 | {
111 | HRESULT hr = S_OK;
112 |
113 | if (g_hWnd && VerifyMenuTheme(hTheme))
114 | {
115 | RECT rc = *pRect;
116 | if (pClipRect)
117 | {
118 | IntersectRect(&rc, pRect, pClipRect);
119 | }
120 |
121 | if (
122 | iPartId == MENU_POPUPBACKGROUND ||
123 | (iPartId == MENU_POPUPITEM || iPartId == MENU_POPUPITEM_FOCUSABLE) ||
124 | iPartId == MENU_POPUPGUTTER ||
125 | iPartId == MENU_POPUPBORDERS
126 | )
127 | {
128 | if (
129 | iPartId == MENU_POPUPBACKGROUND ||
130 | (iPartId == MENU_POPUPITEM || iPartId == MENU_POPUPITEM_FOCUSABLE) ||
131 | (
132 | !IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId) ||
133 | !VerifyThemeBackgroundTransparency(hdc, hTheme, iPartId, iStateId)
134 | )
135 | )
136 | {
137 | auto f = [&](HDC hMemDC, HPAINTBUFFER hPaintBuffer)
138 | {
139 | Clear(hdc, &rc);
140 |
141 | HBRUSH hBrush = CreateSolidBrush(g_bIsDarkMode ? POPUP_HOVER_COLOR_DARK : POPUP_HOVER_COLOR_LIGHT);
142 | FillRect(hMemDC, &rc, hBrush);
143 | DeleteObject(hBrush);
144 |
145 | //GdiFlush();
146 | BufferedPaintSetAlpha(hPaintBuffer, &rc, 0xFF);
147 | };
148 |
149 | BYTE bOpacity = ((iPartId == MENU_POPUPITEM || iPartId == MENU_POPUPITEM_FOCUSABLE) && iStateId == MPI_HOT) ?
150 | (g_bIsDarkMode ? POPUP_HOVER_OPACITY_DARK : POPUP_HOVER_OPACITY_LIGHT) :
151 | 0;
152 |
153 | if (DoBufferedPaint(hdc, &rc, f, bOpacity, BPPF_ERASE | (iPartId == MENU_POPUPBORDERS ? BPPF_NONCLIENT : 0UL)))
154 | {
155 | return hr;
156 | }
157 | }
158 | else
159 | {
160 | if (iStateId != MPI_NORMAL)
161 | {
162 | MyDrawThemeBackground(
163 | hTheme,
164 | hdc,
165 | iPartId,
166 | MPI_NORMAL,
167 | pRect,
168 | pClipRect
169 | );
170 | }
171 | else
172 | {
173 | MyDrawThemeBackground(
174 | hTheme,
175 | hdc,
176 | iPartId,
177 | 0,
178 | pRect,
179 | pClipRect
180 | );
181 | }
182 | }
183 | }
184 | else if (iPartId == MENU_POPUPITEMKBFOCUS)
185 | {
186 | HBRUSH hBrush = (HBRUSH) GetStockObject(g_bIsDarkMode ? WHITE_BRUSH : BLACK_BRUSH);
187 |
188 | bool bSuccess = true;
189 | RECT rcLine;
190 |
191 | auto f = [&](HDC hMemDC, HPAINTBUFFER hPaintBuffer)
192 | {
193 | FillRect(hMemDC, &rcLine, hBrush);
194 | BufferedPaintSetAlpha(hPaintBuffer, &rcLine, 0xFF);
195 | };
196 |
197 | Clear(hdc, &rc);
198 |
199 | // Top line
200 | rcLine = { rc.left, rc.top, rc.right, rc.top + 1 };
201 | bSuccess = bSuccess && DoBufferedPaint(hdc, &rcLine, f, 255, BPPF_ERASE);
202 |
203 | // Bottom line
204 | rcLine = { rc.left, rc.bottom - 1, rc.right, rc.bottom };
205 | bSuccess = bSuccess && DoBufferedPaint(hdc, &rcLine, f, 255, BPPF_ERASE);
206 |
207 | // Left line
208 | rcLine = { rc.left, rc.top, rc.left + 1, rc.bottom };
209 | bSuccess = bSuccess && DoBufferedPaint(hdc, &rcLine, f, 255, BPPF_ERASE);
210 |
211 | // Right line
212 | rcLine = { rc.right - 1, rc.top, rc.right, rc.bottom };
213 | bSuccess = bSuccess && DoBufferedPaint(hdc, &rcLine, f, 255, BPPF_ERASE);
214 |
215 | if (bSuccess)
216 | {
217 | return hr;
218 | }
219 | }
220 | else if (iPartId == MENU_POPUPSEPARATOR)
221 | {
222 | RECT rcSep = { rc.left, rc.top + 2, rc.right, rc.top + 3 };
223 |
224 | auto f = [&](HDC hMemDC, HPAINTBUFFER hPaintBuffer)
225 | {
226 | Clear(hdc, &rc);
227 |
228 | HBRUSH hBrush = CreateSolidBrush(g_bIsDarkMode ? POPUP_SEPARATOR_COLOR_DARK : POPUP_SEPARATOR_COLOR_LIGHT);
229 | FillRect(hMemDC, &rcSep, hBrush);
230 | DeleteObject(hBrush);
231 |
232 | //GdiFlush();
233 | BufferedPaintSetAlpha(hPaintBuffer, &rcSep, 0xFF);
234 | };
235 | if (DoBufferedPaint(hdc, &rcSep, f, g_bIsDarkMode ? POPUP_SEPARATOR_OPACITY_DARK : POPUP_SEPARATOR_OPACITY_LIGHT, BPPF_ERASE))
236 | {
237 | return hr;
238 | }
239 | }
240 | }
241 |
242 | hr = DrawThemeBackgroundHook.OldFunction(
243 | hTheme,
244 | hdc,
245 | iPartId,
246 | iStateId,
247 | pRect,
248 | pClipRect
249 | );
250 |
251 | return hr;
252 | }
253 |
254 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
255 |
256 | HRESULT WINAPI MenuHooks::MyDrawThemeTextEx(
257 | HTHEME hTheme,
258 | HDC hdc,
259 | int iPartId,
260 | int iStateId,
261 | LPCTSTR pszText,
262 | int cchText,
263 | DWORD dwTextFlags,
264 | LPRECT pRect,
265 | const DTTOPTS* pOptions
266 | )
267 | {
268 | HRESULT hr = S_OK;
269 |
270 | if (
271 | g_hWnd &&
272 | !(dwTextFlags & DT_CALCRECT) &&
273 | pOptions &&
274 | (!(pOptions->dwFlags & DTT_CALCRECT) || !(pOptions->dwFlags & DTT_COMPOSITED)) &&
275 | VerifyMenuTheme(hTheme)
276 | )
277 | {
278 | if (!g_bBkColorRefresh)
279 | {
280 | DWORD dwColor;
281 | GetThemeColor(hTheme, MENU_POPUPITEM, MPI_NORMAL, TMT_TEXTCOLOR, &dwColor);
282 | RefreshCurrentMenuBackground(GetRValue(dwColor) > 128, NULL);
283 | g_bBkColorRefresh = true;
284 | }
285 |
286 | DTTOPTS Options = *pOptions;
287 | Options.dwFlags |= DTT_COMPOSITED;
288 |
289 | auto f = [&](HDC hMemDC, HPAINTBUFFER hPaintBuffer)
290 | {
291 | g_alphaFixedState = true;
292 |
293 | hr = DrawThemeTextExHook.OldFunction(
294 | hTheme,
295 | hMemDC,
296 | iPartId,
297 | iStateId,
298 | pszText,
299 | cchText,
300 | dwTextFlags,
301 | pRect,
302 | &Options
303 | );
304 |
305 | //GdiFlush();
306 | g_alphaFixedState = false;
307 | };
308 |
309 | if (DoBufferedPaint(hdc, pRect, f))
310 | {
311 | return hr;
312 | }
313 | }
314 |
315 | g_alphaFixedState = true;
316 |
317 | hr = DrawThemeTextExHook.OldFunction(
318 | hTheme,
319 | hdc,
320 | iPartId,
321 | iStateId,
322 | pszText,
323 | cchText,
324 | dwTextFlags,
325 | pRect,
326 | pOptions
327 | );
328 |
329 | g_alphaFixedState = false;
330 | return hr;
331 | }
332 |
333 | HRESULT WINAPI MenuHooks::MyDrawThemeText(
334 | HTHEME hTheme,
335 | HDC hdc,
336 | int iPartId,
337 | int iStateId,
338 | LPCTSTR pszText,
339 | int cchText,
340 | DWORD dwTextFlags,
341 | DWORD dwTextFlags2,
342 | LPCRECT pRect
343 | )
344 | {
345 | if (g_hWnd && pRect && VerifyMenuTheme(hTheme)) {
346 | DTTOPTS dttOpts = { sizeof(DTTOPTS) };
347 | RECT rc = *pRect;
348 | return DrawThemeTextEx(
349 | hTheme,
350 | hdc,
351 | iPartId,
352 | iStateId,
353 | pszText,
354 | cchText,
355 | dwTextFlags,
356 | &rc,
357 | &dttOpts
358 | );
359 | }
360 |
361 | return DrawThemeTextHook.OldFunction(
362 | hTheme,
363 | hdc,
364 | iPartId,
365 | iStateId,
366 | pszText,
367 | cchText,
368 | dwTextFlags,
369 | dwTextFlags2,
370 | pRect
371 | );
372 | }
373 |
374 | int WINAPI MenuHooks::MyDrawTextW(
375 | HDC hdc,
376 | LPCTSTR lpchText,
377 | int cchText,
378 | LPRECT lprc,
379 | UINT format
380 | )
381 | {
382 | if (g_hWnd && !g_alphaFixedState && !(format & DT_CALCRECT) && GetBkMode(hdc) == TRANSPARENT)
383 | {
384 | DTTOPTS dttOpts = { sizeof(DTTOPTS) };
385 | dttOpts.dwFlags = DTT_TEXTCOLOR;
386 | dttOpts.crText = GetTextColor(hdc);
387 |
388 | HTHEME hTheme = OpenThemeData(NULL, L"Menu");
389 | if (hTheme)
390 | {
391 | DrawThemeTextEx(hTheme, hdc, 0, 0, lpchText, cchText, format, lprc, &dttOpts);
392 | CloseThemeData(hTheme);
393 | }
394 |
395 | return 0;
396 | }
397 | return DrawTextWHook.OldFunction(
398 | hdc,
399 | lpchText,
400 | cchText,
401 | lprc,
402 | format
403 | );
404 | }
405 |
406 | int WINAPI MenuHooks::MyDrawTextExW(
407 | HDC hdc,
408 | LPWSTR lpchText,
409 | int cchText,
410 | LPRECT lprc,
411 | UINT format,
412 | LPDRAWTEXTPARAMS lpdtp
413 | )
414 | {
415 | int nResult;
416 |
417 | if (g_hWnd && !g_alphaFixedState && !lpdtp && !(format & DT_CALCRECT) && GetBkMode(hdc) == TRANSPARENT)
418 | {
419 | DTTOPTS Options = { sizeof(DTTOPTS) };
420 | Options.dwFlags = DTT_TEXTCOLOR;
421 | Options.crText = GetTextColor(hdc);
422 |
423 | HTHEME hTheme = OpenThemeData(NULL, L"Menu");
424 | if (hTheme)
425 | {
426 | DrawThemeTextEx(hTheme, hdc, 0, 0, lpchText, cchText, format, lprc, &Options);
427 | CloseThemeData(hTheme);
428 | }
429 |
430 | return 0;
431 | }
432 |
433 | return nResult = DrawTextExWHook.OldFunction(
434 | hdc,
435 | lpchText,
436 | cchText,
437 | lprc,
438 | format,
439 | lpdtp
440 | );
441 | }
442 |
443 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
444 |
445 | BOOL WINAPI MenuHooks::MySetMenuInfo(
446 | HMENU hMenu,
447 | LPCMENUINFO lpMenuInfo
448 | )
449 | {
450 | // Makes Immersive Menu top and bottom frame transparent
451 |
452 | g_menuOwnerDrawn = true;
453 | if (SystemHelper::IsTransparencyEnabled())
454 | {
455 | if ((lpMenuInfo->fMask & MIM_BACKGROUND) && lpMenuInfo->hbrBack)
456 | {
457 | COLORREF dwColor = GetBrushColor(lpMenuInfo->hbrBack);
458 | RefreshCurrentMenuBackground(GetRValue(dwColor) < 128, dwColor);
459 |
460 | PBYTE pvBits = nullptr;
461 | MENUINFO MenuInfo = *lpMenuInfo;
462 | HBITMAP hBitmap = CreateDIB(nullptr, 1, 1, (PVOID*)&pvBits);
463 |
464 | if (hBitmap && pvBits)
465 | {
466 | SetPixel(pvBits, 0, 0, 0, 0);
467 |
468 | HBRUSH hBrush = CreatePatternBrush(hBitmap);
469 |
470 | DeleteObject(hBitmap);
471 |
472 | if (hBrush)
473 | {
474 | MenuInfo.hbrBack = hBrush;
475 | DeleteObject(lpMenuInfo->hbrBack);
476 |
477 | // DO NOT delete the new brush
478 |
479 | return SetMenuInfoHook.OldFunction(
480 | hMenu,
481 | &MenuInfo
482 | );
483 | }
484 | }
485 | }
486 | }
487 |
488 | return SetMenuInfoHook.OldFunction(
489 | hMenu,
490 | lpMenuInfo
491 | );
492 | }
493 |
494 | BOOL WINAPI MenuHooks::MySetMenuItemBitmaps(
495 | HMENU hMenu,
496 | UINT uPosition,
497 | UINT uFlags,
498 | HBITMAP hBitmapUnchecked,
499 | HBITMAP hBitmapChecked
500 | )
501 | {
502 | if (SystemHelper::IsTransparencyEnabled())
503 | {
504 | PrepareAlpha(hBitmapUnchecked);
505 | PrepareAlpha(hBitmapChecked);
506 | }
507 |
508 | return SetMenuItemBitmapsHook.OldFunction(
509 | hMenu,
510 | uPosition,
511 | uFlags,
512 | hBitmapUnchecked,
513 | hBitmapChecked
514 | );
515 | }
516 |
517 | BOOL WINAPI MenuHooks::MySetMenuItemInfoW(
518 | HMENU hMenu,
519 | UINT item,
520 | BOOL fByPositon,
521 | LPCMENUITEMINFOW lpmii
522 | )
523 | {
524 | if (lpmii && (lpmii->fMask & MIIM_CHECKMARKS || lpmii->fMask & MIIM_BITMAP) && SystemHelper::IsTransparencyEnabled())
525 | {
526 | PrepareAlpha(lpmii->hbmpItem);
527 | PrepareAlpha(lpmii->hbmpUnchecked);
528 | PrepareAlpha(lpmii->hbmpChecked);
529 | }
530 |
531 | return SetMenuItemInfoWHook.OldFunction(
532 | hMenu,
533 | item,
534 | fByPositon,
535 | lpmii
536 | );
537 | }
538 |
539 | BOOL WINAPI MenuHooks::MyInsertMenuItemW(
540 | HMENU hMenu,
541 | UINT item,
542 | BOOL fByPosition,
543 | LPCMENUITEMINFOW lpmii
544 | )
545 | {
546 | if (lpmii && (lpmii->fMask & MIIM_CHECKMARKS || lpmii->fMask & MIIM_BITMAP) && SystemHelper::IsTransparencyEnabled())
547 | {
548 | PrepareAlpha(lpmii->hbmpItem);
549 | PrepareAlpha(lpmii->hbmpUnchecked);
550 | PrepareAlpha(lpmii->hbmpChecked);
551 | }
552 |
553 | return InsertMenuItemWHook.OldFunction(
554 | hMenu,
555 | item,
556 | fByPosition,
557 | lpmii
558 | );
559 | }
560 |
561 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
--------------------------------------------------------------------------------
/AcrylicMenus/MenuHooks.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 | #include "DetoursHelper.h"
4 | #include "AcrylicHelper.h"
5 |
6 | namespace AcrylicMenus
7 | {
8 | namespace MenuHooks
9 | {
10 | extern HRESULT WINAPI MyDrawThemeBackground(
11 | HTHEME hTheme,
12 | HDC hdc,
13 | int iPartId,
14 | int iStateId,
15 | LPCRECT pRect,
16 | LPCRECT pClipRect
17 | );
18 | extern HRESULT WINAPI MyDrawThemeTextEx(
19 | HTHEME hTheme,
20 | HDC hdc,
21 | int iPartId,
22 | int iStateId,
23 | LPCTSTR pszText,
24 | int cchText,
25 | DWORD dwTextFlags,
26 | LPRECT pRect,
27 | const DTTOPTS* pOptions
28 | );
29 | extern HRESULT WINAPI MyDrawThemeText(
30 | HTHEME hTheme,
31 | HDC hdc,
32 | int iPartId,
33 | int iStateId,
34 | LPCTSTR pszText,
35 | int cchText,
36 | DWORD dwTextFlags,
37 | DWORD dwTextFlags2,
38 | LPCRECT pRect
39 | );
40 | extern int WINAPI MyDrawTextW(
41 | HDC hdc,
42 | LPCTSTR lpchText,
43 | int cchText,
44 | LPRECT lprc,
45 | UINT format
46 | );
47 | extern int WINAPI MyDrawTextExW(
48 | HDC hdc,
49 | LPWSTR lpchText,
50 | int cchText,
51 | LPRECT lprc,
52 | UINT format,
53 | LPDRAWTEXTPARAMS lpdtp
54 | );
55 | extern BOOL WINAPI MySetMenuInfo(
56 | HMENU hMenu,
57 | LPCMENUINFO lpMenuInfo
58 | );
59 | extern BOOL WINAPI MySetMenuItemBitmaps(
60 | HMENU hMenu,
61 | UINT uPosition,
62 | UINT uFlags,
63 | HBITMAP hBitmapUnchecked,
64 | HBITMAP hBitmapChecked
65 | );
66 | extern BOOL WINAPI MyInsertMenuItemW(
67 | HMENU hMenu,
68 | UINT item,
69 | BOOL fByPosition,
70 | LPCMENUITEMINFOW lpmii
71 | );
72 | extern BOOL WINAPI MySetMenuItemInfoW(
73 | HMENU hMenu,
74 | UINT item,
75 | BOOL fByPositon,
76 | LPCMENUITEMINFOW lpmii
77 | );
78 |
79 |
80 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 |
82 | extern DetoursHook DrawThemeBackgroundHook;
83 |
84 | extern DetoursHook DrawThemeTextExHook;
85 | extern DetoursHook DrawThemeTextHook;
86 | extern DetoursHook DrawTextWHook;
87 | extern DetoursHook DrawTextExWHook;
88 |
89 | extern DetoursHook SetMenuInfoHook;
90 | extern DetoursHook SetMenuItemBitmapsHook;
91 | extern DetoursHook SetMenuItemInfoWHook;
92 | extern DetoursHook InsertMenuItemWHook;
93 |
94 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
95 |
96 |
97 | extern void Win32HookStartup();
98 | extern void Win32HookShutdown();
99 | }
100 | };
--------------------------------------------------------------------------------
/AcrylicMenus/MenuManager.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "MenuManager.h"
3 | #include "ThemeHelper.h"
4 | #include "AcrylicHelper.h"
5 | #include "SystemHelper.h"
6 | #include "AppearanceConfiguration.h"
7 |
8 | using namespace AcrylicMenus;
9 | using namespace AcrylicMenus::MenuManager;
10 |
11 | thread_local HWND MenuManager::g_hWnd = NULL;
12 | thread_local bool MenuManager::g_bIsDarkMode = false;
13 | thread_local DWORD MenuManager::g_dwBkColor = NULL;
14 | thread_local bool MenuManager::g_bBkColorRefresh = false;
15 | thread_local bool MenuManager::g_alphaFixedState = false;
16 | thread_local bool MenuManager::g_menuOwnerDrawn = false;
17 |
18 | void ApplyAcrylicEffect();
19 |
20 | void MenuManager::SetCurrentMenu(HWND hWnd)
21 | {
22 | g_alphaFixedState = false;
23 |
24 | if (!hWnd)
25 | {
26 | g_bBkColorRefresh = false;
27 | g_menuOwnerDrawn = false;
28 | }
29 | else if (!g_bBkColorRefresh)
30 | {
31 | bool bIsDark = ThemeHelper::IsMenuUseDarkMode(hWnd);
32 | RefreshCurrentMenuBackground(bIsDark, bIsDark ? ACRYLIC_TINT_DARK : ACRYLIC_TINT_LIGHT);
33 | g_bBkColorRefresh = false;
34 | }
35 |
36 | g_hWnd = hWnd;
37 |
38 | ApplyAcrylicEffect();
39 | }
40 |
41 | void MenuManager::RefreshCurrentMenuBackground(bool bIsDarkMode, DWORD dwBkColor)
42 | {
43 | bool bDarkModeChanged = g_bIsDarkMode != bIsDarkMode;
44 |
45 | if (ACRYLIC_TINT_AUTO)
46 | {
47 | if (dwBkColor)
48 | {
49 | g_dwBkColor = dwBkColor;
50 | g_bBkColorRefresh = true;
51 |
52 | // Request acrylic tint reapplying
53 | bDarkModeChanged = true;
54 | }
55 | else if (bDarkModeChanged)
56 | {
57 | ThemeHelper::GetMenuFillColor(
58 | bIsDarkMode ? L"ImmersiveStartDark::Menu" : L"ImmersiveStart::Menu",
59 | &g_dwBkColor
60 | );
61 | }
62 | }
63 |
64 | if (!bDarkModeChanged)
65 | {
66 | return;
67 | }
68 |
69 | g_bIsDarkMode = bIsDarkMode;
70 | ApplyAcrylicEffect();
71 | }
72 |
73 | void ApplyAcrylicEffect()
74 | {
75 | if (SystemHelper::g_bIsWindows11)
76 | {
77 | AcrylicHelper::SetAcrylicEffect(
78 | g_hWnd,
79 | g_bIsDarkMode ? WIN11_LUMINOSITY_TINT_DARK : WIN11_LUMINOSITY_TINT_LIGHT
80 | );
81 | }
82 | else
83 | {
84 | AcrylicHelper::SetAcrylicEffect(
85 | g_hWnd,
86 | ACRYLIC_TINT_AUTO ? g_dwBkColor : (g_bIsDarkMode ? ACRYLIC_TINT_DARK : ACRYLIC_TINT_LIGHT),
87 | g_bIsDarkMode ? ACRYLIC_OPACITY_DARK : ACRYLIC_OPACITY_LIGHT
88 | );
89 | }
90 | }
--------------------------------------------------------------------------------
/AcrylicMenus/MenuManager.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 |
4 | namespace AcrylicMenus
5 | {
6 | namespace MenuManager
7 | {
8 | extern thread_local HWND g_hWnd;
9 | extern thread_local bool g_bIsDarkMode;
10 | extern thread_local DWORD g_dwBkColor;
11 | extern thread_local bool g_bBkColorRefresh;
12 | extern thread_local bool g_alphaFixedState;
13 | extern thread_local bool g_menuOwnerDrawn;
14 |
15 | void SetCurrentMenu(HWND hWnd);
16 | void RefreshCurrentMenuBackground(bool bIsDarkMode, DWORD dwBkColor);
17 | }
18 | }
--------------------------------------------------------------------------------
/AcrylicMenus/Resource.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include "winres.h"
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // Neutral (Default) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD)
19 | LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
20 | #pragma code_page(1251)
21 |
22 | /////////////////////////////////////////////////////////////////////////////
23 | //
24 | // Version
25 | //
26 |
27 | VS_VERSION_INFO VERSIONINFO
28 | FILEVERSION 1,0,8,0
29 | PRODUCTVERSION 1,0,8,0
30 | FILEFLAGSMASK 0x3fL
31 | #ifdef _DEBUG
32 | FILEFLAGS 0x1L
33 | #else
34 | FILEFLAGS 0x0L
35 | #endif
36 | FILEOS 0x40004L
37 | FILETYPE 0x2L
38 | FILESUBTYPE 0x0L
39 | BEGIN
40 | BLOCK "StringFileInfo"
41 | BEGIN
42 | BLOCK "040004b0"
43 | BEGIN
44 | VALUE "CompanyName", "ALTaleX531, Maplespe, krlvm"
45 | VALUE "FileDescription", "AcrylicMenus Hook DLL"
46 | VALUE "FileVersion", "1.0.8.0"
47 | VALUE "InternalName", "AcrylicMenus.dll"
48 | VALUE "LegalCopyright", "Copyright (C) ALTaleX531, Maplespe, 2022, krlvm 2021-2022"
49 | VALUE "OriginalFilename", "AcrylicMenus.dll"
50 | VALUE "ProductName", "AcrylicMenus"
51 | VALUE "ProductVersion", "1.0.8.0"
52 | END
53 | END
54 | BLOCK "VarFileInfo"
55 | BEGIN
56 | VALUE "Translation", 0x400, 1200
57 | END
58 | END
59 |
60 | #endif // Neutral (Default) resources
61 | /////////////////////////////////////////////////////////////////////////////
62 |
63 |
64 | /////////////////////////////////////////////////////////////////////////////
65 | // Russian (Russia) resources
66 |
67 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
68 | LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
69 | #pragma code_page(1251)
70 |
71 | #ifdef APSTUDIO_INVOKED
72 | /////////////////////////////////////////////////////////////////////////////
73 | //
74 | // TEXTINCLUDE
75 | //
76 |
77 | 1 TEXTINCLUDE
78 | BEGIN
79 | "resource.h\0"
80 | END
81 |
82 | 2 TEXTINCLUDE
83 | BEGIN
84 | "#include ""winres.h""\r\n"
85 | "\0"
86 | END
87 |
88 | 3 TEXTINCLUDE
89 | BEGIN
90 | "\r\n"
91 | "\0"
92 | END
93 |
94 | #endif // APSTUDIO_INVOKED
95 |
96 | #endif // Russian (Russia) resources
97 | /////////////////////////////////////////////////////////////////////////////
98 |
99 |
100 |
101 | #ifndef APSTUDIO_INVOKED
102 | /////////////////////////////////////////////////////////////////////////////
103 | //
104 | // Generated from the TEXTINCLUDE 3 resource.
105 | //
106 |
107 |
108 | /////////////////////////////////////////////////////////////////////////////
109 | #endif // not APSTUDIO_INVOKED
110 |
111 |
--------------------------------------------------------------------------------
/AcrylicMenus/SettingsHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 |
4 | #pragma warning(disable : 4996)
5 |
6 | namespace AcrylicMenus
7 | {
8 | namespace SettingsHelper
9 | {
10 | extern bool g_redrawDarkThemeBorders10;
11 |
12 | static bool IsFeatureEnabled(LPCWSTR lpRegistryValue)
13 | {
14 | HKEY hKey;
15 | RegOpenKeyEx(
16 | HKEY_CURRENT_USER,
17 | L"SOFTWARE\\AcrylicMenus", 0, KEY_READ, &hKey
18 | );
19 |
20 | if (!hKey) return FALSE;
21 |
22 | DWORD dwResult = 0;
23 | DWORD dwSize = sizeof(DWORD);
24 | LSTATUS nError = RegQueryValueExW(
25 | hKey,
26 | lpRegistryValue,
27 | 0,
28 | NULL,
29 | (LPBYTE)&dwResult,
30 | &dwSize
31 | );
32 |
33 | RegCloseKey(hKey);
34 |
35 | return ERROR_SUCCESS == nError ? dwResult : false;
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/AcrylicMenus/SystemHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 |
4 | #pragma warning(disable : 4996)
5 |
6 | namespace AcrylicMenus
7 | {
8 | namespace SystemHelper
9 | {
10 | extern bool g_bIsWindows11;
11 |
12 |
13 | typedef BOOL(WINAPI* pfnRtlGetVersion)(OSVERSIONINFOEXW*);
14 | static DWORD DetectOSBuildNumber()
15 | {
16 | HMODULE hMod = LoadLibrary(TEXT("ntdll.dll"));
17 | if (!hMod)
18 | {
19 | return 0;
20 | }
21 |
22 | pfnRtlGetVersion RtlGetVersion = (pfnRtlGetVersion)GetProcAddress(hMod, "RtlGetVersion");
23 |
24 | OSVERSIONINFOEXW info;
25 | ZeroMemory(&info, sizeof(OSVERSIONINFOEXW));
26 | RtlGetVersion(&info);
27 |
28 | DWORD dwBuildNumber = info.dwBuildNumber;
29 | FreeLibrary(hMod);
30 | return dwBuildNumber;
31 | }
32 |
33 | static bool IsTransparencyEnabled()
34 | {
35 | DWORD dwResult = 0;
36 | DWORD dwSize = sizeof(DWORD);
37 | RegGetValue(
38 | HKEY_CURRENT_USER,
39 | L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
40 | L"EnableTransparency",
41 | RRF_RT_REG_DWORD,
42 | nullptr,
43 | &dwResult, &dwSize
44 | );
45 | return dwResult == 1;
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/AcrylicMenus/ThemeHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 |
4 | namespace AcrylicMenus
5 | {
6 | namespace ThemeHelper
7 | {
8 | // Windows 11 22H2+
9 | enum MENUPARTSEX
10 | {
11 | MENU_POPUPITEMKBFOCUS = 26,
12 | MENU_POPUPITEM_FOCUSABLE = 27
13 | };
14 |
15 | typedef HRESULT(WINAPI*pfnGetThemeClass)(HTHEME hTheme, LPCTSTR pszClassName, int cchClassName);
16 | static pfnGetThemeClass GetThemeClass
17 | = (pfnGetThemeClass)GetProcAddress(GetModuleHandle(L"Uxtheme"), MAKEINTRESOURCEA(74));
18 |
19 | typedef BOOL(WINAPI*pfnIsThemeClassDefined)(HTHEME hTheme, LPCTSTR pszAppName, LPCTSTR pszClassName, BOOL bMatchClass);
20 | static pfnIsThemeClassDefined IsThemeClassDefined
21 | = (pfnIsThemeClassDefined)GetProcAddress(GetModuleHandle(L"Uxtheme"), MAKEINTRESOURCEA(50));
22 |
23 | typedef BOOL(WINAPI*pfnIsTopLevelWindow)(HWND hWnd);
24 | static pfnIsTopLevelWindow IsTopLevelWindow
25 | = (pfnIsTopLevelWindow)GetProcAddress(GetModuleHandle(L"User32"), "IsTopLevelWindow");
26 |
27 | static void GetMenuFillColor(LPCWSTR pszClassList, COLORREF *pColor)
28 | {
29 | HTHEME hTheme = OpenThemeData(NULL, pszClassList);
30 | GetThemeColor(hTheme, MENU_POPUPBACKGROUND, 0, TMT_FILLCOLOR, pColor);
31 | CloseThemeData(hTheme);
32 | }
33 |
34 | static bool IsWindowUseDarkMode(HWND hwnd)
35 | {
36 | BOOL bResult { FALSE };
37 | DwmGetWindowAttribute(hwnd, 20, &bResult, sizeof(bResult));
38 | return bResult;
39 | }
40 |
41 | static inline bool IsAncestorUseDarkMode(GUITHREADINFO gti)
42 | {
43 | HWND hwndMenuRoot = GetAncestor(gti.hwndMenuOwner, GA_ROOT);
44 | return IsWindowUseDarkMode(hwndMenuRoot);
45 | }
46 |
47 | static bool IsMenuUseDarkMode(HWND hwnd)
48 | {
49 | GUITHREADINFO gti = { sizeof(GUITHREADINFO), };
50 | DWORD tid = GetWindowThreadProcessId(hwnd, NULL);
51 |
52 | if (tid && GetGUIThreadInfo(tid, >i))
53 | {
54 | return IsWindowUseDarkMode(gti.hwndMenuOwner); // || IsAncestorUseDarkMode(gti);
55 | }
56 |
57 | return false;
58 | }
59 |
60 | static inline bool VerifyThemeData(HTHEME hTheme, LPCTSTR pszThemeClassName)
61 | {
62 | TCHAR pszClassName[MAX_PATH + 1];
63 | GetThemeClass(hTheme, pszClassName, MAX_PATH);
64 | return !_wcsicmp(pszClassName, pszThemeClassName);
65 | }
66 |
67 | static inline bool VerifyWindowClass(HWND hWnd, LPCTSTR pszClassName, BOOL bRequireTopLevel = FALSE)
68 | {
69 | TCHAR pszClass[MAX_PATH + 1] = {};
70 | GetClassName(hWnd, pszClass, MAX_PATH);
71 | return (!_tcscmp(pszClass, pszClassName) && (bRequireTopLevel ? IsTopLevelWindow(hWnd) : TRUE));
72 | }
73 |
74 | static inline bool IsPopupMenu(HWND hWnd)
75 | {
76 | if (GetClassLong(hWnd, GCW_ATOM) == 32768)
77 | {
78 | return true;
79 | }
80 |
81 | TCHAR pszClass[MAX_PATH + 1];
82 | GetClassName(hWnd, pszClass, MAX_PATH);
83 |
84 | return IsTopLevelWindow(hWnd) && _tcscmp(pszClass, TEXT("#32768")) == 0;
85 | }
86 |
87 | static inline void Clear(HDC hdc, LPCRECT lpRect)
88 | {
89 | PatBlt(
90 | hdc,
91 | lpRect->left,
92 | lpRect->top,
93 | lpRect->right - lpRect->left,
94 | lpRect->bottom - lpRect->top,
95 | BLACKNESS
96 | );
97 | }
98 |
99 | static inline HBITMAP CreateDIB(HDC hdc, LONG nWidth, LONG nHeight, PVOID* pvBits)
100 | {
101 | BITMAPINFO bitmapInfo = {};
102 | bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader);
103 | bitmapInfo.bmiHeader.biBitCount = 32;
104 | bitmapInfo.bmiHeader.biCompression = BI_RGB;
105 | bitmapInfo.bmiHeader.biPlanes = 1;
106 | bitmapInfo.bmiHeader.biWidth = nWidth;
107 | bitmapInfo.bmiHeader.biHeight = -nHeight;
108 |
109 | return CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, pvBits, nullptr, 0);
110 | }
111 |
112 | static inline COLORREF GetBrushColor(HBRUSH hBrush)
113 | {
114 | LOGBRUSH lbr = {};
115 | GetObject(hBrush, sizeof(lbr), &lbr);
116 | if (lbr.lbStyle != BS_SOLID)
117 | {
118 | return CLR_NONE;
119 | }
120 | return lbr.lbColor;
121 | }
122 |
123 | static inline void SetPixel(PBYTE pvBits, BYTE b, BYTE g, BYTE r, BYTE a)
124 | {
125 | pvBits[0] = (b * (a + 1)) >> 8;
126 | pvBits[1] = (g * (a + 1)) >> 8;
127 | pvBits[2] = (r * (a + 1)) >> 8;
128 | pvBits[3] = a;
129 | }
130 |
131 | static void PrepareAlpha(HBITMAP hBitmap)
132 | {
133 | if (!hBitmap)
134 | {
135 | return;
136 | }
137 |
138 | if (GetObjectType(hBitmap) != OBJ_BITMAP)
139 | {
140 | return;
141 | }
142 |
143 | HDC hdc = CreateCompatibleDC(nullptr);
144 | BITMAPINFO bmi = { sizeof(bmi.bmiHeader) };
145 |
146 | if (hdc)
147 | {
148 | if (GetDIBits(hdc, hBitmap, 0, 0, nullptr, &bmi, DIB_RGB_COLORS) and bmi.bmiHeader.biBitCount == 32)
149 | {
150 | bmi.bmiHeader.biCompression = BI_RGB;
151 |
152 | BYTE* pvBits = new(std::nothrow) BYTE[bmi.bmiHeader.biSizeImage];
153 |
154 | if (pvBits)
155 | {
156 | if (GetDIBits(hdc, hBitmap, 0, bmi.bmiHeader.biHeight, (LPVOID)pvBits, &bmi, DIB_RGB_COLORS))
157 | {
158 | bool bHasAlpha = false;
159 |
160 | for (UINT i = 0; i < bmi.bmiHeader.biSizeImage; i += 4)
161 | {
162 | if (pvBits[i + 3] != 0)
163 | {
164 | bHasAlpha = true;
165 | break;
166 | }
167 | }
168 |
169 | if (!bHasAlpha)
170 | {
171 | for (UINT i = 0; i < bmi.bmiHeader.biSizeImage; i += 4)
172 | {
173 | pvBits[i] = (pvBits[i] * 256) >> 8;
174 | pvBits[i + 1] = (pvBits[i + 1] * 256) >> 8;
175 | pvBits[i + 2] = (pvBits[i + 2] * 256) >> 8;
176 | pvBits[i + 3] = 255;
177 | }
178 | }
179 |
180 | SetDIBits(hdc, hBitmap, 0, bmi.bmiHeader.biHeight, pvBits, &bmi, DIB_RGB_COLORS);
181 | }
182 | delete[] pvBits;
183 | }
184 | }
185 | DeleteDC(hdc);
186 | }
187 | }
188 |
189 | template
190 | static BOOL DoBufferedPaint(
191 | HDC hdc,
192 | LPCRECT Rect,
193 | T&& t,
194 | BYTE dwOpacity = 255,
195 | DWORD dwFlag = BPPF_ERASE,
196 | BOOL bUpdateTarget = TRUE,
197 | BOOL bUseBlendFunction = TRUE
198 | )
199 | {
200 | HDC hMemDC = nullptr;
201 | BLENDFUNCTION BlendFunction = { AC_SRC_OVER, 0, dwOpacity, AC_SRC_ALPHA };
202 | BP_PAINTPARAMS PaintParams = { sizeof(BP_PAINTPARAMS), dwFlag, nullptr, bUseBlendFunction ? &BlendFunction : nullptr };
203 | HPAINTBUFFER hPaintBuffer = BeginBufferedPaint(hdc, Rect, BPBF_TOPDOWNDIB, &PaintParams, &hMemDC);
204 |
205 | if (!hPaintBuffer || !hMemDC)
206 | {
207 | return FALSE;
208 | }
209 |
210 | SetLayout(hMemDC, GetLayout(hdc));
211 | SelectObject(hMemDC, GetCurrentObject(hdc, OBJ_FONT));
212 | SelectObject(hMemDC, GetCurrentObject(hdc, OBJ_BRUSH));
213 | SelectObject(hMemDC, GetCurrentObject(hdc, OBJ_PEN));
214 | SetTextAlign(hMemDC, GetTextAlign(hdc));
215 |
216 | t(hMemDC, hPaintBuffer);
217 | EndBufferedPaint(hPaintBuffer, bUpdateTarget);
218 |
219 | return TRUE;
220 | }
221 |
222 | template
223 | static BOOL BufferedPaintWalkBits(
224 | HPAINTBUFFER hPaintBuffer,
225 | T&& t
226 | )
227 | {
228 | int cxRow = 0;
229 | RGBQUAD* pbBuffer = nullptr;
230 | RECT targetRect = {};
231 | if (SUCCEEDED(GetBufferedPaintTargetRect(hPaintBuffer, &targetRect)))
232 | {
233 | int cx = targetRect.right - targetRect.left;
234 | int cy = targetRect.bottom - targetRect.top;
235 | if (SUCCEEDED(GetBufferedPaintBits(hPaintBuffer, &pbBuffer, &cxRow)))
236 | {
237 | for (int y = 0; y < cy; y++)
238 | {
239 | for (int x = 0; x < cx; x++)
240 | {
241 | RGBQUAD *pRGBAInfo = &pbBuffer[y * cxRow + x];
242 | if (!t(y, x, pRGBAInfo))
243 | {
244 | break;
245 | }
246 | }
247 | }
248 | return TRUE;
249 | }
250 | }
251 | return FALSE;
252 | }
253 | }
254 | }
--------------------------------------------------------------------------------
/AcrylicMenus/WindowHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "pch.h"
3 | #include "SettingsHelper.h"
4 | #include "AppearanceConfiguration.h"
5 |
6 | namespace AcrylicMenus
7 | {
8 | namespace WindowHelper
9 | {
10 | ///
11 | /// After user selects option, if menu fade out animation
12 | /// is enabled in system settings, system will draw
13 | /// the selected item, but its background color alpha value
14 | /// is set to 0 and GDI does not support transparency, so
15 | /// it will be just black, which is not pleasant to see
16 | /// in light mode, so we temporary turn off the animation
17 | /// (see MenuHandler SubclassProc), then starting our
18 | /// custom animation and re-enabling the system preference.
19 | ///
20 | /// We create a layered popup window, capture the item
21 | /// with BitBlt and draw it onto the window, then beginning
22 | /// the animation in a new thread - it will resemble
23 | /// the default fade out animation.
24 | ///
25 |
26 | #pragma region Menu Fade Out Animation
27 |
28 | #ifdef _WIN64
29 | #define GetTickCountU GetTickCount64
30 | #else
31 | #define GetTickCountU GetTickCount
32 | #endif
33 |
34 | #define MENU_ANIMATION_FRAMES 350
35 | #define MENU_ANIMATION_INTERVAL 10
36 |
37 | DWORD WINAPI MenuFadeOutAnimationThreadProc(LPVOID lpParameter)
38 | {
39 | HWND hwnd = (HWND)lpParameter;
40 | BLENDFUNCTION pBlend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
41 |
42 | DWORD dwStart = GetTickCountU() - 55;
43 |
44 | Sleep(MENU_ANIMATION_INTERVAL);
45 |
46 | for (int i = GetTickCountU() - dwStart; i <= MENU_ANIMATION_FRAMES; i = GetTickCount64() - dwStart)
47 | {
48 | pBlend.SourceConstantAlpha = ((255 * MENU_ANIMATION_FRAMES) - (255 * i)) / MENU_ANIMATION_FRAMES;
49 | UpdateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &pBlend, ULW_ALPHA);
50 | Sleep(MENU_ANIMATION_INTERVAL);
51 | }
52 |
53 | return PostMessageW(hwnd, WM_CLOSE, NULL, NULL);
54 | }
55 |
56 | void BeginMenuFadeOutAnimation(MENUBARINFO &pmbi)
57 | {
58 | HWND hwnd = CreateWindowExW(
59 | 0x80800A8, // Spy++
60 | L"Static",
61 | L"Fade",
62 | WS_POPUP,
63 | pmbi.rcBar.left,
64 | pmbi.rcBar.top,
65 | pmbi.rcBar.right - pmbi.rcBar.left,
66 | pmbi.rcBar.bottom - pmbi.rcBar.top,
67 | NULL,
68 | NULL,
69 | NULL,
70 | NULL
71 | );
72 |
73 | RECT rcDst;
74 | GetWindowRect(hwnd, &rcDst);
75 |
76 | SIZE szDst = { rcDst.right - rcDst.left, rcDst.bottom - rcDst.top };
77 | POINT ptDst = { rcDst.left, rcDst.top };
78 | POINT ptSrc = { 0, 0 };
79 |
80 | BLENDFUNCTION pBlend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
81 |
82 | HDC hdcScreen = GetDC(NULL);
83 | HDC hdcMemory = CreateCompatibleDC(hdcScreen);
84 |
85 | HBITMAP bmpMemory = CreateCompatibleBitmap(hdcScreen, szDst.cx, szDst.cy);
86 | SelectObject(hdcMemory, bmpMemory);
87 |
88 | BITMAP bitmap;
89 | GetObject(bmpMemory, sizeof(BITMAP), &bitmap);
90 |
91 | BitBlt(
92 | hdcMemory,
93 | 0,
94 | 0,
95 | szDst.cx,
96 | szDst.cy,
97 | hdcScreen,
98 | pmbi.rcBar.left,
99 | pmbi.rcBar.top,
100 | SRCCOPY
101 | );
102 |
103 | UpdateLayeredWindow(hwnd, hdcScreen, &ptDst, &szDst, hdcMemory, &ptSrc, 0, &pBlend, ULW_ALPHA);
104 | SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
105 |
106 | DeleteObject(bmpMemory);
107 |
108 | DeleteDC(hdcMemory);
109 | ReleaseDC(NULL, hdcScreen);
110 |
111 | HANDLE hThread = CreateThread(NULL, 0, MenuFadeOutAnimationThreadProc, hwnd, 0, NULL);
112 | if (hThread) CloseHandle(hThread);
113 | }
114 |
115 | #pragma endregion
116 | }
117 | }
--------------------------------------------------------------------------------
/AcrylicMenus/amapi.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "amapi.h"
3 | #include "SystemHelper.h"
4 | #include "MenuHandler.h"
5 |
6 | #pragma data_seg("shared")
7 | HWINEVENTHOOK g_hHook = NULL;
8 | #pragma data_seg()
9 | #pragma comment(linker,"/SECTION:shared,RWS")
10 |
11 | using namespace AcrylicMenus;
12 |
13 | extern HMODULE g_hModule;
14 |
15 | extern "C"
16 | {
17 | BOOL WINAPI RegisterHook(DWORD dwProcessId)
18 | {
19 | if (IsHookInstalled())
20 | {
21 | SetLastError(ERROR_ALREADY_EXISTS);
22 | return FALSE;
23 | }
24 |
25 | g_hHook = SetWinEventHook(
26 | EVENT_OBJECT_CREATE, EVENT_OBJECT_SHOW,
27 | g_hModule,
28 | MenuHandler::WinEventProc,
29 | dwProcessId, 0,
30 | WINEVENT_INCONTEXT
31 | );
32 |
33 | AcrylicMenus::Startup();
34 |
35 | return !!g_hHook;
36 | }
37 |
38 | BOOL WINAPI UnregisterHook()
39 | {
40 | if (!IsHookInstalled())
41 | {
42 | SetLastError(ERROR_INVALID_PARAMETER);
43 | return FALSE;
44 | }
45 |
46 | BOOL bResult = UnhookWinEvent(g_hHook);
47 | if (bResult)
48 | {
49 | g_hHook = NULL;
50 | AcrylicMenus::Shutdown();
51 | }
52 |
53 | return bResult;
54 | }
55 |
56 | BOOL WINAPI IsHookInstalled()
57 | {
58 | return g_hHook != NULL;
59 | }
60 | }
61 |
62 | void AcrylicMenus::Startup()
63 | {
64 | Detours::Begin();
65 | //
66 | MenuHooks::Win32HookStartup();
67 | //
68 | Detours::Commit();
69 | }
70 |
71 | void AcrylicMenus::Shutdown()
72 | {
73 | Detours::Begin();
74 | //
75 | MenuHooks::Win32HookShutdown();
76 | //
77 | Detours::Commit();
78 | }
--------------------------------------------------------------------------------
/AcrylicMenus/amapi.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #define AMAPI __declspec(dllimport)
5 |
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 |
10 | AMAPI BOOL WINAPI RegisterHook(DWORD dwProcessId);
11 | AMAPI BOOL WINAPI UnregisterHook();
12 | AMAPI BOOL WINAPI IsHookInstalled();
13 |
14 | #ifdef __cplusplus
15 | }
16 | #endif
17 |
18 | namespace AcrylicMenus
19 | {
20 | void Startup();
21 | void Shutdown();
22 | }
--------------------------------------------------------------------------------
/AcrylicMenus/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "amapi.h"
3 | #include "SystemHelper.h"
4 | #include "SettingsHelper.h"
5 |
6 | using namespace AcrylicMenus;
7 |
8 | HMODULE g_hModule = nullptr;
9 | bool SystemHelper::g_bIsWindows11 = false;
10 |
11 | BOOL APIENTRY DllMain(
12 | HMODULE hModule,
13 | DWORD dwReason,
14 | LPVOID lpReserved
15 | )
16 | {
17 | switch (dwReason)
18 | {
19 | case DLL_PROCESS_ATTACH:
20 | {
21 | g_hModule = hModule;
22 | DisableThreadLibraryCalls(hModule);
23 | SystemHelper::g_bIsWindows11 = SystemHelper::DetectOSBuildNumber() >= 22000;
24 | AcrylicMenus::Startup();
25 | break;
26 | }
27 | case DLL_PROCESS_DETACH:
28 | {
29 | AcrylicMenus::Shutdown();
30 | break;
31 | }
32 | case DLL_THREAD_ATTACH:
33 | case DLL_THREAD_DETACH:
34 | break;
35 | }
36 | return TRUE;
37 | }
--------------------------------------------------------------------------------
/AcrylicMenus/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/AcrylicMenus/pch.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
--------------------------------------------------------------------------------
/AcrylicMenus/pch.h:
--------------------------------------------------------------------------------
1 | #ifndef PCH_H
2 | #define PCH_H
3 |
4 | #define WIN32_LEAN_AND_MEAN
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include