Windowsキーの無効化
最近、息子(2歳)がパソコンのキーボードで遊ぶようになりました。で、一度シャットダウンされてしまったので、それ以降はロックするようにしていました。ですが、多少は触らせてあげたいなぁと思い、息子用のデスクトップを作成することにしました。
そこで問題となったのがWindowsキーです。Formを作ってFormBorderStyleをNoneにして、WindowStateをMaximizedにすればそれっぽい画面にはなりますが、Windowsキーを押すとスタートメニューが開いてシャットダウンされる危険性が高くなります(実際、以前もWindowsキー経由でシャットダウンされました)。そこで、Windowsキーを無効化する方法について調査しました。
結論としては、Windowsキーを無効化するには低水準フック(グローバルフック)を利用する必要がありました。以下がVB.NETの実装ソースです。
Imports System.Runtime.InteropServices Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load InitKeyboard() Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None Me.WindowState = FormWindowState.Maximized End Sub 'Declare the keybord hook constant. 'For other hook types, obtain these values from Winuser.h in Microsoft SDK. Dim WH_KEYBOARD_LL As Integer = 13 Shared hHook As Integer = 0 'Keep the reference so that the delegate is not garbage collected. Private hookproc As CallBack Public Delegate Function CallBack( _ ByVal nCode As Integer, _ ByVal wParam As IntPtr, _ ByVal lParam As IntPtr) As Integer 'Import for the SetWindowsHookEx function. <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ Public Overloads Shared Function SetWindowsHookEx _ (ByVal idHook As Integer, ByVal HookProc As CallBack, _ ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer End Function 'Import for the GetModuleHandle function. <DllImport("kernel32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ Public Overloads Shared Function GetModuleHandle _ (ByVal lpModuleName As String) As IntPtr End Function 'Import for the CallNextHookEx function. <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ Public Overloads Shared Function CallNextHookEx _ (ByVal idHook As Integer, ByVal nCode As Integer, _ ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer End Function 'Import for the UnhookWindowsHookEx function. <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ Public Overloads Shared Function UnhookWindowsHookEx _ (ByVal idHook As Integer) As Boolean End Function 'KeyboardHookStruct structure declaration. <StructLayout(LayoutKind.Sequential)> Public Structure KeyboardLLHookStruct Public vkCode As Integer Public scanCode As Integer Public flags As Integer Public time As Integer Public dwExtraInfo As Integer End Structure Private Sub InitKeyboard() hookproc = AddressOf KeybordHookProc hHook = SetWindowsHookEx(WH_KEYBOARD_LL, hookproc, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0) If hHook.Equals(0) Then MsgBox("SetWindowsHookEx Failed") End If End Sub Public Shared Function KeybordHookProc( _ ByVal nCode As Integer, _ ByVal wParam As IntPtr, _ ByVal lParam As IntPtr) As Integer If (nCode < 0) Then Return CallNextHookEx(hHook, nCode, wParam, lParam) End If Dim hookStruct As New KeyboardLLHookStruct() hookStruct = CType(Marshal.PtrToStructure(lParam, hookStruct.GetType()), KeyboardLLHookStruct) Select Case hookStruct.vkCode Case Keys.LWin, Keys.RWin Return 1 End Select Return CallNextHookEx(hHook, nCode, wParam, lParam) End Function Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed Dim ret As Boolean = UnhookWindowsHookEx(hHook) If ret.Equals(False) Then MsgBox("UnhookWindowsHookEx Failed") End If End Sub End Class
以下のページ(※1)が非常に参考になりました。4月から育児休暇を取得していたので、ゼロから学ぶVisualBasic(※2)を片手にVB.NETについて勉強を始めたのですが、やっぱりWindowsを操作できるのって楽しいですね。仕事ではJavaしか扱っていなかったのですが、あまりに簡単にWindowsアプリを作れることにビックリしています。
※1 http://www.ailight.jp/BBS/Detail.aspx?Header_ID=1784
http://vsug.jp/tabid/63/view/topic/forumid/45/postid/1344/Default.aspx#1388
※2 http://itpro.nikkeibp.co.jp/article/MAG/20081113/319258/