WM_DEVICECHANGE 消息未发送到 WndProc - C++

发布于 2024-10-06 04:36:53 字数 3776 浏览 8 评论 0原文

我的应用程序创建一个窗口来处理 WM_DEVICECHANGE Windows 消息。 WndProc 确实被调用了几次,直到我的应用程序调用一个函数来轮询键盘事件,但无论出于何种原因,当我移除或插入 USB 设备时它都不会被调用。

这是我的 USB 设备的 GUID。我确信它是正确的:

static const GUID _guidForCP210xDevices = {
    0xA2A39220, 0x39F4, 0x4B88, 0xAE, 0xCB, 0x3D, 0x86, 0xA3, 0x5D, 0xC7, 0x48
};

这就是我的窗口的创建方式:

m_hInstance = ::GetModuleHandle( NULL );

if ( m_hInstance == NULL )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to retrieve the module handle.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

m_wcx.cbSize = sizeof(WNDCLASSEX);  // size of structure
m_wcx.style = CS_HREDRAW | CS_VREDRAW; // initially minimized
m_wcx.lpfnWndProc = &WndProc;       // points to window procedure
m_wcx.cbClsExtra = 0;               // no extra class memory
m_wcx.cbWndExtra = 0;               // no extra window memory
m_wcx.hInstance = m_hInstance;      // handle to instance
m_wcx.hIcon = ::LoadIcon( NULL, IDI_APPLICATION ); // default app icon
m_wcx.hCursor = ::LoadCursor( NULL, IDC_ARROW ); // standard arrow cursor
m_wcx.hbrBackground = NULL;         // no background to paint
m_wcx.lpszMenuName = NULL;          // no menu resource
m_wcx.lpszClassName = _pwcWindowClass; // name of window class
m_wcx.hIconSm = NULL;               // search system resources for sm icon

m_atom = ::RegisterClassEx( &m_wcx );

if ( m_atom == 0 )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to register window class.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

m_hWnd = ::CreateWindow(
    _pwcWindowClass,
    _pwcWindowName,
    WS_ICONIC,
    0,
    0,
    CW_USEDEFAULT,
    0,
    NULL,
    NULL,
    m_hInstance,
    NULL
    );

if ( m_hWnd == NULL )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to create window.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

::ShowWindow( m_hWnd, SW_HIDE );    // function does not fail

if ( RegisterForNotification() != ERROR_SUCCESS )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to register for device notification.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

这是我注册设备通知的方式:

static DEV_BROADCAST_DEVICEINTERFACE dbt = {0};

ASSERT(m_hWnd != NULL);

// Populate DEV_BROADCAST_DEVICEINTERFACE structure.
dbt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
dbt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
dbt.dbcc_classguid = _guidForCP210xDevices;

// Register for HID devic notifications
m_hNotify = RegisterDeviceNotification( m_hWnd, &dbt, DEVICE_NOTIFY_WINDOW_HANDLE );

