DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Alt + Tabキーによる「タスクスイッチ機能」の制限方法

環境/言語:[Windows Vista Business SP1]
分類:[.NET]

開発言語:Visual Studio 2008
OS:Windows Vista Business SP1


いつもお世話になっております。

本日はVistaの「タスクスイッチ機能」の制限方法について質問があります。
ここでは「タスクスイッチ機能」とは、Alt + Tabキー押下で表示される、
ウィンドウ切り替えのことを表します。

上記機能を特定の条件で動作しないようにしたいのですが、必要条件として
キーアサインを変更しないこと(レジストリの変更不可)があります。

SetWindowsHookEx APIによるロウレベルのキーフックを行い、
コールバックでキーコードを取得、Tabキーの場合は
My.Computer.Keyboard.AltKeyDownプロパティをチェック、
Trueの場合はCallNextHookExを呼ばずに終了しています。

この場合、Alt + Tabキーによる「タスクスイッチ機能」が、一度目は起動し
二度目からは起動しないという事象が発生します。

どうやらMy.Computer.Keyboard.AltKeyDownプロパティが一度目はTrueを取得
出来ないようなのですが、なぜこのような動作になるのでしょうか?

APIコールバック中でMy.Computer.Keyboard.AltKeyDownプロパティが常に取得
出来ない等規則があればわかるのですが…

また、この処理はクラス化しており、アプリケーション(業務)側はこのクラスの
インスタンスを取得(シングルトンです)して使用しております。
(複数のアプリケーションが同時にこのクラスを使用することはありません)

そもそも、「タスクスイッチ機能」をこのような形で制限するのが間違いなので
しょうか?
(そうであったとしても、My.Computer.Keyboard.AltKeyDownプロパティの動作は
不可解です)

何卒、ご教示願います。



以下にSetWindowsHookExコールバックのソースコードを示します。

  Private Function KeybordHookProc(ByVal ncode As Integer, ByVal wparam As System.IntPtr, ByVal lparam As System.IntPtr) As Integer
        Dim hookStruct As KeyboardLLHookStruct = Nothing
        Dim keyEnable As Boolean = False
        Try
            'フックコード判定
            If (ncode < 0) Then
                Return CallNextHookEx(Me.kHookRun, ncode, wparam, lparam) '次のフックプロシージャへフック情報を渡す
            End If
        Catch ex As Exception
            FinishKeyHook()
            Return cKEYHOOK_RETURNCODE
        End Try

        Try
            'キーフック情報の構造体を取得
            hookStruct = CType(Marshal.PtrToStructure(lparam, hookStruct.GetType()), KeyboardLLHookStruct)

            'KEY_UPを無視する。
            If hookStruct.flags = cNOMAL_KEYUP Or hookStruct.flags = cABNOMAL_KEYUP Then
                Return CallNextHookEx(Me.kHookRun, ncode, wparam, lparam) '次のフックプロシージャへフック情報を渡す
            End If

            'TASKSWICTHの制限 (Tab + Altの動作制限)
            If My.Settings.TASKSWICTH_ENABLED = False And hookStruct.vkCode = Keys.Tab Then
                If My.Computer.Keyboard.AltKeyDown = True Then
                     Return cKEYHOOK_RETURNCODE  '無効
                End If
            End If

            'キー制限チェック
            If Me.keyCtrl.IsKeyLimit(hookStruct.vkCode) = True Then
                keyEnable = True
                Return cKEYHOOK_RETURNCODE 'キー制限のため、リターンコードを返却
            End If

            '次のフックプロシージャへフック情報を渡す
            Return CallNextHookEx(Me.kHookRun, ncode, wparam, lparam)

        Catch ex As Exception
            Call FinishKeyHook()
        Finally
            Call AppCall(keyEnable, hookStruct) 'アプリケーションコールバック呼び出し
        End Try
    End Function
回答ではないです。

そもそも、なぜそんなことをしたいのでしょうか。
ユーザーから見ると不便に思うので、そんなことをしたいと言われても「やめておくべきだ」という答えになりかねませんので、理由をお聞きしました。

また、Vista 以降の Windows キーと Tab キーを押す形の切り替えとか、Alt+Esc キーとか、いろいろとありそうですが、その辺はどのようにお考えなのでしょうか。

# 組み込み機器として制限したいのであれば、Embedded 製品を検討すべきだと思いますと付け加えておきます。
2010/10/04(Mon) 10:22:33 編集(投稿者)

Azuleanさん 回答ありがとうございます。

> そもそも、なぜそんなことをしたいのでしょうか。
> ユーザーから見ると不便に思うので、そんなことをしたいと言われても「やめておくべきだ」という答えになりかねませんので、理由をお聞きしました。

Vista端末操作の点から、ユーザ様より「その様にしたい」との要望があったためです。
(立場上、元受から孫以上の距離がありますので詳しいことは判りません…すみません)


> また、Vista 以降の Windows キーと Tab キーを押す形の切り替えとか、Alt+Esc キーとか、いろいろとありそうですが、その辺はどのようにお考えなのでしょうか。

ほとんどのキー操作は以下のロジックで制限しています。

            'キー制限チェック
            If Me.keyCtrl.IsKeyLimit(hookStruct.vkCode) = True Then
                keyEnable = True
                Return cKEYHOOK_RETURNCODE 'キー制限のため、リターンコードを返却
            End If

右クリックやフォルダアクセスはポリシーで、キー操作に関してはこちらでという判断のようです。
今回、Tabキーは使用可能であるため、この様な問題に当たりました。


> # 組み込み機器として制限したいのであれば、Embedded 製品を検討すべきだと思いますと付け加えておきます。

私自身、本来はそうすべきと考えています。
そもそも、Vistaなのに、Vistaの機能はもちろんWindowsの機能さえまともに使用出来ない環境を
わざわざ実装する意味は無い…と思っております。

が、そうも言えない立場ですので、力技で解決してしまおう。というわけです。
何卒、ご教示願います。
2010/10/04(Mon) 14:06:56 編集(投稿者)

原因が判明したので報告します。

今回は、先のソースコードにもある通り、キー制限を行っていたロジックで
「左Altキー」と「右Altキー」の制限を行っていたため、
My.Computer.Keyboard.AltKeyDownプロパティが初回のみ正しく取得出来なかった。
ということのようです。

そのため、「左Altキー」と「右Altキー」の制限を辞めたところ、正常にプロパティ
の値が取得出来ました。

「Tab + Alt」によるタスクスイッチを起動させることで
My.Computer.Keyboard.AltKeyDownプロパティが正常化した?のでしょうか?
APIに依存しているとも言えないこの動作は不思議に思います。

初回が取得出来なかった原因は不明ですが、とりあえず解決とさせていただきます。

皆様、ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板