Multithreading in C++ - The Thread Control Panel
(Page 5 of 11 )
The code for the thread control panel is shown here. This file is called tcp.cpp.
// A thread control panel.
#include <map>
#include <windows.h>
#include "panel.h"
using namespace std;
const int NUMPRIORITIES = 5;
const int OFFSET = 2;
// Array of strings for priority list box.
char priorities[NUMPRIORITIES][80] = {
"Lowest",
"Below Normal",
"Normal",
"Above Normal",
"Highest"
};
// A Thread Control Panel Class.
class ThrdCtrlPanel {
// Information about the thread under control.
struct ThreadInfo {
HANDLE hThread; // handle of thread
int priority; // current priority
bool suspended; // true if suspended
ThreadInfo(HANDLE ht, int p, bool s) {
hThread = ht;
priority = p;
suspended = s;
}
};
// This map holds a ThreadInfo for each
// active thread control panel.
static map<HWND, ThreadInfo> dialogmap;
public:
// Construct a control panel.
ThrdCtrlPanel(HINSTANCE hInst, HANDLE hThrd);
// The control panel's callback function.
static LRESULT CALLBACK ThreadPanel(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
};
// Define static member dialogmap.
map<HWND, ThrdCtrlPanel::ThreadInfo>
ThrdCtrlPanel::dialogmap;
// Create a thread control panel. ThrdCtrlPanel::ThrdCtrlPanel(HINSTANCE hInst,
HANDLE hThrd)
{
ThreadInfo ti(hThrd,
GetThreadPriority(hThrd)+OFFSET,
false);
// Owner window is desktop.
HWND hDialog = CreateDialog(hInst, "ThreadPanelDB",
NULL,
(DLGPROC) ThreadPanel);
// Put info about this dialog box in the map.
dialogmap.insert(pair<HWND, ThreadInfo>(hDialog, ti));
// Set the control panel's title.
char str[80] = "Control Panel for Thread ";
char str2[4];
_itoa(dialogmap.size(), str2, 10);
strcat(str, str2);
SetWindowText(hDialog, str);
// Offset each dialog box instance.
MoveWindow(hDialog, 30*dialogmap.size(),
30*dialogmap.size(),
300, 250, 1);
// Update priority setting in the list box.
SendDlgItemMessage(hDialog, IDD_LB, LB_SETCURSEL,
(WPARAM) ti.priority, 0);
// Increase priority to ensure control. You can
// change or remove this statement based on your
// execution environment.
SetThreadPriority(GetCurrentThread(),
THREAD_PRIORITY_ABOVE_NORMAL);
}
// Thread control panel dialog box callback function.
LRESULT CALLBACK ThrdCtrlPanel::ThreadPanel(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
int i;
HWND hpbRes, hpbSus, hpbTerm;
switch(message) {
case WM_INITDIALOG:
// Initialize priority list box.
for(i=0; i<NUMPRIORITIES i++) {
SendDlgItemMessage(hwnd, IDD_LB,
LB_ADDSTRING, 0, (LPARAM) priorities[i]);
}
// Set suspend and resume buttons for thread.
hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
hpbRes = GetDlgItem(hwnd, IDD_RESUME);
EnableWindow(hpbSus, true); // enable Suspend
EnableWindow(hpbRes, false); // disable Resume
return 1;
case WM_COMMAND:
map<HWND, ThreadInfo>::iterator p = dialogmap.find(hwnd);
switch(LOWORD(wParam)) {
case IDD_TERMINATE:
TerminateThread(p->second.hThread, 0);
// Disable Terminate button.
hpbTerm = GetDlgItem(hwnd, IDD_TERMINATE); }
EnableWindow(hpbTerm, false); // disable
// Disable Suspend and Resume buttons.
hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
hpbRes = GetDlgItem(hwnd, IDD_RESUME);
EnableWindow(hpbSus, false); // disable Suspend
EnableWindow(hpbRes, false); // disable Resume
return 1;
case IDD_SUSPEND:
SuspendThread(p->second.hThread);
// Set state of the Suspend and Resume buttons.
hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
hpbRes = GetDlgItem(hwnd, IDD_RESUME);
EnableWindow(hpbSus, false); // disable Suspend
EnableWindow(hpbRes, true); // enable Resume
p->second.suspended = true;
return 1;
case IDD_RESUME:
ResumeThread(p->second.hThread);
// Set state of the Suspend and Resume buttons.
hpbSus = GetDlgItem(hwnd, IDD_SUSPEND);
hpbRes = GetDlgItem(hwnd, IDD_RESUME); /'
EnableWindow(hpbSus, true); // enable Suspend /'
EnableWindow(hpbRes, false); // disable Resume
p->second.suspended = false;
return 1;
case IDD_LB:
// If a list box entry was clicked,
// then change the priority.
if(HIWORD(wParam)==LBN_DBLCLK) {
p->second.priority = SendDlgItemMessage(hwnd,
IDD_LB, LB_GETCURSEL,/'
0, 0);
SetThreadPriority(p->second.hThread,
p->second.priority-OFFSET);
}
return 1;
case IDCANCEL:
// If thread is suspended when panel is closed,
// then resume thread to prevent deadlock.
if(p->second.suspended) {
ResumeThread(p->second.hThread);
p->second.suspended = false;
}
// Remove this thread from the list.
dialogmap.erase(hwnd);
// Close the panel.
DestroyWindow(hwnd);?
return 1;
}
}
return 0;
}
The control panel requires the following resource file, called tcp.rc:
#include <windows.h>
#include "panel.h"
ThreadPanelDB DIALOGEX 20, 20, 140, 110
CAPTION "Thread Control Panel"
STYLE WS_BORDER | WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU
{
DEFPUSHBUTTON "Done", IDCANCEL, 55, 80, 33, 14
PUSHBUTTON "Terminate", IDD_TERMINATE, 10, 20, 42, 12
PUSHBUTTON "Suspend", IDD_SUSPEND, 10, 35, 42, 12
PUSHBUTTON "Resume", IDD_RESUME, 10, 50, 42, 12
LISTBOX IDD_LB, 65, 20, 63, 42, LBS_NOTIFY | WS_VISIBLE |
WS_BORDER | WS_VSCROLL | WS_TABSTOP
CTEXT "Thread Priority", IDD_TEXT1, 65, 8, 64, 10
CTEXT "Change State", IDD_TEXT2, 0, 8, 64, 10
}
The control panel uses the following header file called panel.h:
#define IDD_LB 200
#define IDD_TERMINATE 202
#define IDD_SUSPEND 204
#define IDD_RESUME 206
#define IDD_TEXT1 208
#define IDD_TEXT2 209
To use the thread control panel, follow these steps:
- Include tcp.cpp in your program.
- Include tcp.rc in your program’s resource file.
- Create the thread or threads that you want to control.
- Instantiate a ThrdCtrlPanel object for each thread.
Each ThrdCtrlPanel object links a thread with a dialog box that controls it. For large projects in which multiple files need access to ThrdCtrlPanel, you will need to use a header file called tcp.h that contains the declaration for ThrdCtrlPanel. Here is tcp.h:
// A header file for the ThrdCtrlPanel class.
class ThrdCtrlPanel {
public:
// Construct a control panel.
ThrdCtrlPanel(HINSTANCE hInst, HANDLE hThrd);
// The control panel's callback function.
static LRESULT CALLBACK ThreadPanel(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
};
Next: A Closer Look at the Thread Control Panel >>
More C++ Articles
More By McGraw-Hill/Osborne
|
This article is taken from chapter three of The Art of C++, written by Herbert Schildt (McGraw-Hill/Osborne, 2004; ISBN: 0072255129). Check it out at your favorite bookstore. Buy this book now.
|
|