Skip to content

Commit 2163d64

Browse files
authored
Feature: Added support for previewing Office files (#13096)
1 parent bc446d0 commit 2163d64

File tree

13 files changed

+2212
-6
lines changed

13 files changed

+2212
-6
lines changed

src/Files.App/Files.App.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- Copyright (c) 2023 Files Community. Licensed under the MIT License. See the LICENSE. -->
1+
<!-- Copyright (c) 2023 Files Community. Licensed under the MIT License. See the LICENSE. -->
22
<Project Sdk="Microsoft.NET.Sdk">
33

44
<PropertyGroup>
@@ -77,6 +77,7 @@
7777
<ItemGroup>
7878
<PackageReference Include="ByteSize" Version="2.1.1" />
7979
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
80+
<PackageReference Include="DirectNCore" Version="1.13.2.1" />
8081
<PackageReference Include="DiscUtils.Udf" Version="0.16.13" />
8182
<PackageReference Include="FluentFTP" Version="43.0.1" />
8283
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />
@@ -97,6 +98,7 @@
9798
<PackageReference Include="CommunityToolkit.WinUI.UI.Behaviors" Version="7.1.2" />
9899
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" />
99100
<PackageReference Include="Tulpep.ActiveDirectoryObjectPicker" Version="3.0.11" />
101+
<PackageReference Include="Vanara.PInvoke.DwmApi" Version="3.4.15" />
100102
<PackageReference Include="Vanara.Windows.Extensions" Version="3.4.16" />
101103
<PackageReference Include="WinUIEx" Version="2.1.0" />
102104
<PackageReference Include="Vanara.PInvoke.Mpr" Version="3.4.16" />

src/Files.App/Helpers/Interop/InteropHelpers.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using Microsoft.UI.Xaml;
66
using System.Reflection;
77
using System.Runtime.InteropServices;
8+
using Vanara.PInvoke;
9+
using static Vanara.PInvoke.User32;
810

911
namespace Files.App.Helpers
1012
{
@@ -51,6 +53,20 @@ public static void ChangeCursor(this UIElement uiElement, InputCursor cursor)
5153
new object[] { cursor }
5254
);
5355
}
56+
57+
[DllImport(Lib.User32, SetLastError = true, EntryPoint = "SetWindowLong")]
58+
private static extern int SetWindowLongPtr32(HWND hWnd, WindowLongFlags nIndex, IntPtr dwNewLong);
59+
60+
[DllImport(Lib.User32, SetLastError = true, EntryPoint = "SetWindowLongPtr")]
61+
private static extern IntPtr SetWindowLongPtr64(HWND hWnd, WindowLongFlags nIndex, IntPtr dwNewLong);
62+
63+
public static IntPtr SetWindowLong(HWND hWnd, WindowLongFlags nIndex, IntPtr dwNewLong)
64+
{
65+
if (IntPtr.Size == 4)
66+
return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
67+
else
68+
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
69+
}
5470
}
5571

