Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213

Перехват wm_devicechange

09.07.2017, 07:44. Показов 2351. Ответов 18

Студворк — интернет-сервис помощи студентам
Здравствуйте написал простенькую программку по отлову сообщений вставки usb носителей. Собственно данный код отлавливает события.Приходит и DBT_DEVTYP_DEVICEINTERFACE и DBT_DEVTYP_VOLUME Но мне нужно сделать так чтобы программа отлавливала события без окна(или хотя бы чтобы окно было скрыто). Но когда я делаю
C++
1
ShowWindow(hWnd, SW_HIDE);
программа ловит только DBT_DEVTYP_VOLUME. Так собственно вопрос как заставить приходить и DBT_DEVTYP_DEVICEINTERFACE в приложении со скрытым окном или в консольным приложением?.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Win32Project6.cpp: определяет точку входа для приложения.
//
 
#include "stdafx.h"
#include "Win32Project6.h"
#include <Dbt.h>
#include <iostream>
#include <hidclass.h>
using namespace std;
#define MAX_LOADSTRING 100
 
// Глобальные переменные:
HINSTANCE hInst;                                // текущий экземпляр
WCHAR szTitle[MAX_LOADSTRING];                  // Текст строки заголовка
WCHAR szWindowClass[MAX_LOADSTRING];            // имя класса главного окна
static GUID GUID_DEVINTERFACE_USB_DEVICE1 = { 0xA5DCBF10L, 0x6530, 0x11D2,
{ 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
// Отправить объявления функций, включенных в этот модуль кода:
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)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
 
    // TODO: разместите код здесь.
 
    // Инициализация глобальных строк
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WIN32PROJECT6, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);
 
    // Выполнить инициализацию приложения:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
 
    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT6));
 
    MSG msg;
 
    // Цикл основного сообщения:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
 
    return (int) msg.wParam;
}
 
 
 
//
//  ФУНКЦИЯ: MyRegisterClass()
//
//  НАЗНАЧЕНИЕ: регистрирует класс окна.
//
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_WIN32PROJECT6));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WIN32PROJECT6);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
 
    return RegisterClassExW(&wcex);
}
 
//
//   ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
//   НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
//   КОММЕНТАРИИ:
//
//        В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
//        создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной
 
   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
     CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
 
 //  HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_ICONIC,
    //   0, 0, CW_USEDEFAULT, 0, 0,
    //   NULL, GetModuleHandle(0), (void*)&GUID_DEVINTERFACE_USB_DEVICE1);
 
   if (!hWnd)
   {
      return FALSE;
   }
 
   ShowWindow(hWnd, SW_SHOW);
  // ShowWindow(hWnd, SW_HIDE);
   UpdateWindow(hWnd);
 
   return TRUE;
}
 
