@@ -47,7 +47,7 @@ public TrayApplication()
4747 _trayIcon = new NotifyIcon
4848 {
4949 Icon = Icon . ExtractAssociatedIcon ( Application . ExecutablePath ) ?? SystemIcons . Application ,
50- Text = "Maximize to Virtual Desktop" ,
50+ Text = "Maximize to Virtual Desktop\n Ctrl+Alt+Shift+X or Shift+Click maximize button " ,
5151 Visible = true ,
5252 ContextMenuStrip = BuildContextMenu ( )
5353 } ;
@@ -103,6 +103,9 @@ protected override void OnHandleCreated(EventArgs e)
103103
104104 Trace . WriteLine ( "TrayApplication: Started." ) ;
105105
106+ // Show first-run balloon tip
107+ ShowFirstRunBalloon ( ) ;
108+
106109 // Check for updates asynchronously
107110 _ = CheckForUpdatesAsync ( ) ;
108111 }
@@ -162,6 +165,14 @@ private ContextMenuStrip BuildContextMenu()
162165
163166 menu . Items . Add ( new ToolStripSeparator ( ) ) ;
164167
168+ var howToUseItem = new ToolStripMenuItem ( "How to Use" , null , ( _ , _ ) =>
169+ {
170+ ShowUsageInfo ( ) ;
171+ } ) ;
172+ menu . Items . Add ( howToUseItem ) ;
173+
174+ menu . Items . Add ( new ToolStripSeparator ( ) ) ;
175+
165176 var updateItem = new ToolStripMenuItem ( "Check for Updates..." , null , async ( _ , _ ) =>
166177 {
167178 await CheckForUpdatesAsync ( userInitiated : true ) ;
@@ -225,6 +236,48 @@ private async Task CheckForUpdatesAsync(bool userInitiated = false)
225236 }
226237 }
227238
239+ private static readonly string FirstRunMarker = Path . Combine (
240+ Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) ,
241+ "MaximizeToVirtualDesktop" , ".firstrun" ) ;
242+
243+ private void ShowFirstRunBalloon ( )
244+ {
245+ try
246+ {
247+ if ( File . Exists ( FirstRunMarker ) ) return ;
248+
249+ Directory . CreateDirectory ( Path . GetDirectoryName ( FirstRunMarker ) ! ) ;
250+ File . WriteAllText ( FirstRunMarker , "" ) ;
251+
252+ _trayIcon . BalloonTipTitle = "Maximize to Virtual Desktop" ;
253+ _trayIcon . BalloonTipText =
254+ "Press Ctrl+Alt+Shift+X or Shift+Click the maximize button " +
255+ "to maximize a window to its own virtual desktop." ;
256+ _trayIcon . BalloonTipIcon = ToolTipIcon . Info ;
257+ _trayIcon . ShowBalloonTip ( 5000 ) ;
258+ }
259+ catch ( Exception ex )
260+ {
261+ Trace . WriteLine ( $ "TrayApplication: First-run balloon failed: { ex . Message } ") ;
262+ }
263+ }
264+
265+ private static void ShowUsageInfo ( )
266+ {
267+ MessageBox . Show (
268+ "Maximize to Virtual Desktop\n \n " +
269+ "Two ways to maximize a window to its own virtual desktop:\n \n " +
270+ " • Hotkey: Ctrl+Alt+Shift+X\n " +
271+ " Toggles the active window to/from a virtual desktop.\n \n " +
272+ " • Shift+Click the maximize button\n " +
273+ " Hold Shift and click any window's maximize button.\n \n " +
274+ "The window is moved to a new virtual desktop and maximized.\n " +
275+ "Close or restore the window to return to your original desktop.\n \n " +
276+ "Use \" Restore All\" in the tray menu to bring everything back." ,
277+ "How to Use — Maximize to Virtual Desktop" ,
278+ MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
279+ }
280+
228281 protected override void OnFormClosing ( FormClosingEventArgs e )
229282 {
230283 Trace . WriteLine ( "TrayApplication: Shutting down..." ) ;
0 commit comments