5672
[ComImport]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<UserControl
3+
x:Class="Files.App.UserControls.FilePreviews.ShellPreview"
4+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:local="using:Files.App.UserControls.FilePreviews"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
Unloaded="PreviewHost_Unloaded"
10+
mc:Ignorable="d">
11+
12+
<ContentPresenter
13+
Name="contentPresenter"
14+
Background="Transparent"
15+
Loaded="PreviewHost_Loaded"
16+
PointerEntered="PreviewHost_PointerEntered"
17+
SizeChanged="PreviewHost_SizeChanged" />
18+
</UserControl>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using Files.App.ViewModels.Previews;
2+
using Microsoft.UI.Xaml;
3+
using Microsoft.UI.Xaml.Controls;
4+
using Vanara.PInvoke;
5+
using Windows.Foundation;
6+
7+
namespace Files.App.UserControls.FilePreviews
8+
{
9+
public sealed partial class ShellPreview : UserControl
10+
{
11+
private ShellPreviewViewModel ViewModel { get; set; }
12+
13+
public ShellPreview(ShellPreviewViewModel model)
14+
{
15+
ViewModel = model;
16+
this.InitializeComponent();
17+
}
18+
19+
private void PreviewHost_Loaded(object sender, RoutedEventArgs e)
20+
{
21+
ViewModel.LoadPreview(contentPresenter);
22+
ViewModel.SizeChanged(GetPreviewSize());
23+
if (XamlRoot.Content is FrameworkElement element)
24+
{
25+
element.SizeChanged += PreviewHost_SizeChanged;
26+
element.PointerEntered += PreviewHost_PointerEntered;
27+
}
28+
}
29+
30+
private void PreviewHost_SizeChanged(object sender, SizeChangedEventArgs e)
31+
{
32+
ViewModel.SizeChanged(GetPreviewSize());
33+
}
34+
35+
private RECT GetPreviewSize()
36+
{
37+
var source = contentPresenter.TransformToVisual(XamlRoot.Content);
38+
var physicalSize = contentPresenter.RenderSize;
39+
var physicalPos = source.TransformPoint(new Point(0, 0));
40+
var scale = XamlRoot.RasterizationScale;
41+
var result = new RECT();
42+
result.Left = (int)(physicalPos.X * scale + 0.5);
43+
result.Top = (int)(physicalPos.Y * scale + 0.5);
44+
result.Width = (int)(physicalSize.Width * scale + 0.5);
45+
result.Height = (int)(physicalSize.Height * scale + 0.5);
46+
return result;
47+
}
48+
49+
private void PreviewHost_Unloaded(object sender, RoutedEventArgs e)
50+
{
51+
if (XamlRoot.Content is FrameworkElement element)
52+
{
53+
element.SizeChanged -= PreviewHost_SizeChanged;
54+
element.PointerEntered -= PreviewHost_PointerEntered;
55+
}
56+
ViewModel.UnloadPreview();
57+
}
58+
59+
private void PreviewHost_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
60+
{
61+
ViewModel.PointerEntered(sender == contentPresenter);
62+
}
63+
}
64+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using Vanara.PInvoke;
4+
5+
namespace Files.App.Utils.Shell
6+
{
7+
public static class ItemStreamHelper
8+
{
9+
[DllImport("shlwapi.dll", CallingConvention = CallingConvention.StdCall, PreserveSig = true, CharSet = CharSet.Unicode)]
10+
static extern HRESULT SHCreateStreamOnFileEx(string pszFile, STGM grfMode, uint dwAttributes, uint fCreate, IntPtr pstmTemplate, out IntPtr ppstm);
11+
12+
[DllImport("shell32.dll", CallingConvention = CallingConvention.StdCall, PreserveSig = true, CharSet = CharSet.Unicode)]
13+
static extern HRESULT SHCreateItemFromParsingName(string pszPath, IntPtr pbc, ref Guid riid, out IntPtr ppv);
14+
15+
static readonly Guid IShellItemIid = Guid.ParseExact("43826d1e-e718-42ee-bc55-a1e261c37bfe", "d");
16+
17+
public static IntPtr IShellItemFromPath(string path)
18+
{
19+
IntPtr psi;
20+
Guid iid = IShellItemIid;
21+
var hr = SHCreateItemFromParsingName(path, IntPtr.Zero, ref iid, out psi);
22+
if ((int)hr < 0)
23+
return IntPtr.Zero;
24+
return psi;
25+
}
26+
27+
public static IntPtr IStreamFromPath(string path)
28+
{
29+
IntPtr pstm;
30+
var hr = SHCreateStreamOnFileEx(path,
31+
STGM.STGM_READ | STGM.STGM_FAILIFTHERE | STGM.STGM_SHARE_DENY_NONE,
32+
0, 0, IntPtr.Zero, out pstm);
33+
if ((int)hr < 0)
34+
return IntPtr.Zero;
35+
return pstm;
36+
}
37+
38+
public static void ReleaseObject(IntPtr obj)
39+
{
40+
Marshal.Release(obj);
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)