Working shell hook (via window) to receive active window handle.

This commit is contained in:
Lorenz Cuno Klopfenstein 2010-06-30 04:57:16 +02:00
parent 12b80982fd
commit 86cf05ae3d
6 changed files with 188 additions and 22 deletions

View file

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using System.Windows.Forms;
namespace OnTopReplica {
class DualModeManager : IDisposable {
public DualModeManager(MainForm form) {
_form = form;
}
MainForm _form;
bool _active = false;
static uint _hookMsgId = NativeHooks.RegisterWindowMessage("SHELLHOOK");
public void EnableDualMode(IEnumerable<WindowHandle> handles) {
if (!NativeHooks.RegisterShellHookWindow(_form.Handle)) {
Console.WriteLine("Failed to register shell hook window.");
return;
}
_active = true;
}
public void ProcessHookMessages(Message msg) {
if (msg.Msg == _hookMsgId) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == NativeHooks.HSHELL_WINDOWACTIVATED ||
hookCode == NativeHooks.HSHELL_RUDEAPPACTIVATED) {
IntPtr activeHandle = msg.LParam;
}
}
}
public void Disable() {
if (!_active)
return;
if (!NativeHooks.DeregisterShellHookWindow(_form.Handle))
Console.WriteLine("Failed to deregister shell hook window.");
_active = false;
}
#region IDisposable Members
public void Dispose() {
Disable();
}
#endregion
}
}

View file

