Files
PowerToys/src/modules/previewpane/common/controls/FormHandlerControl.cs

165 lines
5.3 KiB
C#
Raw Normal View History

2020-08-14 15:10:06 -07:00
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Drawing;
using System.Windows.Forms;
using PreviewHandlerCommon.ComInterop;
2020-08-14 15:10:06 -07:00
namespace Common
{
/// <summary>
/// Form based implementation of <see cref="IPreviewHandlerControl"/>.
/// </summary>
public abstract class FormHandlerControl : Form, IPreviewHandlerControl
{
/// <summary>
/// Needed to make the form a child window.
/// </summary>
private static int gwlStyle = -16;
private static int wsChild = 0x40000000;
/// <summary>
/// Holds the parent window handle.
/// </summary>
private IntPtr parentHwnd;
/// <summary>
/// Initializes a new instance of the <see cref="FormHandlerControl"/> class.
/// </summary>
public FormHandlerControl()
{
// Gets the handle of the control to create the control on the VI thread. Invoking the Control.Handle get accessor forces the creation of the underlying window for the control.
// This is important, because the thread that instantiates the preview handler component and calls its constructor is a single-threaded apartment (STA) thread, but the thread that calls into the interface members later on is a multithreaded apartment (MTA) thread. Windows Forms controls are meant to run on STA threads.
// More details: https://docs.microsoft.com/en-us/archive/msdn-magazine/2007/january/windows-vista-and-office-writing-your-own-preview-handlers.
var forceCreation = this.Handle;
2020-08-14 15:10:06 -07:00
this.FormBorderStyle = FormBorderStyle.None;
this.Visible = false;
}
/// <inheritdoc />
public IntPtr GetWindowHandle()
2020-08-14 15:10:06 -07:00
{
return this.Handle;
}
/// <inheritdoc />
public void QueryFocus(out IntPtr result)
{
var getResult = IntPtr.Zero;
this.InvokeOnControlThread(() =>
{
getResult = NativeMethods.GetFocus();
2020-08-14 15:10:06 -07:00
});
result = getResult;
}
/// <inheritdoc />
public void SetBackgroundColor(Color argbColor)
{
this.InvokeOnControlThread(() =>
{
this.BackColor = argbColor;
});
}
/// <inheritdoc />
public void SetFocus()
{
this.InvokeOnControlThread(() =>
{
this.Focus();
});
}
/// <inheritdoc />
public void SetFont(Font font)
{
this.InvokeOnControlThread(() =>
{
this.Font = font;
});
}
/// <inheritdoc />
public void SetRect(Rectangle windowBounds)
{
this.UpdateWindowBounds(windowBounds);
}
/// <inheritdoc />
public void SetTextColor(Color color)
{
this.InvokeOnControlThread(() =>
{
this.ForeColor = color;
});
}
/// <inheritdoc />
public void SetWindow(IntPtr hwnd, Rectangle rect)
{
this.parentHwnd = hwnd;
this.UpdateWindowBounds(rect);
}
/// <inheritdoc />
public virtual void Unload()
{
this.InvokeOnControlThread(() =>
{
this.Visible = false;
foreach (Control c in this.Controls)
{
c.Dispose();
}
this.Controls.Clear();
});
// Call garbage collection at the time of unloading of Preview.
2020-08-14 15:10:06 -07:00
// Which is preventing prevhost.exe to exit at the time of closing File explorer.
// Preview Handlers run in a separate process from PowerToys. This will not affect the performance of other modules.
[ci]Upgrade to check-spelling 0.0.20alpha7 (#19127) * spelling: added Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: and Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: another Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: color Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: file Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: github Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: not Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: occurrences Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: stamp Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: suppressions Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: the Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: up to Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: whether Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: whichdoes Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * Upgrade check-spelling to v0.0.20-alpha7 Config based on: https://github.com/check-spelling/spell-check-this/tree/a5001170a754da309ca324ce7eed8a076af2f4ac * Adding duplicate detection to patterns.txt * Adding line_forbidden.patterns * Adding reject.txt * Updated excludes (and sorted) * Switching to unified workflow * moving `wil` to allow.txt to clarify that it's a term of art (https://github.com/microsoft/wil), whereas often it's a typo for `will`. * Update src/runner/main.cpp Co-authored-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2022-07-01 10:09:41 -04:00
// Mitigate the following GitHub issue: https://github.com/microsoft/PowerToys/issues/1468
2020-08-14 15:10:06 -07:00
GC.Collect();
}
/// <inheritdoc />
public virtual void DoPreview<T>(T dataSource)
{
this.Visible = true;
}
/// <summary>
/// Executes the specified delegate on the thread that owns the control's underlying window handle.
/// </summary>
/// <param name="func">Delegate to run.</param>
public void InvokeOnControlThread(MethodInvoker func)
{
this.Invoke(func);
}
/// <summary>
/// Update the Form Control window with the passed rectangle.
/// </summary>
/// <param name="windowBounds">An instance of rectangle.</param>
private void UpdateWindowBounds(Rectangle windowBounds)
{
this.InvokeOnControlThread(() =>
{
// We must set the WS_CHILD style to change the form to a control within the Explorer preview pane
int windowStyle = NativeMethods.GetWindowLong(Handle, gwlStyle);
2020-08-14 15:10:06 -07:00
if ((windowStyle & wsChild) == 0)
{
_ = NativeMethods.SetWindowLong(Handle, gwlStyle, windowStyle | wsChild);
2020-08-14 15:10:06 -07:00
}
NativeMethods.SetParent(Handle, parentHwnd);
Bounds = windowBounds;
2020-08-14 15:10:06 -07:00
});
}
}
}