Compare commits

...

505 commits

Author SHA1 Message Date
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
270 changed files with 61553 additions and 8762 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

@ -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,7 +17,7 @@ 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;
@ -27,26 +27,27 @@ namespace SystemTrayMenu.Handler
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; }
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,7 +6,6 @@ namespace SystemTrayMenu
{
using System;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using SystemTrayMenu.Utilities;
@ -15,25 +14,22 @@ namespace SystemTrayMenu
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();
@ -44,10 +40,11 @@ namespace SystemTrayMenu
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);
}
@ -55,28 +52,37 @@ 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);
Log.ProcessStart("mailto:" + "markus@hofknecht.eu" +
"?subject=SystemTrayMenu Bug reported " +
Assembly.GetEntryAssembly().GetName().Version +
"&body=" + ex.ToString());
}
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());
}
if (!isStartup)
{
AppRestart.ByThreadException();
}
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,7 +13,7 @@ namespace SystemTrayMenu.Handler
internal class WaitToLoadMenu : IDisposable
{
private readonly Timer timerStartLoad = new Timer();
private readonly Timer timerStartLoad = new();
private DataGridView dgv;
private int rowIndex;
private DataGridView dgvTmp;
@ -25,7 +25,7 @@ namespace SystemTrayMenu.Handler
internal WaitToLoadMenu()
{
timerStartLoad.Interval = 200;
timerStartLoad.Interval = Properties.Settings.Default.TimeUntilOpens;
timerStartLoad.Tick += WaitStartLoad_Tick;
}
@ -33,7 +33,7 @@ namespace SystemTrayMenu.Handler
internal event Action<int> CloseMenu;
internal event EventHandlerEmpty StopLoadMenu;
internal event Action StopLoadMenu;
internal event Action<DataGridView, int> MouseEnterOk;
@ -41,6 +41,7 @@ namespace SystemTrayMenu.Handler
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

@ -5,118 +5,146 @@
namespace SystemTrayMenu
{
using System;
using System.Diagnostics;
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
{
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;
private static bool isDarkMode;
private static bool readHideFileExtdone;
private static bool isHideFileExtension;
public static bool IsHideFileExtdone => IsHideFileExtension();
public static string Path => Settings.Default.PathDirectory;
public static string Path => Properties.Settings.Default.PathDirectory;
public static string SearchPattern => Settings.Default.SearchPattern;
public static void UpgradeIfNotUpgraded()
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))
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.IsUpgraded = true;
Properties.Settings.Default.Save();
FileVersionInfo versionInfo = FileVersionInfo.
GetVersionInfo(Assembly.GetEntryAssembly().Location);
string upgradedFromPath = $"%localappdata%\\{versionInfo.CompanyName}\\";
try
Settings.Default.PathIcoDirectory = System.IO.Path.Combine(
System.IO.Path.Combine(
Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData), $"SystemTrayMenu"), "ico");
if (!Directory.Exists(Settings.Default.PathIcoDirectory))
{
upgradedFromPath = System.IO.Path.GetFullPath(upgradedFromPath);
Directory.CreateDirectory(Settings.Default.PathIcoDirectory);
}
catch (Exception ex)
{
if (ex is ArgumentException ||
ex is System.Security.SecurityException ||
ex is NotSupportedException ||
ex is PathTooLongException)
{
Log.Warn($"Resolve path {upgradedFromPath} failed", ex);
}
else
{
throw;
}
}
Log.Info($"Settings upgraded from {upgradedFromPath}");
}
}
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>
@ -128,7 +156,7 @@ namespace SystemTrayMenu
if (!readDarkModeDone)
{
// 0 = Dark mode, 1 = Light mode
if (Properties.Settings.Default.IsDarkModeAlwaysOn ||
if (Settings.Default.IsDarkModeAlwaysOn ||
IsRegistryValueThisValue(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize",
"AppsUseLightTheme",
@ -143,10 +171,16 @@ namespace SystemTrayMenu
return isDarkMode;
}
internal static void ResetReadDarkModeDone()
{
isDarkMode = false;
readDarkModeDone = false;
}
/// <summary>
/// Read the OS setting whether HideFileExt enabled.
/// </summary>
/// <returns>true = Dark mode; false = Light mode.</returns>
/// <returns>isHideFileExtension.</returns>
internal static bool IsHideFileExtension()
{
if (!readHideFileExtdone)
@ -166,6 +200,269 @@ namespace SystemTrayMenu
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;
@ -198,5 +495,35 @@ namespace SystemTrayMenu
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,166 +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;
private bool diposeIcon = true;
private bool isDisposed;
/// <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;
}
if (!ContainsMenu &&
Config.IsHideFileExtension())
{
row[1] = Path.GetFileNameWithoutExtension(data.text);
}
else
{
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);
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);
diposeIcon = false;
}
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 &&
@ -174,234 +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);
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);
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 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;
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) 2021 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) 2021 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

@ -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

@ -12,12 +12,8 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
internal static bool Gdi32DeleteObject(IntPtr hObject)
{
return DeleteObject(hObject);
}
[DllImport("gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool DeleteObject(IntPtr hObject);
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int DeleteObject(IntPtr hIcon);
}
}