if ( m_hNotify == NULL )
{
    TRACE(_T("CNotifyWindow::RegisterForNotification : Failed to register for device notification.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    return ::GetLastError();
}

return ERROR_SUCCESS;

我的 WndProc 函数如下所示:

static LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    DEV_BROADCAST_HDR * pHeader = reinterpret_cast<DEV_BROADCAST_HDR *>(lParam);

    switch ( uMsg )
    {
    case WM_DEVICECHANGE:
        if ( pHeader != NULL )
        {
            if ( pHeader->dbch_devicetype == DBT_DEVTYP_PORT )
            {
                OnDeviceChange( wParam );
            }
        }
        break;

    default:
        // Do nothing.
        break;
    }

    return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
}

有谁知道我做错了什么?谢谢。

My application creates a window for the purpose of handling the WM_DEVICECHANGE Windows message. WndProc does get called several times, until my application calls a function to poll for keyboard events, but for whatever reason it does not get called when I remove or insert my USB device.

This is the GUID for my USB device. I'm sure it's correct:

static const GUID _guidForCP210xDevices = {
    0xA2A39220, 0x39F4, 0x4B88, 0xAE, 0xCB, 0x3D, 0x86, 0xA3, 0x5D, 0xC7, 0x48
};

This is how my window is created:

m_hInstance = ::GetModuleHandle( NULL );

if ( m_hInstance == NULL )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to retrieve the module handle.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

m_wcx.cbSize = sizeof(WNDCLASSEX);  // size of structure
m_wcx.style = CS_HREDRAW | CS_VREDRAW; // initially minimized
m_wcx.lpfnWndProc = &WndProc;       // points to window procedure
m_wcx.cbClsExtra = 0;               // no extra class memory
m_wcx.cbWndExtra = 0;               // no extra window memory
m_wcx.hInstance = m_hInstance;      // handle to instance
m_wcx.hIcon = ::LoadIcon( NULL, IDI_APPLICATION ); // default app icon
m_wcx.hCursor = ::LoadCursor( NULL, IDC_ARROW ); // standard arrow cursor
m_wcx.hbrBackground = NULL;         // no background to paint
m_wcx.lpszMenuName = NULL;          // no menu resource
m_wcx.lpszClassName = _pwcWindowClass; // name of window class
m_wcx.hIconSm = NULL;               // search system resources for sm icon

m_atom = ::RegisterClassEx( &m_wcx );

if ( m_atom == 0 )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to register window class.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

m_hWnd = ::CreateWindow(
    _pwcWindowClass,
    _pwcWindowName,
    WS_ICONIC,
    0,
    0,
    CW_USEDEFAULT,
    0,
    NULL,
    NULL,
    m_hInstance,
    NULL
    );

if ( m_hWnd == NULL )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to create window.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

::ShowWindow( m_hWnd, SW_HIDE );    // function does not fail

if ( RegisterForNotification() != ERROR_SUCCESS )
{
    TRACE(_T("CNotifyWindow::CNotifyWindow : Failed to register for device notification.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    THROW(::GetLastError());
}

This is how I register for device notification:

static DEV_BROADCAST_DEVICEINTERFACE dbt = {0};

ASSERT(m_hWnd != NULL);

// Populate DEV_BROADCAST_DEVICEINTERFACE structure.
dbt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
dbt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
dbt.dbcc_classguid = _guidForCP210xDevices;

// Register for HID devic notifications
m_hNotify = RegisterDeviceNotification( m_hWnd, &dbt, DEVICE_NOTIFY_WINDOW_HANDLE );

if ( m_hNotify == NULL )
{
    TRACE(_T("CNotifyWindow::RegisterForNotification : Failed to register for device notification.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
    return ::GetLastError();
}

return ERROR_SUCCESS;

My WndProc function looks like this:

static LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    DEV_BROADCAST_HDR * pHeader = reinterpret_cast<DEV_BROADCAST_HDR *>(lParam);

    switch ( uMsg )
    {
    case WM_DEVICECHANGE:
        if ( pHeader != NULL )
        {
            if ( pHeader->dbch_devicetype == DBT_DEVTYP_PORT )
            {
                OnDeviceChange( wParam );
            }
        }
        break;

    default:
        // Do nothing.
        break;
    }

    return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
}

Does anyone know what I'm doing wrong? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

长途伴 2024-10-13 04:36:53

您缺少一个消息泵来从队列中检索通知并将它们分派到您的 WndProc。消息泵实际上是一个循环,用于检查消息并同步调用适当的 WndProc。 MSDN 有一些关于它们的有用信息。我不知道您的代码的上下文是什么,所以我不确定您是否只需要在 RegisterForNotification 之后插入一个泵,或者是否需要进行更大的架构更改。

You're missing a message pump to retrieve the notifications from the queue and dispatch them to your WndProc. The message pump is effectively a loop that checks for messages and calls the appropriate WndProc synchronously. MSDN has some good information on them. I don't know what the context of your code is, so I'm not sure if you just need to insert a pump after RegisterForNotification or if a larger architectural change is necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文