سؤال

أكتب تمديدًا لتطبيق موجود يحتاج إلى التعامل مع أحداث إدراج/إزالة USB. أنا أعرف vid/pid لجهاز الاهتمام. ومع ذلك ، ليس لدي إمكانية الوصول إلى مقبض النافذة ، لذلك لا أعرف إذا RegisterDeviceNotification سيكون مفيدًا للغاية ، ما لم تكن هناك طريقة للحصول على المقبض عبر WINAPI. ما هي أفضل طريقة للكشف عن أحداث إدراج/إزالة USB مع C ++؟

هذا الرمز النموذج على موقع Microsoft يوضح كيفية تلقي إشعارات الحدث عبر WMI:

كيف يمكن تعديلها لتلقي أحداث إدراج/إزالة USB؟ أو ، هل هناك طريقة أخرى يجب أن أذهب إليها؟ أنا أستخدم Visual Studio 2008. شكرًا.

معلومات إضافية

هذا ما لدي حتى الآن (ناقص التعامل مع الأخطاء):

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

يدخل الكمبيوتر WndProc, ، ولكن ليس عندما أقوم بإزالة/أدخل جهاز USB الخاص بي. يبدو أن جهاز الكمبيوتر لا يدخل أبدًا OnDeviceChange. نقدر أي نصائح. أحتاج إلى التعامل مع الإدراج/إزالة الجهاز غير المتوقع لجهاز USB. إذا أحدث فرقًا ، يظهر جهاز USB كمنفذ COM الظاهري إلى Windows. شكرًا.

معلومات editional: الدعوة CreateWindowEx باستخدام الفصل atom عاد من قبل RegisterClassEx فشل في رسالة الخطأ ، "لا يمكن العثور على فئة النافذة."

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

نهج جديد

أنا أيضًا أحاول هذا النهج الجديد. أحاول الحصول على كتابة نافذة للرسالة فقط لتلقي رسائل تغيير الإخطار لجهاز لجهاز USB. أنا أستخدم MFC و C ++ و Visual Studio 2008. كل شيء يجمع ، ويتم تشغيله دون تحطم أو قفل ، لكن معالج الأحداث لم يتم تشغيله أبدًا. يتم تثبيت جهاز الاهتمام على 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 هو مبالغة هنا ، IMHO.

نصائح أخرى

هناك عينة MSDN على وجه التحديد لحالتك ، في الكود الأصلي.

التسجيل لإشعار الجهاز

من الأفضل أن تفعل ذلك بهذه الطريقة من VIA 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