Skip to content

Commit

Permalink
Wpf.Example - Add Windows 10 Only VirtualKeyboard example
Browse files Browse the repository at this point in the history
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
  • Loading branch information
amaitland committed Apr 6, 2019
1 parent cddece0 commit 0b57e52
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 0 deletions.
10 changes: 10 additions & 0 deletions CefSharp.Wpf.Example/CefSharp.Wpf.Example.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@
<Compile Include="Controls\CefSharpCommands.cs" />
<Compile Include="Controls\ChromiumWebBrowserWithScreenshotSupport.cs" />
<Compile Include="Controls\NonReloadingTabControl.cs" />
<Compile Include="Controls\TouchKeyboard\InputPaneRcw.cs" />
<Compile Include="Controls\TouchKeyboard\TouchKeyboardEventManager.cs" />
<Compile Include="Handlers\AccessibilityHandler.cs" />
<Compile Include="Handlers\DisplayHandler.cs" />
<Compile Include="Handlers\DragHandler.cs" />
Expand All @@ -117,6 +119,9 @@
<Compile Include="Handlers\RequestContextHandler.cs" />
<Compile Include="Handlers\WpfBrowserProcessHandler.cs" />
<Compile Include="Program.cs" />
<Compile Include="TouchKeyboardWin10MainWindow.xaml.cs">
<DependentUpon>TouchKeyboardWin10MainWindow.xaml</DependentUpon>
</Compile>
<Compile Include="SimpleMainWindow.xaml.cs">
<DependentUpon>SimpleMainWindow.xaml</DependentUpon>
</Compile>
Expand All @@ -139,6 +144,10 @@
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="TouchKeyboardWin10MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="SimpleMainWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand All @@ -161,6 +170,7 @@
<ItemGroup>
<None Include="app.config" />
<None Include="app.manifest" />
<None Include="Controls\TouchKeyboard\Readme.md" />
<None Include="crash_reporter.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
67 changes: 67 additions & 0 deletions CefSharp.Wpf.Example/Controls/TouchKeyboard/InputPaneRcw.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Microsoft.Windows.Input.TouchKeyboard.Rcw
{
/// <summary>
/// Contains internal RCWs for invoking the InputPane (tiptsf touch keyboard)
/// </summary>
/// <remarks>
/// Adapted from https://github.com/Microsoft/WPF-Samples/blob/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier/InputPaneRcw.cs
/// Licensed under an MIT license see https://github.com/Microsoft/WPF-Samples/blob/master/LICENSE
/// </remarks>
internal static class InputPaneRcw
{
internal enum TrustLevel
{
BaseTrust,
PartialTrust,
FullTrust
}

[Guid("75CF2C57-9195-4931-8332-F0B409E916AF"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
internal interface IInputPaneInterop
{
[MethodImpl(MethodImplOptions.InternalCall)]
void GetIids(out uint iidCount, [MarshalAs(UnmanagedType.LPStruct)] out Guid iids);

[MethodImpl(MethodImplOptions.InternalCall)]
void GetRuntimeClassName([MarshalAs(UnmanagedType.BStr)] out string className);

[MethodImpl(MethodImplOptions.InternalCall)]
void GetTrustLevel(out TrustLevel TrustLevel);

[MethodImpl(MethodImplOptions.InternalCall)]
IInputPane2 GetForWindow([In] IntPtr appWindow, [In] ref Guid riid);
}

[Guid("8A6B3F26-7090-4793-944C-C3F2CDE26276"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
internal interface IInputPane2
{
[MethodImpl(MethodImplOptions.InternalCall)]
void GetIids(out uint iidCount, [MarshalAs(UnmanagedType.LPStruct)] out Guid iids);

[MethodImpl(MethodImplOptions.InternalCall)]
void GetRuntimeClassName([MarshalAs(UnmanagedType.BStr)] out string className);

[MethodImpl(MethodImplOptions.InternalCall)]
void GetTrustLevel(out TrustLevel TrustLevel);

[MethodImpl(MethodImplOptions.InternalCall)]
bool TryShow();

[MethodImpl(MethodImplOptions.InternalCall)]
bool TryHide();
}
}
}
10 changes: 10 additions & 0 deletions CefSharp.Wpf.Example/Controls/TouchKeyboard/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Code in this folder is adapted from https://github.com/Microsoft/WPF-Samples/tree/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier

Licensed under an MIT license, see https://github.com/Microsoft/WPF-Samples/blob/master/LICENSE

The files aren't included in the .csproj file intentially as they require the Windows 10 SDK

It is reccomended that you obtain and use the https://github.com/Microsoft/WPF-Samples/tree/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier
solution provided by Microsoft. It has more advanced features including TouchKeyboardAwareDecorator, which can be used
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

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved

using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using static Microsoft.Windows.Input.TouchKeyboard.Rcw.InputPaneRcw;

namespace Microsoft.Windows.Input.TouchKeyboard
{
/// <summary>
/// Provides Win10 Touch Keyboard - Show/Hide
/// NOTE: Documentation suggests Win10 SDK is required to compile this.
/// https://github.com/Microsoft/WPF-Samples/blob/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier/Readme.md
/// </summary>
/// <remarks>
/// Adapted from https://github.com/Microsoft/WPF-Samples/blob/master/Input%20and%20Commands/TouchKeyboard/TouchKeyboardNotifier/TouchKeyboardEventManager.cs
/// Licensed under an MIT license see https://github.com/Microsoft/WPF-Samples/blob/master/LICENSE
/// </remarks>
[CLSCompliant(true)]
internal class TouchKeyboardEventManager : IDisposable
{
private const string InputPaneTypeName = "Windows.UI.ViewManagement.InputPane, Windows, ContentType=WindowsRuntime";
/// <summary>
/// The WinRT InputPane type.
/// </summary>
private readonly Type inputPaneType = null;

private IInputPaneInterop inputPaneInterop = null;

private IInputPane2 inputPanel = null;

private bool disposed = false;

/// <summary>
/// Indicates if calling the touch keyboard is supported
/// </summary>
private readonly bool touchKeyboardSupported = false;

/// <summary>
/// TouchKeyboardEventManager
/// </summary>
/// <param name="handle">Need the HWND for the native interop call into IInputPaneInterop</param>
internal TouchKeyboardEventManager(IntPtr handle)
{
inputPaneType = Type.GetType(InputPaneTypeName);

// Get and cast an InputPane COM instance
inputPaneInterop = WindowsRuntimeMarshal.GetActivationFactory(inputPaneType) as IInputPaneInterop;

touchKeyboardSupported = inputPaneInterop != null;

if (touchKeyboardSupported)
{
// Get the actual input pane for this HWND
inputPanel = inputPaneInterop.GetForWindow(handle, typeof(IInputPane2).GUID);
}
}

/// <summary>
/// Returns an instance of the InputPane
/// </summary>
/// <returns>The InputPane</returns>
internal IInputPane2 GetInputPane()
{
if (!touchKeyboardSupported)
{
throw new PlatformNotSupportedException("Native access to touch keyboard APIs not supported on this OS!");
}

return inputPanel;
}

protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (inputPanel != null)
{
Marshal.FinalReleaseComObject(inputPanel);

inputPanel = null;
}

if (inputPaneInterop != null)
{
Marshal.FinalReleaseComObject(inputPaneInterop);

inputPaneInterop = null;
}
}
}

disposed = true;
}

// This code added to correctly implement the disposable pattern.
public void Dispose()
{
Dispose(true);
}
}
}
25 changes: 25 additions & 0 deletions CefSharp.Wpf.Example/TouchKeyboardWin10MainWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Window x:Class="CefSharp.Wpf.Example.TouchKeyboardWin10MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
Title="SimpleMainWindow" WindowState="Maximized">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<wpf:ChromiumWebBrowser Grid.Row="0"
x:Name="Browser"
Address="http://www.google.com"/>
<StatusBar Grid.Row="1">
<ProgressBar HorizontalAlignment="Right"
IsIndeterminate="{Binding WebBrowser.IsLoading}"
Width="100"
Height="16"
Margin="3" />
<Separator />
<!-- TODO: Could show hover link URL here -->
<TextBlock />
</StatusBar>
</Grid>
</Window>
58 changes: 58 additions & 0 deletions CefSharp.Wpf.Example/TouchKeyboardWin10MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright © 2019 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

using System.Windows;
using CefSharp.Enums;
using Microsoft.Windows.Input.TouchKeyboard;

namespace CefSharp.Wpf.Example
{
/// <summary>
/// TouchKeyboardWin10MainWindow provides a very basic Windows 10 only example of
/// showing the onscreen(virtual) keyboard in a WPF app.
/// </summary>
public partial class TouchKeyboardWin10MainWindow : Window
{
private TouchKeyboardEventManager touchKeyboardEventManager;

public TouchKeyboardWin10MainWindow()
{
InitializeComponent();

Browser.VirtualKeyboardRequested += BrowserVirtualKeyboardRequested;
Browser.IsBrowserInitializedChanged += BrowserIsBrowserInitializedChanged;
}

private void BrowserIsBrowserInitializedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
var browserHost = Browser.GetBrowserHost();

touchKeyboardEventManager = new TouchKeyboardEventManager(browserHost.GetWindowHandle());
}
else
{
if (touchKeyboardEventManager != null)
{
touchKeyboardEventManager.Dispose();
}
}
}

private void BrowserVirtualKeyboardRequested(object sender, VirtualKeyboardRequestedEventArgs e)
{
var inputPane = touchKeyboardEventManager.GetInputPane();

if (e.TextInputMode == TextInputMode.None)
{
inputPane.TryHide();
}
else
{
inputPane.TryShow();
}
}
}
}

0 comments on commit 0b57e52

Please sign in to comment.