質問

USB挿入/削除イベントを処理する必要がある既存のアプリケーションの拡張機能を作成しています。私は関心のあるデバイスのVID/PIDを知っています。しかし、私はウィンドウハンドルにアクセスできないので、私は知りません RegisterDeviceNotification 経由でハンドルを取得する方法がない限り、非常に役に立ちます WINAPI. 。 C ++でUSB挿入/除去イベントを検出する最良の方法は何ですか?

Microsoft Webサイトのこのサンプルコード WMIを介してイベント通知を受信する方法を示します。

USB挿入/削除イベントを受信するには、どのように変更できますか?または、私がこれについて進むべき別の方法はありますか? Visual Studio2008を使用しています。ありがとう。

追加情報

これは私がこれまでに持っているものです(マイナスエラー処理):

DEFINE_GUID(GUID_INTERFACE_CP210x, 0x993f7832, 0x6e2d, 0x4a0f, 0xb2, 0x72, 0xe2, 0xc7, 0x8e, 0x74, 0xf9, 0x3e);

MyClass::MyClass()
{
    // Generate message-only window
    _pWndClassEx = (WNDCLASSEX *)malloc( sizeof(WNDCLASSEX) );
    memset( _pWndClassEx, 0, sizeof(WNDCLASSEX) );
    _pWndClassEx->cbSize = sizeof(WNDCLASSEX);
    _pWndClassEx->lpfnWndProc = (WNDPROC)WndProc; // function which will handle messages
    _pWndClassEx->hInstance = GetCurrentModule();
    _pWndClassEx->lpszClassName = pClassName;
    atom = RegisterClassEx( _pWndClassEx );
    _hWnd = CreateWindowEx( 0, pClassName, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );

    // Register the USB device for notification
    _pDevIF = (DEV_BROADCAST_DEVICEINTERFACE *)malloc( sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
    memset( _pDevIF, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
    _pDevIF->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    _pDevIF->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    _pDevIF->dbcc_classguid = GUID_INTERFACE_CP210x;
    _hNotifyDevNode = RegisterDeviceNotification( _hWnd, _pDevIF, DEVICE_NOTIFY_WINDOW_HANDLE );
}

static bool OnDeviceChange(UINT nEventType, DWORD dwData)
{
    switch ( nEventType )
    {
    case DBT_DEVICEARRIVAL:
        // A device has been inserted adn is now available.
        break;

    case DBT_DEVICEREMOVECOMPLETE:
        // Device has been removed.
        break;

    default:
        break;
    }

    return true;
}

static LRESULT WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    switch ( message )
    {
    case WM_DEVICECHANGE:
        OnDeviceChange( wParam, lParam ); // Set breakpoint (never gets here)
        break;

    default:
        break;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

PCが入ります WndProc, 、しかし、USBデバイスを削除/挿入するときではありません。 PCが入ることはないようです OnDeviceChange. 。どんなヒントも感謝しています。 USBデバイスの予期しない挿入/削除を処理する必要があります。違いがある場合、USBデバイスはWindowsへの仮想comポートとして表示されます。ありがとう。

ADITIONAL情報: 電話 CreateWindowEx クラスを使用します atom によって返されます RegisterClassEx 「ウィンドウクラスが見つからない」というエラーメッセージで失敗します。

_hWnd = CreateWindowEx( 0, (LPCTSTR)&atom, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );

新しいアプローチ

私もこの新しいアプローチを試しています。 USBデバイスのデバイス変更通知メッセージを受信するために、メッセージのみのウィンドウを書き込もうとしています。 MFC、C ++、およびVisual Studio2008を使用しています。すべてがコンパイルされており、クラッシュやロックアップせずに実行されますが、イベントハンドラーはトリガーされません。関心のあるデバイスは、Windowsに仮想comポートとしてインストールされています。

私の主なアプリケーションは、以下に説明するクラスをインスタンス化し、その後、キーボードポーリングからのキャラクターの入力が時間ループを使用して待機します。この待ち時間中、イベントが解雇されることを期待してUSBデバイスを削除して挿入します。

class CMessageOnlyWindow : public CWnd
{
    DECLARE_DYNAMIC(CMessageOnlyWindow)
private:
    DEV_BROADCAST_DEVICEINTERFACE * _pDevIF; // The notification filter.
    HDEVNOTIFY _hNotifyDev;             // The device notification handle.
public:
    CMessageOnlyWindow();
    virtual ~CMessageOnlyWindow();
protected:
    afx_msg BOOL OnDeviceChange( UINT nEventType, DWORD dwData );
private:
    void RegisterNotification( void );
    void UnregisterNotification( void );
protected:
    DECLARE_MESSAGE_MAP()               // Must be last.
};

簡単にするために、すべてのクリーンアップとエラー処理を削除しました。

DEFINE_GUID(GUID_INTERFACE_CP210x, 0x993f7832, 0x6e2d, 0x4a0f, \
    0xb2, 0x72, 0xe2, 0xc7, 0x8e, 0x74, 0xf9, 0x3e);

IMPLEMENT_DYNAMIC(CMessageOnlyWindow, CWnd)

CMessageOnlyWindow::CMessageOnlyWindow()
{
    CString cstrWndClassName = ::AfxRegisterWndClass( NULL );
    BOOL bCreated = this->CreateEx( 0, cstrWndClassName,
        L"CMessageOnlyWindow", 0, 0, 0, 0, 0, HWND_MESSAGE, 0 );
    this->RegisterNotification();
}

CMessageOnlyWindow::~CMessageOnlyWindow() {}

BEGIN_MESSAGE_MAP(CMessageOnlyWindow, CWnd)
    ON_WM_DEVICECHANGE()
END_MESSAGE_MAP()

afx_msg BOOL CMessageOnlyWindow::OnDeviceChange( UINT nEventType, DWORD dwData )
{
    switch ( nEventType ) // <-- Never gets here.
    {
    case DBT_DEVICEARRIVAL:
        break;

    case DBT_DEVICEREMOVECOMPLETE:
        break;

    default:
        break;
    }

    return TRUE;
}

void CMessageOnlyWindow::RegisterNotification(void)
{
    _pDevIF = (DEV_BROADCAST_DEVICEINTERFACE *)malloc( sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
    memset( _pDevIF, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
    _pDevIF->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    _pDevIF->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    _pDevIF->dbcc_classguid = GUID_INTERFACE_CP210x;
    _hNotifyDev = RegisterDeviceNotification( this->m_hWnd, _pDevIF, DEVICE_NOTIFY_WINDOW_HANDLE );
}

void CMessageOnlyWindow::UnregisterNotification(void)
{
    UnregisterDeviceNotification( _hNotifyDev );
}

どんな考えや提案は大歓迎です。詳細がない場合は、私に知らせてください、そして私はそれらを追加してうれしいです。ありがとう。

メッセージのみのウィンドウを新しいスレッドで起動する必要がありますか、それとも新しいウィンドウを作成すると、新しいスレッドが自動的にスピンオフされますか?

役に立ちましたか?

解決

待つ以外に何もしないダミーウィンドウを作成する WM_DEVICECHANGE そのウィンドウを使用して登録します RegisterDeviceNotification. 。 WMIはここで過剰なものです、私見。

他のヒント

があります MSDNサンプル 特にあなたのケースのために、ネイティブコード。

デバイス通知の登録

WMIを介してこの方法で行う方が良いです。

私はあなたの「新しいアプローチ」に従い、またOndevicechangeが呼ばれていないことを発見しました。問題は、コンソールアプリだったため、メッセージループがなかったことです。定期的に次の関数を呼び出すことはそれを修正しました。

void check_for_device_change()
{
    MSG msg; 

    const int val = PeekMessage( &msg, 0, 0, 0, PM_REMOVE );

    if( val > 0 )
    { 
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    } 
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top