mirror of
https://github.com/flashwave/topmostfriend.git
synced 2024-11-22 09:48:44 +00:00
v1.1.0 - 2020-01-06
This commit is contained in:
parent
e28311ceb8
commit
312b5bbec8
11 changed files with 626 additions and 118 deletions
|
@ -9,16 +9,13 @@ namespace TopMostFriend {
|
||||||
private const int BUTTON_HEIGHT = 23;
|
private const int BUTTON_HEIGHT = 23;
|
||||||
private const int BUTTON_WIDTH = 70;
|
private const int BUTTON_WIDTH = 70;
|
||||||
|
|
||||||
public const int WM_NCLBUTTONDOWN = 0xA1;
|
|
||||||
public const int HT_CAPTION = 0x02;
|
|
||||||
|
|
||||||
public static void Display() {
|
public static void Display() {
|
||||||
using (AboutWindow about = new AboutWindow())
|
using (AboutWindow about = new AboutWindow())
|
||||||
about.ShowDialog();
|
about.ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AboutWindow() {
|
public AboutWindow() {
|
||||||
Text = $@"About Top Most Friend";
|
Text = @"About Top Most Friend";
|
||||||
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
|
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
|
||||||
BackgroundImage = Properties.Resources.about;
|
BackgroundImage = Properties.Resources.about;
|
||||||
StartPosition = FormStartPosition.CenterScreen;
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
|
@ -81,7 +78,7 @@ namespace TopMostFriend {
|
||||||
Controls.Add(creditButtonfff);
|
Controls.Add(creditButtonfff);
|
||||||
|
|
||||||
Controls.Add(new Label {
|
Controls.Add(new Label {
|
||||||
Text = Application.ProductVersion,
|
Text = @"v" + Application.ProductVersion.Substring(0, Application.ProductVersion.Length - 2), // cut off the last dingus
|
||||||
TextAlign = ContentAlignment.MiddleLeft,
|
TextAlign = ContentAlignment.MiddleLeft,
|
||||||
AutoSize = true,
|
AutoSize = true,
|
||||||
Location = new Point(127, 97),
|
Location = new Point(127, 97),
|
||||||
|
@ -93,8 +90,8 @@ namespace TopMostFriend {
|
||||||
protected override void OnMouseDown(MouseEventArgs e) {
|
protected override void OnMouseDown(MouseEventArgs e) {
|
||||||
base.OnMouseDown(e);
|
base.OnMouseDown(e);
|
||||||
|
|
||||||
Program.ReleaseCapture();
|
Win32.ReleaseCapture();
|
||||||
Program.SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
|
Win32.SendMessage(Handle, Win32.WM_NCLBUTTONDOWN, Win32.HT_CAPTION, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
110
TopMostFriend/HotKeyWindow.cs
Normal file
110
TopMostFriend/HotKeyWindow.cs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TopMostFriend {
|
||||||
|
public sealed class HotKeyWindow : Form {
|
||||||
|
public class HotKeyInfo {
|
||||||
|
public string Name { get; }
|
||||||
|
public int Atom { get; }
|
||||||
|
public int Key { get; }
|
||||||
|
public Action Action { get; }
|
||||||
|
|
||||||
|
public HotKeyInfo(string name, int atom, int key, Action action) {
|
||||||
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
|
Atom = atom;
|
||||||
|
Key = key;
|
||||||
|
Action = action ?? throw new ArgumentNullException(nameof(action));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<HotKeyInfo> RegisteredHotKeys = new List<HotKeyInfo>();
|
||||||
|
|
||||||
|
public HotKeyWindow() {
|
||||||
|
ShowInTaskbar = false;
|
||||||
|
Text = string.Empty;
|
||||||
|
FormBorderStyle = FormBorderStyle.None;
|
||||||
|
StartPosition = FormStartPosition.Manual;
|
||||||
|
Size = new Size(1, 1);
|
||||||
|
Location = new Point(-9999, -9999);
|
||||||
|
CreateHandle();
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnFormClosing(FormClosingEventArgs e) {
|
||||||
|
e.Cancel = e.CloseReason == CloseReason.UserClosing;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void WndProc(ref Message m) {
|
||||||
|
base.WndProc(ref m);
|
||||||
|
|
||||||
|
if(m.Msg == Win32.WM_HOTKEY) {
|
||||||
|
int keyCode = m.LParam.ToInt32();
|
||||||
|
|
||||||
|
lock (RegisteredHotKeys)
|
||||||
|
RegisteredHotKeys.FirstOrDefault(x => x.Key == keyCode)?.Action.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
lock (RegisteredHotKeys) {
|
||||||
|
HotKeyInfo[] hotKeys = RegisteredHotKeys.ToArray();
|
||||||
|
|
||||||
|
foreach(HotKeyInfo hotKey in hotKeys)
|
||||||
|
Unregister(hotKey.Atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Register(string name, Win32ModKeys modifiers, Keys key, Action action) {
|
||||||
|
if (action == null)
|
||||||
|
throw new ArgumentNullException(nameof(action));
|
||||||
|
if(string.IsNullOrEmpty(name))
|
||||||
|
name = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
int atom = Win32.GlobalAddAtom(name);
|
||||||
|
int keyCode = ((ushort)key << 16) | (ushort)modifiers;
|
||||||
|
|
||||||
|
if (atom == 0)
|
||||||
|
throw new Win32Exception(Marshal.GetLastWin32Error(), @"Atom creation failed.");
|
||||||
|
|
||||||
|
if (!Win32.RegisterHotKey(Handle, atom, modifiers, key)) {
|
||||||
|
Win32.GlobalDeleteAtom((ushort)atom);
|
||||||
|
throw new Win32Exception(Marshal.GetLastWin32Error(), @"Hotkey registration failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
lock(RegisteredHotKeys)
|
||||||
|
RegisteredHotKeys.Add(new HotKeyInfo(name, atom, keyCode, action));
|
||||||
|
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unregister(int id) {
|
||||||
|
if (id < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (RegisteredHotKeys) {
|
||||||
|
if (!RegisteredHotKeys.Any(x => x.Atom == id))
|
||||||
|
return;
|
||||||
|
RegisteredHotKeys.RemoveAll(x => x.Atom == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Win32.UnregisterHotKey(Handle, id);
|
||||||
|
Win32.GlobalDeleteAtom((ushort)id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unregister(string name) {
|
||||||
|
int atom = 0;
|
||||||
|
|
||||||
|
lock (RegisteredHotKeys)
|
||||||
|
atom = RegisteredHotKeys.FirstOrDefault(x => x.Name == name)?.Atom ?? 0;
|
||||||
|
|
||||||
|
Unregister(atom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,41 +2,100 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Runtime.InteropServices;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TopMostFriend {
|
namespace TopMostFriend {
|
||||||
public static class Program {
|
public static class Program {
|
||||||
private static NotifyIcon SysIcon;
|
private static NotifyIcon SysIcon;
|
||||||
|
private static HotKeyWindow HotKeys;
|
||||||
private static readonly Process OwnProcess = Process.GetCurrentProcess();
|
private static readonly Process OwnProcess = Process.GetCurrentProcess();
|
||||||
private static int InitialItems = 0;
|
private static int InitialItems = 0;
|
||||||
|
|
||||||
|
private const string GUID =
|
||||||
|
#if DEBUG
|
||||||
|
@"{1A22D9CA-2AA9-48F2-B007-3A48CF205CDD}";
|
||||||
|
#else
|
||||||
|
@"{5BE25191-E1E2-48A7-B038-E986CD989E91}";
|
||||||
|
#endif
|
||||||
|
private static readonly Mutex GlobalMutex = new Mutex(true, GUID);
|
||||||
|
|
||||||
|
public const string FOREGROUND_HOTKEY_ATOM = @"{86795D64-770D-4BD6-AA26-FA638FBAABCF}";
|
||||||
|
public const string FOREGROUND_HOTKEY_SETTING = @"ForegroundHotKey";
|
||||||
|
|
||||||
|
public const string PROCESS_SEPARATOR_SETTING = @"InsertProcessSeparator";
|
||||||
|
public const string LIST_SELF_SETTING = @"ListSelf";
|
||||||
|
public const string SHOW_EMPTY_WINDOW_SETTING = @"ShowEmptyWindowTitles";
|
||||||
|
public const string SHOW_EXPLORER_SETTING = @"ShowExplorerMisc";
|
||||||
|
public const string LIST_BACKGROUND_PATH_SETTING = @"ListBackgroundPath";
|
||||||
|
public const string LIST_BACKGROUND_LAYOUT_SETTING = @"ListBackgroundLayout";
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main() {
|
public static void Main() {
|
||||||
if (Environment.OSVersion.Version.Major >= 6)
|
if (Environment.OSVersion.Version.Major >= 6)
|
||||||
SetProcessDPIAware();
|
Win32.SetProcessDPIAware();
|
||||||
|
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
|
if (!GlobalMutex.WaitOne(0, true)) {
|
||||||
|
MessageBox.Show(@"An instance of Top Most Friend is already running.", @"Top Most Friend");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings.SetDefault(FOREGROUND_HOTKEY_SETTING, ((int)Keys.F << 16) | (int)(Win32ModKeys.MOD_CONTROL | Win32ModKeys.MOD_ALT));
|
||||||
|
|
||||||
|
string backgroundPath = Settings.Get(LIST_BACKGROUND_PATH_SETTING, string.Empty);
|
||||||
|
Image backgroundImage = null;
|
||||||
|
ImageLayout backgroundLayout = 0;
|
||||||
|
|
||||||
|
if(File.Exists(backgroundPath)) {
|
||||||
|
try {
|
||||||
|
backgroundImage = Image.FromFile(backgroundPath);
|
||||||
|
backgroundLayout = (ImageLayout)Settings.Get(LIST_BACKGROUND_LAYOUT_SETTING, 0);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
SysIcon = new NotifyIcon {
|
SysIcon = new NotifyIcon {
|
||||||
Visible = true,
|
Visible = true,
|
||||||
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath),
|
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath),
|
||||||
Text = @"Top Most Application Manager",
|
Text = @"Top Most Application Manager",
|
||||||
};
|
};
|
||||||
SysIcon.MouseDown += SysIcon_MouseDown;
|
SysIcon.MouseDown += SysIcon_MouseDown;
|
||||||
SysIcon.ContextMenuStrip = new ContextMenuStrip();
|
SysIcon.ContextMenuStrip = new ContextMenuStrip {
|
||||||
|
BackgroundImage = backgroundImage,
|
||||||
|
BackgroundImageLayout = backgroundLayout,
|
||||||
|
};
|
||||||
SysIcon.ContextMenuStrip.Items.AddRange(new ToolStripItem[] {
|
SysIcon.ContextMenuStrip.Items.AddRange(new ToolStripItem[] {
|
||||||
new ToolStripSeparator(),
|
new ToolStripSeparator(),
|
||||||
|
new ToolStripMenuItem(@"&Settings", Properties.Resources.cog, new EventHandler((s, e) => SettingsWindow.Display())),
|
||||||
new ToolStripMenuItem(@"&About", Properties.Resources.help, new EventHandler((s, e) => AboutWindow.Display())),
|
new ToolStripMenuItem(@"&About", Properties.Resources.help, new EventHandler((s, e) => AboutWindow.Display())),
|
||||||
new ToolStripMenuItem(@"&Quit", Properties.Resources.door_in, new EventHandler((s, e) => Application.Exit())),
|
new ToolStripMenuItem(@"&Quit", Properties.Resources.door_in, new EventHandler((s, e) => Application.Exit())),
|
||||||
});
|
});
|
||||||
InitialItems = SysIcon.ContextMenuStrip.Items.Count;
|
InitialItems = SysIcon.ContextMenuStrip.Items.Count;
|
||||||
|
|
||||||
|
HotKeys = new HotKeyWindow();
|
||||||
|
SetForegroundHotKey(Settings.Get<int>(FOREGROUND_HOTKEY_SETTING));
|
||||||
|
|
||||||
Application.Run();
|
Application.Run();
|
||||||
|
|
||||||
|
HotKeys.Dispose();
|
||||||
SysIcon.Dispose();
|
SysIcon.Dispose();
|
||||||
|
|
||||||
|
GlobalMutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetForegroundHotKey(int keyCode) {
|
||||||
|
SetForegroundHotKey((Win32ModKeys)(keyCode & 0xFFFF), (Keys)((keyCode & 0xFFFF0000) >> 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetForegroundHotKey(Win32ModKeys mods, Keys key) {
|
||||||
|
Settings.Set(FOREGROUND_HOTKEY_SETTING, ((int)key << 16) | (int)mods);
|
||||||
|
HotKeys.Unregister(FOREGROUND_HOTKEY_ATOM);
|
||||||
|
|
||||||
|
if(mods != 0 && key != 0)
|
||||||
|
HotKeys.Register(FOREGROUND_HOTKEY_ATOM, mods, key, ToggleForegroundWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RefreshWindowList() {
|
private static void RefreshWindowList() {
|
||||||
|
@ -44,54 +103,76 @@ namespace TopMostFriend {
|
||||||
SysIcon.ContextMenuStrip.Items.RemoveAt(0);
|
SysIcon.ContextMenuStrip.Items.RemoveAt(0);
|
||||||
|
|
||||||
IEnumerable<WindowEntry> windows = GetWindowList();
|
IEnumerable<WindowEntry> windows = GetWindowList();
|
||||||
|
Process lastProc = null;
|
||||||
|
bool procSeparator = Settings.Get(PROCESS_SEPARATOR_SETTING, false);
|
||||||
|
bool showEmptyTitles = Settings.Get(SHOW_EMPTY_WINDOW_SETTING, Debugger.IsAttached);
|
||||||
|
bool showExplorerMisc = Settings.Get(SHOW_EXPLORER_SETTING, Debugger.IsAttached);
|
||||||
|
|
||||||
foreach(WindowEntry window in windows) {
|
foreach(WindowEntry window in windows) {
|
||||||
string title = GetWindowTextLazy(window.Window);
|
if(procSeparator && lastProc != window.Process) {
|
||||||
|
if (lastProc != null)
|
||||||
|
SysIcon.ContextMenuStrip.Items.Insert(0, new ToolStripSeparator());
|
||||||
|
lastProc = window.Process;
|
||||||
|
}
|
||||||
|
|
||||||
|
string title = Win32.GetWindowTextString(window.Window);
|
||||||
|
|
||||||
// i think it's a fair assumption that any visible window worth a damn has a window title
|
// i think it's a fair assumption that any visible window worth a damn has a window title
|
||||||
if (string.IsNullOrEmpty(title))
|
if (!showEmptyTitles && string.IsNullOrEmpty(title))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// skip explorer things with specific titles, there's probably a much better way of doing this check
|
// skip explorer things with specific titles, there's probably a much better way of doing this check
|
||||||
// and this will also probably only work properly on english windows but Fuck It what do you want from me
|
// and this will also probably only work properly on english windows but Fuck It what do you want from me
|
||||||
if (window.Process.ProcessName == @"explorer" && (title == @"Program Manager" || title == @"Start"))
|
if (!showExplorerMisc && window.Process.ProcessName == @"explorer" && (title == @"Program Manager" || title == @"Start"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
IntPtr flags = GetWindowLongPtr(window.Window, GWL_EXSTYLE);
|
Image icon = GetWindowIcon(window.Window)?.ToBitmap() ?? null;
|
||||||
bool isTopMost = (flags.ToInt32() & WS_EX_TOPMOST) > 0;
|
bool isTopMost = IsTopMost(window.Window);
|
||||||
|
|
||||||
Image icon = GetWindowIcon(window.Window).ToBitmap();
|
|
||||||
|
|
||||||
SysIcon.ContextMenuStrip.Items.Insert(0, new ToolStripMenuItem(
|
SysIcon.ContextMenuStrip.Items.Insert(0, new ToolStripMenuItem(
|
||||||
title, icon, new EventHandler((s, e) => {
|
title, icon,
|
||||||
SetWindowPos(
|
new EventHandler((s, e) => SetTopMost(window.Window, !isTopMost))
|
||||||
window.Window, new IntPtr(isTopMost ? HWND_NOTOPMOST : HWND_TOPMOST),
|
) {
|
||||||
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isTopMost)
|
|
||||||
SwitchToThisWindow(window.Window, false);
|
|
||||||
})) {
|
|
||||||
CheckOnClick = true,
|
CheckOnClick = true,
|
||||||
Checked = isTopMost,
|
Checked = isTopMost,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsTopMost(IntPtr hWnd) {
|
||||||
|
IntPtr flags = Win32.GetWindowLongPtr(hWnd, Win32.GWL_EXSTYLE);
|
||||||
|
return (flags.ToInt32() & Win32.WS_EX_TOPMOST) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetTopMost(IntPtr hWnd, bool state) {
|
||||||
|
Win32.SetWindowPos(
|
||||||
|
hWnd, new IntPtr(state ? Win32.HWND_TOPMOST : Win32.HWND_NOTOPMOST),
|
||||||
|
0, 0, 0, 0, Win32.SWP_NOMOVE | Win32.SWP_NOSIZE | Win32.SWP_SHOWWINDOW
|
||||||
|
);
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
Win32.SwitchToThisWindow(hWnd, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ToggleForegroundWindow() {
|
||||||
|
IntPtr hWnd = Win32.GetForegroundWindow();
|
||||||
|
SetTopMost(hWnd, !IsTopMost(hWnd));
|
||||||
|
}
|
||||||
|
|
||||||
private static Icon GetWindowIcon(IntPtr hWnd) {
|
private static Icon GetWindowIcon(IntPtr hWnd) {
|
||||||
IntPtr hIcon = SendMessage(hWnd, WM_GETICON, ICON_SMALL2, 0);
|
IntPtr hIcon = Win32.SendMessage(hWnd, Win32.WM_GETICON, Win32.ICON_SMALL2, 0);
|
||||||
|
|
||||||
if(hIcon == IntPtr.Zero) {
|
if(hIcon == IntPtr.Zero) {
|
||||||
hIcon = SendMessage(hWnd, WM_GETICON, ICON_SMALL, 0);
|
hIcon = Win32.SendMessage(hWnd, Win32.WM_GETICON, Win32.ICON_SMALL, 0);
|
||||||
|
|
||||||
if(hIcon == IntPtr.Zero) {
|
if(hIcon == IntPtr.Zero) {
|
||||||
hIcon = SendMessage(hWnd, WM_GETICON, ICON_BIG, 0);
|
hIcon = Win32.SendMessage(hWnd, Win32.WM_GETICON, Win32.ICON_BIG, 0);
|
||||||
|
|
||||||
if(hIcon == IntPtr.Zero) {
|
if(hIcon == IntPtr.Zero) {
|
||||||
hIcon = GetClassLongPtr(hWnd, GCL_HICON);
|
hIcon = Win32.GetClassLongPtr(hWnd, Win32.GCL_HICON);
|
||||||
|
|
||||||
if (hIcon == IntPtr.Zero)
|
if (hIcon == IntPtr.Zero)
|
||||||
hIcon = GetClassLongPtr(hWnd, GCL_HICONSM);
|
hIcon = Win32.GetClassLongPtr(hWnd, Win32.GCL_HICONSM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,13 +184,13 @@ namespace TopMostFriend {
|
||||||
Process[] procs = Process.GetProcesses();
|
Process[] procs = Process.GetProcesses();
|
||||||
|
|
||||||
foreach (Process proc in procs) {
|
foreach (Process proc in procs) {
|
||||||
if (proc.Id == OwnProcess.Id)
|
if (!Settings.Get(LIST_SELF_SETTING, Debugger.IsAttached) && proc.Id == OwnProcess.Id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
IEnumerable<IntPtr> hwnds = proc.GetWindowHandles();
|
IEnumerable<IntPtr> hwnds = proc.GetWindowHandles();
|
||||||
|
|
||||||
foreach (IntPtr ptr in hwnds) {
|
foreach (IntPtr ptr in hwnds) {
|
||||||
if (!IsWindowVisible(ptr))
|
if (!Win32.IsWindowVisible(ptr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
yield return new WindowEntry(proc, ptr);
|
yield return new WindowEntry(proc, ptr);
|
||||||
|
@ -128,9 +209,10 @@ namespace TopMostFriend {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SysIcon_MouseDown(object sender, MouseEventArgs e) {
|
private static void SysIcon_MouseDown(object sender, MouseEventArgs e) {
|
||||||
if (e.Button != MouseButtons.Right)
|
if (e.Button.HasFlag(MouseButtons.Left))
|
||||||
return;
|
ToggleForegroundWindow();
|
||||||
|
|
||||||
|
if (e.Button.HasFlag(MouseButtons.Right))
|
||||||
RefreshWindowList();
|
RefreshWindowList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,88 +220,12 @@ namespace TopMostFriend {
|
||||||
IntPtr hwndCurr = IntPtr.Zero;
|
IntPtr hwndCurr = IntPtr.Zero;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
hwndCurr = FindWindowEx(IntPtr.Zero, hwndCurr, null, null);
|
hwndCurr = Win32.FindWindowEx(IntPtr.Zero, hwndCurr, null, null);
|
||||||
GetWindowThreadProcessId(hwndCurr, out uint procId);
|
Win32.GetWindowThreadProcessId(hwndCurr, out uint procId);
|
||||||
|
|
||||||
if(proc.Id == procId)
|
if(proc.Id == procId)
|
||||||
yield return hwndCurr;
|
yield return hwndCurr;
|
||||||
} while (hwndCurr != IntPtr.Zero);
|
} while (hwndCurr != IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int HWND_TOPMOST = -1;
|
|
||||||
private const int HWND_NOTOPMOST = -2;
|
|
||||||
private const int SWP_NOSIZE = 0x0001;
|
|
||||||
private const int SWP_NOMOVE = 0x0002;
|
|
||||||
private const int SWP_SHOWWINDOW = 0x0040;
|
|
||||||
private const int GWL_EXSTYLE = -20;
|
|
||||||
private const int GCL_HICON = -14;
|
|
||||||
private const int GCL_HICONSM = -34;
|
|
||||||
private const int WS_EX_TOPMOST = 0x08;
|
|
||||||
private const int WM_GETICON = 0x7F;
|
|
||||||
private const int ICON_SMALL = 0;
|
|
||||||
private const int ICON_BIG = 1;
|
|
||||||
private const int ICON_SMALL2 = 2;
|
|
||||||
|
|
||||||
[DllImport(@"user32")]
|
|
||||||
private static extern bool SetProcessDPIAware();
|
|
||||||
|
|
||||||
[DllImport(@"user32", SetLastError = true)]
|
|
||||||
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
|
|
||||||
|
|
||||||
[DllImport(@"user32", SetLastError = true)]
|
|
||||||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
||||||
|
|
||||||
private static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex) {
|
|
||||||
if (IntPtr.Size == 8)
|
|
||||||
return GetWindowLongPtr64(hWnd, nIndex);
|
|
||||||
return new IntPtr(GetWindowLong32(hWnd, nIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport(@"user32", EntryPoint = "GetWindowLong")]
|
|
||||||
private static extern int GetWindowLong32(IntPtr hWnd, int nIndex);
|
|
||||||
|
|
||||||
[DllImport(@"user32", EntryPoint = "GetWindowLongPtr")]
|
|
||||||
private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
|
|
||||||
|
|
||||||
[DllImport(@"user32")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
private static extern bool IsWindowVisible(IntPtr hWnd);
|
|
||||||
|
|
||||||
[DllImport(@"user32", CharSet = CharSet.Auto, SetLastError = true)]
|
|
||||||
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
|
||||||
|
|
||||||
[DllImport(@"user32", SetLastError = true, CharSet = CharSet.Auto)]
|
|
||||||
private static extern int GetWindowTextLength(IntPtr hWnd);
|
|
||||||
|
|
||||||
private static string GetWindowTextLazy(IntPtr hwnd) {
|
|
||||||
int length = GetWindowTextLength(hwnd) + 1;
|
|
||||||
StringBuilder sb = new StringBuilder(length);
|
|
||||||
GetWindowText(hwnd, sb, length);
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex) {
|
|
||||||
if (IntPtr.Size > 4)
|
|
||||||
return GetClassLongPtr64(hWnd, nIndex);
|
|
||||||
return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport(@"user32", EntryPoint = "GetClassLong")]
|
|
||||||
private static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
|
|
||||||
|
|
||||||
[DllImport(@"user32", EntryPoint = "GetClassLongPtr")]
|
|
||||||
private static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
|
|
||||||
|
|
||||||
[DllImport(@"user32", SetLastError = true)]
|
|
||||||
private static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
|
|
||||||
|
|
||||||
[DllImport(@"user32", SetLastError = true)]
|
|
||||||
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int uFlags);
|
|
||||||
|
|
||||||
[DllImport(@"user32", CharSet = CharSet.Auto, SetLastError = false)]
|
|
||||||
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
|
|
||||||
|
|
||||||
[DllImport(@"user32")]
|
|
||||||
public static extern bool ReleaseCapture();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.1.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.1.0.0")]
|
||||||
|
|
10
TopMostFriend/Properties/Resources.Designer.cs
generated
10
TopMostFriend/Properties/Resources.Designer.cs
generated
|
@ -70,6 +70,16 @@ namespace TopMostFriend.Properties {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Bitmap cog {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("cog", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -121,6 +121,9 @@
|
||||||
<data name="about" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="about" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\about.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\about.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="cog" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\cog.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
<data name="door_in" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="door_in" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\door_in.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\door_in.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
BIN
TopMostFriend/Resources/cog.png
Normal file
BIN
TopMostFriend/Resources/cog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 512 B |
58
TopMostFriend/Settings.cs
Normal file
58
TopMostFriend/Settings.cs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TopMostFriend {
|
||||||
|
public static class Settings {
|
||||||
|
private const string ROOT = @"Software\flash.moe\TopMostFriend";
|
||||||
|
|
||||||
|
private static RegistryKey GetRoot() {
|
||||||
|
RegistryKey root = Registry.CurrentUser.OpenSubKey(ROOT, true);
|
||||||
|
|
||||||
|
if (root == null)
|
||||||
|
root = Registry.CurrentUser.CreateSubKey(ROOT);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Get<T>(string name, T fallback = default) {
|
||||||
|
try {
|
||||||
|
return (T)Convert.ChangeType(GetRoot().GetValue(name, fallback), typeof(T));
|
||||||
|
} catch {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Has(string name) {
|
||||||
|
try {
|
||||||
|
GetRoot().GetValueKind(name);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Set(string name, object value) {
|
||||||
|
if(value == null) {
|
||||||
|
Remove(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(value) {
|
||||||
|
case bool b:
|
||||||
|
value = b ? 1 : 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetRoot().SetValue(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetDefault(string name, object value) {
|
||||||
|
if (!Has(name))
|
||||||
|
Set(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Remove(string name) {
|
||||||
|
GetRoot().DeleteValue(name, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
192
TopMostFriend/SettingsWindow.cs
Normal file
192
TopMostFriend/SettingsWindow.cs
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TopMostFriend {
|
||||||
|
public class SettingsWindow : Form {
|
||||||
|
public static SettingsWindow Instance;
|
||||||
|
|
||||||
|
public static void Display() {
|
||||||
|
if(Instance != null) {
|
||||||
|
Instance.Show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = new SettingsWindow();
|
||||||
|
Instance.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int KeyCode { get; set; }
|
||||||
|
|
||||||
|
public readonly TextBox FgKey;
|
||||||
|
public readonly CheckBox FgModCtrl;
|
||||||
|
public readonly CheckBox FgModAlt;
|
||||||
|
public readonly CheckBox FgModShift;
|
||||||
|
|
||||||
|
public SettingsWindow() {
|
||||||
|
Text = @"Top Most Friend Settings";
|
||||||
|
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
|
||||||
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
|
FormBorderStyle = FormBorderStyle.FixedSingle;
|
||||||
|
AutoScaleMode = AutoScaleMode.Dpi;
|
||||||
|
ClientSize = new Size(410, 113);
|
||||||
|
MinimizeBox = MaximizeBox = false;
|
||||||
|
MinimumSize = MaximumSize = Size;
|
||||||
|
|
||||||
|
KeyCode = Settings.Get(Program.FOREGROUND_HOTKEY_SETTING, 0);
|
||||||
|
|
||||||
|
Button applyButton = new Button {
|
||||||
|
Text = @"Apply",
|
||||||
|
Size = new Size(75, 23),
|
||||||
|
Location = new Point(ClientSize.Width - 81, ClientSize.Height - 30),
|
||||||
|
TabIndex = 10003,
|
||||||
|
};
|
||||||
|
applyButton.Click += ApplyButton_Click;
|
||||||
|
Button cancelButton = new Button {
|
||||||
|
Text = @"Cancel",
|
||||||
|
Size = applyButton.Size,
|
||||||
|
Location = new Point(ClientSize.Width - 162, applyButton.Location.Y),
|
||||||
|
TabIndex = 10002,
|
||||||
|
};
|
||||||
|
cancelButton.Click += CancelButton_Click;
|
||||||
|
Button okButton = new Button {
|
||||||
|
Text = @"OK",
|
||||||
|
Size = applyButton.Size,
|
||||||
|
Location = new Point(ClientSize.Width - 243, applyButton.Location.Y),
|
||||||
|
TabIndex = 10001,
|
||||||
|
};
|
||||||
|
okButton.Click += OkButton_Click;
|
||||||
|
|
||||||
|
GroupBox hotKeyGroup = new GroupBox {
|
||||||
|
Text = @"Hotkeys",
|
||||||
|
Location = new Point(6, 6),
|
||||||
|
Size = new Size(Width - 18, 70),
|
||||||
|
};
|
||||||
|
|
||||||
|
Controls.AddRange(new Control[] {
|
||||||
|
applyButton, cancelButton, okButton, hotKeyGroup,
|
||||||
|
});
|
||||||
|
|
||||||
|
Label toggleForegroundLabel = new Label {
|
||||||
|
AutoSize = true,
|
||||||
|
Text = @"Toggle always on top status on active window",
|
||||||
|
Location = new Point(8, 17),
|
||||||
|
};
|
||||||
|
|
||||||
|
const int mod_x = 120;
|
||||||
|
const int mod_y = 34;
|
||||||
|
|
||||||
|
Button fgReset = new Button {
|
||||||
|
Text = @"Reset",
|
||||||
|
Location = new Point(hotKeyGroup.Width - 85, mod_y),
|
||||||
|
};
|
||||||
|
fgReset.Click += FgReset_Click;
|
||||||
|
|
||||||
|
FgKey = new TextBox {
|
||||||
|
Text = ((Keys)(KeyCode >> 16)).ToString(),
|
||||||
|
Location = new Point(12, mod_y + 2),
|
||||||
|
};
|
||||||
|
FgKey.KeyDown += FgKey_KeyDown;
|
||||||
|
|
||||||
|
FgModCtrl = new CheckBox {
|
||||||
|
Text = @"CTRL",
|
||||||
|
Location = new Point(mod_x, mod_y),
|
||||||
|
Checked = (KeyCode & (int)Win32ModKeys.MOD_CONTROL) > 0,
|
||||||
|
Appearance = Appearance.Button,
|
||||||
|
Size = new Size(50, 23),
|
||||||
|
TextAlign = ContentAlignment.MiddleCenter,
|
||||||
|
};
|
||||||
|
FgModCtrl.Click += FgModCtrl_Click;
|
||||||
|
|
||||||
|
FgModAlt = new CheckBox {
|
||||||
|
Text = @"ALT",
|
||||||
|
Location = new Point(mod_x + 50, mod_y),
|
||||||
|
Checked = (KeyCode & (int)Win32ModKeys.MOD_ALT) > 0,
|
||||||
|
Appearance = FgModCtrl.Appearance,
|
||||||
|
Size = FgModCtrl.Size,
|
||||||
|
TextAlign = FgModCtrl.TextAlign,
|
||||||
|
};
|
||||||
|
FgModAlt.Click += FgModAlt_Click;
|
||||||
|
|
||||||
|
FgModShift = new CheckBox {
|
||||||
|
Text = @"SHIFT",
|
||||||
|
Location = new Point(mod_x + 100, mod_y),
|
||||||
|
Checked = (KeyCode & (int)Win32ModKeys.MOD_SHIFT) > 0,
|
||||||
|
Appearance = FgModCtrl.Appearance,
|
||||||
|
Size = FgModCtrl.Size,
|
||||||
|
TextAlign = FgModCtrl.TextAlign,
|
||||||
|
};
|
||||||
|
FgModShift.Click += FgModShift_Click;
|
||||||
|
|
||||||
|
hotKeyGroup.Controls.AddRange(new Control[] {
|
||||||
|
toggleForegroundLabel, FgModCtrl, FgModAlt, FgModShift, fgReset, FgKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FgReset_Click(object sender, EventArgs e) {
|
||||||
|
FgModCtrl.Checked = FgModAlt.Checked = FgModShift.Checked = false;
|
||||||
|
FgKey.Text = string.Empty;
|
||||||
|
KeyCode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Apply() {
|
||||||
|
Settings.Set(Program.FOREGROUND_HOTKEY_SETTING, KeyCode);
|
||||||
|
Program.SetForegroundHotKey(KeyCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OkButton_Click(object sender, EventArgs e) {
|
||||||
|
Apply();
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
private void CancelButton_Click(object sender, EventArgs e) {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
private void ApplyButton_Click(object sender, EventArgs e) {
|
||||||
|
Apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FgModCtrl_Click(object sender, EventArgs e) {
|
||||||
|
if(sender is CheckBox cb) {
|
||||||
|
if (cb.Checked)
|
||||||
|
KeyCode |= (int)Win32ModKeys.MOD_CONTROL;
|
||||||
|
else
|
||||||
|
KeyCode &= ~(int)Win32ModKeys.MOD_CONTROL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void FgModAlt_Click(object sender, EventArgs e) {
|
||||||
|
if (sender is CheckBox cb) {
|
||||||
|
if (cb.Checked)
|
||||||
|
KeyCode |= (int)Win32ModKeys.MOD_ALT;
|
||||||
|
else
|
||||||
|
KeyCode &= ~(int)Win32ModKeys.MOD_ALT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void FgModShift_Click(object sender, EventArgs e) {
|
||||||
|
if (sender is CheckBox cb) {
|
||||||
|
if (cb.Checked)
|
||||||
|
KeyCode |= (int)Win32ModKeys.MOD_SHIFT;
|
||||||
|
else
|
||||||
|
KeyCode &= ~(int)Win32ModKeys.MOD_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FgKey_KeyDown(object sender, KeyEventArgs e) {
|
||||||
|
if (!(sender is TextBox textBox))
|
||||||
|
return;
|
||||||
|
e.Handled = e.SuppressKeyPress = true;
|
||||||
|
textBox.Text = e.KeyCode.ToString();
|
||||||
|
KeyCode &= 0xFFFF;
|
||||||
|
KeyCode |= (int)e.KeyCode << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnFormClosed(FormClosedEventArgs e) {
|
||||||
|
base.OnFormClosed(e);
|
||||||
|
Instance.Dispose();
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,6 +44,9 @@
|
||||||
<Compile Include="AboutWindow.cs">
|
<Compile Include="AboutWindow.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="HotKeyWindow.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
@ -51,6 +54,11 @@
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Settings.cs" />
|
||||||
|
<Compile Include="SettingsWindow.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Win32.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -66,6 +74,7 @@
|
||||||
<None Include="Resources\help.png" />
|
<None Include="Resources\help.png" />
|
||||||
<None Include="Resources\door_in.png" />
|
<None Include="Resources\door_in.png" />
|
||||||
<None Include="Resources\about.png" />
|
<None Include="Resources\about.png" />
|
||||||
|
<None Include="Resources\cog.png" />
|
||||||
<Content Include="TopMostFriend.ico" />
|
<Content Include="TopMostFriend.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
123
TopMostFriend/Win32.cs
Normal file
123
TopMostFriend/Win32.cs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TopMostFriend {
|
||||||
|
[Flags]
|
||||||
|
public enum Win32ModKeys : uint {
|
||||||
|
[Description(@"Alt")]
|
||||||
|
MOD_ALT = 0x0001,
|
||||||
|
[Description(@"Ctrl")]
|
||||||
|
MOD_CONTROL = 0x0002,
|
||||||
|
[Description(@"Shift")]
|
||||||
|
MOD_SHIFT = 0x0004,
|
||||||
|
[Description(@"Windows")]
|
||||||
|
MOD_WIN = 0x0008,
|
||||||
|
MOD_NOREPEAT = 0x4000,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Win32 {
|
||||||
|
public const int HWND_TOPMOST = -1;
|
||||||
|
public const int HWND_NOTOPMOST = -2;
|
||||||
|
|
||||||
|
public const int SWP_NOSIZE = 0x0001;
|
||||||
|
public const int SWP_NOMOVE = 0x0002;
|
||||||
|
public const int SWP_SHOWWINDOW = 0x0040;
|
||||||
|
|
||||||
|
public const int GWL_EXSTYLE = -20;
|
||||||
|
|
||||||
|
public const int GCL_HICON = -14;
|
||||||
|
public const int GCL_HICONSM = -34;
|
||||||
|
|
||||||
|
public const int WS_EX_TOPMOST = 0x08;
|
||||||
|
|
||||||
|
public const int HT_CAPTION = 0x02;
|
||||||
|
|
||||||
|
public const int WM_GETICON = 0x007F;
|
||||||
|
public const int WM_NCLBUTTONDOWN = 0x00A1;
|
||||||
|
public const int WM_HOTKEY = 0x0312;
|
||||||
|
|
||||||
|
public const int ICON_SMALL = 0;
|
||||||
|
public const int ICON_BIG = 1;
|
||||||
|
public const int ICON_SMALL2 = 2;
|
||||||
|
|
||||||
|
[DllImport(@"user32")]
|
||||||
|
public static extern bool SetProcessDPIAware();
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true)]
|
||||||
|
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true)]
|
||||||
|
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
||||||
|
|
||||||
|
public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex) {
|
||||||
|
if (IntPtr.Size == 8)
|
||||||
|
return GetWindowLongPtr64(hWnd, nIndex);
|
||||||
|
return new IntPtr(GetWindowLong32(hWnd, nIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(@"user32", EntryPoint = "GetWindowLong")]
|
||||||
|
public static extern int GetWindowLong32(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport(@"user32", EntryPoint = "GetWindowLongPtr")]
|
||||||
|
public static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport(@"user32")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool IsWindowVisible(IntPtr hWnd);
|
||||||
|
|
||||||
|
[DllImport(@"user32", CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
|
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
|
public static extern int GetWindowTextLength(IntPtr hWnd);
|
||||||
|
|
||||||
|
public static string GetWindowTextString(IntPtr hwnd) {
|
||||||
|
int length = GetWindowTextLength(hwnd) + 1;
|
||||||
|
StringBuilder sb = new StringBuilder(length);
|
||||||
|
GetWindowText(hwnd, sb, length);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex) {
|
||||||
|
if (IntPtr.Size > 4)
|
||||||
|
return GetClassLongPtr64(hWnd, nIndex);
|
||||||
|
return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(@"user32", EntryPoint = "GetClassLong")]
|
||||||
|
public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport(@"user32", EntryPoint = "GetClassLongPtr")]
|
||||||
|
public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true)]
|
||||||
|
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true)]
|
||||||
|
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int uFlags);
|
||||||
|
|
||||||
|
[DllImport(@"user32", CharSet = CharSet.Auto, SetLastError = false)]
|
||||||
|
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
|
||||||
|
|
||||||
|
[DllImport(@"user32")]
|
||||||
|
public static extern bool ReleaseCapture();
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true)]
|
||||||
|
public static extern IntPtr GetForegroundWindow();
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true)]
|
||||||
|
public static extern bool RegisterHotKey(IntPtr hWnd, int id, [MarshalAs(UnmanagedType.U4)] Win32ModKeys fsModifiers, [MarshalAs(UnmanagedType.U4)] Keys vk);
|
||||||
|
|
||||||
|
[DllImport(@"user32", SetLastError = true)]
|
||||||
|
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||||
|
|
||||||
|
[DllImport(@"kernel32", SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
|
public static extern ushort GlobalAddAtom(string lpString);
|
||||||
|
|
||||||
|
[DllImport(@"kernel32", SetLastError = true, ExactSpelling = true)]
|
||||||
|
public static extern ushort GlobalDeleteAtom(ushort nAtom);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue