フォームを最小化した状態で、KeyDownイベントの発生

タグの編集
投稿者 じょにー  (社会人) 投稿日時 2009/2/28 18:13:58
VB6で、フォームを最小化させた状態で、KeyDownイベントを、発生させる事は、可能ですか?
例えば、コマンドボタンを、押したら、フォームを最小化させて、ファンクションキーが、押されたら、元のサイズに、戻すと、言う事をやりたいのですが、可能でしょうか?アドバイス、お願いいたします
投稿者 (削除されました)  () 投稿日時 2009/3/1 21:26:17
(削除されました)
投稿者 るきお  (社会人) 投稿日時 2009/3/1 21:26:17
フォームが最小化されているときにKeyDownイベントを受け取ることはできません。純粋なVBには最小化されているといきにキーボード入力に反応する方法はありません。

どうしても実現したい場合は、Windowsの機能と連携して実現可能です。
つまり、Windowsはどのキーが押されたかいつでも把握しているので、Windowsからキーボード入力を通知してもらうようにするのです。

VB(をはじめてするほとんどのプログラミング言語)はWindowsの機能を使用しようとするととたんに面倒になります。これだけのことを実現するために信じられないようなコードを書いて、綿密にテストする必要があります。

以下にサンプルを紹介します。
このサンプルは標準モジュールとフォームを使用します。Module1に以下のコードを記述してください。
実行するとフォームを最小化しているときに[Ctrl] + [N]を押すと、フォームを標準の大きさに戻せます。

サンプルが長いので投稿を分けます。
投稿者 るきお  (社会人) 投稿日時 2009/3/1 21:27:35

Option Explicit

Private Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As LongByVal id As LongByVal fsModifiers As LongByVal vk As LongAs Long
Private Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As LongByVal id As LongAs Long
Private Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As StringAs Integer
Private Declare Function GlobalDeleteAtom Lib "kernel32" (ByVal nAtom As IntegerAs Integer
Private Const MOD_ALT = &H1
Private Const MOD_CONTROL = &H2
Private Const MOD_SHIFT = &H4

'□API関数 
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongByVal nIndex As LongByVal dwNewLong As LongAs Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As LongByVal hwnd As LongByVal Msg As LongByVal wParam As LongByVal lParam As LongAs Long

'□SetWindowLongで使用 
Private Const GWL_WNDPROC = -4

'□メッセージ 
Private Const WM_CONTEXTMENU = &H7B '右クリック 
Private Const WM_HOTKEY = &H312

'□コレクション すべてウィンドウハンドルがキー 
Dim colDProc As Collection '現在サブクラス化されているコントロールの元のWindowsProcのアドレス 
Dim HotKeyID As Long

Dim m_BaseForm As Form

'■WindowProc 
'■機能:メッセージを横取りする。 
'■備考:この関数はコールバック関数なので定義を変えてはいけない! 
Public Function HotKeyProc(ByVal hwnd As LongByVal uMsg As LongByVal wParam As LongByVal lParam As LongAs Long

    Dim DefaultProc As Long

    Select Case uMsg
        Case WM_HOTKEY
            m_BaseForm.GotHotkey
    End Select

CONTINUE:
    '引当のWindowProcへメッセージを回す。 
    DefaultProc = colDProc(CStr(hwnd))
    HotKeyProc = CallWindowProc(DefaultProc, hwnd, uMsg, wParam, lParam)
End Function

'■BeginSubClass 
'■機能:サブクラス化を開始する。 
Private Sub BeginHotKeyWatch(oControl As Object)

    Static bAlready As Boolean
    Dim DefaultProc As Long

    If Not bAlready Then
        Set colDProc = New Collection
        bAlready = True
    End If

    'サブクラス化実行 
    DefaultProc = SetWindowLong(oControl.hwnd, GWL_WNDPROC, AddressOf HotKeyProc)

    '元のWindowProcのアドレスを保存 
    colDProc.Add DefaultProc, CStr(oControl.hwnd)

End Sub
'■EndSubClass 
'■機能:サブクラス化を終了します。 
Private Sub EndHotKeyWatch(oControl As Object)

    Dim ret As Long
    Dim DefaultProc As Long

    'WindowProcのアドレスを元に戻す。 
    DefaultProc = colDProc(CStr(oControl.hwnd))
    ret = SetWindowLong(oControl.hwnd, GWL_WNDPROC, DefaultProc)
    colDProc.Remove CStr(oControl.hwnd)

End Sub

Public Function CreateHotKey(BaseForm As Form, ByVal HotKeyName As StringByVal Shift As IntegerByVal lVKey As LongAs Long
    
    Dim nID     As Long
    Dim IsShift As Boolean
    Dim IsCtrl  As Boolean
    Dim IsAlt   As Boolean
    Dim fsModifiers As Long
    
    IsShift = Shift And vbShiftMask
    IsCtrl = Shift And vbCtrlMask
    IsAlt = Shift And vbAltMask
    
    fsModifiers = IIf(IsShift, MOD_SHIFT, 0) + IIf(IsCtrl, MOD_CONTROL, 0) + IIf(IsAlt, MOD_ALT, 0)
    
    HotKeyID = GlobalAddAtom(HotKeyName)
    Call RegisterHotKey(BaseForm.hwnd, nID, fsModifiers, lVKey)
    CreateHotKey = HotKeyID
    Set m_BaseForm = BaseForm
    
    Call BeginHotKeyWatch(BaseForm)
    
End Function

Public Sub DeleteHotKey(BaseForm As Form)

    Call EndHotKeyWatch(BaseForm)

    Call UnregisterHotKey(BaseForm.hwnd, HotKeyID)
    Call GlobalDeleteAtom(HotKeyID)
    
End Sub


次にフォームに以下のコードを追加します。

Private Sub Form_Load()

    'Ctrl + N が押されたらGotHotKeyプロシージャを呼び出すように設定する 
    CreateHotKey Me"MyHoykey", vbCtrlMask, vbKeyN

End Sub

Public Sub GotHotkey()

    Me.WindowState = vbNormal
    
End Sub

Private Sub Form_Unload(Cancel As Integer)

    DeleteHotKey Me

End Sub
投稿者 じょにー  (社会人) 投稿日時 2009/3/3 19:20:29
るきお様、回答ありがとうございました
標準機能での実現は、不可能なのですね、参考コードまで、書いていただき、ありがとうございます
教えていただいた、コードを参考に、色々、試行錯誤やってみます、どうも、ありがとうございました
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/3/3 19:33:09
API を使う以外の方法として、DirectInput を使う方法があります。

下記は、マウスとキーボードの入力をとらえるサンプルです。
http://www.geocities.co.jp/SiliconValley/7406/tips/mouse/mouse2.html