C++ WM_DEVICECHANGE LPRAM为空

C++ WM_DEVICECHANGE LPRAM为空,c++,winapi,C++,Winapi,我想检测计算机中任何USB驱动器的插入和移除。我没有Windows GUI编程经验,通常使用Qt,但这次我不得不使用Win32 API 问题是lParam始终为空 我读到我需要使用registerDeviceNotify(),但我使用了它,即使使用DEVICE\u NOTIFY\u ALL\u INTERFACE\u class,lParam始终为空,但函数成功 这是我的密码。我从Visual Studio 2015的Win32应用程序模板中获取了大部分内容: #define MAX_LOADS

我想检测计算机中任何USB驱动器的插入和移除。我没有Windows GUI编程经验,通常使用Qt,但这次我不得不使用Win32 API

问题是
lParam
始终为空

我读到我需要使用
registerDeviceNotify()
,但我使用了它,即使使用
DEVICE\u NOTIFY\u ALL\u INTERFACE\u class
lParam
始终为空,但函数成功

这是我的密码。我从Visual Studio 2015的Win32应用程序模板中获取了大部分内容:

#define MAX_LOADSTRING 100


HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                 _In_opt_ HINSTANCE hPrevInstance,
                 _In_ LPWSTR    lpCmdLine,
                 _In_ int       nCmdShow)
{
// TODO: Place code here.

// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_USBSPREAD, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
    return FALSE;
}

HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(IDC_USBSPREAD));


MSG msg;

// Main message loop:
while (GetMessageW(&msg, nullptr, 0, 0))
{
    if (!TranslateAcceleratorW(msg.hwnd, hAccelTable, &msg))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
}

return (int) msg.wParam;
}



ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style          = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc    = WndProc;
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
wcex.hInstance      = hInstance;
wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_USBSPREAD));
wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_USBSPREAD);
wcex.lpszClassName  = szWindowClass;
wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassExW(&wcex);
}


GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72,
0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable

HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, (void*)&WceusbshGUID);

if (!hWnd)
{
  return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}


 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM         lParam)
{

  switch (message)
 {
 case WM_DEVICECHANGE:
 {
    //if (!lParam) break;
    PDEV_BROADCAST_HDR hdr = (PDEV_BROADCAST_HDR)lParam;
    if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
        PDEV_BROADCAST_DEVICEINTERFACE_W device = (PDEV_BROADCAST_DEVICEINTERFACE_W)hdr;
        if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
            if (wParam == DBT_DEVICEARRIVAL) {
                MessageBoxA(0, "a usb was inserted", "", 0);
            }
            else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
                MessageBoxA(0, "a usb was removed", "", 0);
            }
        }
    }
}
case WM_NCCREATE: // before window creation
    return true;
    break;
case WM_CREATE :
    {
    LPCREATESTRUCT params = (LPCREATESTRUCT)lParam;
    GUID InterfaceClassGuid = *((GUID*)params->lpCreateParams);
    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
    ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    NotificationFilter.dbcc_classguid = InterfaceClassGuid;
    HDEVNOTIFY dev_notify = RegisterDeviceNotification(hWnd, &NotificationFilter,
        DEVICE_NOTIFY_WINDOW_HANDLE);
        if (!dev_notify) {
            string error = "failed with error : ";
            error += GetLastError();
            MessageBoxA(0, error.c_str(), 0, 0);
        }
        else {
            MessageBoxA(0, "succeeded", "", 0);
        }
    }
case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code that uses hdc here...
        EndPaint(hWnd, &ps);
    }
    break;
case WM_DESTROY:
    PostQuitMessage(0);
    break;

default:
    return DefWindowProc(hWnd, message, wParam, lParam);
}



return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
    return (INT_PTR)TRUE;

case WM_COMMAND:
    if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
    {
        EndDialog(hDlg, LOWORD(wParam));
        return (INT_PTR)TRUE;
    }
    break;
}
return (INT_PTR)FALSE;
}

您需要首先检查
wParam
,然后确定从
lParam
可以得到什么(在某些情况下,它可以是
NULL
)。此外,案例后还有一个
中断
缺失

case WM_DEVICECHANGE:
{
    switch(wParam)
    {
        case DBT_DEVICEARRIVAL:
        {
            assert(lParam);                
            ::MessageBoxW(NULL, L"a usb was inserted", L"", MB_OK);
            ::PDEV_BROADCAST_HDR hdr{reinterpret_cast<::PDEV_BROADCAST_HDR>(lParam)};
            if(hdr)
            {
                // check info...
            }
            break;
        }
        default:
        {
            // do nothing...
            break;
        }
    } // switch(wParam)
    break;
}
案例WM_设备变更:
{
交换机(wParam)
{
案例DBT_设备到达:
{
断言(LPRAM);
::MessageBoxW(空,L“已插入usb”,L“”,MB_正常);
::PDEV_BROADCAST_HDR HDR{reinterpret_cast(lParam)};
如果(hdr)
{
//检查信息。。。
}
打破
}
违约:
{
//什么也不做。。。
打破
}
}//开关(wParam)
打破
}

您需要首先检查
wParam
,然后确定从
lParam
中可以得到什么(在某些情况下,它可以是
NULL
)。此外,案例后还有一个
中断
缺失

case WM_DEVICECHANGE:
{
    switch(wParam)
    {
        case DBT_DEVICEARRIVAL:
        {
            assert(lParam);                
            ::MessageBoxW(NULL, L"a usb was inserted", L"", MB_OK);
            ::PDEV_BROADCAST_HDR hdr{reinterpret_cast<::PDEV_BROADCAST_HDR>(lParam)};
            if(hdr)
            {
                // check info...
            }
            break;
        }
        default:
        {
            // do nothing...
            break;
        }
    } // switch(wParam)
    break;
}
案例WM_设备变更:
{
交换机(wParam)
{
案例DBT_设备到达:
{
断言(LPRAM);
::MessageBoxW(空,L“已插入usb”,L“”,MB_正常);
::PDEV_BROADCAST_HDR HDR{reinterpret_cast(lParam)};
如果(hdr)
{
//检查信息。。。
}
打破
}
违约:
{
//什么也不做。。。
打破
}
}//开关(wParam)
打破
}

消息处理不正确。设备插入会生成多个通知,程序在获得所需通知之前失败。您必须首先查看wparam以检查它是否是您想要的消息。然后您可以决定LPRAM是否有趣。现在,它在到达wparam检查之前就停止了。是的,VTT回答很好,我必须先检查wparam。现在问题已经解决,消息处理不正确。设备插入会生成多个通知,程序在获得所需通知之前失败。您必须首先查看wparam以检查它是否是您想要的消息。然后您可以决定LPRAM是否有趣。现在,它在到达wparam检查之前就停止了。是的,VTT回答很好,我必须先检查wparam。现在问题解决了