zourimusi's blog

作業メモとnanoblock関連

WPFで特殊なウィンドウ、スクリーンキーボード

f:id:zourimusi:20131018191720p:plain

1. 特殊なウィンドウを表示する

画面左側にある二つの円形がウィンドウです。

<Window x:Class="ZSubKey.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        WindowStyle="None"  
        AllowsTransparency="True"
        Background="Transparent" 
        Topmost="True" 
        WindowState="Maximized"
        ShowInTaskbar="False">
    <Grid>
        …
    </Grid>
</Window>

・ WindowStyle:枠なしのウィンドウを指定します。

・AllowsTransparency、Background:背景色に透明を指定し、その部分を透過します。マウスイベントも背後のウィンドウに透過します。

・Topmost:ウィンドウを常に最前面に表示します。

・WindowState:最大化して表示するよう指定します。

・ShowInTaskbar:タスクバーに表示しないよう指定します。

 

2. ウィンドウをアクティブにしないようにする

Win32 APIを利用して、コードビハインドに実装します。

スクリーンキーボードを作る場合、自身がアクティブ化してしまうと対象のウィンドウにキーボードイベントが通知できないため、実装が必要です。

[DllImport("user32.dll")]
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

private const int GWL_EXSTYLE = -20;

private const int WS_EX_NOACTIVATE = 0x08000000;

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);

    var helper = new WindowInteropHelper(this);
    SetWindowLong(helper.Handle, GWL_EXSTYLE, GetWindowLong(helper.Handle, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
}

 

3. キーボードイベントを起こす

こちらもWin32 APIを利用します。

今回は緑色の円形をクリックすると、'0'を押下したイベントを起こしています。

なお、0x60は'0'のキーコードです。

パラメーターについてはkeybd_eventのリファレンスなどを参照してください。

[DllImport("user32.dll")]
private static extern uint keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    keybd_event(0x60, 0, 0, (UIntPtr)0);
}