├── img
└── icon.png
├── Setup
├── pinwin.ico
├── Setup.wixproj
└── PinWin.wxs
├── PinWin
├── Resources
│ ├── pinwin.ico
│ ├── pinwinwhite.ico
│ ├── iconfinder_17-Denied_2123868.png
│ ├── iconfinder_30-Target_2123952.png
│ ├── iconfinder_38-Option_2123921.png
│ └── iconfinder_14-Question_2123865.png
├── packages.config
├── Properties
│ ├── Settings.settings
│ ├── AssemblyInfo.cs
│ ├── Settings.Designer.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Program.cs
├── App.config
├── TrayApplicationContext.cs
├── WinApi.cs
├── OptionsForm.cs
├── PinWin.csproj
├── MainApplicationContext.cs
└── OptionsForm.Designer.cs
├── Changelog.md
├── choco
├── tools
│ └── chocolateyinstall.ps1
└── pinwin.nuspec
├── LICENSE.txt
├── README.md
├── .gitattributes
├── PinWin.sln
└── .gitignore
/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/img/icon.png
--------------------------------------------------------------------------------
/Setup/pinwin.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/Setup/pinwin.ico
--------------------------------------------------------------------------------
/PinWin/Resources/pinwin.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/PinWin/Resources/pinwin.ico
--------------------------------------------------------------------------------
/PinWin/Resources/pinwinwhite.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/PinWin/Resources/pinwinwhite.ico
--------------------------------------------------------------------------------
/PinWin/Resources/iconfinder_17-Denied_2123868.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/PinWin/Resources/iconfinder_17-Denied_2123868.png
--------------------------------------------------------------------------------
/PinWin/Resources/iconfinder_30-Target_2123952.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/PinWin/Resources/iconfinder_30-Target_2123952.png
--------------------------------------------------------------------------------
/PinWin/Resources/iconfinder_38-Option_2123921.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/PinWin/Resources/iconfinder_38-Option_2123921.png
--------------------------------------------------------------------------------
/PinWin/Resources/iconfinder_14-Question_2123865.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bluegrams/PinWin/HEAD/PinWin/Resources/iconfinder_14-Question_2123865.png
--------------------------------------------------------------------------------
/PinWin/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Changelog.md:
--------------------------------------------------------------------------------
1 | # PinWin Changelog
2 |
3 | ### v.0.2.2 (2020-04)
4 | - **Fixed:** A bug when opening the options window.
5 |
6 | ### v.0.2.1 (2020-03)
7 | - **Fixed:** App crashes after upgrade from v.0.1. or when opening menu.
8 |
9 | ### v.0.2 (2020-03)
10 | - **New:** Option to show windows list below other items in menu
11 | - **Fixed:** Global hotkey input
12 |
13 | ### v.0.1 (2019-09)
14 | - First released version
15 |
--------------------------------------------------------------------------------
/choco/tools/chocolateyinstall.ps1:
--------------------------------------------------------------------------------
1 | $ErrorActionPreference = 'Stop';
2 | $toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
3 | $fileLocation = Join-Path $toolsDir 'PinWinSetup.msi'
4 |
5 | $packageArgs = @{
6 | packageName = $env:ChocolateyPackageName
7 | fileType = 'msi'
8 | file = $fileLocation
9 | softwareName = 'PinWin*'
10 | silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`""
11 | validExitCodes= @(0, 3010, 1641)
12 | }
13 |
14 | Install-ChocolateyInstallPackage @packageArgs
15 |
--------------------------------------------------------------------------------
/PinWin/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Control+Alt+V
7 |
8 |
9 | True
10 |
11 |
12 | 50
13 |
14 |
15 | False
16 |
17 |
18 |
--------------------------------------------------------------------------------
/PinWin/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using Bluegrams.Application;
4 | using PinWin.Properties;
5 |
6 | namespace PinWin
7 | {
8 | static class Program
9 | {
10 | internal const string UPDATE_URL = "https://pinwin.sourceforge.io/update.xml";
11 |
12 | #if PORTABLE
13 | internal const string UPDATE_IDENTIFIER = "portable";
14 | #else
15 | internal const string UPDATE_IDENTIFIER = "install";
16 | #endif
17 |
18 | [STAThread]
19 | static void Main()
20 | {
21 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
22 | if (AppInfo.IsPortable.GetValueOrDefault())
23 | PortableSettingsProvider.ApplyProvider(Settings.Default);
24 | Application.EnableVisualStyles();
25 | Application.SetCompatibleTextRenderingDefault(false);
26 | Application.Run(new MainApplicationContext());
27 | }
28 |
29 | private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
30 | {
31 | Logger.Default.Log("An unhandled exception caused the application to terminate unexpectedly.",
32 | (Exception)e.ExceptionObject);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/PinWin/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Control+Alt+V
15 |
16 |
17 | True
18 |
19 |
20 | 50
21 |
22 |
23 | False
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2020, Bluegrams.
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/PinWin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using Bluegrams.Application.Attributes;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("PinWin - Pin On Top")]
9 | [assembly: AssemblyDescription("PinWin - Pin Any Window On Top of the Screen")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Bluegrams")]
12 | [assembly: AssemblyProduct("PinWin")]
13 | [assembly: AssemblyCopyright("Copyright © 2020 Bluegrams")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | #if PORTABLE
18 | [assembly: AppPortable(true)]
19 | #else
20 | [assembly: AppPortable(false)]
21 | #endif
22 | [assembly: ProductWebsite("https://pinwin.sourceforge.io")]
23 |
24 | // Setting ComVisible to false makes the types in this assembly not visible
25 | // to COM components. If you need to access a type in this assembly from
26 | // COM, set the ComVisible attribute to true on that type.
27 | [assembly: ComVisible(false)]
28 |
29 | // The following GUID is for the ID of the typelib if this project is exposed to COM
30 | [assembly: Guid("7e06ba38-b308-43e9-b1a6-7851e7a8cbf2")]
31 |
32 | // Version information for an assembly consists of the following four values:
33 | //
34 | // Major Version
35 | // Minor Version
36 | // Build Number
37 | // Revision
38 | //
39 | // You can specify all the values or you can default the Build and Revision Numbers
40 | // by using the '*' as shown below:
41 | // [assembly: AssemblyVersion("1.0.*")]
42 | [assembly: AssemblyVersion("0.2.2.0")]
43 | [assembly: AssemblyFileVersion("0.2.2.0")]
44 |
--------------------------------------------------------------------------------
/choco/pinwin.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | pinwin
7 | 0.2.2
8 | alxnull
9 |
10 |
11 |
12 | PinWin
13 | alxnull
14 | https://sf.net/p/pinwin
15 | https://gitcdn.xyz/repo/Bluegrams/PinWin/master/img/icon.png
16 | © 2020 Bluegrams
17 | https://github.com/Bluegrams/PinWin/blob/master/LICENSE.txt
18 | false
19 | https://github.com/Bluegrams/PinWin
20 | https://github.com/Bluegrams/PinWin/issues
21 | pinwin windows always-on-top ontop pin desktop
22 | Pin any window to be always on top of the screen.
23 | PinWin is a minimal Windows system tray application that allows you to pin any windows to the top of the screen with one click.
24 | https://github.com/Bluegrams/PinWin/blob/master/Changelog.md
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PinWin - Pin On Top
2 |
3 | [](https://github.com/bluegrams/pinwin/blob/master/LICENSE.txt)
4 | [](https://github.com/bluegrams/pinwin)
5 | [](https://sourceforge.net/projects/pinwin/files/)
6 |
7 | > Pin any window to be always on top of the screen
8 |
9 | [](https://sourceforge.net/projects/pinwin/files/)
10 |
11 | PinWin is a minimal Windows system tray application that allows you to pin any windows to the top of the screen with one click.
12 |
13 | ## Features
14 |
15 | - Pin windows from list in system tray
16 |
17 | - Directly select window from screen
18 |
19 | - Global shortcut for selecting windows
20 |
21 | - Runs quietly in background and does not need installation
22 |
23 | ## Setup
24 |
25 | #### Requirements
26 |
27 | PinWin requires Windows 7 or newer and .NET Framework 4.6.2 or higher.
28 |
29 | #### Installation
30 |
31 | - Download the [latest release from SourceForge](https://sourceforge.net/projects/pinwin/files/)
32 |
33 | or
34 |
35 | - Install from [Chocolatey](https://chocolatey.org):
36 | ```
37 | choco install pinwin
38 | ```
39 |
40 | ## Feedback and Support
41 |
42 | _Please leave a feedback on [Sourceforge](https://sourceforge.net/p/pinwin/reviews). Thank you!_
43 |
44 | Places to get help:
45 |
46 | * Ask on [Sourceforge](https://sourceforge.net/p/pinwin/discussion/) (General help, ideas etc.)
47 | * Open an issue on [GitHub](https://github.com/bluegrams/pinwin/issues) (Bugs, feature requests etc.)
48 |
49 | ## Contribute
50 |
51 | You are very welcome to contribute fixes and new features by opening a [pull request on GitHub](https://github.com/bluegrams/pinwin/pulls).
52 |
53 | ## License
54 |
55 | This software is published under [BSD-3-Clause license](https://github.com/Bluegrams/pinwin/blob/master/LICENSE.txt) by Bluegrams.
56 |
--------------------------------------------------------------------------------
/PinWin/TrayApplicationContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Windows.Forms;
4 |
5 | namespace PinWin
6 | {
7 | public class TrayApplicationContext : ApplicationContext
8 | {
9 | public ContextMenuStrip ContextMenu { get; private set; }
10 |
11 | public NotifyIcon NotifyIcon { get; private set; }
12 |
13 | public TrayApplicationContext(Icon icon)
14 | {
15 | ContextMenu = new ContextMenuStrip();
16 | NotifyIcon = new NotifyIcon()
17 | {
18 | Text = Application.ProductName,
19 | Icon = icon,
20 | ContextMenuStrip = ContextMenu,
21 | Visible = true
22 | };
23 | NotifyIcon.MouseClick += NotifyIcon_MouseClick;
24 | NotifyIcon.MouseDoubleClick += NotifyIcon_MouseDoubleClick;
25 | Application.ApplicationExit += Application_ApplicationExit;
26 | }
27 |
28 | protected virtual void OnNotifyIconClick(EventArgs e) { }
29 |
30 | protected virtual void OnNotifyIconDoubleClick(EventArgs e) { }
31 |
32 | protected virtual void OnApplicationExit(EventArgs e) { }
33 |
34 |
35 | private void NotifyIcon_MouseClick(object sender, MouseEventArgs e)
36 | {
37 | if (e.Button == MouseButtons.Right)
38 | {
39 | ContextMenu.Show(Cursor.Position, ToolStripDropDownDirection.AboveRight);
40 | }
41 | else OnNotifyIconClick(e);
42 |
43 | }
44 |
45 | private void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
46 | {
47 | OnNotifyIconDoubleClick(e);
48 | }
49 |
50 | private void Application_ApplicationExit(object sender, EventArgs e)
51 | {
52 | OnApplicationExit(e);
53 | if (ContextMenu != null)
54 | ContextMenu.Dispose();
55 | if (NotifyIcon != null)
56 | {
57 | NotifyIcon.Visible = false;
58 | NotifyIcon.Dispose();
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/PinWin/WinApi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 |
7 | namespace PinWin
8 | {
9 | public static class WinApi
10 | {
11 | private delegate bool EnumDelegate(IntPtr hWnd, int lParam);
12 |
13 | #region Win32 API methods
14 |
15 | [DllImport("user32.dll")]
16 | private static extern bool EnumWindows(EnumDelegate lpEnumFunc, IntPtr lParam);
17 |
18 | [DllImport("user32.dll")]
19 | private static extern bool IsWindowVisible(IntPtr hWnd);
20 |
21 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
22 | private static extern int GetWindowTextLength(IntPtr hWnd);
23 |
24 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
25 | private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
26 |
27 | [DllImport("user32.dll")]
28 | private static extern IntPtr GetShellWindow();
29 |
30 | [DllImport("user32.dll")]
31 | private static extern long GetWindowLong(IntPtr hWnd, int nIndex);
32 |
33 | [DllImport("user32.dll", SetLastError = true)]
34 | private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
35 |
36 | #endregion
37 |
38 | public static Dictionary GetWindowHandles()
39 | {
40 | IntPtr shellWindow = GetShellWindow();
41 | Dictionary handles = new Dictionary();
42 | EnumDelegate callback = (IntPtr hWnd, int lParam) =>
43 | {
44 | if (hWnd == shellWindow || !IsWindowVisible(hWnd)) return true;
45 | int length = GetWindowTextLength(hWnd);
46 | if (length == 0) return true;
47 | StringBuilder sb = new StringBuilder(length + 1);
48 | GetWindowText(hWnd, sb, sb.Capacity);
49 | var title = Regex.Replace(sb.ToString(), @"[\ue000-\uf8ff]", string.Empty);
50 | if (String.IsNullOrEmpty(title)) return true;
51 | handles.Add(hWnd, title);
52 | return true;
53 | };
54 | EnumWindows(callback, IntPtr.Zero);
55 | return handles;
56 | }
57 |
58 | public static bool GetWindowTopmost(IntPtr hWnd)
59 | {
60 | long val = GetWindowLong(hWnd, /* GWL_EXSTYLE */ -20);
61 | return (val & /* WS_EX_TOPMOST */ 0x8L) != 0;
62 | }
63 |
64 | public static bool SetWindowTopmost(IntPtr hWnd, bool topmost)
65 | {
66 | IntPtr mode = topmost ? /* HWND_TOPMOST */ (IntPtr)(-1)
67 | : /* HWND_NOTOPMOST */ (IntPtr)(-2);
68 | return SetWindowPos(hWnd, mode, 0, 0, 0, 0, /* SWP_NOMOVE | SWP_NOSIZE */ 0x1 | 0x2);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Setup/Setup.wixproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 3.10
7 | dd87ceb2-5635-488b-bd9c-52cbd93a608c
8 | 2.0
9 | PinWinSetup
10 | Package
11 |
12 |
13 | bin\$(Configuration)\
14 | obj\$(Configuration)\
15 | Debug
16 |
17 |
18 | bin\$(Configuration)\
19 | obj\$(Configuration)\
20 |
21 |
22 |
23 |
24 |
25 |
26 | PinWin
27 | {7e06ba38-b308-43e9-b1a6-7851e7a8cbf2}
28 | True
29 | True
30 | Binaries;Content;Satellites
31 | INSTALLFOLDER
32 |
33 |
34 |
35 |
36 | $(WixExtDir)\WixNetFxExtension.dll
37 | WixNetFxExtension
38 |
39 |
40 | $(WixExtDir)\WixUIExtension.dll
41 | WixUIExtension
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
60 |
--------------------------------------------------------------------------------
/PinWin/OptionsForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using Bluegrams.Windows.Tools;
4 | using PinWin.Properties;
5 |
6 | namespace PinWin
7 | {
8 | public partial class OptionsForm : Form
9 | {
10 | private MainApplicationContext main;
11 | private KeyCombination selectedKeys;
12 |
13 | public OptionsForm(MainApplicationContext main)
14 | {
15 | this.main = main;
16 | this.selectedKeys = main.HotKey?.KeyCombination ?? KeyCombination.None;
17 | InitializeComponent();
18 | // --- General section ---
19 | chkTruncateTitle.Checked = Settings.Default.TitleLengthLimit < int.MaxValue;
20 | numLimit.Enabled = chkTruncateTitle.Checked;
21 | if (chkTruncateTitle.Checked)
22 | {
23 | numLimit.Value = Settings.Default.TitleLengthLimit;
24 | }
25 | chkWindowsAtEnd.Checked = Settings.Default.WindowsListAtEnd;
26 | chkHotKey.Checked = main.HotKey != null;
27 | panHotKey.Enabled = chkHotKey.Checked;
28 | txtHotKey.Text = selectedKeys.ToString();
29 | // --- Application section ---
30 | chkUpdates.Checked = Settings.Default.AlwaysCheckForUpdates;
31 | }
32 |
33 | private void chkTruncateTitle_CheckedChanged(object sender, EventArgs e)
34 | {
35 | numLimit.Enabled = chkTruncateTitle.Checked;
36 | }
37 |
38 | private void chkHotKey_CheckedChanged(object sender, EventArgs e)
39 | {
40 | panHotKey.Enabled = chkHotKey.Checked;
41 | }
42 |
43 | private void butHotKey_Click(object sender, EventArgs e)
44 | {
45 | // remove current shortcut during key selection
46 | main.SetHotKey(KeyCombination.None);
47 | HotKeyInputForm hkForm = new HotKeyInputForm((Keys)selectedKeys);
48 | if (hkForm.ShowDialog(this) == DialogResult.OK)
49 | {
50 | selectedKeys = (KeyCombination)hkForm.SelectedKeys;
51 | txtHotKey.Text = selectedKeys.ToString();
52 | }
53 | // restores previous shortcut
54 | main.SetHotKey(selectedKeys);
55 | }
56 |
57 | private void butSubmit_Click(object sender, EventArgs e)
58 | {
59 | // --- General section ---
60 | if (chkHotKey.Checked)
61 | {
62 | if (!main.SetHotKey(selectedKeys)) return;
63 | }
64 | else main.SetHotKey(KeyCombination.None);
65 | if (chkTruncateTitle.Checked)
66 | Settings.Default.TitleLengthLimit = (int)numLimit.Value;
67 | else Settings.Default.TitleLengthLimit = int.MaxValue;
68 | Settings.Default.WindowsListAtEnd = chkWindowsAtEnd.Checked;
69 | // --- Application section
70 | Settings.Default.AlwaysCheckForUpdates = chkUpdates.Checked;
71 | this.Close();
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/PinWin/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PinWin.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("Control+Alt+V")]
29 | public string HotKey {
30 | get {
31 | return ((string)(this["HotKey"]));
32 | }
33 | set {
34 | this["HotKey"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
41 | public bool AlwaysCheckForUpdates {
42 | get {
43 | return ((bool)(this["AlwaysCheckForUpdates"]));
44 | }
45 | set {
46 | this["AlwaysCheckForUpdates"] = value;
47 | }
48 | }
49 |
50 | [global::System.Configuration.UserScopedSettingAttribute()]
51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
52 | [global::System.Configuration.DefaultSettingValueAttribute("50")]
53 | public int TitleLengthLimit {
54 | get {
55 | return ((int)(this["TitleLengthLimit"]));
56 | }
57 | set {
58 | this["TitleLengthLimit"] = value;
59 | }
60 | }
61 |
62 | [global::System.Configuration.UserScopedSettingAttribute()]
63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
64 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
65 | public bool WindowsListAtEnd {
66 | get {
67 | return ((bool)(this["WindowsListAtEnd"]));
68 | }
69 | set {
70 | this["WindowsListAtEnd"] = value;
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/PinWin.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.645
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PinWin", "PinWin\PinWin.csproj", "{7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{060ED345-F2C1-408B-B1A7-37CFCC2A168B}"
9 | ProjectSection(SolutionItems) = preProject
10 | Changelog.md = Changelog.md
11 | LICENSE.txt = LICENSE.txt
12 | README.md = README.md
13 | EndProjectSection
14 | EndProject
15 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup", "Setup\Setup.wixproj", "{DD87CEB2-5635-488B-BD9C-52CBD93A608C}"
16 | EndProject
17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "choco", "choco", "{E667BED5-F79A-4305-B701-AED24AB5EADC}"
18 | ProjectSection(SolutionItems) = preProject
19 | choco\pinwin.nuspec = choco\pinwin.nuspec
20 | EndProjectSection
21 | EndProject
22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{D6DF54E0-79AF-462A-A802-4464118076CA}"
23 | ProjectSection(SolutionItems) = preProject
24 | choco\tools\chocolateyinstall.ps1 = choco\tools\chocolateyinstall.ps1
25 | EndProjectSection
26 | EndProject
27 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "img", "img", "{2FAC4F97-AEF9-471E-9B57-579290BDE553}"
28 | ProjectSection(SolutionItems) = preProject
29 | img\icon.png = img\icon.png
30 | EndProjectSection
31 | EndProject
32 | Global
33 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
34 | Debug|Any CPU = Debug|Any CPU
35 | Publish-Install|Any CPU = Publish-Install|Any CPU
36 | Publish-Portable|Any CPU = Publish-Portable|Any CPU
37 | Release|Any CPU = Release|Any CPU
38 | EndGlobalSection
39 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
40 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Publish-Install|Any CPU.ActiveCfg = Release|Any CPU
43 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Publish-Install|Any CPU.Build.0 = Release|Any CPU
44 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Publish-Portable|Any CPU.ActiveCfg = Portable|Any CPU
45 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Publish-Portable|Any CPU.Build.0 = Portable|Any CPU
46 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {DD87CEB2-5635-488B-BD9C-52CBD93A608C}.Debug|Any CPU.ActiveCfg = Debug|x86
49 | {DD87CEB2-5635-488B-BD9C-52CBD93A608C}.Publish-Install|Any CPU.ActiveCfg = Release|x86
50 | {DD87CEB2-5635-488B-BD9C-52CBD93A608C}.Publish-Install|Any CPU.Build.0 = Release|x86
51 | {DD87CEB2-5635-488B-BD9C-52CBD93A608C}.Publish-Portable|Any CPU.ActiveCfg = Release|x86
52 | {DD87CEB2-5635-488B-BD9C-52CBD93A608C}.Release|Any CPU.ActiveCfg = Release|x86
53 | EndGlobalSection
54 | GlobalSection(SolutionProperties) = preSolution
55 | HideSolutionNode = FALSE
56 | EndGlobalSection
57 | GlobalSection(NestedProjects) = preSolution
58 | {E667BED5-F79A-4305-B701-AED24AB5EADC} = {060ED345-F2C1-408B-B1A7-37CFCC2A168B}
59 | {D6DF54E0-79AF-462A-A802-4464118076CA} = {E667BED5-F79A-4305-B701-AED24AB5EADC}
60 | {2FAC4F97-AEF9-471E-9B57-579290BDE553} = {060ED345-F2C1-408B-B1A7-37CFCC2A168B}
61 | EndGlobalSection
62 | GlobalSection(ExtensibilityGlobals) = postSolution
63 | SolutionGuid = {23B94BA9-5C80-4343-ADD9-343CB9F9804D}
64 | EndGlobalSection
65 | EndGlobal
66 |
--------------------------------------------------------------------------------
/PinWin/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PinWin.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PinWin.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap AboutIcon {
67 | get {
68 | object obj = ResourceManager.GetObject("AboutIcon", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Bitmap.
75 | ///
76 | internal static System.Drawing.Bitmap DeleteIcon {
77 | get {
78 | object obj = ResourceManager.GetObject("DeleteIcon", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Drawing.Bitmap.
85 | ///
86 | internal static System.Drawing.Bitmap OptionsIcon {
87 | get {
88 | object obj = ResourceManager.GetObject("OptionsIcon", resourceCulture);
89 | return ((System.Drawing.Bitmap)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
95 | ///
96 | internal static System.Drawing.Icon PinWinIconBlack {
97 | get {
98 | object obj = ResourceManager.GetObject("PinWinIconBlack", resourceCulture);
99 | return ((System.Drawing.Icon)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
105 | ///
106 | internal static System.Drawing.Icon PinWinIconWhite {
107 | get {
108 | object obj = ResourceManager.GetObject("PinWinIconWhite", resourceCulture);
109 | return ((System.Drawing.Icon)(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Looks up a localized resource of type System.Drawing.Bitmap.
115 | ///
116 | internal static System.Drawing.Bitmap TargetIcon {
117 | get {
118 | object obj = ResourceManager.GetObject("TargetIcon", resourceCulture);
119 | return ((System.Drawing.Bitmap)(obj));
120 | }
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
262 |
263 | # Custom
264 | *.msi
265 |
--------------------------------------------------------------------------------
/PinWin/PinWin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7E06BA38-B308-43E9-B1A6-7851E7A8CBF2}
8 | WinExe
9 | PinWin
10 | PinWin
11 | v4.6.2
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 | Resources\pinwin.ico
37 |
38 |
39 | bin\Portable\
40 | TRACE;PORTABLE
41 | true
42 | pdbonly
43 | AnyCPU
44 | prompt
45 | MinimumRecommendedRules.ruleset
46 | true
47 |
48 |
49 |
50 | ..\packages\AppHelpers.WinForms.0.1.0-beta7\lib\net45\AppHelpers.WinForms.dll
51 |
52 |
53 | ..\packages\Bluegrams.Windows.Tools.0.1.0-alpha\lib\net45\Bluegrams.Windows.Tools.dll
54 |
55 |
56 | ..\packages\PortableSettingsProvider.0.2.3\lib\net45\PortableSettingsProvider.dll
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Form
75 |
76 |
77 | OptionsForm.cs
78 |
79 |
80 |
81 |
82 |
83 |
84 | OptionsForm.cs
85 |
86 |
87 | ResXFileCodeGenerator
88 | Resources.Designer.cs
89 | Designer
90 |
91 |
92 | True
93 | Resources.resx
94 | True
95 |
96 |
97 |
98 | SettingsSingleFileGenerator
99 | Settings.Designer.cs
100 |
101 |
102 | True
103 | Settings.settings
104 | True
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/PinWin/MainApplicationContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Windows.Forms;
4 | using System.Drawing;
5 | using System.Collections.Generic;
6 | using PinWin.Properties;
7 | using Bluegrams.Windows.Tools;
8 | using Bluegrams.Application.WinForms;
9 | using Bluegrams.Application;
10 |
11 | namespace PinWin
12 | {
13 | public class MainApplicationContext : TrayApplicationContext
14 | {
15 | private bool notify = true;
16 | private IUpdateChecker updateChecker;
17 |
18 | public GlobalHotKey HotKey { get; private set; }
19 |
20 | public MainApplicationContext() : base(Resources.PinWinIconWhite)
21 | {
22 | ContextMenu.Opening += ContextMenu_Opening;
23 | if (!String.IsNullOrWhiteSpace(Settings.Default.HotKey))
24 | {
25 | var keyConv = new KeysConverter();
26 | Keys keys = (Keys)keyConv.ConvertFromInvariantString(Settings.Default.HotKey);
27 | SetHotKey((KeyCombination)keys);
28 | }
29 | Application.ApplicationExit += Application_ApplicationExit;
30 | updateChecker = new WinFormsUpdateChecker(Program.UPDATE_URL, identifier: Program.UPDATE_IDENTIFIER);
31 | if (Settings.Default.AlwaysCheckForUpdates)
32 | updateChecker.CheckForUpdates();
33 | }
34 |
35 | public bool SetHotKey(KeyCombination keyCombination)
36 | {
37 | HotKey?.Dispose();
38 | HotKey = null;
39 | if (keyCombination == KeyCombination.None) return true;
40 | HotKey = new GlobalHotKey(keyCombination, onHotKeyPressed);
41 | if (!HotKey.Register())
42 | {
43 | MessageBox.Show("Failed to register global shortcut.\nThis may happen if the defined shortcut is already in use.", "PinWin - Error");
44 | return false;
45 | }
46 | return true;
47 | }
48 |
49 | protected override void OnNotifyIconClick(EventArgs e)
50 | {
51 | // this somehow lets the context menu behave correctly
52 | MethodInfo mi = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic);
53 | mi.Invoke(NotifyIcon, null);
54 | ContextMenu.Show(Cursor.Position, ToolStripDropDownDirection.AboveRight);
55 | }
56 |
57 | private void onHotKeyPressed(GlobalHotKey _) => selectWindowFromScreen();
58 |
59 | private void selectWindowFromScreen()
60 | {
61 | if (notify)
62 | {
63 | NotifyIcon.BalloonTipText = "Select a window from screen to pin it on top. Press 'Esc' to exit.";
64 | NotifyIcon.ShowBalloonTip(1);
65 | notify = false;
66 | }
67 | var overlay = new OverlayForm();
68 | overlay.TopMost = true;
69 | if (overlay.ShowDialog() == DialogResult.OK)
70 | {
71 | WinApi.SetWindowTopmost(overlay.SelectionHandle, true);
72 | }
73 | }
74 |
75 | private void ContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
76 | {
77 | ContextMenu.Items.Clear();
78 |
79 | var windowsItems = new List();
80 | foreach (var kv in WinApi.GetWindowHandles())
81 | {
82 | bool topmost = WinApi.GetWindowTopmost(kv.Key);
83 | string truncated = kv.Value.Substring(0, Math.Min(kv.Value.Length, Settings.Default.TitleLengthLimit));
84 | windowsItems.Add(new ToolStripMenuItem(truncated, null,
85 | (o, args) => WinApi.SetWindowTopmost(kv.Key, !topmost))
86 | {
87 | Checked = topmost,
88 | ToolTipText = kv.Value
89 | });
90 | };
91 |
92 | var generalItems = new List()
93 | {
94 | new ToolStripMenuItem("Select Window From Screen", Resources.TargetIcon, onSelectWindowClicked)
95 | { ShortcutKeyDisplayString = HotKey?.KeyCombination.ToString() },
96 | new ToolStripMenuItem("Unpin All Windows", Resources.DeleteIcon, onUnpinAllClicked),
97 | new ToolStripMenuItem("Options", Resources.OptionsIcon, onOptionsClicked),
98 | new ToolStripMenuItem("About", Resources.AboutIcon, onAboutClicked),
99 | new ToolStripMenuItem("Exit", null, onExitClicked),
100 | };
101 |
102 | if (Settings.Default.WindowsListAtEnd)
103 | {
104 | ContextMenu.Items.AddRange(generalItems.ToArray());
105 | ContextMenu.Items.Add(new ToolStripSeparator());
106 | ContextMenu.Items.AddRange(windowsItems.ToArray());
107 | }
108 | else
109 | {
110 | ContextMenu.Items.AddRange(windowsItems.ToArray());
111 | ContextMenu.Items.Add(new ToolStripSeparator());
112 | ContextMenu.Items.AddRange(generalItems.ToArray());
113 | }
114 |
115 | e.Cancel = false;
116 | }
117 |
118 | private void onSelectWindowClicked(object sender, EventArgs e) => selectWindowFromScreen();
119 |
120 | private void onUnpinAllClicked(object sender, EventArgs e)
121 | {
122 | foreach (var kv in WinApi.GetWindowHandles())
123 | {
124 | WinApi.SetWindowTopmost(kv.Key, false);
125 | }
126 | }
127 |
128 | private void onOptionsClicked(object sender, EventArgs e)
129 | {
130 | var optionsForm = new OptionsForm(this);
131 | optionsForm.ShowDialog();
132 | }
133 |
134 | private void onAboutClicked(object sender, EventArgs e)
135 | {
136 | var aboutForm = new AboutForm(Resources.PinWinIconBlack.ToBitmap());
137 | aboutForm.AccentColor = Color.Black;
138 | aboutForm.UpdateChecker = updateChecker;
139 | aboutForm.StartPosition = FormStartPosition.CenterScreen;
140 | aboutForm.ShowDialog();
141 | }
142 |
143 | private void onExitClicked(object sender, EventArgs e)
144 | {
145 | Application.Exit();
146 | }
147 |
148 | private void Application_ApplicationExit(object sender, EventArgs e)
149 | {
150 | if (HotKey != null)
151 | {
152 | KeysConverter keyConv = new KeysConverter();
153 | Settings.Default.HotKey = keyConv.ConvertToInvariantString((Keys)HotKey?.KeyCombination);
154 | }
155 | else Settings.Default.HotKey = null;
156 | Settings.Default.Save();
157 | HotKey?.Dispose();
158 | }
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/Setup/PinWin.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
47 |
48 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | 1
89 |
90 | 1
91 |
92 | 1
93 |
94 |
95 | 1
96 |
97 | 1
98 |
99 | 1
100 | 1
101 | 1
102 |
103 | 1
104 |
105 | WixUI_InstallMode = "Repair" OR WixUI_InstallMode = "Remove"
106 | 1
107 |
108 |
109 |
110 | 1
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | NOT Installed
123 |
124 |
125 |
--------------------------------------------------------------------------------
/PinWin/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\iconfinder_14-Question_2123865.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\Resources\iconfinder_17-Denied_2123868.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\Resources\iconfinder_38-Option_2123921.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
129 |
130 |
131 | ..\Resources\pinwin.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\Resources\pinwinwhite.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
135 |
136 |
137 | ..\Resources\iconfinder_30-Target_2123952.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
--------------------------------------------------------------------------------
/PinWin/OptionsForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace PinWin
2 | {
3 | partial class OptionsForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(OptionsForm));
32 | this.butCancel = new System.Windows.Forms.Button();
33 | this.butSubmit = new System.Windows.Forms.Button();
34 | this.groupBox1 = new System.Windows.Forms.GroupBox();
35 | this.panHotKey = new System.Windows.Forms.Panel();
36 | this.butHotKey = new System.Windows.Forms.Button();
37 | this.txtHotKey = new System.Windows.Forms.TextBox();
38 | this.chkHotKey = new System.Windows.Forms.CheckBox();
39 | this.numLimit = new System.Windows.Forms.NumericUpDown();
40 | this.chkWindowsAtEnd = new System.Windows.Forms.CheckBox();
41 | this.chkTruncateTitle = new System.Windows.Forms.CheckBox();
42 | this.groupBox2 = new System.Windows.Forms.GroupBox();
43 | this.chkUpdates = new System.Windows.Forms.CheckBox();
44 | this.groupBox1.SuspendLayout();
45 | this.panHotKey.SuspendLayout();
46 | ((System.ComponentModel.ISupportInitialize)(this.numLimit)).BeginInit();
47 | this.groupBox2.SuspendLayout();
48 | this.SuspendLayout();
49 | //
50 | // butCancel
51 | //
52 | this.butCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
53 | this.butCancel.Location = new System.Drawing.Point(287, 202);
54 | this.butCancel.Name = "butCancel";
55 | this.butCancel.Size = new System.Drawing.Size(85, 25);
56 | this.butCancel.TabIndex = 2;
57 | this.butCancel.Text = "Cancel";
58 | this.butCancel.UseVisualStyleBackColor = true;
59 | //
60 | // butSubmit
61 | //
62 | this.butSubmit.Location = new System.Drawing.Point(196, 202);
63 | this.butSubmit.Name = "butSubmit";
64 | this.butSubmit.Size = new System.Drawing.Size(85, 25);
65 | this.butSubmit.TabIndex = 1;
66 | this.butSubmit.Text = "OK";
67 | this.butSubmit.UseVisualStyleBackColor = true;
68 | this.butSubmit.Click += new System.EventHandler(this.butSubmit_Click);
69 | //
70 | // groupBox1
71 | //
72 | this.groupBox1.Controls.Add(this.panHotKey);
73 | this.groupBox1.Controls.Add(this.chkHotKey);
74 | this.groupBox1.Controls.Add(this.numLimit);
75 | this.groupBox1.Controls.Add(this.chkWindowsAtEnd);
76 | this.groupBox1.Controls.Add(this.chkTruncateTitle);
77 | this.groupBox1.Location = new System.Drawing.Point(12, 12);
78 | this.groupBox1.Name = "groupBox1";
79 | this.groupBox1.Size = new System.Drawing.Size(360, 109);
80 | this.groupBox1.TabIndex = 3;
81 | this.groupBox1.TabStop = false;
82 | this.groupBox1.Text = "General";
83 | //
84 | // panHotKey
85 | //
86 | this.panHotKey.Controls.Add(this.butHotKey);
87 | this.panHotKey.Controls.Add(this.txtHotKey);
88 | this.panHotKey.Location = new System.Drawing.Point(151, 45);
89 | this.panHotKey.Name = "panHotKey";
90 | this.panHotKey.Size = new System.Drawing.Size(203, 25);
91 | this.panHotKey.TabIndex = 5;
92 | //
93 | // butHotKey
94 | //
95 | this.butHotKey.Location = new System.Drawing.Point(128, 1);
96 | this.butHotKey.Name = "butHotKey";
97 | this.butHotKey.Size = new System.Drawing.Size(75, 23);
98 | this.butHotKey.TabIndex = 4;
99 | this.butHotKey.Text = "Change";
100 | this.butHotKey.UseVisualStyleBackColor = true;
101 | this.butHotKey.Click += new System.EventHandler(this.butHotKey_Click);
102 | //
103 | // txtHotKey
104 | //
105 | this.txtHotKey.Location = new System.Drawing.Point(0, 3);
106 | this.txtHotKey.Name = "txtHotKey";
107 | this.txtHotKey.ReadOnly = true;
108 | this.txtHotKey.Size = new System.Drawing.Size(122, 20);
109 | this.txtHotKey.TabIndex = 2;
110 | //
111 | // chkHotKey
112 | //
113 | this.chkHotKey.AutoSize = true;
114 | this.chkHotKey.Location = new System.Drawing.Point(6, 50);
115 | this.chkHotKey.Name = "chkHotKey";
116 | this.chkHotKey.Size = new System.Drawing.Size(123, 17);
117 | this.chkHotKey.TabIndex = 3;
118 | this.chkHotKey.Text = "Use a global hot key";
119 | this.chkHotKey.UseVisualStyleBackColor = true;
120 | this.chkHotKey.CheckedChanged += new System.EventHandler(this.chkHotKey_CheckedChanged);
121 | //
122 | // numLimit
123 | //
124 | this.numLimit.Location = new System.Drawing.Point(151, 19);
125 | this.numLimit.Maximum = new decimal(new int[] {
126 | 200,
127 | 0,
128 | 0,
129 | 0});
130 | this.numLimit.Minimum = new decimal(new int[] {
131 | 10,
132 | 0,
133 | 0,
134 | 0});
135 | this.numLimit.Name = "numLimit";
136 | this.numLimit.Size = new System.Drawing.Size(90, 20);
137 | this.numLimit.TabIndex = 1;
138 | this.numLimit.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
139 | this.numLimit.Value = new decimal(new int[] {
140 | 50,
141 | 0,
142 | 0,
143 | 0});
144 | //
145 | // chkWindowsAtEnd
146 | //
147 | this.chkWindowsAtEnd.AutoSize = true;
148 | this.chkWindowsAtEnd.Location = new System.Drawing.Point(6, 80);
149 | this.chkWindowsAtEnd.Name = "chkWindowsAtEnd";
150 | this.chkWindowsAtEnd.Size = new System.Drawing.Size(163, 17);
151 | this.chkWindowsAtEnd.TabIndex = 0;
152 | this.chkWindowsAtEnd.Text = "Show windows list at the end";
153 | this.chkWindowsAtEnd.UseVisualStyleBackColor = true;
154 | this.chkWindowsAtEnd.CheckedChanged += new System.EventHandler(this.chkTruncateTitle_CheckedChanged);
155 | //
156 | // chkTruncateTitle
157 | //
158 | this.chkTruncateTitle.AutoSize = true;
159 | this.chkTruncateTitle.Location = new System.Drawing.Point(6, 20);
160 | this.chkTruncateTitle.Name = "chkTruncateTitle";
161 | this.chkTruncateTitle.Size = new System.Drawing.Size(132, 17);
162 | this.chkTruncateTitle.TabIndex = 0;
163 | this.chkTruncateTitle.Text = "Truncate window titles";
164 | this.chkTruncateTitle.UseVisualStyleBackColor = true;
165 | this.chkTruncateTitle.CheckedChanged += new System.EventHandler(this.chkTruncateTitle_CheckedChanged);
166 | //
167 | // groupBox2
168 | //
169 | this.groupBox2.Controls.Add(this.chkUpdates);
170 | this.groupBox2.Location = new System.Drawing.Point(12, 126);
171 | this.groupBox2.Name = "groupBox2";
172 | this.groupBox2.Size = new System.Drawing.Size(360, 70);
173 | this.groupBox2.TabIndex = 4;
174 | this.groupBox2.TabStop = false;
175 | this.groupBox2.Text = "Application";
176 | //
177 | // chkUpdates
178 | //
179 | this.chkUpdates.AutoSize = true;
180 | this.chkUpdates.Location = new System.Drawing.Point(6, 19);
181 | this.chkUpdates.Name = "chkUpdates";
182 | this.chkUpdates.Size = new System.Drawing.Size(195, 17);
183 | this.chkUpdates.TabIndex = 1;
184 | this.chkUpdates.Text = "Always check for updates at startup";
185 | this.chkUpdates.UseVisualStyleBackColor = true;
186 | //
187 | // OptionsForm
188 | //
189 | this.AcceptButton = this.butSubmit;
190 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
191 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
192 | this.CancelButton = this.butCancel;
193 | this.ClientSize = new System.Drawing.Size(384, 239);
194 | this.Controls.Add(this.groupBox2);
195 | this.Controls.Add(this.groupBox1);
196 | this.Controls.Add(this.butSubmit);
197 | this.Controls.Add(this.butCancel);
198 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
199 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
200 | this.MaximizeBox = false;
201 | this.MinimizeBox = false;
202 | this.Name = "OptionsForm";
203 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
204 | this.Text = "PinWin - Options";
205 | this.TopMost = true;
206 | this.groupBox1.ResumeLayout(false);
207 | this.groupBox1.PerformLayout();
208 | this.panHotKey.ResumeLayout(false);
209 | this.panHotKey.PerformLayout();
210 | ((System.ComponentModel.ISupportInitialize)(this.numLimit)).EndInit();
211 | this.groupBox2.ResumeLayout(false);
212 | this.groupBox2.PerformLayout();
213 | this.ResumeLayout(false);
214 |
215 | }
216 |
217 | #endregion
218 | private System.Windows.Forms.Button butCancel;
219 | private System.Windows.Forms.Button butSubmit;
220 | private System.Windows.Forms.GroupBox groupBox1;
221 | private System.Windows.Forms.GroupBox groupBox2;
222 | private System.Windows.Forms.CheckBox chkTruncateTitle;
223 | private System.Windows.Forms.Panel panHotKey;
224 | private System.Windows.Forms.Button butHotKey;
225 | private System.Windows.Forms.TextBox txtHotKey;
226 | private System.Windows.Forms.CheckBox chkHotKey;
227 | private System.Windows.Forms.NumericUpDown numLimit;
228 | private System.Windows.Forms.CheckBox chkUpdates;
229 | private System.Windows.Forms.CheckBox chkWindowsAtEnd;
230 | }
231 | }
--------------------------------------------------------------------------------