├── .gitattributes
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── AnalysisReport.sarif
├── LICENSE
├── PackagingProject
├── Images
│ ├── LargeTile.scale-100.png
│ ├── LargeTile.scale-125.png
│ ├── LargeTile.scale-150.png
│ ├── LargeTile.scale-200.png
│ ├── LargeTile.scale-400.png
│ ├── SmallTile.scale-100.png
│ ├── SmallTile.scale-125.png
│ ├── SmallTile.scale-150.png
│ ├── SmallTile.scale-200.png
│ ├── SmallTile.scale-400.png
│ ├── SplashScreen.scale-100.png
│ ├── SplashScreen.scale-125.png
│ ├── SplashScreen.scale-150.png
│ ├── SplashScreen.scale-200.png
│ ├── SplashScreen.scale-400.png
│ ├── Square150x150Logo.scale-100.png
│ ├── Square150x150Logo.scale-125.png
│ ├── Square150x150Logo.scale-150.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-400.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png
│ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ ├── Square44x44Logo.altform-unplated_targetsize-256.png
│ ├── Square44x44Logo.altform-unplated_targetsize-32.png
│ ├── Square44x44Logo.altform-unplated_targetsize-48.png
│ ├── Square44x44Logo.scale-100.png
│ ├── Square44x44Logo.scale-125.png
│ ├── Square44x44Logo.scale-150.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.scale-400.png
│ ├── Square44x44Logo.targetsize-16.png
│ ├── Square44x44Logo.targetsize-24.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── Square44x44Logo.targetsize-256.png
│ ├── Square44x44Logo.targetsize-32.png
│ ├── Square44x44Logo.targetsize-48.png
│ ├── StoreLogo.backup.png
│ ├── StoreLogo.scale-100.png
│ ├── StoreLogo.scale-125.png
│ ├── StoreLogo.scale-150.png
│ ├── StoreLogo.scale-200.png
│ ├── StoreLogo.scale-400.png
│ ├── Wide310x150Logo.scale-100.png
│ ├── Wide310x150Logo.scale-125.png
│ ├── Wide310x150Logo.scale-150.png
│ ├── Wide310x150Logo.scale-200.png
│ └── Wide310x150Logo.scale-400.png
├── Package.appxmanifest
└── RoundedTB.Package.wapproj
├── README.md
├── RoundedTB.sln
├── RoundedTB
├── .editorconfig
├── AboutWindow.xaml
├── AboutWindow.xaml.cs
├── App.config
├── App.xaml
├── App.xaml.cs
├── AppBars.cs
├── Background.cs
├── FodyWeavers.xml
├── IAppVisibility.cs
├── Infobox.xaml
├── Infobox.xaml.cs
├── Interaction.cs
├── LocalPInvoke.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── MonitorStuff.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── RoundedTB.csproj
├── RoundedTB.ico
├── RoundedTBCanary.ico
├── RoundedTBDev.ico
├── Taskbar.cs
├── TaskbarEffect.xaml
├── TaskbarEffect.xaml.cs
├── Tasklist.cs
├── Types.cs
├── app.manifest
└── res
│ ├── HeadBannerCan.png
│ ├── HeadBannerDev.png
│ ├── Headbanner.png
│ ├── TrayDark.ico
│ └── TrayLight.ico
└── upgrade-assistant.clef
/.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 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: release
2 |
3 | on:
4 | push:
5 |
6 | jobs:
7 | build:
8 | name: build-windows
9 | runs-on: windows-2022
10 |
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@v3
14 | with:
15 | submodules: recursive
16 |
17 | - name: Set up MSBuild
18 | uses: microsoft/setup-msbuild@v1
19 |
20 | - name: NuGet Restore
21 | run: |
22 | cd ${{ github.workspace }}
23 | nuget restore RoundedTB.sln
24 |
25 | - name: Build
26 | run: |
27 | cd ${{ github.workspace }}
28 | msbuild "-property:Configuration=Release" -t:RoundedTB
29 |
30 | - name: Add commit hash to output folder
31 | run: |
32 | Rename-Item -Path ".\RoundedTB\bin\Release" -NewName "RoundedTB-$(git rev-parse --short ${{ github.sha }})"
33 |
34 | - name: Upload artifacts
35 | uses: actions/upload-artifact@v3
36 | with:
37 | name: rtb-artifacts
38 | path: |
39 | .\RoundedTB\bin\RoundedTB-*\
40 |
--------------------------------------------------------------------------------
/.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
364 | /RoundedTB/RoundedTBEmi.ico
365 |
--------------------------------------------------------------------------------
/AnalysisReport.sarif:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json",
3 | "version": "2.1.0",
4 | "runs": [
5 | {
6 | "tool": {
7 | "driver": {
8 | "name": "Dependency Analysis",
9 | "semanticVersion": "0.3.261602",
10 | "informationUri": "https://docs.microsoft.com/en-us/dotnet/core/porting/upgrade-assistant-overview",
11 | "rules": [
12 | {
13 | "id": "UA105",
14 | "name": "PackageToBeDeleted",
15 | "fullDescription": {
16 | "text": "Packages that need to be deleted in order to upgrade the project to chosen TFM"
17 | },
18 | "helpUri": "https://docs.microsoft.com/en-us/dotnet/core/porting/upgrade-assistant-overview"
19 | },
20 | {
21 | "id": "UA106",
22 | "name": "PackageToBeAdded",
23 | "fullDescription": {
24 | "text": "Packages that need to be added in order to upgrade the project to chosen TFM"
25 | },
26 | "helpUri": "https://docs.microsoft.com/en-us/dotnet/core/porting/upgrade-assistant-overview"
27 | }
28 | ]
29 | }
30 | },
31 | "results": [
32 | {
33 | "ruleId": "UA105",
34 | "message": {
35 | "text": "Package Microsoft.Windows.SDK.Contracts, Version=10.0.18362.2005 needs to be deleted."
36 | },
37 | "locations": [
38 | {
39 | "physicalLocation": {
40 | "artifactLocation": {
41 | "uri": "file:///C:/Users/Torch/source/repos/RoundedTB/RoundedTB/RoundedTB.csproj"
42 | },
43 | "region": {}
44 | }
45 | }
46 | ]
47 | },
48 | {
49 | "ruleId": "UA105",
50 | "message": {
51 | "text": "Package System.Runtime.WindowsRuntime, Version=4.6.0 needs to be deleted."
52 | },
53 | "locations": [
54 | {
55 | "physicalLocation": {
56 | "artifactLocation": {
57 | "uri": "file:///C:/Users/Torch/source/repos/RoundedTB/RoundedTB/RoundedTB.csproj"
58 | },
59 | "region": {}
60 | }
61 | }
62 | ]
63 | },
64 | {
65 | "ruleId": "UA105",
66 | "message": {
67 | "text": "Package System.Runtime.WindowsRuntime.UI.Xaml, Version=4.6.0 needs to be deleted."
68 | },
69 | "locations": [
70 | {
71 | "physicalLocation": {
72 | "artifactLocation": {
73 | "uri": "file:///C:/Users/Torch/source/repos/RoundedTB/RoundedTB/RoundedTB.csproj"
74 | },
75 | "region": {}
76 | }
77 | }
78 | ]
79 | },
80 | {
81 | "ruleId": "UA105",
82 | "message": {
83 | "text": "Package System.ValueTuple, Version=4.5.0 needs to be deleted."
84 | },
85 | "locations": [
86 | {
87 | "physicalLocation": {
88 | "artifactLocation": {
89 | "uri": "file:///C:/Users/Torch/source/repos/RoundedTB/RoundedTB/RoundedTB.csproj"
90 | },
91 | "region": {}
92 | }
93 | }
94 | ]
95 | },
96 | {
97 | "ruleId": "UA106",
98 | "message": {
99 | "text": "Package Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers, Version=0.3.261602 needs to be added."
100 | },
101 | "locations": [
102 | {
103 | "physicalLocation": {
104 | "artifactLocation": {
105 | "uri": "file:///C:/Users/Torch/source/repos/RoundedTB/RoundedTB/RoundedTB.csproj"
106 | },
107 | "region": {}
108 | }
109 | }
110 | ]
111 | },
112 | {
113 | "ruleId": "UA106",
114 | "message": {
115 | "text": "Package Microsoft.Windows.Compatibility, Version=6.0.0 needs to be added."
116 | },
117 | "locations": [
118 | {
119 | "physicalLocation": {
120 | "artifactLocation": {
121 | "uri": "file:///C:/Users/Torch/source/repos/RoundedTB/RoundedTB/RoundedTB.csproj"
122 | },
123 | "region": {}
124 | }
125 | }
126 | ]
127 | }
128 | ],
129 | "columnKind": "utf16CodeUnits"
130 | },
131 | {
132 | "tool": {
133 | "driver": {
134 | "name": "API Upgradability",
135 | "semanticVersion": "0.3.261602",
136 | "informationUri": "https://docs.microsoft.com/en-us/dotnet/core/porting/upgrade-assistant-overview"
137 | }
138 | },
139 | "results": [],
140 | "columnKind": "utf16CodeUnits"
141 | },
142 | {
143 | "tool": {
144 | "driver": {
145 | "name": "Component Analysis",
146 | "semanticVersion": "0.3.261602",
147 | "informationUri": "https://docs.microsoft.com/en-us/dotnet/core/porting/upgrade-assistant-overview"
148 | }
149 | },
150 | "results": [],
151 | "columnKind": "utf16CodeUnits"
152 | }
153 | ]
154 | }
--------------------------------------------------------------------------------
/PackagingProject/Images/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/PackagingProject/Images/LargeTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/LargeTile.scale-125.png
--------------------------------------------------------------------------------
/PackagingProject/Images/LargeTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/LargeTile.scale-150.png
--------------------------------------------------------------------------------
/PackagingProject/Images/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/PackagingProject/Images/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SmallTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SmallTile.scale-125.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SmallTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SmallTile.scale-150.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SplashScreen.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SplashScreen.scale-100.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SplashScreen.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SplashScreen.scale-125.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SplashScreen.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SplashScreen.scale-150.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/PackagingProject/Images/SplashScreen.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/SplashScreen.scale-400.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square150x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square150x150Logo.scale-125.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square150x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square150x150Logo.scale-150.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-32.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.scale-100.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.scale-125.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.scale-150.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.scale-400.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.targetsize-16.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.targetsize-24.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.targetsize-256.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.targetsize-32.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/PackagingProject/Images/StoreLogo.backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/StoreLogo.backup.png
--------------------------------------------------------------------------------
/PackagingProject/Images/StoreLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/StoreLogo.scale-100.png
--------------------------------------------------------------------------------
/PackagingProject/Images/StoreLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/StoreLogo.scale-125.png
--------------------------------------------------------------------------------
/PackagingProject/Images/StoreLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/StoreLogo.scale-150.png
--------------------------------------------------------------------------------
/PackagingProject/Images/StoreLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/StoreLogo.scale-200.png
--------------------------------------------------------------------------------
/PackagingProject/Images/StoreLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/StoreLogo.scale-400.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Wide310x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Wide310x150Logo.scale-100.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Wide310x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Wide310x150Logo.scale-125.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Wide310x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Wide310x150Logo.scale-150.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/PackagingProject/Images/Wide310x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/PackagingProject/Images/Wide310x150Logo.scale-400.png
--------------------------------------------------------------------------------
/PackagingProject/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
14 |
15 |
16 | RoundedTB
17 | TorchGM
18 | Images\StoreLogo.png
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/PackagingProject/RoundedTB.Package.wapproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 15.0
5 |
6 |
7 |
8 | Debug
9 | x86
10 |
11 |
12 | Release
13 | x86
14 |
15 |
16 | Debug
17 | x64
18 |
19 |
20 | Release
21 | x64
22 |
23 |
24 | Debug
25 | ARM
26 |
27 |
28 | Release
29 | ARM
30 |
31 |
32 | Debug
33 | ARM64
34 |
35 |
36 | Release
37 | ARM64
38 |
39 |
40 | Debug
41 | AnyCPU
42 |
43 |
44 | Release
45 | AnyCPU
46 |
47 |
48 | Remote Debug
49 | AnyCPU
50 |
51 |
52 | Remote Debug
53 | ARM
54 |
55 |
56 | Remote Debug
57 | ARM64
58 |
59 |
60 | Remote Debug
61 | x64
62 |
63 |
64 | Remote Debug
65 | x86
66 |
67 |
68 |
69 | $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\
70 |
71 |
72 |
73 | 660827eb-23be-4bd2-8a5b-355134f264d8
74 | 10.0.19041.0
75 | 10.0.17763.0
76 | en-US
77 | True
78 | False
79 | 949AB122C53DAF37D8272CA0AA2350D81DDE2329
80 | SHA256
81 | False
82 | True
83 | neutral
84 | 0
85 | ..\RoundedTB\RoundedTB.csproj
86 | True
87 |
88 |
89 | Always
90 |
91 |
92 | Always
93 |
94 |
95 | Always
96 |
97 |
98 | Always
99 |
100 |
101 | Always
102 |
103 |
104 | Always
105 |
106 |
107 | Always
108 |
109 |
110 | Always
111 |
112 |
113 | Always
114 |
115 |
116 | Always
117 |
118 |
119 | Always
120 |
121 |
122 | Always
123 |
124 |
125 | Always
126 |
127 |
128 | Always
129 |
130 |
131 | Always
132 |
133 |
134 |
135 | Designer
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # RoundedTB
4 | #### Add margins, rounded corners and segments to your taskbars!
5 |
6 | 
7 |
8 |
9 | ## How do I get it?
10 | The easiest way to download RoundedTB is from the [Microsoft Store](https://www.microsoft.com/store/productId/9MTFTXSJ9M7F). You can also download the latest version from the Releases tab, unzip it and run `RoundedTB.exe`. If you're a madman, you can compile it yourself or check out the latest [Canary build](https://nightly.link/torchgm/RoundedTB/workflows/ci/master/rtb-artifacts.zip) (note these can be very unfinished, buggy and unstable).
11 |
12 | ## To use
13 | ### Basic options
14 | The simplest way to use RoundedTB is by simply entering a margin and corner radius.
15 | - **Margin** - controls how many pixels to remove from each side of the taskbar, creating a margin around it that you can see and click through.
16 | - **Corner Radius** - adjusts how round the corners of the taskbar should be.
17 |
18 | ### Advanced options
19 | The advanced options allow for further customisation, at the cost of some user-friendliness.
20 | - **Independent Margins** - in the advanced settings, a ... button appears on the margin box. Click it to enable independent margins, which allow you to specify the margin for each side of the taskbar. You can also use negative values to hide the rounded corners for some sides, allowing you to "attach" the taskbar to different sides of the monitor.
21 | - **Dynamic Mode (Windows 11)** - dynamic mode automatically resizes the taskbars to accommodate the number of icons in it, making the taskbar behave similarly to macOS' Dock.
22 | - **Split Mode (Windows 10)** - split mode is a simplified version of dynamic mode for Windows 10. Due to a more limited taskbar, dynamically resizing the taskbar isn't possible. However after some setup, split mode allows you to separate the taskbar from the system tray and resize it at will. I admit it's certainly not as cool as dynamic mode but for now it's better than nothing 🥺. For info on setting up, see the bottom of this readme.
23 | - **Show System Tray** - this toggles whether or not the system tray, clock etc. is displayed in dynamic/split mode. It can be toggled at any time by pressing Win+F2.
24 | - **TranslucentTB Compatibility** - due to a bug in Windows, apps that alter the composition of the taskbar don't allow RoundedTB's changes to show up automatically. Whilst I'm currently not aware of a fix, I've worked closely with [Sylveon](https://github.com/sylveon) to enable some level of compatibility between [TranslucentTB](https://github.com/TranslucentTB/TranslucentTB) and RoundedTB. This is experimental and *will* flicker slightly. It requires TranslucentTB version 2021.5 to function.
25 | - **About RoundedTB** - provides information about the current version of RoundedTB. The "Debug" section lets you open the config and log files.
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ## Known issues
34 | - Auto-hiding is still incredibly experimental and may lead to a lot of flickering, especially with TranslucentTB compatibility or dynamic/split mode enabled. ([#36](https://github.com/torchgm/RoundedTB/issues/36))
35 | - Rounded corners are not antialiased due to a Windows limitation. ([#4](https://github.com/torchgm/RoundedTB/issues/4))
36 | - Dynamic mode won't hide the left side of the taskbar if the taskbar alignment has never been changed. This can be worked around by changing the alignment to Left and back to Center. ([#98](https://github.com/torchgm/RoundedTB/issues/98))
37 | - Dynamic mode/split mode only work correctly when the taskbar is horizontal at the top/bottom of the screen.
38 | - Split mode on Windows 10 only supports the main taskbar, secondary taskbars will not be split.
39 | - When using dynamic mode, the taskbar may occasionally become too large, too small or not update. This can usually be fixed by moving a window to or from that monitor or briefly changing the taskbar alignment. These issues will be reduced in upcoming updates, don't worry! I just need to refactor a lot of code first.
40 | - Compatibility with taskbar mods outside of TranslucentTB version 2021.5 is not currently guaranteed.
41 |
42 | ## Other info
43 | RoundedTB is just a hobby of mine, and I'm certainly not an expert in this field, so I'm really sorry if you encounter a bug! If anything breaks catastrophically, press Ctrl+Shift+Esc to open Task Manager, end RoundedTB and then restart Explorer. At worst, just reboot your PC. RoundedTB makes no permanent changes (though it will run on startup if you enable it from the tray icon), so restarting should clear any issues.
44 |
45 | Feel free to let me know about any bugs by filing an issue so I can look into it. Alternatively if you want to discuss RoundedTB, get some insider sneak-peeks, need some assistance or just want to see what I'm up to, then feel free to join the [Discord server](https://discord.gg/wYQJd8VGSB).
46 |
47 | ### Configuring split mode on Windows 10
48 | Split mode has a couple of limitations and requires a small amount of setup to get working properly.
49 | #### Limitations
50 | - Split mode doesn't resize itself automatically. This feature will be coming to RoundedTB for Windows 10 in the future.
51 | - Toolbars are not compatible with split mode currently, and will need to be disabled apart from one. This is because toolbars are used to mark the "empty" space on the taskbar.
52 | - Split mode only works when the taskbar is horizontal at the top or bottom of the screen, and on the primary monitor.
53 | #### Setup
54 | 1. Right-click the taskbar and disable "Lock the taskbar".
55 | 2. Right-click it again and turn off any existing toolbars.
56 | 3. Right-click a third time, select Toolbars > Desktop.
57 | 4. Use the small || handle to resize the taskbar as you please.
58 |
59 | Watch the following video for a guide on setting up split mode:
60 |
61 | https://user-images.githubusercontent.com/31840547/134795022-1312d011-40f2-4641-8c8d-3d6c0e752747.mp4
62 |
63 |
--------------------------------------------------------------------------------
/RoundedTB.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31423.177
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoundedTB", "RoundedTB\RoundedTB.csproj", "{52C15E53-9E25-4847-8522-8BA77B08106F}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6C4D12A6-8741-4A9E-A343-381E9ED3A952}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|ARM = Debug|ARM
14 | Debug|ARM64 = Debug|ARM64
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|Any CPU = Release|Any CPU
18 | Release|ARM = Release|ARM
19 | Release|ARM64 = Release|ARM64
20 | Release|x64 = Release|x64
21 | Release|x86 = Release|x86
22 | Remote Debug|Any CPU = Remote Debug|Any CPU
23 | Remote Debug|ARM = Remote Debug|ARM
24 | Remote Debug|ARM64 = Remote Debug|ARM64
25 | Remote Debug|x64 = Remote Debug|x64
26 | Remote Debug|x86 = Remote Debug|x86
27 | EndGlobalSection
28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
29 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|ARM.ActiveCfg = Debug|Any CPU
32 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|ARM.Build.0 = Debug|Any CPU
33 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
34 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|ARM64.Build.0 = Debug|Any CPU
35 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|x64.ActiveCfg = Debug|Any CPU
36 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|x64.Build.0 = Debug|Any CPU
37 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|x86.ActiveCfg = Debug|Any CPU
38 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Debug|x86.Build.0 = Debug|Any CPU
39 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|ARM.ActiveCfg = Release|Any CPU
42 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|ARM.Build.0 = Release|Any CPU
43 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|ARM64.ActiveCfg = Release|Any CPU
44 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|ARM64.Build.0 = Release|Any CPU
45 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|x64.ActiveCfg = Release|Any CPU
46 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|x64.Build.0 = Release|Any CPU
47 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|x86.ActiveCfg = Release|Any CPU
48 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Release|x86.Build.0 = Release|Any CPU
49 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|Any CPU.ActiveCfg = Remote Debug|Any CPU
50 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|Any CPU.Build.0 = Remote Debug|Any CPU
51 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|ARM.ActiveCfg = Remote Debug|Any CPU
52 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|ARM.Build.0 = Remote Debug|Any CPU
53 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|ARM64.ActiveCfg = Remote Debug|Any CPU
54 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|ARM64.Build.0 = Remote Debug|Any CPU
55 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|x64.ActiveCfg = Remote Debug|Any CPU
56 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|x64.Build.0 = Remote Debug|Any CPU
57 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|x86.ActiveCfg = Remote Debug|Any CPU
58 | {52C15E53-9E25-4847-8522-8BA77B08106F}.Remote Debug|x86.Build.0 = Remote Debug|Any CPU
59 | EndGlobalSection
60 | GlobalSection(SolutionProperties) = preSolution
61 | HideSolutionNode = FALSE
62 | EndGlobalSection
63 | GlobalSection(ExtensibilityGlobals) = postSolution
64 | SolutionGuid = {DA142517-2AAB-4F18-A60B-23F80035D8E0}
65 | EndGlobalSection
66 | EndGlobal
67 |
--------------------------------------------------------------------------------
/RoundedTB/.editorconfig:
--------------------------------------------------------------------------------
1 | # Rules in this file were initially inferred by Visual Studio IntelliCode from the C:\Users\Torch\source\repos\RoundedTB\RoundedTB\ codebase based on best match to current usage at 30/01/2022 A.D.
2 | # You can modify the rules from these initially generated values to suit your own policies
3 | # You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
4 | [*.cs]
5 |
6 |
7 | #Core editorconfig formatting - indentation
8 |
9 | #use soft tabs (spaces) for indentation
10 | indent_style = space
11 |
12 | #Formatting - indentation options
13 |
14 | #indent switch case contents.
15 | csharp_indent_case_contents = true
16 | #indent switch labels
17 | csharp_indent_switch_labels = true
18 |
19 | #Formatting - new line options
20 |
21 | #place catch statements on a new line
22 | csharp_new_line_before_catch = true
23 | #place else statements on a new line
24 | csharp_new_line_before_else = true
25 | #require finally statements to be on a new line after the closing brace
26 | csharp_new_line_before_finally = true
27 | #require members of object intializers to be on separate lines
28 | csharp_new_line_before_members_in_object_initializers = true
29 | #require braces to be on a new line for object_collection_array_initializers, control_blocks, properties, lambdas, types, accessors, and methods (also known as "Allman" style)
30 | csharp_new_line_before_open_brace = object_collection_array_initializers, control_blocks, properties, lambdas, types, accessors, methods
31 |
32 | #Formatting - organize using options
33 |
34 | #sort System.* using directives alphabetically, and place them before other usings
35 | dotnet_sort_system_directives_first = true
36 |
37 | #Formatting - spacing options
38 |
39 | #require NO space between a cast and the value
40 | csharp_space_after_cast = false
41 | #require a space before the colon for bases or interfaces in a type declaration
42 | csharp_space_after_colon_in_inheritance_clause = true
43 | #require a space after a keyword in a control flow statement such as a for loop
44 | csharp_space_after_keywords_in_control_flow_statements = true
45 | #require a space before the colon for bases or interfaces in a type declaration
46 | csharp_space_before_colon_in_inheritance_clause = true
47 | #remove space within empty argument list parentheses
48 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
49 | #remove space between method call name and opening parenthesis
50 | csharp_space_between_method_call_name_and_opening_parenthesis = false
51 | #do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
52 | csharp_space_between_method_call_parameter_list_parentheses = false
53 | #remove space within empty parameter list parentheses for a method declaration
54 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
55 | #place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
56 | csharp_space_between_method_declaration_parameter_list_parentheses = false
57 |
58 | #Formatting - wrapping options
59 |
60 | #leave code block on single line
61 | csharp_preserve_single_line_blocks = true
62 |
63 | #Style - Code block preferences
64 |
65 | #prefer curly braces even for one line of code
66 | csharp_prefer_braces = true:suggestion
67 |
68 | #Style - expression bodied member options
69 |
70 | #prefer block bodies for accessors
71 | csharp_style_expression_bodied_accessors = false:suggestion
72 | #prefer block bodies for constructors
73 | csharp_style_expression_bodied_constructors = false:suggestion
74 | #prefer block bodies for methods
75 | csharp_style_expression_bodied_methods = false:suggestion
76 | #prefer block bodies for properties
77 | csharp_style_expression_bodied_properties = false:suggestion
78 |
79 | #Style - expression level options
80 |
81 | #prefer out variables to be declared before the method call
82 | csharp_style_inlined_variable_declaration = false:suggestion
83 |
84 | #Style - Expression-level preferences
85 |
86 | #prefer objects to not be initialized using object initializers
87 | dotnet_style_object_initializer = false:suggestion
88 |
89 | #Style - implicit and explicit types
90 |
91 | #prefer explicit type over var in all cases, unless overridden by another code style rule
92 | csharp_style_var_elsewhere = false:suggestion
93 | #prefer explicit type over var to declare variables with built-in system types such as int
94 | csharp_style_var_for_built_in_types = false:suggestion
95 | #prefer explicit type over var when the type is already mentioned on the right-hand side of a declaration
96 | csharp_style_var_when_type_is_apparent = false:suggestion
97 |
98 | #Style - language keyword and framework type options
99 |
100 | #prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
101 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
102 |
103 | #Style - modifier options
104 |
105 | #prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
106 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
107 |
108 | #Style - Modifier preferences
109 |
110 | #when this rule is set to a list of modifiers, prefer the specified ordering.
111 | csharp_preferred_modifier_order = public,private,static,extern,sealed:suggestion
112 |
113 | #Style - Pattern matching
114 |
115 | #prefer pattern matching instead of is expression with type casts
116 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
117 |
118 | #Style - qualification options
119 |
120 | #prefer fields not to be prefaced with this. or Me. in Visual Basic
121 | dotnet_style_qualification_for_field = false:suggestion
122 | #prefer methods not to be prefaced with this. or Me. in Visual Basic
123 | dotnet_style_qualification_for_method = false:suggestion
124 | #prefer properties not to be prefaced with this. or Me. in Visual Basic
125 | dotnet_style_qualification_for_property = false:suggestion
126 |
127 | [*.{cs,vb}]
128 | dotnet_diagnostic.CA1416.severity=silent
--------------------------------------------------------------------------------
/RoundedTB/AboutWindow.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Thanks for downloading RoundedTB. Expand the following categories for more information.
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | • Nobody knows. Some say secrets lie amongst these builds. And bugs. Honestly, I'm pretty sure they're 90% bug. 95%. 98%. Actually the fact you're even seeing this text is probably a bug. idk tbh, i give up
35 |
36 | REMINDER: Autohide is currently rather buggy and must be entirely disabled in Windows.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | • Margin - makes the taskbar slimmer on all sides by this many logical pixels.
45 |
46 | • Corner radius - controls the radius of the taskbar's rounded corners.
47 |
48 | • Advanced - toggles a menu of advanced and experimental features.
49 |
50 | • Apply - applies and saves any unset changes.
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | • [...] Margins - individually sets the margin for each side of the taskbar.
59 |
60 | • Dynamic mode (Windows 11) - Dynamically adjusts the size of the taskbar depending on how many apps are open.
61 |
62 | • Split mode (Windows 10) - allows you to resize the taskbar. Like dynamic mode, but manually adjustable; some setup is required, enable for more info.
63 |
64 | • Show system tray - Displays the system tray in dynamic/split mode. This option can be toggled at any time by pressing Win+F2.
65 |
66 | • Show system tray on hover - Displays the system tray in dynamic/split mode when the mouse hovers over it. This overrides the above option.
67 |
68 | • TranslucentTB compatibility - enables compatibility with TranslucentTB. For more info, enable this option.
69 |
70 | • Fill taskbar when maximised - Fills the taskbar when a window is maximised on that taskbar's monitor.
71 |
72 | • Fill taskbar on alt+tab (Windows 11) - Fills taskbars when alt+tab or the Task Switcher is invoked.
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | • Using RoundedTB with Windows' autohide feature can result in heavy flickering, bugs, an inability to access the taskbar and isn't supported. An upcoming version of RoundedTB will introduce a custom autohide feature that will work correctly.
81 |
82 | • Dynamic mode and split mode only work correctly when the taskbar is at the top or bottom of the monitor.
83 |
84 | • Split mode on Windows 10 is currently only supported on the primary monitor.
85 |
86 | • Taskbar mods other than TranslucentTB are not yet officially supported. Let me know if you run into compatibility issues with other taskbar mods/tweaks.
87 |
88 | • When using dynamic mode, the taskbar may occasionally become too large, too small or not update. This can usually be fixed by moving a window to or from that monitor or briefly changing the taskbar alignment. These issues will be reduced in upcoming updates.
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | • More in-depth instructions, tips and tricks are available in the
97 |
98 | README
99 | .
100 |
101 | • If you're having any issues, or just want to talk about RoundedTB, feel free to join
102 |
103 | the official Discord server
104 | .
105 |
106 | • If you want to browse the source code, file an issue or suggest a feature, check out
107 |
108 | the RoundedTB GitHub repository
109 | .
110 |
111 |
112 | RoundedTB is licensed under the
113 |
114 | GNU General Public License v3.0
115 | . By using the software, you agree to accepting the terms of this license.
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/RoundedTB/AboutWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 | using System.Windows.Navigation;
15 | using System.Diagnostics;
16 |
17 | namespace RoundedTB
18 | {
19 | ///
20 | /// Interaction logic for AboutWindow.xaml
21 | ///
22 | public partial class AboutWindow : Window
23 | {
24 | public AboutWindow()
25 | {
26 | InitializeComponent();
27 | WPFUI.Background.Manager.Apply(WPFUI.Background.BackgroundType.Mica, this);
28 | }
29 |
30 | private void okButton_Click(object sender, RoutedEventArgs e)
31 | {
32 | Close();
33 | }
34 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
35 | {
36 | Process.Start(e.Uri.ToString());
37 | }
38 |
39 | private void configButton_Click(object sender, RoutedEventArgs e)
40 | {
41 | Process.Start(((MainWindow)Application.Current.MainWindow).configPath);
42 | }
43 |
44 | private void logButton_Click(object sender, RoutedEventArgs e)
45 | {
46 | Process.Start(((MainWindow)Application.Current.MainWindow).logPath);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/RoundedTB/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RoundedTB/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/RoundedTB/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace RoundedTB
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | protected override void OnStartup(StartupEventArgs e)
17 | {
18 | WPFUI.Theme.Watcher.Start();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/RoundedTB/AppBars.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace RoundedTB
5 | {
6 | class AppBars
7 | {
8 | [DllImport("shell32.dll")]
9 | public static extern IntPtr SHAppBarMessage(UInt32 dwMessage, ref APPBARDATA pData);
10 |
11 | public enum AppBarMessages
12 | {
13 | New = 0x00,
14 | Remove = 0x01,
15 | QueryPos = 0x02,
16 | SetPos = 0x03,
17 | GetState = 0x04,
18 | GetTaskBarPos = 0x05,
19 | Activate = 0x06,
20 | GetAutoHideBar = 0x07,
21 | SetAutoHideBar = 0x08,
22 | WindowPosChanged = 0x09,
23 | SetState = 0x0a
24 | }
25 |
26 | [StructLayout(LayoutKind.Sequential)]
27 | public struct APPBARDATA
28 | {
29 | public UInt32 cbSize;
30 | public IntPtr hWnd;
31 | public UInt32 uCallbackMessage;
32 | public UInt32 uEdge;
33 | public LocalPInvoke.RECT rc;
34 | public Int32 lParam;
35 | }
36 |
37 | public enum AppBarStates
38 | {
39 | AutoHide = 0x01,
40 | AlwaysOnTop = 0x02
41 | }
42 |
43 | ///
44 | /// Set the Taskbar State option
45 | ///
46 | /// AppBarState to activate
47 | public static void SetAppbarState(IntPtr hwnd, AppBarStates option)
48 | {
49 | APPBARDATA msgData = new APPBARDATA();
50 | msgData.cbSize = (UInt32)Marshal.SizeOf(msgData);
51 | msgData.hWnd = hwnd;
52 | msgData.lParam = (Int32)(option);
53 | SHAppBarMessage((UInt32)AppBarMessages.SetState, ref msgData);
54 | }
55 |
56 | ///
57 | /// Gets the current Taskbar state
58 | ///
59 | /// current Taskbar state
60 | public static AppBarStates GetAppbarState(IntPtr hwnd)
61 | {
62 | APPBARDATA msgData = new APPBARDATA();
63 | msgData.cbSize = (UInt32)Marshal.SizeOf(msgData);
64 | msgData.hWnd = hwnd;
65 | return (AppBarStates)SHAppBarMessage((UInt32)AppBarMessages.GetState, ref msgData);
66 | }
67 |
68 | ///
69 | /// Unregisters the taskbar as an appbar
70 | ///
71 | public static void MakeAppbarSad(IntPtr hwnd)
72 | {
73 | APPBARDATA msgData = new APPBARDATA();
74 | msgData.cbSize = (UInt32)Marshal.SizeOf(msgData);
75 | msgData.hWnd = hwnd;
76 | SHAppBarMessage((UInt32)AppBarMessages.Remove, ref msgData);
77 | }
78 |
79 | ///
80 | /// Unregisters the taskbar as an appbar
81 | ///
82 | public static void SetAppbarRect(IntPtr hwnd, LocalPInvoke.RECT rc)
83 | {
84 | APPBARDATA msgData = new APPBARDATA();
85 | msgData.cbSize = (UInt32)Marshal.SizeOf(msgData);
86 | msgData.hWnd = hwnd;
87 | msgData.rc = rc;
88 | msgData.uEdge = 0x3;
89 | SHAppBarMessage((UInt32)AppBarMessages.SetPos, ref msgData);
90 | }
91 | }
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/RoundedTB/Background.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Diagnostics;
5 | using System.Text;
6 | using System.Windows;
7 | using System.Windows.Threading;
8 |
9 | namespace RoundedTB
10 | {
11 | public class Background
12 | {
13 | // Just have a reference point for the Dispatcher
14 | public MainWindow mw;
15 | bool redrawOverride = false;
16 | int infrequentCount = 0;
17 |
18 | public Background()
19 | {
20 | mw = (MainWindow)Application.Current.MainWindow;
21 | }
22 |
23 |
24 | // Main method for the BackgroundWorker - runs indefinitely
25 | public void DoWork(object sender, DoWorkEventArgs e)
26 | {
27 | mw.interaction.AddLog("in bw");
28 | BackgroundWorker worker = sender as BackgroundWorker;
29 | while (true)
30 | {
31 | try
32 | {
33 | if (worker.CancellationPending == true)
34 | {
35 | mw.interaction.AddLog("cancelling");
36 | e.Cancel = true;
37 | break;
38 | }
39 |
40 | // Primary loop for the running process
41 | else
42 | {
43 | // Section for running less important things without requiring an additional thread
44 | infrequentCount++;
45 | if (infrequentCount == 10)
46 | {
47 | // Check to see if settings need to be shown
48 | List windowList = Interaction.GetTopLevelWindows();
49 | foreach (IntPtr hwnd in windowList)
50 | {
51 | StringBuilder windowClass = new StringBuilder(1024);
52 | StringBuilder windowTitle = new StringBuilder(1024);
53 | try
54 | {
55 | LocalPInvoke.GetClassName(hwnd, windowClass, 1024);
56 | LocalPInvoke.GetWindowText(hwnd, windowTitle, 1024);
57 |
58 | if (windowClass.ToString().Contains("HwndWrapper[RoundedTB.exe") && windowTitle.ToString() == "RoundedTB_SettingsRequest")
59 | {
60 | mw.Dispatcher.Invoke(() =>
61 | {
62 | if (mw.Visibility != Visibility.Visible)
63 | {
64 | mw.ShowMenuItem_Click(null, null);
65 | }
66 | });
67 | LocalPInvoke.SetWindowText(hwnd, "RoundedTB");
68 | }
69 | }
70 | catch (Exception) { }
71 | }
72 |
73 | // Update tray icon
74 | mw.Dispatcher.Invoke(() =>
75 | {
76 | try
77 | {
78 | mw.TrayIconCheck();
79 |
80 | }
81 | catch (Exception)
82 | {
83 |
84 | }
85 | });
86 |
87 | infrequentCount = 0;
88 | }
89 |
90 | // Check if the taskbar is centred, and if it is, directly update the settings; using an interim bool to avoid delaying because I'm lazy
91 | bool isCentred = Taskbar.CheckIfCentred();
92 | mw.activeSettings.IsCentred = isCentred;
93 |
94 | // Work with static values to avoid some null reference exceptions
95 | List taskbars = mw.taskbarDetails;
96 | Types.Settings settings = mw.activeSettings;
97 |
98 | // If the number of taskbars has changed, regenerate taskbar information
99 | if (Taskbar.TaskbarCountOrHandleChanged(taskbars.Count, taskbars[0].TaskbarHwnd))
100 | {
101 | // Forcefully reset taskbars if the taskbar count or main taskbar handle has changed
102 | taskbars = Taskbar.GenerateTaskbarInfo();
103 | Debug.WriteLine("Regenerating taskbar info");
104 | }
105 |
106 | for (int current = 0; current < taskbars.Count; current++)
107 | {
108 | if (taskbars[current].TaskbarHwnd == IntPtr.Zero || taskbars[current].AppListHwnd == IntPtr.Zero)
109 | {
110 | taskbars = Taskbar.GenerateTaskbarInfo();
111 | Debug.WriteLine("Regenerating taskbar info due to a missing handle");
112 | break;
113 | }
114 | // Get the latest quick details of this taskbar
115 | Types.Taskbar newTaskbar = Taskbar.GetQuickTaskbarRects(taskbars[current].TaskbarHwnd, taskbars[current].TrayHwnd, taskbars[current].AppListHwnd);
116 |
117 |
118 | // If the taskbar's monitor has a maximised window, reset it so it's "filled"
119 | if (Taskbar.TaskbarShouldBeFilled(taskbars[current].TaskbarHwnd, settings))
120 | {
121 | if (taskbars[current].Ignored == false)
122 | {
123 | Taskbar.ResetTaskbar(taskbars[current], settings);
124 | taskbars[current].Ignored = true;
125 | }
126 | continue;
127 | }
128 |
129 | // Showhide tray on hover
130 | if (settings.ShowSegmentsOnHover)
131 | {
132 | LocalPInvoke.RECT currentTrayRect = taskbars[current].TrayRect;
133 | LocalPInvoke.RECT currentWidgetsRect = taskbars[current].TaskbarRect;
134 | currentWidgetsRect.Right = Convert.ToInt32(currentWidgetsRect.Right - (currentWidgetsRect.Right - currentWidgetsRect.Left) + (168 * taskbars[current].ScaleFactor));
135 |
136 | if (currentTrayRect.Left != 0)
137 | {
138 | LocalPInvoke.GetCursorPos(out LocalPInvoke.POINT msPt);
139 | bool isHoveringOverTray = LocalPInvoke.PtInRect(ref currentTrayRect, msPt);
140 | bool isHoveringOverWidgets = LocalPInvoke.PtInRect(ref currentWidgetsRect, msPt);
141 | if (isHoveringOverTray && !settings.ShowTray)
142 | {
143 | settings.ShowTray = true;
144 | taskbars[current].Ignored = true;
145 | }
146 | else if (!isHoveringOverTray)
147 | {
148 | taskbars[current].Ignored = true;
149 | settings.ShowTray = false;
150 | }
151 |
152 | if (isHoveringOverWidgets && !settings.ShowWidgets)
153 | {
154 | settings.ShowWidgets = true;
155 | taskbars[current].Ignored = true;
156 | }
157 | else if (!isHoveringOverWidgets)
158 | {
159 | taskbars[current].Ignored = true;
160 | settings.ShowWidgets = false;
161 | }
162 |
163 | }
164 | }
165 |
166 | if (settings.AutoHide > 0)
167 | {
168 | LocalPInvoke.RECT currentTaskbarRect = taskbars[current].TaskbarRect;
169 | LocalPInvoke.GetCursorPos(out LocalPInvoke.POINT msPt);
170 | bool isHoveringOverTaskbar;
171 | if (taskbars[current].TaskbarHidden)
172 | {
173 | currentTaskbarRect.Top = currentTaskbarRect.Bottom - 2;
174 | isHoveringOverTaskbar = LocalPInvoke.PtInRect(ref currentTaskbarRect, msPt);
175 |
176 | }
177 | else
178 | {
179 | isHoveringOverTaskbar = LocalPInvoke.PtInRect(ref currentTaskbarRect, msPt);
180 | }
181 | if (isHoveringOverTaskbar)
182 | {
183 | Debug.WriteLine("___");
184 | }
185 | int animSpeed = 15;
186 | byte taskbarOpacity = 0;
187 | LocalPInvoke.GetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, out _, out taskbarOpacity, out _);
188 | //Debug.WriteLine($"Taskbar opacity: {taskbarOpacity}");
189 | if (isHoveringOverTaskbar && taskbarOpacity == 1)
190 | {
191 | int style = LocalPInvoke.GetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32();
192 | if ((style & LocalPInvoke.WS_EX_TRANSPARENT) == LocalPInvoke.WS_EX_TRANSPARENT)
193 | {
194 | LocalPInvoke.SetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE, LocalPInvoke.GetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32() ^ LocalPInvoke.WS_EX_TRANSPARENT);
195 | }
196 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 63, LocalPInvoke.LWA_ALPHA);
197 | System.Threading.Thread.Sleep(animSpeed);
198 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 127, LocalPInvoke.LWA_ALPHA);
199 | System.Threading.Thread.Sleep(animSpeed);
200 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 191, LocalPInvoke.LWA_ALPHA);
201 | System.Threading.Thread.Sleep(animSpeed);
202 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 255, LocalPInvoke.LWA_ALPHA);
203 | taskbars[current].Ignored = true;
204 | taskbars[current].TaskbarHidden = false;
205 | Debug.WriteLine("MouseOver TB");
206 | }
207 | else if (!isHoveringOverTaskbar && taskbarOpacity == 255)
208 | {
209 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 191, LocalPInvoke.LWA_ALPHA);
210 | System.Threading.Thread.Sleep(animSpeed);
211 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 127, LocalPInvoke.LWA_ALPHA);
212 | System.Threading.Thread.Sleep(animSpeed);
213 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 63, LocalPInvoke.LWA_ALPHA);
214 | System.Threading.Thread.Sleep(animSpeed);
215 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 1, LocalPInvoke.LWA_ALPHA);
216 | int style = LocalPInvoke.GetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32();
217 | if ((style & LocalPInvoke.WS_EX_TRANSPARENT) != LocalPInvoke.WS_EX_TRANSPARENT)
218 | {
219 | LocalPInvoke.SetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE, LocalPInvoke.GetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32() ^ LocalPInvoke.WS_EX_TRANSPARENT);
220 | }
221 | taskbars[current].Ignored = true;
222 | taskbars[current].TaskbarHidden = true;
223 | Debug.WriteLine("MouseOff TB");
224 | }
225 | }
226 | else
227 | {
228 | int animSpeed = 15;
229 | byte taskbarOpacity = 0;
230 | LocalPInvoke.GetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, out _, out taskbarOpacity, out _);
231 | if (taskbarOpacity < 255)
232 | {
233 | int style = LocalPInvoke.GetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32();
234 | if ((style & LocalPInvoke.WS_EX_TRANSPARENT) == LocalPInvoke.WS_EX_TRANSPARENT)
235 | {
236 | LocalPInvoke.SetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE, LocalPInvoke.GetWindowLong(taskbars[current].TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32() ^ LocalPInvoke.WS_EX_TRANSPARENT);
237 | }
238 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 63, LocalPInvoke.LWA_ALPHA);
239 | System.Threading.Thread.Sleep(animSpeed);
240 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 127, LocalPInvoke.LWA_ALPHA);
241 | System.Threading.Thread.Sleep(animSpeed);
242 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 191, LocalPInvoke.LWA_ALPHA);
243 | System.Threading.Thread.Sleep(animSpeed);
244 | LocalPInvoke.SetLayeredWindowAttributes(taskbars[current].TaskbarHwnd, 0, 255, LocalPInvoke.LWA_ALPHA);
245 | taskbars[current].Ignored = true;
246 | taskbars[current].TaskbarHidden = false;
247 | }
248 | }
249 |
250 |
251 | // If the taskbar's overall rect has changed, update it. If it's simple, just update. If it's dynamic, check it's a valid change, then update it.
252 | if (Taskbar.TaskbarRefreshRequired(taskbars[current], newTaskbar, settings.IsDynamic) || taskbars[current].Ignored || redrawOverride)
253 | {
254 | Debug.WriteLine($"Refresh required on taskbar {current}");
255 | taskbars[current].Ignored = false;
256 | int isFullTest = newTaskbar.TrayRect.Left - newTaskbar.AppListRect.Right;
257 | mw.interaction.AddLog($"Taskbar: {current} - AppList ends: {newTaskbar.AppListRect.Right} - Tray starts: {newTaskbar.TrayRect.Left} - Total gap: {isFullTest}");
258 | if (!settings.IsDynamic || (isFullTest <= taskbars[current].ScaleFactor * 25 && isFullTest > 0 && newTaskbar.TrayRect.Left != 0))
259 | {
260 | // Add the rect changes to the temporary list of taskbars
261 | taskbars[current].TaskbarRect = newTaskbar.TaskbarRect;
262 | taskbars[current].AppListRect = newTaskbar.AppListRect;
263 | taskbars[current].TrayRect = newTaskbar.TrayRect;
264 | Taskbar.UpdateSimpleTaskbar(taskbars[current], settings);
265 | mw.interaction.AddLog($"Updated taskbar {current} simply");
266 | }
267 | else
268 | {
269 | if (Taskbar.CheckDynamicUpdateIsValid(taskbars[current], newTaskbar))
270 | {
271 | // Add the rect changes to the temporary list of taskbars
272 | taskbars[current].TaskbarRect = newTaskbar.TaskbarRect;
273 | taskbars[current].AppListRect = newTaskbar.AppListRect;
274 | taskbars[current].TrayRect = newTaskbar.TrayRect;
275 | Taskbar.UpdateDynamicTaskbar(taskbars[current], settings);
276 | mw.interaction.AddLog($"Updated taskbar {current} dynamically");
277 | }
278 | }
279 | }
280 | }
281 | mw.taskbarDetails = taskbars;
282 |
283 |
284 | System.Threading.Thread.Sleep(100);
285 | }
286 | }
287 | catch (TypeInitializationException ex)
288 | {
289 | mw.interaction.AddLog(ex.Message);
290 | mw.interaction.AddLog(ex.InnerException.Message);
291 | throw ex;
292 | }
293 | }
294 | }
295 | }
296 | }
297 |
--------------------------------------------------------------------------------
/RoundedTB/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/RoundedTB/IAppVisibility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RoundedTB
9 | {
10 | public enum MONITOR_APP_VISIBILITY
11 | {
12 | MAV_UNKNOWN = 0,
13 | MAV_NO_APP_VISIBLE = 1,
14 | MAV_APP_VISIBLE = 2
15 | }
16 |
17 | [ComImport, Guid("6584CE6B-7D82-49C2-89C9-C6BC02BA8C38"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
18 | public interface IAppVisibilityEvents
19 | {
20 | void AppVisibilityOnMonitorChanged(IntPtr hMonitor, MONITOR_APP_VISIBILITY previousMode, MONITOR_APP_VISIBILITY currentMode);
21 | void LauncherVisibilityChange([MarshalAs(UnmanagedType.Bool)] bool currentVisibleState);
22 | }
23 |
24 | [ComImport, Guid("2246EA2D-CAEA-4444-A3C4-6DE827E44313"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
25 | public interface IAppVisibility
26 | {
27 | MONITOR_APP_VISIBILITY GetAppVisibilityOnMonitor(IntPtr hMonitor);
28 |
29 | [return: MarshalAs(UnmanagedType.Bool)]
30 | bool IsLauncherVisible();
31 |
32 | uint Advise(IAppVisibilityEvents pCallback);
33 | void Unadvise(uint dwCookie);
34 | }
35 |
36 | [ComImport, Guid("7E5FE3D9-985F-4908-91F9-EE19F9FD1514"), ClassInterface(ClassInterfaceType.None)]
37 | public class AppVisibility { }
38 | }
39 |
--------------------------------------------------------------------------------
/RoundedTB/Infobox.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/RoundedTB/Infobox.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 |
15 | namespace RoundedTB
16 | {
17 | ///
18 | /// Interaction logic for Infobox.xaml
19 | ///
20 | public partial class Infobox : Window
21 | {
22 | public Infobox()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | private void okButton_Click(object sender, RoutedEventArgs e)
28 | {
29 | Close();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/RoundedTB/Interaction.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Windows;
7 | using System.Threading;
8 | using System.Drawing;
9 | using System.Runtime.InteropServices;
10 |
11 | namespace RoundedTB
12 | {
13 | public class Interaction
14 | {
15 | public MainWindow mw;
16 | string m = "";
17 |
18 | public Interaction()
19 | {
20 | try
21 | {
22 | mw = (MainWindow)Application.Current.MainWindow;
23 | }
24 | catch (Exception)
25 | {
26 | // No idea why this was necessary but it was so it's here now. Yay. TODO - work out why this is suddenly broken and unbreak it
27 | }
28 | }
29 |
30 | public Types.Settings ReadJSON()
31 | {
32 | string jsonSettings = File.ReadAllText(mw.configPath);
33 | Types.Settings settings = JsonConvert.DeserializeObject(jsonSettings);
34 | return settings;
35 | }
36 |
37 | public bool IsWindows11()
38 | {
39 | Debug.WriteLine(Environment.OSVersion.Version.Build);
40 | if (Environment.OSVersion.Version.Build >= 21996)
41 | {
42 | return true;
43 | }
44 | return false;
45 | }
46 |
47 | public void WriteJSON()
48 | {
49 | File.Create(mw.configPath).Close();
50 | File.WriteAllText(mw.configPath, JsonConvert.SerializeObject(mw.activeSettings, Formatting.Indented));
51 | }
52 |
53 | public void FileSystem()
54 | {
55 | File.Create(mw.logPath).Close();
56 | if (!File.Exists(mw.configPath))
57 | {
58 | if (mw.isWindows11)
59 | {
60 | mw.activeSettings = new Types.Settings()
61 | {
62 | SimpleTaskbarLayout = new Types.SegmentSettings { CornerRadius = 7, MarginLeft = 3, MarginTop = 3, MarginRight = 3, MarginBottom = 3 },
63 | DynamicAppListLayout = new Types.SegmentSettings { CornerRadius = 7, MarginLeft = 3, MarginTop = 3, MarginRight = 3, MarginBottom = 3 },
64 | DynamicTrayLayout = new Types.SegmentSettings { CornerRadius = 7, MarginLeft = 3, MarginTop = 3, MarginRight = 3, MarginBottom = 3 },
65 | DynamicWidgetsLayout = new Types.SegmentSettings { CornerRadius = 7, MarginLeft = 3, MarginTop = 3, MarginRight = 3, MarginBottom = 3 },
66 | IsDynamic = false,
67 | IsCentred = false,
68 | IsWindows11 = true,
69 | ShowTray = false,
70 | CompositionCompat = false,
71 | IsNotFirstLaunch = false,
72 | FillOnMaximise = true,
73 | FillOnTaskSwitch = true,
74 | ShowSegmentsOnHover = false,
75 | AutoHide = 0
76 | };
77 | }
78 | else
79 | {
80 | mw.activeSettings = new Types.Settings()
81 | {
82 | SimpleTaskbarLayout = new Types.SegmentSettings { CornerRadius = 16, MarginLeft = 2, MarginTop = 2, MarginRight = 2, MarginBottom = 2 },
83 | DynamicAppListLayout = new Types.SegmentSettings { CornerRadius = 16, MarginLeft = 2, MarginTop = 2, MarginRight = 2, MarginBottom = 2 },
84 | DynamicTrayLayout = new Types.SegmentSettings { CornerRadius = 16, MarginLeft = 2, MarginTop = 2, MarginRight = 2, MarginBottom = 2 },
85 | DynamicWidgetsLayout = new Types.SegmentSettings { CornerRadius = 16, MarginLeft = 2, MarginTop = 2, MarginRight = 2, MarginBottom = 2 },
86 | IsDynamic = false,
87 | IsCentred = false,
88 | IsWindows11 = false,
89 | ShowTray = false,
90 | CompositionCompat = false,
91 | IsNotFirstLaunch = false,
92 | FillOnMaximise = true,
93 | FillOnTaskSwitch = false,
94 | ShowSegmentsOnHover = false,
95 | AutoHide = 0
96 | };
97 | }
98 |
99 | WriteJSON(); // butts - Missy Quarry, 2020
100 | }
101 | if (File.ReadAllText(mw.configPath) == "" || File.ReadAllText(mw.configPath) == null)
102 | {
103 | WriteJSON(); // Initialises empty file
104 | }
105 |
106 | }
107 |
108 | public static bool SetWorkspace(LocalPInvoke.RECT rect)
109 | {
110 | bool result = LocalPInvoke.SystemParametersInfo(LocalPInvoke.SPI_SETWORKAREA, 0, ref rect, LocalPInvoke.SPIF_change);
111 | if (!result)
112 | {
113 | // Get error
114 | Debug.WriteLine("Error setting work area: " + Marshal.GetLastWin32Error().ToString());
115 | }
116 |
117 | return result;
118 | }
119 |
120 | public void AddLog(string message)
121 | {
122 | //m = $"[{DateTime.Now}] {message}\n";
123 | //File.AppendAllText(mw.logPath, m);
124 | }
125 |
126 | public static bool IsTranslucentTBRunning()
127 | {
128 | Mutex mutex = null;
129 | try
130 | {
131 | return Mutex.TryOpenExisting("344635E9-9AE4-4E60-B128-D53E25AB70A7", out mutex);
132 | }
133 | finally
134 | {
135 | mutex?.Dispose();
136 | }
137 | }
138 |
139 | // Request that TranslucentTB forefully refesh the taskbar
140 | public static IntPtr UpdateTranslucentTB(IntPtr taskbarHwnd)
141 | {
142 | return LocalPInvoke.SendMessage(LocalPInvoke.FindWindow("TTB_WorkerWindow", "TTB_WorkerWindow"), LocalPInvoke.RegisterWindowMessage("TTB_ForceRefreshTaskbar"), 0, taskbarHwnd);
143 | }
144 |
145 | // Attempt to forcefully refresh the taskbar
146 | public static void UpdateLegacyTB(IntPtr taskbarHwnd)
147 | {
148 | const int WM_DWMCOMPOSITIONCHANGED = 789;
149 | LocalPInvoke.SendMessage(taskbarHwnd, WM_DWMCOMPOSITIONCHANGED, 1, IntPtr.Zero);
150 | }
151 |
152 | ///
153 | /// Calculates whether or not an integer is odd or even.
154 | ///
155 | ///
156 | /// The integer to be checked for oddness.
157 | ///
158 | ///
159 | /// A nullable bool, which represents if the provided integer is odd. If the provided integer is neither even nor odd, then returns null.
160 | ///
161 | public bool? IsOdd(int input)
162 | {
163 | // The following section declares and initialises the required variables for the caculation.
164 | decimal comparison = input / 2; // A decimal, representing approximately half of the user's input.
165 | int check = Convert.ToInt32(comparison) * 2; // An integer-representation of the user's input value.
166 |
167 | // The following section tests for oddness by looking for differences in the prior-initialised values.
168 | if (check == input) // Checks if the "check" value is equal to the input.
169 | {
170 | return false; // Return false to indicate the value is not odd.
171 | }
172 | else if (check != input) // Repeat the above check in the event that quantum tunnelling has resulted in a variable changing.
173 | {
174 | return true; // Return true to indicate the value is odd.
175 | }
176 | return null; // Finally, return null to indicate that the provided number is neither odd nor even - not currently required, added for future-proofing in the event the concept of mathematics changes significantly enough to warrant it.
177 | // (this is a joke to annoy sylly)
178 | }
179 |
180 | public IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
181 | {
182 | const int WM_HOTKEY = 0x0312;
183 |
184 | switch (msg)
185 | {
186 | case WM_HOTKEY:
187 | Debug.WriteLine(msg);
188 | switch (wParam.ToInt32())
189 | {
190 | case 9000:
191 | int vkey = ((int)lParam >> 16) & 0xFFFF;
192 | Debug.WriteLine(vkey);
193 | if (vkey == 0x71)
194 | {
195 | if (mw.showTrayCheckBox.IsChecked == true)
196 | {
197 | mw.showTrayCheckBox.IsChecked = false;
198 | }
199 | else
200 | {
201 | mw.showTrayCheckBox.IsChecked = true;
202 | }
203 | mw.ApplyButton_Click(null, null);
204 | }
205 | handled = true;
206 | break;
207 | }
208 | break;
209 | }
210 | return IntPtr.Zero;
211 | }
212 |
213 | public static bool IsAutoHideEnabled()
214 | {
215 | return Math.Abs(SystemParameters.PrimaryScreenHeight - SystemParameters.WorkArea.Height) > 0;
216 | }
217 |
218 | public bool IsTaskbarVisibleOnMonitor(LocalPInvoke.RECT tbRectP, LocalPInvoke.RECT monitorRectP)
219 | {
220 | Rectangle tbRect = new Rectangle(tbRectP.Left + 3, tbRectP.Top + 3, tbRectP.Right - tbRectP.Left - 3, tbRectP.Bottom - tbRectP.Top - 3);
221 | Rectangle monitorRect = new Rectangle(monitorRectP.Left, monitorRectP.Top, monitorRectP.Right - monitorRectP.Left, monitorRectP.Bottom - monitorRectP.Top);
222 | return tbRect.IntersectsWith(monitorRect);
223 | }
224 |
225 | public delegate bool CallBack(int hwnd, int lParam);
226 |
227 | public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
228 |
229 | public static List GetTopLevelWindows()
230 | {
231 | List AllActiveHandles = new List();
232 | GCHandle listHandle = GCHandle.Alloc(AllActiveHandles);
233 | try
234 | {
235 | EnumWindowsProc tlProc = new EnumWindowsProc(EnumWindow);
236 | LocalPInvoke.EnumWindows(tlProc, GCHandle.ToIntPtr(listHandle));
237 | }
238 | finally
239 | {
240 | if (listHandle.IsAllocated)
241 | {
242 | listHandle.Free();
243 | }
244 | }
245 | return AllActiveHandles;
246 | }
247 |
248 | private static bool EnumWindow(IntPtr handle, IntPtr pointer)
249 | {
250 | GCHandle gch = GCHandle.FromIntPtr(pointer);
251 | if (!(gch.Target is List list))
252 | {
253 | throw new InvalidCastException("GCHandle Target could not be cast as List");
254 | }
255 | list.Add(handle);
256 | return true;
257 | }
258 |
259 | public static bool TaskbarOnMonitorWithMaximisedWindow(IntPtr taskbarHwnd)
260 | {
261 | return true;
262 | }
263 |
264 | public enum TaskbarPosition
265 | {
266 | Unknown = -1,
267 | Left,
268 | Top,
269 | Right,
270 | Bottom,
271 | }
272 |
273 | public sealed class Taskbar
274 | {
275 | public Rectangle Bounds
276 | {
277 | get;
278 | private set;
279 | }
280 | public TaskbarPosition Position
281 | {
282 | get;
283 | private set;
284 | }
285 | public System.Drawing.Point Location
286 | {
287 | get
288 | {
289 | return Bounds.Location;
290 | }
291 | }
292 | public System.Drawing.Size Size
293 | {
294 | get
295 | {
296 | return Bounds.Size;
297 | }
298 | }
299 |
300 | //Always returns false under Windows 7
301 | public bool AlwaysOnTop
302 | {
303 | get;
304 | private set;
305 | }
306 | public bool AutoHide
307 | {
308 | get;
309 | private set;
310 | }
311 |
312 | public Taskbar(IntPtr taskbarHandle)
313 | {
314 |
315 | LocalPInvoke.APPBARDATA data = new LocalPInvoke.APPBARDATA();
316 | data.cbSize = (uint)Marshal.SizeOf(typeof(LocalPInvoke.APPBARDATA));
317 | data.hWnd = taskbarHandle;
318 | IntPtr result = LocalPInvoke.SHAppBarMessage(LocalPInvoke.ABM.GetTaskbarPos, ref data);
319 | Position = (TaskbarPosition)data.uEdge;
320 | Bounds = Rectangle.FromLTRB(data.rc.Left, data.rc.Top, data.rc.Right, data.rc.Bottom);
321 |
322 | data.cbSize = (uint)Marshal.SizeOf(typeof(LocalPInvoke.APPBARDATA));
323 | result = LocalPInvoke.SHAppBarMessage(LocalPInvoke.ABM.GetState, ref data);
324 | int state = result.ToInt32();
325 | AlwaysOnTop = (state & LocalPInvoke.ABS.AlwaysOnTop) == LocalPInvoke.ABS.AlwaysOnTop;
326 | AutoHide = (state & LocalPInvoke.ABS.Autohide) == LocalPInvoke.ABS.Autohide;
327 | }
328 | }
329 | }
330 | }
331 |
--------------------------------------------------------------------------------
/RoundedTB/LocalPInvoke.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 |
6 | namespace RoundedTB
7 | {
8 | public class LocalPInvoke
9 | {
10 | [DllImport("user32.dll", SetLastError = true)]
11 | public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
12 |
13 | [DllImport("user32.dll")]
14 | public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
15 |
16 | [DllImport("user32.dll")]
17 | public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
18 |
19 | [DllImport("user32.dll")]
20 | public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
21 |
22 | [DllImport("user32.dll")]
23 | public static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, RedrawWindowFlags flags);
24 |
25 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
26 | public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
27 |
28 | [DllImport("user32.dll")]
29 | public static extern bool PtInRect(ref RECT lprc, POINT pt);
30 |
31 | [DllImport("user32.dll")]
32 | [return: MarshalAs(UnmanagedType.Bool)]
33 | public static extern bool IsWindow(IntPtr hWnd);
34 |
35 | [DllImport("user32.dll")]
36 | public static extern int GetWindowRgn(IntPtr hWnd, out IntPtr hRgn);
37 |
38 | [DllImport("user32.dll")]
39 | public static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw);
40 |
41 | [DllImport("gdi32.dll")]
42 | public static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int w, int h);
43 |
44 | [DllImport("gdi32.dll")]
45 | public static extern IntPtr CreateRectRgn(int x1, int y1, int x2, int y2);
46 |
47 | [DllImport("user32.dll")]
48 | public static extern IntPtr FindWindowExA(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);
49 |
50 | [DllImport("user32.dll")]
51 | public static extern int GetDpiForWindow(IntPtr hwnd);
52 |
53 | [DllImport("user32.dll")]
54 | public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
55 |
56 | [DllImport("user32.dll")]
57 | public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
58 |
59 | [DllImport("user32.dll")]
60 | public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
61 |
62 | [DllImport("user32.dll")]
63 | [return: MarshalAs(UnmanagedType.Bool)]
64 | public static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
65 |
66 | [DllImport("gdi32.dll")]
67 | public static extern int CombineRgn(IntPtr hrgnDest, IntPtr hrgnSrc1, IntPtr hrgnSrc2, int fnCombineMode);
68 |
69 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
70 | public static extern int RegisterWindowMessage(string lpString);
71 |
72 | [DllImport("shell32.dll", SetLastError = true)]
73 | public static extern IntPtr SHAppBarMessage(ABM dwMessage, [In] ref APPBARDATA pData);
74 |
75 | [DllImport("user32.dll", SetLastError = true)]
76 | public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
77 |
78 | [DllImport("user32.dll", SetLastError = true)]
79 | [return: MarshalAs(UnmanagedType.Bool)]
80 | public static extern bool GetCursorPos(out POINT lpPoint);
81 |
82 | [DllImport("user32.dll")]
83 | public static extern int ShowWindow(int hwnd, int command);
84 |
85 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
86 | [return: MarshalAs(UnmanagedType.Bool)]
87 | public static extern bool SystemParametersInfo(int uiAction, int uiParam, ref RECT pvParam, int fWinIni);
88 |
89 | [DllImport("user32.dll")]
90 | [return: MarshalAs(UnmanagedType.Bool)]
91 | public static extern bool IsWindowVisible(IntPtr hWnd);
92 |
93 | [DllImport("dwmapi.dll")]
94 | public static extern int DwmGetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE dwAttribute, out bool pvAttribute, int cbAttribute);
95 |
96 | [DllImport("user32.dll")]
97 | [return: MarshalAs(UnmanagedType.Bool)]
98 | public static extern bool EnumWindows(Interaction.EnumWindowsProc lpEnumFunc, IntPtr lParam);
99 |
100 | [DllImport("user32.dll", SetLastError = true)]
101 | [return: MarshalAs(UnmanagedType.Bool)]
102 | public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
103 |
104 | [DllImport("user32.dll", SetLastError = true, EntryPoint = "GetClassNameW", CharSet = CharSet.Unicode)]
105 | public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
106 |
107 | [DllImport("user32.dll")]
108 | public static extern IntPtr WindowFromPoint(POINT p);
109 |
110 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
111 | public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
112 |
113 | [DllImport("user32.dll")]
114 | public static extern bool SetForegroundWindow(IntPtr hWnd);
115 |
116 | [DllImport("user32.dll")]
117 | public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
118 |
119 | [DllImport("user32.dll")]
120 | public static extern bool IsIconic(IntPtr hWnd);
121 |
122 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
123 | public static extern bool SetWindowText(IntPtr hwnd, string lpString);
124 |
125 | [DllImport("shell32.dll")]
126 | public static extern IntPtr SHAppBarMessage(uint dwMessage, [In] ref APPBARDATA pData);
127 |
128 | [DllImport("user32.dll")]
129 | public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
130 |
131 | [DllImport("user32.dll")]
132 | public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
133 |
134 | [DllImport("user32.dll")]
135 | public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
136 |
137 | [DllImport("user32.dll", SetLastError = true)]
138 | public static extern bool GetLayeredWindowAttributes(IntPtr hwnd, out uint crKey, out byte bAlpha, out uint dwFlags);
139 |
140 | public const int GWL_EXSTYLE = -20;
141 | public const int WS_EX_LAYERED = 0x80000;
142 | public const int WS_EX_TRANSPARENT = 0x00000020;
143 | public const int LWA_ALPHA = 0x2;
144 | public const int LWA_COLORKEY = 0x1;
145 |
146 | public enum AppBarStates
147 | {
148 | AutoHide = 0x01,
149 | AlwaysOnTop = 0x02
150 | }
151 |
152 | public enum DWMWINDOWATTRIBUTE : uint
153 | {
154 | NCRenderingEnabled = 1,
155 | NCRenderingPolicy,
156 | TransitionsForceDisabled,
157 | AllowNCPaint,
158 | CaptionButtonBounds,
159 | NonClientRtlLayout,
160 | ForceIconicRepresentation,
161 | Flip3DPolicy,
162 | ExtendedFrameBounds,
163 | HasIconicBitmap,
164 | DisallowPeek,
165 | ExcludedFromPeek,
166 | Cloak,
167 | Cloaked,
168 | FreezeRepresentation
169 | }
170 |
171 | public enum ShowState : int
172 | {
173 | SW_HIDE = 0,
174 | SW_SHOWNORMAL = 1,
175 | SW_NORMAL = 1,
176 | SW_SHOWMINIMIZED = 2,
177 | SW_SHOWMAXIMIZED = 3,
178 | SW_MAXIMIZE = 3,
179 | SW_SHOWNOACTIVATE = 4,
180 | SW_SHOW = 5,
181 | SW_MINIMIZE = 6,
182 | SW_SHOWMINNOACTIVE = 7,
183 | SW_SHOWNA = 8,
184 | SW_RESTORE = 9,
185 | SW_SHOWDEFAULT = 10,
186 | SW_FORCEMINIMIZE = 11,
187 | SW_MAX = 11
188 | }
189 |
190 | public const int SPIF_SENDWININICHANGE = 2;
191 | public const int SPIF_UPDATEINIFILE = 1;
192 | public const int SPIF_change = SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE;
193 | public const int SPI_SETWORKAREA = 47;
194 | public const int SPI_GETWORKAREA = 48;
195 | public const int SW_HIDE = 0;
196 | public const int SW_SHOW = 1;
197 | public const int SW_SHOWNORMAL = 1;
198 | public const int SW_SHOWMINIMIZED = 2;
199 | public const int SW_SHOWMAXIMIZED = 3;
200 | public const int SW_SHOWNOACTIVATE = 4;
201 | public const int SW_RESTORE = 9;
202 | public const int SW_SHOWDEFAULT = 10;
203 |
204 | public struct POINT
205 | {
206 | public int x;
207 | public int y;
208 | }
209 |
210 | [StructLayout(LayoutKind.Sequential)]
211 | public struct RECT
212 | {
213 | public int Left;
214 | public int Top;
215 | public int Right;
216 | public int Bottom;
217 | }
218 |
219 | [StructLayout(LayoutKind.Sequential)]
220 | public struct APPBARDATA
221 | {
222 | public uint cbSize;
223 | public IntPtr hWnd;
224 | public uint uCallbackMessage;
225 | public ABE uEdge;
226 | public RECT rc;
227 | public int lParam;
228 | }
229 |
230 | public enum ABM : uint
231 | {
232 | New = 0x00000000,
233 | Remove = 0x00000001,
234 | QueryPos = 0x00000002,
235 | SetPos = 0x00000003,
236 | GetState = 0x00000004,
237 | GetTaskbarPos = 0x00000005,
238 | Activate = 0x00000006,
239 | GetAutoHideBar = 0x00000007,
240 | SetAutoHideBar = 0x00000008,
241 | WindowPosChanged = 0x00000009,
242 | SetState = 0x0000000A,
243 | }
244 |
245 | public enum ABE : uint
246 | {
247 | Left = 0,
248 | Top = 1,
249 | Right = 2,
250 | Bottom = 3
251 | }
252 |
253 | public static class ABS
254 | {
255 | public const int Autohide = 0x0000001;
256 | public const int AlwaysOnTop = 0x0000002;
257 | }
258 |
259 | ///
260 | /// Contains information about the placement of a window on the screen.
261 | ///
262 | [Serializable]
263 | [StructLayout(LayoutKind.Sequential)]
264 | public struct WINDOWPLACEMENT
265 | {
266 | ///
267 | /// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).
268 | ///
269 | /// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly.
270 | ///
271 | ///
272 | public int Length;
273 |
274 | ///
275 | /// Specifies flags that control the position of the minimized window and the method by which the window is restored.
276 | ///
277 | public int Flags;
278 |
279 | ///
280 | /// The current show state of the window.
281 | ///
282 | public ShowWindowCommands ShowCmd;
283 |
284 | ///
285 | /// The coordinates of the window's upper-left corner when the window is minimized.
286 | ///
287 | public POINT MinPosition;
288 |
289 | ///
290 | /// The coordinates of the window's upper-left corner when the window is maximized.
291 | ///
292 | public POINT MaxPosition;
293 |
294 | ///
295 | /// The window's coordinates when the window is in the restored position.
296 | ///
297 | public RECT NormalPosition;
298 |
299 | ///
300 | /// Gets the default (empty) value.
301 | ///
302 | public static WINDOWPLACEMENT Default
303 | {
304 | get
305 | {
306 | WINDOWPLACEMENT result = new WINDOWPLACEMENT();
307 | result.Length = Marshal.SizeOf(result);
308 | return result;
309 | }
310 | }
311 | }
312 |
313 | public enum ShowWindowCommands
314 | {
315 | ///
316 | /// Hides the window and activates another window.
317 | ///
318 | Hide = 0,
319 | ///
320 | /// Activates and displays a window. If the window is minimized or
321 | /// maximized, the system restores it to its original size and position.
322 | /// An application should specify this flag when displaying the window
323 | /// for the first time.
324 | ///
325 | Normal = 1,
326 | ///
327 | /// Activates the window and displays it as a minimized window.
328 | ///
329 | ShowMinimized = 2,
330 | ///
331 | /// Maximizes the specified window.
332 | ///
333 | Maximize = 3, // is this the right value?
334 | ///
335 | /// Activates the window and displays it as a maximized window.
336 | ///
337 | ShowMaximized = 3,
338 | ///
339 | /// Displays a window in its most recent size and position. This value
340 | /// is similar to , except
341 | /// the window is not activated.
342 | ///
343 | ShowNoActivate = 4,
344 | ///
345 | /// Activates the window and displays it in its current size and position.
346 | ///
347 | Show = 5,
348 | ///
349 | /// Minimizes the specified window and activates the next top-level
350 | /// window in the Z order.
351 | ///
352 | Minimize = 6,
353 | ///
354 | /// Displays the window as a minimized window. This value is similar to
355 | /// , except the
356 | /// window is not activated.
357 | ///
358 | ShowMinNoActive = 7,
359 | ///
360 | /// Displays the window in its current size and position. This value is
361 | /// similar to , except the
362 | /// window is not activated.
363 | ///
364 | ShowNA = 8,
365 | ///
366 | /// Activates and displays the window. If the window is minimized or
367 | /// maximized, the system restores it to its original size and position.
368 | /// An application should specify this flag when restoring a minimized window.
369 | ///
370 | Restore = 9,
371 | ///
372 | /// Sets the show state based on the SW_* value specified in the
373 | /// STARTUPINFO structure passed to the CreateProcess function by the
374 | /// program that started the application.
375 | ///
376 | ShowDefault = 10,
377 | ///
378 | /// Windows 2000/XP: Minimizes a window, even if the thread
379 | /// that owns the window is not responding. This flag should only be
380 | /// used when minimizing windows from a different thread.
381 | ///
382 | ForceMinimize = 11
383 | }
384 |
385 | [Flags()]
386 | public enum RedrawWindowFlags : uint
387 | {
388 | ///
389 | /// Invalidates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
390 | /// You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_INVALIDATE invalidates the entire window.
391 | ///
392 | Invalidate = 0x1,
393 |
394 | /// Causes the OS to post a WM_PAINT message to the window regardless of whether a portion of the window is invalid.
395 | InternalPaint = 0x2,
396 |
397 | ///
398 | /// Causes the window to receive a WM_ERASEBKGND message when the window is repainted.
399 | /// Specify this value in combination with the RDW_INVALIDATE value; otherwise, RDW_ERASE has no effect.
400 | ///
401 | Erase = 0x4,
402 |
403 | ///
404 | /// Validates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
405 | /// You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_VALIDATE validates the entire window.
406 | /// This value does not affect internal WM_PAINT messages.
407 | ///
408 | Validate = 0x8,
409 |
410 | NoInternalPaint = 0x10,
411 |
412 | /// Suppresses any pending WM_ERASEBKGND messages.
413 | NoErase = 0x20,
414 |
415 | /// Excludes child windows, if any, from the repainting operation.
416 | NoChildren = 0x40,
417 |
418 | /// Includes child windows, if any, in the repainting operation.
419 | AllChildren = 0x80,
420 |
421 | /// Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND and WM_PAINT messages before the RedrawWindow returns, if necessary.
422 | UpdateNow = 0x100,
423 |
424 | ///
425 | /// Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND messages before RedrawWindow returns, if necessary.
426 | /// The affected windows receive WM_PAINT messages at the ordinary time.
427 | ///
428 | EraseNow = 0x200,
429 |
430 | Frame = 0x400,
431 |
432 | NoFrame = 0x800
433 | }
434 |
435 | [Flags()]
436 | public enum SetWindowPosFlags : uint
437 | {
438 | /// If the calling thread and the thread that owns the window are attached to different input queues,
439 | /// the system posts the request to the thread that owns the window. This prevents the calling thread from
440 | /// blocking its execution while other threads process the request.
441 | /// SWP_ASYNCWINDOWPOS
442 | AsynchronousWindowPosition = 0x4000,
443 | /// Prevents generation of the WM_SYNCPAINT message.
444 | /// SWP_DEFERERASE
445 | DeferErase = 0x2000,
446 | /// Draws a frame (defined in the window's class description) around the window.
447 | /// SWP_DRAWFRAME
448 | DrawFrame = 0x0020,
449 | /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to
450 | /// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE
451 | /// is sent only when the window's size is being changed.
452 | /// SWP_FRAMECHANGED
453 | FrameChanged = 0x0020,
454 | /// Hides the window.
455 | /// SWP_HIDEWINDOW
456 | HideWindow = 0x0080,
457 | /// Does not activate the window. If this flag is not set, the window is activated and moved to the
458 | /// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter
459 | /// parameter).
460 | /// SWP_NOACTIVATE
461 | DoNotActivate = 0x0010,
462 | /// Discards the entire contents of the client area. If this flag is not specified, the valid
463 | /// contents of the client area are saved and copied back into the client area after the window is sized or
464 | /// repositioned.
465 | /// SWP_NOCOPYBITS
466 | DoNotCopyBits = 0x0100,
467 | /// Retains the current position (ignores X and Y parameters).
468 | /// SWP_NOMOVE
469 | IgnoreMove = 0x0002,
470 | /// Does not change the owner window's position in the Z order.
471 | /// SWP_NOOWNERZORDER
472 | DoNotChangeOwnerZOrder = 0x0200,
473 | /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to
474 | /// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent
475 | /// window uncovered as a result of the window being moved. When this flag is set, the application must
476 | /// explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
477 | /// SWP_NOREDRAW
478 | DoNotRedraw = 0x0008,
479 | /// Same as the SWP_NOOWNERZORDER flag.
480 | /// SWP_NOREPOSITION
481 | DoNotReposition = 0x0200,
482 | /// Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
483 | /// SWP_NOSENDCHANGING
484 | DoNotSendChangingEvent = 0x0400,
485 | /// Retains the current size (ignores the cx and cy parameters).
486 | /// SWP_NOSIZE
487 | IgnoreResize = 0x0001,
488 | /// Retains the current Z order (ignores the hWndInsertAfter parameter).
489 | /// SWP_NOZORDER
490 | IgnoreZOrder = 0x0004,
491 | /// Displays the window.
492 | /// SWP_SHOWWINDOW
493 | ShowWindow = 0x0040,
494 | }
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 | // mystery
508 | [DllImport("user32.dll")]
509 | public static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
510 |
511 | [StructLayout(LayoutKind.Sequential)]
512 | public struct WindowCompositionAttributeData
513 | {
514 | public WindowCompositionAttribute Attribute;
515 | public IntPtr Data;
516 | public int SizeOfData;
517 | }
518 |
519 | public enum WindowCompositionAttribute
520 | {
521 | WCA_ACCENT_POLICY = 19
522 | }
523 |
524 | public enum AccentState
525 | {
526 | ACCENT_DISABLED = 0,
527 | ACCENT_ENABLE_BLURBEHIND = 3,
528 | ACCENT_ENABLE_ACRYLICBLURBEHIND = 4
529 | }
530 |
531 | [StructLayout(LayoutKind.Sequential)]
532 | public struct AccentPolicy
533 | {
534 | public AccentState AccentState;
535 | public int AccentFlags;
536 | public int GradientColor;
537 | public int AnimationId;
538 | }
539 | }
540 | }
541 |
--------------------------------------------------------------------------------
/RoundedTB/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
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 | Always show
94 | Always hide
95 | [unavailable]
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/RoundedTB/MonitorStuff.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Windows;
5 |
6 | namespace RoundedTB
7 | {
8 | class MonitorStuff
9 | {
10 | [DllImport("user32.dll")]
11 | public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, EnumMonitorsDelegate lpfnEnum, IntPtr dwData);
12 | [DllImport("user32.dll")]
13 | public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lplmi);
14 |
15 | [StructLayout(LayoutKind.Sequential)]
16 | public struct MONITORINFO
17 | {
18 | public uint cbSize;
19 | public LocalPInvoke.RECT rcMonitor;
20 | public LocalPInvoke.RECT rcWork;
21 | public uint dwFlags;
22 | }
23 |
24 | // Stuff for acquiring mouse position because Cursor.Position failed me
25 | [StructLayout(LayoutKind.Sequential)]
26 | public struct POINT
27 | {
28 | public int X;
29 | public int Y;
30 |
31 | public static implicit operator Point(POINT point)
32 | {
33 | return new Point(point.X, point.Y);
34 | }
35 | }
36 |
37 | // It's like a normal bool but delegate, perhaps its also delicate? I don't know. That's up to you, I suppose!
38 | public delegate bool EnumMonitorsDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref LocalPInvoke.RECT lprcMonitor, IntPtr dwData);
39 |
40 | // Gets a list of display info
41 | public static DisplayInfoCollection GetDisplays()
42 | {
43 | DisplayInfoCollection col = new DisplayInfoCollection();
44 |
45 | EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero,
46 | delegate (IntPtr hMonitor, IntPtr hdcMonitor, ref LocalPInvoke.RECT lprcMonitor, IntPtr dwData)
47 | {
48 | MONITORINFO mi = new MONITORINFO();
49 | mi.cbSize = (uint)Marshal.SizeOf(mi);
50 | bool success = GetMonitorInfo(hMonitor, ref mi);
51 | if (success)
52 | {
53 | DisplayInfo di = new DisplayInfo
54 | {
55 | ScreenWidth = (mi.rcMonitor.Right - mi.rcMonitor.Left).ToString(),
56 | ScreenHeight = (mi.rcMonitor.Bottom - mi.rcMonitor.Top).ToString(),
57 | MonitorArea = mi.rcMonitor,
58 | WorkArea = mi.rcWork,
59 | Availability = mi.dwFlags.ToString(),
60 | Handle = hMonitor,
61 | Top = mi.rcMonitor.Top,
62 | Left = mi.rcMonitor.Left
63 | };
64 | col.Add(di);
65 | }
66 | return true;
67 | }, IntPtr.Zero);
68 | return col;
69 | }
70 |
71 | // Super-handy to do things or something
72 | public class DisplayInfoCollection : List
73 | {
74 | }
75 |
76 | // What the above is made of
77 | public class DisplayInfo
78 | {
79 | public string Availability { get; set; }
80 | public string ScreenHeight { get; set; }
81 | public string ScreenWidth { get; set; }
82 | public LocalPInvoke.RECT MonitorArea { get; set; }
83 | public LocalPInvoke.RECT WorkArea { get; set; }
84 | public IntPtr Handle { get; set; }
85 | public int Top { get; set; }
86 | public int Left { get; set; }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/RoundedTB/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("RoundedTB")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("RoundedTB")]
15 | [assembly: AssemblyCopyright("Copyright © 2021")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/RoundedTB/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace RoundedTB.Properties {
12 | using global::System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RoundedTB.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/RoundedTB/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/RoundedTB/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace RoundedTB.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/RoundedTB/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RoundedTB/RoundedTB.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0-windows10.0.19041
4 | WinExe
5 | false
6 | publish\
7 | true
8 | Disk
9 | false
10 | Foreground
11 | 7
12 | Days
13 | false
14 | false
15 | true
16 | 0
17 | 1.0.0.%2a
18 | false
19 | true
20 | false
21 | true
22 | true
23 | true
24 |
25 |
26 | RoundedTBCanary.ico
27 |
28 |
29 | app.manifest
30 |
31 |
32 | true
33 | Z:\RTBDebug\bin\
34 |
35 |
36 |
37 |
38 |
39 |
40 | 1.2.1
41 |
42 |
43 | 1.1.0
44 |
45 |
46 |
47 | 13.0.1
48 |
49 |
50 | 0.7.104
51 |
52 |
53 |
54 | 1.2.1
55 |
56 |
57 | all
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}
67 | 1
68 | 0
69 | 0
70 | tlbimp
71 | False
72 | True
73 |
74 |
75 | tlbimp
76 | 0
77 | 1
78 | 944de083-8fb8-45cf-bcb7-c477acb2f897
79 | 0
80 | false
81 | true
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | False
91 | Microsoft .NET Framework 4.8 %28x86 and x64%29
92 | true
93 |
94 |
95 | False
96 | .NET Framework 3.5 SP1
97 | false
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/RoundedTB/RoundedTB.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/RoundedTB.ico
--------------------------------------------------------------------------------
/RoundedTB/RoundedTBCanary.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/RoundedTBCanary.ico
--------------------------------------------------------------------------------
/RoundedTB/RoundedTBDev.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/RoundedTBDev.ico
--------------------------------------------------------------------------------
/RoundedTB/Taskbar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.Win32;
7 | using System.ComponentModel;
8 | using System.Diagnostics;
9 | using System.Windows;
10 | using System.Windows.Threading;
11 | using Newtonsoft.Json;
12 | using System.Runtime.InteropServices;
13 | using System.Windows.Forms;
14 | using System.Windows.Media;
15 | using System.Runtime.InteropServices;
16 |
17 | namespace RoundedTB
18 | {
19 | class Taskbar
20 | {
21 | ///
22 | /// Checks if the taskbar is centred.
23 | ///
24 | ///
25 | /// A bool indicating if the taskbar is centred.
26 | ///
27 | public static bool CheckIfCentred()
28 | {
29 | bool retVal;
30 | try
31 | {
32 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"))
33 | {
34 | if (key != null)
35 | {
36 | int val = (int)key.GetValue("TaskbarAl");
37 |
38 | if (val == 1)
39 | {
40 | retVal = true;
41 | }
42 | else
43 | {
44 | retVal = false;
45 | }
46 | }
47 | else
48 | {
49 | retVal = false;
50 | }
51 | }
52 | }
53 | catch (Exception)
54 | {
55 | return false;
56 | }
57 | return retVal;
58 | }
59 |
60 | ///
61 | /// Compares two taskbars' rects to see if they've changed
62 | ///
63 | ///
64 | /// a bool indicating if the taskbar's, applist's, and tray's rects rects have changed.
65 | ///
66 | public static bool TaskbarRefreshRequired(Types.Taskbar currentTB, Types.Taskbar newTB, bool isDynamic)
67 | {
68 | // REMINDER: newTB will only have rect & hwnd info. Everything else will be null.
69 |
70 |
71 | bool taskbarRectChanged = true;
72 | bool appListRectChanged = true;
73 | bool trayRectChanged = true;
74 |
75 | if (
76 | currentTB.TaskbarRect.Left == newTB.TaskbarRect.Left &&
77 | currentTB.TaskbarRect.Top == newTB.TaskbarRect.Top &&
78 | currentTB.TaskbarRect.Right == newTB.TaskbarRect.Right &&
79 | currentTB.TaskbarRect.Bottom == newTB.TaskbarRect.Bottom)
80 | {
81 | taskbarRectChanged = false;
82 | }
83 | if (
84 | currentTB.AppListRect.Left == newTB.AppListRect.Left &&
85 | currentTB.AppListRect.Top == newTB.AppListRect.Top &&
86 | currentTB.AppListRect.Right == newTB.AppListRect.Right &&
87 | currentTB.AppListRect.Bottom == newTB.AppListRect.Bottom)
88 | {
89 | appListRectChanged = false;
90 | }
91 | if (
92 | (currentTB.TrayRect.Left + 5 >= newTB.TrayRect.Left && currentTB.TrayRect.Left - 5 <= newTB.TrayRect.Left) &&
93 | currentTB.TrayRect.Top == newTB.TrayRect.Top &&
94 | currentTB.TrayRect.Right == newTB.TrayRect.Right &&
95 | currentTB.TrayRect.Bottom == newTB.TrayRect.Bottom)
96 | {
97 | trayRectChanged = false;
98 | }
99 |
100 | if (isDynamic && (taskbarRectChanged || appListRectChanged || trayRectChanged))
101 | {
102 | return true;
103 | }
104 | else if (!isDynamic && taskbarRectChanged)
105 | {
106 | return true;
107 | }
108 | else
109 | {
110 | return false;
111 | }
112 | }
113 |
114 | ///
115 | /// Gets the rects of the three components of the taskbar from their respective handles.
116 | ///
117 | ///
118 | /// a partial Taskbar containing just rects and handles.
119 | ///
120 | public static Types.Taskbar GetQuickTaskbarRects(IntPtr taskbarHwnd, IntPtr trayHwnd, IntPtr appListHwnd)
121 | {
122 | LocalPInvoke.GetWindowRect(taskbarHwnd, out LocalPInvoke.RECT taskbarRectCheck);
123 | LocalPInvoke.GetWindowRect(trayHwnd, out LocalPInvoke.RECT trayRectCheck);
124 | LocalPInvoke.GetWindowRect(appListHwnd, out LocalPInvoke.RECT appListRectCheck);
125 |
126 | return new Types.Taskbar()
127 | {
128 | TaskbarHwnd = taskbarHwnd,
129 | TrayHwnd = trayHwnd,
130 | AppListHwnd = appListHwnd,
131 | TaskbarRect = taskbarRectCheck,
132 | TrayRect = trayRectCheck,
133 | AppListRect = appListRectCheck
134 | };
135 | }
136 |
137 | ///
138 | /// Resets the specified taskbar.
139 | ///
140 | public static void ResetTaskbar(Types.Taskbar taskbar, Types.Settings settings)
141 | {
142 | LocalPInvoke.SetWindowRgn(taskbar.TaskbarHwnd, IntPtr.Zero, true);
143 | LocalPInvoke.SetLayeredWindowAttributes(taskbar.TaskbarHwnd, 0, 255, LocalPInvoke.LWA_ALPHA);
144 | int style = LocalPInvoke.GetWindowLong(taskbar.TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32();
145 | if ((style & LocalPInvoke.WS_EX_LAYERED) == LocalPInvoke.WS_EX_LAYERED)
146 | {
147 | LocalPInvoke.SetWindowLong(taskbar.TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE, LocalPInvoke.GetWindowLong(taskbar.TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32() ^ LocalPInvoke.WS_EX_LAYERED);
148 | }
149 | style = LocalPInvoke.GetWindowLong(taskbar.TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32();
150 | if ((style & LocalPInvoke.WS_EX_TRANSPARENT) == LocalPInvoke.WS_EX_TRANSPARENT)
151 | {
152 | LocalPInvoke.SetWindowLong(taskbar.TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE, LocalPInvoke.GetWindowLong(taskbar.TaskbarHwnd, LocalPInvoke.GWL_EXSTYLE).ToInt32() ^ LocalPInvoke.WS_EX_TRANSPARENT);
153 | }
154 |
155 | if (settings.CompositionCompat)
156 | {
157 | Interaction.UpdateTranslucentTB(taskbar.TaskbarHwnd);
158 | }
159 | }
160 |
161 | ///
162 | /// Creates a basic region for a specific taskbar and applies it.
163 | ///
164 | ///
165 | /// a bool indicating success.
166 | ///
167 | public static bool UpdateSimpleTaskbar(Types.Taskbar taskbar, Types.Settings settings)
168 | {
169 | try
170 | {
171 | // Create an effective region to be applied to the taskbar
172 | Types.EffectiveRegion taskbarEffectiveRegion = new Types.EffectiveRegion
173 | {
174 | CornerRadius = Convert.ToInt32(settings.SimpleTaskbarLayout.CornerRadius * taskbar.ScaleFactor),
175 | Top = Convert.ToInt32(settings.SimpleTaskbarLayout.MarginTop * taskbar.ScaleFactor),
176 | Left = Convert.ToInt32(settings.SimpleTaskbarLayout.MarginLeft * taskbar.ScaleFactor),
177 | Width = Convert.ToInt32(taskbar.TaskbarRect.Right - taskbar.TaskbarRect.Left - (settings.SimpleTaskbarLayout.MarginRight * taskbar.ScaleFactor)) + 1,
178 | Height = Convert.ToInt32(taskbar.TaskbarRect.Bottom - taskbar.TaskbarRect.Top - (settings.SimpleTaskbarLayout.MarginBottom * taskbar.ScaleFactor)) + 1
179 | };
180 |
181 | IntPtr region = LocalPInvoke.CreateRoundRectRgn(taskbarEffectiveRegion.Left, taskbarEffectiveRegion.Top, taskbarEffectiveRegion.Width, taskbarEffectiveRegion.Height, taskbarEffectiveRegion.CornerRadius, taskbarEffectiveRegion.CornerRadius);
182 | LocalPInvoke.SetWindowRgn(taskbar.TaskbarHwnd, region, true);
183 | if (settings.CompositionCompat)
184 | {
185 | Interaction.UpdateTranslucentTB(taskbar.TaskbarHwnd);
186 | }
187 | return true;
188 | }
189 | catch (Exception)
190 | {
191 | return false;
192 | }
193 | }
194 |
195 | ///
196 | /// Creates a dynamic region for a specific taskbar and applies it.
197 | ///
198 | ///
199 | /// a bool indicating success.
200 | ///
201 | public static bool UpdateDynamicTaskbar(Types.Taskbar taskbar, Types.Settings settings)
202 | {
203 | try
204 | {
205 | IntPtr mainRegion;
206 | IntPtr workingRegion = LocalPInvoke.CreateRoundRectRgn(1, 1, 1, 1, 0, 0);
207 | int centredDistanceFromEdge = 0;
208 |
209 | // Create an effective region to be applied to the taskbar for the applist
210 | Types.EffectiveRegion taskbarEffectiveRegion = new Types.EffectiveRegion
211 | {
212 | CornerRadius = Convert.ToInt32(settings.DynamicAppListLayout.CornerRadius * taskbar.ScaleFactor),
213 | Top = Convert.ToInt32(settings.DynamicAppListLayout.MarginTop * taskbar.ScaleFactor),
214 | Left = Convert.ToInt32(settings.DynamicAppListLayout.MarginLeft * taskbar.ScaleFactor),
215 | Width = Convert.ToInt32(taskbar.TaskbarRect.Right - taskbar.TaskbarRect.Left - (settings.DynamicAppListLayout.MarginRight * taskbar.ScaleFactor)) + 1,
216 | Height = Convert.ToInt32(taskbar.TaskbarRect.Bottom - taskbar.TaskbarRect.Top - (settings.DynamicAppListLayout.MarginBottom * taskbar.ScaleFactor)) + 1
217 | };
218 |
219 | // Create an effective region to be applied to the taskbar for the applist
220 | Types.EffectiveRegion centredEffectiveRegion = new Types.EffectiveRegion
221 | {
222 | CornerRadius = Convert.ToInt32(settings.DynamicAppListLayout.CornerRadius * taskbar.ScaleFactor),
223 | Top = Convert.ToInt32(settings.DynamicAppListLayout.MarginTop * taskbar.ScaleFactor),
224 | Left = Convert.ToInt32(settings.DynamicAppListLayout.MarginRight * taskbar.ScaleFactor) - 1,
225 | Width = Convert.ToInt32(taskbar.TaskbarRect.Right - taskbar.TaskbarRect.Left - (settings.DynamicAppListLayout.MarginRight * taskbar.ScaleFactor)) + 1,
226 | Height = Convert.ToInt32(taskbar.TaskbarRect.Bottom - taskbar.TaskbarRect.Top - (settings.DynamicAppListLayout.MarginBottom * taskbar.ScaleFactor)) + 1
227 | };
228 |
229 | // Create an effective region to be applied to the taskbar for the tray
230 | Types.EffectiveRegion trayEffectiveRegion = new Types.EffectiveRegion
231 | {
232 | CornerRadius = Convert.ToInt32(settings.DynamicTrayLayout.CornerRadius * taskbar.ScaleFactor),
233 | Top = Convert.ToInt32(settings.DynamicTrayLayout.MarginTop * taskbar.ScaleFactor),
234 | Left = Convert.ToInt32((settings.DynamicTrayLayout.MarginLeft * taskbar.ScaleFactor) - (3 * taskbar.ScaleFactor)), // Add extra margin for taskbar left as there's no "padding" provided by Windows and always looks weird as soon as you trim it otherwise.
235 | Width = Convert.ToInt32(taskbar.TaskbarRect.Right - taskbar.TaskbarRect.Left - (settings.DynamicTrayLayout.MarginRight * taskbar.ScaleFactor)) + 1,
236 | Height = Convert.ToInt32(taskbar.TaskbarRect.Bottom - taskbar.TaskbarRect.Top - (settings.DynamicTrayLayout.MarginBottom * taskbar.ScaleFactor)) + 1
237 | };
238 |
239 | Types.EffectiveRegion widgetsEffectiveRegion = new Types.EffectiveRegion
240 | {
241 | CornerRadius = Convert.ToInt32(settings.DynamicWidgetsLayout.CornerRadius * taskbar.ScaleFactor),
242 | Top = Convert.ToInt32(settings.DynamicWidgetsLayout.MarginTop * taskbar.ScaleFactor),
243 | Left = Convert.ToInt32(settings.DynamicWidgetsLayout.MarginLeft * taskbar.ScaleFactor),
244 | Width = Convert.ToInt32(168 * taskbar.ScaleFactor - (settings.DynamicWidgetsLayout.MarginRight * taskbar.ScaleFactor)) + 1,
245 | Height = Convert.ToInt32(taskbar.TaskbarRect.Bottom - taskbar.TaskbarRect.Top - (settings.DynamicWidgetsLayout.MarginBottom * taskbar.ScaleFactor)) + 1
246 | };
247 |
248 | centredDistanceFromEdge = taskbar.TaskbarRect.Right - taskbar.AppListRect.Right - Convert.ToInt32(2 * taskbar.ScaleFactor);
249 |
250 | Tasklist tasklist = new Tasklist();
251 | tasklist.Update();
252 |
253 | List buttons = tasklist.GetButtons();
254 |
255 | Tasklist.TasklistButton rightmostButton = null;
256 | Tasklist.TasklistButton leftmostButton = null;
257 | foreach (var button in buttons)
258 | {
259 | if (rightmostButton == null || button.x > rightmostButton.x)
260 | {
261 | rightmostButton = button;
262 | }
263 |
264 | if (leftmostButton == null || button.x < leftmostButton.x)
265 | {
266 | leftmostButton = button;
267 | }
268 | }
269 |
270 | if (rightmostButton != null)
271 | {
272 | Debug.WriteLine("Rightmost Button Name: " + rightmostButton.name);
273 | Debug.WriteLine("X-coordinate: " + rightmostButton.x);
274 | Debug.WriteLine("Y-coordinate: " + rightmostButton.y);
275 | Debug.WriteLine("Width: " + rightmostButton.width);
276 | Debug.WriteLine("Height: " + rightmostButton.height);
277 | }
278 | else
279 | {
280 | Debug.WriteLine("No buttons found.");
281 | }
282 |
283 | //int totalWidth = buttons.Sum(button => button.width); Sum of width of all apps in the taskbar
284 |
285 | centredDistanceFromEdge = taskbar.TaskbarRect.Right - rightmostButton.x - rightmostButton.width; //Right-most calculation (only works for grouped)
286 |
287 |
288 | centredDistanceFromEdge = leftmostButton.x - leftmostButton.width; //Left-most calculation (Works for grouped and ungrouped)
289 |
290 |
291 |
292 | // If on Windows 10, add an extra 20 logical pixels for the grabhandle
293 | if (!settings.IsWindows11)
294 | {
295 | centredDistanceFromEdge -= Convert.ToInt32(20 * taskbar.ScaleFactor);
296 | }
297 |
298 | // Create region for if the taskbar is centred by take the right-to-right distance (centredDistanceFromEdge) off from both sides, as well as the margin
299 | if (settings.IsCentred)
300 | {
301 |
302 |
303 | mainRegion = LocalPInvoke.CreateRoundRectRgn(
304 | centredDistanceFromEdge + centredEffectiveRegion.Left,
305 | centredEffectiveRegion.Top,
306 | centredEffectiveRegion.Width - centredDistanceFromEdge,
307 | centredEffectiveRegion.Height,
308 | centredEffectiveRegion.CornerRadius,
309 | centredEffectiveRegion.CornerRadius
310 | );
311 | }
312 |
313 | // Create a region for if the taskbar is left-aligned, right-to-right distance (centredDistanceFromEdge) off from the right-hand side, as well as the margin
314 | else
315 | {
316 |
317 | mainRegion = LocalPInvoke.CreateRoundRectRgn(
318 | taskbarEffectiveRegion.Left,
319 | taskbarEffectiveRegion.Top,
320 | taskbarEffectiveRegion.Width - centredDistanceFromEdge,
321 | taskbarEffectiveRegion.Height,
322 | taskbarEffectiveRegion.CornerRadius,
323 | taskbarEffectiveRegion.CornerRadius
324 | );
325 | }
326 |
327 | // If the user has it enabled and the tray handle isn't null, create a region for the system tray and merge it with the taskbar region
328 | if (settings.ShowTray && taskbar.TrayHwnd != IntPtr.Zero)
329 | {
330 | IntPtr trayRegion = LocalPInvoke.CreateRoundRectRgn(
331 | (taskbar.TrayRect.Left - taskbar.TaskbarRect.Left) - trayEffectiveRegion.Left,
332 | trayEffectiveRegion.Top,
333 | trayEffectiveRegion.Width,
334 | trayEffectiveRegion.Height,
335 | trayEffectiveRegion.CornerRadius,
336 | trayEffectiveRegion.CornerRadius
337 | );
338 |
339 | LocalPInvoke.CombineRgn(workingRegion, trayRegion, mainRegion, 2);
340 | mainRegion = workingRegion;
341 | }
342 |
343 | if (settings.ShowWidgets)
344 | {
345 | IntPtr widgetsRegion = LocalPInvoke.CreateRoundRectRgn(
346 | widgetsEffectiveRegion.Left,
347 | widgetsEffectiveRegion.Top,
348 | widgetsEffectiveRegion.Width,
349 | widgetsEffectiveRegion.Height,
350 | widgetsEffectiveRegion.CornerRadius,
351 | widgetsEffectiveRegion.CornerRadius
352 | );
353 |
354 | LocalPInvoke.CombineRgn(workingRegion, widgetsRegion, mainRegion, 2);
355 | mainRegion = workingRegion;
356 | }
357 |
358 | // Apply the final region to the taskbar
359 | LocalPInvoke.SetWindowRgn(taskbar.TaskbarHwnd, mainRegion, true);
360 | if (settings.CompositionCompat)
361 | {
362 | Interaction.UpdateTranslucentTB(taskbar.TaskbarHwnd);
363 | }
364 |
365 | return true;
366 | }
367 | catch (Exception)
368 | {
369 | return false;
370 | }
371 |
372 | }
373 |
374 | ///
375 | /// Checks if there are any new taskbars, or if any taskbars are no longer present.
376 | ///
377 | ///
378 | /// a bool indicating success.
379 | ///
380 | public static bool TaskbarCountOrHandleChanged(int taskbarCount, IntPtr mainTaskbarHandle)
381 | {
382 | List currentTaskbars = new List();
383 | bool otherTaskbarsExist = true;
384 | IntPtr hwndPrevious = IntPtr.Zero;
385 | currentTaskbars.Add(LocalPInvoke.FindWindowExA(IntPtr.Zero, hwndPrevious, "Shell_TrayWnd", null));
386 |
387 | if (currentTaskbars[0] == IntPtr.Zero)
388 | {
389 | return false;
390 | }
391 |
392 | if (currentTaskbars[0] != mainTaskbarHandle)
393 | {
394 | return true;
395 | }
396 |
397 | while (otherTaskbarsExist)
398 | {
399 | IntPtr hwndCurrent = LocalPInvoke.FindWindowExA(IntPtr.Zero, hwndPrevious, "Shell_SecondaryTrayWnd", null);
400 | hwndPrevious = hwndCurrent;
401 |
402 | if (hwndCurrent == IntPtr.Zero)
403 | {
404 | otherTaskbarsExist = false;
405 | }
406 | else
407 | {
408 | currentTaskbars.Add(hwndCurrent);
409 | }
410 | }
411 | if (currentTaskbars.Count != taskbarCount)
412 | {
413 | return true;
414 | }
415 | return false;
416 | }
417 |
418 | ///
419 | /// Checks if the provided update is valid.
420 | ///
421 | ///
422 | /// A bool indicating if the update is valid.
423 | ///
424 | public static bool CheckDynamicUpdateIsValid(Types.Taskbar currentTB, Types.Taskbar newTB)
425 | {
426 | // REMINDER: newTB will only have rect & hwnd info. Everything else will be null.
427 |
428 | // Check if either of the supplied taskbars are null
429 | if (currentTB == null || newTB == null)
430 | {
431 | return false;
432 | }
433 |
434 | // Check if the taskbar handles are different
435 | if (currentTB.TaskbarHwnd != newTB.TaskbarHwnd)
436 | {
437 | return false;
438 | }
439 |
440 | // Get width of app list. Not strictly necessary as the applist is always measured from the left but doing so just in case
441 | int newAppListWidth = newTB.AppListRect.Right - newTB.AppListRect.Left;
442 | int currentAppListWidth = currentTB.AppListRect.Right - currentTB.AppListRect.Left;
443 |
444 | if (newTB.AppListRect.Right >= newTB.TrayRect.Left && newTB.TrayRect.Left != 0)
445 | {
446 | return false;
447 | }
448 |
449 | if (newAppListWidth == newTB.TrayRect.Left && newTB.TrayRect.Left != 0)
450 | {
451 | return false;
452 | }
453 |
454 | if (newAppListWidth <= 20 * currentTB.ScaleFactor && newAppListWidth != 0)
455 | {
456 | return false;
457 | }
458 |
459 | if (newAppListWidth >= newTB.TaskbarRect.Right - newTB.TaskbarRect.Left && newAppListWidth != 0)
460 | {
461 | return false;
462 | }
463 |
464 | Debug.WriteLine($"Old width: {currentAppListWidth}\nNew width: {newAppListWidth}");
465 | return true;
466 | }
467 |
468 | ///
469 | /// Collects information on any currently-present taskbars.
470 | ///
471 | ///
472 | /// A list of taskbars populated with information about their size, handles etc.
473 | ///
474 | public static List GenerateTaskbarInfo()
475 | {
476 | List retVal = new List();
477 |
478 | IntPtr hwndMain = LocalPInvoke.FindWindowExA(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", null); // Find main taskbar
479 | LocalPInvoke.GetWindowRect(hwndMain, out LocalPInvoke.RECT rectMain); // Get the RECT of the main taskbar
480 |
481 | IntPtr hrgnMain = IntPtr.Zero; // Set recovery region to IntPtr.Zero
482 | IntPtr hwndTray = LocalPInvoke.FindWindowExA(hwndMain, IntPtr.Zero, "TrayNotifyWnd", null); // Get handle to the main taskbar's tray
483 | LocalPInvoke.GetWindowRect(hwndTray, out LocalPInvoke.RECT rectTray); // Get the RECT for the main taskbar's tray
484 | IntPtr hwndAppList = LocalPInvoke.FindWindowExA(LocalPInvoke.FindWindowExA(hwndMain, IntPtr.Zero, "ReBarWindow32", null), IntPtr.Zero, "MSTaskSwWClass", null); // Get the handle to the main taskbar's app list
485 | LocalPInvoke.GetWindowRect(hwndAppList, out LocalPInvoke.RECT rectAppList);// Get the RECT for the main taskbar's app list
486 |
487 | retVal.Add(new Types.Taskbar
488 | {
489 | TaskbarHwnd = hwndMain,
490 | TrayHwnd = hwndTray,
491 | AppListHwnd = hwndAppList,
492 | TaskbarRect = rectMain,
493 | TrayRect = rectTray,
494 | AppListRect = rectAppList,
495 | RecoveryHrgn = hrgnMain,
496 | ScaleFactor = Convert.ToDouble(LocalPInvoke.GetDpiForWindow(hwndMain)) / 96.00,
497 | TaskbarRes = $"{rectMain.Right - rectMain.Left} x {rectMain.Bottom - rectMain.Top}",
498 | Ignored = false
499 | });
500 | int style = LocalPInvoke.GetWindowLong(hwndMain, LocalPInvoke.GWL_EXSTYLE).ToInt32();
501 | if ((style & LocalPInvoke.WS_EX_LAYERED) != LocalPInvoke.WS_EX_LAYERED)
502 | {
503 | LocalPInvoke.SetWindowLong(hwndMain, LocalPInvoke.GWL_EXSTYLE, LocalPInvoke.GetWindowLong(hwndMain, LocalPInvoke.GWL_EXSTYLE).ToInt32() ^ LocalPInvoke.WS_EX_LAYERED);
504 | LocalPInvoke.SetLayeredWindowAttributes(hwndMain, 0, 255, LocalPInvoke.LWA_ALPHA);
505 | }
506 |
507 |
508 |
509 |
510 | bool i = true;
511 | IntPtr hwndPrevious = IntPtr.Zero;
512 | while (i)
513 | {
514 | IntPtr hwndCurrent = LocalPInvoke.FindWindowExA(IntPtr.Zero, hwndPrevious, "Shell_SecondaryTrayWnd", null);
515 | hwndPrevious = hwndCurrent;
516 |
517 | if (hwndCurrent == IntPtr.Zero)
518 | {
519 | i = false;
520 | }
521 | else
522 | {
523 | LocalPInvoke.GetWindowRect(hwndCurrent, out LocalPInvoke.RECT rectCurrent);
524 | LocalPInvoke.GetWindowRgn(hwndCurrent, out IntPtr hrgnCurrent);
525 | Interaction interaction = new Interaction();
526 | IntPtr hwndSecTray = IntPtr.Zero;
527 | if (interaction.IsWindows11())
528 | {
529 | IntPtr imd = LocalPInvoke.FindWindowExA(hwndCurrent, IntPtr.Zero, "Windows.UI.Composition.DesktopWindowContentBridge", null);
530 | hwndSecTray = LocalPInvoke.FindWindowExA(hwndCurrent, imd, "Windows.UI.Composition.DesktopWindowContentBridge", null);
531 | }
532 | else
533 | {
534 | hwndSecTray = LocalPInvoke.FindWindowExA(hwndCurrent, IntPtr.Zero, "TrayNotifyWnd", null); // Get handle to this secondary taskbar's tray
535 | }
536 | LocalPInvoke.GetWindowRect(hwndTray, out LocalPInvoke.RECT rectSecTray); // Get the RECT for this secondary taskbar's tray
537 | IntPtr hwndSecAppList = LocalPInvoke.FindWindowExA(LocalPInvoke.FindWindowExA(hwndCurrent, IntPtr.Zero, "WorkerW", null), IntPtr.Zero, "MSTaskListWClass", null); // Get the handle to the main taskbar's app list
538 | LocalPInvoke.GetWindowRect(hwndSecAppList, out LocalPInvoke.RECT rectSecAppList);// Get the RECT for this secondary taskbar's app list
539 | retVal.Add(new Types.Taskbar
540 | {
541 | TaskbarHwnd = hwndCurrent,
542 | TrayHwnd = hwndSecTray,
543 | AppListHwnd = hwndSecAppList,
544 | TaskbarRect = rectCurrent,
545 | TrayRect = rectSecTray,
546 | AppListRect = rectSecAppList,
547 | RecoveryHrgn = hrgnCurrent,
548 | ScaleFactor = Convert.ToDouble(LocalPInvoke.GetDpiForWindow(hwndCurrent)) / 96.00,
549 | TaskbarRes = $"{rectCurrent.Right - rectCurrent.Left} x {rectCurrent.Bottom - rectCurrent.Top}",
550 | Ignored = false
551 | });
552 | style = LocalPInvoke.GetWindowLong(hwndCurrent, LocalPInvoke.GWL_EXSTYLE).ToInt32();
553 | if ((style & LocalPInvoke.WS_EX_LAYERED) != LocalPInvoke.WS_EX_LAYERED)
554 | {
555 | LocalPInvoke.SetWindowLong(hwndCurrent, LocalPInvoke.GWL_EXSTYLE, LocalPInvoke.GetWindowLong(hwndCurrent, LocalPInvoke.GWL_EXSTYLE).ToInt32() ^ LocalPInvoke.WS_EX_LAYERED);
556 | LocalPInvoke.SetLayeredWindowAttributes(hwndCurrent, 0, 255, LocalPInvoke.LWA_ALPHA);
557 | }
558 | }
559 | }
560 |
561 | //foreach (var tb in retVal)
562 | //{
563 | // TaskbarShouldBeFilled(tb.TaskbarHwnd);
564 | //}
565 | return retVal;
566 | }
567 |
568 | ///
569 | /// Checks if the given taskbar should be filled to the edge of the screen.
570 | ///
571 | ///
572 | /// A bool indicating whether or not the taskbar needs to be filled.
573 | ///
574 | public static bool TaskbarShouldBeFilled(IntPtr taskbarHwnd, Types.Settings settings)
575 | {
576 | bool retVal = false;
577 |
578 | if (settings.FillOnMaximise)
579 | {
580 | // Attempt to check for if alt+tab/task switcher is open (Windows 11 only)
581 | IntPtr topHwnd = LocalPInvoke.WindowFromPoint(new LocalPInvoke.POINT() { x = 0, y = 0 });
582 | StringBuilder windowClass = new StringBuilder(1024);
583 | try
584 | {
585 | LocalPInvoke.GetClassName(topHwnd, windowClass, 1024);
586 |
587 | if (windowClass.ToString() == "XamlExplorerHostIslandWindow" && settings.FillOnTaskSwitch)
588 | {
589 | return true;
590 | }
591 | }
592 | catch (Exception) { }
593 |
594 | List windowList = Interaction.GetTopLevelWindows();
595 | foreach (IntPtr windowHwnd in windowList)
596 | {
597 | if (LocalPInvoke.IsWindowVisible(windowHwnd))
598 | {
599 | if (LocalPInvoke.MonitorFromWindow(taskbarHwnd, 2) == LocalPInvoke.MonitorFromWindow(windowHwnd, 2))
600 | {
601 | LocalPInvoke.DwmGetWindowAttribute(windowHwnd, LocalPInvoke.DWMWINDOWATTRIBUTE.Cloaked, out bool isCloaked, 0x4);
602 | if (!isCloaked)
603 | {
604 | LocalPInvoke.WINDOWPLACEMENT lpwndpl = new LocalPInvoke.WINDOWPLACEMENT();
605 | LocalPInvoke.GetWindowPlacement(windowHwnd, ref lpwndpl);
606 | if (lpwndpl.ShowCmd == LocalPInvoke.ShowWindowCommands.ShowMaximized)
607 | {
608 | retVal = true;
609 | }
610 | }
611 | }
612 | }
613 | }
614 | }
615 |
616 | return retVal;
617 | }
618 |
619 | ///
620 | /// Sets the appbar properties of the taskbar.
621 | ///
622 | public static void SetTaskbarState(LocalPInvoke.AppBarStates option, IntPtr hwnd)
623 | {
624 | LocalPInvoke.APPBARDATA msgData = new LocalPInvoke.APPBARDATA();
625 | msgData.cbSize = (uint)Marshal.SizeOf(msgData);
626 | msgData.hWnd = hwnd;
627 | msgData.lParam = (int)option;
628 | LocalPInvoke.SHAppBarMessage(LocalPInvoke.ABM.SetState, ref msgData);
629 | }
630 |
631 |
632 | }
633 | }
634 |
--------------------------------------------------------------------------------
/RoundedTB/TaskbarEffect.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/RoundedTB/TaskbarEffect.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Runtime.InteropServices;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Navigation;
15 | using System.Windows.Shapes;
16 | using System.Windows.Threading;
17 | using System.ComponentModel;
18 | using System.Threading;
19 |
20 | namespace RoundedTB
21 | {
22 | ///
23 | /// Interaction logic for TaskbarEffect.xaml
24 | ///
25 | public partial class TaskbarEffect : Window
26 | {
27 | BackgroundWorker backgroundWorker = new BackgroundWorker();
28 | public POINT pOINT = new POINT();
29 | public Point pp = new Point();
30 |
31 | public TaskbarEffect()
32 | {
33 |
34 | InitializeComponent();
35 | { // Code for removing from Alt+Tab
36 | Window w = new Window();
37 | w.Top = -10000;
38 | w.Left = -10000;
39 | w.Width = 1;
40 | w.Height = 1;
41 | w.WindowStyle = WindowStyle.ToolWindow;
42 | w.Show();
43 | Owner = w;
44 | w.Hide();
45 | }
46 | Show();
47 |
48 | mwin.Top = 0;
49 | mwin.Left = 0;
50 | backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
51 | backgroundWorker.RunWorkerAsync();
52 | }
53 |
54 | private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
55 | {
56 | while (true)
57 | {
58 | Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => MoveTheThingy()));
59 | Thread.Sleep(10);
60 | }
61 | }
62 | public void MoveTheThingy()
63 | {
64 | GetCursorPos(out pOINT);
65 | Point pp = mwin.PointFromScreen(pOINT);
66 | Canvas.SetLeft(eye, pp.X - (eye.Width / 2));
67 | Canvas.SetTop(eye, pp.Y - (eye.Height / 2));
68 |
69 | }
70 |
71 |
72 |
73 |
74 | [DllImport("user32.dll")]
75 | public static extern bool GetCursorPos(out POINT lpPoint);
76 |
77 |
78 | public struct POINT
79 | {
80 | public int X;
81 | public int Y;
82 |
83 | public static implicit operator Point(POINT point)
84 | {
85 | return new Point(point.X, point.Y);
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/RoundedTB/Tasklist.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Runtime.InteropServices;
5 | using UIAutomationClient;
6 | //PowerToys Shortcut-Guide code ported to C#
7 |
8 | public class Tasklist
9 | {
10 | private IUIAutomation automation;
11 | private IUIAutomationElement element;
12 |
13 | private int UIA_BoundingRectanglePropertyId = 30001;//Unused
14 |
15 | public void Update()
16 | {
17 | IntPtr tasklistHwnd = FindTasklistWindow();
18 |
19 | if (tasklistHwnd == IntPtr.Zero)
20 | return;
21 |
22 | InitializeAutomation();
23 |
24 | element = automation.ElementFromHandle(tasklistHwnd);
25 | }
26 |
27 | public bool UpdateButtons(List buttons)
28 | {
29 | if (automation == null || element == null)
30 | return false;
31 |
32 | IUIAutomationElementArray elements = element.FindAll(TreeScope.TreeScope_Children, automation.CreateTrueCondition());
33 |
34 | if (elements == null)
35 | return false;
36 |
37 | int count = elements.Length;
38 |
39 | List foundButtons = new List();
40 | foundButtons.Capacity = count;
41 |
42 | for (int i = 0; i < count; ++i)
43 | {
44 | IUIAutomationElement child = elements.GetElement(i);
45 |
46 | TasklistButton button = new TasklistButton();
47 | object varRect = child.GetCurrentPropertyValue(30001); //child.GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId);
48 | if (varRect is double[] rectArray && rectArray.Length == 4)
49 | {
50 | button.x = (int)rectArray[0];
51 | button.y = (int)rectArray[1];
52 | button.width = (int)rectArray[2];
53 | button.height = (int)rectArray[3];
54 | }
55 | else
56 | {
57 | return false;
58 | }
59 | string automationId = child.GetCurrentPropertyValue(30011); //UIA_AutomationIdPropertyId
60 | button.name = automationId;
61 |
62 | foundButtons.Add(button);
63 | }
64 |
65 | buttons.Clear();
66 | for (int i = 0; i < foundButtons.Count; i++)
67 | {
68 | if (buttons.Count == 0)
69 | {
70 | foundButtons[i].keynum = 1;
71 | buttons.Add(foundButtons[i]);
72 | }
73 | else
74 | {
75 | if (foundButtons[i].x < buttons[buttons.Count - 1].x || foundButtons[i].y < buttons[buttons.Count - 1].y)
76 | break;
77 | if (foundButtons[i].name == buttons[buttons.Count - 1].name)
78 | continue;
79 |
80 | foundButtons[i].keynum = buttons[buttons.Count - 1].keynum + 1;
81 | buttons.Add(foundButtons[i]);
82 |
83 | if (buttons[buttons.Count - 1].keynum == 10)
84 | break;
85 | }
86 | }
87 | return true;
88 | }
89 |
90 | public List GetButtons()
91 | {
92 |
93 | List buttons = new List();
94 | UpdateButtons(buttons);
95 | return buttons;
96 | }
97 |
98 | private IntPtr FindTasklistWindow()
99 | {
100 | IntPtr tasklistHwnd = FindWindow("Shell_TrayWnd", null);
101 | if (tasklistHwnd == IntPtr.Zero)
102 | return IntPtr.Zero;
103 |
104 | tasklistHwnd = FindWindowEx(tasklistHwnd, IntPtr.Zero, "ReBarWindow32", null);
105 | if (tasklistHwnd == IntPtr.Zero)
106 | return IntPtr.Zero;
107 |
108 | tasklistHwnd = FindWindowEx(tasklistHwnd, IntPtr.Zero, "MSTaskSwWClass", null);
109 | if (tasklistHwnd == IntPtr.Zero)
110 | return IntPtr.Zero;
111 |
112 | tasklistHwnd = FindWindowEx(tasklistHwnd, IntPtr.Zero, "MSTaskListWClass", null);
113 | return tasklistHwnd;
114 | }
115 |
116 | private void InitializeAutomation()
117 | {
118 | if (automation == null)
119 | {
120 | automation = new CUIAutomation();
121 | }
122 | }
123 |
124 | [DllImport("user32.dll", SetLastError = true)]
125 | private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
126 |
127 | [DllImport("user32.dll", SetLastError = true)]
128 | private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
129 |
130 | public class TasklistButton
131 | {
132 | public string? name;
133 | public int x;
134 | public int y;
135 | public int width;
136 | public int height;
137 | public int keynum;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/RoundedTB/Types.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RoundedTB
8 | {
9 | public class Types
10 | {
11 | public class Taskbar
12 | {
13 | public IntPtr TaskbarHwnd { get; set; } // Handle to the taskbar
14 | public IntPtr TrayHwnd { get; set; } // Handle to the tray on the taskbar (if present)
15 | public IntPtr AppListHwnd { get; set; } // Handle to the list of open/pinned apps on the taskbar
16 | public LocalPInvoke.RECT TaskbarRect { get; set; } // Bounding box for the taskbar
17 | public LocalPInvoke.RECT TrayRect { get; set; } // Bounding box for the tray (dynamic)
18 | public LocalPInvoke.RECT AppListRect { get; set; } // Bounding box for the list of pinned & open apps (dynamic)
19 | public IntPtr RecoveryHrgn { get; set; } // Pointer to the recovery region for any given taskbar. Defaults to IntPtr.Zero
20 | public double ScaleFactor { get; set; } // The scale factor of the monitor the taskbar is on
21 | public string TaskbarRes { get; set; } // Resolution of the taskbar as text
22 | public bool Ignored { get; set; } // Specifies if the taskbar should be ignored when applying changes
23 | public bool TaskbarHidden { get; set; } // Specifies if this taskbar is currently hidden by RTB
24 | public bool TrayHidden { get; set; } // Specifies if the tray is currently hidden by RTB on this taskbar
25 | public int AppListWidth { get; set; } // Specifies the width of the app list
26 | public TaskbarEffect TaskbarEffectWindow { get; set; } // Unused clone to apply effects to the taskbar
27 | }
28 |
29 | public class Settings
30 | {
31 | public int Version { get; set; }
32 | public SegmentSettings SimpleTaskbarLayout { get; set; }
33 | public SegmentSettings DynamicAppListLayout { get; set; }
34 | public SegmentSettings DynamicTrayLayout { get; set; }
35 | public SegmentSettings DynamicWidgetsLayout { get; set; }
36 | public bool IsDynamic { get; set; }
37 | public bool IsCentred { get; set; }
38 | public bool IsWindows11 { get; set; }
39 | public bool ShowTray { get; set; }
40 | public bool ShowWidgets { get; set; }
41 | public bool CompositionCompat { get; set; }
42 | public bool IsNotFirstLaunch { get; set; }
43 | public bool FillOnMaximise { get; set; }
44 | public bool FillOnTaskSwitch { get; set; }
45 | public bool ShowSegmentsOnHover { get; set; }
46 | public int AutoHide { get; set; }
47 | }
48 |
49 | public class EffectiveRegion
50 | {
51 | public int CornerRadius { get; set; }
52 | public int Top { get; set; }
53 | public int Left { get; set; }
54 | public int Width { get; set; }
55 | public int Height { get; set; }
56 | }
57 |
58 | public class SegmentSettings
59 | {
60 | public int CornerRadius { get; set; }
61 | public int MarginTop { get; set; }
62 | public int MarginLeft { get; set; }
63 | public int MarginBottom { get; set; }
64 | public int MarginRight { get; set; }
65 | }
66 |
67 | public enum TrayMode
68 | {
69 | Show = 0,
70 | Hide = 1,
71 | AutoHide = 2,
72 | }
73 |
74 | public enum CompositionMode
75 | {
76 | None = 0,
77 | TranslucentTB = 1,
78 | Legacy = 2,
79 | }
80 |
81 | public enum KeyModifier
82 | {
83 | None = 0,
84 | Alt = 1,
85 | Control = 2,
86 | Shift = 4,
87 | WinKey = 8
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/RoundedTB/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
60 |
61 |
62 |
76 |
77 |
78 | UTF-8
79 | PerMonitorV2
80 | SegmentHeap
81 | true
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/RoundedTB/res/HeadBannerCan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/res/HeadBannerCan.png
--------------------------------------------------------------------------------
/RoundedTB/res/HeadBannerDev.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/res/HeadBannerDev.png
--------------------------------------------------------------------------------
/RoundedTB/res/Headbanner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/res/Headbanner.png
--------------------------------------------------------------------------------
/RoundedTB/res/TrayDark.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/res/TrayDark.ico
--------------------------------------------------------------------------------
/RoundedTB/res/TrayLight.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Benisgo/RoundedTB/cdb307cb927cbf396dc60b39a27a7ae18a787aaa/RoundedTB/res/TrayLight.ico
--------------------------------------------------------------------------------