Skip to content

Commit 0b57e52

Browse files
committed
Wpf.Example - Add Windows 10 Only VirtualKeyboard example
Change App.xaml StartupUri to TouchKeyboardWin10MainWindow.xaml Imported WPF example code from https://github.com/Microsoft/WPF-Samples/tree/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier
1 parent cddece0 commit 0b57e52

File tree

6 files changed

+279
-0
lines changed

6 files changed

+279
-0
lines changed

CefSharp.Wpf.Example/CefSharp.Wpf.Example.csproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@
109109
<Compile Include="Controls\CefSharpCommands.cs" />
110110
<Compile Include="Controls\ChromiumWebBrowserWithScreenshotSupport.cs" />
111111
<Compile Include="Controls\NonReloadingTabControl.cs" />
112+
<Compile Include="Controls\TouchKeyboard\InputPaneRcw.cs" />
113+
<Compile Include="Controls\TouchKeyboard\TouchKeyboardEventManager.cs" />
112114
<Compile Include="Handlers\AccessibilityHandler.cs" />
113115
<Compile Include="Handlers\DisplayHandler.cs" />
114116
<Compile Include="Handlers\DragHandler.cs" />
@@ -117,6 +119,9 @@
117119
<Compile Include="Handlers\RequestContextHandler.cs" />
118120
<Compile Include="Handlers\WpfBrowserProcessHandler.cs" />
119121
<Compile Include="Program.cs" />
122+
<Compile Include="TouchKeyboardWin10MainWindow.xaml.cs">
123+
<DependentUpon>TouchKeyboardWin10MainWindow.xaml</DependentUpon>
124+
</Compile>
120125
<Compile Include="SimpleMainWindow.xaml.cs">
121126
<DependentUpon>SimpleMainWindow.xaml</DependentUpon>
122127
</Compile>
@@ -139,6 +144,10 @@
139144
<DependentUpon>MainWindow.xaml</DependentUpon>
140145
<SubType>Code</SubType>
141146
</Compile>
147+
<Page Include="TouchKeyboardWin10MainWindow.xaml">
148+
<Generator>MSBuild:Compile</Generator>
149+
<SubType>Designer</SubType>
150+
</Page>
142151
<Page Include="SimpleMainWindow.xaml">
143152
<SubType>Designer</SubType>
144153
<Generator>MSBuild:Compile</Generator>
@@ -161,6 +170,7 @@
161170
<ItemGroup>
162171
<None Include="app.config" />
163172
<None Include="app.manifest" />
173+
<None Include="Controls\TouchKeyboard\Readme.md" />
164174
<None Include="crash_reporter.cfg">
165175
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
166176
</None>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
2+
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
3+
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
4+
// PARTICULAR PURPOSE.
5+
//
6+
// Copyright (c) Microsoft Corporation. All rights reserved
7+
8+
using System;
9+
using System.Runtime.CompilerServices;
10+
using System.Runtime.InteropServices;
11+
12+
namespace Microsoft.Windows.Input.TouchKeyboard.Rcw
13+
{
14+
/// <summary>
15+
/// Contains internal RCWs for invoking the InputPane (tiptsf touch keyboard)
16+
/// </summary>
17+
/// <remarks>
18+
/// Adapted from https://github.com/Microsoft/WPF-Samples/blob/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier/InputPaneRcw.cs
19+
/// Licensed under an MIT license see https://github.com/Microsoft/WPF-Samples/blob/master/LICENSE
20+
/// </remarks>
21+
internal static class InputPaneRcw
22+
{
23+
internal enum TrustLevel
24+
{
25+
BaseTrust,
26+
PartialTrust,
27+
FullTrust
28+
}
29+
30+
[Guid("75CF2C57-9195-4931-8332-F0B409E916AF"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
31+
[ComImport]
32+
internal interface IInputPaneInterop
33+
{
34+
[MethodImpl(MethodImplOptions.InternalCall)]
35+
void GetIids(out uint iidCount, [MarshalAs(UnmanagedType.LPStruct)] out Guid iids);
36+
37+
[MethodImpl(MethodImplOptions.InternalCall)]
38+
void GetRuntimeClassName([MarshalAs(UnmanagedType.BStr)] out string className);
39+
40+
[MethodImpl(MethodImplOptions.InternalCall)]
41+
void GetTrustLevel(out TrustLevel TrustLevel);
42+
43+
[MethodImpl(MethodImplOptions.InternalCall)]
44+
IInputPane2 GetForWindow([In] IntPtr appWindow, [In] ref Guid riid);
45+
}
46+
47+
[Guid("8A6B3F26-7090-4793-944C-C3F2CDE26276"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
48+
[ComImport]
49+
internal interface IInputPane2
50+
{
51+
[MethodImpl(MethodImplOptions.InternalCall)]
52+
void GetIids(out uint iidCount, [MarshalAs(UnmanagedType.LPStruct)] out Guid iids);
53+
54+
[MethodImpl(MethodImplOptions.InternalCall)]
55+
void GetRuntimeClassName([MarshalAs(UnmanagedType.BStr)] out string className);
56+
57+
[MethodImpl(MethodImplOptions.InternalCall)]
58+
void GetTrustLevel(out TrustLevel TrustLevel);
59+
60+
[MethodImpl(MethodImplOptions.InternalCall)]
61+
bool TryShow();
62+
63+
[MethodImpl(MethodImplOptions.InternalCall)]
64+
bool TryHide();
65+
}
66+
}
67+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Code in this folder is adapted from https://github.com/Microsoft/WPF-Samples/tree/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier
2+
3+
Licensed under an MIT license, see https://github.com/Microsoft/WPF-Samples/blob/master/LICENSE
4+
5+
The files aren't included in the .csproj file intentially as they require the Windows 10 SDK
6+
7+
It is reccomended that you obtain and use the https://github.com/Microsoft/WPF-Samples/tree/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier
8+
solution provided by Microsoft. It has more advanced features including TouchKeyboardAwareDecorator, which can be used
9+
to resize your window when the touch keyboard is visible. Please read https://github.com/Microsoft/WPF-Samples/blob/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier/Readme.md
10+
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
2+
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
3+
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
4+
// PARTICULAR PURPOSE.
5+
//
6+
// Copyright (c) Microsoft Corporation. All rights reserved
7+
8+
using System;
9+
using System.Runtime.InteropServices;
10+
using System.Runtime.InteropServices.WindowsRuntime;
11+
using static Microsoft.Windows.Input.TouchKeyboard.Rcw.InputPaneRcw;
12+
13+
namespace Microsoft.Windows.Input.TouchKeyboard
14+
{
15+
/// <summary>
16+
/// Provides Win10 Touch Keyboard - Show/Hide
17+
/// NOTE: Documentation suggests Win10 SDK is required to compile this.
18+
/// https://github.com/Microsoft/WPF-Samples/blob/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier/Readme.md
19+
/// </summary>
20+
/// <remarks>
21+
/// Adapted from https://github.com/Microsoft/WPF-Samples/blob/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier/TouchKeyboardEventManager.cs
22+
/// Licensed under an MIT license see https://github.com/Microsoft/WPF-Samples/blob/master/LICENSE
23+
/// </remarks>
24+
[CLSCompliant(true)]
25+
internal class TouchKeyboardEventManager : IDisposable
26+
{
27+
private const string InputPaneTypeName = "Windows.UI.ViewManagement.InputPane, Windows, ContentType=WindowsRuntime";
28+
/// <summary>
29+
/// The WinRT InputPane type.
30+
/// </summary>
31+
private readonly Type inputPaneType = null;
32+
33+
private IInputPaneInterop inputPaneInterop = null;
34+
35+
private IInputPane2 inputPanel = null;
36+
37+
private bool disposed = false;
38+
39+
/// <summary>
40+
/// Indicates if calling the touch keyboard is supported
41+
/// </summary>
42+
private readonly bool touchKeyboardSupported = false;
43+
44+
/// <summary>
45+
/// TouchKeyboardEventManager
46+
/// </summary>
47+
/// <param name="handle">Need the HWND for the native interop call into IInputPaneInterop</param>
48+
internal TouchKeyboardEventManager(IntPtr handle)
49+
{
50+
inputPaneType = Type.GetType(InputPaneTypeName);
51+
52+
// Get and cast an InputPane COM instance
53+
inputPaneInterop = WindowsRuntimeMarshal.GetActivationFactory(inputPaneType) as IInputPaneInterop;
54+
55+
touchKeyboardSupported = inputPaneInterop != null;
56+
57+
if (touchKeyboardSupported)
58+
{
59+
// Get the actual input pane for this HWND
60+
inputPanel = inputPaneInterop.GetForWindow(handle, typeof(IInputPane2).GUID);
61+
}
62+
}
63+
64+
/// <summary>
65+
/// Returns an instance of the InputPane
66+
/// </summary>
67+
/// <returns>The InputPane</returns>
68+
internal IInputPane2 GetInputPane()
69+
{
70+
if (!touchKeyboardSupported)
71+
{
72+
throw new PlatformNotSupportedException("Native access to touch keyboard APIs not supported on this OS!");
73+
}
74+
75+
return inputPanel;
76+
}
77+
78+
protected virtual void Dispose(bool disposing)
79+
{
80+
if (!disposed)
81+
{
82+
if (disposing)
83+
{
84+
if (inputPanel != null)
85+
{
86+
Marshal.FinalReleaseComObject(inputPanel);
87+
88+
inputPanel = null;
89+
}
90+
91+
if (inputPaneInterop != null)
92+
{
93+
Marshal.FinalReleaseComObject(inputPaneInterop);
94+
95+
inputPaneInterop = null;
96+
}
97+
}
98+
}
99+
100+
disposed = true;
101+
}
102+
103+
// This code added to correctly implement the disposable pattern.
104+
public void Dispose()
105+
{
106+
Dispose(true);
107+
}
108+
}
109+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Window x:Class="CefSharp.Wpf.Example.TouchKeyboardWin10MainWindow"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
5+
Title="SimpleMainWindow" WindowState="Maximized">
6+
<Grid>
7+
<Grid.RowDefinitions>
8+
<RowDefinition />
9+
<RowDefinition Height="Auto" />
10+
</Grid.RowDefinitions>
11+
<wpf:ChromiumWebBrowser Grid.Row="0"
12+
x:Name="Browser"
13+
Address="http://www.google.com"/>
14+
<StatusBar Grid.Row="1">
15+
<ProgressBar HorizontalAlignment="Right"
16+
IsIndeterminate="{Binding WebBrowser.IsLoading}"
17+
Width="100"
18+
Height="16"
19+
Margin="3" />
20+
<Separator />
21+
<!-- TODO: Could show hover link URL here -->
22+
<TextBlock />
23+
</StatusBar>
24+
</Grid>
25+
</Window>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright © 2019 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
using System.Windows;
6+
using CefSharp.Enums;
7+
using Microsoft.Windows.Input.TouchKeyboard;
8+
9+
namespace CefSharp.Wpf.Example
10+
{
11+
/// <summary>
12+
/// TouchKeyboardWin10MainWindow provides a very basic Windows 10 only example of
13+
/// showing the onscreen(virtual) keyboard in a WPF app.
14+
/// </summary>
15+
public partial class TouchKeyboardWin10MainWindow : Window
16+
{
17+
private TouchKeyboardEventManager touchKeyboardEventManager;
18+
19+
public TouchKeyboardWin10MainWindow()
20+
{
21+
InitializeComponent();
22+
23+
Browser.VirtualKeyboardRequested += BrowserVirtualKeyboardRequested;
24+
Browser.IsBrowserInitializedChanged += BrowserIsBrowserInitializedChanged;
25+
}
26+
27+
private void BrowserIsBrowserInitializedChanged(object sender, DependencyPropertyChangedEventArgs e)
28+
{
29+
if ((bool)e.NewValue)
30+
{
31+
var browserHost = Browser.GetBrowserHost();
32+
33+
touchKeyboardEventManager = new TouchKeyboardEventManager(browserHost.GetWindowHandle());
34+
}
35+
else
36+
{
37+
if (touchKeyboardEventManager != null)
38+
{
39+
touchKeyboardEventManager.Dispose();
40+
}
41+
}
42+
}
43+
44+
private void BrowserVirtualKeyboardRequested(object sender, VirtualKeyboardRequestedEventArgs e)
45+
{
46+
var inputPane = touchKeyboardEventManager.GetInputPane();
47+
48+
if (e.TextInputMode == TextInputMode.None)
49+
{
50+
inputPane.TryHide();
51+
}
52+
else
53+
{
54+
inputPane.TryShow();
55+
}
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)