• 使用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 }
    :-)
  • 相关阅读:
    python3线程介绍01(如何启动和调用线程)
    CentOS7 设置静态 ip
    png2ico
    Thunderbird 配置 QQ mail
    memcached 开机启动 (Ubuntu)
    CentOS7 docker 安装的 container-selinux 问题及解决
    YAML 的基本语法
    docker 的脚本化安装和使用
    解决Windows下 “setup.py build” 时出现错误 ” error: Unable to find vcvarsall.bat”
    Electric Fence
  • 原文地址:https://www.cnblogs.com/dioncnblogs/p/MSGQUEUE.html
Copyright © 2020-2023  润新知