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

Перехват wm_devicechange

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

Author24 — интернет-сервис помощи студентам
Здравствуйте написал простенькую программку по отлову сообщений вставки 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
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.07.2017, 07:44
Ответы с готовыми решениями:

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

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

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

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

18
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
09.07.2017, 21:08 2
Вместо SW_HIDE лучше использовать HWND_MESSAGE в CreateWindow.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
09.07.2017, 22:13  [ТС] 3
вместо
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
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 09:29 4
А RegisterDeviceNotification у тебя вызывается?
Тут загвоздка в том, что без RegisterDeviceNotification сообщение WM_DEVICECHANGE
приходит только в top-level окна. Если ты делаешь ShowWindow(SW_HIDE) или создаешь
окно с HWND_MESSAGE, то окно таким не является и сообщение не приходит.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 11:13  [ТС] 5
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
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 11:27 6
Цитата Сообщение от 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  [ТС] 7
Да Я уже перенес все 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
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 12:09 8
Да. См. описание структуры 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  [ТС] 9
Я так понимаю нужно задать как минимум еще dbcv_unitmask но я не знаю как...
Мне нужно чтобы приходило при втыкании любого USB носителя. Как задать значение не подскажете?
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 12:45 10
Попробуй так:
C
1
dbcv_unitmask = 0x3FFFFFF; // 26 младших битов установлено в 1 (26 = к-во символов A-Z).
Впрочем, я не уверен, что можно подписываться на сообщения от несуществующих томов...
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 14:29  [ТС] 11
Те вы удтверждаете dev type volume нельзя поймать через окно hwnd_message?

Добавлено через 39 минут
Задал маску сообщение все равно не приходит dbt_devtype_volume
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 14:37 12
Цитата Сообщение от kold2015 Посмотреть сообщение
Те вы удтверждаете dev type volume нельзя поймать через окно hwnd_message?
Нет, я такого не говорил.
Просто подписываться на сообщения от тома, как мне кажется, можно только если
сам том существует.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 15:10  [ТС] 13
Так как же получить DBT_DEVTYPE_VOLUME .......?
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 15:28 14
Цитата Сообщение от kold2015 Посмотреть сообщение
Задал маску сообщение все равно не приходит dbt_devtype_volume
Ну ок, а что возвращает функция RegisterDeviceNotification? И что при этом в GetLastError()?
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 16:25  [ТС] 15
Getlasterror возвращает 1066 по описанию это error_service_specific_error
Registerdevicenotification возвращает null
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 16:33 16
Значит, предположение подтвердилось и подписываться на сообщение 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  [ТС] 17
Те вы предлагаете как я понял ПОСЛЕ запуска программы делать снимок дисков а потом в wm_devicechange проверять его?
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
10.07.2017, 16:58 18
Да, как вариант.
0
1 / 1 / 0
Регистрация: 18.02.2014
Сообщений: 213
10.07.2017, 18:11  [ТС] 19
Спасибо за помощь. Но возможно будут еще вопросы.
0
10.07.2017, 18:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.07.2017, 18:11
Помогаю со студенческими работами здесь

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

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

RegisterDeviceNotification / WM_DEVICECHANGE / VID _ PID
Не могу подписаться на WM_DEVICECHANGE какие-то неизвестные ошибки не пойму что не так ...

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


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru