Compare commits

...

523 commits

Author SHA1 Message Date
Peter Kirmeier
b3f2ce8500
Merge pull request #524 from HansieNL/master
Update lang.nl.resx
2024-06-18 19:07:14 +02:00
HansieNL
235737381e
Update lang.nl.resx 2024-06-10 01:12:46 +02:00
Markus Hofknecht
ccbfd22db0 Merge branch 'master' of https://github.com/Hofknecht/SystemTrayMenu 2023-09-09 10:03:12 +02:00
Markus Hofknecht
23d846c691 version 1.3.5.0 2023-09-09 10:02:57 +02:00
Markus Hofknecht
a16f686b14
Update README.md 2023-09-09 09:57:42 +02:00
Markus Hofknecht
3c9f345db3 README.md 2023-09-01 14:28:46 +02:00
Markus Hofknecht
bd71f6fa3b [BUG] In v1.3.3 introduced a issue that always asking for admin, but should only ask if shortcut requires run as admin (#499), version 1.3.4.0 2023-08-28 14:54:54 +02:00
Markus Hofknecht
5c043cea17 Update README.md 2023-08-28 14:38:09 +02:00
Markus Hofknecht
dbd1e4e0da Merge branch 'master' of https://github.com/Hofknecht/SystemTrayMenu 2023-08-28 14:07:07 +02:00
Markus Hofknecht
effaa6a79e [BUG] In v1.3.3 introduced a issue that always asking for admin, but should only ask if shortcut requires run as admin (#499), version 1.3.4.0 2023-08-28 14:06:55 +02:00
Markus Hofknecht
88d0abc548
Update README.md 2023-08-26 09:22:26 +02:00
Markus Hofknecht
851c0917ec Merge branch 'master' of https://github.com/Hofknecht/SystemTrayMenu 2023-08-25 23:41:29 +02:00
Markus Hofknecht
72a46d9d5b
Update README.md 2023-08-25 23:41:12 +02:00
Markus Hofknecht
7305a74a1b Update README.md 2023-08-25 23:41:11 +02:00
Markus Hofknecht
ea1b7eb9bb Update README.md 2023-08-25 23:17:02 +02:00
Markus Hofknecht
b80802bd6e [Feature] Framework Self-Contained & .Net 7 (#277), version 1.3.3.0 2023-08-25 22:41:32 +02:00
Markus Hofknecht
c1a821d03c [Feature] Framework Self-Contained, not more necessary to install .Net 6/7 sdk (#277), version 1.3.3.0 2023-08-25 22:20:35 +02:00
Markus Hofknecht
1cde65f3da [Feature] Framework Self-Contained, not more necessary to install .Net 6/7 sdk (#277), version 1.3.3.0 2023-08-25 22:03:17 +02:00
Markus Hofknecht
20d7f05edd [Feature] Framework Self-Contained, not more necessary to install .Net 6/7 sdk (#277), version 1.3.3.0 2023-08-25 21:56:56 +02:00
Markus Hofknecht
5fbba28fa6 [Feature] Framework Self-Contained, not more necessary to install .Net 6 sdk (#277), version 1.3.3.0 2023-08-25 21:47:18 +02:00
Markus Hofknecht
1b09ee8c9b [Feature] Framework Self-Contained, not more necessary to install .Net 6 sdk (#277), version 1.3.3.0 2023-08-25 20:20:15 +02:00
Markus Hofknecht
784c671a81 [Feature] Framework Self-Contained, not more necessary to install .Net 6 sdk (#277), version 1.3.3.0 2023-08-25 19:02:26 +02:00
Markus Hofknecht
cdb86df907 [BUG] Languages Filipino, Hebrew and Norwegian not working (#467), version 1.3.2.10 2023-08-25 15:22:25 +02:00
Markus Hofknecht
945114317f [BUG] ArgumentOutOfRangeException at KeyboardInput.SelectPreviousMenu (#477), version 1.3.2.9 2023-08-25 14:06:26 +02:00
Markus Hofknecht
b30b9193b9 [BUG] System.NullReferenceException WatcherProcessItem (#491), version 1.3.2.8 2023-08-25 13:09:01 +02:00
Markus Hofknecht
b2f3a938f1 README.md 2023-08-25 12:25:46 +02:00
Markus Hofknecht
432ca5f0e5 README.md 2023-08-25 12:24:36 +02:00
Markus Hofknecht
30d9dfe786 [BUG] Fix fast renames causes duplicated item (#497), version 1.3.2.7 2023-08-25 11:55:17 +02:00
Markus Hofknecht
f4290f4905 [BUG] Fix fast renames causes duplicated item (#497), version 1.3.2.7 2023-08-25 10:52:06 +02:00
Markus Hofknecht
9bc8847f3c [Feature] Add search bar right click 'Paste' (#466), version 1.3.2.7 2023-08-12 12:01:38 +02:00
Markus Hofknecht
7ea5b40248 [Feature] Show hint to find settings (#490), version 1.3.2.4 2023-08-12 11:09:06 +02:00
Markus Hofknecht
68258eb104 [BUG] Child processes won't elevate (#488), version 1.3.2.6 2023-08-12 10:48:09 +02:00
Markus Hofknecht
9683e5c461 [Feature] Icon-only view like "Quick Launch" (#495), version 1.3.2.5 2023-08-10 15:10:55 +02:00
Markus Hofknecht
00b4c5ddcc [Feature] Show hint to find settings and enable by default 'Show function key Settings' #490, version 1.3.2.4 2023-07-30 14:58:02 +02:00
Markus Hofknecht
e76790a5e1 [BUG] NullReferenceException StartWorker() (#469), version 1.3.2.3 2023-07-29 13:07:46 +02:00
Markus Hofknecht
2add7288ea
Update README.md 2023-07-29 12:22:27 +02:00
Markus Hofknecht
49acc2ae27
Update README.md 2023-07-29 10:54:28 +02:00
Markus Hofknecht
a296df3da4 Child processes won't elevate (#488), version 1.3.2.2 2023-06-24 20:01:04 +02:00
Markus Hofknecht
4cf4b980ea
Update README.md 2023-03-20 19:43:44 +01:00
Markus Hofknecht
1f9a2483f4 [Feature] Add search bar right click 'Paste' (#466), version 1.3.2.1 2023-03-20 14:21:22 +01:00
TGi
12b0a99e76
Update lang.zh-TW.resx (#471)
Update language file zh-TW
Co-authored-by: TGi <yrctw@csie.io>
2023-03-20 09:13:23 +01:00
Markus Hofknecht
6dd343e5f4 version 1.3.2.0 2022-10-24 20:01:04 +02:00
Markus Hofknecht
83944572da Merge branch 'master' of https://github.com/Hofknecht/SystemTrayMenu
# Conflicts:
#	README.md
2022-10-24 19:33:41 +02:00
Markus Hofknecht
a131b2a3dd [BUG] Fix NullReferenceException as GetShortcutFileNamePath (#463), version 1.3.2.0 2022-10-24 19:31:05 +02:00
Peter Kirmeier
aa3dcbc38c Adjusted username in Readme 2022-10-23 00:22:04 +02:00
Markus Hofknecht
1d4820c946 Not enough memory resources are available to process this command. (#442), version 1.3.1.9 2022-10-20 17:55:54 +02:00
Markus Hofknecht
87dbd64c73 [BUG] Blurry tray icon (#462), version 1.3.1.8 2022-10-20 17:46:55 +02:00
Markus Hofknecht
ad4942aad6 [BUG] Fix InvalidOperationException: No room is available to display rows. (#454), version 1.3.1.7 2022-10-08 12:50:47 +02:00
Markus Hofknecht
d01948563c [Feature] Sort method for grouping by file extensions (#450), version 1.3.1.6 2022-10-06 18:46:03 +02:00
Markus Hofknecht
52bff9dbf9 Merge branch 'master' of https://github.com/Hofknecht/SystemTrayMenu 2022-10-05 21:45:26 +02:00
Markus Hofknecht
56122d04d5 [Feature] Improve Sort method options translations (#450, #453), version 1.3.1.5 2022-10-05 21:45:15 +02:00
Markus Hofknecht
3415a92820 [Feature] Improve Sort method options translations (#450, #453), version 1.3.1.5 2022-10-05 21:35:06 +02:00
Markus Hofknecht
b50b122d8c [Feature] Option ResolveLinksToFolders default true (#453), version 1.3.1.5 2022-10-05 20:57:31 +02:00
Markus Hofknecht
18f1570d99 [Feature] Gamepad support (#451), version 1.3.1.4 2022-09-26 19:02:18 +02:00
Markus Hofknecht
5069e00eee [BUG] Language Italian and Irish (#446), version 1.3.1.3 2022-08-30 21:47:23 +02:00
Markus Hofknecht
0254018210 Language Italian and Irish (#446), version 1.3.1.3 2022-08-30 21:42:52 +02:00
Markus Hofknecht
9fa3b70e39 [BUG] Fix rename folder live updated (#445), version 1.3.1.2 2022-08-27 16:54:54 +02:00
Markus Hofknecht
729afdf67f [BUG] Search bar in sub directory for empty directories (#443), version 1.3.1.1 2022-08-27 15:14:29 +02:00
yrctw
fbbd0f1f54
Update lang.zh-TW for version 1.3.1.0 (#444)
* Create lang.zh-TW.resx

* Create lang.zh-TW.resx

* Create lang.zh-TW.resx

* Delete lang.zh-TW.Designer.cs

* Update language file zh-TW

* Update language file zh-TW

* Update language file zh-TW
2022-08-16 11:27:15 +02:00
Markus Hofknecht
3a37b16dfd version 1.3.1.0 2022-08-09 19:54:22 +02:00
Markus Hofknecht
e28c2724b1 [BUG] Fix CheckForUpdatesDialog dpi scaling for button (#439), version 1.3.0.19 2022-08-09 16:18:30 +02:00
Markus Hofknecht
fb0f07c19a [BUG] Fix CheckForUpdatesDialog dpi scaling for button (#439), version 1.2.0.19 2022-08-09 14:28:19 +02:00
Markus Hofknecht
effa675eac [BUG] Fix cross thread exceptoin at CheckForUpdates (#438), version 1.3.0.18 2022-08-09 14:15:56 +02:00
Markus Hofknecht
123bece791 [Feature] Adjust width when items deleted (#431), version 1.3.0.17 2022-08-07 17:49:42 +02:00
Markus Hofknecht
2662b7540d [BUG] 'Show directory title' incorrectly displayed when in 'relative directory' mode (#435), version 1.3.0.16 2022-08-06 00:09:19 +02:00
Markus Hofknecht
1a9da04f78 [BUG] Fix Duplicate file/folder name causes unexpected result on opening (#434), version 1.3.0.15 2022-08-05 22:19:55 +02:00
Markus Hofknecht
8f1d04a66c [Feature] Adjust height when items deleted or added (#430), version 1.3.0.14 2022-08-02 00:49:56 +02:00
Markus Hofknecht
14a83d7672 [Feature] Default sizes to match Windows File Explorer (#418), version 1.3.0.13 2022-08-01 22:22:48 +02:00
Markus Hofknecht
275b707bd2 [Feature] Adjust height when items deleted or added (#430), version 1.3.0.13 2022-08-01 21:42:27 +02:00
Markus Hofknecht
41d0c76e5a [Feature] Height and Width max in percentage (#426), version 1.3.0.12 2022-08-01 20:16:04 +02:00
Markus Hofknecht
a14d0296a3 [Feature] Make "draggable" zones for when Title bar is hidden (#428), version 1.3.0.11 2022-08-01 18:43:29 +02:00
Markus Hofknecht
480ad7b13b [BUG] Fix alt+f4 killing the menu but not the app (#427), version 1.3.0.10 2022-07-28 15:02:15 +02:00
Markus Hofknecht
b2ce80f376 [Feature] Height and Width max in percentage (#426), version 1.3.0.9 2022-07-28 13:00:49 +02:00
Markus Hofknecht
a14ea6fb32 [Feature] Default sizes to match Windows File Explorer (#418), version 1.3.0.8 2022-07-27 21:35:09 +02:00
Markus Hofknecht
663baa3f69 [BUG] Fix NullReferenceException at SettingsForm_FormClosed #425, version 1.3.0.7 2022-07-25 08:36:29 +02:00
Markus Hofknecht
88bdabf5f2 [Feature] Settings menu - Always on top behavior (#417), version 1.3.0.6 2022-07-18 23:05:15 +02:00
Markus Hofknecht
9c43fb181f [Feature] Adjust translation texts (#402), version 1.3.0.5 2022-07-18 22:21:37 +02:00
Markus Hofknecht
271a55d0ff Code cleanup, version 1.3.0.4 2022-07-17 01:11:32 +02:00
Markus Hofknecht
5007203094 [Feature] Add English GB language support (#402, #414), version 1.3.0.3 2022-07-16 23:27:24 +02:00
Markus Hofknecht
02b80946ce [Feature] Add English GB language support (#402, #414), version 1.3.0.3 2022-07-16 23:11:00 +02:00
yrctw
5cc40a1739
Update language file zh-TW (#411)
* Create lang.zh-TW.resx

* Create lang.zh-TW.resx

* Create lang.zh-TW.resx

* Delete lang.zh-TW.Designer.cs

* Update language file zh-TW

* Update language file zh-TW
2022-07-14 21:13:25 +02:00
Markus Hofknecht
05c381bb70 [Feature] Improve generate shortcut via drag drop url into menu (#412), version 1.3.0.2 2022-07-14 21:08:09 +02:00
Markus Hofknecht
2ef5922801 [BUG] Scrollbar visible in Options menu (#409), version 1.3.0.1 2022-07-14 21:06:51 +02:00
Markus Hofknecht
b30fdee093 [BUG] Scrollbar visible in Options menu (#409), version 1.3.0.1 2022-07-12 12:55:06 +02:00
Markus Hofknecht
22bfc56146 version 1.3.0.0 2022-07-10 18:01:30 +02:00
Markus Hofknecht
1fab03d91e version 1.3.0.0 2022-07-10 16:31:47 +02:00
Markus Hofknecht
919d88c7ed [Feature] Option which function keys are shown (#401), version 1.2.9.35 2022-07-10 15:39:27 +02:00
Markus Hofknecht
f2b34ea33f [Feature] Refresh root folder on change of contents (#330), version 1.2.9.34 2022-07-10 11:40:48 +02:00
Markus Hofknecht
70a70acd02 [Feature] Resize Optionsmenu (#406), version 1.2.9.33 2022-07-10 01:53:36 +02:00
Markus Hofknecht
d9ad6bdd7b [Feature] Resize Optionsmenu (#406), version 1.2.9.32 2022-07-10 01:46:18 +02:00
Markus Hofknecht
49766341c1 [Feature] Resize Optionsmenu (#406), version 1.2.9.31 2022-07-10 00:24:09 +02:00
Markus Hofknecht
3f23f0ebc2 [Feature] Resize Optionsmenu (#406), version 1.2.9.30 2022-07-09 22:10:53 +02:00
Markus Hofknecht
7c8926a29a [Bug] Fix scrollbar visibilty due to resize options menu #406 #407, version 1.2.9.29 2022-07-09 19:23:18 +02:00
Markus Hofknecht
2c9dc941de [Bug] Fix scrollbar visibilty due to resize options menu #406 #407, version 1.2.9.29 2022-07-09 19:11:10 +02:00
Markus Hofknecht
75b0648983 [Feature] Resize Optionsmenu (#406), version 1.2.9.28 2022-07-09 12:55:55 +02:00
Markus Hofknecht
aa91a4088f [Feature] Update function for the non Store Version (#185), version 1.2.9.27 2022-07-07 15:18:16 +02:00
Markus Hofknecht
5677320a54 [Feature] Update function for the non Store Version (#185), version 1.2.9.26 2022-07-05 21:53:38 +02:00
Markus Hofknecht
25ee3d2043 [BUG] Fix wrong error message and unwanted drag (#405), version 1.2.9.25 2022-06-26 10:56:47 +02:00
Markus Hofknecht
c0e962dd19 [Feature] Update turkish translations (#403), version 1.2.9.24 2022-06-23 20:34:45 +02:00
Markus Hofknecht
7211e4dff1 [Feature] Refresh root folder on change of contents (#330), version 1.2.9.23 2022-06-20 17:39:39 +02:00
Markus Hofknecht
1ec1842bb0 [Feature] Refresh root folder on change of contents (#330), version 1.2.9.22 2022-06-18 23:43:30 +02:00
Markus Hofknecht
e4c297e333 [Feature] Refresh root folder on change of contents (#330, #399, #400), version 1.2.9.21 2022-06-18 13:03:28 +02:00
Markus Hofknecht
7c253fa28a [Feature] Refresh root folder on change of contents (#330, #399, #400), version 1.2.9.20 2022-06-17 14:38:09 +02:00
Markus Hofknecht
bcb537d1ee [Feature] Options 'Sort by' (#399), 1.2.9.19 2022-06-13 01:32:36 +02:00
Markus Hofknecht
d6093e46b6 [BUG] Fix not scrolled to searched item (#398), version 1.2.9.18 2022-06-11 13:04:21 +02:00
Markus Hofknecht
7afcb95f5c [BUG] Fix not scrolled to searched item (#398), version 1.2.9.18 2022-06-11 12:45:46 +02:00
Markus Hofknecht
f5b29b43cd [BUG] Fix not scrolled to searched item (#398), version 1.2.9.18 2022-06-11 11:26:47 +02:00
Markus Hofknecht
48fcc40acd [Feature] Option 'Directory of Internet Shortcut Icons' (#397), version 1.2.9.17 2022-06-10 18:41:49 +02:00
Markus Hofknecht
532716ea12 [Feature] Show icons of *.ico files and links to *.ico files (#396), version 1.2.9.16 2022-06-09 19:55:13 +02:00
Markus Hofknecht
e5e1f848e4 [Feature] Sharper folder icon at 200% (#395), 1.2.9.15 2022-06-08 20:32:38 +02:00
Markus Hofknecht
c79cefd1c9 [Feature] Option 'Show link overlay' default false (#394), 1.2.9.14 2022-06-06 22:46:13 +02:00
Markus Hofknecht
9dbbaf1b02 [BUG] Fix drop shadow not working when UseFading false (#393), version 1.2.9.13 2022-06-06 14:46:34 +02:00
Markus Hofknecht
81dd170b62 [Feature] Option OpenDirectoryWithOneClick default false (#392), 1.2.9.12 2022-06-06 14:00:17 +02:00
Markus Hofknecht
76cde235c9 [Feature] Option to store log file at application directory instead into AppData (#371), version 1.2.9.11 2022-06-05 15:39:54 +02:00
Markus Hofknecht
c614cdf71b [Feature] Option to store log file at application directory instead into AppData (#371), version 1.2.9.11 2022-06-05 15:27:35 +02:00
Markus Hofknecht
d3c61273d3 [Feature] Add all missing languages automatically (#388), version 1.2.9.10 2022-06-05 11:36:48 +02:00
Markus Hofknecht
faa32f96a2 This reverts commit ac70e4369a. 2022-06-05 02:43:18 +02:00
Markus Hofknecht
ac70e4369a [BUG] TaskbarForm is activated even though it shouldn't be activated (#391), version 1.2.9.11 2022-06-04 18:37:57 +02:00
Markus Hofknecht
10b4c820ea Cleaner interface (#337, #380, #386, #390), version 1.2.9.10 2022-06-01 21:11:36 +02:00
Markus Hofknecht
a4836d10b9 Cleaner interface (#337, #380, #386, #390), version 1.2.9.10 2022-06-01 21:10:18 +02:00
Markus Hofknecht
4973212f15 Cleaner interface (#380, #386, #389), version 1.2.9.9 2022-05-31 23:23:26 +02:00
Markus Hofknecht
94dd3ddd0c [Feature] Add all missing languages automatically (#388), version 1.2.9.8 2022-05-29 20:42:42 +02:00
Markus Hofknecht
23f69c5fa8 [Feature] Add all missing languages automatically (#388), version 1.2.9.8 2022-05-29 16:54:46 +02:00
Markus Hofknecht
62c7883ed6 [Feature] Add all missing languages automatically (#388), version 1.2.9.8 2022-05-29 16:41:23 +02:00
Markus Hofknecht
c4debe75a8 [Feature] Add all missing languages automatically (#388), version 1.2.9.8 2022-05-29 14:47:53 +02:00
Markus Hofknecht
d61dffbbd4 [Feature] Add Slovak (#336), version 1.2.9.7 2022-05-29 11:08:47 +02:00
yrctw
0988b5c211
Create lang.zh-TW.resx (#387)
* Create lang.zh-TW.resx

* Create lang.zh-TW.resx

* Create lang.zh-TW.resx
2022-05-29 09:29:44 +02:00
Markus Hofknecht
07ed93d29e [Feature] Filter menu by file type (#384), version 1.2.9.5 2022-05-25 17:08:11 +02:00
Markus Hofknecht
e12842085e [Feature] Sort folder contents by date (#370), version 1.2.9.5 2022-05-02 20:29:39 +02:00
Markus Hofknecht
1172bdd114 [Feature] Option to configure drag settings (#377), version 1.2.9.5 2022-05-02 20:25:11 +02:00
Markus Hofknecht
587ebcfc90 [Feature] Option to configure drag settings (#377), version 1.2.9.5 2022-05-02 19:55:15 +02:00
Markus Hofknecht
756838ae85 [BUG] Fix Exception when PathDirectory empty and click "Change to relative folder" (#376), version 1.2.9.4 2022-04-30 11:51:50 +02:00
Markus Hofknecht
a16e8eb7c5 [BUG] Batchfiles are not executed from their storage directory (#372), 1.2.9.3 2022-04-10 23:20:14 +02:00
Markus Hofknecht
137a792431
Update README.md 2022-04-01 22:36:41 +02:00
Markus Hofknecht
cc502be893 Sort folder contents by date (#370), 1.2.9.2 2022-03-29 10:52:23 +02:00
Markus Hofknecht
9411780c48
Update README.md 2022-03-13 15:20:54 +01:00
Markus Hofknecht
e6d805145a
Update README.md 2022-03-13 13:29:19 +01:00
Markus Hofknecht
4427f2e9e5
Update README.md 2022-03-11 19:38:51 +01:00
Markus Hofknecht
7c20b6088d
Update README.md 2022-03-11 18:51:31 +01:00
Markus Hofknecht
73a5ea9cae [Feature] Improve icon (#337), version 1.2.9.1 2022-03-11 13:25:19 +01:00
Markus Hofknecht
1bbfe4354b
Update README.md 2022-03-11 13:10:31 +01:00
Markus Hofknecht
ca8523752e [Feature] Do not close menu when contextmenu copy item was used (#367), version 1.2.9.0 2022-02-27 16:44:08 +01:00
Markus Hofknecht
37ec270c25 [BUG] Restart automatically in case folder was empty (#366), 1.2.8.11 2022-02-26 10:39:00 +01:00
Markus Hofknecht
9234515fd9 [BUG] Folders to not extend over screen edge (#324), version 1.2.8.11 2022-02-22 16:52:02 +01:00
Markus Hofknecht
f4b540f339 [BUG] without fading - open menu - lose focus via win+e, then click get focus again, stays transparent (#342), version 1.2.8.10 2022-02-21 19:34:16 +01:00
Markus Hofknecht
3c0ed17988 [BUG] Fix issue when empty main menu and right click into it (#338, #361), version 1.2.8.9 2022-02-21 17:25:31 +01:00
Markus Hofknecht
a9f3308b27 [BUG] drag, scroll and search at same time (#335), version 1.2.8.8 2022-02-20 21:35:38 +01:00
Markus Hofknecht
aef79c431a [BUG] Do not spam logfile with access denied (#363), version 1.2.8.7 2022-02-20 18:43:57 +01:00
Markus Hofknecht
49eac15a87 [BUG] search text cut off (#362), version 1.2.8.6 2022-02-20 18:00:04 +01:00
Markus Hofknecht
a8643b00b1 Code Cleaning, version 1.2.8.5 2022-02-20 17:22:34 +01:00
Markus Hofknecht
eaf755ee81 [BUG] A generic error occurred in GDI+. at GetHicon Load_Tick (#361), version 1.2.8.4 2022-02-20 17:16:45 +01:00
Markus Hofknecht
7256910367 [Feature] Add 'Cancel' to quit (Bugsplat dialog) (#360), version 1.2.8.3 2022-02-19 13:59:51 +01:00
Markus Hofknecht
e6bd977f5c [BUG] Rare NullReferenceException at LoadSubMenuCompleted (#359), version 1.2.8.1 2022-02-18 16:02:16 +01:00
Markus Hofknecht
5eb471b077 [BUG] Application language does not change (#314, #329), version 1.2.8.0 2022-02-16 16:28:39 +01:00
Markus Hofknecht
afef0fa13f [BUG] Application language does not change (#314, #329), version 1.2.8.0 2022-02-16 16:04:54 +01:00
Markus Hofknecht
dfa24aadb1
Update README.md 2022-02-15 00:11:30 +01:00
Markus Hofknecht
74970ad7b7
Update README.md 2022-02-14 21:35:50 +01:00
Markus Hofknecht
38cca98da5
Update README.md 2022-02-14 21:26:20 +01:00
Markus Hofknecht
57c634149e
Update README.md 2022-02-14 20:58:17 +01:00
Markus Hofknecht
ab4c30bb15
Update README.md 2022-02-13 22:49:25 +01:00
Markus Hofknecht
f8f50d6c27 6.0.2 SDK update has broken WinForms apps (#328) 2022-02-13 22:20:13 +01:00
Markus Hofknecht
44db922628 version 1.2.7.0 2022-02-13 21:03:07 +01:00
Markus Hofknecht
cd508b7584 [BUG] Fix rare ArgumentOutOfRangeException TextBoxSearch_TextChanged (#327), version 1.2.7.0 2022-02-13 20:54:54 +01:00
Markus Hofknecht
411fc5ab07
Update README.md 2022-02-13 12:05:01 +01:00
Markus Hofknecht
c62670901e
Update README.md 2022-02-13 10:20:00 +01:00
Tanja Hofknecht
3a11885d72
Update README.md 2022-02-12 15:10:20 +01:00
Tanja Hofknecht
39a0e750bd
Update README.md 2022-02-12 12:58:42 +01:00
Markus Hofknecht
36ceb2b9af [BUG] "Pixel maximum menu width" not working as expected (#319), version 1.2.6.5 2022-02-11 20:48:11 +01:00
Markus Hofknecht
3ba03b8f9e [BUG] "Pixel maximum menu width" not working as expected (#319), version 1.2.6.4 2022-02-11 16:10:35 +01:00
Markus Hofknecht
ba69fe4df8 [Feature] Put all language files in sub directory (#314), version 1.2.6.3 2022-02-07 22:45:19 +01:00
Tanja Hofknecht
21b79ed0d4
Update README.md 2022-02-07 20:37:37 +01:00
Markus Hofknecht
3def2f40c0 [BUG] "Store config at the assembly location" not working for "protected folder locations" (#321), version 1.2.6.2 2022-02-07 20:22:38 +01:00
Markus Hofknecht
37355bdfe1 [BUG] ArgumentOutOfRangeException since version 1.2.3.6 (#322), version 1.2.6.1 2022-02-07 19:22:16 +01:00
Markus Hofknecht
021d1b2d85 [BUG] Default do a restart if any other instance is running (#320), version 1.2.6.0 2022-02-07 16:41:30 +01:00
Markus Hofknecht
b32f8aaffd [BUG] In version 1.2.4 FileNotFoundException when logfile not exists (#318), version 1.2.5.0 2022-02-07 07:26:59 +01:00
Markus Hofknecht
168c67e992 version 1.2.4.0 2022-02-06 16:12:46 +01:00
chip33
461b4a9d17
[BUG] Task View causes Explorer restart when SystemTrayMenu is open (#299, #317), version 1.2.3.9 2022-02-06 16:03:09 +01:00
Markus Hofknecht
4ddd229797
Update README.md 2022-02-06 16:00:51 +01:00
Markus Hofknecht
fc55672814 [Feature] Option 'Show in Taskbar' default true (#304, #299), version 1.2.3.9 2022-02-06 14:36:44 +01:00
Markus Hofknecht
1ff825f598
Update README.md 2022-02-06 12:43:32 +01:00
Markus Hofknecht
fffa4b62f5
Update README.md 2022-02-06 11:21:09 +01:00
Markus Hofknecht
206dc1c3df Update README.md 2022-02-05 14:36:17 +01:00
Tanja Hofknecht
fe2afeeb92
Update README.md 2022-02-05 13:18:15 +01:00
Markus Hofknecht
e214d71862 [Feature] Fix warnings (#299, #313), version 1.2.3.8 2022-02-05 13:13:11 +01:00
Markus Hofknecht
23848e8014 [Feature] Fix warnings (#313), version 1.2.3.8 2022-02-05 12:47:27 +01:00
Markus Hofknecht
4c927a4225 [Feature] Fix warning SYSLIB0014 - Replace WebClient with HttpClient (#313), version 1.2.3.8 2022-02-05 11:58:19 +01:00
Markus Hofknecht
2c4e9c656c [Feature] Clear logfile, keep only 2 mb (#312), version 1.2.3.7 2022-02-05 11:28:19 +01:00
Markus Hofknecht
86c0771c3e [Feature] Visual feedback during click (#311), version 1.2.3.6 2022-02-05 10:32:28 +01:00
Markus Hofknecht
95181d34a5 [Feature] Option to turn off menu fading (#310), version 1.2.3.5 2022-02-04 23:44:32 +01:00
Markus Hofknecht
f683797258 [Feature] Option to turn off menu fading (#310), version 1.2.3.5 2022-02-04 23:40:07 +01:00
Markus Hofknecht
4ad0e3c7a2 [Feature] Option to turn off menu fading (#310), version 2022-02-04 22:10:39 +01:00
Markus Hofknecht
754830eda4 [Feature] When loading aborted clear selected row (#309), version 1.2.3.3 2022-02-04 15:49:45 +01:00
Markus Hofknecht
16c25df2b0 [Feature] pos1 and end scroll to first or last (#308), version 1.2.3.2 2022-02-04 14:37:37 +01:00
Markus Hofknecht
282eede778 [BUG] Fix Disappears after relogin via rdp (#307), 1.2.3.1 2022-02-04 14:34:46 +01:00
Markus Hofknecht
d6fc6941db
Update README.md 2022-02-02 23:52:18 +01:00
Markus Hofknecht
7968ccf4a3 version 1.2.3.0 2022-01-30 17:23:29 +01:00
Markus Hofknecht
9e65ec3143 [BUG] Search reset sometimes not working (#303), version 1.2.2.12 2022-01-30 16:53:13 +01:00
Markus Hofknecht
968cf08a36
Update README.md 2022-01-30 16:10:17 +01:00
Markus Hofknecht
9725c092e9 [Feature] Option #276 as default / arg -r to restart (#305), version 1.2.2.11 2022-01-30 15:05:48 +01:00
Markus Hofknecht
c219720685 [Feature] Option 'Show in Taskbar' default false (#304), version 2022-01-30 14:34:53 +01:00
Markus Hofknecht
101df84e73 [BUG] Search reset sometimes not working (#303), version 1.2.2.9 2022-01-30 13:51:23 +01:00
Markus Hofknecht
27f2fed2f8 [BUG] DirectoryNotFoundException when GenerateDriveShortctus enabled and move root folder (#302), version 1.2.2.8 2022-01-30 11:26:40 +01:00
Markus Hofknecht
27a77d5b31 [Feature] Add 'Support SystemTrayMenu' to context menu (#301), version 1.2.2.7 2022-01-27 21:16:49 +01:00
Markus Hofknecht
6b972b52cd [Feature] Option OpenItemWithOneClick default true instead false (#300), version 1.2.2.6 2022-01-27 20:44:20 +01:00
Markus Hofknecht
a43c6e0d9c [BUG] Right click on items to choose "Send to" doesn't work (#225), version 1.2.2.5 2022-01-25 17:40:43 +01:00
Markus Hofknecht
ea1d6a0d19 [Feature] Option to set icon size (#297), version 1.2.2.4 2022-01-22 15:43:44 +01:00
Markus Hofknecht
2ec51aa3e2 [Feature] Submenus should appear on top of the menu above (#294), version 1.2.2.3 2022-01-15 14:44:56 +01:00
Markus Hofknecht
4bd9abe3f7 [Feature] Single click on directory should open windows explorer (#295), version 1.2.2.2 2022-01-15 12:07:02 +01:00
Markus Hofknecht
a98461a2c7 [BUG] File extension *.URL should not be shown (#296), version 1.2.2.1 2022-01-15 10:44:53 +01:00
Markus Hofknecht
80a13f67e1 [BUG] File extension *.URL should not be shown (#296), version 1.2.2.1 2022-01-15 10:43:27 +01:00
Dmitriy
07c5a8a585
[Feature] Update Russian localization (#293) 2022-01-11 19:32:01 +01:00
Markus Hofknecht
04fd61fade version 1.2.2.0 2022-01-09 17:44:15 +01:00
Markus Hofknecht
72b9f56e74 [Feature] Swipe scrolling on touchscreen (#275), version 1.2.1.4 2022-01-09 17:13:10 +01:00
Markus Hofknecht
8354e9fece [BUG] Fix Settingsform does not open when option disabled cache main menu (#291), version 1.2.1.3 2022-01-09 14:17:00 +01:00
Markus Hofknecht
2242f2bc34 [BUG] Scrollbar wrong with new option 'appear only when search' (#290, #289), version 1.2.1.2 2022-01-09 13:33:44 +01:00
Markus Hofknecht
5533a2d749 [BUG] Fix NullReferenceException Dgv_MouseDown (#288), version 1.2.1.1 2022-01-09 11:51:21 +01:00
Markus Hofknecht
0511468757 [Feature] Swipe scrolling on touchscreen (#275), version 1.2.1.1 2022-01-08 23:23:14 +01:00
Markus Hofknecht
09a6b8927f version 1.2.1.0 2022-01-08 13:39:19 +01:00
Markus Hofknecht
50d0dc09d1 [Feature] Additional folder contents - new option 'appear only when search' (#284), version 1.2.0.13 2022-01-08 11:49:34 +01:00
Markus Hofknecht
a4a13ecde5 [Feature] Additional folder contents - new option 'appear only when search' (#284), version 1.2.0.13 2022-01-08 11:42:31 +01:00
Markus Hofknecht
fe4e172b9b [Feature] Additional folder contents - new option 'appear only when search' (#284), version 1.2.0.13 2022-01-08 11:39:23 +01:00
Markus Hofknecht
4c600a8c66 [Feature] Executable to show the menu (#276), version 1.2.0.12 2022-01-07 18:24:17 +01:00
Markus Hofknecht
2659d19283 [Feature] Option to overwrite OS setting 'show hidden files' (#285), version 1.2.0.11 2022-01-07 15:49:33 +01:00
Markus Hofknecht
6d28822851 [BUG] Fix hidden files not shown transparent, version 1.2.0.10 2022-01-07 12:41:09 +01:00
Tanja Hofknecht
d2705342c0
Merge pull request #287 from Hofknecht/fix_bug_286
[BUG] Entering '[' in the search box results in an error #286
2022-01-06 14:22:49 +01:00
Peter Kirmeier
1c571291de [BUG] Entering '[' in the search box results in an error #286
Update search patterns to handle brackets correctly
2022-01-06 13:49:07 +01:00
Markus Hofknecht
7e1f646783 [Feature] Executable to show the menu (#276), version 1.2.0.9 2022-01-01 22:22:18 +01:00
Markus Hofknecht
057e2281a6 [Feature] Executable to show the menu (#276), version 1.2.0.9 2022-01-01 19:52:39 +01:00
Markus Hofknecht
18443a1682 [Feature] Executable to show the menu (#276), version 1.2.0.9 2022-01-01 19:10:20 +01:00
Markus Hofknecht
555996a3cb [BUG] File name is cut off if it contains a point (#282), version 1.2.0.8 2022-01-01 12:37:33 +01:00
Markus Hofknecht
c5d9b5aeda [Feature] Swipe scrolling on touchscreen (#275), version 1.2.0.7 2021-12-30 12:36:00 +01:00
Markus Hofknecht
543ff7bc29 [Feature] Swipe scrolling on touchscreen (#275), version 1.2.0.7 2021-12-30 11:56:34 +01:00
Markus Hofknecht
3ce1407477
Update README.md 2021-12-27 12:29:50 +01:00
Markus Hofknecht
a102c968f3 [Feature] Reset 'Custom location' after display changed event e.g. rdp and custom location not more within screen bounds (#269, #281), version 1.2.0.6 2021-12-27 12:22:52 +01:00
Markus Hofknecht
0d393684a0 [Feature] Do not block menu when settings form open (#280), 1.2.0.5 2021-12-27 07:36:07 +01:00
Markus Hofknecht
8394704fec [Feature] Do not block menu when settings form open (#280), 1.2.0.5 2021-12-27 07:35:39 +01:00
Markus Hofknecht
db46db002d [Feature] Remember Custom location between restarts (#278, #279), version 1.2.0.4 2021-12-27 06:31:23 +01:00
Markus Hofknecht
401e1329f1 [BUG] Fix FileNotFoundException - Option GenerateDriveShortcuts - in case Windows Defender triggered (#272), version 1.2.0.3 2021-12-27 06:28:46 +01:00
Markus Hofknecht
6d3832521f
Update README.md 2021-12-20 22:19:22 +01:00
Markus Hofknecht
d0dfc22a37
Update README.md 2021-12-20 20:11:19 +01:00
Markus Hofknecht
dbc7d83eed
Update README.md 2021-12-20 19:36:36 +01:00
Markus Hofknecht
1da1f489f4
Update README.md 2021-12-19 23:08:06 +01:00
Markus Hofknecht
94cf09f2b1
Update README.md 2021-12-19 22:57:12 +01:00
Markus Hofknecht
e8ca06e005
Update README.md 2021-12-18 11:46:43 +01:00
Markus Hofknecht
1aa6e7171d
Update README.md 2021-12-17 17:13:57 +01:00
Markus Hofknecht
3dbafe4075
Update README.md 2021-12-14 22:42:46 +01:00
Markus Hofknecht
961131e1c1
Update README.md 2021-12-14 18:41:09 +01:00
Markus Hofknecht
1e9d94e70f
Update README.md 2021-12-14 00:27:40 +01:00
Markus Hofknecht
6092273d52
Update README.md 2021-12-13 18:32:49 +01:00
Markus Hofknecht
6078d6cf8e
Update README.md 2021-12-13 17:31:26 +01:00
Markus Hofknecht
b224692eea
Update README.md 2021-12-13 13:19:18 +01:00
Markus Hofknecht
f80fbf6583
Update README.md 2021-12-12 17:02:44 +01:00
Markus Hofknecht
088412ddb4 [Feature] Show network shared directory with wrong flag super hidden (#271), version 1.2.0.2 2021-12-12 16:53:08 +01:00
Markus Hofknecht
31bae17632 [Feature] Show network shared directory with wrong flag super hidden (#271), version 1.2.0.2 2021-12-12 16:52:50 +01:00
Markus Hofknecht
76b04a0979 [Feature] Open menu preferably to the right (#262), version 1.2.0.1 2021-12-12 16:52:50 +01:00
Markus Hofknecht
424bd195eb
Update README.md 2021-12-12 15:07:08 +01:00
Markus Hofknecht
b4ad6b4ec1
Update README.md 2021-12-11 17:41:01 +01:00
Markus Hofknecht
1840afdd29
Update README.md 2021-12-11 17:22:17 +01:00
Markus Hofknecht
f2ac3fa66a
Update README.md 2021-12-11 16:10:04 +01:00
Markus Hofknecht
e81e955da9
Update README.md 2021-12-11 15:54:43 +01:00
Markus Hofknecht
af7591617e
Update README.md 2021-12-11 15:52:33 +01:00
Markus Hofknecht
adea63e089 version 1.2.0.0 2021-12-11 15:37:00 +01:00
Markus Hofknecht
a94bbb8bb5 [Feature] Adjust default options (#270), version 1.1.2.6 2021-12-11 14:34:28 +01:00
Markus Hofknecht
466151311d [Feature] UI design changes (#261), version 1.1.2.5 2021-12-10 22:10:31 +01:00
Markus Hofknecht
5c2a4c5bc2 [Feature] UI design changes (#261), version 1.1.2.5 2021-12-10 20:35:10 +01:00
Markus Hofknecht
ddb8241528
Update README.md 2021-12-10 15:33:36 +01:00
Markus Hofknecht
c0351a534d [Feature] Generate shortcuts to drives (#259), version 1.1.2.4 2021-12-10 15:20:24 +01:00
Markus Hofknecht
a846f1b5e4 [Features] (#260, #261, #262, #263, #264, #265, #266, #267), version 1.1.2.3 2021-12-09 21:12:56 +01:00
Markus Hofknecht
4fad5b17aa [Features] (#260, #261, #262, #263, #264, #265, #266, #267), version 1.1.2.2 2021-12-09 20:00:33 +01:00
Markus Hofknecht
8233667fd5 [Feature] Smooth round corners (#260), version 1.1.2.1 2021-12-05 17:04:48 +01:00
Markus Hofknecht
2c04a00307 [Feature] version 1.1.2.0 2021-12-05 16:35:48 +01:00
Markus Hofknecht
a5e68548d2 [Feature] Optimize code true (#258), version 1.1.1.6 2021-12-01 17:04:59 +01:00
Markus Hofknecht
7ebdb01934 [Feature] Show message if target not exists (#257), version 1.1.1.5" 2021-11-29 20:22:23 +01:00
Markus Hofknecht
ab91572424
Update README.md 2021-11-29 18:32:23 +01:00
Markus Hofknecht
5df5fd77cd [Feature] Add Persian (#256), version 1.1.1.4 2021-11-28 22:06:55 +01:00
Markus Hofknecht
b1226d15a1 [BUG] IndexOutOfRangeException when BrowserSelector as Standard browser (#237), version 1.1.1.3 2021-11-28 19:42:35 +01:00
Markus Hofknecht
b7a7364b40 [BUG] DragDrop URL to main menu not working (#254), version 1.1.1.2 2021-11-28 14:05:01 +01:00
Markus Hofknecht
976ad23fc3 [Feature] Remove option 'Update the position every time the menu opens', set it automatic (#253), version 1.1.1.1 2021-11-28 13:40:50 +01:00
Markus Hofknecht
6611d4a7e8
Update README.md 2021-11-28 00:49:33 +01:00
Markus Hofknecht
58ee1f86ec
Update README.md 2021-11-27 16:36:43 +01:00
Markus Hofknecht
8db78f8131 [Feature] version 1.1.1.0 2021-11-26 14:23:25 +01:00
Markus Hofknecht
c2d5ca5062 [Feature] When open during mainpreload open it afterwards (#251), version 1.1.0.8 2021-11-25 23:49:50 +01:00
Markus Hofknecht
7a0bfef122 [Feature] Drag menu to custom location (#249), version 1.1.0.7 2021-11-24 19:01:59 +01:00
Markus Hofknecht
79f0bbe740 [Feature] DragDrop a file into a application (#34), version 1.1.0.6 2021-11-24 00:22:38 +01:00
Markus Hofknecht
92d7e058a9 [Feature] Ignore open close events during main preload (#248), 1.1.0.6 2021-11-23 23:48:59 +01:00
Markus Hofknecht
898768ce71 [Feature] DragDrop a file into a application (#34), version 1.1.0.5 2021-11-23 23:08:29 +01:00
Markus Hofknecht
08c6b09b2f
Update README.md 2021-11-22 21:50:41 +01:00
Markus Hofknecht
bba1bedede [BUG] Lnk not not resolved if target contains a dot (.) (#247), version 1.1.0.4 2021-11-22 21:49:47 +01:00
Markus Hofknecht
83fa626b08
Update README.md 2021-11-22 20:03:46 +01:00
Markus Hofknecht
63a8300a68
Update README.md 2021-11-22 19:54:39 +01:00
Markus Hofknecht
a2accaa6e6
Update README.md 2021-11-22 19:37:09 +01:00
Dmitriy
3dc0b487f0
[Feature] Update Russian localization (#246) 2021-11-22 17:42:29 +01:00
Markus Hofknecht
cc9ebd4ecd [Feature] Add 'Settings' and 'Restart' to main menu (#244), version 1.1.0.3 2021-11-21 17:24:01 +01:00
Markus Hofknecht
8d0c0bb307 [Feature] Improve options Main menu location (#243), version 1.1.0.2 2021-11-20 21:34:20 +01:00
Markus Hofknecht
8021cbf02c [Feature] Improve options Main menu location (#243), version 1.1.0.2 2021-11-20 19:52:16 +01:00
Markus Hofknecht
c833817ab0 [Feature] Improve options Main menu location (#243), version 1.1.0.2 2021-11-20 19:45:41 +01:00
Markus Hofknecht
ac5a24dd3a [Feature] Improve options Main menu location (#243), version 1.1.0.2 2021-11-20 18:16:42 +01:00
Markus Hofknecht
b4f3f4f0a1 [BUG] Open CLSID key (GUID) shortcuts does not work (#242), version 1.1.0.1 2021-11-20 11:45:19 +01:00
Tanja Hofknecht
e5bb901a62
Update README.md 2021-11-19 19:49:39 +01:00
Markus Hofknecht
ff2ee98393 [Feature] Update to .NET 6 (#157), version 1.1.0.0 2021-11-19 16:25:37 +01:00
Markus Hofknecht
775500c5e4 [Feature] Update to .NET 6 (#157), version 1.1.0.0 2021-11-19 16:25:36 +01:00
Markus Hofknecht
9da079eea5
Update README.md 2021-11-19 16:17:28 +01:00
Markus Hofknecht
c073204193
Update README.md 2021-11-18 23:13:39 +01:00
Markus Hofknecht
c647cfef86 [Feature] Option to cache main menu (#232, #241), version 1.0.27.5 2021-11-18 21:12:03 +01:00
Markus Hofknecht
69e8cf4e6b [BUG] Fix a rare exception when moving trough menu by keyboard and execute file (#240), version 1.0.27.3 2021-11-18 00:52:24 +01:00
Markus Hofknecht
7f4266fffb [Feature] Taskbar with option 'Use Icon from folder' (#239), version 1.0.27.2 2021-11-17 23:47:26 +01:00
Markus Hofknecht
3dce420521 [Feature] Taskbar with option 'Use Icon from folder' (#239), version 1.0.27.2 2021-11-17 23:47:01 +01:00
Markus Hofknecht
fd3cbd1f69
Update README.md 2021-11-17 20:17:15 +01:00
Markus Hofknecht
8c32dcbeb1
Update README.md 2021-11-17 00:21:15 +01:00
Markus Hofknecht
78325f1c61 [Feature] Update to .NET 6 (#157), version 1.0.27.1 2021-11-17 00:13:46 +01:00
Markus Hofknecht
5830f530c2 [Feature] Update to .NET 6 (#157), version 1.0.27.1 2021-11-16 20:31:42 +01:00
Markus Hofknecht
675facc773 [Feature] Update to .NET 6 (#157), version 1.0.27.1 2021-11-16 20:30:19 +01:00
Markus Hofknecht
e45c97b4f8 [Feature] Update to .NET 6 (#157), version 1.0.27.1 2021-11-16 19:47:49 +01:00
Markus Hofknecht
1f84df7300 [BUG] Round Corners Fail to Show Outline (#238), version 1.0.26.2 2021-11-14 10:53:57 +01:00
Markus Hofknecht
53b2a5082d [Feature] Round corners (#236), version 1.0.26.1 2021-11-13 21:31:03 +01:00
Markus Hofknecht
9333577a4f
Update README.md 2021-11-13 20:37:17 +01:00
Markus Hofknecht
b70f966371 [Feature] Round corners (#236), version 1.0.26.0 2021-11-13 19:44:32 +01:00
Markus Hofknecht
f2303853a1 [Feature] Option to adjust row height (#235), version 1.0.25.10 2021-11-13 16:52:55 +01:00
Markus Hofknecht
a2507973db [Feature] Option to cache main menu (#232), version 1.0.25.9 2021-11-13 15:20:43 +01:00
Markus Hofknecht
7f65ef0e7f [Feature] Option to cache main menu (#232), version 1.0.25.9 2021-11-13 13:55:01 +01:00
Markus Hofknecht
fd554ec7ea [Feature] Search all throughout the subfolders (#211, #232), version 1.0.25.8 2021-11-13 08:18:33 +01:00
Markus Hofknecht
ec7a2467f1 [Feature] Search all throughout the subfolders (#211, #232), version 1.0.25.7 2021-11-12 13:44:02 +01:00
Markus Hofknecht
e4f3d6b67a [BUG] COMException (0x8000FFFF) when exit while folder dialog open (#233), version 1.0.25.6 2021-11-12 13:41:15 +01:00
Markus Hofknecht
6d8cf4da39 [Feature] Search all throughout the subfolders (#211, #232), version 1.0.25.5 2021-11-10 23:39:52 +01:00
Markus Hofknecht
fc353ce760 [BUG] Menu Spills Over Across Monitors (#231), version 1.0.25.4 2021-11-09 18:48:30 +01:00
Markus Hofknecht
a677a7a9b4 [Feature] Option to set a position of the main menu (#229), version 1.0.25.3 2021-11-09 18:35:29 +01:00
Markus Hofknecht
eee8b6b2f0 [Feature] Option to set a position of the main menu (#229), version 1.0.25.3 2021-11-09 18:31:29 +01:00
Markus Hofknecht
47f5c32655 [Feature] Option to use Taskbar item (#230), version 1.0.25.2 2021-11-09 17:41:48 +01:00
Markus Hofknecht
467afe57d1 [BUG] Do not restart if DisplayChange was due to STM open (#223), version 1.0.25.1 2021-11-09 17:41:48 +01:00
Markus Hofknecht
c84b7b3996
Update README.md 2021-11-03 10:29:31 +01:00
Markus Hofknecht
bc2899708a [Feature] When Tab to previous menu or press enter, select all text in search (#228), version 1.0.25.0 2021-11-01 13:32:06 +01:00
Markus Hofknecht
3ec663361f [Feature] When Tab to previous menu or press enter, select all text in search (#228), version 1.0.24.5 2021-10-28 19:42:13 +02:00
Markus Hofknecht
a140f13c23 [Feature] Stay open when 'Enter' pressed and reactivated within 200ms (#223, #226, #227), version 1.0.24.4 2021-10-28 16:29:04 +02:00
Markus Hofknecht
ceb128b702 [Feature] Stay open when 'Enter' pressed and reactivated within 200ms (#226), version 1.0.24.3 2021-10-26 22:09:40 +02:00
Markus Hofknecht
bf1629eb4c [Feature] Show item which was clicked for 250ms as loading (#224), version 1.0.24.2 2021-10-25 21:45:49 +02:00
Markus Hofknecht
9189b0629d [BUG] Do not restart if DisplayChange was due to STM open (#223), version 1.0.24.1 2021-10-25 18:55:43 +02:00
Markus Hofknecht
ae34aded47
Update README.md 2021-10-24 11:11:34 +02:00
Markus Hofknecht
cba17dd877 [BUG] Argument Handling (#222), version 1.0.24.0 2021-10-24 10:18:50 +02:00
Markus Hofknecht
f2366c0512 [BUG] Argument Handling #222 2021-10-24 09:46:38 +02:00
Markus Hofknecht
680c093659 Code Cleanup, version 1.0.23.0 2021-10-23 21:54:40 +02:00
Markus Hofknecht
ed362a8f9d Code Cleanup, version 1.0.23.0 2021-10-23 17:40:48 +02:00
Markus Hofknecht
d3e4c655ae Code Cleanup, version 1.0.23.0 2021-10-23 16:27:53 +02:00
Markus Hofknecht
7c234efad6 [BUG] Microsoft Store Autostart not working (#131), version 1.0.23.0 2021-10-23 13:45:22 +02:00
Markus Hofknecht
f5234bcec3 [BUG] Microsoft Store Autostart not working (#131), version 1.0.23.0 2021-10-23 11:59:39 +02:00
Markus Hofknecht
8a6101d329 [BUG] loading icons not updated after search and revert search (#221), version 1.0.22.2 2021-10-21 21:28:58 +02:00
Markus Hofknecht
8cff4365fc [BUG] Microsoft Store Autostart not working (#131), version 1.0.22.2 2021-10-21 20:51:24 +02:00
Markus Hofknecht
15cf58c28c [BUG] Icons of shortcuts not displayed correctly (#209, #218, #155), version 1.0.22.1 2021-10-21 20:25:13 +02:00
Markus Hofknecht
56ba365909 [BUG] Icons of shortcuts not displayed correctly (#209, #218, #155), version 1.0.22.0 2021-10-17 16:35:59 +02:00
Markus Hofknecht
a30778401e [BUG] Icons of shortcuts not displayed correctly (#209, #218, #155), version 1.0.21.4 2021-10-15 19:42:02 +02:00
Markus Hofknecht
a35ebda9d4 [Feature] Add Turkish (#220), version 1.0.21.3 2021-10-13 20:05:03 +02:00
Markus Hofknecht
155d0679a8 [Feature] Add Turkish (#220), version 1.0.21.3 2021-10-13 17:26:46 +02:00
Markus Hofknecht
49ea3cd7fe [BUG] Fix GDI Leak at open main menu (#219), version 1.0.21.3 2021-10-13 17:17:33 +02:00
Markus Hofknecht
1e330d40a8 [BUG] Icons of shortcuts not displayed correctly (#209, #218, #155), version 1.0.21.2 2021-10-13 17:13:11 +02:00
Markus Hofknecht
a16a3687fa [BUG] Settings dialog doesn't show all elements (#217), version 1.0.21.1 2021-10-11 19:06:26 +02:00
Markus Hofknecht
e9efc8cd0b [BUG] Settings dialog doesn't show all elements (#217), version 1.0.21.1 2021-10-11 18:58:10 +02:00
Markus Hofknecht
ee828466b2
Update README.md 2021-10-11 16:48:44 +02:00
Markus Hofknecht
f999504b9b
Update README.md 2021-10-10 20:24:20 +02:00
Markus Hofknecht
5382f9f5af
Update README.md
Update READMEN.md
2021-10-10 19:46:11 +02:00
Markus Hofknecht
b217c55bc1 [Feature] Fix warnings / clean code (#215), version 1.0.21.0 2021-10-10 18:01:29 +02:00
Markus Hofknecht
4919aa9afd [Feature] Fix warnings / clean code (#215), version 1.0.21.0 2021-10-10 17:33:54 +02:00
Markus Hofknecht
30312cc025 [Feature] Main Menu Loading icon and fix warning / clean code (#215), version 1.0.20.5 2021-10-10 16:44:06 +02:00
Markus Hofknecht
b4f3e4e6b5 [Feature] Mouse disturbing while using keys (#69), version 1.0.20.4 2021-10-10 14:49:03 +02:00
Markus Hofknecht
a8eec0d626 [BUG] Rare flickering in darkmode and open same item several times (#214), version 1.0.20.4 2021-10-10 14:47:15 +02:00
Markus Hofknecht
dc02aab5ab [BUG] NullReferenceException when missing default browser (#213), version 1.0.20.3 2021-10-09 23:24:13 +02:00
Markus Hofknecht
d669b15bde [Feature] Clear internal icon cache if too big (#207), version 1.0.20.2 2021-10-06 23:22:58 +02:00
Markus Hofknecht
de57fce8f3 [Feature] Settings add button to open root folder #206, version 1.0.20.1 2021-10-06 22:49:42 +02:00
Kristof Zerbe
450fbfddf3
[Feature] Settings add button to open root folder #206, version 1.0.20.1 2021-10-06 21:32:18 +02:00
Markus Hofknecht
6d563f63ec [Feature] Improved performance (#204), version 1.0.20.0 2021-10-05 23:02:08 +02:00
Markus Hofknecht
64e7e93167 [Feature] Improved performance (#204), version 1.0.20.0 2021-10-05 22:47:47 +02:00
Markus Hofknecht
693f196225 [Feature] Translate error shortcut not found (#203), version 1.0.19.6 2021-10-05 22:23:41 +02:00
Markus Hofknecht
8e83943044 [BUG] max menu handling (#202), version 1.0.19.5 2021-10-04 21:36:52 +02:00
Markus Hofknecht
0e7c59af0c [Feature] e.g. a folder "wwwwww" is cut off with "wwwww ..." but it should be shown in its entirety (#201), version 1.0.19.5 2021-10-04 21:31:22 +02:00
Markus Hofknecht
8d5690928f [Feature] if folder empty or not exists let user choose new root folder (#192), version 1.0.19.5 2021-10-04 17:47:39 +02:00
Markus Hofknecht
b5d35ea0d5 [Feature] Show loading menu (#161), version 1.0.19.4 2021-10-03 20:24:22 +02:00
Markus Hofknecht
a0cbd533cc [BUG] click chrome app not working / fix exe argument handling (#200), version 1.0.19.3 2021-10-02 20:55:37 +02:00
Markus Hofknecht
f323abca72 [BUG] click chrome app not working / fix exe argument handling (#200), version 1.0.19.3 2021-10-02 20:47:35 +02:00
Markus Hofknecht
520e056f6f [BUG] XmlException invalid character in config (#199), version 1.0.19.2 2021-10-01 20:24:51 +02:00
Markus Hofknecht
76492e11dd [BUG] Fix ArgumentException DirectoryNotFoundException (#198), version 1.0.19.1 2021-09-29 22:27:15 +02:00
Markus Hofknecht
bec9212d1b [BUG] Fix ArgumentException DirectoryNotFoundException (#198), version 1.0.19.1 2021-09-29 22:21:02 +02:00
Markus Hofknecht
e921e1dc7e [Feature] Select root folder by windows context menu (#195), version 1.0.19.0 2021-09-28 21:52:46 +02:00
Peter Kirmeier
99fb5a0c08 [Feature] Select root folder by windows context menu #195, 1.0.18.4 2021-09-27 17:42:18 +02:00
Markus Hofknecht
b1dd42518c [Feature] if folder empty or not exists let user choose new root folder #192, version 1.0.18.3 2021-09-24 15:58:37 +02:00
Markus Hofknecht
bf7a92f6b9 [Feature] Show menu faster (load icons in background and update UI later) #196, 1.0.18.2 2021-09-24 15:37:58 +02:00
Markus Hofknecht
cc70299972 [Feature] Show menu faster (load icons in background and update UI later) #196, 1.0.18.2 2021-09-23 22:53:46 +02:00
Markus Hofknecht
7c77c235c4 [Feature] Select root folder by windows context menu #195, version 1.0.18.1 2021-09-23 12:00:59 +02:00
Markus Hofknecht
ee6e7b65f4
Update README.md 2021-09-14 19:15:16 +02:00
Markus Hofknecht
e55ed9870d
Update README.md 2021-09-14 19:14:15 +02:00
Markus Hofknecht
2683a032c8
Update README.md 2021-09-14 19:10:13 +02:00
Markus Hofknecht
2c16ade92f Revert "Revert [Feature] Update to .NET 5 (#157), version 1.0.18.0" 2021-08-31 20:01:02 +02:00
Markus Hofknecht
6ca1cbaf5a Revert [Feature] Update to .NET 5 (#157), version 1.0.18.0 2021-08-31 19:46:09 +02:00
Markus Hofknecht
edd66fb68c [Feature] Update to .NET 5 (#157), version 1.0.18.0 2021-08-23 14:23:59 +02:00
Markus Hofknecht
48a896ada6 [Feature] Update to .NET 5 (#157), version 1.0.18.0 2021-08-20 12:01:34 +02:00
Markus Hofknecht
4b13cd7129
Update README.md 2021-08-17 12:26:24 +02:00
Markus Hofknecht
0783a12727 Customize colors of icons (#194), version 1.0.17.69 2021-08-17 10:21:00 +02:00
Markus Hofknecht
4f38568896 Customize colors of icons (#194), version 1.0.17.69 2021-08-16 11:48:51 +02:00
Markus Hofknecht
577b9b7d5d
Update README.md 2021-07-10 21:48:07 +02:00
Markus Hofknecht
35422f9ba5 Customize Color 'Border of Menu' (#191), version 1.0.17.68 2021-07-03 21:50:59 +02:00
Markus Hofknecht
8dd90406dc [Feature] Show how many folders and files a folder contains in searchbar (#189), version 1.0.17.67 2021-06-27 15:42:34 +02:00
Markus Hofknecht
0a310aadb0 [Feature] Show how many folders and files a folder contains in searchbar (#189), version 1.0.17.67 2021-06-27 14:44:12 +02:00
Markus Hofknecht
f430782d23 [Feature] High resolution compatibility (#188), version 1.0.17.66 2021-06-27 12:24:36 +02:00
Markus Hofknecht
d5af7893ce [Feature] Option to appear at mouse location (#135), version 1.0.17.66 2021-06-27 12:24:05 +02:00
Markus Hofknecht
97fda95805 [Feature] High resolution compatibility (#188), version 1.0.17.65 2021-06-27 11:35:07 +02:00
Markus Hofknecht
0f745cd586 [Feature] High resolution compatibility #188 2021-06-26 15:23:39 +02:00
Markus Hofknecht
74c68b6d46 Generate URL shortcut by drag drop url from browser to a menu (#190), version 1.0.17.64 2021-06-26 13:24:56 +02:00
Markus Hofknecht
99f4c6e46c [Feature] CodeBuity&Refactor (#49) 2021-06-18 19:31:40 +02:00
Markus Hofknecht
134536dbde
Update README.md 2021-06-10 21:46:24 +02:00
Markus Hofknecht
39fb41a9b9 [BUG] Pipeline fails at NuGet restore (#187) 2021-06-06 18:36:55 +02:00
Markus Hofknecht
bb89755da6 [BUG] Pipeline fails at NuGet restore (#187) 2021-06-06 17:21:46 +02:00
Markus Hofknecht
6e17a69cf9 Update azure-pipelines.yml for Azure Pipelines 2021-06-06 16:40:04 +02:00
Markus Hofknecht
70f95a0991 Update azure-pipelines.yml for Azure Pipelines 2021-06-06 16:28:16 +02:00
Markus Hofknecht
61fdad66d9 Update azure-pipelines.yml for Azure Pipelines 2021-06-06 16:10:02 +02:00
Markus Hofknecht
7ee83dd8c9 Update azure-pipelines.yml for Azure Pipelines 2021-06-06 15:37:36 +02:00
tanjalibertatis
7afcf103bf [Feature] Option to choose own icon (#176), version 1.0.17.63 2021-06-06 15:04:11 +02:00
Markus Hofknecht
17079c28e6 [Feature] Option to choose own icon (#176), version 1.0.17.63 2021-06-06 14:46:48 +02:00
Markus Hofknecht
fa12339659 [Feature] Show live option color changes (#184) 2021-06-06 13:15:01 +02:00
Markus Hofknecht
7310f4c3a5 [Feature] Custom Scrollbar (#183), [Feature] Show live option color changes (#184) 2021-06-06 12:53:02 +02:00
Markus Hofknecht
9ef27fd14e [Feature] Show live option color changes (#184) 2021-06-06 12:00:06 +02:00
tanjalibertatis
d644154c6d [Feature] Add Languages (#156) 2021-06-06 10:23:30 +02:00
Markus Hofknecht
95059eaab2 [Feature] Custom Scrollbar (#183), [Feature] Show live option color changes (#184), version 1.0.17.63 2021-06-05 23:57:36 +02:00
Markus Hofknecht
0fa8b4cf84 [Feature] Custom Scrollbar (#183), version 1.0.17.62 2021-06-05 11:52:33 +02:00
Markus Hofknecht
c5f4add68b [Feature] Custom Scrollbar (#183), version 1.0.17.61 2021-06-04 21:26:03 +02:00
Markus Hofknecht
47ccdd7d21 [Feature] Custom Scrollbar (#183), version 1.0.17.60 2021-06-04 19:08:21 +02:00
Markus Hofknecht
e6f496a72e [Feature] Custom Scrollbar (#183), version 1.0.17.59 2021-06-04 17:21:52 +02:00
Markus Hofknecht
81b4bd037b [Feature] Custom Scrollbar (#183), version 1.0.17.59 2021-06-04 17:15:18 +02:00
Markus Hofknecht
e10620f717 [Feature] Custom Scrollbar (#183), version 1.0.17.58 2021-06-03 15:00:53 +02:00
Markus Hofknecht
0fe947e4bf [Feature] Custom Scrollbar (#183), version 1.0.17.53 2021-06-03 12:53:17 +02:00
tanjalibertatis
3d22f41b2a [Feature] Add Languages (#156), version 1.0.17.56 2021-06-02 22:48:55 +02:00
tanjalibertatis
fd6c3d5be2 [Feature] Add Languages (#156), version 1.0.17.55 2021-06-01 23:19:23 +02:00
tanjalibertatis
f2cb823c54 [Feature] Add Languages (#156), version 1.0.17.54 2021-05-30 22:14:39 +02:00
tanjalibertatis
58d99bf793 [Feature] Add Languages (#156), version 1.0.17.53 2021-05-30 21:51:17 +02:00
Markus Hofknecht
fae8fec3c3
Update README.md
Update README.md
2021-05-29 21:34:32 +02:00
Markus Hofknecht
b12ca85489 [BUG] ArgumentOutOfRangeException & ObjectDisposedException at NativeWindow.Callback (#172, #173), version 1.0.17.52 2021-05-29 17:14:36 +02:00
Markus Hofknecht
642b3a731e [Feature] Option maximum menu height (#181), version 1.0.17.51 2021-05-29 09:46:54 +02:00
Markus Hofknecht
bdaebea71a [Feature] Option maximum menu height (#181), version 1.0.17.51 2021-05-29 09:45:59 +02:00
Markus Hofknecht
27a018e5d0 [BUG] Fix refresh when scroll with mousewheel (#180), version 1.0.17.50 2021-05-29 09:37:29 +02:00
Markus Hofknecht
366acc27ad [BUG] ArgumentOutOfRangeException & ObjectDisposedException at NativeWindow.Callback (#172, #173), version 1.0.17.49 2021-05-29 09:25:37 +02:00
Markus Hofknecht
0241f9c93c [BUG] Hide DataColumn (#179), version 1.0.17.48 2021-05-29 09:13:14 +02:00
Markus Hofknecht
c0d71c6948 [Feature] Option to appear at mouse location (#135), version 1.0.17.47 2021-05-28 23:23:05 +02:00
Markus Hofknecht
7b526db87e [Feature] Faster fading (#178), version 1.0.17.46 2021-05-28 22:45:32 +02:00
Markus Hofknecht
f4338c1c50 [Feature] Faster fading (#178), version 1.0.17.46 2021-05-28 22:24:09 +02:00
tanjalibertatis
bc89f2403a [Feature] Add Languages (#156), version 1.0.17.46 2021-05-28 21:37:39 +02:00
Markus Hofknecht
3e205d8479
Merge pull request #175 from HansieNL/master
Update lang.nl-NL.resx
2021-05-28 20:52:30 +02:00
Markus Hofknecht
0044b88a79 [BUG] ObjectDisposedException at Fading_Show User32ShowInactiveTopmost (#177) 2021-05-28 20:48:26 +02:00
HansieNL
d3318b65da
Update lang.nl-NL.resx
Some minor changes in translation.
2021-05-24 11:15:46 +02:00
Markus Hofknecht
30fe44980b
Update README.md 2021-05-21 17:52:50 +02:00
Markus Hofknecht
2ee8779652 [BUG] Fix ArgumentException: Illegal characters in path (#171), version 1.0.17.44 2021-05-21 15:48:00 +02:00
Markus Hofknecht
1aa3dec4d5 [BUG] Fix ArgumentException: Illegal characters in path (#171), version 1.0.17.44 2021-05-21 15:40:43 +02:00
Markus Hofknecht
027e51407c [BUG] Fix ArgumentException: Illegal characters in path (#171), version 1.0.17.43 2021-05-20 20:37:17 +02:00
tanjalibertatis
a972ae3b70 [Feature] Add Languages (#156), version 1.0.17.43 2021-05-16 22:19:00 +02:00
tanjalibertatis
bae4d72585 [Feature] Add Languages (#156), version 1.0.17.43 2021-05-16 21:45:24 +02:00
Markus Hofknecht
bd95ee3cd5 [Feature] Show loading as mouse cursor and extra loading menu (#161), version 1.0.17.42 2021-05-14 12:33:35 +02:00
Markus Hofknecht
85587370f8 [Feature] Show loading as mouse cursor and extra loading menu (#161), version 1.0.17.42 2021-05-14 12:22:15 +02:00
Markus Hofknecht
7bac914f51 [Feature] Fix ArgumentException: Illegal characters in path (#171) 2021-05-14 12:16:09 +02:00
Markus Hofknecht
4fefc4f253 [Feature] Show loading as mouse cursor and extra loading menu (#161), version 1.0.17.42 2021-05-13 15:20:40 +02:00
Markus Hofknecht
d4fb5afdc7 [Feature] Show link overlay for files like lnk & URL (#166), version 1.0.17.41
revert
Revision: a005582d5e
Author: Markus Hofknecht <Markus@Hofknecht.eu>
Date: 02.05.2021 10:05:33
Message:
[Feature] Show link overlay for files like lnk & URL (#166), version 1.0.17.26

----
Modified: DataClasses/RowData.cs
Modified: Utilities/File/FileLnk.cs
Modified: Utilities/File/IconReader.cs
2021-05-09 22:44:49 +02:00
Markus Hofknecht
cae6aa7922
Update README.md
Update README.md
2021-05-09 18:09:36 +02:00
tanjalibertatis
0374261774 [Feature] Add Languages (#156), version 1.0.17.40 2021-05-09 13:46:39 +02:00
Markus Hofknecht
600d73d40e [BUG] FileLoadException: Could not load file or assembly 'System.Drawing.Common, Version=4.0.2.2 (#165), version 1.0.17.40 2021-05-09 13:14:37 +02:00
Markus Hofknecht
313d786555 [Feature] USB - Portable user.config and relative folder (#158), version 1.0.17.39 2021-05-09 12:18:19 +02:00
Markus Hofknecht
5dd6828a31 [Feature] USB - Portable user.config and relative folder (#158), version 1.0.17.38 2021-05-09 11:42:57 +02:00
Markus Hofknecht
5db49aebd0 [Feature] USB - Portable user.config and relative folder (#158), version 1.0.17.38 2021-05-09 11:36:49 +02:00
Markus Hofknecht
b7038b5780 [Feature] USB - Portable user.config and relative folder (#158), version 1.0.17.37 2021-05-09 09:52:37 +02:00
Markus Hofknecht
94bc94b626 [Feature] Settings Customize Colors (#160), version 1.0.17.36 2021-05-06 23:31:47 +02:00
tanjalibertatis
ed8232b606 [Feature] Add Languages (#156), version 1.0.17.35 2021-05-05 21:27:54 +02:00
tanjalibertatis
65bf8e55e9 [Feature] Add Languages (#156), version 1.0.17.35 2021-05-05 21:25:38 +02:00
Markus Hofknecht
b7c1c4fe6e [Feature] Settings Customize Colors (#160), version 1.0.17.34 2021-05-04 21:59:55 +02:00
Markus Hofknecht
b871d422e4 [Feature] Settings Customize Colors (#160), version 1.0.17.33 2021-05-04 16:58:12 +02:00
Markus Hofknecht
5ae2ca2e26 [Feature] Settings Customize Colors (#160), version 1.0.17.33 2021-05-04 16:20:29 +02:00
Markus Hofknecht
70f98c97d8 [Feature] Settings Customize Colors (#160), version 1.0.17.33 2021-05-04 16:18:29 +02:00
Markus Hofknecht
519c9c8fe4
Update README.md 2021-05-03 22:59:48 +02:00
Markus Hofknecht
b9acf24962 [Feature] Settings option to close always directly stm after focus lost (#170), version 1.0.17.32 2021-05-02 15:21:07 +02:00
Markus Hofknecht
ec8f677593 [Feature] Refactor GetDefaultBrowserPath, ProcessStart (#169), version 1.0.17.31 2021-05-02 15:02:40 +02:00
Markus Hofknecht
c12ed3fc4e [Feature] Refactor GetDefaultBrowserPath, ProcessStart (#169), version 1.0.17.31 2021-05-02 15:01:31 +02:00
tanjalibertatis
7301b61a42 [Feature] Add Languages (#156), version 1.0.17.30 2021-05-02 14:51:16 +02:00
Markus Hofknecht
88cab02cf0 [Feature] Settings option to close always directly stm after a file or folder was clicked (default off) (#168), version 1.0.17.29 2021-05-02 13:12:18 +02:00
Peter Kirmeier
15609e7240 [Feature] Update target version to Win 10 2004
Minimum target version kept at Win 10 1809
2021-05-02 12:29:17 +02:00
Markus Hofknecht
2fd0270a1b [Feature] Improve performance case Lnk and host not exists (#167), version 1.0.17.27 2021-05-02 10:11:50 +02:00
Markus Hofknecht
a005582d5e [Feature] Show link overlay for files like lnk & URL (#166), version 1.0.17.26 2021-05-02 10:05:43 +02:00
Markus Hofknecht
c824c7a10b
Create FUNDING.yml 2021-05-01 21:15:30 +02:00
Markus Hofknecht
a12096ebfb
Update README.md
Update README.md
2021-04-29 10:51:08 +02:00
Markus Hofknecht
b316929135
Update README.md
Update README.md
2021-04-29 10:50:29 +02:00
Tanja Hofknecht
989ab5d3cc
Update README.md 2021-04-28 23:42:06 +02:00
tanjalibertatis
2b7f1740c4 [Feature] Add Languages (#156), version 1.0.17.26 2021-04-28 23:41:21 +02:00
Tanja Hofknecht
2b4cf855fc
Update README.md 2021-04-28 23:26:33 +02:00
Markus Hofknecht
7914950c9f [Feature] Option to appear at mouse location (#135), version 1.0.17.25 2021-04-28 22:58:33 +02:00
Tanja Hofknecht
49907998bb
Merge pull request #163 from igorruckert/patch-1
Create lang.pt-BR.resx
2021-04-28 21:32:12 +02:00
Igor Rückert
f17db4ed9f
Create lang.pt-BR.resx
Add Portuguese (Brazil) translation for SystemTrayMenu
2021-04-27 20:10:16 -03:00
Markus Hofknecht
66b14a5c7f
Update README.md
Update README.md
2021-04-28 00:29:02 +02:00
Markus Hofknecht
f5aece4741
Update README.md
Update README.md
2021-04-27 21:38:29 +02:00
Markus Hofknecht
ac28ab2b1c [BUG] Potential crash when icons cannot be loaded properly (#159), version 1.0.17.25 2021-04-27 20:35:48 +02:00
Markus Hofknecht
40ec45960b [Feature] Add Languages (#156), version 1.0.17.24 2021-04-27 20:07:46 +02:00
Markus Hofknecht
6c185f8767
Update README.md
Update README.md
2021-04-27 19:42:27 +02:00
Markus Hofknecht
2c7600661d
Update READMEN.md
Update READMEN.md
2021-04-27 19:39:13 +02:00
Markus Hofknecht
d64e3df694
Update README.md
Update README.md
2021-04-27 19:22:26 +02:00
Markus Hofknecht
bfea86fa6a
Update README.md
Update README.md
2021-04-27 19:15:42 +02:00
tanjalibertatis
721ee0579e [Feature] Add Languages (#156), version 1.0.17.24 2021-04-27 18:22:12 +02:00
Markus Hofknecht
1a06c0ebe7
Merge pull request #162 from HansieNL/master
Create lang.nl-NL.resx
2021-04-27 17:04:03 +02:00
HansieNL
4200cb9cc0
Create lang.nl-NL.resx
Language Dutch / Nederlands
2021-04-27 03:46:10 +02:00
tanjalibertatis
8678196326 [Feature] Add Languages (#156), version 1.0.17.23 2021-04-26 21:05:15 +02:00
Peter Kirmeier
f92de22b2b Renamed resource to match with actual file name 2021-04-26 20:06:27 +02:00
Peter Kirmeier
2cea00c942 Using cached icon instead of loading it multiple times from resources
This prevents a potential crash if lots of icons cannot be loaded
(see https://stackoverflow.com/questions/36446000/system-reflection-targetinvocationexception-in-resources-designer-vb )
Fixes #159
2021-04-26 19:41:04 +02:00
Markus Hofknecht
d894277d00 [Feature] Settings Menu (#154), version 1.0.17.22 2021-04-26 18:09:56 +02:00
Markus Hofknecht
1edfa657ae [Feature] Settings Menu (#154), version 1.0.17.21 2021-04-25 20:40:11 +02:00
Markus Hofknecht
11caf4ed91 [Feature] Settings Menu (#154), version 1.0.17.21 2021-04-25 16:22:53 +02:00
tanjalibertatis
afa153fd9b [Feature] Add Languages (#156), version 1.0.17.20 2021-04-24 23:03:24 +02:00
Markus Hofknecht
a175d6a718 Revert "[Feature] Read icons from system cache (#149), version 1.0.17.17", version 1.0.17.19
This reverts commit ecebddb0cb.
This reverts commit 010af66b42.
2021-04-24 11:32:30 +02:00
Markus Hofknecht
903322eaa1 [Feature] Enable WinL as modifier for hotkey and make Ctrl+WinL the new default hotkey (#153), version 1.0.17.18 2021-04-22 21:10:08 +02:00
Markus Hofknecht
ceb55191f2 [Feature] Enable WinL as modifier for hotkey and make Ctrl+WinL the new default hotkey (#153), version 1.0.17.18 2021-04-22 19:46:34 +02:00
Markus Hofknecht
ecebddb0cb [Feature] Read icons from system cache (#149), version 1.0.17.17 2021-04-22 19:32:25 +02:00
Markus Hofknecht
010af66b42 [Feature] Read icons from system cache (#149), version 1.0.17.17 2021-04-22 19:18:03 +02:00
Markus Hofknecht
a5e1ff4c25 [Feature] Migrate from deprecated FxCop analyzers to .NET analyzers (#152), version 1.0.17.16 2021-04-17 02:39:48 +02:00
Markus Hofknecht
83a9d29da2 [Feature] item starts with searchstring, sort it on top (#99), version 1.0.17.15 2021-04-16 23:14:39 +02:00
Markus Hofknecht
c1beb9ffa9 [Feature] Hide extensions for known file types, see folder options (#83), version 1.0.17.14 2021-04-16 21:30:45 +02:00
Markus Hofknecht
85fd0371b5 [Feature] Resolve path from which the settings are upgraded in logfile (#147), version 1.0.17.13 2021-04-16 18:59:35 +02:00
Markus Hofknecht
2932ddf1b6 [BUG] Fix catch EvaluateException SyntaxErrorException when search (#151), version 1.0.17.12 2021-04-16 18:39:21 +02:00
Markus Hofknecht
9aa75c72b8 [Feature] Add Spanish (#150), version 1.0.17.11 2021-04-15 19:01:23 +02:00
Markus Hofknecht
cdb5cb56f1 [Feature] item starts with searchstring, sort it on top (#99), version 1.0.17.10 2021-04-14 23:12:14 +02:00
Markus Hofknecht
c00c02356a [Feature] item starts with searchstring, sort it on top (#99), version 1.0.17.10 2021-04-14 21:06:54 +02:00
Markus Hofknecht
6162364577 [BUG] NullReferenceException when regedit key missing for darkmode (#148), version 1.0.17.9 2021-04-13 20:02:54 +02:00
Markus Hofknecht
f48306c27d
Update dotnetframework.yml 2021-04-13 18:39:53 +02:00
Markus Hofknecht
7ff2768f94
Update dotnetframework.yml 2021-04-13 18:28:55 +02:00
Markus Hofknecht
bddf4ccea1 [Feature] Add Language - Resources/lang.fr-FR.resx (#145), version 1.0.17.8 2021-04-13 17:50:31 +02:00
Markus Hofknecht
754c4a2218 [BUG] Prevent endless loop in case there would be a error in startup (#144), version 1.0.17.7 2020-11-08 10:07:55 +01:00
274 changed files with 61643 additions and 8343 deletions

79
.editorconfig Normal file
View file

@ -0,0 +1,79 @@
[*.cs]
# WFAC010: Unsupported high DPI configuration
dotnet_diagnostic.WFAC010.severity = silent
csharp_indent_labels = one_less_than_current
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
dotnet_diagnostic.SX1101.severity = warning
dotnet_diagnostic.SA1101.severity = silent
[*.{cs,vb}]
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = crlf
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion

12
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: Hofknecht # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View file

@ -7,10 +7,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Setup Nuget.exe
uses: warrenbuckley/Setup-Nuget@v1
uses: nuget/setup-nuget@v1
- name: Nuget Restore
run: nuget restore SystemTrayMenu.sln
- name: Setup MSBuild.exe
uses: warrenbuckley/Setup-MSBuild@v1
uses: microsoft/setup-msbuild@v1
- name: Build with MSBuild
run: msbuild SystemTrayMenu.sln -p:Configuration=Release

View file

@ -4,9 +4,11 @@
namespace SystemTrayMenu
{
using System;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
using SystemTrayMenu.Business;
using SystemTrayMenu.Helper.Updater;
using SystemTrayMenu.UserInterface;
using SystemTrayMenu.Utilities;
@ -15,32 +17,98 @@ namespace SystemTrayMenu
/// </summary>
internal class App : IDisposable
{
private readonly AppNotifyIcon menuNotifyIcon = new AppNotifyIcon();
private readonly Menus menus = new Menus();
private readonly AppNotifyIcon menuNotifyIcon = new();
private readonly Menus menus = new();
private readonly TaskbarForm taskbarForm = null;
public App()
{
AppRestart.BeforeRestarting += Dispose;
SystemEvents.DisplaySettingsChanged += AppRestart.ByDisplaySettings;
SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
menus.LoadStarted += menuNotifyIcon.LoadingStart;
menus.LoadStopped += menuNotifyIcon.LoadingStop;
menuNotifyIcon.Exit += Application.Exit;
menuNotifyIcon.Restart += AppRestart.ByMenuNotifyIcon;
menuNotifyIcon.Click += MenuNotifyIcon_Click;
void MenuNotifyIcon_Click()
{
menus.SwitchOpenClose(true);
}
menuNotifyIcon.OpenLog += Log.OpenLogFile;
menus.MainPreload();
if (Properties.Settings.Default.ShowInTaskbar)
{
taskbarForm = new TaskbarForm();
taskbarForm.FormClosed += TaskbarForm_FormClosed;
taskbarForm.Deactivate += SetStateNormal;
taskbarForm.Resize += SetStateNormal;
taskbarForm.Activated += TasbkarItemActivated;
}
DllImports.NativeMethods.User32ShowInactiveTopmost(taskbarForm);
if (Properties.Settings.Default.CheckForUpdates)
{
new Thread((obj) => GitHubUpdate.ActivateNewVersionFormOrCheckForUpdates(
showWhenUpToDate: false))
.Start();
}
}
public void Dispose()
{
SystemEvents.DisplaySettingsChanged -= AppRestart.ByDisplaySettings;
menus.Dispose();
menuNotifyIcon.Dispose();
if (taskbarForm?.InvokeRequired == true)
{
taskbarForm.Invoke(Dispose);
}
else
{
AppRestart.BeforeRestarting -= Dispose;
SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged;
menus.LoadStarted -= menuNotifyIcon.LoadingStart;
menus.LoadStopped -= menuNotifyIcon.LoadingStop;
menus.Dispose();
menuNotifyIcon.Click -= MenuNotifyIcon_Click;
menuNotifyIcon.OpenLog -= Log.OpenLogFile;
menuNotifyIcon.Dispose();
if (taskbarForm != null)
{
taskbarForm.FormClosed -= TaskbarForm_FormClosed;
taskbarForm.Deactivate -= SetStateNormal;
taskbarForm.Resize -= SetStateNormal;
taskbarForm.Activated -= TasbkarItemActivated;
taskbarForm.Dispose();
}
}
}
private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
menus.ReAdjustSizeAndLocation();
}
private void MenuNotifyIcon_Click()
{
menus.SwitchOpenClose(true);
}
private void TaskbarForm_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
/// <summary>
/// This ensures that next click on taskbaritem works as activate event/click event.
/// </summary>
private void SetStateNormal(object sender, EventArgs e)
{
if (Form.ActiveForm == taskbarForm)
{
taskbarForm.WindowState = FormWindowState.Normal;
}
}
private void TasbkarItemActivated(object sender, EventArgs e)
{
SetStateNormal(sender, e);
taskbarForm.Activate();
taskbarForm.Focus();
menus.SwitchOpenCloseByTaskbarItem();
}
}
}

View file

@ -17,36 +17,37 @@ namespace SystemTrayMenu.Handler
internal class KeyboardInput : IDisposable
{
private readonly Menu[] menus;
private readonly KeyboardHook hook = new KeyboardHook();
private readonly KeyboardHook hook = new();
private int iRowKey = -1;
private int iMenuKey = 0;
private int iMenuKey;
public KeyboardInput(Menu[] menus)
{
this.menus = menus;
}
internal event EventHandlerEmpty HotKeyPressed;
public event Action HotKeyPressed;
internal event EventHandlerEmpty ClosePressed;
public event Action ClosePressed;
internal event Action<DataGridView, int> RowSelected;
public event Action<DataGridView, int> RowSelected;
internal event Action<int, DataGridView> RowDeselected;
public event Action<DataGridView, int> RowDeselected;
internal event Action<DataGridView, int> EnterPressed;
public event Action<DataGridView, int> EnterPressed;
internal event EventHandlerEmpty Cleared;
public event Action Cleared;
internal bool InUse { get; set; } = false;
public bool InUse { get; set; }
public void Dispose()
{
hook.KeyPressed -= Hook_KeyPressed;
hook.Dispose();
}
internal void RegisterHotKey()
public void RegisterHotKey()
{
if (!string.IsNullOrEmpty(Properties.Settings.Default.HotKey))
{
@ -54,10 +55,6 @@ namespace SystemTrayMenu.Handler
{
hook.RegisterHotKey();
hook.KeyPressed += Hook_KeyPressed;
void Hook_KeyPressed(object sender, KeyPressedEventArgs e)
{
HotKeyPressed?.Invoke();
}
}
catch (InvalidOperationException ex)
{
@ -68,27 +65,38 @@ namespace SystemTrayMenu.Handler
}
}
internal void ResetSelectedByKey()
public void ResetSelectedByKey()
{
iRowKey = -1;
iMenuKey = 0;
}
internal void CmdKeyProcessed(object sender, Keys keys)
public void CmdKeyProcessed(object sender, Keys keys)
{
sender ??= menus[iMenuKey];
switch (keys)
{
case Keys.Enter:
SelectByKey(keys);
menus[iMenuKey]?.FocusTextBox();
break;
case Keys.Left:
SelectByKey(keys);
break;
case Keys.Right:
SelectByKey(keys);
break;
case Keys.Home:
case Keys.End:
case Keys.Up:
case Keys.Down:
case Keys.Left:
case Keys.Right:
case Keys.Escape:
case Keys.Alt | Keys.F4:
SelectByKey(keys);
break;
case Keys.Control | Keys.F:
Menu menu = menus[iMenuKey];
menu.FocusTextBox();
menus[iMenuKey]?.FocusTextBox();
break;
case Keys.Tab:
{
@ -105,7 +113,7 @@ namespace SystemTrayMenu.Handler
indexNew = indexMax;
}
menus[indexNew].FocusTextBox();
menus[indexNew]?.FocusTextBox();
}
break;
@ -124,21 +132,21 @@ namespace SystemTrayMenu.Handler
indexNew = 0;
}
menus[indexNew].FocusTextBox();
menus[indexNew]?.FocusTextBox();
}
break;
case Keys.Apps:
{
DataGridView dgv = menus[iMenuKey].GetDataGridView();
DataGridView dgv = menus[iMenuKey]?.GetDataGridView();
if (iRowKey > -1 &&
dgv.Rows.Count > iRowKey)
{
Point pt = dgv.GetCellDisplayRectangle(2, iRowKey, false).Location;
Point point = dgv.GetCellDisplayRectangle(2, iRowKey, false).Location;
RowData trigger = (RowData)dgv.Rows[iRowKey].Cells[2].Value;
MouseEventArgs mea = new MouseEventArgs(MouseButtons.Right, 1, pt.X, pt.Y, 0);
trigger.MouseDown(dgv, mea);
MouseEventArgs mouseEventArgs = new(MouseButtons.Right, 1, point.X, point.Y, 0);
trigger.MouseDown(dgv, mouseEventArgs);
}
}
@ -164,48 +172,30 @@ namespace SystemTrayMenu.Handler
}
}
/// <summary>
/// While menu is open user presses a key to search for specific entries.
/// </summary>
/// <param name="sender">not used.</param>
/// <param name="e">Key data of the pressed key.</param>
internal void KeyPress(object sender, KeyPressEventArgs e)
{
if (char.IsLetterOrDigit(e.KeyChar) ||
char.IsPunctuation(e.KeyChar) ||
char.IsWhiteSpace(e.KeyChar) ||
char.IsSeparator(e.KeyChar))
{
string letter = e.KeyChar.ToString(CultureInfo.InvariantCulture);
Menu menu = menus[iMenuKey];
menu.KeyPressedSearch(letter);
e.Handled = true;
}
}
internal void SearchTextChanging()
public void SearchTextChanging()
{
ClearIsSelectedByKey();
}
internal void SearchTextChanged(object sender, EventArgs e)
public void SearchTextChanged(Menu menu, bool isSearchStringEmpty)
{
Menu menu = (Menu)sender;
DataGridView dgv = menu.GetDataGridView();
if (dgv.Rows.Count > 0)
if (isSearchStringEmpty)
{
ClearIsSelectedByKey();
}
else if (dgv.Rows.Count > 0)
{
Select(dgv, 0, true);
}
}
internal void ClearIsSelectedByKey()
public void ClearIsSelectedByKey()
{
ClearIsSelectedByKey(iMenuKey, iRowKey);
}
internal void Select(DataGridView dgv, int i, bool refreshview)
public void Select(DataGridView dgv, int i, bool refreshview)
{
int newiMenuKey = ((Menu)dgv.TopLevelControl).Level;
if (i != iRowKey || newiMenuKey != iMenuKey)
@ -220,7 +210,11 @@ namespace SystemTrayMenu.Handler
{
DataGridViewRow row = dgv.Rows[i];
RowData rowData = (RowData)row.Cells[2].Value;
rowData.IsSelected = true;
if (rowData != null)
{
rowData.IsSelected = true;
}
if (refreshview)
{
row.Selected = false;
@ -229,6 +223,11 @@ namespace SystemTrayMenu.Handler
}
}
private void Hook_KeyPressed(object sender, KeyPressedEventArgs e)
{
HotKeyPressed?.Invoke();
}
private bool IsAnyMenuSelectedByKey(
ref DataGridView dgv,
ref Menu menuFromSelected,
@ -292,19 +291,29 @@ namespace SystemTrayMenu.Handler
switch (keys)
{
case Keys.Enter:
if (iRowKey > -1 &&
dgv.Rows.Count > iRowKey)
if (iRowKey > -1 && dgv.Rows.Count > iRowKey)
{
RowData trigger = (RowData)dgv.Rows[iRowKey].Cells[2].Value;
if (trigger.IsMenuOpen || !trigger.ContainsMenu)
{
trigger.MouseDown(dgv, null);
trigger.MouseClick(null, out bool toCloseByMouseClick);
trigger.DoubleClick(
new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0),
out bool toCloseByDoubleClick);
if (toCloseByMouseClick || toCloseByDoubleClick)
{
ClosePressed?.Invoke();
}
if (iRowKey > -1 && dgv.Rows.Count > iRowKey)
{
// Raise Dgv_RowPostPaint to show ProcessStarted
dgv.InvalidateRow(iRowKey);
}
}
else
{
RowDeselected(iRowBefore, dgvBefore);
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
EnterPressed.Invoke(dgv, iRowKey);
}
@ -315,7 +324,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatchedReverse(dgv, iRowKey) ||
SelectMatchedReverse(dgv, dgv.Rows.Count - 1))
{
RowDeselected(iRowBefore, dgvBefore);
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
@ -325,82 +334,59 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(iRowBefore, dgvBefore);
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
break;
case Keys.Home:
if (SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
break;
case Keys.End:
if (SelectMatchedReverse(dgv, dgv.Rows.Count - 1))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
break;
case Keys.Left:
int iMenuKeyNext = iMenuKey + 1;
if (isStillSelected)
bool nextMenuLocationIsLeft = menus[iMenuKey + 1] != null && menus[iMenuKey + 1].Location.X < menus[iMenuKey].Location.X;
bool previousMenuLocationIsRight = iMenuKey > 0 && menus[iMenuKey]?.Location.X < menus[iMenuKey - 1]?.Location.X;
if (nextMenuLocationIsLeft || previousMenuLocationIsRight)
{
if (menuFromSelected != null &&
menuFromSelected == menus[iMenuKeyNext])
{
dgv = menuFromSelected.GetDataGridView();
if (dgv.Rows.Count > 0)
{
iMenuKey += 1;
iRowKey = -1;
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(iRowBefore, dgvBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
}
SelectNextMenu(iRowBefore, ref dgv, dgvBefore, menuFromSelected, isStillSelected, ref toClear);
}
else
else if (iMenuKey > 0)
{
iRowKey = -1;
iMenuKey = menus.Where(m => m != null).Count() - 1;
if (menus[iMenuKey] != null)
{
dgv = menus[iMenuKey].GetDataGridView();
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(iRowBefore, dgvBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
SelectPreviousMenu(iRowBefore, ref menu, ref dgv, dgvBefore, ref toClear);
}
break;
case Keys.Right:
if (iMenuKey > 0)
bool nextMenuLocationIsRight = menus[iMenuKey + 1]?.Location.X > menus[iMenuKey]?.Location.X;
bool previousMenuLocationIsLeft = iMenuKey > 0 && menus[iMenuKey]?.Location.X > menus[iMenuKey - 1]?.Location.X;
if (nextMenuLocationIsRight || previousMenuLocationIsLeft)
{
if (menus[iMenuKey - 1] != null)
{
iMenuKey -= 1;
iRowKey = -1;
menu = menus[iMenuKey];
dgv = menu.GetDataGridView();
if (SelectMatched(dgv, dgv.SelectedRows[0].Index) ||
SelectMatched(dgv, 0))
{
RowDeselected(iRowBefore, dgvBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
SelectNextMenu(iRowBefore, ref dgv, dgvBefore, menuFromSelected, isStillSelected, ref toClear);
}
else
else if (iMenuKey > 0)
{
RowDeselected(iRowBefore, dgvBefore);
iMenuKey = 0;
iRowKey = -1;
toClear = true;
Cleared?.Invoke();
SelectPreviousMenu(iRowBefore, ref menu, ref dgv, dgvBefore, ref toClear);
}
break;
case Keys.Escape:
RowDeselected(iRowBefore, dgvBefore);
case Keys.Alt | Keys.F4:
RowDeselected(dgvBefore, iRowBefore);
iMenuKey = 0;
iRowKey = -1;
toClear = true;
@ -412,7 +398,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey, keyInput) ||
SelectMatched(dgv, 0, keyInput))
{
RowDeselected(iRowBefore, null);
RowDeselected(null, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
@ -422,7 +408,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey, keyInput) ||
SelectMatched(dgv, 0, keyInput))
{
RowDeselected(iRowBefore, null);
RowDeselected(null, iRowBefore);
SelectRow(dgv, iRowKey);
}
else
@ -441,6 +427,77 @@ namespace SystemTrayMenu.Handler
}
}
private void SelectPreviousMenu(int iRowBefore, ref Menu menu, ref DataGridView dgv, DataGridView dgvBefore, ref bool toClear)
{
if (iMenuKey > 0)
{
if (menus[iMenuKey - 1] != null)
{
iMenuKey -= 1;
iRowKey = -1;
menu = menus[iMenuKey];
dgv = menu.GetDataGridView();
if ((dgv.SelectedRows.Count > 0 &&
SelectMatched(dgv, dgv.SelectedRows[0].Index)) ||
SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
}
else
{
RowDeselected(dgvBefore, iRowBefore);
iMenuKey = 0;
iRowKey = -1;
toClear = true;
Cleared?.Invoke();
}
}
private void SelectNextMenu(int iRowBefore, ref DataGridView dgv, DataGridView dgvBefore, Menu menuFromSelected, bool isStillSelected, ref bool toClear)
{
int iMenuKeyNext = iMenuKey + 1;
if (isStillSelected)
{
if (menuFromSelected != null &&
menuFromSelected == menus[iMenuKeyNext])
{
dgv = menuFromSelected.GetDataGridView();
if (dgv.Rows.Count > 0)
{
iMenuKey += 1;
iRowKey = -1;
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
}
}
else
{
iRowKey = -1;
iMenuKey = menus.Where(m => m != null).Count() - 1;
if (menus[iMenuKey] != null)
{
dgv = menus[iMenuKey].GetDataGridView();
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
}
}
private void SelectRow(DataGridView dgv, int iRowKey)
{
InUse = true;
@ -521,9 +578,13 @@ namespace SystemTrayMenu.Handler
if (dgv.Rows.Count > rowIndex)
{
DataGridViewRow row = dgv.Rows[rowIndex];
RowData rowData = (RowData)row.Cells[2].Value;
rowData.IsSelected = false;
row.Selected = false;
RowData rowData = (RowData)row.Cells[2].Value;
if (rowData != null)
{
rowData.IsSelected = false;
rowData.IsClicking = false;
}
}
}
}

File diff suppressed because it is too large Load diff

269
Business/MenusHelpers.cs Normal file
View file

@ -0,0 +1,269 @@
// <copyright file="MenusHelpers.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Business
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using SystemTrayMenu.DataClasses;
using SystemTrayMenu.Helper;
using SystemTrayMenu.Utilities;
internal static class MenusHelpers
{
internal static void GetItemsForMainMenu(BackgroundWorker worker, string path, ref MenuData menuData)
{
menuData.IsNetworkRoot = FileLnk.IsNetworkRoot(path);
if (menuData.IsNetworkRoot)
{
GetNetworkRootDirectories(path, ref menuData);
}
else
{
GetDirectories(worker, path, ref menuData);
GetFiles(worker, path, ref menuData);
}
}
internal static void GetAddionalItemsForMainMenu(ref MenuData menuData)
{
if (menuData.Level != 0)
{
return;
}
foreach (var path in GetAddionalPathsForMainMenu())
{
GetDirectoriesAndFilesRecursive(ref menuData, path.Path, path.OnlyFiles, path.Recursive);
}
}
internal static IEnumerable<(string Path, bool Recursive, bool OnlyFiles)> GetAddionalPathsForMainMenu()
{
foreach (string pathAndRecursivString in Properties.Settings.Default.PathsAddToMainMenu.Split(@"|"))
{
if (string.IsNullOrEmpty(pathAndRecursivString))
{
continue;
}
string pathAddForMainMenu = pathAndRecursivString.Split("recursiv:")[0].Trim();
bool recursive = pathAndRecursivString.Split("recursiv:")[1].StartsWith("True");
bool onlyFiles = pathAndRecursivString.Split("onlyFiles:")[1].StartsWith("True");
yield return (Path: pathAddForMainMenu, Recursive: recursive, OnlyFiles: onlyFiles);
}
}
internal static void ReadHiddenAndReadIcons(BackgroundWorker worker, ref MenuData menuData)
{
List<RowData> rowDatasToRemove = new();
foreach (RowData rowData in menuData.RowDatas)
{
if (worker?.CancellationPending == true)
{
return;
}
if (!menuData.IsNetworkRoot && FolderOptions.IsHidden(rowData))
{
rowDatasToRemove.Add(rowData);
continue;
}
rowData.ReadIcon(true);
}
menuData.RowDatas = menuData.RowDatas.Except(rowDatasToRemove).ToList();
}
internal static void CheckIfValid(ref MenuData menuData)
{
if (menuData.Validity == MenuDataValidity.Undefined)
{
if (menuData.RowDatas.Count == 0)
{
menuData.Validity = MenuDataValidity.Empty;
}
else
{
menuData.Validity = MenuDataValidity.Valid;
}
}
}
internal static void SortItemsWhenValid(ref MenuData menuData)
{
if (menuData.Validity != MenuDataValidity.Valid)
{
return;
}
menuData.RowDatas = SortItems(menuData.RowDatas);
}
internal static List<RowData> SortItems(List<RowData> rowDatas)
{
if (Properties.Settings.Default.SortByTypeAndNameWindowsExplorerSort)
{
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
.ThenBy(x => x.Text, new WindowsExplorerSort()).ToList();
}
else if (Properties.Settings.Default.SortByTypeAndDate)
{
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
.ThenByDescending(x => x.FileInfo.LastWriteTime).ToList();
}
else if (Properties.Settings.Default.SortByFileExtensionAndName)
{
rowDatas = rowDatas.OrderBy(x => x.FileExtension).ThenBy(x => x.Text).ToList();
}
else if (Properties.Settings.Default.SortByName)
{
rowDatas = rowDatas.OrderBy(x => x.Text).ToList();
}
else if (Properties.Settings.Default.SortByDate)
{
rowDatas = rowDatas.OrderByDescending(x => x.FileInfo.LastWriteTime).ToList();
}
return rowDatas;
}
private static void GetNetworkRootDirectories(string path, ref MenuData menuData)
{
Process cmd = new();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
try
{
bool resolvedSomething = false;
cmd.Start();
cmd.StandardInput.WriteLine($"net view {path}");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
string output = cmd.StandardOutput.ReadToEnd();
cmd.WaitForExit();
cmd.Close();
List<string> lines = output
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
if (lines.Count > 8)
{
foreach (string line in lines.Skip(6).SkipLast(2))
{
int indexOfFirstSpace = line.IndexOf(" ", StringComparison.InvariantCulture);
if (indexOfFirstSpace > 0)
{
string directory = Path.Combine(path, line[..indexOfFirstSpace]);
menuData.RowDatas.Add(new RowData(true, false, true, menuData.Level, directory));
resolvedSomething = true;
}
}
}
if (!resolvedSomething)
{
Log.Info($"Could not resolve network root folder: {path} , output:{output}");
}
}
catch (Exception ex)
{
Log.Warn($"path:'{path}'", ex);
if (ex is UnauthorizedAccessException)
{
menuData.Validity = MenuDataValidity.NoAccess;
}
}
}
private static void GetDirectories(BackgroundWorker worker, string path, ref MenuData menuData)
{
try
{
foreach (var directory in Directory.GetDirectories(path))
{
if (worker?.CancellationPending == true)
{
return;
}
menuData.RowDatas.Add(new RowData(true, false, false, menuData.Level, directory));
}
}
catch (Exception ex)
{
Log.Warn($"path:'{path}'", ex);
if (ex is UnauthorizedAccessException)
{
menuData.Validity = MenuDataValidity.NoAccess;
}
}
}
private static void GetFiles(BackgroundWorker worker, string path, ref MenuData menuData)
{
try
{
foreach (string file in DirectoryBySearchPattern.GetFiles(path, Config.SearchPattern))
{
if (worker?.CancellationPending == true)
{
return;
}
menuData.RowDatas.Add(new RowData(false, false, false, menuData.Level, file));
}
}
catch (Exception ex)
{
Log.Warn($"path:'{path}'", ex);
if (ex is UnauthorizedAccessException)
{
menuData.Validity = MenuDataValidity.NoAccess;
}
}
}
private static void GetDirectoriesAndFilesRecursive(
ref MenuData menuData,
string path,
bool onlyFiles,
bool recursiv)
{
try
{
foreach (string file in DirectoryBySearchPattern.GetFiles(path, Config.SearchPattern))
{
menuData.RowDatas.Add(new RowData(false, true, false, menuData.Level, file));
}
foreach (string directory in Directory.GetDirectories(path))
{
if (!onlyFiles)
{
menuData.RowDatas.Add(new RowData(true, true, false, menuData.Level, directory));
}
if (recursiv)
{
GetDirectoriesAndFilesRecursive(ref menuData, directory, onlyFiles, recursiv);
}
}
}
catch (Exception ex)
{
Log.Warn($"GetDirectoriesAndFilesRecursive path:'{path}'", ex);
}
}
}
}

View file

@ -6,45 +6,45 @@ namespace SystemTrayMenu
{
using System;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using SystemTrayMenu.Utilities;
internal static class Program
{
private static bool isStartup = true;
[STAThread]
private static void Main()
private static void Main(string[] args)
{
try
{
Log.Initialize();
SingleAppInstance.Initialize();
Translator.Initialize();
Config.SetFolderByWindowsContextMenu(args);
Config.LoadOrSetByUser();
Config.Initialize();
PrivilegeChecker.Initialize();
Config.UpgradeIfNotUpgraded();
if (Config.LoadOrSetByUser())
if (SingleAppInstance.Initialize())
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += ThreadException;
static void ThreadException(object s, ThreadExceptionEventArgs t)
{
AskUserSendError(t.Exception);
}
Application.ThreadException += Application_ThreadException;
Scaling.Initialize();
FolderOptions.Initialize();
using (new App())
{
isStartup = false;
Log.WriteApplicationRuns();
Application.Run();
}
}
Application.ThreadException -= Application_ThreadException;
Config.Dispose();
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // => Represents ThreadException during attached to process
{
AskUserSendError(ex);
}
@ -52,24 +52,36 @@ namespace SystemTrayMenu
{
Log.Close();
}
}
static void AskUserSendError(Exception ex)
private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
AskUserSendError(e.Exception);
}
private static void AskUserSendError(Exception ex)
{
Log.Error("Application Crashed", ex);
DialogResult dialogResult = MessageBox.Show(
"A problem has been encountered and the application needs to restart. " +
"Reporting this error will help us make our product better. " +
"Press 'Yes' to open your standard email app (emailto: Markus@Hofknecht.eu). " + Environment.NewLine +
@"You can also create an issue manually here https://github.com/Hofknecht/SystemTrayMenu/issues" + Environment.NewLine +
"Press 'Cancel' to quit SystemTrayMenu.",
"SystemTrayMenu Crashed",
MessageBoxButtons.YesNoCancel);
if (dialogResult == DialogResult.Yes)
{
Log.Error("Application Crashed", ex);
if (MessageBox.Show(
"A problem has been encountered and the application needs to restart. " +
"Reporting this error will help us make our product better. " +
"Press yes to open your standard email app.",
"SystemTrayMenu BugSplat",
MessageBoxButtons.YesNo) == DialogResult.Yes)
{
Log.ProcessStart("mailto:" + "markus@hofknecht.eu" +
"?subject=SystemTrayMenu Bug reported " +
Assembly.GetEntryAssembly().GetName().Version +
"&body=" + ex.ToString());
}
Log.ProcessStart("mailto:" + "markus@hofknecht.eu" +
"?subject=SystemTrayMenu Bug reported " +
Assembly.GetEntryAssembly().GetName().Version +
"&body=" + ex.ToString());
}
if (!isStartup && dialogResult != DialogResult.Cancel)
{
AppRestart.ByThreadException();
}
}

View file

@ -10,7 +10,7 @@ namespace SystemTrayMenu.Handler
internal class WaitLeave : IDisposable
{
private readonly Timer timerLeaveCheck = new Timer();
private readonly Timer timerLeaveCheck = new();
public WaitLeave(int timeUntilTriggered)
{
@ -18,10 +18,11 @@ namespace SystemTrayMenu.Handler
timerLeaveCheck.Tick += TimerLeaveCheckTick;
}
public event EventHandlerEmpty LeaveTriggered;
public event Action LeaveTriggered;
public void Dispose()
{
timerLeaveCheck.Tick -= TimerLeaveCheckTick;
timerLeaveCheck.Dispose();
}

View file

@ -13,19 +13,19 @@ namespace SystemTrayMenu.Handler
internal class WaitToLoadMenu : IDisposable
{
private readonly Timer timerStartLoad = new Timer();
private DataGridView dgv = null;
private int rowIndex = 0;
private DataGridView dgvTmp = null;
private int rowIndexTmp = 0;
private readonly Timer timerStartLoad = new();
private DataGridView dgv;
private int rowIndex;
private DataGridView dgvTmp;
private int rowIndexTmp;
private int mouseMoveEvents = 0;
private int mouseMoveEvents;
private DateTime dateTimeLastMouseMoveEvent = DateTime.Now;
private bool checkForMouseActive = true;
internal WaitToLoadMenu()
{
timerStartLoad.Interval = 200;
timerStartLoad.Interval = Properties.Settings.Default.TimeUntilOpens;
timerStartLoad.Tick += WaitStartLoad_Tick;
}
@ -33,14 +33,15 @@ namespace SystemTrayMenu.Handler
internal event Action<int> CloseMenu;
internal event EventHandlerEmpty StopLoadMenu;
internal event Action StopLoadMenu;
internal event Action<DataGridView, int> MouseEnterOk;
internal bool MouseActive { get; set; } = false;
internal bool MouseActive { get; set; }
public void Dispose()
{
timerStartLoad.Tick -= WaitStartLoad_Tick;
timerStartLoad.Stop();
timerStartLoad.Dispose();
dgv?.Dispose();
@ -92,7 +93,7 @@ namespace SystemTrayMenu.Handler
}
}
internal void RowDeselected(int rowIndex, DataGridView dgv)
internal void RowDeselected(DataGridView dgv, int rowIndex)
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
@ -129,7 +130,7 @@ namespace SystemTrayMenu.Handler
{
if (!MouseActive)
{
if (mouseMoveEvents > 3)
if (mouseMoveEvents > 6)
{
MouseActive = true;
if (dgvTmp != null && !dgvTmp.IsDisposed)
@ -168,19 +169,17 @@ namespace SystemTrayMenu.Handler
{
RowData rowData = (RowData)dgv.Rows[rowIndex].Cells[2].Value;
Menu menu = (Menu)dgv.FindForm();
rowData.MenuLevel = menu.Level;
rowData.Level = menu.Level;
if (rowData.ContainsMenu)
{
CloseMenu.Invoke(rowData.MenuLevel + 2);
}
else
{
CloseMenu.Invoke(rowData.MenuLevel + 1);
CloseMenu.Invoke(rowData.Level + 2);
}
CloseMenu.Invoke(rowData.Level + 1);
if (!rowData.IsContextMenuOpen &&
rowData.ContainsMenu &&
rowData.MenuLevel + 1 < MenuDefines.MenusMax)
rowData.Level + 1 < MenuDefines.MenusMax)
{
StartLoadMenu.Invoke(rowData);
}
@ -193,7 +192,11 @@ namespace SystemTrayMenu.Handler
this.dgv = dgv;
this.rowIndex = rowIndex;
RowData rowData = (RowData)dgv.Rows[rowIndex].Cells[2].Value;
rowData.IsSelected = true;
if (rowData != null)
{
rowData.IsSelected = true;
}
dgv.Rows[rowIndex].Selected = false;
dgv.Rows[rowIndex].Selected = true;
}
@ -203,10 +206,14 @@ namespace SystemTrayMenu.Handler
if (dgv != null && dgv.Rows.Count > rowIndex)
{
RowData rowData = (RowData)dgv.Rows[rowIndex].Cells[2].Value;
rowData.IsSelected = false;
dgv.Rows[rowIndex].Selected = false;
this.dgv = null;
this.rowIndex = 0;
if (rowData != null)
{
rowData.IsSelected = false;
rowData.IsClicking = false;
dgv.Rows[rowIndex].Selected = false;
this.dgv = null;
this.rowIndex = 0;
}
}
}
}

View file

@ -8,21 +8,88 @@ namespace SystemTrayMenu
internal static class AppColors
{
internal static readonly Color Blue = Color.FromArgb(204, 232, 255);
internal static readonly Color DarkModeBlue = Color.FromArgb(51, 51, 51);
internal static readonly Color BlueBorder = Color.FromArgb(153, 209, 255);
internal static readonly Color DarkModeBlueBorder = Color.FromArgb(20, 29, 75);
internal static readonly Color Green = Color.FromArgb(194, 245, 222);
internal static readonly Color DarkModeGreen = Color.FromArgb(20, 65, 42);
internal static readonly Color GreenBorder = Color.FromArgb(153, 255, 165);
internal static readonly Color DarkModeGreenBorder = Color.FromArgb(20, 75, 85);
internal static readonly Color Red = Color.FromArgb(255, 204, 232);
internal static readonly Color DarkModeRed = Color.FromArgb(75, 24, 52);
internal static readonly Color Azure = Color.Azure;
internal static readonly Color DarkModeAzure = DarkModeBackColor1;
public static Color Arrow { get; internal set; }
internal static readonly Color DarkModeBackColor3 = Color.FromArgb(25, 25, 25);
internal static readonly Color DarkModeBackColor2 = Color.FromArgb(32, 32, 32);
internal static readonly Color DarkModeBackColor1 = Color.FromArgb(43, 43, 43);
public static Color ArrowHoverBackground { get; internal set; }
public static Color ArrowHover { get; internal set; }
public static Color ArrowClick { get; internal set; }
public static Color ArrowClickBackground { get; internal set; }
public static Color SliderArrowsAndTrackHover { get; internal set; }
public static Color Slider { get; internal set; }
public static Color SliderHover { get; internal set; }
public static Color SliderDragging { get; internal set; }
public static Color ScrollbarBackground { get; internal set; }
public static Color ArrowDarkMode { get; internal set; }
public static Color ArrowHoverBackgroundDarkMode { get; internal set; }
public static Color ArrowHoverDarkMode { get; internal set; }
public static Color ArrowClickDarkMode { get; internal set; }
public static Color ArrowClickBackgroundDarkMode { get; internal set; }
public static Color SliderArrowsAndTrackHoverDarkMode { get; internal set; }
public static Color SliderDarkMode { get; internal set; }
public static Color SliderHoverDarkMode { get; internal set; }
public static Color SliderDraggingDarkMode { get; internal set; }
public static Color ScrollbarBackgroundDarkMode { get; internal set; }
public static Color SelectedItem { get; set; }
public static Color DarkModeSelecetedItem { get; set; }
public static Color SelectedItemBorder { get; set; }
public static Color DarkModeSelectedItemBorder { get; set; }
public static Color OpenFolder { get; set; }
public static Color DarkModeOpenFolder { get; set; }
public static Color OpenFolderBorder { get; set; }
public static Color DarkModeOpenFolderBorder { get; set; }
public static Color Background { get; set; }
public static Color DarkModeBackground { get; set; }
public static Color BackgroundBorder { get; set; }
public static Color DarkModeBackgroundBorder { get; set; }
public static Color SearchField { get; set; }
public static Color DarkModeSearchField { get; set; }
public static Bitmap BitmapOpenFolder { get; set; }
public static Bitmap BitmapPin { get; set; }
public static Bitmap BitmapSettings { get; set; }
public static Bitmap BitmapRestart { get; set; }
public static Bitmap BitmapPinActive { get; set; }
public static Bitmap BitmapSearch { get; set; }
public static Color Icons { get; set; }
public static Color DarkModeIcons { get; set; }
}
}

15
Config/ColorAndCode.cs Normal file
View file

@ -0,0 +1,15 @@
// <copyright file="ColorAndCode.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu
{
using System.Drawing;
internal struct ColorAndCode
{
public Color Color { get; set; }
public string HtmlColorCode { get; set; }
}
}

View file

@ -4,113 +4,164 @@
namespace SystemTrayMenu
{
using System.Diagnostics;
using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using Svg;
using SystemTrayMenu.Properties;
using SystemTrayMenu.UserInterface.FolderBrowseDialog;
using SystemTrayMenu.Utilities;
using static SystemTrayMenu.Utilities.IconReader;
public static class Config
{
public const string Language = "en";
private static readonly Icon SystemTrayMenu = new Icon(Properties.Resources.SystemTrayMenu, SystemInformation.SmallIconSize);
private static readonly Icon IconRootFolder = GetIconSTA(Path, Path, false, IconSize.Small, true);
private static bool readDarkModeDone = false;
private static bool isDarkModeFromFirstCall = false;
private static bool readDarkModeDone;
private static bool isDarkMode;
private static bool readHideFileExtdone;
private static bool isHideFileExtension;
public static string Path => Properties.Settings.Default.PathDirectory;
public static string Path => Settings.Default.PathDirectory;
public static void UpgradeIfNotUpgraded()
public static string SearchPattern => Settings.Default.SearchPattern;
public static bool ShowDirectoryTitleAtTop => Settings.Default.ShowDirectoryTitleAtTop;
public static bool ShowSearchBar => Settings.Default.ShowSearchBar;
public static bool ShowCountOfElementsBelow => Settings.Default.ShowCountOfElementsBelow;
public static bool ShowFunctionKeyOpenFolder => Settings.Default.ShowFunctionKeyOpenFolder;
public static bool ShowFunctionKeyPinMenu => Settings.Default.ShowFunctionKeyPinMenu;
public static bool ShowFunctionKeySettings => Settings.Default.ShowFunctionKeySettings;
public static bool ShowFunctionKeyRestart => Settings.Default.ShowFunctionKeyRestart;
public static bool AlwaysOpenByPin { get; internal set; }
public static void Initialize()
{
if (!Properties.Settings.Default.IsUpgraded)
UpgradeIfNotUpgraded();
InitializeColors();
if (string.IsNullOrEmpty(Settings.Default.PathIcoDirectory))
{
// configs located at "%localappdata%\<AssemblyCompany>\"
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.IsUpgraded = true;
Properties.Settings.Default.Save();
FileVersionInfo versionInfo = FileVersionInfo.
GetVersionInfo(Assembly.GetEntryAssembly().Location);
Log.Info($"Settings upgraded from " +
$"%localappdata%\\{versionInfo.CompanyName}\\");
Settings.Default.PathIcoDirectory = System.IO.Path.Combine(
System.IO.Path.Combine(
Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData), $"SystemTrayMenu"), "ico");
if (!Directory.Exists(Settings.Default.PathIcoDirectory))
{
Directory.CreateDirectory(Settings.Default.PathIcoDirectory);
}
}
}
public static bool LoadOrSetByUser()
public static void Dispose()
{
bool pathOK = Directory.Exists(Path);
AppColors.BitmapOpenFolder.Dispose();
AppColors.BitmapPin.Dispose();
AppColors.BitmapPinActive.Dispose();
AppColors.BitmapSettings.Dispose();
AppColors.BitmapRestart.Dispose();
AppColors.BitmapSearch.Dispose();
}
if (!pathOK)
public static Icon GetAppIcon()
{
if (Settings.Default.UseIconFromRootFolder)
{
string textFirstStart = Translator.GetText("TextFirstStart");
return IconRootFolder;
}
else
{
return SystemTrayMenu;
}
}
public static void SetFolderByWindowsContextMenu(string[] args)
{
if (args != null && args.Length > 0 && args[0] != "-r")
{
string path = args[0];
Log.Info($"SetFolderByWindowsContextMenu() path: {path}");
Settings.Default.PathDirectory = path;
Settings.Default.Save();
}
}
public static void LoadOrSetByUser()
{
if (string.IsNullOrEmpty(Path))
{
string textFirstStart = Translator.GetText(
"Read the FAQ and then choose a root directory for SystemTrayMenu.");
MessageBox.Show(
textFirstStart,
Translator.GetText("SystemTrayMenu"),
"SystemTrayMenu",
MessageBoxButtons.OK);
ShowHelpFAQ();
pathOK = SetFolderByUser();
SetFolderByUser();
}
return pathOK;
}
public static bool SetFolderByUser(bool save = true)
public static void SetFolderByUser(bool save = true)
{
bool pathOK = false;
bool userAborted = false;
using (FolderDialog dialog = new FolderDialog())
using FolderDialog dialog = new();
dialog.InitialFolder = Path;
if (dialog.ShowDialog() == DialogResult.OK)
{
dialog.InitialFolder = Path;
do
Settings.Default.PathDirectory = dialog.Folder;
if (save)
{
if (dialog.ShowDialog() == DialogResult.OK)
{
if (Directory.Exists(dialog.Folder))
{
pathOK = true;
Properties.Settings.Default.PathDirectory =
dialog.Folder;
if (save)
{
Properties.Settings.Default.Save();
}
}
}
else
{
userAborted = true;
}
Settings.Default.Save();
}
while (!pathOK && !userAborted);
}
}
return pathOK;
public static void SetFolderIcoByUser()
{
using FolderDialog dialog = new();
dialog.InitialFolder = Settings.Default.PathIcoDirectory;
if (dialog.ShowDialog() == DialogResult.OK)
{
Settings.Default.PathIcoDirectory = dialog.Folder;
}
}
internal static void ShowHelpFAQ()
{
string browserPath = FileUrl.GetDefaultBrowserPath();
if (!string.IsNullOrEmpty(browserPath))
{
Process.Start(browserPath, "https://github.com/Hofknecht/SystemTrayMenu#FAQ");
}
Log.ProcessStart("https://github.com/Hofknecht/SystemTrayMenu#FAQ");
}
internal static void ShowSupportSystemTrayMenu()
{
Log.ProcessStart("https://github.com/Hofknecht/SystemTrayMenu#donations");
}
/// <summary>
/// Read the OS setting whether dark mode is enabled.
/// </summary>
/// <returns>true = Dark mode; false = Light mode.</returns>
internal static bool IsDarkMode()
{
bool isDarkMode = false;
if (readDarkModeDone)
if (!readDarkModeDone)
{
isDarkMode = isDarkModeFromFirstCall;
}
else
{
if (Properties.Settings.Default.IsDarkModeAlwaysOn || IsDarkModeActive())
// 0 = Dark mode, 1 = Light mode
if (Settings.Default.IsDarkModeAlwaysOn ||
IsRegistryValueThisValue(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize",
"AppsUseLightTheme",
"0"))
{
isDarkModeFromFirstCall = true;
isDarkMode = true;
}
@ -120,15 +171,359 @@ namespace SystemTrayMenu
return isDarkMode;
}
/// <summary>
/// Read the OS setting whether dark mode is enabled.
/// </summary>
/// <returns>true = Dark mode; false = Light mode.</returns>
private static bool IsDarkModeActive()
internal static void ResetReadDarkModeDone()
{
// Check: AppsUseLightTheme (REG_DWORD)
// 0 = Dark mode, 1 = Light mode
return Registry.GetValue("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme", 1).ToString() == "0";
isDarkMode = false;
readDarkModeDone = false;
}
/// <summary>
/// Read the OS setting whether HideFileExt enabled.
/// </summary>
/// <returns>isHideFileExtension.</returns>
internal static bool IsHideFileExtension()
{
if (!readHideFileExtdone)
{
// 0 = To show extensions, 1 = To hide extensions
if (IsRegistryValueThisValue(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced",
"HideFileExt",
"1"))
{
isHideFileExtension = true;
}
readHideFileExtdone = true;
}
return isHideFileExtension;
}
internal static void InitializeColors(bool save = true)
{
ColorConverter converter = new();
ColorAndCode colorAndCode = default;
bool changed = false;
colorAndCode.HtmlColorCode = Settings.Default.ColorSelectedItem;
colorAndCode.Color = Color.FromArgb(204, 232, 255);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSelectedItem = colorAndCode.HtmlColorCode;
AppColors.SelectedItem = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeSelecetedItem;
colorAndCode.Color = Color.FromArgb(51, 51, 51);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeSelecetedItem = colorAndCode.HtmlColorCode;
AppColors.DarkModeSelecetedItem = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSelectedItemBorder;
colorAndCode.Color = Color.FromArgb(153, 209, 255);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSelectedItemBorder = colorAndCode.HtmlColorCode;
AppColors.SelectedItemBorder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeSelectedItemBorder;
colorAndCode.Color = Color.FromArgb(20, 29, 75);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeSelectedItemBorder = colorAndCode.HtmlColorCode;
AppColors.DarkModeSelectedItemBorder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorOpenFolder;
colorAndCode.Color = Color.FromArgb(194, 245, 222);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorOpenFolder = colorAndCode.HtmlColorCode;
AppColors.OpenFolder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeOpenFolder;
colorAndCode.Color = Color.FromArgb(20, 65, 42);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeOpenFolder = colorAndCode.HtmlColorCode;
AppColors.DarkModeOpenFolder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorOpenFolderBorder;
colorAndCode.Color = Color.FromArgb(153, 255, 165);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorOpenFolderBorder = colorAndCode.HtmlColorCode;
AppColors.OpenFolderBorder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeOpenFolderBorder;
colorAndCode.Color = Color.FromArgb(20, 75, 85);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeOpenFolderBorder = colorAndCode.HtmlColorCode;
AppColors.DarkModeOpenFolderBorder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorIcons;
colorAndCode.Color = Color.FromArgb(149, 160, 166);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorIcons = colorAndCode.HtmlColorCode;
AppColors.Icons = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeIcons;
colorAndCode.Color = Color.FromArgb(149, 160, 166);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeIcons = colorAndCode.HtmlColorCode;
AppColors.DarkModeIcons = colorAndCode.Color;
string htmlColorCodeIcons;
if (IsDarkMode())
{
htmlColorCodeIcons = Settings.Default.ColorDarkModeIcons;
}
else
{
htmlColorCodeIcons = Settings.Default.ColorIcons;
}
AppColors.BitmapOpenFolder =
ReadSvg(Properties.Resources.ic_fluent_folder_arrow_right_48_regular, htmlColorCodeIcons);
AppColors.BitmapPin =
ReadSvg(Properties.Resources.ic_fluent_pin_48_regular, htmlColorCodeIcons);
AppColors.BitmapSettings =
ReadSvg(Properties.Resources.ic_fluent_settings_28_regular, htmlColorCodeIcons);
AppColors.BitmapRestart =
ReadSvg(Properties.Resources.ic_fluent_arrow_sync_24_regular, htmlColorCodeIcons);
AppColors.BitmapPinActive =
ReadSvg(Properties.Resources.ic_fluent_pin_48_filled, htmlColorCodeIcons);
AppColors.BitmapSearch =
ReadSvg(Properties.Resources.ic_fluent_search_48_regular, htmlColorCodeIcons);
colorAndCode.HtmlColorCode = Settings.Default.ColorSearchField;
colorAndCode.Color = Color.FromArgb(255, 255, 255);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSearchField = colorAndCode.HtmlColorCode;
AppColors.SearchField = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeSearchField;
colorAndCode.Color = Color.FromArgb(25, 25, 25);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeSearchField = colorAndCode.HtmlColorCode;
AppColors.DarkModeSearchField = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorBackground;
colorAndCode.Color = Color.FromArgb(255, 255, 255);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorBackground = colorAndCode.HtmlColorCode;
AppColors.Background = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeBackground;
colorAndCode.Color = Color.FromArgb(32, 32, 32);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeBackground = colorAndCode.HtmlColorCode;
AppColors.DarkModeBackground = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorBackgroundBorder;
colorAndCode.Color = Color.FromArgb(0, 0, 0);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorBackgroundBorder = colorAndCode.HtmlColorCode;
AppColors.BackgroundBorder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorDarkModeBackgroundBorder;
colorAndCode.Color = Color.FromArgb(0, 0, 0);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorDarkModeBackgroundBorder = colorAndCode.HtmlColorCode;
AppColors.DarkModeBackgroundBorder = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrow;
colorAndCode.Color = Color.FromArgb(96, 96, 96);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrow = colorAndCode.HtmlColorCode;
AppColors.Arrow = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowHoverBackground;
colorAndCode.Color = Color.FromArgb(218, 218, 218);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowHoverBackground = colorAndCode.HtmlColorCode;
AppColors.ArrowHoverBackground = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowHover;
colorAndCode.Color = Color.FromArgb(0, 0, 0);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowHover = colorAndCode.HtmlColorCode;
AppColors.ArrowHover = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowClick;
colorAndCode.Color = Color.FromArgb(255, 255, 255);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowClick = colorAndCode.HtmlColorCode;
AppColors.ArrowClick = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowClickBackground;
colorAndCode.Color = Color.FromArgb(96, 96, 96);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowClickBackground = colorAndCode.HtmlColorCode;
AppColors.ArrowClickBackground = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSliderArrowsAndTrackHover;
colorAndCode.Color = Color.FromArgb(192, 192, 192);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSliderArrowsAndTrackHover = colorAndCode.HtmlColorCode;
AppColors.SliderArrowsAndTrackHover = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSlider;
colorAndCode.Color = Color.FromArgb(205, 205, 205);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSlider = colorAndCode.HtmlColorCode;
AppColors.Slider = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSliderHover;
colorAndCode.Color = Color.FromArgb(166, 166, 166);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSliderHover = colorAndCode.HtmlColorCode;
AppColors.SliderHover = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSliderDragging;
colorAndCode.Color = Color.FromArgb(96, 96, 96);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSliderDragging = colorAndCode.HtmlColorCode;
AppColors.SliderDragging = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorScrollbarBackground;
colorAndCode.Color = Color.FromArgb(240, 240, 240);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorScrollbarBackground = colorAndCode.HtmlColorCode;
AppColors.ScrollbarBackground = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowDarkMode;
colorAndCode.Color = Color.FromArgb(103, 103, 103);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowDarkMode = colorAndCode.HtmlColorCode;
AppColors.ArrowDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowHoverBackgroundDarkMode;
colorAndCode.Color = Color.FromArgb(55, 55, 55);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowHoverBackgroundDarkMode = colorAndCode.HtmlColorCode;
AppColors.ArrowHoverBackgroundDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowHoverDarkMode;
colorAndCode.Color = Color.FromArgb(103, 103, 103);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowHoverDarkMode = colorAndCode.HtmlColorCode;
AppColors.ArrowHoverDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowClickDarkMode;
colorAndCode.Color = Color.FromArgb(23, 23, 23);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowClickDarkMode = colorAndCode.HtmlColorCode;
AppColors.ArrowClickDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorArrowClickBackgroundDarkMode;
colorAndCode.Color = Color.FromArgb(166, 166, 166);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorArrowClickBackgroundDarkMode = colorAndCode.HtmlColorCode;
AppColors.ArrowClickBackgroundDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSliderArrowsAndTrackHoverDarkMode;
colorAndCode.Color = Color.FromArgb(77, 77, 77);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSliderArrowsAndTrackHoverDarkMode = colorAndCode.HtmlColorCode;
AppColors.SliderArrowsAndTrackHoverDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSliderDarkMode;
colorAndCode.Color = Color.FromArgb(77, 77, 77);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSliderDarkMode = colorAndCode.HtmlColorCode;
AppColors.SliderDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSliderHoverDarkMode;
colorAndCode.Color = Color.FromArgb(122, 122, 122);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSliderHoverDarkMode = colorAndCode.HtmlColorCode;
AppColors.SliderHoverDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorSliderDraggingDarkMode;
colorAndCode.Color = Color.FromArgb(166, 166, 166);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorSliderDraggingDarkMode = colorAndCode.HtmlColorCode;
AppColors.SliderDraggingDarkMode = colorAndCode.Color;
colorAndCode.HtmlColorCode = Settings.Default.ColorScrollbarBackgroundDarkMode;
colorAndCode.Color = Color.FromArgb(23, 23, 23);
colorAndCode = ProcessColorAndCode(converter, colorAndCode, ref changed);
Settings.Default.ColorScrollbarBackgroundDarkMode = colorAndCode.HtmlColorCode;
AppColors.ScrollbarBackgroundDarkMode = colorAndCode.Color;
if (save && changed)
{
Settings.Default.Save();
}
}
private static Bitmap ReadSvg(byte[] byteArray, string htmlColorCode)
{
string str = Encoding.UTF8.GetString(byteArray);
str = str.Replace("#585858", htmlColorCode);
byteArray = Encoding.UTF8.GetBytes(str);
using MemoryStream stream = new(byteArray);
SvgDocument svgDocument = SvgDocument.Open<SvgDocument>(stream);
svgDocument.Color = new SvgColourServer(Color.Black);
return svgDocument.Draw();
}
private static bool IsRegistryValueThisValue(string keyName, string valueName, string value)
{
bool isRegistryValueThisValue = false;
try
{
object registryHideFileExt = Registry.GetValue(keyName, valueName, 1);
if (registryHideFileExt == null)
{
Log.Info($"Could not read registry keyName:{keyName} valueName:{valueName}");
}
else if (registryHideFileExt.ToString() == value)
{
isRegistryValueThisValue = true;
}
}
catch (Exception ex)
{
if (ex is System.Security.SecurityException ||
ex is IOException)
{
Log.Warn($"Could not read registry keyName:{keyName} valueName:{valueName}", ex);
}
else
{
throw;
}
}
return isRegistryValueThisValue;
}
private static void UpgradeIfNotUpgraded()
{
if (!Settings.Default.IsUpgraded)
{
Settings.Default.Upgrade();
Settings.Default.IsUpgraded = true;
Settings.Default.Save();
Log.Info($"Settings upgraded from {CustomSettingsProvider.UserConfigPath}");
}
}
private static ColorAndCode ProcessColorAndCode(
ColorConverter colorConverter,
ColorAndCode colorAndCode,
ref bool changedHtmlColorCode)
{
try
{
colorAndCode.Color = (Color)colorConverter.ConvertFromString(colorAndCode.HtmlColorCode);
}
catch (ArgumentException ex)
{
Log.Warn($"HtmlColorCode {colorAndCode.HtmlColorCode}", ex);
colorAndCode.HtmlColorCode = ColorTranslator.ToHtml(colorAndCode.Color);
changedHtmlColorCode = true;
}
return colorAndCode;
}
}
}

View file

@ -8,13 +8,9 @@ namespace SystemTrayMenu
internal static class MenuDefines
{
internal const int Scrollspeed = 4;
internal const int TimeUntilClose = 1000;
internal const int MenusMax = 50;
internal const int LengthMax = 37;
internal const float MaxMenuWidth = 300;
internal static readonly Color File = Color.White;
internal static readonly Color Folder = Color.White;
internal const int Scrollspeed = 3;
public static Color ColorSelectedItem
{
@ -22,11 +18,11 @@ namespace SystemTrayMenu
{
if (Config.IsDarkMode())
{
return AppColors.DarkModeBlue;
return AppColors.DarkModeSelecetedItem;
}
else
{
return AppColors.Blue;
return AppColors.SelectedItem;
}
}
}
@ -37,11 +33,11 @@ namespace SystemTrayMenu
{
if (Config.IsDarkMode())
{
return AppColors.DarkModeBlueBorder;
return AppColors.DarkModeSelectedItemBorder;
}
else
{
return AppColors.BlueBorder;
return AppColors.SelectedItemBorder;
}
}
}
@ -52,11 +48,11 @@ namespace SystemTrayMenu
{
if (Config.IsDarkMode())
{
return AppColors.DarkModeGreen;
return AppColors.DarkModeOpenFolder;
}
else
{
return AppColors.Green;
return AppColors.OpenFolder;
}
}
}
@ -67,56 +63,26 @@ namespace SystemTrayMenu
{
if (Config.IsDarkMode())
{
return AppColors.DarkModeGreenBorder;
return AppColors.DarkModeOpenFolderBorder;
}
else
{
return AppColors.GreenBorder;
return AppColors.OpenFolderBorder;
}
}
}
public static Color ColorTitleWarning
public static Color ColorIcons
{
get
{
if (Config.IsDarkMode())
{
return AppColors.DarkModeRed;
return AppColors.DarkModeIcons;
}
else
{
return AppColors.Red;
}
}
}
public static Color ColorTitleSelected
{
get
{
if (Config.IsDarkMode())
{
return AppColors.DarkModeBlue;
}
else
{
return AppColors.Blue;
}
}
}
public static Color ColorTitleBackground
{
get
{
if (Config.IsDarkMode())
{
return AppColors.DarkModeAzure;
}
else
{
return AppColors.Azure;
return AppColors.Icons;
}
}
}

View file

@ -8,7 +8,7 @@ namespace SystemTrayMenu.DataClasses
internal enum MenuDataValidity
{
AbortedOrUnknown,
Undefined,
Valid,
Empty,
NoAccess,
@ -16,9 +16,23 @@ namespace SystemTrayMenu.DataClasses
internal struct MenuData
{
internal List<RowData> RowDatas;
internal MenuDataValidity Validity;
internal int Level;
internal RowData RowDataParent;
public MenuData(int level)
{
RowDatas = new List<RowData>();
Validity = MenuDataValidity.Undefined;
Level = level;
RowDataParent = null;
IsNetworkRoot = false;
}
internal List<RowData> RowDatas { get; set; }
internal MenuDataValidity Validity { get; set; }
internal int Level { get; }
internal RowData RowDataParent { get; set; }
internal bool IsNetworkRoot { get; set; }
}
}

View file

@ -5,170 +5,198 @@
namespace SystemTrayMenu.DataClasses
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Windows.Forms;
using IWshRuntimeLibrary;
using SystemTrayMenu.Utilities;
using TAFactory.IconPack;
using static SystemTrayMenu.Utilities.IconReader;
using Menu = SystemTrayMenu.UserInterface.Menu;
internal class RowData : IDisposable
internal class RowData
{
private static DateTime contextMenuClosed;
private string workingDirectory;
private string arguments;
private string text;
private Icon icon = null;
private bool diposeIcon = true;
private bool isDisposed = false;
private Icon icon;
/// <summary>
/// Initializes a new instance of the <see cref="RowData"/> class.
/// empty dummy.
/// </summary>
internal RowData()
{
}
internal FileInfo FileInfo { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="RowData"/> class.
/// (Related replace "\x00" see #171.)
/// </summary>
/// <param name="isFolder">Flag if file or folder.</param>
/// <param name="isAddionalItem">Flag if addional item, from other folder than root folder.</param>
/// <param name="isNetworkRoot">Flag if resolved from network root folder.</param>
/// <param name="level">The number of the menu level.</param>
/// <param name="path">Path to item.</param>
internal RowData(bool isFolder, bool isAddionalItem, bool isNetworkRoot, int level, string path)
{
IsFolder = isFolder;
IsAddionalItem = isAddionalItem;
IsNetworkRoot = isNetworkRoot;
Level = level;
try
{
FileInfo = new FileInfo(path.Replace("\x00", string.Empty));
Path = IsFolder ? $@"{FileInfo.FullName}\" : FileInfo.FullName;
FileExtension = System.IO.Path.GetExtension(Path);
IsLink = FileExtension.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase);
if (IsLink)
{
ResolvedPath = FileLnk.GetResolvedFileName(Path, out bool isLinkToFolder);
IsLinkToFolder = isLinkToFolder || FileLnk.IsNetworkRoot(ResolvedPath);
ShowOverlay = Properties.Settings.Default.ShowLinkOverlay;
Text = System.IO.Path.GetFileNameWithoutExtension(Path);
if (string.IsNullOrEmpty(ResolvedPath))
{
Log.Info($"Resolved path is empty: '{Path}'");
ResolvedPath = Path;
}
}
else
{
ResolvedPath = Path;
if (string.IsNullOrEmpty(FileInfo.Name))
{
int nameBegin = FileInfo.FullName.LastIndexOf(@"\", StringComparison.InvariantCulture) + 1;
Text = FileInfo.FullName[nameBegin..];
}
else if (FileExtension.Equals(".url", StringComparison.InvariantCultureIgnoreCase) ||
FileExtension.Equals(".appref-ms", StringComparison.InvariantCultureIgnoreCase))
{
ShowOverlay = Properties.Settings.Default.ShowLinkOverlay;
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
}
else if (!IsFolder && Config.IsHideFileExtension())
{
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
}
else
{
Text = FileInfo.Name;
}
}
ContainsMenu = IsFolder;
if (Properties.Settings.Default.ResolveLinksToFolders)
{
ContainsMenu |= IsLinkToFolder;
}
IsMainMenu = Level == 0;
}
catch (Exception ex)
{
Log.Warn($"path:'{path}'", ex);
}
}
internal FileInfo FileInfo { get; }
internal string Path { get; }
internal bool IsFolder { get; }
internal bool IsAddionalItem { get; }
internal bool IsNetworkRoot { get; }
internal int Level { get; set; }
internal string FileExtension { get; }
internal bool IsLink { get; }
internal string ResolvedPath { get; }
internal bool IsLinkToFolder { get; }
internal bool ShowOverlay { get; }
internal string Text { get; }
internal bool ContainsMenu { get; }
internal bool IsMainMenu { get; }
internal Menu SubMenu { get; set; }
internal bool IsMenuOpen { get; set; }
internal bool IsSelected { get; set; }
internal bool IsClicking { get; set; }
internal bool ContainsMenu { get; set; }
internal bool IsSelected { get; set; }
internal bool IsContextMenuOpen { get; set; }
internal bool IsResolvedLnk { get; set; }
internal bool HiddenEntry { get; set; }
internal string TargetFilePath { get; set; }
internal string TargetFilePathOrig { get; set; }
internal int RowIndex { get; set; }
internal int MenuLevel { get; set; }
internal bool IconLoading { get; set; }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
internal void SetText(string text)
{
this.text = text;
}
internal bool ProcessStarted { get; set; }
internal void SetData(RowData data, DataTable dataTable)
{
DataRow row = dataTable.Rows.Add();
data.RowIndex = dataTable.Rows.IndexOf(row);
if (icon == null)
{
icon = Properties.Resources.WhiteTransparency;
}
if (HiddenEntry)
{
row[0] = IconReader.AddIconOverlay(
data.icon,
Properties.Resources.WhiteTransparency);
row[0] = AddIconOverlay(data.icon, Properties.Resources.White50Percentage);
}
else
{
row[0] = data.icon;
}
row[1] = data.text;
row[1] = data.Text;
row[2] = data;
}
internal bool ReadIcon(bool isDirectory, ref string resolvedLnkPath)
internal Icon ReadIcon(bool updateIconInBackground)
{
bool isLnkDirectory = false;
if (string.IsNullOrEmpty(TargetFilePath))
if (IsFolder || IsLinkToFolder)
{
Log.Info($"TargetFilePath from {resolvedLnkPath} empty");
}
else if (isDirectory)
{
icon = IconReader.GetFolderIconSTA(
TargetFilePath,
IconReader.FolderType.Closed,
false);
icon = GetFolderIconWithCache(Path, ShowOverlay, updateIconInBackground, IsMainMenu, out bool loading);
IconLoading = loading;
}
else
{
bool handled = false;
string fileExtension = Path.GetExtension(TargetFilePath);
icon = GetFileIconWithCache(Path, ResolvedPath, ShowOverlay, updateIconInBackground, IsMainMenu, out bool loading);
IconLoading = loading;
}
if (fileExtension == ".lnk")
if (!IconLoading)
{
if (icon == null)
{
handled = SetLnk(
ref isLnkDirectory,
ref resolvedLnkPath);
icon = Properties.Resources.NotFound;
}
else if (fileExtension == ".url")
else if (HiddenEntry)
{
handled = SetUrl();
}
else if (fileExtension == ".sln")
{
handled = SetSln();
}
if (!handled)
{
try
{
icon = IconReader.GetFileIconWithCache(TargetFilePath, false);
diposeIcon = false;
// other project -> fails sometimes
// icon = IconHelper.ExtractIcon(TargetFilePath, 0);
// standard way -> fails sometimes
// icon = Icon.ExtractAssociatedIcon(filePath);
// API Code Pack -> fails sometimes
// ShellFile shellFile = ShellFile.FromFilePath(filePath);
// Bitmap shellThumb = shellFile.Thumbnail.ExtraLargeBitmap;
}
catch (Exception ex)
{
if (ex is SecurityException ||
ex is ArgumentException ||
ex is UnauthorizedAccessException ||
ex is PathTooLongException ||
ex is NotSupportedException)
{
Log.Warn($"path:'{TargetFilePath}'", ex);
}
else
{
throw;
}
}
icon = AddIconOverlay(icon, Properties.Resources.White50Percentage);
}
}
return isLnkDirectory;
return icon;
}
internal void MouseDown(DataGridView dgv, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
IsClicking = true;
}
if (e != null &&
e.Button == MouseButtons.Right &&
FileInfo != null &&
@ -178,232 +206,97 @@ namespace SystemTrayMenu.DataClasses
{
IsContextMenuOpen = true;
ShellContextMenu ctxMnu = new ShellContextMenu();
ShellContextMenu ctxMnu = new();
Point location = dgv.FindForm().Location;
Point point = new Point(
Point point = new(
e.X + location.X + dgv.Location.X,
e.Y + location.Y + dgv.Location.Y);
if (ContainsMenu)
{
DirectoryInfo[] dir = new DirectoryInfo[1];
dir[0] = new DirectoryInfo(TargetFilePathOrig);
dir[0] = new DirectoryInfo(Path);
ctxMnu.ShowContextMenu(dir, point);
TriggerFileWatcherChangeWorkaround();
}
else
{
FileInfo[] arrFI = new FileInfo[1];
arrFI[0] = new FileInfo(TargetFilePathOrig);
arrFI[0] = FileInfo;
ctxMnu.ShowContextMenu(arrFI, point);
TriggerFileWatcherChangeWorkaround();
}
IsContextMenuOpen = false;
contextMenuClosed = DateTime.Now;
}
if (Properties.Settings.Default.OpenItemWithOneClick)
void TriggerFileWatcherChangeWorkaround()
{
OpenItem(e);
}
}
internal void DoubleClick(MouseEventArgs e)
{
if (!Properties.Settings.Default.OpenItemWithOneClick)
{
OpenItem(e);
}
if (ContainsMenu &&
(e == null || e.Button == MouseButtons.Left))
{
Log.ProcessStart(TargetFilePath, null, true);
}
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
if (diposeIcon)
try
{
icon?.Dispose();
string parentFolder = System.IO.Path.GetDirectoryName(Path);
Directory.GetFiles(parentFolder);
}
catch (Exception ex)
{
Log.Warn($"{nameof(TriggerFileWatcherChangeWorkaround)} '{Path}'", ex);
}
}
isDisposed = true;
}
private void OpenItem(MouseEventArgs e)
internal void MouseClick(MouseEventArgs e, out bool toCloseByDoubleClick)
{
IsClicking = false;
toCloseByDoubleClick = false;
if (Properties.Settings.Default.OpenItemWithOneClick)
{
OpenItem(e, ref toCloseByDoubleClick);
}
if (Properties.Settings.Default.OpenDirectoryWithOneClick &&
ContainsMenu && (e == null || e.Button == MouseButtons.Left))
{
Log.ProcessStart(Path);
if (!Properties.Settings.Default.StaysOpenWhenItemClicked)
{
toCloseByDoubleClick = true;
}
}
}
internal void DoubleClick(MouseEventArgs e, out bool toCloseByDoubleClick)
{
IsClicking = false;
toCloseByDoubleClick = false;
if (!Properties.Settings.Default.OpenItemWithOneClick)
{
OpenItem(e, ref toCloseByDoubleClick);
}
if (!Properties.Settings.Default.OpenDirectoryWithOneClick &&
ContainsMenu && (e == null || e.Button == MouseButtons.Left))
{
Log.ProcessStart(Path);
if (!Properties.Settings.Default.StaysOpenWhenItemClicked)
{
toCloseByDoubleClick = true;
}
}
}
private void OpenItem(MouseEventArgs e, ref bool toCloseByOpenItem)
{
if (!ContainsMenu &&
(e == null || e.Button == MouseButtons.Left))
{
try
ProcessStarted = true;
string workingDirectory = System.IO.Path.GetDirectoryName(ResolvedPath);
Log.ProcessStart(Path, string.Empty, false, workingDirectory, true, ResolvedPath);
if (!Properties.Settings.Default.StaysOpenWhenItemClicked)
{
using Process p = new Process
{
StartInfo = new ProcessStartInfo(TargetFilePath)
{
FileName = TargetFilePathOrig,
Arguments = arguments,
WorkingDirectory = workingDirectory,
CreateNoWindow = true,
UseShellExecute = true,
},
};
p.Start();
}
catch (Win32Exception ex)
{
Log.Warn($"path:'{TargetFilePath}'", ex);
MessageBox.Show(ex.Message);
toCloseByOpenItem = true;
}
}
}
private bool SetLnk(
ref bool isLnkDirectory,
ref string resolvedLnkPath)
{
bool handled = false;
resolvedLnkPath = FileLnk.GetResolvedFileName(TargetFilePath);
if (FileLnk.IsDirectory(resolvedLnkPath))
{
icon = IconReader.GetFolderIconSTA(TargetFilePath, IconReader.FolderType.Open, true);
handled = true;
isLnkDirectory = true;
}
else if (FileLnk.IsNetworkRoot(resolvedLnkPath))
{
isLnkDirectory = true;
}
else if (string.IsNullOrEmpty(resolvedLnkPath))
{
Log.Info($"Resolve *.LNK '{TargetFilePath}' has no icon");
}
else
{
IWshShell shell = new WshShell();
IWshShortcut lnk = shell.CreateShortcut(TargetFilePath)
as IWshShortcut;
arguments = lnk.Arguments;
workingDirectory = lnk.WorkingDirectory;
string iconLocation = lnk.IconLocation;
if (iconLocation.Length > 2)
{
iconLocation = iconLocation[0..^2];
if (System.IO.File.Exists(iconLocation))
{
try
{
icon = Icon.ExtractAssociatedIcon(iconLocation);
handled = true;
}
catch (ArgumentException ex)
{
Log.Warn($"iconLocation:'{iconLocation}'", ex);
}
}
}
TargetFilePath = resolvedLnkPath;
}
SetText(Path.GetFileNameWithoutExtension(TargetFilePathOrig));
return handled;
}
private bool SetUrl()
{
bool handled = false;
string iconFile = string.Empty;
try
{
FileIni file = new FileIni(TargetFilePath);
iconFile = file.Value("IconFile", string.Empty);
if (string.IsNullOrEmpty(iconFile))
{
string browserPath = FileUrl.GetDefaultBrowserPath();
if (string.IsNullOrEmpty(browserPath))
{
Log.Info($"Resolve *.URL '{TargetFilePath}'" +
$"No default browser found!");
}
else
{
icon = IconReader.GetFileIconWithCache(browserPath, false);
diposeIcon = false;
handled = true;
}
}
else if (System.IO.File.Exists(iconFile))
{
icon = Icon.ExtractAssociatedIcon(iconFile);
handled = true;
}
else
{
Log.Info($"Resolve *.URL '{TargetFilePath}' has no icon");
}
}
catch (Exception ex)
{
if (ex is SecurityException ||
ex is ArgumentException ||
ex is UnauthorizedAccessException ||
ex is PathTooLongException ||
ex is NotSupportedException)
{
Log.Warn(
$"path:'{TargetFilePath}', " +
$"iconFile:'{iconFile}'", ex);
}
else
{
throw;
}
}
SetText($"{FileInfo.Name[0..^4]}");
return handled;
}
private bool SetSln()
{
bool handled = false;
StringBuilder executable = new StringBuilder(1024);
try
{
DllImports.NativeMethods.Shell32FindExecutable(TargetFilePath, string.Empty, executable);
// icon = IconReader.GetFileIcon(executable, false);
// e.g. VS 2019 icon, need another icom in imagelist
List<Icon> extractedIcons = IconHelper.ExtractAllIcons(
executable.ToString());
icon = extractedIcons.Last();
handled = true;
}
catch (Exception ex)
{
if (ex is SecurityException ||
ex is ArgumentException ||
ex is UnauthorizedAccessException ||
ex is PathTooLongException ||
ex is NotSupportedException)
{
Log.Warn(
$"path:'{TargetFilePath}', " +
$"executable:'{executable}'", ex);
}
else
{
throw;
}
}
return handled;
}
}
}

View file

@ -10,4 +10,7 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:Partial elements should be documented", Justification = "we need to document")]
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1602:Enumeration items should be documented", Justification = "we need to document")]
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1000:Keywords should be spaced correctly", Justification = "new() should not be replaced by new() ")]
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this", Justification = "Standard codecleanup removes the this")]
[assembly: SuppressMessage("Interoperability", "CA1416:Check platform compatibility", Justification = "this is a long way to get platform compatibility")]

View file

@ -9,19 +9,19 @@ namespace SystemTrayMenu.Helper
public class DgvMouseRow : IDisposable
{
private readonly Timer timerRaiseRowMouseLeave = new Timer();
private DataGridView dgv = null;
private DataGridViewCellEventArgs eventArgs = null;
private readonly Timer timerRaiseRowMouseLeave = new();
private DataGridView dgv;
private DataGridViewCellEventArgs eventArgs;
internal DgvMouseRow()
{
timerRaiseRowMouseLeave.Interval = 200;
timerRaiseRowMouseLeave.Tick += Elapsed;
void Elapsed(object sender, EventArgs e)
{
timerRaiseRowMouseLeave.Stop();
TriggerRowMouseLeave();
}
timerRaiseRowMouseLeave.Tick += TimerRaiseRowMouseLeave_Tick;
}
~DgvMouseRow() // the finalizer
{
Dispose(false);
}
internal event Action<object, DataGridViewCellEventArgs> RowMouseEnter;
@ -75,11 +75,18 @@ namespace SystemTrayMenu.Helper
{
if (disposing)
{
timerRaiseRowMouseLeave.Tick -= TimerRaiseRowMouseLeave_Tick;
timerRaiseRowMouseLeave.Dispose();
dgv?.Dispose();
dgv = null;
}
}
private void TimerRaiseRowMouseLeave_Tick(object sender, EventArgs e)
{
timerRaiseRowMouseLeave.Stop();
TriggerRowMouseLeave();
}
private void TriggerRowMouseLeave()
{
if (dgv != null)

190
Helpers/DragDropHelper.cs Normal file
View file

@ -0,0 +1,190 @@
// <copyright file="DragDropHelper.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helper
{
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using SystemTrayMenu.DataClasses;
using SystemTrayMenu.UserInterface;
using SystemTrayMenu.Utilities;
public static class DragDropHelper
{
public static void DragEnter(object sender, DragEventArgs e)
{
object data = e.Data.GetData("UniformResourceLocator");
if (data is MemoryStream memoryStream)
{
byte[] bytes = memoryStream.ToArray();
Encoding encod = Encoding.ASCII;
string url = encod.GetString(bytes);
if (!string.IsNullOrEmpty(url))
{
e.Effect = DragDropEffects.Copy;
}
}
}
public static void DragDrop(object sender, DragEventArgs e)
{
Menu menu = (Menu)sender;
string path;
if (menu != null)
{
RowData rowData = (RowData)menu.Tag;
if (rowData != null)
{
path = rowData.ResolvedPath;
}
else
{
path = Config.Path;
}
}
else
{
path = Config.Path;
}
object data = e.Data.GetData("UniformResourceLocator");
MemoryStream ms = data as MemoryStream;
byte[] bytes = ms.ToArray();
Encoding encod = Encoding.ASCII;
string url = encod.GetString(bytes);
new Thread(CreateShortcutInBackground).Start();
void CreateShortcutInBackground()
{
CreateShortcut(url.Replace("\0", string.Empty), path);
}
}
private static void CreateShortcut(string url, string pathToStoreFile)
{
string title = GetUrlShortcutTitle(url);
string fileNamePathShortcut = pathToStoreFile + "\\" + title.Trim() + ".url";
WriteShortcut(url, null, fileNamePathShortcut);
string pathIcon = DownloadUrlIcon(url);
if (!string.IsNullOrEmpty(pathIcon))
{
WriteShortcut(url, pathIcon, fileNamePathShortcut);
}
}
private static string GetUrlShortcutTitle(string url)
{
string title = url
.Replace("/", " ")
.Replace("https", string.Empty)
.Replace("http", string.Empty);
string invalid =
new string(Path.GetInvalidFileNameChars()) +
new string(Path.GetInvalidPathChars());
foreach (char character in invalid)
{
title = title.Replace(character.ToString(), string.Empty);
}
title = Truncate(title, 128); // max 255
return title;
}
private static string Truncate(string value, int maxLength)
{
if (!string.IsNullOrEmpty(value) &&
value.Length > maxLength)
{
value = value[..maxLength];
}
return value;
}
private static void WriteShortcut(string url, string pathIcon, string fileNamePathShortcut)
{
try
{
if (File.Exists(fileNamePathShortcut))
{
File.Delete(fileNamePathShortcut);
}
StreamWriter writer = new(fileNamePathShortcut);
writer.WriteLine("[InternetShortcut]");
writer.WriteLine($"URL={url.TrimEnd('\0')}");
writer.WriteLine("IconIndex=0");
writer.WriteLine($"HotKey=0");
writer.WriteLine($"IDList=");
if (!string.IsNullOrEmpty(pathIcon))
{
writer.WriteLine($"IconFile={pathIcon}");
}
writer.Flush();
writer.Close();
}
catch (Exception ex)
{
Log.Warn($"{nameof(WriteShortcut)} failed", ex);
}
}
private static string DownloadUrlIcon(string url)
{
string pathIcon = string.Empty;
string pathToStoreIcons = Properties.Settings.Default.PathIcoDirectory;
Uri uri = new(url);
string hostname = uri.Host.ToString();
string pathIconPng = Path.Combine(pathToStoreIcons, $"{hostname}.png");
string urlGoogleIconDownload = @"http://www.google.com/s2/favicons?sz=32&domain=" + url;
HttpClient client = new();
try
{
if (!Directory.Exists(pathToStoreIcons))
{
Directory.CreateDirectory(pathToStoreIcons);
}
using HttpResponseMessage response = client.GetAsync(urlGoogleIconDownload).Result;
using HttpContent content = response.Content;
Stream stream = content.ReadAsStreamAsync().Result;
using var fileStream = File.Create(pathIconPng);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fileStream);
fileStream.Close();
pathIcon = Path.Combine(pathToStoreIcons, $"{hostname}.ico");
if (!ImagingHelper.ConvertToIcon(pathIconPng, pathIcon, 32))
{
Log.Info("Failed to convert icon.");
}
}
catch (Exception ex)
{
Log.Warn($"{nameof(DownloadUrlIcon)} failed", ex);
}
try
{
if (File.Exists(pathIconPng))
{
File.Delete(pathIconPng);
}
}
catch (Exception ex)
{
Log.Warn($"{nameof(DownloadUrlIcon)} failed to delete {pathIconPng}", ex);
}
return pathIcon;
}
}
}

View file

@ -2,7 +2,7 @@
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface
namespace SystemTrayMenu.Helper
{
using System;
using System.Windows.Forms;
@ -10,7 +10,7 @@ namespace SystemTrayMenu.UserInterface
public class Fading : IDisposable
{
private const int Interval60FPS = 16; // 60fps=>1s/60fps=~16.6ms
private const int Interval100FPS = 10; // 100fps=>1s/100fps=~10ms
private const double StepIn = 0.20;
private const double StepOut = 0.10;
@ -20,26 +20,27 @@ namespace SystemTrayMenu.UserInterface
private const double Shown = 1.00;
private const double ShownMinus = 0.80; // Shown - StepIn
private readonly Timer timer = new Timer();
private readonly Timer timer = new();
private FadingState state = FadingState.Idle;
private double opacity = 0.00;
private bool visible = false;
private double opacity;
private bool visible;
internal Fading()
{
timer.Interval = Interval60FPS;
timer.Tick += Tick;
void Tick(object sender, EventArgs e)
{
FadeStep();
}
timer.Interval = Interval100FPS;
timer.Tick += Timer_Tick;
}
internal event EventHandlerEmpty Hide;
~Fading() // the finalizer
{
Dispose(false);
}
internal event EventHandlerEmpty Show;
internal event Action Hide;
internal event EventHandler<double> ChangeOpacity;
internal event Action Show;
internal event Action<double> ChangeOpacity;
internal enum FadingState
{
@ -66,6 +67,7 @@ namespace SystemTrayMenu.UserInterface
{
if (disposing)
{
timer.Tick -= Timer_Tick;
timer.Dispose();
}
}
@ -81,10 +83,14 @@ namespace SystemTrayMenu.UserInterface
{
state = newState;
timer.Start();
FadeStep();
}
}
private void Timer_Tick(object sender, EventArgs e)
{
FadeStep();
}
private void FadeStep()
{
switch (state)
@ -95,17 +101,25 @@ namespace SystemTrayMenu.UserInterface
visible = true;
Show?.Invoke();
opacity = 0;
ChangeOpacity?.Invoke(this, opacity);
ChangeOpacity?.Invoke(opacity);
}
else if (opacity < ShownMinus)
else if (Properties.Settings.Default.UseFading &&
opacity < ShownMinus)
{
opacity += StepIn;
ChangeOpacity?.Invoke(this, opacity);
ChangeOpacity?.Invoke(opacity);
}
else if (opacity != Shown)
else
{
if (!Properties.Settings.Default.UseFading)
{
// #393 provoke a redraw for the CS_DROPSHADOW to work
opacity = ShownMinus;
ChangeOpacity?.Invoke(opacity);
}
opacity = Shown;
ChangeOpacity?.Invoke(this, Shown);
ChangeOpacity?.Invoke(opacity);
StartStopTimer(FadingState.Idle);
}
@ -116,39 +130,47 @@ namespace SystemTrayMenu.UserInterface
visible = true;
Show?.Invoke();
opacity = 0;
ChangeOpacity?.Invoke(this, opacity);
ChangeOpacity?.Invoke(opacity);
}
else if (opacity < TransparentMinus)
else if (Properties.Settings.Default.UseFading &&
opacity < TransparentMinus)
{
opacity += StepIn;
ChangeOpacity?.Invoke(this, opacity);
ChangeOpacity?.Invoke(opacity);
}
else if (opacity > TransparentPlus)
else if (Properties.Settings.Default.UseFading &&
opacity > TransparentPlus)
{
opacity -= StepOut;
ChangeOpacity?.Invoke(this, opacity);
ChangeOpacity?.Invoke(opacity);
}
else if (opacity != Transparent)
else
{
ChangeOpacity?.Invoke(this, Transparent);
opacity = Transparent;
ChangeOpacity?.Invoke(opacity);
StartStopTimer(FadingState.Idle);
}
break;
case FadingState.Hide:
if (opacity > StepOut)
if (Properties.Settings.Default.UseFading &&
opacity > StepOut)
{
opacity -= StepOut;
ChangeOpacity?.Invoke(this, opacity);
ChangeOpacity?.Invoke(opacity);
}
else if (visible)
{
opacity = 0;
ChangeOpacity?.Invoke(this, opacity);
ChangeOpacity?.Invoke(opacity);
visible = false;
Hide?.Invoke();
StartStopTimer(FadingState.Idle);
}
else
{
StartStopTimer(FadingState.Idle);
}
break;
case FadingState.Idle:

147
Helpers/ImagingHelper.cs Normal file
View file

@ -0,0 +1,147 @@
// <copyright file="ImagingHelper.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helper
{
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
/// <summary>
/// Provides helper methods for imaging.
/// </summary>
public static class ImagingHelper
{
/// <summary>
/// Converts a PNG image to a icon (ico).
/// </summary>
/// <param name="input">The input stream.</param>
/// <param name="output">The output stream.</param>
/// <param name="size">The size (16x16 px by default).</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio.</param>
/// <returns>Wether or not the icon was succesfully generated.</returns>
public static bool ConvertToIcon(Stream input, Stream output, int size = 16, bool preserveAspectRatio = false)
{
Bitmap inputBitmap = (Bitmap)Image.FromStream(input);
if (inputBitmap != null)
{
int width, height;
if (preserveAspectRatio)
{
width = size;
height = inputBitmap.Height / inputBitmap.Width * size;
}
else
{
width = height = size;
}
Bitmap newBitmap = new(inputBitmap, new Size(width, height));
if (newBitmap != null)
{
// save the resized png into a memory stream for future use
using MemoryStream memoryStream = new();
newBitmap.Save(memoryStream, ImageFormat.Png);
BinaryWriter iconWriter = new(output);
if (output != null && iconWriter != null)
{
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)1);
// image entry 1
// 0 image width
iconWriter.Write((byte)width);
// 1 image height
iconWriter.Write((byte)height);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)memoryStream.Length);
// 12-15 offset of image data
iconWriter.Write(6 + 16);
// write image data
// png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray());
iconWriter.Flush();
return true;
}
}
return false;
}
return false;
}
/// <summary>
/// Converts a PNG image to a icon (ico).
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="size">The size (16x16 px by default).</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio.</param>
/// <returns>Wether or not the icon was succesfully generated.</returns>
public static bool ConvertToIcon(string inputPath, string outputPath, int size = 16, bool preserveAspectRatio = false)
{
using FileStream inputStream = new(inputPath, FileMode.Open);
using FileStream outputStream = new(outputPath, FileMode.OpenOrCreate);
return ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio);
}
public static Image RotateImage(Image img, float rotationAngle)
{
// create an empty Bitmap image
Bitmap bmp = new(img.Width, img.Height);
// turn the Bitmap into a Graphics object
Graphics gfx = Graphics.FromImage(bmp);
// now we set the rotation point to the center of our image
gfx.TranslateTransform(0.5f + ((float)bmp.Width / 2), 0.5f + ((float)bmp.Height / 2));
// now rotate the image
gfx.RotateTransform(rotationAngle);
gfx.TranslateTransform(0.5f - ((float)bmp.Width / 2), 0.5f - ((float)bmp.Height / 2));
// set the InterpolationMode to HighQualityBicubic so to ensure a high
// quality image once it is transformed to the specified size
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
// now draw our new image onto the graphics object
gfx.DrawImage(img, new Point(0, 0));
// dispose of our Graphics object
gfx.Dispose();
// return the image
return bmp;
}
}
}

215
Helpers/JoystickHelper.cs Normal file
View file

@ -0,0 +1,215 @@
// <copyright file="JoystickHelper.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helpers
{
using System;
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Reflection.Metadata;
using System.Threading;
using System.Windows.Forms;
using SharpDX.DirectInput;
public class JoystickHelper : IDisposable
{
private readonly System.Timers.Timer timerReadJoystick = new();
private readonly object lockRead = new();
private Joystick joystick;
private Keys pressingKey;
private int pressingKeyCounter;
private bool joystickHelperEnabled;
public JoystickHelper()
{
timerReadJoystick.Interval = 80;
timerReadJoystick.Elapsed += ReadJoystickLoop;
timerReadJoystick.Enabled = false;
if (Properties.Settings.Default.SupportGamepad)
{
timerReadJoystick.Start();
}
}
~JoystickHelper() // the finalizer
{
Dispose(false);
}
public event Action<Keys> KeyPressed;
public void Enable()
{
joystickHelperEnabled = true;
}
public void Disable()
{
joystickHelperEnabled = false;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
timerReadJoystick.Elapsed -= ReadJoystickLoop;
timerReadJoystick?.Dispose();
joystick?.Dispose();
}
}
private static Keys ReadKeyFromState(JoystickUpdate state)
{
Keys keys = Keys.None;
switch (state.Offset)
{
case JoystickOffset.PointOfViewControllers0:
switch (state.Value)
{
case 0:
keys = Keys.Up;
break;
case 9000:
keys = Keys.Right;
break;
case 18000:
keys = Keys.Down;
break;
case 27000:
keys = Keys.Left;
break;
default:
break;
}
break;
case JoystickOffset.Buttons0:
if (state.Value == 128)
{
keys = Keys.Enter;
}
break;
default:
break;
}
return keys;
}
private void ReadJoystickLoop(object sender, System.Timers.ElapsedEventArgs e)
{
if (joystickHelperEnabled)
{
lock (lockRead)
{
timerReadJoystick.Stop();
if (joystick == null)
{
Thread.Sleep(3000);
InitializeJoystick();
}
else
{
ReadJoystick();
}
timerReadJoystick.Start();
}
}
}
private void ReadJoystick()
{
try
{
joystick.Poll();
JoystickUpdate[] datas = joystick.GetBufferedData();
foreach (JoystickUpdate state in datas)
{
if (state.Value < 0)
{
pressingKey = Keys.None;
pressingKeyCounter = 0;
continue;
}
Keys key = ReadKeyFromState(state);
if (key != Keys.None)
{
KeyPressed?.Invoke(key);
if (state.Offset == JoystickOffset.PointOfViewControllers0)
{
pressingKeyCounter = 0;
pressingKey = key;
}
}
}
if (pressingKey != Keys.None)
{
pressingKeyCounter += 1;
if (pressingKeyCounter > 1)
{
KeyPressed?.Invoke(pressingKey);
}
}
}
catch
{
joystick?.Dispose();
joystick = null;
}
}
private void InitializeJoystick()
{
// Initialize DirectInput
DirectInput directInput = new();
// Find a Joystick Guid
Guid joystickGuid = Guid.Empty;
foreach (DeviceInstance deviceInstance in directInput.GetDevices(
DeviceType.Gamepad,
DeviceEnumerationFlags.AllDevices))
{
joystickGuid = deviceInstance.InstanceGuid;
}
// If Gamepad not found, look for a Joystick
if (joystickGuid == Guid.Empty)
{
foreach (DeviceInstance deviceInstance in directInput.GetDevices(
DeviceType.Joystick,
DeviceEnumerationFlags.AllDevices))
{
joystickGuid = deviceInstance.InstanceGuid;
}
}
// If Joystick found
if (joystickGuid != Guid.Empty)
{
// Instantiate the joystick
joystick = new Joystick(directInput, joystickGuid);
// Set BufferSize in order to use buffered data.
joystick.Properties.BufferSize = 128;
var handle = Process.GetCurrentProcess().MainWindowHandle;
joystick.SetCooperativeLevel(handle, CooperativeLevel.NonExclusive | CooperativeLevel.Background);
// Acquire the joystick
joystick.Acquire();
}
}
}
}

View file

@ -12,16 +12,15 @@ namespace SystemTrayMenu.Helper
/// </summary>
internal class KeyPressedEventArgs : EventArgs
{
private readonly KeyboardHookModifierKeys modifier;
private readonly Keys key;
internal KeyPressedEventArgs(KeyboardHookModifierKeys modifier, Keys key)
{
this.modifier = modifier;
Modifier = modifier;
this.key = key;
}
internal KeyboardHookModifierKeys Modifier => modifier;
internal KeyboardHookModifierKeys Modifier { get; }
internal Keys Key => key;
}

View file

@ -13,7 +13,7 @@ namespace SystemTrayMenu.Helper
/// The enumeration of possible modifiers.
/// </summary>
[Flags]
internal enum KeyboardHookModifierKeys : uint
public enum KeyboardHookModifierKeys : uint
{
None = 0,
Alt = 1,
@ -24,16 +24,13 @@ namespace SystemTrayMenu.Helper
public sealed class KeyboardHook : IDisposable
{
private readonly Window window = new Window();
private readonly Window window = new();
private int currentId;
public KeyboardHook()
{
// register the event of the inner native window.
window.KeyPressed += (sender, args) =>
{
KeyPressed?.Invoke(this, args);
};
window.KeyPressed += Window_KeyPressed;
}
/// <summary>
@ -50,6 +47,7 @@ namespace SystemTrayMenu.Helper
}
// dispose the inner native window.
window.KeyPressed -= Window_KeyPressed;
window.Dispose();
}
@ -107,6 +105,11 @@ namespace SystemTrayMenu.Helper
RegisterHotKey((uint)modifier, key);
}
private void Window_KeyPressed(object sender, KeyPressedEventArgs e)
{
KeyPressed?.Invoke(this, e);
}
private void RegisterHotKey(uint modifier, Keys key)
{
currentId += 1;

View file

@ -0,0 +1,251 @@
// <copyright file="GitHubUpdate.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helper.Updater
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Net.Http;
using System.Reflection;
using System.Windows.Forms;
using SystemTrayMenu.Utilities;
public class GitHubUpdate
{
private static List<Dictionary<string, object>> releases;
private static Form newVersionForm;
public static void ActivateNewVersionFormOrCheckForUpdates(bool showWhenUpToDate)
{
if (newVersionForm != null)
{
newVersionForm.HandleInvoke(newVersionForm.Activate);
}
else
{
CheckForUpdates(showWhenUpToDate);
}
}
private static void CheckForUpdates(bool showWhenUpToDate)
{
string urlGithubReleases = @"http://api.github.com/repos/Hofknecht/SystemTrayMenu/releases";
HttpClient client = new();
// https://developer.github.com/v3/#user-agent-required
client.DefaultRequestHeaders.Add("User-Agent", "SystemTrayMenu/" + Application.ProductVersion.ToString());
// https://developer.github.com/v3/media/#request-specific-version
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3.text+json");
try
{
using HttpResponseMessage response = client.GetAsync(urlGithubReleases).Result;
using HttpContent content = response.Content;
string responseString = content.ReadAsStringAsync().Result;
releases = responseString.FromJson<List<Dictionary<string, object>>>();
}
catch (Exception ex)
{
Log.Warn($"{nameof(CheckForUpdates)} failed", ex);
}
if (releases == null)
{
Log.Info($"{nameof(CheckForUpdates)} failed.");
}
else
{
RemoveCurrentAndOlderVersions();
ShowNewVersionOrUpToDateDialog(showWhenUpToDate);
}
newVersionForm?.Dispose();
newVersionForm = null;
}
private static void RemoveCurrentAndOlderVersions()
{
int releasesCount = releases.Count;
Version versionCurrent = Assembly.GetExecutingAssembly().GetName().Version;
for (int i = 0; i < releasesCount; i++)
{
string tagName = releases[i]["tag_name"].ToString();
Version versionGitHub = new(tagName.Replace("v", string.Empty));
if (versionGitHub.CompareTo(versionCurrent) < 1)
{
releases.RemoveRange(i, releasesCount - i);
break;
}
}
}
private static void ShowNewVersionOrUpToDateDialog(bool showWhenUpToDate)
{
if (releases.Count > 0)
{
if (NewVersionDialog() == DialogResult.Yes)
{
Log.ProcessStart("https://github.com/Hofknecht/SystemTrayMenu/releases");
}
}
else if (showWhenUpToDate)
{
MessageBox.Show(Translator.GetText("You have the latest version of SystemTrayMenu!"));
}
}
/// <summary>
/// Creates a window to show changelog of new available versions.
/// </summary>
/// <param name="LatestVersionTitle">Name of latest release.</param>
/// <param name="Changelog">Pathnotes.</param>
/// <returns>OK = OK, Yes = Website, else = Cancel.</returns>
private static DialogResult NewVersionDialog()
{
const int ClientPad = 15;
newVersionForm = new()
{
StartPosition = FormStartPosition.CenterScreen,
FormBorderStyle = FormBorderStyle.FixedDialog,
Icon = Config.GetAppIcon(),
ShowInTaskbar = false,
};
newVersionForm.FormBorderStyle = FormBorderStyle.Sizable;
newVersionForm.MaximizeBox = true;
newVersionForm.MinimizeBox = false;
newVersionForm.ClientSize = new Size(600, 400);
newVersionForm.MinimumSize = newVersionForm.ClientSize;
newVersionForm.Text = Translator.GetText("New version available!");
Label label = new()
{
Size = new Size(newVersionForm.ClientSize.Width - ClientPad, 20),
Location = new Point(ClientPad, ClientPad),
Text = $"{Translator.GetText("Latest available version:")} {GetLatestVersionName()}",
};
newVersionForm.Controls.Add(label);
Button buttonOK = new()
{
DialogResult = DialogResult.OK,
Name = "buttonOK",
};
buttonOK.Location = new Point(
newVersionForm.ClientSize.Width - buttonOK.Size.Width - ClientPad,
newVersionForm.ClientSize.Height - buttonOK.Size.Height - ClientPad);
buttonOK.MinimumSize = new Size(75, 23);
buttonOK.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonOK.Text = Translator.GetText("OK");
buttonOK.AutoSizeMode = AutoSizeMode.GrowAndShrink;
buttonOK.AutoSize = true;
newVersionForm.Controls.Add(buttonOK);
Button buttonGoToDownloadPage = new()
{
DialogResult = DialogResult.Yes,
Name = "buttonGoToDownloadPage",
};
buttonGoToDownloadPage.Location = new Point(
newVersionForm.ClientSize.Width - buttonGoToDownloadPage.Size.Width - ClientPad - buttonOK.Size.Width - ClientPad,
newVersionForm.ClientSize.Height - buttonGoToDownloadPage.Size.Height - ClientPad);
buttonGoToDownloadPage.MinimumSize = new Size(75, 23);
buttonGoToDownloadPage.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonGoToDownloadPage.Text = Translator.GetText("Go to download page");
buttonGoToDownloadPage.AutoSizeMode = AutoSizeMode.GrowAndShrink;
buttonGoToDownloadPage.AutoSize = true;
newVersionForm.Controls.Add(buttonGoToDownloadPage);
TextBox textBox = new()
{
Location = new Point(ClientPad, label.Location.Y + label.Size.Height + 5),
};
textBox.Size = new Size(
newVersionForm.ClientSize.Width - (ClientPad * 2),
buttonOK.Location.Y - ClientPad - textBox.Location.Y);
textBox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
textBox.Multiline = true;
textBox.Text = GetChangelog();
textBox.ReadOnly = true;
textBox.ScrollBars = ScrollBars.Both;
textBox.BackColor = Color.FromKnownColor(KnownColor.Window);
textBox.ForeColor = Color.FromKnownColor(KnownColor.ControlText);
newVersionForm.Controls.Add(textBox);
newVersionForm.AcceptButton = buttonOK;
return newVersionForm.ShowDialog();
}
/// <summary>
/// Returns the latest release version name.
/// </summary>
/// <returns>Version name.</returns>
private static string GetLatestVersionName()
{
string result = "Unknown";
if (releases == null)
{
return result;
}
try
{
result = releases[0]["tag_name"].ToString().Replace("v", string.Empty);
}
catch (Exception ex)
{
Log.Warn($"{nameof(GetLatestVersionName)} failed", ex);
}
return result;
}
/// <summary>
/// Returns the change log from current version up to the latest release version.
/// </summary>
/// <returns>Change log summary or error text.</returns>
private static string GetChangelog()
{
string result = string.Empty;
string errorstr = "An error occurred during update check!" + Environment.NewLine;
if (releases == null)
{
return errorstr + "Could not receive changelog!";
}
try
{
for (int i = 0; i < releases.Count; i++)
{
Dictionary<string, object> release = releases[i];
result += release["name"].ToString()
+ Environment.NewLine
+ release["body_text"].ToString()
.Replace("\n\n", Environment.NewLine)
.Replace("\n \n", Environment.NewLine)
+ Environment.NewLine + Environment.NewLine;
if (i < releases.Count)
{
result += "--------------------------------------------------" +
"-------------------------------------------------------"
+ Environment.NewLine;
}
}
result = result.Replace("\n", Environment.NewLine);
}
catch (Exception ex)
{
Log.Warn($"{nameof(GetChangelog)}", ex);
result = errorstr + ex.Message.ToString();
}
return result;
}
}
}

View file

@ -0,0 +1,480 @@
// <copyright file="JsonParser.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helper.Updater
{
// Copyright (c) 2018 Alex Parker
// Copyright (c) 2018-2019 Peter Kirmeier
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
// Really simple JSON parser in ~300 lines
// - Attempts to parse JSON files with minimal GC allocation
// - Nice and simple "[1,2,3]".FromJson<List<int>>() API
// - Classes and structs can be parsed too!
// class Foo { public int Value; }
// "{\"Value\":10}".FromJson<Foo>()
// - Can parse JSON without type information into Dictionary<string,object> and List<object> e.g.
// "[1,2,3]".FromJson<object>().GetType() == typeof(List<object>)
// "{\"Value\":10}".FromJson<object>().GetType() == typeof(Dictionary<string,object>)
// - No JIT Emit support to support AOT compilation on iOS
// - Attempts are made to NOT throw an exception if the JSON is corrupted or invalid: returns null instead.
// - Only public fields and property setters on classes/structs will be written to
//
// Limitations:
// - No JIT Emit support to parse structures quickly
// - Limited to parsing <2GB JSON files (due to int.MaxValue)
// - Parsing of abstract classes or interfaces is NOT supported and will throw an exception.
public static class JSONParser
{
[ThreadStatic]
private static Stack<List<string>> splitArrayPool;
[ThreadStatic]
private static StringBuilder stringBuilder;
[ThreadStatic]
private static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfoCache;
[ThreadStatic]
private static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyInfoCache;
public static T FromJson<T>(this string json)
{
// Initialize, if needed, the ThreadStatic variables
propertyInfoCache ??= new Dictionary<Type, Dictionary<string, PropertyInfo>>();
fieldInfoCache ??= new Dictionary<Type, Dictionary<string, FieldInfo>>();
stringBuilder ??= new StringBuilder();
splitArrayPool ??= new Stack<List<string>>();
// Remove all whitespace not within strings to make parsing simpler
stringBuilder.Length = 0;
for (int i = 0; i < json.Length; i++)
{
char c = json[i];
if (c == '"')
{
i = AppendUntilStringEnd(true, i, json);
continue;
}
if (char.IsWhiteSpace(c))
{
continue;
}
stringBuilder.Append(c);
}
// Parse the thing!
return (T)ParseValue(typeof(T), stringBuilder.ToString());
}
internal static object ParseValue(Type type, string json)
{
if (type == typeof(string))
{
if (json.Length <= 2)
{
return string.Empty;
}
StringBuilder parseStringBuilder = new(json.Length);
for (int i = 1; i < json.Length - 1; ++i)
{
if (json[i] == '\\' && i + 1 < json.Length - 1)
{
int j = "\"\\nrtbf/".IndexOf(json[i + 1]);
if (j >= 0)
{
parseStringBuilder.Append("\"\\\n\r\t\b\f/"[j]);
++i;
continue;
}
if (json[i + 1] == 'u' && i + 5 < json.Length - 1)
{
if (uint.TryParse(json.AsSpan(i + 2, 4), System.Globalization.NumberStyles.AllowHexSpecifier, null, out uint c))
{
parseStringBuilder.Append((char)c);
i += 5;
continue;
}
}
}
parseStringBuilder.Append(json[i]);
}
return parseStringBuilder.ToString();
}
if (type.IsPrimitive)
{
var result = Convert.ChangeType(json, type, System.Globalization.CultureInfo.InvariantCulture);
return result;
}
if (type == typeof(decimal))
{
decimal.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out decimal result);
return result;
}
if (json == "null")
{
return null;
}
if (type.IsEnum)
{
if (json[0] == '"')
{
json = json[1..^1];
}
try
{
return Enum.Parse(type, json, false);
}
catch
{
return 0;
}
}
if (type.IsArray)
{
Type arrayType = type.GetElementType();
if (json[0] != '[' || json[^1] != ']')
{
return null;
}
List<string> elems = Split(json);
Array newArray = Array.CreateInstance(arrayType, elems.Count);
for (int i = 0; i < elems.Count; i++)
{
newArray.SetValue(ParseValue(arrayType, elems[i]), i);
}
splitArrayPool.Push(elems);
return newArray;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
Type listType = type.GetGenericArguments()[0];
if (json[0] != '[' || json[^1] != ']')
{
return null;
}
List<string> elems = Split(json);
var list = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count });
for (int i = 0; i < elems.Count; i++)
{
list.Add(ParseValue(listType, elems[i]));
}
splitArrayPool.Push(elems);
return list;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
Type keyType, valueType;
{
Type[] args = type.GetGenericArguments();
keyType = args[0];
valueType = args[1];
}
// Refuse to parse dictionary keys that aren't of type string
if (keyType != typeof(string))
{
return null;
}
// Must be a valid dictionary element
if (json[0] != '{' || json[^1] != '}')
{
return null;
}
// The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
{
return null;
}
var dictionary = (IDictionary)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count / 2 });
for (int i = 0; i < elems.Count; i += 2)
{
if (elems[i].Length <= 2)
{
continue;
}
string keyValue = elems[i][1..^1];
object val = ParseValue(valueType, elems[i + 1]);
dictionary.Add(keyValue, val);
}
return dictionary;
}
if (type == typeof(object))
{
return ParseAnonymousValue(json);
}
if (json[0] == '{' && json[^1] == '}')
{
return ParseObject(type, json);
}
return null;
}
private static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json)
{
stringBuilder.Append(json[startIdx]);
for (int i = startIdx + 1; i < json.Length; i++)
{
if (json[i] == '\\')
{
if (appendEscapeCharacter)
{
stringBuilder.Append(json[i]);
}
stringBuilder.Append(json[i + 1]);
i++; // Skip next character as it is escaped
}
else if (json[i] == '"')
{
stringBuilder.Append(json[i]);
return i;
}
else
{
stringBuilder.Append(json[i]);
}
}
return json.Length - 1;
}
// Splits { <value>:<value>, <value>:<value> } and [ <value>, <value> ] into a list of <value> strings
private static List<string> Split(string json)
{
List<string> splitArray = splitArrayPool.Count > 0 ? splitArrayPool.Pop() : new List<string>();
splitArray.Clear();
if (json.Length == 2)
{
return splitArray;
}
int parseDepth = 0;
stringBuilder.Length = 0;
for (int i = 1; i < json.Length - 1; i++)
{
switch (json[i])
{
case '[':
case '{':
parseDepth++;
break;
case ']':
case '}':
parseDepth--;
break;
case '"':
i = AppendUntilStringEnd(true, i, json);
continue;
case ',':
case ':':
if (parseDepth == 0)
{
splitArray.Add(stringBuilder.ToString());
stringBuilder.Length = 0;
continue;
}
break;
}
stringBuilder.Append(json[i]);
}
splitArray.Add(stringBuilder.ToString());
return splitArray;
}
private static object ParseAnonymousValue(string json)
{
if (json.Length == 0)
{
return null;
}
if (json[0] == '{' && json[^1] == '}')
{
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
{
return null;
}
var dict = new Dictionary<string, object>(elems.Count / 2);
for (int i = 0; i < elems.Count; i += 2)
{
dict.Add(elems[i][1..^1], ParseAnonymousValue(elems[i + 1]));
}
return dict;
}
if (json[0] == '[' && json[^1] == ']')
{
List<string> items = Split(json);
var finalList = new List<object>(items.Count);
for (int i = 0; i < items.Count; i++)
{
finalList.Add(ParseAnonymousValue(items[i]));
}
return finalList;
}
if (json[0] == '"' && json[^1] == '"')
{
return ParseValue(typeof(string), json); // fix https://github.com/zanders3/json/issues/29
}
if (char.IsDigit(json[0]) || json[0] == '-')
{
if (json.Contains('.'))
{
double.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double result);
return result;
}
else
{
_ = int.TryParse(json, out int result);
return result;
}
}
if (json == "true")
{
return true;
}
if (json == "false")
{
return false;
}
// handles json == "null" as well as invalid JSON
return null;
}
private static Dictionary<string, T> CreateMemberNameDictionary<T>(T[] members)
where T : MemberInfo
{
Dictionary<string, T> nameToMember = new(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < members.Length; i++)
{
/*T member = members[i];
if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true))
continue;
string name = member.Name;
if (member.IsDefined(typeof(DataMemberAttribute), true))
{
DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true);
if (!string.IsNullOrEmpty(dataMemberAttribute.Name))
name = dataMemberAttribute.Name;
}
nameToMember.Add(name, member);*/
// The above code is not working with .Net framework 2.0, so we ignore these attributes for compatibility reasons:
nameToMember.Add(members[i].Name, members[i]);
}
return nameToMember;
}
private static object ParseObject(Type type, string json)
{
object instance = FormatterServices.GetUninitializedObject(type);
// The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
{
return instance;
}
if (!fieldInfoCache.TryGetValue(type, out Dictionary<string, FieldInfo> nameToField))
{
nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
fieldInfoCache.Add(type, nameToField);
}
if (!propertyInfoCache.TryGetValue(type, out Dictionary<string, PropertyInfo> nameToProperty))
{
nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
propertyInfoCache.Add(type, nameToProperty);
}
for (int i = 0; i < elems.Count; i += 2)
{
if (elems[i].Length <= 2)
{
continue;
}
string key = elems[i][1..^1];
string value = elems[i + 1];
if (nameToField.TryGetValue(key, out FieldInfo fieldInfo))
{
fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value));
}
else if (nameToProperty.TryGetValue(key, out PropertyInfo propertyInfo))
{
propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null);
}
}
return instance;
}
}
}

View file

@ -26,7 +26,7 @@ namespace SystemTrayMenu.Helper
{
IntPtr taskbarHandle = User32FindWindow(ClassName, null);
APPBARDATA data = new APPBARDATA
APPBARDATA data = new()
{
cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA)),
hWnd = taskbarHandle,

View file

@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
TAMAHO SystemTrayMenu - browse and open your files easily
Copyright (C) 2020 Markus Hofknecht
Copyright (C) 2022 Markus Hofknecht
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -652,7 +652,7 @@ You can contact me by mail Markus@Hofknecht.eu
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
TAMAHO SystemTrayMenu Copyright (C) 2020 Markus Hofknecht
TAMAHO SystemTrayMenu Copyright (C) 2022 Markus Hofknecht
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

View file

@ -42,27 +42,27 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern uint GetCurrentThreadId();
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern bool BringWindowToTop(IntPtr hWnd);
}
}

View file

@ -19,7 +19,7 @@ namespace SystemTrayMenu.DllImports
// The CreatePopupMenu function creates a drop-down menu, submenu, or shortcut menu. The menu is initially empty. You can insert or append menu items by using the InsertMenuItem function. You can also use the InsertMenu function to insert menu items and the AppendMenu function to append menu items.
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern IntPtr CreatePopupMenu();
}
}

View file

@ -0,0 +1,40 @@
// <copyright file="CreateRoundRectRgn.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.DllImports
{
using System;
using System.Runtime.InteropServices;
/// <summary>
/// wraps the methodcalls to native windows dll's.
/// </summary>
public static partial class NativeMethods
{
public static bool GetRegionRoundCorners(int width, int height, int widthEllipse, int heightEllipse, out System.Drawing.Region region)
{
bool success = false;
region = null;
IntPtr handle = CreateRoundRectRgn(0, 0, width, height, widthEllipse, heightEllipse);
if (handle != IntPtr.Zero)
{
region = System.Drawing.Region.FromHrgn(handle);
_ = DeleteObject(handle);
success = true;
}
return success;
}
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreateRoundRectRgn(
int nLeftRect, // x-coordinate of upper-left corner
int nTopRect, // y-coordinate of upper-left corner
int nRightRect, // x-coordinate of lower-right corner
int nBottomRect, // y-coordinate of lower-right corner
int nWidthEllipse, // width of ellipse
int nHeightEllipse); // height of ellipse
}
}

View file

@ -1,4 +1,4 @@
// <copyright file="GetDeviceCaps.cs" company="PlaceholderCompany">
// <copyright file="DeleteObject.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
@ -12,13 +12,8 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
public static int Gdi32GetDeviceCaps(IntPtr hdc, int nIndex)
{
return GetDeviceCaps(hdc, nIndex);
}
[DllImport("gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int DeleteObject(IntPtr hIcon);
}
}

View file

@ -18,7 +18,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int DestroyIcon(IntPtr hIcon);
}
}

View file

@ -19,7 +19,7 @@ namespace SystemTrayMenu.DllImports
// The DestroyMenu function destroys the specified menu and frees any memory that the menu occupies.
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern bool DestroyMenu(IntPtr hMenu);
}
}

View file

@ -18,7 +18,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);
}
}

View file

@ -18,7 +18,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}
}

View file

@ -12,7 +12,6 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
#pragma warning disable SA1600 // Elements should be documented
public const uint ShgfiIcon = 0x000000100; // get icon
public const uint ShgfiSYSICONINDEX = 0x000004000; // get system icon index
public const uint ShgfiLINKOVERLAY = 0x000008000; // put a link overlay on icon
@ -22,16 +21,6 @@ namespace SystemTrayMenu.DllImports
public const uint FileAttributeDirectory = 0x00000010;
public const uint FileAttributeNormal = 0x00000080;
public const int IldTransparent = 0x00000001;
#pragma warning restore SA1600 // Elements should be documented
/// <summary>
/// comctl32 ImageList_GetIcon(IntPtr hIcon).
/// </summary>
/// <param name="hIcon">hIcon.</param>
public static void Comctl32ImageListGetIcon(IntPtr hIcon)
{
_ = DestroyIcon(hIcon);
}
/// <summary>
/// comctl32 ImageList_GetIcon(IntPtr himl, int i, int flags).
@ -41,7 +30,7 @@ namespace SystemTrayMenu.DllImports
/// <param name="flags">flags.</param>
/// <returns>IntPtr.</returns>
[DllImport("comctl32", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
internal static extern IntPtr ImageList_GetIcon(
IntPtr himl,
int i,

View file

@ -1,25 +0,0 @@
// <copyright file="GetMenuDefaultItem.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.DllImports
{
using System;
using System.Runtime.InteropServices;
/// <summary>
/// wraps the methodcalls to native windows dll's.
/// </summary>
public static partial class NativeMethods
{
public static int User32GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags)
{
return GetMenuDefaultItem(hMenu, fByPos, gmdiFlags);
}
// Determines the default menu item on the specified menu
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags);
}
}

View file

@ -20,7 +20,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int GetSystemMetrics(int nIndex);
}
}

View file

@ -34,21 +34,21 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKeyCode);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize);
}
}

View file

@ -41,7 +41,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern IntPtr SHAppBarMessage(ABM dwMessage, [In] ref APPBARDATA pData);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]

View file

@ -19,7 +19,7 @@ namespace SystemTrayMenu.DllImports
// Retrieves the IShellFolder interface for the desktop folder, which is the root of the Shell's namespace.
[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int SHGetDesktopFolder(out IntPtr ppshf);
}
}

View file

@ -30,7 +30,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern IntPtr SHGetFileInfo(
string pszPath,
uint dwFileAttributes,

View file

@ -19,7 +19,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("shfolder.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath);
}
}

View file

@ -33,7 +33,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern bool SetWindowPos(
int hWnd, // Window handle
int hWndInsertAfter, // Placement-order handle

View file

@ -13,7 +13,7 @@ namespace SystemTrayMenu.DllImports
public static partial class NativeMethods
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
}

View file

@ -17,7 +17,7 @@ namespace SystemTrayMenu.DllImports
}
[DllImport("shlwapi.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int StrCmpLogicalW(string x, string y);
}
}

View file

@ -20,7 +20,7 @@ namespace SystemTrayMenu.DllImports
// Takes a STRRET structure returned by IShellFolder::GetDisplayNameOf, converts it to a string, and places the result in a buffer.
[DllImport("shlwapi.dll", EntryPoint = "StrRetToBuf", ExactSpelling = false, SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int StrRetToBuf(IntPtr pstr, IntPtr pidl, StringBuilder pszBuf, int cchBuf);
}
}

View file

@ -18,7 +18,6 @@ namespace SystemTrayMenu.DllImports
[Flags]
internal enum TPM : uint
{
#pragma warning disable SA1602 // Enumeration items should be documented
LEFTBUTTON = 0x0000, // LEFTALIGN = 0x0000, // TOPALIGN = 0x0000, // HORIZONTAL = 0x0000,
RIGHTBUTTON = 0x0002,
CENTERALIGN = 0x0004,
@ -35,7 +34,6 @@ namespace SystemTrayMenu.DllImports
VERNEGANIMATION = 0x2000,
NOANIMATION = 0x4000,
LAYOUTRTL = 0x8000,
#pragma warning restore SA1602 // Enumeration items should be documented
}
/// <summary>
@ -55,7 +53,7 @@ namespace SystemTrayMenu.DllImports
// The TrackPopupMenuEx function displays a shortcut menu at the specified location and tracks the selection of items on the shortcut menu. The shortcut menu can appear anywhere on the screen.
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern uint TrackPopupMenuEx(IntPtr hmenu, TPM flags, int x, int y, IntPtr hwnd, IntPtr lptpm);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 B

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 KiB

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 B

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 B

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Some files were not shown because too many files have changed in this diff Show more