home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / advanced / mutexes / mutexdlg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  9.4 KB  |  413 lines

  1. // mutexesDlg.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12. //
  13. // This sample application is derived from the Mutex application
  14. // distributed with Jeffrey Richter's "Advanced Windows" programming book
  15. // (Microsoft Press).  See the book for more information about Win32
  16. // programming topics, including thread synchronization.
  17.  
  18. #include "stdafx.h"
  19. #include "mutexes.h"
  20. #include "mutexdlg.h"
  21. #include "threads.h"
  22.  
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27.  
  28. /////////////////////////////////////////////////////////////////////////////
  29. // CAboutDlg dialog used for App About
  30.  
  31. class CAboutDlg : public CDialog
  32. {
  33. public:
  34.     CAboutDlg();
  35.  
  36. // Dialog Data
  37.     //{{AFX_DATA(CAboutDlg)
  38.     enum { IDD = IDD_ABOUTBOX };
  39.     //}}AFX_DATA
  40.  
  41. // Implementation
  42. protected:
  43.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  44.     //{{AFX_MSG(CAboutDlg)
  45.     //}}AFX_MSG
  46.     DECLARE_MESSAGE_MAP()
  47. };
  48.  
  49. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  50. {
  51.     //{{AFX_DATA_INIT(CAboutDlg)
  52.     //}}AFX_DATA_INIT
  53. }
  54.  
  55. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  56. {
  57.     CDialog::DoDataExchange(pDX);
  58.     //{{AFX_DATA_MAP(CAboutDlg)
  59.     //}}AFX_DATA_MAP
  60. }
  61.  
  62. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  63.     //{{AFX_MSG_MAP(CAboutDlg)
  64.         // No message handlers
  65.     //}}AFX_MSG_MAP
  66. END_MESSAGE_MAP()
  67.  
  68. /////////////////////////////////////////////////////////////////////////////
  69. // CMutexesDlg dialog
  70.  
  71. CMutexesDlg::CMutexesDlg(CWnd* pParent /*=NULL*/)
  72.     : CDialog(CMutexesDlg::IDD, pParent),
  73.      m_mutex(FALSE, NULL),
  74.      m_strNumber(_T("0"))
  75. {
  76.     //{{AFX_DATA_INIT(CMutexesDlg)
  77.         // NOTE: the ClassWizard will add member initialization here
  78.     //}}AFX_DATA_INIT
  79.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  80.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  81.  
  82.     m_pCounterThread = NULL;
  83.     m_pDisplayThread = NULL;
  84. }
  85.  
  86. void CMutexesDlg::DoDataExchange(CDataExchange* pDX)
  87. {
  88.     CDialog::DoDataExchange(pDX);
  89.     //{{AFX_DATA_MAP(CMutexesDlg)
  90.         // NOTE: the ClassWizard will add DDX and DDV calls here
  91.     //}}AFX_DATA_MAP
  92. }
  93.  
  94. BEGIN_MESSAGE_MAP(CMutexesDlg, CDialog)
  95.     //{{AFX_MSG_MAP(CMutexesDlg)
  96.     ON_WM_SYSCOMMAND()
  97.     ON_WM_PAINT()
  98.     ON_WM_QUERYDRAGICON()
  99.     ON_CBN_SELCHANGE(IDC_PRIORITYCLASS, OnPriorityClassChange)
  100.     ON_CBN_SELCHANGE(IDC_CNTRTHRDPRIORITY, OnPriorityChangeCntr)
  101.     ON_CBN_SELCHANGE(IDC_DSPYTHRDPRIORITY, OnPriorityChangeDisp)
  102.     ON_WM_CLOSE()
  103.     ON_BN_CLICKED(IDC_PAUSE, OnPause)
  104.     //}}AFX_MSG_MAP
  105. END_MESSAGE_MAP()
  106.  
  107.  
  108. /////////////////////////////////////////////////////////////////////////////
  109. // CMutexesDlg message handlers
  110.  
  111. BOOL CMutexesDlg::OnInitDialog()
  112. {
  113.     CDialog::OnInitDialog();
  114.  
  115.     // Add "About..." menu item to system menu.
  116.  
  117.     // IDM_ABOUTBOX must be in the system command range.
  118.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  119.     ASSERT(IDM_ABOUTBOX < 0xF000);
  120.  
  121.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  122.     CString strAboutMenu;
  123.     strAboutMenu.LoadString(IDS_ABOUTBOX);
  124.     if (!strAboutMenu.IsEmpty())
  125.     {
  126.         pSysMenu->AppendMenu(MF_SEPARATOR);
  127.         pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  128.     }
  129.  
  130.     // Fill the Process Priority Class combo box and select
  131.     // Normal.
  132.  
  133.     CComboBox* pBox;
  134.     pBox = (CComboBox*) GetDlgItem(IDC_PRIORITYCLASS);
  135.  
  136.     ASSERT(pBox != NULL);
  137.     if (pBox != NULL)
  138.     {
  139.         pBox->AddString(_T("Idle"));
  140.         pBox->AddString(_T("Normal"));
  141.         pBox->AddString(_T("High"));
  142.         pBox->AddString(_T("Realtime"));
  143.         pBox->SetCurSel(1); // Normal
  144.     }
  145.  
  146.     // Fill the Display Thread Priority
  147.     // combo box and select Normal.
  148.  
  149.     pBox = (CComboBox*) GetDlgItem(IDC_DSPYTHRDPRIORITY);
  150.     ASSERT(pBox != NULL);
  151.     if (pBox != NULL)
  152.     {
  153.         pBox->AddString(_T("Idle"));
  154.         pBox->AddString(_T("Lowest"));
  155.         pBox->AddString(_T("Below normal"));
  156.         pBox->AddString(_T("Normal"));
  157.         pBox->AddString(_T("Above normal"));
  158.         pBox->AddString(_T("Highest"));
  159.         pBox->AddString(_T("Timecritical"));
  160.         pBox->SetCurSel(3);  // Normal
  161.     }
  162.  
  163.     // Fill the Counter Thread Priority
  164.     // combo box and select Normal.
  165.  
  166.     pBox = (CComboBox*) GetDlgItem(IDC_CNTRTHRDPRIORITY);
  167.     ASSERT(pBox != NULL);
  168.     if (pBox != NULL)
  169.     {
  170.         pBox->AddString(_T("Idle"));
  171.         pBox->AddString(_T("Lowest"));
  172.         pBox->AddString(_T("Below normal"));
  173.         pBox->AddString(_T("Normal"));
  174.         pBox->AddString(_T("Above normal"));
  175.         pBox->AddString(_T("Highest"));
  176.         pBox->AddString(_T("Timecritical"));
  177.         pBox->SetCurSel(3);  // Normal
  178.     }
  179.  
  180.     // initialize the threads and let them start running!
  181.  
  182.     m_pDisplayThread = (CDisplayThread*)
  183.         AfxBeginThread(RUNTIME_CLASS(CDisplayThread), THREAD_PRIORITY_NORMAL,
  184.             0, CREATE_SUSPENDED);
  185.     m_pDisplayThread->SetOwner(this);
  186.     m_pDisplayThread->ResumeThread();
  187.  
  188.     m_pCounterThread = (CCounterThread*)
  189.         AfxBeginThread(RUNTIME_CLASS(CCounterThread), THREAD_PRIORITY_NORMAL,
  190.             0, CREATE_SUSPENDED);
  191.     m_pCounterThread->SetOwner(this);
  192.     m_pCounterThread->ResumeThread();
  193.  
  194.     return TRUE;  // return TRUE  unless you set the focus to a control
  195. }
  196.  
  197. void CMutexesDlg::OnSysCommand(UINT nID, LPARAM lParam)
  198. {
  199.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  200.     {
  201.         CAboutDlg dlgAbout;
  202.         dlgAbout.DoModal();
  203.     }
  204.     else
  205.     {
  206.         CDialog::OnSysCommand(nID, lParam);
  207.     }
  208. }
  209.  
  210. // If you add a minimize button to your dialog, you will need the code below
  211. //  to draw the icon.  For MFC applications using the document/view model,
  212. //  this is automatically done for you by the framework.
  213.  
  214. void CMutexesDlg::OnPaint()
  215. {
  216.     if (IsIconic())
  217.     {
  218.         CPaintDC dc(this); // device context for painting
  219.  
  220.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  221.  
  222.         // Center icon in client rectangle
  223.         int cxIcon = GetSystemMetrics(SM_CXICON);
  224.         int cyIcon = GetSystemMetrics(SM_CYICON);
  225.         CRect rect;
  226.         GetClientRect(&rect);
  227.         int x = (rect.Width() - cxIcon + 1) / 2;
  228.         int y = (rect.Height() - cyIcon + 1) / 2;
  229.  
  230.         // Draw the icon
  231.         dc.DrawIcon(x, y, m_hIcon);
  232.     }
  233.     else
  234.     {
  235.         CDialog::OnPaint();
  236.     }
  237. }
  238.  
  239. // The system calls this to obtain the cursor to display while the user drags
  240. //  the minimized window.
  241. HCURSOR CMutexesDlg::OnQueryDragIcon()
  242. {
  243.     return (HCURSOR) m_hIcon;
  244. }
  245.  
  246. void CMutexesDlg::AddToListBox(LPCTSTR szBuffer)
  247. {
  248.     CListBox* pBox = (CListBox*) GetDlgItem(IDC_DATABOX);
  249.     ASSERT(pBox != NULL);
  250.  
  251.     if (pBox != NULL)
  252.     {
  253.         int x = pBox->AddString(szBuffer);
  254.         pBox->SetCurSel(x);
  255.  
  256.         if (pBox->GetCount() > 100)
  257.             pBox->DeleteString(0);
  258.     }
  259. }
  260.  
  261. void CMutexesDlg::OnClose()
  262. {
  263.     int nCount = 0;
  264.     DWORD   dwStatus;
  265.  
  266.     CButton* pCheck = (CButton*) GetDlgItem(IDC_PAUSE);
  267.     BOOL bPaused = ((pCheck->GetState() & 0x003) != 0);
  268.  
  269.     if (bPaused == TRUE)
  270.     {
  271.         pCheck->SetCheck(0);
  272.         m_pCounterThread->ResumeThread();
  273.         m_pDisplayThread->ResumeThread();
  274.     }
  275.  
  276.     if (m_pCounterThread != NULL)
  277.     {
  278.         VERIFY(::GetExitCodeThread(m_pCounterThread->m_hThread, &dwStatus));
  279.         if (dwStatus == STILL_ACTIVE)
  280.         {
  281.             nCount++;
  282.             m_pCounterThread->m_bDone = TRUE;
  283.         }
  284.         else
  285.         {
  286.             delete m_pCounterThread;
  287.             m_pCounterThread = NULL;
  288.         }
  289.     }
  290.  
  291.     if (m_pDisplayThread != NULL)
  292.     {
  293.         VERIFY(::GetExitCodeThread(m_pDisplayThread->m_hThread, &dwStatus));
  294.         if (dwStatus == STILL_ACTIVE)
  295.         {
  296.             nCount++;
  297.             m_pDisplayThread->m_bDone = TRUE;
  298.         }
  299.         else
  300.         {
  301.             delete m_pDisplayThread;
  302.             m_pDisplayThread = NULL;
  303.         }
  304.     }
  305.  
  306.     if (nCount == 0)
  307.         CDialog::OnClose();
  308.     else
  309.         PostMessage(WM_CLOSE, 0, 0);
  310. }
  311.  
  312. void CMutexesDlg::OnPriorityClassChange()
  313. {
  314.     DWORD dw;
  315.     CComboBox* pBox = (CComboBox*) GetDlgItem(IDC_PRIORITYCLASS);
  316.     int nCurSel = pBox->GetCurSel();
  317.  
  318.     switch (nCurSel)
  319.     {
  320.     case 0:
  321.         dw = IDLE_PRIORITY_CLASS;
  322.         break;
  323.  
  324.     case 1:
  325.     default:
  326.         dw = NORMAL_PRIORITY_CLASS;
  327.         break;
  328.  
  329.     case 2:
  330.         dw = HIGH_PRIORITY_CLASS;
  331.         break;
  332.  
  333.     case 3:
  334.         dw = REALTIME_PRIORITY_CLASS;
  335.         break;
  336.     }
  337.  
  338.     SetPriorityClass(GetCurrentProcess(), dw);
  339. }
  340.  
  341. void CMutexesDlg::OnPriorityChangeDisp()
  342. {
  343.     OnPriorityChange(IDC_DSPYTHRDPRIORITY);
  344. }
  345.  
  346. void CMutexesDlg::OnPriorityChangeCntr()
  347. {
  348.     OnPriorityChange(IDC_CNTRTHRDPRIORITY);
  349. }
  350.  
  351. void CMutexesDlg::OnPriorityChange(UINT nID)
  352. {
  353.     ASSERT(nID == IDC_CNTRTHRDPRIORITY || nID == IDC_DSPYTHRDPRIORITY);
  354.  
  355.     DWORD dw;
  356.     CComboBox* pBox = (CComboBox*) GetDlgItem(nID);
  357.     int nCurSel = pBox->GetCurSel();
  358.  
  359.     switch (nCurSel)
  360.     {
  361.     case 0:
  362.         dw = (DWORD) THREAD_PRIORITY_IDLE;
  363.         break;
  364.  
  365.     case 1:
  366.         dw = (DWORD) THREAD_PRIORITY_LOWEST;
  367.         break;
  368.  
  369.     case 2:
  370.         dw = (DWORD) THREAD_PRIORITY_BELOW_NORMAL;
  371.         break;
  372.  
  373.     case 3:
  374.     default:
  375.         dw = (DWORD) THREAD_PRIORITY_NORMAL;
  376.         break;
  377.  
  378.     case 4:
  379.         dw = (DWORD) THREAD_PRIORITY_ABOVE_NORMAL;
  380.         break;
  381.  
  382.     case 5:
  383.         dw = (DWORD) THREAD_PRIORITY_HIGHEST;
  384.         break;
  385.  
  386.     case 6:
  387.         dw = (DWORD) THREAD_PRIORITY_TIME_CRITICAL;
  388.         break;
  389.     }
  390.  
  391.     if (nID == IDC_CNTRTHRDPRIORITY)
  392.         m_pCounterThread->SetThreadPriority(dw);
  393.     else
  394.         m_pDisplayThread->SetThreadPriority(dw);
  395. }
  396.  
  397. void CMutexesDlg::OnPause()
  398. {
  399.     CButton* pCheck = (CButton*) GetDlgItem(IDC_PAUSE);
  400.     BOOL bPaused = ((pCheck->GetState() & 0x003) != 0);
  401.  
  402.     if (bPaused)
  403.     {
  404.         m_pCounterThread->SuspendThread();
  405.         m_pDisplayThread->SuspendThread();
  406.     }
  407.     else
  408.     {
  409.         m_pCounterThread->ResumeThread();
  410.         m_pDisplayThread->ResumeThread();
  411.     }
  412. }
  413.