@ -34,6 +34,7 @@
this.switchToWindowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.selectRegionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.forwardClicksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.dualWindowModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuContextOpacity = new System.Windows.Forms.ToolStripMenuItem();
this.menuOpacity = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
@ -79,6 +80,7 @@
this.switchToWindowToolStripMenuItem,
this.selectRegionToolStripMenuItem,
this.forwardClicksToolStripMenuItem,
this.dualWindowModeToolStripMenuItem,
this.menuContextOpacity,
this.resizeToolStripMenuItem,
this.dockToolStripMenuItem,
@ -89,7 +91,7 @@
this.aboutToolStripMenuItem,
this.menuContextClose});
this.menuContext.Name = "menuContext";
this.menuContext.Size = new System.Drawing.Size(169, 296);
this.menuContext.Size = new System.Drawing.Size(178, 318);
this.menuContext.Opening += new System.ComponentModel.CancelEventHandler(this.Menu_opening);
//
// menuContextWindows
@ -97,7 +99,7 @@
this.menuContextWindows.DropDown = this.menuWindows;
this.menuContextWindows.Image = global::OnTopReplica.Properties.Resources.window_multiple16;
this.menuContextWindows.Name = "menuContextWindows";
this.menuContextWindows.Size = new System.Drawing.Size(168, 22);
this.menuContextWindows.Size = new System.Drawing.Size(177, 22);
this.menuContextWindows.Text = global::OnTopReplica.Strings.MenuWindows;
this.menuContextWindows.ToolTipText = global::OnTopReplica.Strings.MenuWindowsTT;
this.menuContextWindows.DropDownOpening += new System.EventHandler(this.Menu_Windows_opening);
@ -120,7 +122,7 @@
//
this.switchToWindowToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.window_switch;
this.switchToWindowToolStripMenuItem.Name = "switchToWindowToolStripMenuItem";
this.switchToWindowToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.switchToWindowToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.switchToWindowToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuSwitch;
this.switchToWindowToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuSwitchTT;
this.switchToWindowToolStripMenuItem.Click += new System.EventHandler(this.Menu_Switch_click);
@ -130,7 +132,7 @@
this.selectRegionToolStripMenuItem.Enabled = false;
this.selectRegionToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.regions;
this.selectRegionToolStripMenuItem.Name = "selectRegionToolStripMenuItem";
this.selectRegionToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.selectRegionToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.selectRegionToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuRegion;
this.selectRegionToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuRegionTT;
this.selectRegionToolStripMenuItem.Click += new System.EventHandler(this.Menu_Region_click);
@ -138,17 +140,25 @@
// forwardClicksToolStripMenuItem
//
this.forwardClicksToolStripMenuItem.Name = "forwardClicksToolStripMenuItem";
this.forwardClicksToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.forwardClicksToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.forwardClicksToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuClickForwarding;
this.forwardClicksToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuClickForwardingTT;
this.forwardClicksToolStripMenuItem.Click += new System.EventHandler(this.Menu_Forward_click);
//
// dualWindowModeToolStripMenuItem
//
this.dualWindowModeToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.window_multiple16;
this.dualWindowModeToolStripMenuItem.Name = "dualWindowModeToolStripMenuItem";
this.dualWindowModeToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.dualWindowModeToolStripMenuItem.Text = "Dual window mode";
this.dualWindowModeToolStripMenuItem.Click += new System.EventHandler(this.Menu_Dual_click);
//
// menuContextOpacity
//
this.menuContextOpacity.DropDown = this.menuOpacity;
this.menuContextOpacity.Image = global::OnTopReplica.Properties.Resources.window_opacity16;
this.menuContextOpacity.Name = "menuContextOpacity";
this.menuContextOpacity.Size = new System.Drawing.Size(168, 22);
this.menuContextOpacity.Size = new System.Drawing.Size(177, 22);
this.menuContextOpacity.Text = global::OnTopReplica.Strings.MenuOpacity;
//
// menuOpacity
@ -159,10 +169,9 @@
this.toolStripMenuItem3,
this.toolStripMenuItem4});
this.menuOpacity.Name = "menuOpacity";
this.menuOpacity.OwnerItem = this.menuContextOpacity;
this.menuOpacity.ShowCheckMargin = true;
this.menuOpacity.ShowImageMargin = false;
this.menuOpacity.Size = new System.Drawing.Size(154, 114);
this.menuOpacity.Size = new System.Drawing.Size(154, 92);
this.menuOpacity.Opening += new System.ComponentModel.CancelEventHandler(this.Menu_Opacity_opening);
//
// toolStripMenuItem1
@ -208,7 +217,7 @@
this.resizeToolStripMenuItem.DropDown = this.menuResize;
this.resizeToolStripMenuItem.Enabled = false;
this.resizeToolStripMenuItem.Name = "resizeToolStripMenuItem";
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.resizeToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuResize;
//
// menuResize
@ -274,7 +283,7 @@
this.bottomRightToolStripMenuItem});
this.dockToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.pos_null;
this.dockToolStripMenuItem.Name = "dockToolStripMenuItem";
this.dockToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.dockToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.dockToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuPosition;
this.dockToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuPositionTT;
//
@ -313,7 +322,7 @@
// chromeToolStripMenuItem
//
this.chromeToolStripMenuItem.Name = "chromeToolStripMenuItem";
this.chromeToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.chromeToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.chromeToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuChrome;
this.chromeToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuChromeTT;
this.chromeToolStripMenuItem.Click += new System.EventHandler(this.Menu_Chrome_click);
@ -322,7 +331,7 @@
//
this.reduceToIconToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.reduce;
this.reduceToIconToolStripMenuItem.Name = "reduceToIconToolStripMenuItem";
this.reduceToIconToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.reduceToIconToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.reduceToIconToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuReduce;
this.reduceToIconToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuReduceTT;
this.reduceToIconToolStripMenuItem.Click += new System.EventHandler(this.Menu_Reduce_click);
@ -330,13 +339,13 @@
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(165, 6);
this.toolStripSeparator1.Size = new System.Drawing.Size(174, 6);
//
// languageToolStripMenuItem
//
this.languageToolStripMenuItem.DropDown = this.menuLanguages;
this.languageToolStripMenuItem.Name = "languageToolStripMenuItem";
this.languageToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.languageToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.languageToolStripMenuItem.Text = global::OnTopReplica.Strings.Language;
//
// menuLanguages
@ -390,7 +399,7 @@
// aboutToolStripMenuItem
//
this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.aboutToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuAbout;
this.aboutToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuAboutTT;
this.aboutToolStripMenuItem.Click += new System.EventHandler(this.Menu_About_click);
@ -399,7 +408,7 @@
//
this.menuContextClose.Image = global::OnTopReplica.Properties.Resources.close_new;
this.menuContextClose.Name = "menuContextClose";
this.menuContextClose.Size = new System.Drawing.Size(168, 22);
this.menuContextClose.Size = new System.Drawing.Size(177, 22);
this.menuContextClose.Text = global::OnTopReplica.Strings.MenuClose;
this.menuContextClose.Click += new System.EventHandler(this.Menu_Close_click);
//
@ -473,6 +482,7 @@
private System.Windows.Forms.ToolStripMenuItem danskToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem chromeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem danskToolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem dualWindowModeToolStripMenuItem;
}
}

View file

