add preview handler
This commit is contained in:
		| @@ -18,7 +18,7 @@ | ||||
|     <DebugType>full</DebugType> | ||||
|     <Optimize>false</Optimize> | ||||
|     <OutputPath>bin\Debug\</OutputPath> | ||||
|     <DefineConstants>DEBUG;TRACE</DefineConstants> | ||||
|     <DefineConstants>TRACE;DEBUG;THUMBNAIL</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||
| @@ -27,7 +27,7 @@ | ||||
|     <DebugType>pdbonly</DebugType> | ||||
|     <Optimize>true</Optimize> | ||||
|     <OutputPath>bin\Release\</OutputPath> | ||||
|     <DefineConstants>TRACE</DefineConstants> | ||||
|     <DefineConstants>TRACE;THUMBNAIL</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||
| @@ -46,7 +46,6 @@ | ||||
|     <Reference Include="System.Data.DataSetExtensions" /> | ||||
|     <Reference Include="Microsoft.CSharp" /> | ||||
|     <Reference Include="System.Data" /> | ||||
|     <Reference Include="System.Net.Http" /> | ||||
|     <Reference Include="System.Xml" /> | ||||
|   </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 | ||||
| { | ||||
|  | ||||
|     /// <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, | ||||
|  | ||||
|         /// <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 | ||||
|         /// <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> | ||||
|         /// The X coordinate of the point | ||||
|         /// </summary> | ||||
|         public int X { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The Y coordinate of the point | ||||
|         /// </summary> | ||||
|         public int Y { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Determines if two NativePoints are equal. | ||||
|         /// </summary> | ||||
|         /// <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> | ||||
|         /// Determines if two NativePoints are not equal. | ||||
|         /// </summary> | ||||
|         /// <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> | ||||
|         /// Determines if this NativePoint is equal to another. | ||||
|         /// </summary> | ||||
|         /// <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> | ||||
|         /// Gets a hash code for the NativePoint. | ||||
|         /// </summary> | ||||
|         /// <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 | ||||
|     { | ||||
| #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"); | ||||
| #endif | ||||
|  | ||||
|         internal static readonly Guid IInitializeWithFileGuid = new Guid("b7d14566-0509-4cce-a71f-0a554233bd9b"); | ||||
|         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"); | ||||
|     } | ||||
|  | ||||
|     #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> | ||||
|     /// Provides means by which to initialize with a file. | ||||
|     /// </summary> | ||||
| @@ -67,6 +70,26 @@ namespace ShellExtensions.Interop | ||||
|         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 | ||||
|  | ||||
|     // <summary> | ||||
| @@ -89,4 +112,178 @@ namespace ShellExtensions.Interop | ||||
|         /// </summary> | ||||
|         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 | ||||
|     { | ||||
| #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 StorageStreamCountLessThanZero = "Count must be greater than or equal to zero."; | ||||
|         public const string StorageStreamIsReadonly = "The stream was initialized as read-only."; | ||||
|         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 ThumbnailProviderInterfaceNotImplemented = "{0} must implement one or more of IThumbnailFromStream, IThumbnailFromShellObject or IThumbnailFromFile."; | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,8 +9,14 @@ | ||||
|     <Import_RootNamespace>ShellExtensions</Import_RootNamespace> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Compile Include="$(MSBuildThisFileDirectory)Interop\HandlerNativeMethods.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)StorageStream.cs" /> | ||||
|     <Compile Include="$(MSBuildThisFileDirectory)ThumbnailProviders\ManagedInitializationInterfaces.cs" /> | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System.Drawing; | ||||
| #if THUMBNAIL | ||||
| using System.Drawing; | ||||
| using System.IO; | ||||
|  | ||||
| namespace ShellExtensions | ||||
| @@ -52,3 +53,4 @@ namespace ShellExtensions | ||||
|         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.Common; | ||||
| using ShellExtensions.Resources; | ||||
| @@ -280,3 +281,4 @@ namespace ShellExtensions | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System; | ||||
| #if THUMBNAIL | ||||
| using System; | ||||
|  | ||||
| namespace ShellExtensions | ||||
| { | ||||
| @@ -134,3 +135,4 @@ namespace ShellExtensions | ||||
|         VideoSprockets = 3 | ||||
|     } | ||||
| } | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user