Java, C#, C++, Visual Basic, Delphi 등에서 화상 키보드를 표시, 숨기기, 이동 또는 크기 조정하는 방법

Windows 메시지를 사용하여 가상 키보드를 제어할 수 있습니다.

예:
WM_CSKEYBOARD = WM_USER + 192;
WM_CSKEYBOARDMOVE = WM_USER + 193;
WM_CSKEYBOARDRESIZE = WM_USER + 197;

// to show keyboard
PostMessage(FindWindow('TFirstForm', 'hvkFirstForm'), WM_CSKEYBOARD, 1, 0);

// to close keyboard
PostMessage(FindWindow('TFirstForm', 'hvkFirstForm'), WM_CSKEYBOARD, 2, 0);

// to fade keyboard
PostMessage(FindWindow('TFirstForm', 'hvkFirstForm'), WM_CSKEYBOARD, 3, 0);

// to toggle (show/hide) keyboard
PostMessage(FindWindow('TFirstForm', 'hvkFirstForm'), WM_CSKEYBOARD, 4, 0);

// to move keyboard (Left, Top - new position)
PostMessage(FindWindow('TFirstForm', 'hvkFirstForm'), WM_CSKEYBOARDMOVE, Left, Top);

// to resize keyboard
PostMessage(FindWindow('TFirstForm', 'hvkFirstForm'), WM_CSKEYBOARDRESIZE, Width, Height);
Visual Basic 2008(VB.NET) 샘플 코드:
Const WM_CSKEYBOARD = &H400 + 192
Const WM_CSKEYBOARDMOVE = &H400 + 193
Const WM_CSKEYBOARDRESIZE = &H400 + 197
 
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
 
    'Open/show Hot Virtual Keyboard in Visual Basic
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim hWnd As Integer
        hWnd = FindWindow("TFirstForm", "hvkFirstForm")
        PostMessage(hWnd, WM_CSKEYBOARD, 1, 0)
    End Sub
 
    'Close Hot Virtual Keyboard in Visual Basic
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim hWnd As Integer
        hWnd = FindWindow("TFirstForm", "hvkFirstForm")
        PostMessage(hWnd, WM_CSKEYBOARD, 2, 0)
    End Sub
 
    'Move Hot Virtual Keyboard in Visual Basic; Move it first then show it
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Dim hWnd As Integer
        hWnd = FindWindow("TFirstForm", "hvkFirstForm")
        PostMessage(hWnd, WM_CSKEYBOARDMOVE, 200, 200)
        PostMessage(hWnd, WM_CSKEYBOARD, 1, 0)
    End Sub
 
    'Toggle Hot Virtual Keyboard in Visual Basic
    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Dim hWnd As Integer
        hWnd = FindWindow("TFirstForm", "hvkFirstForm")
        PostMessage(hWnd, WM_CSKEYBOARD, 4, 0)
    End Sub
 
    'Fade Hot Virtual Keyboard in Visual Basic
    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        Dim hWnd As Integer
        hWnd = FindWindow("TFirstForm", "hvkFirstForm")
        PostMessage(hWnd, WM_CSKEYBOARD, 3, 0)
    End Sub
 
    'Change the keyboard type and show it
    Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
        'Change the Registry entry for the required keyboard
        My.Computer.Registry.SetValue("HKEY_CURRENT_USER\Software\ComfortSoftware\hvk", "KeyboardName", "Name of your chosen keyboard")
        'Open the keyboard
        Dim hWnd As Integer
        hWnd = FindWindow("TFirstForm", "hvkFirstForm")
        PostMessage(hWnd, WM_CSKEYBOARD, 1, 0)
    End Sub
 
    'Change to another keyboard type and show it
    Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
        'Change the Registry entry for the required keyboard
        My.Computer.Registry.SetValue("HKEY_CURRENT_USER\Software\ComfortSoftware\hvk", "KeyboardName", "Name of another chosen keyboard")
        'Open the keyboard
        Dim hWnd As Integer
        hWnd = FindWindow("TFirstForm", "hvkFirstForm")
        PostMessage(hWnd, WM_CSKEYBOARD, 1, 0)
    End Sub
