简体   繁体   中英

WM_DEVICECHANGE lParam is null

I want to detect the insertion and removing of any USB drive in my computer. I am not experienced in Windows GUI programming, and usually use Qt, but I had to use the Win32 API this time.

The problem is that lParam is always null.

I read that I need to use RegisterDeviceNotification() , but I used it and even with DEVICE_NOTIFY_ALL_INTERFACE_CLASSES , lParam is always null, however the function succeeds.

This is my code. Most of it I took from a Win32 app template from Visual Studio 2015:

#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;
}

You need to check wParam first and then figure out what to expect from lParam (it can be NULL in some situations). Also there is a break missing after case.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM