diff --git a/src/App.config b/src/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/src/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/MainForm.Designer.cs b/src/MainForm.Designer.cs new file mode 100755 index 0000000..65ec75a --- /dev/null +++ b/src/MainForm.Designer.cs @@ -0,0 +1,137 @@ +namespace WindowsPinner +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btnRefresh = new System.Windows.Forms.Button(); + this.fakePictureBox = new System.Windows.Forms.PictureBox(); + this.image = new System.Windows.Forms.PictureBox(); + this.lstWindows = new System.Windows.Forms.ComboBox(); + this.SetTopMost = new System.Windows.Forms.Button(); + this.SetNoTopMost = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.fakePictureBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.image)).BeginInit(); + this.SuspendLayout(); + // + // btnRefresh + // + this.btnRefresh.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.btnRefresh.Location = new System.Drawing.Point(498, 83); + this.btnRefresh.Name = "btnRefresh"; + this.btnRefresh.Size = new System.Drawing.Size(75, 23); + this.btnRefresh.TabIndex = 15; + this.btnRefresh.Text = "Refresh"; + this.btnRefresh.UseVisualStyleBackColor = true; + this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click); + // + // fakePictureBox + // + this.fakePictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.fakePictureBox.BackColor = System.Drawing.SystemColors.ButtonFace; + this.fakePictureBox.Location = new System.Drawing.Point(228, 112); + this.fakePictureBox.Name = "fakePictureBox"; + this.fakePictureBox.Size = new System.Drawing.Size(345, 205); + this.fakePictureBox.TabIndex = 13; + this.fakePictureBox.TabStop = false; + // + // image + // + this.image.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.image.BackColor = System.Drawing.Color.White; + this.image.Location = new System.Drawing.Point(228, 112); + this.image.Name = "image"; + this.image.Size = new System.Drawing.Size(345, 205); + this.image.TabIndex = 14; + this.image.TabStop = false; + // + // lstWindows + // + this.lstWindows.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.lstWindows.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.lstWindows.FormattingEnabled = true; + this.lstWindows.Location = new System.Drawing.Point(228, 85); + this.lstWindows.Name = "lstWindows"; + this.lstWindows.Size = new System.Drawing.Size(260, 21); + this.lstWindows.TabIndex = 12; + this.lstWindows.SelectedIndexChanged += new System.EventHandler(this.lstWindows_SelectedIndexChanged); + // + // SetTopMost + // + this.SetTopMost.Location = new System.Drawing.Point(579, 112); + this.SetTopMost.Name = "SetTopMost"; + this.SetTopMost.Size = new System.Drawing.Size(83, 36); + this.SetTopMost.TabIndex = 16; + this.SetTopMost.Text = "Set\r\nTopMost"; + this.SetTopMost.UseVisualStyleBackColor = true; + this.SetTopMost.Click += new System.EventHandler(this.SetTopMost_Click); + // + // SetNoTopMost + // + this.SetNoTopMost.Location = new System.Drawing.Point(579, 154); + this.SetNoTopMost.Name = "SetNoTopMost"; + this.SetNoTopMost.Size = new System.Drawing.Size(83, 36); + this.SetNoTopMost.TabIndex = 17; + this.SetNoTopMost.Text = "Set\r\nNo-TopMost"; + this.SetNoTopMost.UseVisualStyleBackColor = true; + this.SetNoTopMost.Click += new System.EventHandler(this.SetNoTopMost_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.SetNoTopMost); + this.Controls.Add(this.SetTopMost); + this.Controls.Add(this.btnRefresh); + this.Controls.Add(this.image); + this.Controls.Add(this.fakePictureBox); + this.Controls.Add(this.lstWindows); + this.Name = "MainForm"; + this.Text = "WindowsPinner"; + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.fakePictureBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.image)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button btnRefresh; + private System.Windows.Forms.PictureBox fakePictureBox; + private System.Windows.Forms.PictureBox image; + private System.Windows.Forms.ComboBox lstWindows; + private System.Windows.Forms.Button SetTopMost; + private System.Windows.Forms.Button SetNoTopMost; + } +} + diff --git a/src/MainForm.cs b/src/MainForm.cs new file mode 100755 index 0000000..01636b3 --- /dev/null +++ b/src/MainForm.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WindowsPinner +{ + public partial class MainForm : Form + { + //constants + byte opacity = 255; //0-255 + + + [StructLayout(LayoutKind.Sequential)] + internal struct PSIZE + { + public int x; + public int y; + } + + [DllImport("dwmapi.dll")] + static extern int DwmRegisterThumbnail(IntPtr dest, IntPtr src, out IntPtr thumb); + + [DllImport("dwmapi.dll")] + static extern int DwmUnregisterThumbnail(IntPtr thumb); + + [DllImport("dwmapi.dll")] + static extern int DwmQueryThumbnailSourceSize(IntPtr thumb, out PSIZE size); + + [StructLayout(LayoutKind.Sequential)] + internal struct DWM_THUMBNAIL_PROPERTIES + { + public int dwFlags; + public Rect rcDestination; + public Rect rcSource; + public byte opacity; + public bool fVisible; + public bool fSourceClientAreaOnly; + } + + [DllImport("dwmapi.dll")] + static extern int DwmUpdateThumbnailProperties(IntPtr hThumb, ref DWM_THUMBNAIL_PROPERTIES props); + + [StructLayout(LayoutKind.Sequential)] + internal struct Rect + { + internal Rect(int left, int top, int right, int bottom) + { + Left = left; + Top = top; + Right = right; + Bottom = bottom; + } + + public int Left; + public int Top; + public int Right; + public int Bottom; + } + + private List windows; + + private void GetWindows() + { + windows = new List(); + + EnumWindows(Callback, 0); + + lstWindows.Items.Clear(); + foreach (Window w in windows) + lstWindows.Items.Add(w); + } + + private bool Callback(IntPtr hwnd, int lParam) + { + if (this.Handle != hwnd && (GetWindowLongA(hwnd, GWL_STYLE) & TARGETWINDOW) == TARGETWINDOW) + { + StringBuilder sb = new StringBuilder(200); + GetWindowText(hwnd, sb, sb.Capacity); + Window t = new Window(); + t.Handle = hwnd; + t.Title = sb.ToString(); + windows.Add(t); + } + + return true; //continue enumeration + } + + delegate bool EnumWindowsCallback(IntPtr hwnd, int lParam); + + [DllImport("user32.dll")] + static extern int EnumWindows(EnumWindowsCallback lpEnumFunc, int lParam); + + [DllImport("user32.dll")] + public static extern void GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); + + [DllImport("user32.dll")] + static extern ulong GetWindowLongA(IntPtr hWnd, int nIndex); + + static readonly int GWL_STYLE = -16; + + static readonly ulong WS_VISIBLE = 0x10000000L; + static readonly ulong WS_BORDER = 0x00800000L; + static readonly ulong TARGETWINDOW = WS_BORDER | WS_VISIBLE; + + internal class Window + { + public string Title; + public IntPtr Handle; + + public override string ToString() + { + return Title; + } + } + + private IntPtr thumb; + private void btnRefresh_Click(object sender, EventArgs e) + { + if (thumb != IntPtr.Zero) + DwmUnregisterThumbnail(thumb); + + GetWindows(); + } + + private void lstWindows_SelectedIndexChanged(object sender, EventArgs e) + { + if (lstWindows.SelectedIndex > -1) + { + + Window w = (Window)lstWindows.SelectedItem; + if (thumb != IntPtr.Zero) + DwmUnregisterThumbnail(thumb); + + int i = DwmRegisterThumbnail(this.Handle, w.Handle, out thumb); + if (i == 0) + UpdateThumb(); + + CurrentWindow = w; + } + } + + static readonly int DWM_TNP_VISIBLE = 0x8; + static readonly int DWM_TNP_OPACITY = 0x4; + static readonly int DWM_TNP_RECTDESTINATION = 0x1; + + private void UpdateThumb() + { + if (thumb != IntPtr.Zero) + { + PSIZE size; + DwmQueryThumbnailSourceSize(thumb, out size); + + DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES(); + props.dwFlags = DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_OPACITY; + + props.fVisible = true; + props.opacity = (byte)opacity; //opacity.Value; + + props.rcDestination = new Rect(image.Left, image.Top, image.Right, image.Bottom); + if (size.x < image.Width) + props.rcDestination.Right = props.rcDestination.Left + size.x; + if (size.y < image.Height) + props.rcDestination.Bottom = props.rcDestination.Top + size.y; + + DwmUpdateThumbnailProperties(thumb, ref props); + } + } + + + [DllImport("user32.dll")] + static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + + // A Win32 constant + const int WM_SETTEXT = 0x000C; + const int WM_KEYDOWN = 0x0100; + const int VK_RETURN = 0x0D; + + // An overload of the SendMessage function, this time taking in a string as the lParam. + [DllImport("User32.dll")] + public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, string lParam); + [DllImport("User32.Dll")] + public static extern Int32 PostMessage(int hWnd, int msg, int wParam, int lParam); + + [DllImport("user32.dll")] + static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); + const int SW_MAXIMIZE = 3; + const int SW_SHOW = 5; + const int SW_HIDE = 0; + const int SW_SHOWNORMAL = 1; + const int SW_RESTORE = 9; + + [DllImport("user32.dll", EntryPoint = "SetWindowPos")] + public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags); + const int HWND_BOTTOM = 1; + const int HWND_NOTOPMOST = -2; + const int HWND_TOP = 0; + const int HWND_TOPMOST = -1; + + const int SWP_ASYNCWINDOWPOS = 0x4000; + const int SWP_DEFERERASE = 0x2000; + const int SWP_DRAWFRAME = 0x0020; + const int SWP_FRAMECHANGED = 0x0020; + const int SWP_HIDEWINDOW = 0x0080; + const int SWP_NOACTIVATE = 0x0010; + const int SWP_NOCOPYBITS = 0x0100; + const int SWP_NOMOVE = 0x0002; + const int SWP_NOOWNERZORDER = 0x0200; + const int SWP_NOREDRAW = 0x0008; + const int SWP_NOREPOSITION = 0x0200; + const int SWP_NOSENDCHANGING = 0x0400; + const int SWP_NOSIZE = 0x0001; + const int SWP_NOZORDER = 0x0004; + const int SWP_SHOWWINDOW = 0x0040; + + [DllImport("user32.dll")] + static extern bool SetCursorPos(int X, int Y); + + [DllImport("user32.dll")] + private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); + + public MainForm() + { + InitializeComponent(); + } + + private void SetTopMost_Click(object sender, EventArgs e) + { + setTopMost(CurrentWindow.Handle); + setTopMost(this.Handle); + } + + private void SetNoTopMost_Click(object sender, EventArgs e) + { + setNoTopMost(CurrentWindow.Handle); + } + + + Window CurrentWindow; + private void MainForm_Load(object sender, EventArgs e) + { + setTopMost(this.Handle); + + GetWindows(); + } + + public void setTopMost(IntPtr hWnd) + { + SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + + } + + public void setNoTopMost(IntPtr hWnd) + { + SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + } + } +} diff --git a/src/MainForm.resx b/src/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/src/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Program.cs b/src/Program.cs new file mode 100755 index 0000000..410120c --- /dev/null +++ b/src/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WindowsPinner +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + } +} diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..43f7038 --- /dev/null +++ b/src/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WindowsPinner")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WindowsPinner")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("baef5074-7c46-4f2c-8437-bc70ffc10955")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Properties/Resources.Designer.cs b/src/Properties/Resources.Designer.cs new file mode 100755 index 0000000..49b5e62 --- /dev/null +++ b/src/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsPinner.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsPinner.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/src/Properties/Resources.resx b/src/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/src/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Properties/Settings.Designer.cs b/src/Properties/Settings.Designer.cs new file mode 100755 index 0000000..e48303b --- /dev/null +++ b/src/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsPinner.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/src/Properties/Settings.settings b/src/Properties/Settings.settings new file mode 100755 index 0000000..abf36c5 --- /dev/null +++ b/src/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/WindowsPinner.csproj b/src/WindowsPinner.csproj new file mode 100755 index 0000000..7c9ad2f --- /dev/null +++ b/src/WindowsPinner.csproj @@ -0,0 +1,83 @@ + + + + + Debug + AnyCPU + {BAEF5074-7C46-4F2C-8437-BC70FFC10955} + WinExe + WindowsPinner + WindowsPinner + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + \ No newline at end of file diff --git a/src/WindowsPinner.sln b/src/WindowsPinner.sln new file mode 100755 index 0000000..540d78f --- /dev/null +++ b/src/WindowsPinner.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.87 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsPinner", "WindowsPinner.csproj", "{BAEF5074-7C46-4F2C-8437-BC70FFC10955}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BAEF5074-7C46-4F2C-8437-BC70FFC10955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAEF5074-7C46-4F2C-8437-BC70FFC10955}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAEF5074-7C46-4F2C-8437-BC70FFC10955}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAEF5074-7C46-4F2C-8437-BC70FFC10955}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {46771FC0-5131-4546-A572-94384ED71B4A} + EndGlobalSection +EndGlobal