add preview handler
This commit is contained in:
parent
0f48dbe845
commit
c03de86d02
@ -18,7 +18,7 @@
|
|||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;THUMBNAIL</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE;THUMBNAIL</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
@ -46,7 +46,6 @@
|
|||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
377
ShellExtensions/Interop/Common/ShellNativeEnums.cs
Normal file
377
ShellExtensions/Interop/Common/ShellNativeEnums.cs
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ShellExtensions.Interop.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The STGM constants are flags that indicate
|
||||||
|
/// conditions for creating and deleting the object and access modes
|
||||||
|
/// for the object.
|
||||||
|
///
|
||||||
|
/// You can combine these flags, but you can only choose one flag
|
||||||
|
/// from each group of related flags. Typically one flag from each
|
||||||
|
/// of the access and sharing groups must be specified for all
|
||||||
|
/// functions and methods which use these constants.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum AccessModes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that, in direct mode, each change to a storage
|
||||||
|
/// or stream element is written as it occurs.
|
||||||
|
/// </summary>
|
||||||
|
Direct = 0x00000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that, in transacted mode, changes are buffered
|
||||||
|
/// and written only if an explicit commit operation is called.
|
||||||
|
/// </summary>
|
||||||
|
Transacted = 0x00010000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a faster implementation of a compound file
|
||||||
|
/// in a limited, but frequently used, case.
|
||||||
|
/// </summary>
|
||||||
|
Simple = 0x08000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the object is read-only,
|
||||||
|
/// meaning that modifications cannot be made.
|
||||||
|
/// </summary>
|
||||||
|
Read = 0x00000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables you to save changes to the object,
|
||||||
|
/// but does not permit access to its data.
|
||||||
|
/// </summary>
|
||||||
|
Write = 0x00000001,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables access and modification of object data.
|
||||||
|
/// </summary>
|
||||||
|
ReadWrite = 0x00000002,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies that subsequent openings of the object are
|
||||||
|
/// not denied read or write access.
|
||||||
|
/// </summary>
|
||||||
|
ShareDenyNone = 0x00000040,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prevents others from subsequently opening the object in Read mode.
|
||||||
|
/// </summary>
|
||||||
|
ShareDenyRead = 0x00000030,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prevents others from subsequently opening the object
|
||||||
|
/// for Write or ReadWrite access.
|
||||||
|
/// </summary>
|
||||||
|
ShareDenyWrite = 0x00000020,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prevents others from subsequently opening the object in any mode.
|
||||||
|
/// </summary>
|
||||||
|
ShareExclusive = 0x00000010,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the storage object with exclusive access to the most
|
||||||
|
/// recently committed version.
|
||||||
|
/// </summary>
|
||||||
|
Priority = 0x00040000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the underlying file is to be automatically destroyed when the root
|
||||||
|
/// storage object is released. This feature is most useful for creating temporary files.
|
||||||
|
/// </summary>
|
||||||
|
DeleteOnRelease = 0x04000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that, in transacted mode, a temporary scratch file is usually used
|
||||||
|
/// to save modifications until the Commit method is called.
|
||||||
|
/// Specifying NoScratch permits the unused portion of the original file
|
||||||
|
/// to be used as work space instead of creating a new file for that purpose.
|
||||||
|
/// </summary>
|
||||||
|
NoScratch = 0x00100000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that an existing storage object
|
||||||
|
/// or stream should be removed before the new object replaces it.
|
||||||
|
/// </summary>
|
||||||
|
Create = 0x00001000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the new object while preserving existing data in a stream named "Contents".
|
||||||
|
/// </summary>
|
||||||
|
Convert = 0x00020000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Causes the create operation to fail if an existing object with the specified name exists.
|
||||||
|
/// </summary>
|
||||||
|
FailIfThere = 0x00000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This flag is used when opening a storage object with Transacted
|
||||||
|
/// and without ShareExclusive or ShareDenyWrite.
|
||||||
|
/// In this case, specifying NoSnapshot prevents the system-provided
|
||||||
|
/// implementation from creating a snapshot copy of the file.
|
||||||
|
/// Instead, changes to the file are written to the end of the file.
|
||||||
|
/// </summary>
|
||||||
|
NoSnapshot = 0x00200000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Supports direct mode for single-writer, multireader file operations.
|
||||||
|
/// </summary>
|
||||||
|
DirectSingleWriterMultipleReader = 0x00400000
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PREVIEW_HANDLER
|
||||||
|
/// <summary>
|
||||||
|
/// HRESULT Wrapper
|
||||||
|
/// </summary>
|
||||||
|
public enum HResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// S_OK
|
||||||
|
/// </summary>
|
||||||
|
Ok = 0x0000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// S_FALSE
|
||||||
|
/// </summary>
|
||||||
|
False = 0x0001,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// E_INVALIDARG
|
||||||
|
/// </summary>
|
||||||
|
InvalidArguments = unchecked((int)0x80070057),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// E_OUTOFMEMORY
|
||||||
|
/// </summary>
|
||||||
|
OutOfMemory = unchecked((int)0x8007000E),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// E_NOINTERFACE
|
||||||
|
/// </summary>
|
||||||
|
NoInterface = unchecked((int)0x80004002),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// E_FAIL
|
||||||
|
/// </summary>
|
||||||
|
Fail = unchecked((int)0x80004005),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// E_ELEMENTNOTFOUND
|
||||||
|
/// </summary>
|
||||||
|
ElementNotFound = unchecked((int)0x80070490),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TYPE_E_ELEMENTNOTFOUND
|
||||||
|
/// </summary>
|
||||||
|
TypeElementNotFound = unchecked((int)0x8002802B),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NO_OBJECT
|
||||||
|
/// </summary>
|
||||||
|
NoObject = unchecked((int)0x800401E5),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Win32 Error code: ERROR_CANCELLED
|
||||||
|
/// </summary>
|
||||||
|
Win32ErrorCanceled = 1223,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ERROR_CANCELLED
|
||||||
|
/// </summary>
|
||||||
|
Canceled = unchecked((int)0x800704C7),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The requested resource is in use
|
||||||
|
/// </summary>
|
||||||
|
ResourceInUse = unchecked((int)0x800700AA),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The requested resources is read-only.
|
||||||
|
/// </summary>
|
||||||
|
AccessDenied = unchecked((int)0x80030005)
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum WindowStyles
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a thin-line border.
|
||||||
|
/// </summary>
|
||||||
|
Border = 0x00800000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a title bar (includes the WS_BORDER style).
|
||||||
|
/// </summary>
|
||||||
|
Caption = 0x00C00000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is a child window.
|
||||||
|
/// A window with this style cannot have a menu bar.
|
||||||
|
/// This style cannot be used with the WS_POPUP style.
|
||||||
|
/// </summary>
|
||||||
|
Child = 0x40000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as the WS_CHILD style.
|
||||||
|
/// </summary>
|
||||||
|
ChildWindow = 0x40000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Excludes the area occupied by child windows when drawing occurs within the parent window.
|
||||||
|
/// This style is used when creating the parent window.
|
||||||
|
/// </summary>
|
||||||
|
ClipChildren = 0x02000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clips child windows relative to each other;
|
||||||
|
/// that is, when a particular child window receives a WM_PAINT message,
|
||||||
|
/// the WS_CLIPSIBLINGS style clips all other overlapping child windows out of the region of the child window to be updated.
|
||||||
|
/// If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible,
|
||||||
|
/// when drawing within the client area of a child window, to draw within the client area of a neighboring child window.
|
||||||
|
/// </summary>
|
||||||
|
ClipSiblings = 0x04000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is initially disabled. A disabled window cannot receive input from the user.
|
||||||
|
/// To change this after a window has been created, use the EnableWindow function.
|
||||||
|
/// </summary>
|
||||||
|
Disabled = 0x08000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a border of a style typically used with dialog boxes.
|
||||||
|
/// A window with this style cannot have a title bar.
|
||||||
|
/// </summary>
|
||||||
|
DialogFrame = 0x0040000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is the first control of a group of controls.
|
||||||
|
/// The group consists of this first control and all controls defined after it, up to the next control with the WS_GROUP style.
|
||||||
|
/// The first control in each group usually has the WS_TABSTOP style so that the user can move from group to group.
|
||||||
|
/// The user can subsequently change the keyboard focus from one control in the group to the next control
|
||||||
|
/// in the group by using the direction keys.
|
||||||
|
///
|
||||||
|
/// You can turn this style on and off to change dialog box navigation.
|
||||||
|
/// To change this style after a window has been created, use the SetWindowLong function.
|
||||||
|
/// </summary>
|
||||||
|
Group = 0x00020000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a horizontal scroll bar.
|
||||||
|
/// </summary>
|
||||||
|
HorizontalScroll = 0x00100000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is initially minimized.
|
||||||
|
/// Same as the WS_MINIMIZE style.
|
||||||
|
/// </summary>
|
||||||
|
Iconic = 0x20000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is initially maximized.
|
||||||
|
/// </summary>
|
||||||
|
Maximize = 0x01000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a maximize button.
|
||||||
|
/// Cannot be combined with the WS_EX_CONTEXTHELP style.
|
||||||
|
/// The WS_SYSMENU style must also be specifie
|
||||||
|
/// </summary>
|
||||||
|
MaximizeBox = 0x00010000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is initially minimized.
|
||||||
|
/// Same as the WS_ICONIC style.
|
||||||
|
/// </summary>
|
||||||
|
Minimize = 0x20000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a minimize button.
|
||||||
|
/// Cannot be combined with the WS_EX_CONTEXTHELP style.
|
||||||
|
/// The WS_SYSMENU style must also be specified.
|
||||||
|
/// </summary>
|
||||||
|
MinimizeBox = 0x00020000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is an overlapped window.
|
||||||
|
/// An overlapped window has a title bar and a border.
|
||||||
|
/// Same as the WS_TILED style.
|
||||||
|
/// </summary>
|
||||||
|
Overlapped = 0x00000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The windows is a pop-up window.
|
||||||
|
/// This style cannot be used with the WS_CHILD style.
|
||||||
|
/// </summary>
|
||||||
|
Popup = unchecked((int)0x80000000),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a sizing border.
|
||||||
|
/// Same as the WS_THICKFRAME style.
|
||||||
|
/// </summary>
|
||||||
|
SizeBox = 0x00040000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a window menu on its title bar.
|
||||||
|
/// The WS_CAPTION style must also be specified.
|
||||||
|
/// </summary>
|
||||||
|
SystemMenu = 0x00080000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is a control that can receive the keyboard focus when the user presses the TAB key.
|
||||||
|
/// Pressing the TAB key changes the keyboard focus to the next control with the WS_TABSTOP style.
|
||||||
|
///
|
||||||
|
/// You can turn this style on and off to change dialog box navigation.
|
||||||
|
/// To change this style after a window has been created, use the SetWindowLong function.
|
||||||
|
/// For user-created windows and modeless dialogs to work with tab stops,
|
||||||
|
/// alter the message loop to call the IsDialogMessage function.
|
||||||
|
/// </summary>
|
||||||
|
Tabstop = 0x00010000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a sizing border.
|
||||||
|
/// Same as the WS_SIZEBOX style.
|
||||||
|
/// </summary>
|
||||||
|
ThickFrame = 0x00040000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is an overlapped window.
|
||||||
|
/// An overlapped window has a title bar and a border.
|
||||||
|
/// Same as the WS_OVERLAPPED style.
|
||||||
|
/// </summary>
|
||||||
|
Tiled = 0x00000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is initially visible.
|
||||||
|
///
|
||||||
|
/// This style can be turned on and off by using the ShowWindow or SetWindowPos function.
|
||||||
|
/// </summary>
|
||||||
|
Visible = 0x10000000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window has a vertical scroll bar.
|
||||||
|
/// </summary>
|
||||||
|
VerticalScroll = 0x00200000,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is an overlapped window.
|
||||||
|
/// Same as the WS_OVERLAPPEDWINDOW style.
|
||||||
|
/// </summary>
|
||||||
|
TiledWindowMask = Overlapped | Caption | SystemMenu | ThickFrame | MinimizeBox | MaximizeBox,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is a pop-up window.
|
||||||
|
/// The WS_CAPTION and WS_POPUPWINDOW styles must be combined to make the window menu visible.
|
||||||
|
/// </summary>
|
||||||
|
PopupWindowMask = Popup | Border | SystemMenu,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window is an overlapped window. Same as the WS_TILEDWINDOW style.
|
||||||
|
/// </summary>
|
||||||
|
OverlappedWindowMask = Overlapped | Caption | SystemMenu | ThickFrame | MinimizeBox | MaximizeBox,
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
@ -1,125 +1,280 @@
|
|||||||
using System;
|
#if PREVIEW_HANDLER
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ShellExtensions.Interop.Common
|
namespace ShellExtensions.Interop.Common
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The STGM constants are flags that indicate
|
/// Wraps the native Windows MSG structure.
|
||||||
/// conditions for creating and deleting the object and access modes
|
|
||||||
/// for the object.
|
|
||||||
///
|
|
||||||
/// You can combine these flags, but you can only choose one flag
|
|
||||||
/// from each group of related flags. Typically one flag from each
|
|
||||||
/// of the access and sharing groups must be specified for all
|
|
||||||
/// functions and methods which use these constants.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
public struct Message
|
||||||
public enum AccessModes
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that, in direct mode, each change to a storage
|
/// Gets the window handle
|
||||||
/// or stream element is written as it occurs.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Direct = 0x00000000,
|
public IntPtr WindowHandle { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that, in transacted mode, changes are buffered
|
/// Gets the window message
|
||||||
/// and written only if an explicit commit operation is called.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Transacted = 0x00010000,
|
public uint Msg { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides a faster implementation of a compound file
|
/// Gets the WParam
|
||||||
/// in a limited, but frequently used, case.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Simple = 0x08000000,
|
public IntPtr WParam { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that the object is read-only,
|
/// Gets the LParam
|
||||||
/// meaning that modifications cannot be made.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Read = 0x00000000,
|
public IntPtr LParam { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables you to save changes to the object,
|
/// Gets the time
|
||||||
/// but does not permit access to its data.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Write = 0x00000001,
|
public int Time { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables access and modification of object data.
|
/// Gets the point
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ReadWrite = 0x00000002,
|
public NativePoint Point { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies that subsequent openings of the object are
|
/// Creates a new instance of the Message struct
|
||||||
/// not denied read or write access.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ShareDenyNone = 0x00000040,
|
/// <param name="windowHandle">Window handle</param>
|
||||||
|
/// <param name="msg">Message</param>
|
||||||
|
/// <param name="wparam">WParam</param>
|
||||||
|
/// <param name="lparam">LParam</param>
|
||||||
|
/// <param name="time">Time</param>
|
||||||
|
/// <param name="point">Point</param>
|
||||||
|
internal Message(IntPtr windowHandle, uint msg, IntPtr wparam, IntPtr lparam, int time, NativePoint point)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
WindowHandle = windowHandle;
|
||||||
|
Msg = msg;
|
||||||
|
WParam = wparam;
|
||||||
|
LParam = lparam;
|
||||||
|
Time = time;
|
||||||
|
Point = point;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents others from subsequently opening the object in Read mode.
|
/// Determines if two messages are equal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ShareDenyRead = 0x00000030,
|
/// <param name="first">First message</param>
|
||||||
|
/// <param name="second">Second message</param>
|
||||||
|
/// <returns>True if first and second message are equal; false otherwise.</returns>
|
||||||
|
public static bool operator ==(Message first, Message second)
|
||||||
|
{
|
||||||
|
return first.WindowHandle == second.WindowHandle
|
||||||
|
&& first.Msg == second.Msg
|
||||||
|
&& first.WParam == second.WParam
|
||||||
|
&& first.LParam == second.LParam
|
||||||
|
&& first.Time == second.Time
|
||||||
|
&& first.Point == second.Point;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents others from subsequently opening the object
|
/// Determines if two messages are not equal.
|
||||||
/// for Write or ReadWrite access.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ShareDenyWrite = 0x00000020,
|
/// <param name="first">First message</param>
|
||||||
|
/// <param name="second">Second message</param>
|
||||||
|
/// <returns>True if first and second message are not equal; false otherwise.</returns>
|
||||||
|
public static bool operator !=(Message first, Message second)
|
||||||
|
{
|
||||||
|
return !(first == second);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents others from subsequently opening the object in any mode.
|
/// Determines if this message is equal to another.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ShareExclusive = 0x00000010,
|
/// <param name="obj">Another message</param>
|
||||||
|
/// <returns>True if this message is equal argument; false otherwise.</returns>
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj != null && obj is Message message && this == message;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the storage object with exclusive access to the most
|
/// Gets a hash code for the message.
|
||||||
/// recently committed version.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Priority = 0x00040000,
|
/// <returns>Hash code for this message.</returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
int hash = WindowHandle.GetHashCode();
|
||||||
|
hash = hash * 31 + Msg.GetHashCode();
|
||||||
|
hash = hash * 31 + WParam.GetHashCode();
|
||||||
|
hash = hash * 31 + LParam.GetHashCode();
|
||||||
|
hash = hash * 31 + Time.GetHashCode();
|
||||||
|
hash = hash * 31 + Point.GetHashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that the underlying file is to be automatically destroyed when the root
|
/// A wrapper for the native POINT structure.
|
||||||
/// storage object is released. This feature is most useful for creating temporary files.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DeleteOnRelease = 0x04000000,
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct NativePoint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the NativePoint
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The x coordinate of the point.</param>
|
||||||
|
/// <param name="y">The y coordinate of the point.</param>
|
||||||
|
public NativePoint(int x, int y)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that, in transacted mode, a temporary scratch file is usually used
|
/// The X coordinate of the point
|
||||||
/// to save modifications until the Commit method is called.
|
|
||||||
/// Specifying NoScratch permits the unused portion of the original file
|
|
||||||
/// to be used as work space instead of creating a new file for that purpose.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NoScratch = 0x00100000,
|
public int X { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that an existing storage object
|
/// The Y coordinate of the point
|
||||||
/// or stream should be removed before the new object replaces it.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Create = 0x00001000,
|
public int Y { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the new object while preserving existing data in a stream named "Contents".
|
/// Determines if two NativePoints are equal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Convert = 0x00020000,
|
/// <param name="first">First NativePoint</param>
|
||||||
|
/// <param name="second">Second NativePoint</param>
|
||||||
|
/// <returns>True if first NativePoint is equal to the second; false otherwise.</returns>
|
||||||
|
public static bool operator ==(NativePoint first, NativePoint second)
|
||||||
|
{
|
||||||
|
return first.X == second.X
|
||||||
|
&& first.Y == second.Y;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Causes the create operation to fail if an existing object with the specified name exists.
|
/// Determines if two NativePoints are not equal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FailIfThere = 0x00000000,
|
/// <param name="first">First NativePoint</param>
|
||||||
|
/// <param name="second">Second NativePoint</param>
|
||||||
|
/// <returns>True if first NativePoint is not equal to the second; false otherwise.</returns>
|
||||||
|
public static bool operator !=(NativePoint first, NativePoint second)
|
||||||
|
{
|
||||||
|
return !(first == second);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This flag is used when opening a storage object with Transacted
|
/// Determines if this NativePoint is equal to another.
|
||||||
/// and without ShareExclusive or ShareDenyWrite.
|
|
||||||
/// In this case, specifying NoSnapshot prevents the system-provided
|
|
||||||
/// implementation from creating a snapshot copy of the file.
|
|
||||||
/// Instead, changes to the file are written to the end of the file.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NoSnapshot = 0x00200000,
|
/// <param name="obj">Another NativePoint to compare</param>
|
||||||
|
/// <returns>True if this NativePoint is equal obj; false otherwise.</returns>
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj != null && obj is NativePoint point && this == point;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports direct mode for single-writer, multireader file operations.
|
/// Gets a hash code for the NativePoint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DirectSingleWriterMultipleReader = 0x00400000
|
/// <returns>Hash code for the NativePoint</returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
int hash = X.GetHashCode();
|
||||||
|
hash = hash * 31 + Y.GetHashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A wrapper for a RECT struct
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct NativeRect
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Position of left edge
|
||||||
|
/// </summary>
|
||||||
|
public int Left { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Position of top edge
|
||||||
|
/// </summary>
|
||||||
|
public int Top { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Position of right edge
|
||||||
|
/// </summary>
|
||||||
|
public int Right { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Position of bottom edge
|
||||||
|
/// </summary>
|
||||||
|
public int Bottom { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new NativeRect initialized with supplied values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">Position of left edge</param>
|
||||||
|
/// <param name="top">Position of top edge</param>
|
||||||
|
/// <param name="right">Position of right edge</param>
|
||||||
|
/// <param name="bottom">Position of bottom edge</param>
|
||||||
|
public NativeRect(int left, int top, int right, int bottom)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Top = top;
|
||||||
|
Right = right;
|
||||||
|
Bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if two NativeRects are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="first">First NativeRect</param>
|
||||||
|
/// <param name="second">Second NativeRect</param>
|
||||||
|
/// <returns>True if first NativeRect is equal to second; false otherwise.</returns>
|
||||||
|
public static bool operator ==(NativeRect first, NativeRect second)
|
||||||
|
{
|
||||||
|
return first.Left == second.Left
|
||||||
|
&& first.Top == second.Top
|
||||||
|
&& first.Right == second.Right
|
||||||
|
&& first.Bottom == second.Bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if two NativeRects are not equal
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="first">First NativeRect</param>
|
||||||
|
/// <param name="second">Second NativeRect</param>
|
||||||
|
/// <returns>True if first is not equal to second; false otherwise.</returns>
|
||||||
|
public static bool operator !=(NativeRect first, NativeRect second)
|
||||||
|
{
|
||||||
|
return !(first == second);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the NativeRect is equal to another Rect.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">Another NativeRect to compare</param>
|
||||||
|
/// <returns>True if this NativeRect is equal to the one provided; false otherwise.</returns>
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj != null && obj is NativeRect rect && this == rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a hash code for the NativeRect
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns hash code for this NativeRect</returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
int hash = Left.GetHashCode();
|
||||||
|
hash = hash * 31 + Top.GetHashCode();
|
||||||
|
hash = hash * 31 + Right.GetHashCode();
|
||||||
|
hash = hash * 31 + Bottom.GetHashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -7,7 +7,29 @@ namespace ShellExtensions.Interop
|
|||||||
{
|
{
|
||||||
internal static class HandlerNativeMethods
|
internal static class HandlerNativeMethods
|
||||||
{
|
{
|
||||||
|
#if PREVIEW_HANDLER
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern IntPtr GetFocus();
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern void SetWindowPos(
|
||||||
|
IntPtr hWnd,
|
||||||
|
IntPtr hWndInsertAfter,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int cx,
|
||||||
|
int cy,
|
||||||
|
SetWindowPositionOptions flags);
|
||||||
|
|
||||||
|
internal static readonly Guid IPreviewHandlerGuid = new Guid("8895b1c6-b41f-4c1c-a562-0d564250836f");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if THUMBNAIL
|
||||||
internal static readonly Guid IThumbnailProviderGuid = new Guid("e357fccd-a995-4576-b01f-234630154e96");
|
internal static readonly Guid IThumbnailProviderGuid = new Guid("e357fccd-a995-4576-b01f-234630154e96");
|
||||||
|
#endif
|
||||||
|
|
||||||
internal static readonly Guid IInitializeWithFileGuid = new Guid("b7d14566-0509-4cce-a71f-0a554233bd9b");
|
internal static readonly Guid IInitializeWithFileGuid = new Guid("b7d14566-0509-4cce-a71f-0a554233bd9b");
|
||||||
internal static readonly Guid IInitializeWithStreamGuid = new Guid("b824b49d-22ac-4161-ac8a-9916e8fa3f7f");
|
internal static readonly Guid IInitializeWithStreamGuid = new Guid("b824b49d-22ac-4161-ac8a-9916e8fa3f7f");
|
||||||
@ -16,25 +38,6 @@ namespace ShellExtensions.Interop
|
|||||||
internal static readonly Guid IMarshalGuid = new Guid("00000003-0000-0000-C000-000000000046");
|
internal static readonly Guid IMarshalGuid = new Guid("00000003-0000-0000-C000-000000000046");
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Interfaces
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// ComVisible interface for native IThumbnailProvider
|
|
||||||
/// </summary>
|
|
||||||
[ComImport]
|
|
||||||
[Guid("e357fccd-a995-4576-b01f-234630154e96")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
interface IThumbnailProvider
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a pointer to a bitmap to display as a thumbnail
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="squareLength"></param>
|
|
||||||
/// <param name="bitmapHandle"></param>
|
|
||||||
/// <param name="bitmapType"></param>
|
|
||||||
void GetThumbnail(uint squareLength, [Out] out IntPtr bitmapHandle, [Out] out uint bitmapType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides means by which to initialize with a file.
|
/// Provides means by which to initialize with a file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -67,6 +70,26 @@ namespace ShellExtensions.Interop
|
|||||||
void Initialize(IStream stream, AccessModes fileMode);
|
void Initialize(IStream stream, AccessModes fileMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if THUMBNAIL
|
||||||
|
#region Interfaces
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ComVisible interface for native IThumbnailProvider
|
||||||
|
/// </summary>
|
||||||
|
[ComImport]
|
||||||
|
[Guid("e357fccd-a995-4576-b01f-234630154e96")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
interface IThumbnailProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a pointer to a bitmap to display as a thumbnail
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="squareLength"></param>
|
||||||
|
/// <param name="bitmapHandle"></param>
|
||||||
|
/// <param name="bitmapType"></param>
|
||||||
|
void GetThumbnail(uint squareLength, [Out] out IntPtr bitmapHandle, [Out] out uint bitmapType);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// <summary>
|
// <summary>
|
||||||
@ -89,4 +112,178 @@ namespace ShellExtensions.Interop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
HasAlphaChannel = 2,
|
HasAlphaChannel = 2,
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PREVIEW_HANDLER
|
||||||
|
[ComImport]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("fc4801a3-2ba9-11cf-a229-00aa003d7352")]
|
||||||
|
interface IObjectWithSite
|
||||||
|
{
|
||||||
|
void SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object pUnkSite);
|
||||||
|
void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvSite);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[Guid("00000114-0000-0000-C000-000000000046")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
interface IOleWindow
|
||||||
|
{
|
||||||
|
void GetWindow(out IntPtr phwnd);
|
||||||
|
void ContextSensitiveHelp([MarshalAs(UnmanagedType.Bool)] bool fEnterMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("8895b1c6-b41f-4c1c-a562-0d564250836f")]
|
||||||
|
interface IPreviewHandler
|
||||||
|
{
|
||||||
|
void SetWindow(IntPtr hwnd, ref NativeRect rect);
|
||||||
|
void SetRect(ref NativeRect rect);
|
||||||
|
void DoPreview();
|
||||||
|
void Unload();
|
||||||
|
void SetFocus();
|
||||||
|
void QueryFocus(out IntPtr phwnd);
|
||||||
|
[PreserveSig]
|
||||||
|
HResult TranslateAccelerator(ref Message pmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("fec87aaf-35f9-447a-adb7-20234491401a")]
|
||||||
|
interface IPreviewHandlerFrame
|
||||||
|
{
|
||||||
|
void GetWindowContext(IntPtr pinfo);
|
||||||
|
[PreserveSig]
|
||||||
|
HResult TranslateAccelerator(ref Message pmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("8327b13c-b63f-4b24-9b8a-d010dcc3f599")]
|
||||||
|
interface IPreviewHandlerVisuals
|
||||||
|
{
|
||||||
|
void SetBackgroundColor(NativeColorRef color);
|
||||||
|
void SetFont(ref LogFont plf);
|
||||||
|
void SetTextColor(NativeColorRef color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Structs
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class for marshaling to native LogFont struct
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||||
|
public class LogFont
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Font height
|
||||||
|
/// </summary>
|
||||||
|
public int Height { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font width
|
||||||
|
/// </summary>
|
||||||
|
public int Width { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font escapement
|
||||||
|
/// </summary>
|
||||||
|
public int Escapement { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font orientation
|
||||||
|
/// </summary>
|
||||||
|
public int Orientation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font weight
|
||||||
|
/// </summary>
|
||||||
|
public int Weight { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font italic
|
||||||
|
/// </summary>
|
||||||
|
public byte Italic { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font underline
|
||||||
|
/// </summary>
|
||||||
|
public byte Underline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font strikeout
|
||||||
|
/// </summary>
|
||||||
|
public byte Strikeout { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font character set
|
||||||
|
/// </summary>
|
||||||
|
public byte CharacterSet { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font out precision
|
||||||
|
/// </summary>
|
||||||
|
public byte OutPrecision { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font clip precision
|
||||||
|
/// </summary>
|
||||||
|
public byte ClipPrecision { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font quality
|
||||||
|
/// </summary>
|
||||||
|
public byte Quality { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font pitch and family
|
||||||
|
/// </summary>
|
||||||
|
public byte PitchAndFamily { get; set; }
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||||
|
private string faceName = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Font face name
|
||||||
|
/// </summary>
|
||||||
|
public string FaceName { get => faceName; set => faceName = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct NativeColorRef
|
||||||
|
{
|
||||||
|
public uint Dword { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum SetWindowPositionOptions
|
||||||
|
{
|
||||||
|
AsyncWindowPos = 0x4000,
|
||||||
|
DeferErase = 0x2000,
|
||||||
|
DrawFrame = FrameChanged,
|
||||||
|
FrameChanged = 0x0020, // The frame changed: send WM_NCCALCSIZE
|
||||||
|
HideWindow = 0x0080,
|
||||||
|
NoActivate = 0x0010,
|
||||||
|
CoCopyBits = 0x0100,
|
||||||
|
NoMove = 0x0002,
|
||||||
|
NoOwnerZOrder = 0x0200, // Don't do owner Z ordering
|
||||||
|
NoRedraw = 0x0008,
|
||||||
|
NoResposition = NoOwnerZOrder,
|
||||||
|
NoSendChanging = 0x0400, // Don't send WM_WINDOWPOSCHANGING
|
||||||
|
NoSize = 0x0001,
|
||||||
|
NoZOrder = 0x0004,
|
||||||
|
ShowWindow = 0x0040
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum SetWindowPositionInsertAfter
|
||||||
|
{
|
||||||
|
NoTopMost = -2,
|
||||||
|
TopMost = -1,
|
||||||
|
Top = 0,
|
||||||
|
Bottom = 1
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
#if PREVIEW_HANDLER
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace ShellExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This interface exposes the <see cref="Load"/> function for initializing the
|
||||||
|
/// Preview Handler with a <typeparamref name="Stream"/>.
|
||||||
|
/// This interface can be used in conjunction with the other intialization interfaces,
|
||||||
|
/// but only 1 will be accessed according to the priorities preset by the Windows Shell:
|
||||||
|
/// <typeparamref name="IPreviewFromStream"/>
|
||||||
|
/// <typeparamref name="IPreviewFromShellObject"/>
|
||||||
|
/// <typeparamref name="IPreviewFromFile"/>
|
||||||
|
/// </summary>
|
||||||
|
public interface IPreviewFromStream
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides the <typeparamref name="Stream"/> to the item from which a preview should be created.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">Stream to the previewed file, this stream is only available in the scope of this method.</param>
|
||||||
|
void Load(Stream stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This interface exposes the <see cref="Load"/> function for initializing the
|
||||||
|
/// Preview Handler with a <typeparamref name="FileInfo"/>.
|
||||||
|
/// This interface can be used in conjunction with the other intialization interfaces,
|
||||||
|
/// but only 1 will be accessed according to the priorities preset by the Windows Shell:
|
||||||
|
/// <typeparamref name="IPreviewFromStream"/>
|
||||||
|
/// <typeparamref name="IPreviewFromShellObject"/>
|
||||||
|
/// <typeparamref name="IPreviewFromFile"/>
|
||||||
|
/// </summary>
|
||||||
|
public interface IPreviewFromFile
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides the <typeparamref name="FileInfo"/> to the item from which a preview should be created.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">File information to the previewed file.</param>
|
||||||
|
void Load(FileInfo info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
377
ShellExtensions/PreviewHandlers/PreviewHandler.cs
Normal file
377
ShellExtensions/PreviewHandlers/PreviewHandler.cs
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
#if PREVIEW_HANDLER
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using ShellExtensions.Interop;
|
||||||
|
using ShellExtensions.Interop.Common;
|
||||||
|
using ShellExtensions.Resources;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace ShellExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the base class for all preview handlers and provides their basic functionality.
|
||||||
|
/// To create a custom preview handler a class must derive from this, use the <typeparamref name="PreviewHandlerAttribute"/>,
|
||||||
|
/// and implement 1 or more of the following interfaces:
|
||||||
|
/// <typeparamref name="IPreviewFromStream"/>,
|
||||||
|
/// <typeparamref name="IPreviewFromShellObject"/>,
|
||||||
|
/// <typeparamref name="IPreviewFromFile"/>.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class PreviewHandler : ICustomQueryInterface, IPreviewHandler, IPreviewHandlerVisuals, IOleWindow, IObjectWithSite, IInitializeWithStream, IInitializeWithFile
|
||||||
|
{
|
||||||
|
private bool _isPreviewShowing;
|
||||||
|
private IntPtr _parentHwnd;
|
||||||
|
private IPreviewHandlerFrame _frame;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the preview is currently showing
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPreviewShowing => _isPreviewShowing;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called immediately before the preview is to be shown.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void Initialize() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the preview is no longer shown.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void Uninitialize() { }
|
||||||
|
|
||||||
|
#region Required functions - Abstract functions
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This should return the window handle to be displayed in the Preview.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract IntPtr Handle { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called to update the bounds and position of the preview control
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bounds"></param>
|
||||||
|
protected abstract void UpdateBounds(NativeRect bounds);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when an exception occurs during the initialization of the control
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="caughtException"></param>
|
||||||
|
protected abstract void HandleInitializeException(Exception caughtException);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the preview control obtains focus.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract void SetFocus();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when a request is received to set or change the background color according to the user's preferences.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">An int representing the ARGB color</param>
|
||||||
|
protected abstract void SetBackground(int argb);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when a request is received to set or change the foreground color according to the user's preferences.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">An int representing the ARGB color</param>
|
||||||
|
protected abstract void SetForeground(int argb);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called to set the font of the preview control according to the user's preferences.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="font"></param>
|
||||||
|
protected abstract void SetFont(LogFont font);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called to set the parent of the preview control.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle"></param>
|
||||||
|
protected abstract void SetParentHandle(IntPtr handle);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IPreviewHandler Members
|
||||||
|
|
||||||
|
void IPreviewHandler.SetWindow(IntPtr hwnd, ref NativeRect rect)
|
||||||
|
{
|
||||||
|
_parentHwnd = hwnd;
|
||||||
|
UpdateBounds(rect);
|
||||||
|
SetParentHandle(_parentHwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPreviewHandler.SetRect(ref NativeRect rect)
|
||||||
|
{
|
||||||
|
UpdateBounds(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPreviewHandler.DoPreview()
|
||||||
|
{
|
||||||
|
_isPreviewShowing = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
HandleInitializeException(exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPreviewHandler.Unload()
|
||||||
|
{
|
||||||
|
Uninitialize();
|
||||||
|
_isPreviewShowing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPreviewHandler.SetFocus()
|
||||||
|
{
|
||||||
|
SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPreviewHandler.QueryFocus(out IntPtr phwnd)
|
||||||
|
{
|
||||||
|
phwnd = HandlerNativeMethods.GetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
HResult IPreviewHandler.TranslateAccelerator(ref Message pmsg)
|
||||||
|
{
|
||||||
|
return _frame != null ? _frame.TranslateAccelerator(ref pmsg) : HResult.False;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IPreviewHandlerVisuals Members
|
||||||
|
|
||||||
|
void IPreviewHandlerVisuals.SetBackgroundColor(NativeColorRef color)
|
||||||
|
{
|
||||||
|
SetBackground((int)color.Dword);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPreviewHandlerVisuals.SetTextColor(NativeColorRef color)
|
||||||
|
{
|
||||||
|
SetForeground((int)color.Dword);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPreviewHandlerVisuals.SetFont(ref LogFont plf)
|
||||||
|
{
|
||||||
|
SetFont(plf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IOleWindow Members
|
||||||
|
|
||||||
|
void IOleWindow.GetWindow(out IntPtr phwnd)
|
||||||
|
{
|
||||||
|
phwnd = Handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOleWindow.ContextSensitiveHelp(bool fEnterMode)
|
||||||
|
{
|
||||||
|
// Preview handlers don't support context sensitive help. (As far as I know.)
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IObjectWithSite Members
|
||||||
|
|
||||||
|
void IObjectWithSite.SetSite(object pUnkSite)
|
||||||
|
{
|
||||||
|
_frame = pUnkSite as IPreviewHandlerFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IObjectWithSite.GetSite(ref Guid riid, out object ppvSite)
|
||||||
|
{
|
||||||
|
ppvSite = _frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IInitializeWithStream Members
|
||||||
|
|
||||||
|
void IInitializeWithStream.Initialize(System.Runtime.InteropServices.ComTypes.IStream stream, AccessModes fileMode)
|
||||||
|
{
|
||||||
|
IPreviewFromStream preview = this as IPreviewFromStream;
|
||||||
|
if (preview == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
string.Format(System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
LocalizedMessages.PreviewHandlerUnsupportedInterfaceCalled,
|
||||||
|
nameof(IPreviewFromStream)));
|
||||||
|
}
|
||||||
|
using (var storageStream = new StorageStream(stream, fileMode != AccessModes.ReadWrite))
|
||||||
|
{
|
||||||
|
preview.Load(storageStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IInitializeWithFile Members
|
||||||
|
|
||||||
|
void IInitializeWithFile.Initialize(string filePath, AccessModes fileMode)
|
||||||
|
{
|
||||||
|
IPreviewFromFile preview = this as IPreviewFromFile;
|
||||||
|
if (preview == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
string.Format(System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
LocalizedMessages.PreviewHandlerUnsupportedInterfaceCalled,
|
||||||
|
nameof(IPreviewFromFile)));
|
||||||
|
}
|
||||||
|
preview.Load(new FileInfo(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ComRegistration
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the assembly is registered via RegAsm.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="registerType">Type to register.</param>
|
||||||
|
[ComRegisterFunction]
|
||||||
|
private static void Register(Type registerType)
|
||||||
|
{
|
||||||
|
if (registerType != null && registerType.IsSubclassOf(typeof(PreviewHandler)))
|
||||||
|
{
|
||||||
|
object[] attrs = registerType.GetCustomAttributes(typeof(PreviewHandlerAttribute), true);
|
||||||
|
if (attrs != null && attrs.Length == 1)
|
||||||
|
{
|
||||||
|
PreviewHandlerAttribute attr = attrs[0] as PreviewHandlerAttribute;
|
||||||
|
ThrowIfNotValid(registerType);
|
||||||
|
RegisterPreviewHandler(registerType.GUID, attr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(
|
||||||
|
string.Format(System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
LocalizedMessages.PreviewHandlerInvalidAttributes, registerType.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the assembly is Unregistered via RegAsm.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="registerType">Type to unregister</param>
|
||||||
|
[ComUnregisterFunction]
|
||||||
|
private static void Unregister(Type registerType)
|
||||||
|
{
|
||||||
|
if (registerType != null && registerType.IsSubclassOf(typeof(PreviewHandler)))
|
||||||
|
{
|
||||||
|
object[] attrs = registerType.GetCustomAttributes(typeof(PreviewHandlerAttribute), true);
|
||||||
|
if (attrs != null && attrs.Length == 1)
|
||||||
|
{
|
||||||
|
PreviewHandlerAttribute attr = attrs[0] as PreviewHandlerAttribute;
|
||||||
|
UnregisterPreviewHandler(registerType.GUID, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RegisterPreviewHandler(Guid previewerGuid, PreviewHandlerAttribute attribute)
|
||||||
|
{
|
||||||
|
string guid = previewerGuid.ToString("B");
|
||||||
|
// Create a new prevhost AppID so that this always runs in its own isolated process
|
||||||
|
using (RegistryKey appIdsKey = Registry.ClassesRoot.OpenSubKey("AppID", true))
|
||||||
|
using (RegistryKey appIdKey = appIdsKey.CreateSubKey(attribute.AppId))
|
||||||
|
{
|
||||||
|
appIdKey.SetValue("DllSurrogate", @"%SystemRoot%\system32\prevhost.exe", RegistryValueKind.ExpandString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add preview handler to preview handler list
|
||||||
|
using (RegistryKey handlersKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", true))
|
||||||
|
{
|
||||||
|
handlersKey.SetValue(guid, attribute.Name, RegistryValueKind.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify preview handler registration
|
||||||
|
using (RegistryKey clsidKey = Registry.ClassesRoot.OpenSubKey("CLSID"))
|
||||||
|
using (RegistryKey idKey = clsidKey.OpenSubKey(guid, true))
|
||||||
|
{
|
||||||
|
idKey.SetValue("DisplayName", attribute.Name, RegistryValueKind.String);
|
||||||
|
idKey.SetValue("AppID", attribute.AppId, RegistryValueKind.String);
|
||||||
|
idKey.SetValue("DisableLowILProcessIsolation", attribute.DisableLowILProcessIsolation ? 1 : 0, RegistryValueKind.DWord);
|
||||||
|
|
||||||
|
using (RegistryKey inproc = idKey.OpenSubKey("InprocServer32", true))
|
||||||
|
{
|
||||||
|
inproc.SetValue("ThreadingModel", "Apartment", RegistryValueKind.String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string extension in attribute.Extensions.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
Trace.WriteLine("Registering extension '" + extension + "' with previewer '" + guid + "'");
|
||||||
|
|
||||||
|
// Set preview handler for specific extension
|
||||||
|
using (RegistryKey extensionKey = Registry.ClassesRoot.CreateSubKey(extension))
|
||||||
|
using (RegistryKey shellexKey = extensionKey.CreateSubKey("shellex"))
|
||||||
|
using (RegistryKey previewKey = shellexKey.CreateSubKey(HandlerNativeMethods.IPreviewHandlerGuid.ToString("B")))
|
||||||
|
{
|
||||||
|
previewKey.SetValue(null, guid, RegistryValueKind.String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UnregisterPreviewHandler(Guid previewerGuid, PreviewHandlerAttribute attribute)
|
||||||
|
{
|
||||||
|
string guid = previewerGuid.ToString("B");
|
||||||
|
foreach (string extension in attribute.Extensions.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
Trace.WriteLine("Unregistering extension '" + extension + "' with previewer '" + guid + "'");
|
||||||
|
using (RegistryKey shellexKey = Registry.ClassesRoot.OpenSubKey(extension + "\\shellex", true))
|
||||||
|
{
|
||||||
|
shellexKey.DeleteSubKey(HandlerNativeMethods.IPreviewHandlerGuid.ToString(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (RegistryKey appIdsKey = Registry.ClassesRoot.OpenSubKey("AppID", true))
|
||||||
|
{
|
||||||
|
appIdsKey.DeleteSubKey(attribute.AppId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (RegistryKey classesKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", true))
|
||||||
|
{
|
||||||
|
classesKey.DeleteValue(guid, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ThrowIfNotValid(Type type)
|
||||||
|
{
|
||||||
|
var interfaces = type.GetInterfaces();
|
||||||
|
if (!interfaces.Any(x => x is IPreviewFromStream || x is IPreviewFromFile))
|
||||||
|
{
|
||||||
|
throw new NotImplementedException(
|
||||||
|
string.Format(System.Globalization.CultureInfo.InvariantCulture,
|
||||||
|
LocalizedMessages.PreviewHandlerInterfaceNotImplemented,
|
||||||
|
type.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICustomQueryInterface Members
|
||||||
|
|
||||||
|
CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv)
|
||||||
|
{
|
||||||
|
ppv = IntPtr.Zero;
|
||||||
|
// Forces COM to not use the managed (free threaded) marshaler
|
||||||
|
if (iid == HandlerNativeMethods.IMarshalGuid)
|
||||||
|
{
|
||||||
|
return CustomQueryInterfaceResult.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((iid == HandlerNativeMethods.IInitializeWithStreamGuid && !(this is IPreviewFromStream)) ||
|
||||||
|
(iid == HandlerNativeMethods.IInitializeWithFileGuid && !(this is IPreviewFromFile)))
|
||||||
|
{
|
||||||
|
return CustomQueryInterfaceResult.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CustomQueryInterfaceResult.NotHandled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
48
ShellExtensions/PreviewHandlers/PreviewHandlerAttribute.cs
Normal file
48
ShellExtensions/PreviewHandlers/PreviewHandlerAttribute.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#if PREVIEW_HANDLER
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ShellExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class attribute is applied to a Preview Handler to specify registration parameters.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||||
|
public sealed class PreviewHandlerAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the attribute.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">Name of the Handler</param>
|
||||||
|
/// <param name="extensions">Semi-colon-separated list of file extensions supported by the handler.</param>
|
||||||
|
/// <param name="appId">A unique guid used for process isolation.</param>
|
||||||
|
public PreviewHandlerAttribute(string name, string extensions, string appId)
|
||||||
|
{
|
||||||
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
|
Extensions = extensions ?? throw new ArgumentNullException(nameof(extensions));
|
||||||
|
AppId = appId ?? throw new ArgumentNullException(nameof(appId));
|
||||||
|
DisableLowILProcessIsolation = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the handler.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the semi-colon-separated list of extensions supported by the preview handler.
|
||||||
|
/// </summary>
|
||||||
|
public string Extensions { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the AppId associated with the handler for use with the surrogate host process.
|
||||||
|
/// </summary>
|
||||||
|
public string AppId { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disables low integrity-level process isolation.
|
||||||
|
/// <remarks>This should be avoided as it could be a security risk.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableLowILProcessIsolation { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
119
ShellExtensions/PreviewHandlers/WinFormsPreviewHandler.cs
Normal file
119
ShellExtensions/PreviewHandlers/WinFormsPreviewHandler.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#if PREVIEW_HANDLER
|
||||||
|
using ShellExtensions.Interop;
|
||||||
|
using ShellExtensions.Interop.Common;
|
||||||
|
using ShellExtensions.Resources;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace ShellExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the base class for all WinForms-based preview handlers and provides their basic functionality.
|
||||||
|
/// To create a custom preview handler that contains a WinForms user control,
|
||||||
|
/// a class must derive from this, use the <typeparamref name="PreviewHandlerAttribute"/>,
|
||||||
|
/// and implement 1 or more of the following interfaces:
|
||||||
|
/// <typeparamref name="IPreviewFromStream"/>,
|
||||||
|
/// <typeparamref name="IPreviewFromShellObject"/>,
|
||||||
|
/// <typeparamref name="IPreviewFromFile"/>.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class WinFormsPreviewHandler : PreviewHandler, IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This control must be populated by the deriving class before the preview is shown.
|
||||||
|
/// </summary>
|
||||||
|
public UserControl Control { get; protected set; }
|
||||||
|
|
||||||
|
protected void ThrowIfNoControl()
|
||||||
|
{
|
||||||
|
if (Control == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(LocalizedMessages.PreviewHandlerControlNotInitialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when an exception is thrown during itialization of the preview control.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="caughtException"></param>
|
||||||
|
protected override void HandleInitializeException(Exception caughtException)
|
||||||
|
{
|
||||||
|
if (caughtException == null) { throw new ArgumentNullException(nameof(caughtException)); }
|
||||||
|
|
||||||
|
Control = new UserControl();
|
||||||
|
Control.Controls.Add(new TextBox
|
||||||
|
{
|
||||||
|
ReadOnly = true,
|
||||||
|
Multiline = true,
|
||||||
|
Dock = DockStyle.Fill,
|
||||||
|
Text = caughtException.ToString(),
|
||||||
|
BackColor = Color.OrangeRed
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateBounds(NativeRect bounds)
|
||||||
|
{
|
||||||
|
Control.Bounds = Rectangle.FromLTRB(bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
|
||||||
|
Control.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetFocus()
|
||||||
|
{
|
||||||
|
Control.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetBackground(int argb)
|
||||||
|
{
|
||||||
|
Control.BackColor = Color.FromArgb(argb);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetForeground(int argb)
|
||||||
|
{
|
||||||
|
Control.ForeColor = Color.FromArgb(argb);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetFont(Interop.LogFont font)
|
||||||
|
{
|
||||||
|
Control.Font = Font.FromLogFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IntPtr Handle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
{
|
||||||
|
return Control.Handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetParentHandle(IntPtr handle)
|
||||||
|
{
|
||||||
|
HandlerNativeMethods.SetParent(Control.Handle, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
~WinFormsPreviewHandler()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && Control != null)
|
||||||
|
{
|
||||||
|
Control.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
186
ShellExtensions/PreviewHandlers/WpfPreviewHandler.cs
Normal file
186
ShellExtensions/PreviewHandlers/WpfPreviewHandler.cs
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
#if PREVIEW_HANDLER
|
||||||
|
using ShellExtensions.Interop;
|
||||||
|
using ShellExtensions.Interop.Common;
|
||||||
|
using ShellExtensions.Resources;
|
||||||
|
using System;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Interop;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace ShellExtensions.PreviewHandlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the base class for all WPF-based preview handlers and provides their basic functionality.
|
||||||
|
/// To create a custom preview handler that contains a WPF user control,
|
||||||
|
/// a class must derive from this, use the <typeparamref name="PreviewHandlerAttribute"/>,
|
||||||
|
/// and implement 1 or more of the following interfaces:
|
||||||
|
/// <typeparamref name="IPreviewFromStream"/>,
|
||||||
|
/// <typeparamref name="IPreviewFromShellObject"/>,
|
||||||
|
/// <typeparamref name="IPreviewFromFile"/>.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class WpfPreviewHandler : PreviewHandler, IDisposable
|
||||||
|
{
|
||||||
|
HwndSource _source = null;
|
||||||
|
private IntPtr _parentHandle = IntPtr.Zero;
|
||||||
|
private NativeRect _bounds;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This control must be populated by the deriving class before the preview is shown.
|
||||||
|
/// </summary>
|
||||||
|
public UserControl Control { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Throws an exception if the Control property has not been populated.
|
||||||
|
/// </summary>
|
||||||
|
protected void ThrowIfNoControl()
|
||||||
|
{
|
||||||
|
if (Control == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(LocalizedMessages.PreviewHandlerControlNotInitialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the placement of the Control.
|
||||||
|
/// </summary>
|
||||||
|
protected void UpdatePlacement()
|
||||||
|
{
|
||||||
|
if (_source != null)
|
||||||
|
{
|
||||||
|
HandlerNativeMethods.SetParent(_source.Handle, _parentHandle);
|
||||||
|
|
||||||
|
HandlerNativeMethods.SetWindowPos(_source.Handle, new IntPtr((int)SetWindowPositionInsertAfter.Top),
|
||||||
|
0, 0, Math.Abs(_bounds.Left - _bounds.Right), Math.Abs(_bounds.Top - _bounds.Bottom), SetWindowPositionOptions.ShowWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetParentHandle(IntPtr handle)
|
||||||
|
{
|
||||||
|
_parentHandle = handle;
|
||||||
|
UpdatePlacement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
if (_source == null)
|
||||||
|
{
|
||||||
|
ThrowIfNoControl();
|
||||||
|
|
||||||
|
HwndSourceParameters p = new HwndSourceParameters
|
||||||
|
{
|
||||||
|
WindowStyle = (int)(WindowStyles.Child | WindowStyles.Visible | WindowStyles.ClipSiblings),
|
||||||
|
ParentWindow = _parentHandle,
|
||||||
|
Width = Math.Abs(_bounds.Left - _bounds.Right),
|
||||||
|
Height = Math.Abs(_bounds.Top - _bounds.Bottom)
|
||||||
|
};
|
||||||
|
|
||||||
|
_source = new HwndSource(p);
|
||||||
|
_source.CompositionTarget.BackgroundColor = Brushes.WhiteSmoke.Color;
|
||||||
|
_source.RootVisual = (Visual)Control.Content;
|
||||||
|
}
|
||||||
|
UpdatePlacement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IntPtr Handle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
{
|
||||||
|
if (_source == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(LocalizedMessages.WpfPreviewHandlerNoHandle);
|
||||||
|
}
|
||||||
|
return _source.Handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateBounds(NativeRect bounds)
|
||||||
|
{
|
||||||
|
_bounds = bounds;
|
||||||
|
UpdatePlacement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void HandleInitializeException(Exception caughtException)
|
||||||
|
{
|
||||||
|
if (caughtException == null) { return; }
|
||||||
|
|
||||||
|
TextBox text = new TextBox
|
||||||
|
{
|
||||||
|
IsReadOnly = true,
|
||||||
|
MaxLines = 20,
|
||||||
|
Text = caughtException.ToString()
|
||||||
|
};
|
||||||
|
Control = new UserControl() { Content = text };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetFocus()
|
||||||
|
{
|
||||||
|
Control.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetBackground(int argb)
|
||||||
|
{
|
||||||
|
Control.Background = new SolidColorBrush(Color.FromArgb(
|
||||||
|
(byte)((argb >> 24) & 0xFF), //a
|
||||||
|
(byte)((argb >> 16) & 0xFF), //r
|
||||||
|
(byte)((argb >> 8) & 0xFF), //g
|
||||||
|
(byte)(argb & 0xFF))); //b
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetForeground(int argb)
|
||||||
|
{
|
||||||
|
Control.Foreground = new SolidColorBrush(Color.FromArgb(
|
||||||
|
(byte)((argb >> 24) & 0xFF), //a
|
||||||
|
(byte)((argb >> 16) & 0xFF), //r
|
||||||
|
(byte)((argb >> 8) & 0xFF), //g
|
||||||
|
(byte)(argb & 0xFF))); //b
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetFont(LogFont font)
|
||||||
|
{
|
||||||
|
if (font == null) { throw new ArgumentNullException(nameof(font)); }
|
||||||
|
|
||||||
|
Control.FontFamily = new FontFamily(font.FaceName);
|
||||||
|
Control.FontSize = font.Height;
|
||||||
|
Control.FontWeight = font.Weight > 0 && font.Weight < 1000 ?
|
||||||
|
System.Windows.FontWeight.FromOpenTypeWeight(font.Weight) :
|
||||||
|
System.Windows.FontWeights.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Preview handler control finalizer
|
||||||
|
/// </summary>
|
||||||
|
~WpfPreviewHandler()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes the control
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides means to dispose the object.
|
||||||
|
/// When overriden, it is imperative that base.Dispose(true) is called within the implementation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"></param>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && _source != null)
|
||||||
|
{
|
||||||
|
_source.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -2,12 +2,22 @@
|
|||||||
{
|
{
|
||||||
internal sealed class LocalizedMessages
|
internal sealed class LocalizedMessages
|
||||||
{
|
{
|
||||||
|
#if PREVIEW_HANDLER
|
||||||
|
public const string PreviewHandlerControlNotInitialized = "Control has not yet been assigned. Methods requiring it cannot be called.";
|
||||||
|
public const string PreviewHandlerInterfaceNotImplemented = "{0} must implement one or more of IPreviewFromStream, IPreviewFromShellObject or IPreviewFromFile.";
|
||||||
|
public const string PreviewHandlerInvalidAttributes = "PreviewHandler '{0}' must have exactly one PreviewHandler attribute.";
|
||||||
|
public const string PreviewHandlerUnsupportedInterfaceCalled = "Unable to call interface {0} because it is not supported on this object.";
|
||||||
|
public const string WpfPreviewHandlerNoHandle = "Cannot retrieve handle because proxy window has not been created.";
|
||||||
|
#endif
|
||||||
|
|
||||||
public const string StorageStreamBufferOverflow = "The sum of offset and count must be less than or equal to the size of the buffer.";
|
public const string StorageStreamBufferOverflow = "The sum of offset and count must be less than or equal to the size of the buffer.";
|
||||||
public const string StorageStreamCountLessThanZero = "Count must be greater than or equal to zero.";
|
public const string StorageStreamCountLessThanZero = "Count must be greater than or equal to zero.";
|
||||||
public const string StorageStreamIsReadonly = "The stream was initialized as read-only.";
|
public const string StorageStreamIsReadonly = "The stream was initialized as read-only.";
|
||||||
public const string StorageStreamOffsetLessThanZero = "Offset must be greater than or equal to zero.";
|
public const string StorageStreamOffsetLessThanZero = "Offset must be greater than or equal to zero.";
|
||||||
|
|
||||||
|
#if THUMBNAIL
|
||||||
public const string ThumbnailProviderDisabledProcessIsolation = "{0} does not implement IThumbnailFromStream and so requires DisableProcessIsolation set to true.";
|
public const string ThumbnailProviderDisabledProcessIsolation = "{0} does not implement IThumbnailFromStream and so requires DisableProcessIsolation set to true.";
|
||||||
public const string ThumbnailProviderInterfaceNotImplemented = "{0} must implement one or more of IThumbnailFromStream, IThumbnailFromShellObject or IThumbnailFromFile.";
|
public const string ThumbnailProviderInterfaceNotImplemented = "{0} must implement one or more of IThumbnailFromStream, IThumbnailFromShellObject or IThumbnailFromFile.";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,14 @@
|
|||||||
<Import_RootNamespace>ShellExtensions</Import_RootNamespace>
|
<Import_RootNamespace>ShellExtensions</Import_RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Interop\HandlerNativeMethods.cs" />
|
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Interop\Common\ShellNativeStructs.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Interop\Common\ShellNativeStructs.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)Interop\HandlerNativeMethods.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)Interop\Common\ShellNativeEnums.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)PreviewHandlers\ManagedInitializationInterfaces.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)PreviewHandlers\PreviewHandler.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)PreviewHandlers\PreviewHandlerAttribute.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)PreviewHandlers\WinFormsPreviewHandler.cs" />
|
||||||
|
<Compile Include="$(MSBuildThisFileDirectory)PreviewHandlers\WpfPreviewHandler.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)Resources\LocalizedMessages.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)Resources\LocalizedMessages.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)StorageStream.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)StorageStream.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)ThumbnailProviders\ManagedInitializationInterfaces.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)ThumbnailProviders\ManagedInitializationInterfaces.cs" />
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Drawing;
|
#if THUMBNAIL
|
||||||
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace ShellExtensions
|
namespace ShellExtensions
|
||||||
@ -52,3 +53,4 @@ namespace ShellExtensions
|
|||||||
Bitmap ConstructBitmap(FileInfo info, int sideSize);
|
Bitmap ConstructBitmap(FileInfo info, int sideSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Win32;
|
#if THUMBNAIL
|
||||||
|
using Microsoft.Win32;
|
||||||
using ShellExtensions.Interop;
|
using ShellExtensions.Interop;
|
||||||
using ShellExtensions.Interop.Common;
|
using ShellExtensions.Interop.Common;
|
||||||
using ShellExtensions.Resources;
|
using ShellExtensions.Resources;
|
||||||
@ -280,3 +281,4 @@ namespace ShellExtensions
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
#if THUMBNAIL
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace ShellExtensions
|
namespace ShellExtensions
|
||||||
{
|
{
|
||||||
@ -134,3 +135,4 @@ namespace ShellExtensions
|
|||||||
VideoSprockets = 3
|
VideoSprockets = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user