//
//  ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  НАЗНАЧЕНИЕ:  обрабатывает сообщения в главном окне.
//
//  WM_COMMAND — обработать меню приложения
//  WM_PAINT — отрисовать главное окно
//  WM_DESTROY — отправить сообщение о выходе и вернуться
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DEVICECHANGE:
    {
        if (wParam == DBT_DEVICEARRIVAL)
        {
            DEV_BROADCAST_HDR *fd = PDEV_BROADCAST_HDR(lParam);
            DWORD d = fd->dbch_devicetype;
            if (d == DBT_DEVTYP_DEVICEINTERFACE)
            {
                cout << "INTERFACE" << endl;
            }
            if (d == DBT_DEVTYP_VOLUME)
            {
                cout << "VOLUME" << endl;
            }
        }
    }
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Разобрать выбор в меню:
            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:
        {
            DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
            ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
            NotificationFilter.dbcc_size = sizeof(NotificationFilter);
            NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
            NotificationFilter.dbcc_reserved = 0;
            NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE1;
            
            HDEVNOTIFY hDevNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Добавьте сюда любой код прорисовки, использующий HDC...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
 
// Обработчик сообщений для окна "О программе".
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;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.07.2017, 07:44
Ответы с готовыми решениями:

WM_DEVICECHANGE
Здравствуйте, при подключении или отключении usb устройства сообщение &quot;WM_DEVICECHANGE&quot; приходить несколько раз: Remove - ...

WinAPI C++ WM_DEVICECHANGE
Вообщем цель определить любое воткнутое USB устройство. Выбрал WIN API поскольку жрет мало ресурсов, выбрал С++ потому что он не тащит за...

Грабли с WM_DEVICECHANGE
Потратил кучу времени на изучение структур связанных с WM_DEVICECHANGE. Все работает как надо wParam == DBT_DEVICEARRIVAL , отлавливает...

18
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.07.2017, 21:08
Вместо SW_HIDE лучше использовать HWND_MESSAGE в CreateWindow.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
09.07.2017, 22:13  [ТС]
вместо
C++
1
2
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
     CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
использовал
C++
1
HWND hWnd=CreateWindowEx(0, szWindowClass, szTitle, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
итог wm_devicechange вообще не приходит
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 09:29
А RegisterDeviceNotification у тебя вызывается?
Тут загвоздка в том, что без RegisterDeviceNotification сообщение WM_DEVICECHANGE
приходит только в top-level окна. Если ты делаешь ShowWindow(SW_HIDE) или создаешь
окно с HWND_MESSAGE, то окно таким не является и сообщение не приходит.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 11:13  [ТС]
RegistrDeviceNotification у меня в обработке WM_PAINT. Я так понял что событие wm_paint не приходит когда я создаю окно с hwnd_message поэтому registerdevicenotification не выполняется.

Добавлено через 33 минуты
Я так понял если использовать hwnd_message то в каком событии лучше регистрировать registerdevicenotification? В wm_create?

Добавлено через 19 минут
В итоге c hwnd_message создал глобальную булевую переменную и при первом заходе в wm_create регистрирую registerdevicenotification с dbt decrypted interface. И оно приходит. Не приходит dbt_devtype_volume. Но как я правильно понимаю его теперь тоже нужно регистрировать в отдельной registrdevicenotification?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 11:27
Цитата Сообщение от kold2015 Посмотреть сообщение
RegistrDeviceNotification у меня в обработке WM_PAINT.
Так перенеси его куда-нибудь в обработчик WM_CREATE.
В WM_PAINT таким вещам не место (эти сообщения ведь приходят сотнями и тысячами).

Цитата Сообщение от kold2015 Посмотреть сообщение
Не приходит dbt_devtype_volume. Но как я правильно понимаю его теперь тоже нужно регистрировать в отдельной registrdevicenotification?
Да.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 12:05  [ТС]
Да Я уже перенес все wm_create

Регистрирую dev broadcast volume после dev broadcast dev interface

C++
1
2
3
4
5
DEV_BROADCAST_VOLUM notfilt;
notfilt.dbcv_size = sizeof (notfilt);
notfilt.dbcv_devicetype = DBT_DEVTYPE_VOLUME;
 
HDEVNOTIFY hDevNotify2= Registerdevicenotification(hWnd, &notfilt, DEVICE_NOTIFY_WINDOW_HANDLE);
Регистрирую так, но DBT_DEVTYPE_VOLUME все равно не приходит.
Я подозреваю что нужно еще что-то задать?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 12:09
Да. См. описание структуры DEV_BROADCAST_VOLUME в MSDN:
dbcv_unitmask

The logical unit mask identifying one or more logical units. Each bit in the mask corresponds to one logical drive. Bit 0 represents drive A, bit 1 represents drive B, and so on.

dbcv_flags

This parameter can be one of the following values.
Value Meaning

DBTF_MEDIA (0x0001)
Change affects media in drive. If not set, change affects physical device or drive.

DBTF_NET (0x0002)
Indicated logical volume is a network volume.
Еще можно использовать DEV_BROADCAST_HANDLE, передавая в dbch_handle хэндл конкретного тома,
тогда уведомления будут приходить только при событиях на соответствующем диске.
Так, например, можно отслеживать попытки извлечения USB-флэшки.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 12:36  [ТС]
Я так понимаю нужно задать как минимум еще dbcv_unitmask но я не знаю как...
Мне нужно чтобы приходило при втыкании любого USB носителя. Как задать значение не подскажете?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 12:45
Попробуй так:
C
1
dbcv_unitmask = 0x3FFFFFF; // 26 младших битов установлено в 1 (26 = к-во символов A-Z).
Впрочем, я не уверен, что можно подписываться на сообщения от несуществующих томов...
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 14:29  [ТС]
Те вы удтверждаете dev type volume нельзя поймать через окно hwnd_message?

Добавлено через 39 минут
Задал маску сообщение все равно не приходит dbt_devtype_volume
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 14:37
Цитата Сообщение от kold2015 Посмотреть сообщение
Те вы удтверждаете dev type volume нельзя поймать через окно hwnd_message?
Нет, я такого не говорил.
Просто подписываться на сообщения от тома, как мне кажется, можно только если
сам том существует.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 15:10  [ТС]
Так как же получить DBT_DEVTYPE_VOLUME .......?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 15:28
Цитата Сообщение от kold2015 Посмотреть сообщение
Задал маску сообщение все равно не приходит dbt_devtype_volume
Ну ок, а что возвращает функция RegisterDeviceNotification? И что при этом в GetLastError()?
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 16:25  [ТС]
Getlasterror возвращает 1066 по описанию это error_service_specific_error
Registerdevicenotification возвращает null
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 16:33
Значит, предположение подтвердилось и подписываться на сообщение WM_DEVICECHANGE + volume
можно только для существующих томов (как и для DBT_DEVTYPE_HANDLE, например).

А отслеживать появление тома можно иначе.
Например, RegisterDeviceNotification + DBT_DEVTYP_DEVICEINTERFACE и по приходу сообщения
WM_DEVICECHANGE с кодом DBT_DEVICEARRIVAL искать новые буквы дисков в GetLogicalDriveStrings.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 16:54  [ТС]
Те вы предлагаете как я понял ПОСЛЕ запуска программы делать снимок дисков а потом в wm_devicechange проверять его?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.07.2017, 16:58
Да, как вариант.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 18:11  [ТС]
Спасибо за помощь. Но возможно будут еще вопросы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.07.2017, 18:11
Помогаю со студенческими работами здесь

Как обработать WM_DEVICECHANGE?
Нужна помощь, как заделать хук на событие - вставка изъятие USB-устройства???? Алгоритм такой воткнул/вынул флешку и получил месэдж от...

WM_DEVICECHANGE RegisterDeviceNotification PDEV_BROADCAST_HDR
При приведении происходит исключение System.OverflowException что-то там переполнение из-за чего так? case DBT_DEVICEARRIVAL: { ...

Не могу разобраться с WM_DEVICECHANGE
Здравствуйте! Необходимо перертсовать дерево со списком дисков в системе, когда в(из) USB разъем(а) вставляется (вынимается) флешка или...

RegisterDeviceNotification / WM_DEVICECHANGE / VID _ PID
Не могу подписаться на WM_DEVICECHANGE какие-то неизвестные ошибки не пойму что не так virtual void WndProc(Message% m) override ...

Обработка события подключения и отключения USB(WM_DEVICECHANGE)
Всем привет . Такая задача, требуется отследить подключение и отключение USB. Следующий код работает но выдает одно и тоже в события...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru