zoukankan      html  css  js  c++  java
  • MFC使用自定义消息

    可以在一个线程的执行函数中向另一个线程发送自定义的消息来达到通信的目的.一个线程向另外一个线程发送消息是通过操作系统实现的.利用 Windows 操作系统的消息驱动机制,当一个线程发出一条消息时,操作系统首先接收到该消息,然后把该消息转发给目标线程,接收消息的线程必须已经建立了消息循环.

    例程 7 MultiThread7
    该例程演示了如何使用自定义消息进行线程间通信.首先,主线程向 CCalculateThread 线程发送消息WM_CALCULATE,CCalculateThread 线程收到消息后进行计算,再向主线程发送 WM_DISPLAY 消息,主线程收到该消息后显示计算结果.
    建立一个基于对话框的工程 MultiThread7,在对话框 IDD_MULTITHREAD7_DIALOG 中加入三个单选按钮IDC_RADIO1,IDC_RADIO2,IDC_RADIO3,标题分别为1+2+3+4+......+10,1+2+3+4+......+50,1+2+3+4+......+100.加入按钮 IDC_SUM,标题为“求和”.加入标签框 IDC_STATUS,属性选中“边框”.

    分别双击三个单选按钮,添加消息响应函数:
    void CMultiThread7Dlg::OnRadio1()
    {
    nAddend=10;
    }
    void CMultiThread7Dlg::OnRadio2()
    {
    nAddend=50;
    }
    void CMultiThread7Dlg::OnRadio3()
    {
    nAddend=100;
    }

    并在 OnInitDialog 函数中完成相应的初始化工作:

     1 BOOL CMultiThread7Dlg::OnInitDialog()
     2 {
     3     CDialogEx::OnInitDialog();
     4 
     5     // 将“关于...”菜单项添加到系统菜单中。
     6 
     7     // IDM_ABOUTBOX 必须在系统命令范围内。
     8     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
     9     ASSERT(IDM_ABOUTBOX < 0xF000);
    10 
    11     CMenu* pSysMenu = GetSystemMenu(FALSE);
    12     if (pSysMenu != NULL)
    13     {
    14         BOOL bNameValid;
    15         CString strAboutMenu;
    16         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    17         ASSERT(bNameValid);
    18         if (!strAboutMenu.IsEmpty())
    19         {
    20             pSysMenu->AppendMenu(MF_SEPARATOR);
    21             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    22         }
    23     }
    24 
    25     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    26     //  执行此操作
    27     SetIcon(m_hIcon, TRUE);            // 设置大图标
    28     SetIcon(m_hIcon, FALSE);        // 设置小图标
    29 
    30     // TODO: 在此添加额外的初始化代码
    31     ((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);
    32     nAddend = 10;
    33     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    34 }

    在 MultiThread7Dlg.h 中添加: #include "CalculateThread.h"

     1 // MultiThread7Dlg.h : 头文件
     2 //
     3 #include "CalculateThread.h"
     4 
     5 
     6 #define WM_DISPLAY WM_USER+2
     7 
     8 #pragma once
     9 
    10 
    11 // CMultiThread7Dlg 对话框
    12 class CMultiThread7Dlg : public CDialogEx
    13 {
    14 // 构造
    15 public:
    16     CMultiThread7Dlg(CWnd* pParent = NULL);    // 标准构造函数
    17     CCalculateThread *m_pCalculateThread;
    18 // 对话框数据
    19 #ifdef AFX_DESIGN_TIME
    20     enum { IDD = IDD_MULTITHREAD7_DIALOG };
    21 #endif
    22 
    23     protected:
    24     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    25 
    26 
    27 // 实现
    28 protected:
    29     HICON m_hIcon;
    30     int nAddend;
    31     LRESULT OnDisplay(WPARAM wParam, LPARAM lParam);
    32     // 生成的消息映射函数
    33     virtual BOOL OnInitDialog();
    34     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    35     afx_msg void OnPaint();
    36     afx_msg HCURSOR OnQueryDragIcon();
    37     DECLARE_MESSAGE_MAP()
    38 public:
    39     afx_msg void OnBnClickedRadio1();
    40     afx_msg void OnBnClickedRadio2();
    41     afx_msg void OnBnClickedRadio3();
    42     afx_msg void OnBnClickedSum();
    43 };

    在 MultiThread7Dlg.cpp 中添加: BEGIN_MESSAGE_MAP(CMultiThread7Dlg, CDialog)

      1 // MultiThread7Dlg.cpp : 实现文件
      2 //
      3 
      4 #include "stdafx.h"
      5 #include "MultiThread7.h"
      6 #include "MultiThread7Dlg.h"
      7 #include "afxdialogex.h"
      8 
      9 #ifdef _DEBUG
     10 #define new DEBUG_NEW
     11 #endif
     12 
     13 
     14 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
     15 
     16 class CAboutDlg : public CDialogEx
     17 {
     18 public:
     19     CAboutDlg();
     20 
     21 // 对话框数据
     22 #ifdef AFX_DESIGN_TIME
     23     enum { IDD = IDD_ABOUTBOX };
     24 #endif
     25 
     26     protected:
     27     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
     28 
     29 // 实现
     30 protected:
     31     DECLARE_MESSAGE_MAP()
     32 };
     33 
     34 CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
     35 {
     36 }
     37 
     38 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
     39 {
     40     CDialogEx::DoDataExchange(pDX);
     41 }
     42 
     43 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
     44 END_MESSAGE_MAP()
     45 
     46 
     47 // CMultiThread7Dlg 对话框
     48 
     49 
     50 
     51 CMultiThread7Dlg::CMultiThread7Dlg(CWnd* pParent /*=NULL*/)
     52     : CDialogEx(IDD_MULTITHREAD7_DIALOG, pParent)
     53 {
     54     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
     55 }
     56 
     57 void CMultiThread7Dlg::DoDataExchange(CDataExchange* pDX)
     58 {
     59     CDialogEx::DoDataExchange(pDX);
     60 }
     61 
     62 BEGIN_MESSAGE_MAP(CMultiThread7Dlg, CDialogEx)
     63     ON_WM_SYSCOMMAND()
     64     ON_WM_PAINT()
     65     ON_WM_QUERYDRAGICON()
     66     ON_BN_CLICKED(IDC_RADIO1, &CMultiThread7Dlg::OnBnClickedRadio1)
     67     ON_BN_CLICKED(IDC_RADIO2, &CMultiThread7Dlg::OnBnClickedRadio2)
     68     ON_BN_CLICKED(IDC_RADIO3, &CMultiThread7Dlg::OnBnClickedRadio3)
     69     ON_MESSAGE(WM_DISPLAY, &CMultiThread7Dlg::OnDisplay)
     70     ON_BN_CLICKED(IDC_SUM, &CMultiThread7Dlg::OnBnClickedSum)
     71 END_MESSAGE_MAP()
     72 
     73 
     74 // CMultiThread7Dlg 消息处理程序
     75 
     76 BOOL CMultiThread7Dlg::OnInitDialog()
     77 {
     78     CDialogEx::OnInitDialog();
     79 
     80     // 将“关于...”菜单项添加到系统菜单中。
     81 
     82     // IDM_ABOUTBOX 必须在系统命令范围内。
     83     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
     84     ASSERT(IDM_ABOUTBOX < 0xF000);
     85 
     86     CMenu* pSysMenu = GetSystemMenu(FALSE);
     87     if (pSysMenu != NULL)
     88     {
     89         BOOL bNameValid;
     90         CString strAboutMenu;
     91         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
     92         ASSERT(bNameValid);
     93         if (!strAboutMenu.IsEmpty())
     94         {
     95             pSysMenu->AppendMenu(MF_SEPARATOR);
     96             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
     97         }
     98     }
     99 
    100     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    101     //  执行此操作
    102     SetIcon(m_hIcon, TRUE);            // 设置大图标
    103     SetIcon(m_hIcon, FALSE);        // 设置小图标
    104 
    105     // TODO: 在此添加额外的初始化代码
    106     ((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);
    107     nAddend = 10;
    108     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    109 }
    110 
    111 void CMultiThread7Dlg::OnSysCommand(UINT nID, LPARAM lParam)
    112 {
    113     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    114     {
    115         CAboutDlg dlgAbout;
    116         dlgAbout.DoModal();
    117     }
    118     else
    119     {
    120         CDialogEx::OnSysCommand(nID, lParam);
    121     }
    122 }
    123 
    124 // 如果向对话框添加最小化按钮,则需要下面的代码
    125 //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
    126 //  这将由框架自动完成。
    127 
    128 void CMultiThread7Dlg::OnPaint()
    129 {
    130     if (IsIconic())
    131     {
    132         CPaintDC dc(this); // 用于绘制的设备上下文
    133 
    134         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    135 
    136         // 使图标在工作区矩形中居中
    137         int cxIcon = GetSystemMetrics(SM_CXICON);
    138         int cyIcon = GetSystemMetrics(SM_CYICON);
    139         CRect rect;
    140         GetClientRect(&rect);
    141         int x = (rect.Width() - cxIcon + 1) / 2;
    142         int y = (rect.Height() - cyIcon + 1) / 2;
    143 
    144         // 绘制图标
    145         dc.DrawIcon(x, y, m_hIcon);
    146     }
    147     else
    148     {
    149         CDialogEx::OnPaint();
    150     }
    151 }
    152 
    153 //当用户拖动最小化窗口时系统调用此函数取得光标
    154 //显示。
    155 HCURSOR CMultiThread7Dlg::OnQueryDragIcon()
    156 {
    157     return static_cast<HCURSOR>(m_hIcon);
    158 }
    159 
    160 
    161 
    162 void CMultiThread7Dlg::OnBnClickedRadio1()
    163 {
    164     // TODO: 在此添加控件通知处理程序代码
    165     nAddend = 10;
    166 }
    167 
    168 
    169 void CMultiThread7Dlg::OnBnClickedRadio2()
    170 {
    171     // TODO: 在此添加控件通知处理程序代码
    172     nAddend = 50;
    173 }
    174 
    175 
    176 void CMultiThread7Dlg::OnBnClickedRadio3()
    177 {
    178     // TODO: 在此添加控件通知处理程序代码
    179     nAddend = 100;
    180 }
    181 
    182 
    183 
    184 LRESULT CMultiThread7Dlg::OnDisplay(WPARAM wParam, LPARAM lParam)
    185 {
    186     int nTemp = (int)wParam;
    187     SetDlgItemInt(IDC_STATUS, nTemp, FALSE);
    188     return 0;
    189 }
    190 
    191 void CMultiThread7Dlg::OnBnClickedSum()
    192 {
    193     // TODO: 在此添加控件通知处理程序代码
    194     m_pCalculateThread = (CCalculateThread *) AfxBeginThread(RUNTIME_CLASS(CCalculateThread));
    195     Sleep(500);
    196     m_pCalculateThread->PostThreadMessage(WM_CALCULATE, nAddend, NULL);
    197     m_pCalculateThread = NULL;
    198 }

    CalculateThread.h

     1 #pragma once
     2 #include "afxwin.h"
     3 
     4 #define WM_CALCULATE WM_USER+1
     5 
     6 
     7 class CCalculateThread :public CWinThread
     8 {
     9 
    10     DECLARE_DYNCREATE(CCalculateThread)
    11 protected:
    12     CCalculateThread();
    13     ~CCalculateThread();
    14 public:
    15 
    16     virtual BOOL InitInstance();
    17     virtual int    ExitInstance();
    18 
    19     afx_msg void OnCalculate(UINT wParam, LONG lParam);
    20 
    21 protected:
    22     
    23     DECLARE_MESSAGE_MAP()
    24 };

    CalculateThread.cpp

     1 #include "stdafx.h"
     2 #include "CalculateThread.h"
     3 #include "MultiThread7Dlg.h"
     4 
     5 IMPLEMENT_DYNCREATE(CCalculateThread, CWinThread)
     6 
     7 BEGIN_MESSAGE_MAP(CCalculateThread, CWinThread)
     8     //{{AFX_MSG_MAP(CCalculateThread)
     9     // NOTE - the ClassWizard will add and remove mapping macros here.
    10     //}}AFX_MSG_MAP
    11     ON_THREAD_MESSAGE(WM_CALCULATE, &CCalculateThread::OnCalculate)
    12     //和主线程对比,注意它们的区别
    13 END_MESSAGE_MAP()
    14 
    15 CCalculateThread::CCalculateThread()
    16 {
    17 }
    18 
    19 
    20 CCalculateThread::~CCalculateThread()
    21 {
    22     AfxEndThread(0);
    23 }
    24 
    25 
    26 BOOL CCalculateThread::InitInstance()
    27 {
    28     // TODO: 在此执行任意逐线程初始化
    29     return TRUE;
    30 }
    31 
    32 int CCalculateThread::ExitInstance()
    33 {
    34     // TODO: 在此执行任意逐线程清理
    35     return CWinThread::ExitInstance();
    36 }
    37 
    38 
    39 void CCalculateThread::OnCalculate(UINT wParam, LONG lParam)
    40 {
    41     int nTmpt = 0;
    42     for (int i = 0; i <= (int)wParam; i++)
    43     {
    44         nTmpt = nTmpt + i;
    45     }
    46     Sleep(500);
    47     ::PostMessage((HWND)(GetMainWnd()->GetSafeHwnd()), WM_DISPLAY, nTmpt, NULL);
    48     //return 0;
    49 }
  • 相关阅读:
    【模板整合计划】高阶数据结构
    【模板整合计划】高阶数据结构—线段树
    主席树【权值线段树】(转)
    Flask系列(二) 模板 templates
    用java实现Shazam 译文
    [转] 研究云计算与海量数据处理方向建议看的论文列表
    程序员应知 如何分析海量数据
    大数据技术大会
    android监控网络状态
    HP(惠普)大中华区总裁孙振耀退休感言
  • 原文地址:https://www.cnblogs.com/codecamel/p/5942900.html
Copyright © 2011-2022 走看看