Advertisement
BurningBunny

Set window always on top from a tray icon in C#

Jul 10th, 2013
715
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.39 KB | None | 0 0
  1. /*
  2.  *
  3.  * Developed by Adam Rakaska
  4.  *  http://csharpcodewhisperer.blogspot.com
  5.  *    http://arakaska.wix.com/intelligentsoftware
  6.  *
  7.  *
  8.  * Made using SharpDevelop
  9.  *
  10.  *
  11.  */
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Diagnostics;
  15. using System.Drawing;
  16. using System.Globalization;
  17. using System.Runtime.InteropServices;
  18. using System.Threading;
  19. using System.Windows.Forms;
  20.  
  21. namespace StayOnTop
  22. {
  23.     public sealed class NotificationIcon
  24.     {
  25.         // Changelog; stores a list of windows we made topmost,
  26.         //  so we can 'roll-back' the changes upon exit.
  27.         //
  28.         // ChangeLog<WindowTitle, IsTopmost>
  29.         private Dictionary<string,bool> changeLog = new Dictionary<string, bool>();
  30.        
  31.         // Performance / use information. Shown in the about box.
  32.         int numRedraws      = 0;
  33.        
  34.         private NotifyIcon notifyIcon;
  35.         public NotificationIcon()
  36.         {
  37.             // Initialize
  38.             notifyIcon = new NotifyIcon();
  39.             notifyIcon.ContextMenu = new ContextMenu();
  40.            
  41.             // Subscribe to events
  42.             notifyIcon.ContextMenu.Popup    += menuDrawMenu;    // DoubleClick, MouseDown
  43.            
  44.             // Resources
  45.             System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NotificationIcon));
  46.             notifyIcon.Icon = (Icon)resources.GetObject("$this.Icon");
  47.         }
  48.        
  49.         // The icon has been clicked, the menu is about to be drawn
  50.         private void menuDrawMenu(object sender, EventArgs e)
  51.         {
  52.             numRedraws++;
  53.             notifyIcon.ContextMenu.MenuItems.Clear();
  54.             notifyIcon.ContextMenu.MenuItems.AddRange(DynamicMenu());
  55.         }
  56.        
  57.         // Generate a context menu that displays titles of windows
  58.         private MenuItem[] DynamicMenu()
  59.         {
  60.             string[] titleArray = GetWindowTitles();
  61.            
  62.             List<MenuItem> menuList = new List<MenuItem>();
  63.             foreach(string title in titleArray)
  64.             {
  65.                 if(changeLog.ContainsKey(title))
  66.                 {
  67.                     if(changeLog[title])
  68.                     {
  69.                         menuList.Add(new MenuItem("* " + title, menuWinClick));
  70.                     }
  71.                     else
  72.                     {
  73.                         menuList.Add(new MenuItem(title, menuWinClick));
  74.                     }
  75.                 }
  76.                 else
  77.                 {
  78.                     menuList.Add(new MenuItem(title, menuWinClick));
  79.                 }
  80.             }
  81.             menuList.Add(new MenuItem("_____________"));
  82.             menuList.Add(new MenuItem("About", menuAboutClick));
  83.             menuList.Add(new MenuItem("Exit", menuExitClick));
  84.            
  85.             return menuList.ToArray();
  86.         }
  87.        
  88.        
  89.         private void menuWinClick(object sender, EventArgs e)
  90.         {
  91.             string title = sender.ToString();
  92.            
  93.             string[] winTitles = GetWindowTitles();
  94.             foreach(string win in winTitles)
  95.             {
  96.                 if(title.Contains(win))
  97.                 {
  98.                     title = win;
  99.                 }
  100.             }
  101.            
  102.             if(changeLog.ContainsKey(title))
  103.             {
  104.                 bool isTopmost = !changeLog[title];
  105.                 changeLog[title] = isTopmost;
  106.                 AssignTopmostWindow(title,isTopmost);
  107.             }
  108.             else
  109.             {
  110.                 changeLog.Add(title,true);
  111.                 AssignTopmostWindow(title,true);
  112.             }
  113.         }
  114.        
  115.         private void menuExitClick(object sender, EventArgs e)
  116.         {
  117.             // Roll-back changes by
  118.             //  unsetting every topmost window
  119.             foreach(KeyValuePair<string,bool> entry in changeLog)
  120.             {
  121.                 if(entry.Value) // If topmost
  122.                 {
  123.                     AssignTopmostWindow(entry.Key,false);
  124.                 }
  125.             }
  126.            
  127.             Application.Exit();
  128.         }
  129.        
  130.         private void menuAboutClick(object sender, EventArgs e)
  131.         {
  132.             MessageBox.Show(string.Join(Environment.NewLine,
  133.                                         "TopmostTray - Makes windows always on top",
  134.                                         "  by Adam Rakaska",
  135.                                         "    http://csharpcodewhisperer.blogspot.com",
  136.                                         "",
  137.                                         "Number of menu redraws: " + numRedraws.ToString()
  138.                                        ),
  139.                             "About"
  140.                            );
  141.         }
  142.        
  143.         string[] GetWindowTitles()
  144.         {
  145.             List<string> winList = new List<string>();
  146.            
  147.             Process[] procArray = Process.GetProcesses();
  148.             foreach(Process proc in procArray)
  149.             {
  150.                 if(!string.IsNullOrWhiteSpace(proc.MainWindowTitle))
  151.                 {
  152.                     winList.Add(proc.MainWindowTitle);
  153.                 }
  154.             }
  155.             return winList.ToArray();
  156.         }
  157.        
  158.         void AssignTopmostWindow(string windowTitle,bool makeTopmost)
  159.         {
  160.             IntPtr hWnd = FindWindow((string)null,windowTitle);
  161.            
  162.             RECT rect = new RECT();
  163.             GetWindowRect(new HandleRef(this,hWnd),out rect);
  164.            
  165.             SetWindowPos(hWnd,
  166.                          makeTopmost ? HWND_TOPMOST : HWND_NOTOPMOST,
  167.                          rect.X, rect.Y, rect.Width, rect.Height,
  168.                          SWP_SHOWWINDOW);
  169.         }
  170.        
  171.        
  172.        
  173.         #region Main
  174.        
  175.         [STAThread]
  176.         public static void Main(string[] args)
  177.         {
  178.             Application.EnableVisualStyles();
  179.             Application.SetCompatibleTextRenderingDefault(false);
  180.            
  181.             bool isFirstInstance;
  182.             // Please use a unique name for the mutex to prevent conflicts with other programs
  183.             using (Mutex mtx = new Mutex(true, "TopmostTray", out isFirstInstance))
  184.             {
  185.                 if (isFirstInstance) {
  186.                     NotificationIcon notificationIcon = new NotificationIcon();
  187.                     notificationIcon.notifyIcon.Visible = true;
  188.                     Application.Run();
  189.                     notificationIcon.notifyIcon.Dispose();
  190.                 } else {
  191.                     // The application is already running
  192.                     // TODO: Display message box or change focus to existing application instance
  193.                 }
  194.             } // releases the Mutex
  195.         }
  196.        
  197.         #endregion
  198.        
  199.        
  200.        
  201.         #region WIN32
  202.        
  203.         static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
  204.         static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
  205.         static readonly IntPtr HWND_TOP = new IntPtr(0);
  206.         static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
  207.         const UInt32 SWP_NOSIZE = 0x0001;
  208.         const UInt32 SWP_NOMOVE = 0x0002;
  209.         const UInt32 SWP_NOZORDER = 0x0004;
  210.         const UInt32 SWP_NOREDRAW = 0x0008;
  211.         const UInt32 SWP_NOACTIVATE = 0x0010;
  212.         const UInt32 SWP_FRAMECHANGED = 0x0020;
  213.         const UInt32 SWP_SHOWWINDOW = 0x0040;
  214.         const UInt32 SWP_HIDEWINDOW = 0x0080;
  215.         const UInt32 SWP_NOCOPYBITS = 0x0100;
  216.         const UInt32 SWP_NOOWNERZORDER = 0x0200;
  217.         const UInt32 SWP_NOSENDCHANGING = 0x0400;
  218.        
  219.         [StructLayout(LayoutKind.Sequential)]
  220.         public struct RECT
  221.         {
  222.             public int Left, Top, Right, Bottom;
  223.             public RECT(int left, int top, int right, int bottom) { Left = left; Top = top; Right = right; Bottom = bottom; }
  224.             public RECT(System.Drawing.Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
  225.             public int X { get { return Left; } set { Right -= (Left - value); Left = value; } }
  226.             public int Y { get { return Top; } set { Bottom -= (Top - value); Top = value; } }
  227.             public int Height { get { return Bottom - Top; } set { Bottom = value + Top; } }
  228.             public int Width { get { return Right - Left; } set { Right = value + Left; } }
  229.             public static implicit operator System.Drawing.Rectangle(RECT r) { return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height); }
  230.             public static implicit operator RECT(System.Drawing.Rectangle r) { return new RECT(r); }
  231.         }
  232.  
  233.         [DllImport("user32.dll", SetLastError = true)]
  234.         private static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
  235.        
  236.         [DllImport("user32.dll")]
  237.         [return: MarshalAs(UnmanagedType.Bool)]
  238.         public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);
  239.  
  240.         [DllImport("user32.dll")]
  241.         [return: MarshalAs(UnmanagedType.Bool)]
  242.         private static extern bool SetWindowPos( IntPtr hWnd, IntPtr hWndInsertAfter,
  243.                                                 int x, int y, int cx, int cy,
  244.                                                 uint uFlags
  245.                                                );
  246.        
  247.         #endregion
  248.        
  249.     }
  250. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement