今天讲一下线程如何向对话框传递消息,步骤如下:
- 创建消息数,在xxDlg.h: #define WM_RESPONSE WM_USER+1
- 声明消息函数成员函数xxDlg.h: afx_msg LRESULT winMessageFun(WPARAM wParam, LPARAM lParam); (注意返回值类型为LRESULT,在VC里可以是void 类,但在vs内会提示不兼容,只能用LRESULT)
- 添加消息映像xxDlg.cpp: ON_MESSAGE(WM_RESPONSE,winMessageFun)
- 定义消息响应函数xxxDlg.cpp:
LRESULT CMFCApplicationThresdDlg::winMessageFun(WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); WORD value = lParam; CString str; str.Format(_T("%d\r\n"), value); m_edit1 += str; UpdateData(FALSE); return 0; }
- 定义线程传递参数结构体
1 struct ThreadParam 2 { 3 HWND ThreadID; 4 WORD ThreadVal; 5 };
- 创建线程,在点击按键后启动线程:
1 void CMFCApplicationThresdDlg::Btn_Clicked_Start() 2 { 3 // TODO: Add your control notification handler code here 4 ThreadParam *pRecvParam = new ThreadParam; 5 pRecvParam->ThreadVal = 0; 6 pRecvParam->ThreadID = m_hWnd; 7 //create thread 8 HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)pRecvParam, 0, NULL); 9 }
- 声明线程函数xxDlg.h:
1 private: 2 static DWORD WINAPI ThreadProc(LPVOID lpParameter);
- 定义线程函数:
1 DWORD CMFCApplicationThresdDlg::ThreadProc(LPVOID lpParameter) 2 { 3 WORD value = ((ThreadParam*)lpParameter)->ThreadVal; 4 HWND hwnd = ((ThreadParam*)lpParameter)->ThreadID; 5 while (1) 6 { 7 value++; 8 ::PostMessage(hwnd, WM_RESPONSE, 0, (LPARAM)value); 9 Sleep(1000); 10 } 11 return 0; 12 }
- 源码:
1 // MFCApplicationThresdDlg.cpp : implementation file 2 // 3 4 #include "stdafx.h" 5 #include "MFCApplicationThresd.h" 6 #include "MFCApplicationThresdDlg.h" 7 #include "afxdialogex.h" 8 9 #ifdef _DEBUG 10 #define new DEBUG_NEW 11 #endif 12 13 14 // CAboutDlg dialog used for App About 15 16 class CAboutDlg : public CDialogEx 17 { 18 public: 19 CAboutDlg(); 20 21 // Dialog Data 22 enum { IDD = IDD_ABOUTBOX }; 23 24 protected: 25 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 26 27 // Implementation 28 protected: 29 DECLARE_MESSAGE_MAP() 30 }; 31 32 CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) 33 { 34 } 35 36 void CAboutDlg::DoDataExchange(CDataExchange* pDX) 37 { 38 CDialogEx::DoDataExchange(pDX); 39 } 40 41 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) 42 END_MESSAGE_MAP() 43 44 45 // CMFCApplicationThresdDlg dialog 46 47 48 49 CMFCApplicationThresdDlg::CMFCApplicationThresdDlg(CWnd* pParent /*=NULL*/) 50 : CDialogEx(CMFCApplicationThresdDlg::IDD, pParent) 51 , m_edit1(_T("")) 52 { 53 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 54 } 55 56 void CMFCApplicationThresdDlg::DoDataExchange(CDataExchange* pDX) 57 { 58 CDialogEx::DoDataExchange(pDX); 59 DDX_Text(pDX, IDC_EDIT1, m_edit1); 60 } 61 62 BEGIN_MESSAGE_MAP(CMFCApplicationThresdDlg, CDialogEx) 63 ON_WM_SYSCOMMAND() 64 ON_WM_PAINT() 65 ON_WM_QUERYDRAGICON() 66 ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplicationThresdDlg::Btn_Clicked_Start) 67 ON_MESSAGE(WM_RESPONSE,winMessageFun) 68 END_MESSAGE_MAP() 69 70 71 // CMFCApplicationThresdDlg message handlers 72 73 BOOL CMFCApplicationThresdDlg::OnInitDialog() 74 { 75 CDialogEx::OnInitDialog(); 76 77 // Add "About..." menu item to system menu. 78 79 // IDM_ABOUTBOX must be in the system command range. 80 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 81 ASSERT(IDM_ABOUTBOX < 0xF000); 82 83 CMenu* pSysMenu = GetSystemMenu(FALSE); 84 if (pSysMenu != NULL) 85 { 86 BOOL bNameValid; 87 CString strAboutMenu; 88 bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); 89 ASSERT(bNameValid); 90 if (!strAboutMenu.IsEmpty()) 91 { 92 pSysMenu->AppendMenu(MF_SEPARATOR); 93 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 94 } 95 } 96 97 // Set the icon for this dialog. The framework does this automatically 98 // when the application's main window is not a dialog 99 SetIcon(m_hIcon, TRUE); // Set big icon 100 SetIcon(m_hIcon, FALSE); // Set small icon 101 102 // TODO: Add extra initialization here 103 104 return TRUE; // return TRUE unless you set the focus to a control 105 } 106 107 void CMFCApplicationThresdDlg::OnSysCommand(UINT nID, LPARAM lParam) 108 { 109 if ((nID & 0xFFF0) == IDM_ABOUTBOX) 110 { 111 CAboutDlg dlgAbout; 112 dlgAbout.DoModal(); 113 } 114 else 115 { 116 CDialogEx::OnSysCommand(nID, lParam); 117 } 118 } 119 120 // If you add a minimize button to your dialog, you will need the code below 121 // to draw the icon. For MFC applications using the document/view model, 122 // this is automatically done for you by the framework. 123 124 void CMFCApplicationThresdDlg::OnPaint() 125 { 126 if (IsIconic()) 127 { 128 CPaintDC dc(this); // device context for painting 129 130 SendMessage(WM_ICONERASEBKGND, reinterpret_cast
(dc.GetSafeHdc()), 0); 131 132 // Center icon in client rectangle 133 int cxIcon = GetSystemMetrics(SM_CXICON); 134 int cyIcon = GetSystemMetrics(SM_CYICON); 135 CRect rect; 136 GetClientRect(&rect); 137 int x = (rect.Width() - cxIcon + 1) / 2; 138 int y = (rect.Height() - cyIcon + 1) / 2; 139 140 // Draw the icon 141 dc.DrawIcon(x, y, m_hIcon); 142 } 143 else 144 { 145 CDialogEx::OnPaint(); 146 } 147 } 148 149 // The system calls this function to obtain the cursor to display while the user drags 150 // the minimized window. 151 HCURSOR CMFCApplicationThresdDlg::OnQueryDragIcon() 152 { 153 return static_cast (m_hIcon); 154 } 155 156 157 158 void CMFCApplicationThresdDlg::Btn_Clicked_Start() 159 { 160 // TODO: Add your control notification handler code here 161 ThreadParam *pRecvParam = new ThreadParam; 162 pRecvParam->ThreadVal = 0; 163 pRecvParam->ThreadID = m_hWnd; 164 //create thread 165 HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)pRecvParam, 0, NULL); 166 } 167 DWORD CMFCApplicationThresdDlg::ThreadProc(LPVOID lpParameter) 168 { 169 WORD value = ((ThreadParam*)lpParameter)->ThreadVal; 170 HWND hwnd = ((ThreadParam*)lpParameter)->ThreadID; 171 while (1) 172 { 173 value++; 174 ::PostMessage(hwnd, WM_RESPONSE, 0, (LPARAM)value); 175 Sleep(1000); 176 } 177 return 0; 178 } 179 LRESULT CMFCApplicationThresdDlg::winMessageFun(WPARAM wParam, LPARAM lParam) 180 { 181 UNREFERENCED_PARAMETER(wParam); 182 UNREFERENCED_PARAMETER(lParam); 183 WORD value = lParam; 184 CString str; 185 str.Format(_T("%d\r\n"), value); 186 m_edit1 += str; 187 UpdateData(FALSE); 188 return 0; 189 } 1 // MFCApplicationThresdDlg.h : header file 2 // 3 4 #pragma once 5 6 7 // CMFCApplicationThresdDlg dialog 8 #define WM_RESPONSE WM_USER+1 9 struct ThreadParam 10 { 11 HWND ThreadID; 12 WORD ThreadVal; 13 }; 14 class CMFCApplicationThresdDlg : public CDialogEx 15 { 16 // Construction 17 public: 18 CMFCApplicationThresdDlg(CWnd* pParent = NULL); // standard constructor 19 20 // Dialog Data 21 enum { IDD = IDD_MFCAPPLICATIONTHRESD_DIALOG }; 22 private: 23 static DWORD WINAPI ThreadProc(LPVOID lpParameter); 24 25 protected: 26 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 27 28 29 // Implementation 30 protected: 31 HICON m_hIcon; 32 33 // Generated message map functions 34 virtual BOOL OnInitDialog(); 35 afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 36 afx_msg void OnPaint(); 37 afx_msg HCURSOR OnQueryDragIcon(); 38 afx_msg LRESULT winMessageFun(WPARAM wParam, LPARAM lParam); 39 DECLARE_MESSAGE_MAP() 40 public: 41 CString m_edit1; 42 afx_msg void Btn_Clicked_Start(); 43 };
谢谢!
End.