前言
大家好,我是Mark。 许久未碰 Unity,最近遇到个实际需求:要在触摸屏 Windows 设备上调用系统触摸键盘。翻了不少资料,发现大多方案都是拉起旧版 “屏幕键盘”,样式偏老旧,和新版 Windows 的设计风格格格不入。为了适配现代 UI 审美,我专门研究了新版触摸键盘的调用逻辑,整理出一套完整可落地的解决方案,分享给有同样需求的开发者~
一、最终效果

二、解决方案
- 使用 COM 接口拉起Windows触摸键盘
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using UnityEngine;
using Debug = UnityEngine.Debug;
// ==================== COM接口定义(用于调用Windows触摸键盘) ====================[ComImport]
[Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ITipInvocation
{
void Toggle(IntPtr hwnd);
}
[ComImport]
[Guid("4ce576fa-83dc-4F88-951c-9d0782b4e376")]
class TipInvocation { }
public class WinTouchKeyboard : MonoBehaviour
{
/// <summary>
/// 打开Windows触摸键盘(通过COM接口)
/// </summary>
public void ShowKeyboard()
{
try
{
ITipInvocation tip = new TipInvocation() as ITipInvocation;
// 传入当前Unity进程的主窗口句柄
tip.Toggle(Process.GetCurrentProcess().MainWindowHandle);
Debug.Log("已尝试打开触摸键盘");
}
catch (Exception e)
{
Debug.LogError($"打开触摸键盘失败:{e.Message}");
}
}
/// <summary>
/// 关闭Windows触摸键盘(COM接口的Toggle方法可切换状态)
/// </summary>
public void HideKeyboard()
{
try
{
ITipInvocation tip = new TipInvocation() as ITipInvocation;
tip.Toggle(Process.GetCurrentProcess().MainWindowHandle);
Debug.Log("已尝试关闭触摸键盘");
}
catch (Exception e)
{
Debug.LogError($"关闭触摸键盘失败:{e.Message}");
}
}
}
- 接收WebView FocusedInputFieldChanged 回调事件
using UnityEngine;
using Vuplex.WebView;
using System;
public class CanvasWebViewMessageReceiver : MonoBehaviour
{
// 1. 拖拽场景中的 CanvasWebViewPrefab 到此处
public CanvasWebViewPrefab canvasWebViewPrefab;
private WinTouchKeyboard winTouchKeyboard;
private void Start()
{
// 安全检查
if (canvasWebViewPrefab == null)
{
return;
}
winTouchKeyboard = FindObjectOfType<WinTouchKeyboard>();
// 2. 监听 WebView 初始化完成事件
canvasWebViewPrefab.Initialized += OnWebViewInitialized;
}
/// <summary>
/// WebView 初始化完成后调用
/// </summary>
private void OnWebViewInitialized(object sender, EventArgs e)
{
Debug.Log("WebView 初始化完成,开始监听 FocusedInputFieldChanged 消息...");
canvasWebViewPrefab.WebView.FocusedInputFieldChanged += (sender, eventArgs) =>
{
if (eventArgs.Type == FocusedInputFieldType.Text)
{
winTouchKeyboard.ShowKeyboard();
// 获得焦点时启用输入法的合成模式,如果不启用导致网页输入框无法输入中文
Input.imeCompositionMode = IMECompositionMode.On;
Debug.Log("IME enabled On: " + Input.imeIsSelected);
}
else
{
winTouchKeyboard.HideKeyboard();
// 焦点丢失,关闭输入法合成模式,输入法直接输出单个字符(无法输入中文等需要组合的文字)
Input.imeCompositionMode = IMECompositionMode.Off;
Debug.Log("IME enabled Off: " + Input.imeIsSelected);
}
};
}
}
三、结束
好了,今天就写到这吧~
对你有帮助的话可以点赞、关注、收藏,有问题评论区见哈~
原创不易,若转载请注明出处,感谢大家~