使用Windows消息队列处理线程之间通信

这个程序前阵子帮一个朋友实现的,之前从未用消息队列做过类似的事情,做完后感觉其在线程同步,通信发面很好用,难怪COM也用这套机制。

程序稍微修改便能用作一般性的处理,目前实现的功能类似于监控Windows USB设备的插拔操作。

可以直接注释掉CString的使用后使用 cl /EHsc /W4 /Zi 编译,或粘贴到任意的VS中做编译。

  1 #include <Windows.h>
  2 #include <tchar.h>
  3 #include <Dbt.h>
  4 #include <setupapi.h>
  5 #include <iostream>
  6 #include <atlstr.h> // CString
  7 using namespace std;
  8 
  9 #pragma comment (lib, "Kernel32.lib")
 10 #pragma comment (lib, "User32.lib")
 11 
 12 #define THRD_MESSAGE_EXIT WM_USER + 1
 13 const _TCHAR CLASS_NAME[]  = _T("Sample Window Class");
 14 
 15 HWND hWnd;
 16 
 17 static const GUID GUID_DEVINTERFACE_LIST[] = 
 18 {
 19     // GUID_DEVINTERFACE_USB_DEVICE
 20     { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },
 21     // GUID_DEVINTERFACE_DISK
 22     { 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },
 23     // GUID_DEVINTERFACE_HID, 
 24     { 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },
 25     // GUID_NDIS_LAN_CLASS
 26     { 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } }
 27     //// GUID_DEVINTERFACE_COMPORT
 28     //{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },
 29     //// GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
 30     //{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
 31     //// GUID_DEVINTERFACE_PARALLEL
 32     //{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },
 33     //// GUID_DEVINTERFACE_PARCLASS
 34     //{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } }
 35 };
 36 
 37 void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam)
 38 {
 39     CString szDevId = pDevInf->dbcc_name + 4;
 40     int idx = szDevId.ReverseFind(_T('#'));
 41     szDevId.Truncate(idx);
 42     szDevId.Replace(_T('#'), _T('\\'));
 43     szDevId.MakeUpper();
 44 
 45     CString szClass;
 46     idx = szDevId.Find(_T('\\'));
 47     szClass = szDevId.Left(idx);
 48 
 49     CString szTmp;
 50     if ( DBT_DEVICEARRIVAL == wParam ) \
 51         szTmp.Format(_T("Adding %s\r\n"), szDevId.GetBuffer());
 52     else 
 53         szTmp.Format(_T("Removing %s\r\n"), szDevId.GetBuffer());
 54 
 55     _tprintf(szTmp);
 56 }
 57 
 58 LRESULT DeviceChange(UINT message, WPARAM wParam, LPARAM lParam)
 59 {
 60     if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam ) 
 61     {
 62         PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
 63         PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
 64         PDEV_BROADCAST_HANDLE pDevHnd;
 65         PDEV_BROADCAST_OEM pDevOem;
 66         PDEV_BROADCAST_PORT pDevPort;
 67         PDEV_BROADCAST_VOLUME pDevVolume;
 68         switch( pHdr->dbch_devicetype ) 
 69         {
 70             case DBT_DEVTYP_DEVICEINTERFACE:
 71                 pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
 72                 UpdateDevice(pDevInf, wParam);
 73                 break;
 74 
 75             case DBT_DEVTYP_HANDLE:
 76                 pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
 77                 break;
 78 
 79             case DBT_DEVTYP_OEM:
 80                 pDevOem = (PDEV_BROADCAST_OEM)pHdr;
 81                 break;
 82 
 83             case DBT_DEVTYP_PORT:
 84                 pDevPort = (PDEV_BROADCAST_PORT)pHdr;
 85                 break;
 86 
 87             case DBT_DEVTYP_VOLUME:
 88                 pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
 89                 break;
 90         }
 91     }
 92     return 0;
 93 }
 94 
 95 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 96 {
 97     switch(message)
 98     {
 99     case WM_PAINT:
100         break;
101     case WM_SIZE:
102         break;
103     case WM_DEVICECHANGE:
104         return DeviceChange(message, wParam, lParam);
105     }
106 
107     return DefWindowProc(hWnd, message, wParam, lParam);
108 }
109 
110 ATOM MyRegisterClass()
111 {
112     WNDCLASS wc = {0};
113     wc.lpfnWndProc   = WndProc;
114     wc.hInstance     = GetModuleHandle(NULL);
115     wc.lpszClassName = CLASS_NAME;
116     return RegisterClass(&wc);
117 }
118 
119 bool CreateMessageOnlyWindow()
120 {
121     hWnd = CreateWindowEx(0, CLASS_NAME, _T(""), WS_OVERLAPPEDWINDOW,
122         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
123         NULL,       // Parent window    
124         NULL,       // Menu
125         GetModuleHandle(NULL),  // Instance handle
126         NULL        // Additional application data
127         );
128 
129     return hWnd != NULL;
130 }
131 
132 void RegisterDeviceNotify()
133 {
134     HDEVNOTIFY hDevNotify;
135     for (int i = 0; i < sizeof(GUID_DEVINTERFACE_LIST) / sizeof(GUID); i++)
136     {
137         DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
138         ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
139         NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
140         NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
141         NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
142         hDevNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
143     }
144 }
145 
146 DWORD WINAPI ThrdFunc( LPVOID lpParam )
147 {
148     if (0 == MyRegisterClass())
149         return -1;
150 
151     if (!CreateMessageOnlyWindow())
152         return -1;
153 
154     RegisterDeviceNotify();
155 
156     MSG msg;
157     while (GetMessage(&msg, NULL, 0, 0))
158     {
159         if (msg.message == THRD_MESSAGE_EXIT)
160         {
161             cout << "worker receive the exiting Message..." << endl;
162             return 0;
163         }
164 
165         TranslateMessage(&msg);
166         DispatchMessage(&msg);
167     }
168 
169     return 0;
170 }
171 
172 int main(int argc, char** argv)
173 {
174     DWORD iThread;
175     HANDLE hThread = CreateThread( NULL, 0, ThrdFunc, NULL, 0, &iThread);
176     if (hThread == NULL) {
177         cout << "error" << endl;
178         return -1;
179     }
180 
181     char chQtNum;
182     do 
183     {
184         cout << "enter Q/q for quit: " << endl;
185         cin >> chQtNum;
186 
187     } while (chQtNum != 'Q' && chQtNum != 'q');
188 
189     PostThreadMessage(iThread, THRD_MESSAGE_EXIT, 0, 0);
190     WaitForSingleObject(hThread, INFINITE);
191     CloseHandle(hThread);
192     return 0;
193 }
:-)
posted @ 2013-04-23 21:18  godion  阅读(1189)  评论(0编辑  收藏  举报