2

USBドライブが挿入されたことを検出しようとしています。現在、ダミーウィンドウを作成してRegisterDeviceNotification実行しています。ただし、ウィンドウがメッセージを受信して​​いないように見えるため、私のアプローチは正しいとは思いません。

#include <iostream>
#define WINVER 0x501
#include <windows.h>
#include <dbt.h>
#include "devicehandler.h"
#include "remover.h"

DeviceHandler::DeviceHandler(Remover* remover)
{
    this->remover = remover;
    this->hWnd = this->createHandleWindow();
    this->registerDeviceHandler();
    this->messageLoop(this->hWnd);
}

DeviceHandler::~DeviceHandler()
{
    this->unregisterDeviceHandler();
}

void DeviceHandler::messageLoop(HWND hWnd)
{
    std::cerr << "Entering message loop." << std::endl; // Gets here!

    MSG msg;
    while (GetMessage(&msg, this->hWnd, 0, 0)) {
        std::cerr << "Loop!" << std::endl; // Does not get here!
        switch (msg.message) {
            case WM_DEVICECHANGE:
                {
                    PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR) msg.lParam;
                    switch(msg.wParam) {
                        case DBT_DEVICEARRIVAL:
                            std::cerr << "Device added!" << std::endl;
                            break;
                        default:
                            std::cerr << "Other device event." << std::endl;
                            break;
                    }
                    break;
                }
            default:
                break;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

HWND DeviceHandler::createHandleWindow()
{
    std::cerr << "Creating handle window... ";

    HWND hWnd = CreateWindow(NULL, NULL, WS_ICONIC, 0, 0, CW_USEDEFAULT, 0,
                             NULL, NULL, GetModuleHandle(NULL), NULL);
    ShowWindow(hWnd, SW_HIDE);

    std::cerr << "done!" << std::endl;
    return hWnd;
}

void DeviceHandler::registerDeviceHandler()
{
    std::cerr << "Device notification handling... ";
    // GUID guid = { 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } };
    GUID guid = { 0x25dbce51, 0x6c8f, 0x4a72, { 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 } };
    DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
    ZeroMemory(&notificationFilter, sizeof(notificationFilter));
    notificationFilter.dbcc_size       = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    notificationFilter.dbcc_classguid  = guid;

    this->deviceNotifier = RegisterDeviceNotification(this->hWnd,
                                                      &notificationFilter,
                                                      DEVICE_NOTIFY_WINDOW_HANDLE);
    std::cerr << "done!" << std::endl;
}

void DeviceHandler::unregisterDeviceHandler()
{
    UnregisterDeviceNotification(this->deviceNotifier);
}

これはメッセージ ループを配置するのに適切な場所ではないと推測していますが、WinAPI はあまり得意ではありません。プログラムをメッセージ ループに入れるにはどうすればよいですか? (また、できればデバイス通知も登録してください。)

4

2 に答える 2

2

メッセージのみの Windowを作成する必要があります。デバイス通知や電源イベントなど、登録したメッセージを受信できますが、表示されることはありません。

メッセージのみのウィンドウは RegisterClassEx に登録する必要があります

ウィンドウ クラスを登録したら、ウィンドウ クラス名を HWND_MESSAGE と共に親として CreateWindowEx に渡します。CreateWindow は、CreateWindowEx代わりに次のように使用する必要があります。

HWND hWnd = CreateWindowEx(0, myClassName, _T("This is not the class name"), 
                0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, this);

コールバックのように WNDPROC を呼び出すTranslateMessageおよびDispathMessageと共に GetMessage を引き続き使用します。それは何も悪いことではありませんが、Windows プロシージャで DeviceHandler クラスへのポインターを失います。

thisこれが、の最後のパラメータとして渡す理由ですCreateWindowEx。メッセージを受信したときにそれを取得WM_CREATEし、 と を使用して Windows クラスのユーザー データに設定できSetWindowLongPtrますGWLP_USERDATA。その後のすべての呼び出しは、ポインタを取得GetWindowLongPtrして DeviceHandler オブジェクトにキャストします。

これはテクニックの良い例です。

ルールに従ってプレイするには、使用する独自のウィンドウ クラスを登録する必要がありますが、ウィンドウ クラスを使用GWLP_USERDATAしても動作するはずSTATICです。

最後の注意:処理しないメッセージについては、必ずDefWindowProcを呼び出してください。

于 2012-09-25T13:12:27.107 に答える
1

有効なクラス名を指定しなかったため、ウィンドウが作成されないことが問題のようです。HWNDこの場合は が返されNULL、デバイスはそれを登録してメッセージを送信できません。

他の回答で提案されているように、デバイス通知を受信する目的でメッセージのみのウィンドウを使用できます。ただし、この場合、ウィンドウ クラスを登録する必要はSTATICありません。たとえば、定義済みのクラス名を使用できます (実際には独自のウィンドウ プロシージャを指定する必要がないため)。

HWND hwnd = CreateWindowEx(0, "STATIC", 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
于 2012-09-25T14:33:45.607 に答える