January
3rd
2014

Virtual Keyboard with Unity
by

What happens if your application is targeting a touchscreen computer without a physical keyboard but requires keyboard input from the user? One solution, like in many games, is to create a custom virtual keyboard inside the application. But what if you want regional and language support like japanese, chinese, arabic…?
Based from the article from Intel “Touch keyboard access for Windows 8 desktop apps“, the following script will allow you how to call the built-in keyboards provided with the Windows OS.

However, in order to work, the application needs to run in window mode. Please follow this post in order to launch a maximized borderless Unity application for raising the virtual keyboard without disturbing the game.

using UnityEngine;
using System;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;

public static class VirtualKeyboard {
	[DllImport("user32")]
	static extern IntPtr FindWindow(String sClassName, String sAppName);
	[DllImport("user32")]
	static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
	
	private static Process _onScreenKeyboardProcess = null;
	
	/// <summary>
	/// Show the touch keyboard (tabtip.exe).
	/// </summary>
	public static void ShowTouchKeyboard() {
		//ExternalCall("C:\\Program Files\\Common Files\\Microsoft Shared\\ink\\tabtip.exe", null, false);
		
		ExternalCall("TABTIP", null, false);
	}
	
	/// <summary>
	/// Hide the touch keyboard (tabtip.exe).
	/// </summary>
	public static void HideTouchKeyboard() {
		uint WM_SYSCOMMAND = 274;
		int SC_CLOSE   = 61536;
		IntPtr ptr = FindWindow("IPTip_Main_Window", null);
		PostMessage(ptr , WM_SYSCOMMAND, SC_CLOSE, 0);
	}
	
	/// <summary>
	/// Show the on screen keyboard (osk.exe).
	/// </summary>
	public static void ShowOnScreenKeyboard() {
		//ExternalCall("C:\\Windows\\system32\\osk.exe", null, false);
		
		if(_onScreenKeyboardProcess == null || _onScreenKeyboardProcess.HasExited)
			_onScreenKeyboardProcess = ExternalCall("OSK", null, false);
	}
	
	/// <summary>
	/// Hide the on screen keyboard (osk.exe).
	/// </summary>
	public static void HideOnScreenKeyboard() {
		if(_onScreenKeyboardProcess != null && !_onScreenKeyboardProcess.HasExited)
			_onScreenKeyboardProcess.Kill();
	}
	
	/// <summary>
	/// Set size and location of the OSK.exe keyboard, via registry changes.  Messy, but only known method.
	/// </summary>
	/// <param name='rect'>
	/// Rect.
	/// </param>
	public static void RepositionOnScreenKeyboard(Rect rect)
	{
		ExternalCall("REG", @"ADD HKCU\Software\Microsoft\Osk /v WindowLeft /t REG_DWORD /d " + (int) rect.x + " /f", true);
		ExternalCall("REG", @"ADD HKCU\Software\Microsoft\Osk /v WindowTop /t REG_DWORD /d " + (int) rect.y + " /f", true);
		ExternalCall("REG", @"ADD HKCU\Software\Microsoft\Osk /v WindowWidth /t REG_DWORD /d " + (int) rect.width + " /f", true);
		ExternalCall("REG", @"ADD HKCU\Software\Microsoft\Osk /v WindowHeight /t REG_DWORD /d " + (int) rect.height + " /f", true);
	}
	
	private static Process ExternalCall(string filename, string arguments, bool hideWindow) {
		ProcessStartInfo startInfo = new ProcessStartInfo();
		startInfo.FileName = filename;
		startInfo.Arguments = arguments;
		
		// if just command, we don't want to see the console displayed
		if(hideWindow) {
			startInfo.RedirectStandardOutput = true;
	        startInfo.RedirectStandardError = true;
	        startInfo.UseShellExecute = false;
	        startInfo.CreateNoWindow = true;
		}
		
		Process process = new Process();
		process.StartInfo = startInfo;
		process.Start();	
		
		return process;
	}
}
  • Yasar khan
    20 August 2015 at 17 h 24 min

    Hi i have used your script in unity and kept my application in windowed mode but still i can’t call on screen keyboard in unity.Please help me.

  • Nurlan
    4 November 2015 at 18 h 45 min

    Thanks man

  • picpic
    4 December 2015 at 17 h 28 min

    Hello,

    Thanks you for this very useful script, but i have a little problem, it work very well in editor but it doesn’t work after build !

    Win32Exception: Le fichier spécifié est introuvable
    at System.Diagnostics.Process.StartWithShellExecuteEx (System.Diagnostics.ProcessStartInfo startInfo) [0x00000] in :0
    at System.Diagnostics.Process.Start () [0x00000] in :0
    at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:Start ()
    at VirtualKeyboard.ExternalCall (System.String filename, System.String arguments, Boolean hideWindow) [0x00000] in :0
    at VirtualKeyboard.ShowTouchKeyboard () [0x00000] in :0
    at ShowScreenBeyboard.Update () [0x00000] in :0

    Thanks you

    • picpic
      4 December 2015 at 18 h 21 min

      Hi again i just test in 64 bit exe and it work thanks, after research no mod for win32

  • Gamgie
    3 August 2016 at 20 h 14 min

    Hello !!

    Thanks for this script it helps a lot !! (for interactive installation for example)

    I’m facing an issue.
    I’m using the touch keyboard but I need to move my GUI to avoid it to be hidden by keyboard appearing.

    So how can I know how many pixels I need to translate my GUI ?
    It looks like it is based on physical screen size (8.5 cm on my 2 different screen here).

    Get the physical screen size is not so easy (based on screen drivers etc, not very easy and scalable). I think get the keyboard window height is the best solution but I don’t know how to do it.

    Any idea ?

    Thanks :)

    • Gamgie
      4 August 2016 at 18 h 46 min

      I finally found a solution, maybe it will help someone.

      Add this :

      [StructLayout(LayoutKind.Sequential)]
      public struct RECT
      {
      public int Left;
      public int Top;
      public int Right;
      public int Bottom;
      }
      [DllImport(“user32″)]
      static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

      public static RECT GetTouchKeyboardRect()
      {
      IntPtr ptr = FindWindow(“IPTip_Main_Window”, null);

      RECT rect = new RECT();
      GetWindowRect(ptr, out rect);

      return rect;
      }

      This solution only works when the touchkeyboard is open.

Leave a Reply

Your email address will not be published.