View file

@ -1,24 +0,0 @@
// <copyright file="GetDeviceCaps.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 Gdi32GetDeviceCaps(IntPtr hdc, int nIndex)
{
return GetDeviceCaps(hdc, nIndex);
}
[DllImport("gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
}
}

View file

@ -0,0 +1,39 @@
// <copyright file="GetIcon.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 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
public const uint ShgfiLARGEICON = 0x000000000; // get large icon
public const uint ShgfiSMALLICON = 0x000000001; // get small icon
public const uint ShgfiOPENICON = 0x000000002; // get open icon
public const uint FileAttributeDirectory = 0x00000010;
public const uint FileAttributeNormal = 0x00000080;
public const int IldTransparent = 0x00000001;
/// <summary>
/// comctl32 ImageList_GetIcon(IntPtr himl, int i, int flags).
/// </summary>
/// <param name="himl">himl.</param>
/// <param name="i">i.</param>
/// <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,
int flags);
}
}

View file

@ -1,29 +0,0 @@
// <copyright file="IShellItem.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.DllImports
{
using System;
using System.Runtime.InteropServices;
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
public interface IShellItem
{
void BindToHandler(
IntPtr pbc,
[MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
[MarshalAs(UnmanagedType.LPStruct)] Guid riid,
out IntPtr ppv);
void GetParent(out IShellItem ppsi);
void GetDisplayName(SIGDN sigdnName, out IntPtr ppszName);
void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
void Compare(IShellItem psi, uint hint, out int piOrder);
}
}

View file

@ -1,20 +0,0 @@
// <copyright file="IShellItemImageFactory.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.DllImports
{
using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellItemImageFactory
{
void GetImage(
[In, MarshalAs(UnmanagedType.Struct)] SIZE size,
[In] SIIGBF flags,
[Out] out IntPtr phbm);
}
}

View file

@ -1,22 +0,0 @@
// <copyright file="SHCreateItemFromParsingName.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
{
[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
internal static extern void SHCreateItemFromParsingName(
[In][MarshalAs(UnmanagedType.LPWStr)] string pszPath,
[In] IntPtr pbc,
[In][MarshalAs(UnmanagedType.LPStruct)] Guid riid,
[Out][MarshalAs(UnmanagedType.Interface, IidParameterIndex = 2)] out IShellItem ppv);
}
}

View file

@ -0,0 +1,55 @@
// <copyright file="SHGetFileInfo.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
{
private const int maxPath = 256;
internal static IntPtr Shell32SHGetFileInfo(
string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbFileInfo,
uint uFlags)
{
return SHGetFileInfo(
pszPath,
dwFileAttributes,
ref psfi,
cbFileInfo,
uFlags);
}
[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
private static extern IntPtr SHGetFileInfo(
string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbFileInfo,
uint uFlags);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct SHFILEINFO
{
public const int NAMESIZE = 80;
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = maxPath)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAMESIZE)]
public string szTypeName;
}
}
}

View file

@ -1,18 +0,0 @@
// <copyright file="SIGDN.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.DllImports
{
public enum SIGDN : uint
{
NORMALDISPLAY = 0,
PARENTRELATIVEPARSING = 0x80018001,
PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
DESKTOPABSOLUTEPARSING = 0x80028000,
PARENTRELATIVEEDITING = 0x80031001,
DESKTOPABSOLUTEEDITING = 0x8004c000,
FILESYSPATH = 0x80058000,
URL = 0x80068000,
}
}

View file

@ -1,19 +0,0 @@
// <copyright file="SIIGBF.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.DllImports
{
using System;
[Flags]
public enum SIIGBF
{
SIIGBF_RESIZETOFIT = 0x00,
SIIGBF_BIGGERSIZEOK = 0x01,
SIIGBF_MEMORYONLY = 0x02,
SIIGBF_ICONONLY = 0x04,
SIIGBF_THUMBNAILONLY = 0x08,
SIIGBF_INCACHEONLY = 0x10,
}
}

View file

@ -1,21 +0,0 @@
// <copyright file="SIZE.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.DllImports
{
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SIZE
{
public int Cx;
public int Cy;
public SIZE(int cx, int cy)
{
Cx = cx;
Cy = cy;
}
}
}

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>

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -3,13 +3,14 @@
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="49543SystemTrayMenu.SystemTrayMenu"
Publisher="CN=5884501C-92ED-45DE-9508-9D987C314243"
Version="1.0.17.0" />
Version="1.3.5.0" />
<Properties>
<DisplayName>SystemTrayMenu</DisplayName>
@ -40,6 +41,15 @@
<uap:SplashScreen Image="Images\SplashScreen.png" />
<uap:LockScreen BadgeLogo="Images\BadgeLogo.png" Notification="badge"/>
</uap:VisualElements>
<Extensions>
<uap5:Extension
Category="windows.startupTask">
<uap5:StartupTask
TaskId="MyStartupId"
Enabled="false"
DisplayName="SystemTrayMenu" />
</uap5:Extension>
</Extensions>
</Application>
</Applications>

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