add preview handler

This commit is contained in:
2021-12-28 16:53:45 +08:00
parent 0f48dbe845
commit c03de86d02
14 changed files with 1613 additions and 91 deletions

View 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
}

View File

@ -1,125 +1,280 @@
using System;
#if PREVIEW_HANDLER
using System;
using System.Runtime.InteropServices;
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.
/// Wraps the native Windows MSG structure.
/// </summary>
[Flags]
public enum AccessModes
public struct Message
{
/// <summary>
/// Indicates that, in direct mode, each change to a storage
/// or stream element is written as it occurs.
/// Gets the window handle
/// </summary>
Direct = 0x00000000,
public IntPtr WindowHandle { get; }
/// <summary>
/// Indicates that, in transacted mode, changes are buffered
/// and written only if an explicit commit operation is called.
/// Gets the window message
/// </summary>
Transacted = 0x00010000,
public uint Msg { get; }
/// <summary>
/// Provides a faster implementation of a compound file
/// in a limited, but frequently used, case.
/// Gets the WParam
/// </summary>
Simple = 0x08000000,
public IntPtr WParam { get; }
/// <summary>
/// Indicates that the object is read-only,
/// meaning that modifications cannot be made.
/// Gets the LParam
/// </summary>
Read = 0x00000000,
public IntPtr LParam { get; }
/// <summary>
/// Enables you to save changes to the object,
/// but does not permit access to its data.
/// Gets the time
/// </summary>
Write = 0x00000001,
public int Time { get; }
/// <summary>
/// Enables access and modification of object data.
/// Gets the point
/// </summary>
ReadWrite = 0x00000002,
public NativePoint Point { get; }
/// <summary>
/// Specifies that subsequent openings of the object are
/// not denied read or write access.
/// Creates a new instance of the Message struct
/// </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>
/// Prevents others from subsequently opening the object in Read mode.
/// Determines if two messages are equal.
/// </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>
/// Prevents others from subsequently opening the object
/// for Write or ReadWrite access.
/// Determines if two messages are not equal.
/// </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>
/// Prevents others from subsequently opening the object in any mode.
/// Determines if this message is equal to another.
/// </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>
/// Opens the storage object with exclusive access to the most
/// recently committed version.
/// Gets a hash code for the message.
/// </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>
/// A wrapper for the native POINT structure.
/// </summary>
[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>
/// 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.
/// The X coordinate of the point
/// </summary>
DeleteOnRelease = 0x04000000,
public int X { get; set; }
/// <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.
/// The Y coordinate of the point
/// </summary>
NoScratch = 0x00100000,
public int Y { get; set; }
/// <summary>
/// Indicates that an existing storage object
/// or stream should be removed before the new object replaces it.
/// Determines if two NativePoints are equal.
/// </summary>
Create = 0x00001000,
/// <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>
/// Creates the new object while preserving existing data in a stream named "Contents".
/// Determines if two NativePoints are not equal.
/// </summary>
Convert = 0x00020000,
/// <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>
/// Causes the create operation to fail if an existing object with the specified name exists.
/// Determines if this NativePoint is equal to another.
/// </summary>
FailIfThere = 0x00000000,
/// <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>
/// 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.
/// Gets a hash code for the NativePoint.
/// </summary>
NoSnapshot = 0x00200000,
/// <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>
/// Supports direct mode for single-writer, multireader file operations.
/// Position of top edge
/// </summary>
DirectSingleWriterMultipleReader = 0x00400000
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