C# 샘플 코드:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public const Int32 WM_USER = 1024;
public const Int32 WM_CSKEYBOARD = WM_USER + 192;
public const Int32 WM_CSKEYBOARDMOVE = WM_USER + 193;
public const Int32 WM_CSKEYBOARDRESIZE = WM_USER + 197;

[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern Int32 FindWindow(string _ClassName, string _WindowName);

[DllImport("User32.DLL")]
public static extern Boolean PostMessage(Int32 hWnd, Int32 Msg, Int32 wParam, Int32 lParam);


Int32 hWnd = FindWindow("TFirstForm", "hvkFirstForm");
PostMessage(hWnd, WM_CSKEYBOARD, 1, 0 ); // Show
PostMessage(hWnd, WM_CSKEYBOARD, 2, 0); // Hide
PostMessage(hWnd, WM_CSKEYBOARDMOVE, 0, 0); // Move to 0, 0
PostMessage(hWnd, WM_CSKEYBOARDRESIZE, 600, 300); // Resize to 600, 300
C++(CLR 구문) 샘플 코드:
using namespace System::Runtime::InteropServices; 
using namespace System::Security::Permissions; 
using namespace Microsoft::Win32; 
 
const System::UInt32 WM_USER = 1024; 
const System::UInt32 WM_CSKEYBOARD = WM_USER + 192; 
const System::UInt32 WM_CSKEYBOARDMOVE = WM_USER + 193;  
 
[DllImport("user32.dll")] 
extern IntPtr FindWindow(String^ lpClassName, String^ lpWindowName); 
[DllImport("user32.dll")] 
extern IntPtr PostMessage(System::IntPtr hWnd, System::UInt32 Msg, int wParam, int lParam); 
[assembly:RegistryPermissionAttribute(SecurityAction::RequestMinimum, All = "HKEY_CURRENT_USER")]; 
 
 
....blah blah blah you normal code...
 
 
void button1_Click(System::Object^  sender, System::EventArgs^  e) 
{ 
    // Open/show the Hot Virtual Keyboard 
    IntPtr hWnd; 
    hWnd = FindWindow("TFirstForm", "hvkFirstForm"); 
    PostMessage(hWnd, WM_CSKEYBOARD, 1, 0); 
} 
void button2_Click(System::Object^  sender, System::EventArgs^  e) 
{ 
        // close the Hot Virtual Keyboard 
    IntPtr hWnd; 
    hWnd = FindWindow("TFirstForm", "hvkFirstForm"); 
    PostMessage(hWnd, WM_CSKEYBOARD, 2, 0); 
} 
void button3_Click(System::Object^  sender, System::EventArgs^  e) 
{ 
    //Move the Hot Virtual Keyboard; Move it first then show it 
    IntPtr hWnd; 
    hWnd = FindWindow("TFirstForm", "hvkFirstForm"); 
    PostMessage(hWnd, WM_CSKEYBOARDMOVE, 200, 200); 
    PostMessage(hWnd, WM_CSKEYBOARD, 1, 0); 
} 
void button4_Click(System::Object^  sender, System::EventArgs^  e) 
{ 
    //Toggle the Hot Virtual Keyboard 
    IntPtr hWnd; 
    hWnd = FindWindow("TFirstForm", "hvkFirstForm"); 
    PostMessage(hWnd, WM_CSKEYBOARD, 4, 0); 
} 
void button5_Click(System::Object^  sender, System::EventArgs^  e) 
{ 
    //Fade the Hot Virtual Keyboard 
    IntPtr hWnd; 
    hWnd = FindWindow("TFirstForm", "hvkFirstForm"); 
    PostMessage(hWnd, WM_CSKEYBOARD, 3, 0); 
} 
void button6_Click(System::Object^  sender, System::EventArgs^  e) 
{ 
    //Change the keyboard type and show it 
    System::Object ^kname="NumPad"; 
 
    //Change the Registry entry for the required keyboard 
 
    RegistryKey ^key= Registry::CurrentUser->OpenSubKey ( "Software\\ComfortSoftware\\hvk",true); 
    key->SetValue("KeyboardName",kname); 
 
    //Open the keyboard 
    IntPtr hWnd; 
    hWnd = FindWindow("TFirstForm", "hvkFirstForm"); 
    PostMessage(hWnd, WM_CSKEYBOARD, 1, 0); 
}
Java 샘플 코드:
/*
* This file is heavily based on Jawin: http://jawinproject.sourceforge.net/
*
* assumes Hot Virtual Keyboard is loaded...
* 
*/

package client.keyboard;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import org.jawin.COMException;
import org.jawin.FuncPtr;
import org.jawin.ReturnFlags;
import org.jawin.io.LittleEndianInputStream;
import org.jawin.io.LittleEndianOutputStream;
import org.jawin.io.NakedByteStream;

public class ComfortSoftwareKeyboard {

    protected static final String COMFORT_SOFTWARE_WINDOW_NAME = "hvkFirstForm";
    protected static final String COMFORT_SOFTWARE_CLASS_NAME = "TFirstForm";
    
    protected static final int WM_USER = 1024;
    protected static final int WM_CSKEYBOARD = WM_USER + 192;
    protected static final int WM_CSKEYBOARDMOVE = WM_USER + 193;

    protected static final Call FIND_WINDOW = new Call("USER32.DLL", "FindWindowW", "GG:I:", 8);
    protected static final Call POST_MESSAGE = new Call("USER32.DLL", "PostMessageW", "IIII:I:", 16);
    
    private static ComfortSoftwareKeyboard INSTANCE = new ComfortSoftwareKeyboard();

    public static ComfortSoftwareKeyboard getInstance() {
        return INSTANCE;
    }

    protected int getWindowHandle() throws COMException, IOException {
        FuncPtr findWindow = null;
        findWindow = new FuncPtr(FIND_WINDOW.getDllName(), FIND_WINDOW.getFunctionName());
        NakedByteStream bs = new NakedByteStream();
        LittleEndianOutputStream leo = new LittleEndianOutputStream(bs);
        leo.writeStringUnicode(COMFORT_SOFTWARE_CLASS_NAME);
        leo.writeStringUnicode(COMFORT_SOFTWARE_WINDOW_NAME);
        byte[] b = findWindow.invoke(FIND_WINDOW.getParameterDescription(), FIND_WINDOW.getStackSize(), bs, null,
                ReturnFlags.CHECK_FALSE);
        LittleEndianInputStream leis = new LittleEndianInputStream(
                new ByteArrayInputStream(b));
        int l = leis.readInt();
        findWindow.close();
        return l;
    }

    public int move(int x, int y) throws COMException, IOException {
        int hWnd = getWindowHandle();

        FuncPtr postMessage = null;
        postMessage = new FuncPtr(POST_MESSAGE.getDllName(), POST_MESSAGE.getFunctionName());
        NakedByteStream bs = new NakedByteStream();
        LittleEndianOutputStream leo = new LittleEndianOutputStream(bs);

        leo.writeInt(hWnd);
        leo.writeInt(WM_CSKEYBOARDMOVE);
        leo.writeInt(x);
        leo.writeInt(y);

        byte[] b = postMessage.invoke(POST_MESSAGE.getParameterDescription(), POST_MESSAGE.getStackSize(), bs, null,
                ReturnFlags.CHECK_FALSE);
        LittleEndianInputStream leis = new LittleEndianInputStream(
                new ByteArrayInputStream(b));
        int l = leis.readInt();
        postMessage.close();
        return l;
    }
    
    public int setVisible(boolean visible) throws COMException, IOException {
        int hWnd = getWindowHandle();

        FuncPtr postMessage = null;
        postMessage = new FuncPtr(POST_MESSAGE.getDllName(), POST_MESSAGE.getFunctionName());
        NakedByteStream bs = new NakedByteStream();
        LittleEndianOutputStream leo = new LittleEndianOutputStream(bs);

        leo.writeInt(hWnd);
        leo.writeInt(WM_CSKEYBOARD);
        leo.writeInt(visible ? 1 : 2);
        leo.writeInt(0);

        byte[] b = postMessage.invoke(POST_MESSAGE.getParameterDescription(), POST_MESSAGE.getStackSize(), bs, null,
                ReturnFlags.CHECK_FALSE);
        LittleEndianInputStream leis = new LittleEndianInputStream(
                new ByteArrayInputStream(b));
        int l = leis.readInt();
        postMessage.close();
        return l;
    }

    public static void main(String[] args) throws Exception {
        try {
            ComfortSoftwareKeyboard keyboard = ComfortSoftwareKeyboard.getInstance();
            keyboard.setVisible(true);
            Thread.sleep(1000);
            keyboard.setVisible(false);
            Thread.sleep(1000);
            keyboard.setVisible(true);
            for (int i = 0; i < 100;i++) {
                keyboard.move(i, i);
            }
        } catch (COMException e) {
        } finally {
        }
    }
}

class Call {
    private int stackSize;
    private String functionName;
    private String parameterDescription;
    private String dllName;
    
    public Call(String dllName, String functionName, String parameterDescription, int stackSize) {
        this.stackSize = stackSize;
        this.functionName = functionName;
        this.parameterDescription = parameterDescription;
        this.dllName = dllName;
    }
    public int getStackSize() {return stackSize;}
    public String getFunctionName() {return functionName;}
    public String getParameterDescription() {return parameterDescription;}
    public String getDllName() {return dllName;}
}

Windows 메시지를 사용할 수 없는 경우 이 파일들을 다운로드하여 사용해 보세요:
https://hotvirtualkeyboard.com/files/ShowKB.exe
https://hotvirtualkeyboard.com/files/HideKB.exe
https://hotvirtualkeyboard.com/files/ToggleKB.exe

https://hotvirtualkeyboard.com/files/MoveTopKB.exe
https://hotvirtualkeyboard.com/files/MoveBottomKB.exe
https://hotvirtualkeyboard.com/files/MoveLeftKB.exe
https://hotvirtualkeyboard.com/files/MoveRightKB.exe

https://hotvirtualkeyboard.com/files/MoveKB.exe
(명령줄 형식: MoveKB.exe Left Top)

https://hotvirtualkeyboard.com/files/SetNameKB.exe
(명령줄 형식: SetNameKB.exe KeyboardName)


Virtual Keyboard Commander로 작동 방식을 확인할 수 있습니다

HTML을 사용하여 키오스크 소프트웨어를 작성하는 경우 특별한 JavaScript 함수를 사용하여 화상 키보드를 제어할 수 있습니다.

JavaScript를 사용하면 키보드를 표시, 숨기기 또는 이동할 수 있습니다. 특별한 JavaScript 함수를 사용하여 키보드 관련 정보를 브라우저 제목에 추가하기만 하면 애플리케이션이 제목의 변경 사항을 모니터링합니다.

JavaScript 함수와 예제가 포함된 파일은 여기에서 다운로드하세요: https://hotvirtualkeyboard.com/commander.html

WM_CSKEYBOARDMOVE: DPI가 다른 여러 화면을 사용할 때 키보드 이동 문제 해결.

예를 들어, 화면 1은 해상도가 2560x1440이며 Windows 디스플레이 설정에서 "125% 배율"로 설정되어 있습니다. 화면 2는 1920x1080이며 "100% 배율"로 설정되어 있습니다.

hvk.exe 파일의 Windows 앱 호환성 설정을 열고 DPI 동작을 "애플리케이션"으로 설정합니다. 이는 애플리케이션이 DPI 관련 모든 계산을 관리한다는 의미입니다. 이 설정을 활성화하면 API의 이동 함수에 물리적 픽셀 값을 전달할 수 있으며, 키보드 창이 정확히 해당 위치로 이동합니다.

이 호환 모드를 프로그래밍 방식으로(예: 자체 설치 프로그램으로) 활성화하려면 다음 레지스트리 키를 설정해야 합니다:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers:
"C:\Program Files\HotVirtualKeyboard\hvk.exe"="~ HIGHDPIAWARE"

그러면 모든 사용자에게 적용됩니다. 또는 현재 사용자(HKCU)의 레지스트리에 이 키를 배치할 수도 있습니다.