@ -19,6 +19,8 @@ namespace OnTopReplica {
WindowManager _windowManager = new WindowManager();
WindowHandle _lastWindowHandle = null;
DualModeManager _dualModeManager;
public MainForm() {
InitializeComponent();
KeepAspectRatio = false;
@ -59,6 +61,8 @@ namespace OnTopReplica {
_hotKeyManager = new HotKeyManager(this);
_hotKeyManager.RegisterHotKey(HotKeyManager.HotKeyModifiers.Control | HotKeyManager.HotKeyModifiers.Shift,
Keys.O, new HotKeyManager.HotKeyHandler(HotKeyOpenHandler));
_dualModeManager = new DualModeManager(this);
}
#region Child forms & controls events
@ -170,6 +174,10 @@ namespace OnTopReplica {
_hotKeyManager.Dispose();
_hotKeyManager = null;
//Destroy dual mode manager
_dualModeManager.Dispose();
_dualModeManager = null;
base.OnClosing(e);
}
@ -201,6 +209,8 @@ namespace OnTopReplica {
protected override void WndProc(ref Message m) {
if (_hotKeyManager != null)
_hotKeyManager.ProcessHotKeys(m);
if (_dualModeManager != null)
_dualModeManager.ProcessHookMessages(m);
switch(m.Msg){
case NativeMethods.WM_NCRBUTTONUP:
@ -292,13 +302,13 @@ namespace OnTopReplica {
//Handle special "none" window
if (tsi.Tag == null) {
ThumbnailUnset();
UnsetThumbnail();
return;
}
var selectionData = (WindowListHelper.WindowSelectionData)tsi.Tag;
if (_windowManager != null) {
ThumbnailSet(selectionData.Handle, selectionData.Region);
SetThumbnail(selectionData.Handle, selectionData.Region);
}
}
@ -310,6 +320,10 @@ namespace OnTopReplica {
NativeMethods.SetForegroundWindow(_lastWindowHandle.Handle);
}
private void Menu_Dual_click(object sender, EventArgs e) {
}
private void Menu_Forward_click(object sender, EventArgs e) {
if (Settings.Default.FirstTimeClickForwarding && !_thumbnailPanel.ReportThumbnailClicks) {
TaskDialog dlg = new TaskDialog(Strings.InfoClickForwarding, Strings.InfoClickForwardingTitle, Strings.InfoClickForwardingContent) {
@ -543,7 +557,12 @@ namespace OnTopReplica {
#region Thumbnail operation
private void ThumbnailSet(WindowHandle handle, StoredRegion region) {
/// <summary>
/// Sets a new thumbnail.
/// </summary>
/// <param name="handle">Handle to the window to clone.</param>
/// <param name="region">Region of the window to clone.</param>
public void SetThumbnail(WindowHandle handle, StoredRegion region) {
try {
_lastWindowHandle = handle;
@ -563,7 +582,10 @@ namespace OnTopReplica {
SetAspectRatio(_thumbnailPanel.ThumbnailOriginalSize);
}
private void ThumbnailUnset(){
/// <summary>
/// Disables the cloned thumbnail.
/// </summary>
public void UnsetThumbnail(){
//Unset handle
_lastWindowHandle = null;
_thumbnailPanel.UnsetThumbnail();
@ -580,7 +602,7 @@ namespace OnTopReplica {
ShowErrorDialog(title, Strings.ErrorGenericThumbnailHandleError, ex.Message);
}
ThumbnailUnset();
UnsetThumbnail();
}
/// <summary>Automatically sizes the window in order to accomodate the thumbnail p times.</summary>
@ -695,7 +717,7 @@ namespace OnTopReplica {
/// </summary>
public void ResetMainForm() {
//Reset form settings
ThumbnailUnset();
UnsetThumbnail();
RegionBoxShowing = false;
//Reset location and size (edge of the screen, min size)

View file

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace OnTopReplica {
/// <summary>
/// Helpers for interop with native Windows hooks.
/// </summary>
static class NativeHooks {
public const int HSHELL_WINDOWACTIVATED = 4;
public const int HSHELL_RUDEAPPACTIVATED = HSHELL_WINDOWACTIVATED | HSHELL_HIGHBIT;
const int HSHELL_HIGHBIT = 0x8000;
/// <summary>
/// Registers the WM_ID for a window message.
/// </summary>
/// <param name="wndMessageName">Name of the window message.</param>
[DllImport("User32.dll")]
public static extern uint RegisterWindowMessage(string wndMessageName);
/// <summary>
/// Registers a window as a shell hook window.
/// </summary>
[DllImport("User32.dll")]
public static extern bool RegisterShellHookWindow(IntPtr hwnd);
/// <summary>
/// Deregisters a window as a shell hook window.
/// </summary>
[DllImport("User32.dll")]
public static extern bool DeregisterShellHookWindow(IntPtr hwnd);
}
}

View file

@ -297,5 +297,16 @@ namespace OnTopReplica
[DllImport("user32.dll")]
public static extern short GetKeyState(VirtualKeyState nVirtKey);
[DllImport("kernel32.dll")]
static extern uint FormatMessage(uint dwFlags, IntPtr lpSource,
int dwMessageId, uint dwLanguageId, [Out] StringBuilder lpBuffer,
uint nSize, IntPtr Arguments);
public static string GetLastErrorMessage(int msgCode) {
var sb = new StringBuilder(300);
FormatMessage((uint)(0x00001000), IntPtr.Zero, msgCode, 0, sb, 299, IntPtr.Zero);
return sb.ToString();
}
}
}

View file

@ -86,6 +86,28 @@
<PropertyGroup>
<ApplicationManifest>OnTopReplica.exe.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Deployment" />
@ -109,6 +131,8 @@
</Compile>
<Compile Include="CloneClickEventArgs.cs" />
<Compile Include="CloseRequestEventArgs.cs" />
<Compile Include="DualModeManager.cs" />
<Compile Include="NativeHooks.cs" />
<Compile Include="WindowsSevenMethods.cs" />
<None Include="CommonControls.cs" />
<Compile Include="EnumerationExtensions.cs" />