CrProces.h
#define IDM_EXIT 100
#define IDM_TEST 200
#define IDM_ABOUT 301
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
CrProces.rc
#include "windows.h"
#include "CrProces.h"
MYAPP ICON DISCARDABLE "GENERIC.ICO"
MYAPP MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
MENUITEM "&Test!", IDM_TEST
POPUP "&Help"
BEGIN
MENUITEM "&About My Application...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 171, 43
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
CAPTION "My Application"
FONT 8, "MS Sans Serif"
{
CONTROL "MyApp", -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 3, 2, 16, 16
CONTROL "Generic Application", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 4, 100, 8
CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 116, 26, 50, 14
}
CrProces.c
#include <windows.h>
#include "CrProces.h"
HINSTANCE hInst; // current instance
LPCTSTR lpszAppName = "MyApp";
LPCTSTR lpszTitle = "My Application";
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
// Register the main application window class.
//............................................
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, lpszAppName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage(hInstance, lpszAppName,
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wc))
return(FALSE);
hInst = hInstance;
// Create the main application window.
//....................................
hWnd = CreateWindow(lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return(FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
HWND hList = NULL;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
// Create list box.
//.................
hList = CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "",
|
|
LBS_STANDARD | LBS_NOINTEGRALHEIGHT |
WS_CHILD | WS_VISIBLE,
0, 0, 10, 10,
hWnd, (HMENU)101,
hInst, NULL);
break;
case WM_SIZE:
if (wParam!= SIZE_MINIMIZED)
MoveWindow(hList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_TEST:
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
// Initialize structures.
//.......................
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
CreateProcess(NULL, "CALC", NULL, NULL, FALSE,
0, NULL, NULL, &si, &pi);
WaitForInputIdle(GetCurrentProcess(), INFINITE);
// Loop until process terminates.
//...............................
if (pi.hProcess)
{
DWORD dwExitCode = STILL_ACTIVE;
while (dwExitCode == STILL_ACTIVE)
{
WaitForSingleObject(pi.hProcess, 1000);
GetExitCodeProcess(pi.hProcess, &dwExitCode);
SendMessage(hList, LB_INSERTSTRING, 0, (LPARAM)"Waiting for Calc.");
UpdateWindow(hWnd);
}
SendMessage(hList, LB_INSERTSTRING, 0, (LPARAM)"Calc is Finished");
}
}
break;
case IDM_ABOUT:
DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
return(0L);
}
LRESULT CALLBACK About(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
CreateThread . , , . , , , , , . , .
. , Windows NT/2000 . :
*
* . Windows NT/2000 Windows 9.x, , NULL.
* , . , 32- .
* 32- , .
* , , , .
* . .
|
|
CreateThread . , , , . CreateThread .
Windows 9.x Windows NT/2000 , . , . , , . Win32 API ( synchronization objects). , .
, . . . 1.
1.
: . , , . , .
(wait functions) API, , . . , , . , , .
(mutex object) " " (mutual exclusion). . , , , , . Winl6Lock Winl6Mutex Windows 9.x 16- GDI USER . , CreateMutex , .
(semaphore object) . ( ), . , . , .
. , . , . . , CreateSemaphore .
|
|
(event objects) . . : , , , .
(manual-reset event object) SetEvent. ResetEvent. PulseEvent . , , . , CreateEvent .
(auto-reset event object) . , . , . , OpenEvent .
, , . 2. , .
2.
, | |
, , . , Win32 API , . (critical section) , . InitializeCriticalSection.
EnterCriticalSection API. , , , , , , , LeaveCriticalSection.
,
Win32 API, , , . 3.
3. ,
|
|
Attach Threadlnput | |
CancelWartableTimer | , |
CovertThreadToFiber | |
CreateEvent | |
CreateFiber | |
CreafeMutex | |
CreateProcess | |
CreateProcessAsUser | , |
CreateRemoteThread | , |
CreateSemaphore | |
CreateThread | |
Create WaitableTimer | |
DeleteCriticalSection | |
DeleteFiber | |
DuplicateHandle | , |
EnterCriticalSection | , , |
ExitProcess | |
ExitThread | |
GetCurrentFiber | |
GetCurrentProcess | |
GetCurrentProcessID | |
GetCurrentThread | |
GetCurrentThreadID | |
GetExitCodeProcess | . |
GetExitCodeThread | . |
GetFiberData | , |
GelPriorityClass | |
GetProcessAffinityMask | |
GetProcessHeap | |
GetProcessHeaps | , , |
GetProcessPriorityBoost | |
GetProcessShutdownParameters | |
GetProcessTimes | |
GetProcessVersion | Windows |
GetProcessWorkingSetSize | |
GetQueueStatus | |
GetThreadContext | |
GetThreadPriority | |
GetThreadPriorityBoost | |
GetThreadSelectorEntry | (LDT) |
GetThreadTimes | |
InitializeCrrticalSection | |
InterlockedCompareExchange | |
InterlockedDecrement | |
InterlockedExchange | |
InterlockedExchangeAdd | |
Interlockedlncrement | |
LeaveCriticalSection | , |
MsgWaitForMultipleObjects | , , |
MsgWaitForMultipieObjectsEx | , MsgWaitForMuitipleObjects, , - () |
OpenEvent | |
OpenMutex | |
OpenProcess | |
OpenSemaphore | |
OpenWaitableTimer | |
PulseEvent | , . |
QueueUserAPC | () |
RaiseException | , . RaiseException |
ReadProcessMemory | |
RegisterHotKey | |
ReleaseMutex | |
ReleaseSemaphore | |
ResetEvent | |
ResumeThread | |
SetEvent | |
SetPriorityClass | |
SetProcessAffinityMask | |
SetProcessPriorityBoost | |
SetProcessShufdownParameters | |
SetProcessWorkingSetSize | |
SetThreadAffinityMask | |
SetThreadContext | |
SetThreadldealProcessor | |
SetThreadPriority | |
SetThreadPriorityBoost | |
SetUnhandledExceptionFilter | |
SetWartableTimer | |
SignalObjectAndWait | |
Sleep | . |
SleepEx | Sleep , - () |
SuspendThread | |
SwitchToFiber | |
TerminateProcess | |
TerminateThread | |
TIsAlloc | |
TIsFree | |
TIsGetValue | , |
TIsGetValue | , |
TryEnterCrrticalSection | , , |
UnhandledExceptionFiter | , |
UnregisteredHotKey | |
WattForlnputldle | , |
WaitForMultipleObjects | |
WaitForMultipleObjectsEx | , WaitForMultipleObjects, , - () |
WaitForSingleObject | |
WaitForSingleObjectEx | , WaitForSingleObject, , - () |
WriteProcessMemory | , , |
CreateEvent
|
|
CreateEvent , SetEvent. , . , . , WaitFor-SingleObject, . , .
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpSecurityAttribs, BOOL bManualReset, BOOL nInitialState, LPCTSTR lpszEventName)
HANDLE: , . NULL. , GetLastError ERROR_ALREADY_EXIST, - 0.
winbase.h
. CreateProcess, DuplicateHandle, OpenEvent, ResetEvent, SetEvent, WaitForSingleObject, WaitForMultipleObjects.
, , . : Read, Write, Quit Help. , , . Read, Write. , , , . . , . .
CrEvent.h
#define IDM_EXIT 100
#define IDM_READ 200
#define IDM_WRITE 201
#define IDM_ABOUT 301
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
CrEvent.rc
#include "windows.h"
#include "CrEvent.h"
MYAPP ICON DISCARDABLE "GENERIC.ICO"
MYAPP MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Read", IDM_READ
MENUITEM "&Write", IDM_WRITE
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&About My Application...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 171, 43
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
CAPTION "My Application"
FONT 8, "MS Sans Serif"
{
CONTROL "MyApp", -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 3, 2, 16, 16
CONTROL "Generic Application", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 4, 100, 8
CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 116, 26, 50, 14
}
CrEvent.c
#include <windows.h>
#include "CrEvent.h"
HINSTANCE hInst; // current instance
LPCTSTR lpszAppName = "MyApp";
LPCTSTR lpszTitle = "My Application";
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
// Register the main application window class.
//............................................
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, lpszAppName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage(hInstance, lpszAppName,
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wc))
return(FALSE);
hInst = hInstance;
// Create the main application window.
//....................................
hWnd = CreateWindow(lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return(FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
#define SEMAPHORE_MAX_COUNT 10
LPCTSTR lpszReadSem = "Read Semaphore";
LPCTSTR lpszWriteEvent = "Write Event";
HANDLE hSemRead = NULL;
HANDLE hEventWrite = NULL;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
// Make the two synchronization objects.
//......................................
hSemRead = CreateSemaphore(NULL, 10, 10, lpszReadSem);
hEventWrite = CreateEvent(NULL, TRUE, TRUE, lpszWriteEvent);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_READ:
{
HANDLE hTmpSemRead;
HANDLE hTmpEventWrite;
hTmpSemRead= OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, lpszReadSem);
hTmpEventWrite = OpenEvent(SYNCHRONIZE, FALSE, lpszWriteEvent);
SetWindowText(hWnd, "Waiting for all Writes to Finish");
// Check that write manual reset event is signaled.
//.................................................
WaitForSingleObject(hEventWrite, INFINITE);
// Wait for semaphore.
//....................
WaitForSingleObject(hSemRead, INFINITE);
// Do the simulated read.
//.......................
SetWindowText(hWnd, "Reading");
Sleep(5000);
// Release semaphore.
//...................
ReleaseSemaphore(hSemRead, 1, NULL);
SetWindowText(hWnd, "Done Reading");
// Close the temporary handles.
//.............................
CloseHandle(hTmpSemRead);
CloseHandle(hTmpEventWrite);
}
break;
case IDM_WRITE:
{
DWORD dwSemaphoreCount = 0;
HANDLE hTmpSemRead;
HANDLE hTmpEventWrite;
hTmpSemRead = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, lpszReadSem);
hTmpEventWrite = OpenEvent(SYNCHRONIZE, FALSE, lpszWriteEvent);
// Wait for manual-reset event: it becomes nonsignaled.
//.....................................................
SetWindowText(hWnd, "Waiting for Write Event");
WaitForSingleObject(hEventWrite, INFINITE);
ResetEvent(hEventWrite);
SetWindowText(hWnd, "Waiting for All Reads to Finish");
// Release semaphore until its count is the maximum allowed.
//..........................................................
while (dwSemaphoreCount!= SEMAPHORE_MAX_COUNT)
{
WaitForSingleObject(hSemRead, INFINITE);
ReleaseSemaphore(hSemRead, 1, &dwSemaphoreCount);
dwSemaphoreCount++;
}
SetWindowText(hWnd, "Writing");
// Do the simulated write.
//........................
Sleep(10000);
SetWindowText(hWnd, "Done Writing");
// SetEvent: event object becomes signaled.
//.........................................
SetEvent(hEventWrite);
// Close the handles.
//...................
CloseHandle(hTmpSemRead);
CloseHandle(hTmpEventWrite);
}
break;
case IDM_ABOUT:
DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
}
break;
case WM_DESTROY:
if (hSemRead)
CloseHandle(hSemRead);
if (hEventWrite)
CloseHandle(hEventWrite);
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
return(0L);
}
LRESULT CALLBACK About(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
SECURITY_ATTRIBUTES
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL blnheritHandle; } SECURITY_ATTRIBUTES;
nLength DWORD: .
lpSecurityDescriptor LPVOID: , . NULL, . Windows 9.x .
blnheritHandle BOOL: , TRUE. FALSE.
CreateMutex
CreateMutex , . , . , , , . , , , , . , ReleaseMutex , . MUTEX_ALL_ACCESS , . . , , CloseHandle. , .
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpSecurityAttribs, BOOL bInitialOwner, LPCTSTR lpszMutexName)
HANDLE: , . NULL. , GetLastError ERROR_ALREADY_EXIST; 0. GetLastError.
winbase.h
. CreateProcess, DuplicateHandle, OpenMutex, ReleaseMutex, WaitForSingleObject, WaitForMultipleObjects.
. Test!, , , , . Test! . .
. \local-sources\chap25\25-03.txt
CrMutex.h
#define IDM_EXIT 100
#define IDM_TEST 200
#define IDM_ABOUT 301
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
CrMutex.rc
#include "windows.h"
#include "CrMutex.h"
MYAPP ICON DISCARDABLE "GENERIC.ICO"
MYAPP MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
MENUITEM "&Test!", IDM_TEST
POPUP "&Help"
BEGIN
MENUITEM "&About My Application...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 171, 43
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
CAPTION "My Application"
FONT 8, "MS Sans Serif"
{
CONTROL "MyApp", -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 3, 2, 16, 16
CONTROL "Generic Application", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 4, 100, 8
CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 116, 26, 50, 14
}
CrMutex.c
#include <windows.h>
#include "CrMutex.h"
HINSTANCE hInst; // current instance
LPCTSTR lpszAppName = "MyApp";
LPCTSTR lpszTitle = "My Application";
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
// Register the main application window class.
//............................................
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, lpszAppName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage(hInstance, lpszAppName,
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wc))
return(FALSE);
hInst = hInstance;
// Create the main application window.
//....................................
hWnd = CreateWindow(lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return(FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
LPCTSTR lpszMutex = "Example Mutex";
HANDLE hMutex = NULL;
// Child thread procedure waits until mutex becomes signaled,
// holds the object for five seconds, and then releases it.
//...........................................................
DWORD WINAPI ChildThreadProc(LPDWORD lpData)
{
TCHAR szBuffer[128];
HWND hWnd = (HWND)lpData;
HANDLE hTmpMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, lpszMutex);
wsprintf(szBuffer,"Thread %x waiting for Mutex %x",
GetCurrentThreadId(), hMutex);
SendMessage(hWnd, WM_USER, 0, (LPARAM)szBuffer);
// Wait for signaled mutex.
//.........................
WaitForSingleObject(hMutex, INFINITE);
wsprintf(szBuffer,"Thread %x got mutex!", GetCurrentThreadId());
SendMessage(hWnd, WM_USER, 0, (LPARAM)szBuffer);
// Shut out other threads.
//........................
Sleep(5000);
// Release mutex.
//...............
wsprintf(szBuffer,"Thread %x is done with mutex", GetCurrentThreadId());
SendMessage(hWnd, WM_USER, 0, (LPARAM) szBuffer);
ReleaseMutex(hMutex);
CloseHandle(hMutex);
return(0);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hList = NULL;
static int nMsgNum = 0;
switch(uMsg)
{
case WM_CREATE:
// Create list box.
//.................
hList = CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "",
LBS_STANDARD | LBS_NOINTEGRALHEIGHT |
WS_CHILD | WS_VISIBLE,
0, 0, 10, 10,
hWnd, (HMENU)101,
hInst, NULL);
hMutex = CreateMutex(NULL, FALSE, lpszMutex);
break;
case WM_SIZE:
if (wParam!= SIZE_MINIMIZED)
MoveWindow(hList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_USER:
{
TCHAR szBuffer[128];
wsprintf(szBuffer, "%3d: %s", ++nMsgNum, (LPTSTR)lParam);
SendMessage(hList, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuffer);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_TEST:
{
DWORD id;
// Make a thread.
//...............
CreateThread(NULL, 0, ChildThreadProc, hWnd, 0, &id);
}
break;
case IDM_ABOUT:
DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
}
break;
case WM_DESTROY:
if (hMutex)
CloseHandle(hMutex);
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
return(0L);
}
LRESULT CALLBACK About(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
CreateSemaphore
CreateSemaphore . , , , , . (, WaitForSingleObject), . Release-Semaphore, . , ISemMax-Count.
DWORD CreateSemaphore(LPSECURITY_ATTRIBUTES lpThreadSecurity, LONG lSemInitialCount, LONG lSemMaxCount, LPCTSTR lpszSemName)
winbase.h
. CloseHandle, DuplicateHandle, OpenSemaphore, ReleaseSemaphore, WaitForSingleObject, WaitForMultipleObjects.
. Test!, . , , , . , Test!, .
CrSem.h
#define IDM_EXIT 100
#define IDM_TEST 200
#define IDM_ABOUT 301
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
CrSem.rc
#include "windows.h"
#include "CrSem.h"
MYAPP ICON DISCARDABLE "GENERIC.ICO"
MYAPP MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
MENUITEM "&Test!", IDM_TEST
POPUP "&Help"
BEGIN
MENUITEM "&About My Application...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 171, 43
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
CAPTION "My Application"
FONT 8, "MS Sans Serif"
{
CONTROL "MyApp", -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 3, 2, 16, 16
CONTROL "Generic Application", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 4, 100, 8
CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 116, 26, 50, 14
}
CrSem.c
#include <windows.h>
#include "CrSem.h"
HINSTANCE hInst; // current instance
LPCTSTR lpszAppName = "MyApp";
LPCTSTR lpszTitle = "My Application";
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
// Register the main application window class.
//............................................
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, lpszAppName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage(hInstance, lpszAppName,
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wc))
return(FALSE);
hInst = hInstance;
// Create the main application window.
//....................................
hWnd = CreateWindow(lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return(FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
LPCTSTR lpszSemaphore = "Test Semaphore";
// This is a child thread procedure that waits for a semaphore,
// holds the semaphore for five seconds, and releases the semaphore.
// Threads that cannot get semaphores will wait until other threads exit.
//.......................................................................
DWORD WINAPI ChildThreadProc(LPDWORD lpData)
{
TCHAR szBuffer[256];
DWORD dwSemCount = 0;
HWND hList = (HWND)lpData;
HANDLE hSemaphore = OpenSemaphore(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, lpszSemaphore);
wsprintf(szBuffer,"Thread %x waiting for semaphore %x",
GetCurrentThreadId(), hSemaphore);
SendMessage(hList, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuffer);
// Check for signaled semaphore.
//..............................
WaitForSingleObject(hSemaphore, INFINITE);
wsprintf(szBuffer,"Thread %x got semaphore", GetCurrentThreadId());
SendMessage(hList, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuffer);
Sleep(5000);
// Release semaphore.
//...................
ReleaseSemaphore(hSemaphore, 1, &dwSemCount);
wsprintf(szBuffer,"Thread %x is done with semaphore. Its count was %ld.",
GetCurrentThreadId(), dwSemCount);
SendMessage(hList, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szBuffer);
CloseHandle(hSemaphore);
return(0);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hList = NULL;
static HANDLE hSemaphore = NULL;
switch(uMsg)
{
case WM_CREATE:
// Create list box.
//.................
hList = CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "",
LBS_STANDARD | LBS_NOINTEGRALHEIGHT |
WS_CHILD | WS_VISIBLE,
0, 0, 10, 10,
hWnd, (HMENU)101,
hInst, NULL);
hSemaphore = CreateSemaphore(NULL, 4, 4, lpszSemaphore);
break;
case WM_SIZE:
if (wParam!= SIZE_MINIMIZED)
MoveWindow(hList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_TEST:
{
DWORD dwChildId;
CreateThread(NULL, 0, ChildThreadProc, hList, 0, &dwChildId);
}
break;
case IDM_ABOUT:
DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
}
break;
case WM_DESTROY:
if (hSemaphore)
CloseHandle(hSemaphore);
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
return(0L);
}
LRESULT CALLBACK About(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
CreateThread
CreateThread , . . . , lpStartAddr. , DWORD, ExitThread. , , GetExitCodeThread.
THREAD_PRIORITY_NORMAL. GetThreadPriority SetThreadPriority. , CloseHandle.
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadSecurity, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParam, DWORD dwCreateFlags, LPDWORD lpdwThreadId)
HANDLE: , . NULL. GetLastError.
winbase.h
. CloseHandle, CreateProcess,CreateRemoteThread, ExitThread, GetExitCodeThread, GetLastError, OpenThreadToken, SetErrorMode, TerminateProcess, TerminateThread.
. CreateSemaphore.
EnterCriticalSection
EnterCriticalSection . , . . , EnterCriticalSection , . LeaveCriticalSection , , . , EnterCriticalSection TryEnterCriticalSection , .
VOID EnterCriticalSection (LPCRITICAL_SECTION lpcs)
lpcs LPCRITICAL_SECTION: .
winbase.h
. CreateMutex, DeleteCriticalSection, InitializeCriticalSection, LeaveCriticalSection.
( ) . , Test!, . .
. \local-sources\chap25\25-07.txt
EntCrSec.h
#define IDM_EXIT 100
#define IDM_TEST 200
#define IDM_ABOUT 301
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
EntCrSec.rc
#include "windows.h"
#include "EntCrSec.h"
MYAPP ICON DISCARDABLE "GENERIC.ICO"
MYAPP MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
MENUITEM "&Test!", IDM_TEST
POPUP "&Help"
BEGIN
MENUITEM "&About My Application...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 171, 43
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
CAPTION "My Appl