題目要求:點擊搶紅包後,先將第一個編輯框的值設置爲1000,而後建立三個線程,讓右邊的編輯框值依次設置爲1000(用事件完成)框架
// MutexExDlg.h : 頭文件 // #pragma once // CMutexExDlg 對話框 class CMutexExDlg : public CDialogEx { // 構造 public: CMutexExDlg(CWnd* pParent = NULL); // 標準構造函數 // 對話框數據 enum { IDD = IDD_MUTEXEX_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 static HANDLE hThread[3]; static HANDLE m_Mutex; static HANDLE m_Event; static DWORD WINAPI ThreadProc0(LPVOID lpParameter); static DWORD WINAPI ThreadProc1(LPVOID lpParameter); static DWORD WINAPI ThreadProc2(LPVOID lpParameter); static DWORD WINAPI ThreadProc3(LPVOID lpParameter); // 實現 protected: HICON m_hIcon; // 生成的消息映射函數 virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg void OnBnClickedButton1(); static int m_Edit0; static int m_Edit1; static int m_Edit2; static int m_Edit3; };
// MutexExDlg.cpp : 實現文件 // #include "stdafx.h" #include "MutexEx.h" #include "MutexExDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMutexExDlg 對話框 CMutexExDlg::CMutexExDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMutexExDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMutexExDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, m_Edit0); DDV_MinMaxInt(pDX, m_Edit0, 0, 1000); DDX_Text(pDX, IDC_EDIT2, m_Edit1); DDV_MinMaxInt(pDX, m_Edit1, 0, 1000); DDX_Text(pDX, IDC_EDIT3, m_Edit2); DDV_MinMaxInt(pDX, m_Edit2, 0, 1000); DDX_Text(pDX, IDC_EDIT4, m_Edit3); DDV_MinMaxInt(pDX, m_Edit3, 0, 1000); } BEGIN_MESSAGE_MAP(CMutexExDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CMutexExDlg::OnBnClickedButton1) END_MESSAGE_MAP() // CMutexExDlg 消息處理程序 BOOL CMutexExDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 設置此對話框的圖標。 當應用程序主窗口不是對話框時,框架將自動 // 執行此操做 SetIcon(m_hIcon, TRUE); // 設置大圖標 SetIcon(m_hIcon, FALSE); // 設置小圖標 // TODO: 在此添加額外的初始化代碼 return TRUE; // 除非將焦點設置到控件,不然返回 TRUE } // 若是向對話框添加最小化按鈕,則須要下面的代碼 // 來繪製該圖標。 對於使用文檔/視圖模型的 MFC 應用程序, // 這將由框架自動完成。 void CMutexExDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用於繪製的設備上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使圖標在工做區矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 繪製圖標 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //當用戶拖動最小化窗口時系統調用此函數取得光標 //顯示。 HCURSOR CMutexExDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } // 重寫虛函數 PreTranslateMessage 屏蔽掉Esc鍵和Enter鍵 BOOL CMutexExDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) { int keyCode = (int)pMsg->wParam; if (keyCode == VK_ESCAPE || keyCode == VK_RETURN) { return TRUE; } } return CDialogEx::PreTranslateMessage(pMsg); } HANDLE CMutexExDlg::m_Mutex = NULL; HANDLE CMutexExDlg::m_Event = NULL; int CMutexExDlg::m_Edit0 = 0; int CMutexExDlg::m_Edit1 = 0; int CMutexExDlg::m_Edit2 = 0; int CMutexExDlg::m_Edit3 = 0; HANDLE CMutexExDlg::hThread[3] = { NULL }; // 搶紅包按鈕點擊事件處理函數 void CMutexExDlg::OnBnClickedButton1() { // 獲取編輯框內容到str變量 CString str; GetDlgItem(IDC_EDIT1)->GetWindowText(str); // CString 轉 int m_Edit0 = _ttoi(str); m_Edit1 = 0; m_Edit2 = 0; m_Edit3 = 0; // 這裏須要建立一個線程 由於 WaitForMultipleObjects 會阻塞住 另外把this指針做爲參數傳遞給線程,用於子線程更新編輯框內容 HANDLE hThread0 = ::CreateThread(NULL, NULL, ThreadProc0, this, NULL, NULL); CloseHandle(hThread0); } DWORD WINAPI CMutexExDlg::ThreadProc0(LPVOID lpParameter) { CMutexExDlg* pDlg = (CMutexExDlg*)lpParameter; // 建立一個事件 m_Event = ::CreateEvent(NULL, FALSE, // FALSE 表明 WaitForSingleObject到以後,事件仍是未通知狀態,須要手動設置已通知狀態 FALSE, // FALSE 表明 事件建立完以後,不能立刻被 WaitForSingleObject 到 NULL); // 建立三個線程搶紅包 hThread[0] = ::CreateThread(NULL, NULL, ThreadProc1, lpParameter, NULL, NULL); hThread[1] = ::CreateThread(NULL, NULL, ThreadProc2, lpParameter, NULL, NULL); hThread[2] = ::CreateThread(NULL, NULL, ThreadProc3, lpParameter, NULL, NULL); // 設置編輯框內容 ::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT1), L"1000"); // 將對象設置爲已通知狀態 ::SetEvent(m_Event); // 使用WaitForMultipleObjects監聽全部線程,當線程所有結束後,調用CloseHandle關閉句柄. WaitForMultipleObjects(3, hThread, TRUE, -1); ::CloseHandle(hThread[0]); ::CloseHandle(hThread[1]); ::CloseHandle(hThread[2]); ::CloseHandle(m_Mutex); return 0; } // 線程回調函數1 DWORD WINAPI CMutexExDlg::ThreadProc1(LPVOID lpParameter) { CMutexExDlg* pDlg = (CMutexExDlg*)lpParameter; while (true) { WaitForSingleObject(m_Event, -1); ::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT2), L"1000"); Sleep(2000); // 將對象設置爲已通知狀態 ::SetEvent(m_Event); } return 0; } // 線程回調函數2 DWORD WINAPI CMutexExDlg::ThreadProc2(LPVOID lpParameter) { CMutexExDlg* pDlg = (CMutexExDlg*)lpParameter; while (true) { WaitForSingleObject(m_Event, -1); ::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT3), L"1000"); Sleep(2000); // 將對象設置爲已通知狀態 ::SetEvent(m_Event); } return 0; } // 線程回調函數3 DWORD WINAPI CMutexExDlg::ThreadProc3(LPVOID lpParameter) { CMutexExDlg* pDlg = (CMutexExDlg*)lpParameter; while (true) { WaitForSingleObject(m_Event, -1); ::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT4), L"1000"); Sleep(2000); // 將對象設置爲已通知狀態 ::SetEvent(m_Event); } return 0; }