Skip to content

Commit c4da744

Browse files
committed
v1.2.0 - 2020-01-07
1 parent 312b5bb commit c4da744

File tree

3 files changed

+117
-17
lines changed

3 files changed

+117
-17
lines changed

TopMostFriend/Program.cs

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.ComponentModel;
34
using System.Diagnostics;
45
using System.Drawing;
56
using System.IO;
7+
using System.Linq;
8+
using System.Security.Principal;
9+
using System.Text;
610
using System.Threading;
711
using System.Windows.Forms;
812

913
namespace TopMostFriend {
1014
public static class Program {
1115
private static NotifyIcon SysIcon;
1216
private static HotKeyWindow HotKeys;
13-
private static readonly Process OwnProcess = Process.GetCurrentProcess();
1417
private static int InitialItems = 0;
1518

1619
private const string GUID =
@@ -30,21 +33,38 @@ public static class Program {
3033
public const string SHOW_EXPLORER_SETTING = @"ShowExplorerMisc";
3134
public const string LIST_BACKGROUND_PATH_SETTING = @"ListBackgroundPath";
3235
public const string LIST_BACKGROUND_LAYOUT_SETTING = @"ListBackgroundLayout";
36+
public const string ALWAYS_ADMIN_SETTING = @"RunAsAdministrator";
3337

3438
[STAThread]
35-
public static void Main() {
39+
public static void Main(string[] args) {
3640
if (Environment.OSVersion.Version.Major >= 6)
3741
Win32.SetProcessDPIAware();
3842

3943
Application.EnableVisualStyles();
4044
Application.SetCompatibleTextRenderingDefault(false);
4145

46+
if (args.Contains(@"--reset-admin"))
47+
Settings.Remove(ALWAYS_ADMIN_SETTING);
48+
49+
string cliToggle = args.FirstOrDefault(x => x.StartsWith(@"--hwnd="));
50+
if (!string.IsNullOrEmpty(cliToggle) && int.TryParse(cliToggle.Substring(7), out int cliToggleHWnd))
51+
ToggleWindow(new IntPtr(cliToggleHWnd));
52+
53+
if (args.Contains(@"--stop"))
54+
return;
55+
4256
if (!GlobalMutex.WaitOne(0, true)) {
4357
MessageBox.Show(@"An instance of Top Most Friend is already running.", @"Top Most Friend");
4458
return;
4559
}
4660

47-
Settings.SetDefault(FOREGROUND_HOTKEY_SETTING, ((int)Keys.F << 16) | (int)(Win32ModKeys.MOD_CONTROL | Win32ModKeys.MOD_ALT));
61+
Settings.SetDefault(FOREGROUND_HOTKEY_SETTING, 0);
62+
Settings.SetDefault(ALWAYS_ADMIN_SETTING, false);
63+
64+
if (Settings.Get<bool>(ALWAYS_ADMIN_SETTING) && !IsElevated()) {
65+
Elevate();
66+
return;
67+
}
4868

4969
string backgroundPath = Settings.Get(LIST_BACKGROUND_PATH_SETTING, string.Empty);
5070
Image backgroundImage = null;
@@ -76,26 +96,67 @@ public static void Main() {
7696
InitialItems = SysIcon.ContextMenuStrip.Items.Count;
7797

7898
HotKeys = new HotKeyWindow();
79-
SetForegroundHotKey(Settings.Get<int>(FOREGROUND_HOTKEY_SETTING));
99+
100+
try {
101+
SetForegroundHotKey(Settings.Get<int>(FOREGROUND_HOTKEY_SETTING));
102+
} catch(Win32Exception ex) {
103+
Console.WriteLine(@"Hotkey registration failed:");
104+
Console.WriteLine(ex);
105+
}
80106

81107
Application.Run();
82108

83-
HotKeys.Dispose();
84-
SysIcon.Dispose();
109+
Shutdown();
110+
}
85111

112+
public static void Shutdown() {
113+
HotKeys?.Dispose();
114+
SysIcon?.Dispose();
86115
GlobalMutex.ReleaseMutex();
87116
}
88117

118+
private static bool? IsElevatedValue;
119+
120+
public static bool IsElevated() {
121+
if (!IsElevatedValue.HasValue) {
122+
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
123+
IsElevatedValue = identity != null && new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator);
124+
}
125+
126+
return IsElevatedValue.Value;
127+
}
128+
129+
public static void Elevate(string args = null) {
130+
if (IsElevated())
131+
return;
132+
133+
Shutdown();
134+
135+
Process.Start(new ProcessStartInfo {
136+
UseShellExecute = true,
137+
FileName = Application.ExecutablePath,
138+
WorkingDirectory = Environment.CurrentDirectory,
139+
Arguments = args ?? string.Empty,
140+
Verb = @"runas",
141+
});
142+
Application.Exit();
143+
}
144+
89145
public static void SetForegroundHotKey(int keyCode) {
90146
SetForegroundHotKey((Win32ModKeys)(keyCode & 0xFFFF), (Keys)((keyCode & 0xFFFF0000) >> 16));
91147
}
92148

93149
public static void SetForegroundHotKey(Win32ModKeys mods, Keys key) {
94-
Settings.Set(FOREGROUND_HOTKEY_SETTING, ((int)key << 16) | (int)mods);
95-
HotKeys.Unregister(FOREGROUND_HOTKEY_ATOM);
96-
97-
if(mods != 0 && key != 0)
98-
HotKeys.Register(FOREGROUND_HOTKEY_ATOM, mods, key, ToggleForegroundWindow);
150+
try {
151+
Settings.Set(FOREGROUND_HOTKEY_SETTING, ((int)key << 16) | (int)mods);
152+
HotKeys.Unregister(FOREGROUND_HOTKEY_ATOM);
153+
154+
if (mods != 0 && key != 0)
155+
HotKeys.Register(FOREGROUND_HOTKEY_ATOM, mods, key, ToggleForegroundWindow);
156+
} catch (Win32Exception ex) {
157+
Debug.WriteLine(@"Hotkey registration failed:");
158+
Debug.WriteLine(ex);
159+
}
99160
}
100161

101162
private static void RefreshWindowList() {
@@ -150,12 +211,32 @@ public static void SetTopMost(IntPtr hWnd, bool state) {
150211
0, 0, 0, 0, Win32.SWP_NOMOVE | Win32.SWP_NOSIZE | Win32.SWP_SHOWWINDOW
151212
);
152213

214+
if(IsTopMost(hWnd) != state) {
215+
MessageBoxButtons buttons = MessageBoxButtons.OK;
216+
StringBuilder sb = new StringBuilder();
217+
sb.AppendLine(@"Wasn't able to change topmost status on this window.");
218+
219+
if (!IsElevated()) {
220+
sb.AppendLine(@"Do you want to restart Top Most Friend as administrator and try again?");
221+
buttons = MessageBoxButtons.YesNo;
222+
}
223+
224+
DialogResult result = MessageBox.Show(sb.ToString(), @"Top Most Friend", buttons, MessageBoxIcon.Error);
225+
226+
if (result == DialogResult.Yes)
227+
Elevate($@"--hwnd={hWnd}");
228+
return;
229+
}
230+
153231
if (state)
154232
Win32.SwitchToThisWindow(hWnd, false);
155233
}
156234

157235
public static void ToggleForegroundWindow() {
158-
IntPtr hWnd = Win32.GetForegroundWindow();
236+
ToggleWindow(Win32.GetForegroundWindow());
237+
}
238+
239+
public static void ToggleWindow(IntPtr hWnd) {
159240
SetTopMost(hWnd, !IsTopMost(hWnd));
160241
}
161242

@@ -182,9 +263,10 @@ private static Icon GetWindowIcon(IntPtr hWnd) {
182263

183264
private static IEnumerable<WindowEntry> GetWindowList() {
184265
Process[] procs = Process.GetProcesses();
266+
Process self = Process.GetCurrentProcess();
185267

186268
foreach (Process proc in procs) {
187-
if (!Settings.Get(LIST_SELF_SETTING, Debugger.IsAttached) && proc.Id == OwnProcess.Id)
269+
if (!Settings.Get(LIST_SELF_SETTING, Debugger.IsAttached) && proc == self)
188270
continue;
189271

190272
IEnumerable<IntPtr> hwnds = proc.GetWindowHandles();

TopMostFriend/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@
2929
// Build Number
3030
// Revision
3131
//
32-
[assembly: AssemblyVersion("1.1.0.0")]
33-
[assembly: AssemblyFileVersion("1.1.0.0")]
32+
[assembly: AssemblyVersion("1.2.0.0")]
33+
[assembly: AssemblyFileVersion("1.2.0.0")]

TopMostFriend/SettingsWindow.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ public static void Display() {
2727
public readonly CheckBox FgModAlt;
2828
public readonly CheckBox FgModShift;
2929

30+
public readonly CheckBox FlAlwaysAdmin;
31+
3032
public SettingsWindow() {
3133
Text = @"Top Most Friend Settings";
3234
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
3335
StartPosition = FormStartPosition.CenterScreen;
3436
FormBorderStyle = FormBorderStyle.FixedSingle;
3537
AutoScaleMode = AutoScaleMode.Dpi;
36-
ClientSize = new Size(410, 113);
38+
ClientSize = new Size(410, 163);
3739
MinimizeBox = MaximizeBox = false;
3840
MinimumSize = MaximumSize = Size;
3941

@@ -67,8 +69,14 @@ public SettingsWindow() {
6769
Size = new Size(Width - 18, 70),
6870
};
6971

72+
GroupBox flagsGroup = new GroupBox {
73+
Text = @"Flags",
74+
Location = new Point(6, 76),
75+
Size = new Size(Width - 18, 50),
76+
};
77+
7078
Controls.AddRange(new Control[] {
71-
applyButton, cancelButton, okButton, hotKeyGroup,
79+
applyButton, cancelButton, okButton, hotKeyGroup, flagsGroup,
7280
});
7381

7482
Label toggleForegroundLabel = new Label {
@@ -125,6 +133,15 @@ public SettingsWindow() {
125133
hotKeyGroup.Controls.AddRange(new Control[] {
126134
toggleForegroundLabel, FgModCtrl, FgModAlt, FgModShift, fgReset, FgKey,
127135
});
136+
137+
FlAlwaysAdmin = new CheckBox {
138+
Text = @"Always run as administrator",
139+
Location = new Point(10, 20),
140+
Checked = Settings.Get(Program.ALWAYS_ADMIN_SETTING, false),
141+
AutoSize = true,
142+
};
143+
144+
flagsGroup.Controls.Add(FlAlwaysAdmin);
128145
}
129146

130147
private void FgReset_Click(object sender, EventArgs e) {
@@ -135,6 +152,7 @@ private void FgReset_Click(object sender, EventArgs e) {
135152

136153
public void Apply() {
137154
Settings.Set(Program.FOREGROUND_HOTKEY_SETTING, KeyCode);
155+
Settings.Set(Program.ALWAYS_ADMIN_SETTING, FlAlwaysAdmin.Checked);
138156
Program.SetForegroundHotKey(KeyCode);
139157
}
140158

0 commit comments

Comments
 (0)