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