№ | Макрос | Разрешаемые значения |
START_USESHOWWINDOW | dwShowWindow | |
STARTF_USESIZE | dwXSize и dwYSize | |
STARTF_USEPOSITION | dwX и dwY | |
STARTF_USECOUNTCHARS | dwXCountChars и dwYCount-Chars | |
STARTF_USEFILLATTRIBUTE | dwFillAttribute | |
STARTF_USESTDHANDLES | hStdInput | |
STARTF_FORCEONFEEDBACK | Включает возврат курсора | |
STARTF_FORCEOFFFEEDBACK | Выключает возврат курсора | |
STARTF_SCREENSAVER | Процесс является «хранителем экрана» (screen saver) |
Большинство полей структуры STARTUPINFO обычно не используется, и Вы можете их игнорировать. Однако задавать значение поля cb, содержащего размер структуры, обязательно, и, кроме того, некоторые другие поля должны иметь значение NULL. В примере этой главы информация о новом процессе в структуре STARTUPINFO задается следующим образом:
STARTUPINFO startin;
//
// Порождение нового процесса
//
startin.cb = sizeof(STARTUPINFO);
startin.lpReserved = NULL;
startin.lpDesktop = NULL;
startin.lpTitle = NULL;
startin.dwFlags = STARTF_USESHOWWINDOW;
startin.cbReserved2 = 0;
startin.lpReserved2 = NULL;
startin. wShowWindow = SW_SHOWMINIMIZED;
Таким образом, новый процесс будет начинаться с минимизированным окном, поскольку значение dwFlags установлено в STARTF_USESHOW-WINDOW, что позволяет использовать поле wShowWindow (по умолчанию размеры окна нового процесса Windows определяет самостоятельно).
Последним параметром функции CreateProcess() является lpPInfo – указатель на структуру типа PROCESS_INFORMATION, которая определяется следующим образом:
typedef struct _PROCESS_INFORMATION
{
HANDLE hProcess; // Дескриптор нового процесса
HANDLE hThread; // Дескриптор главного потока
DWORD dwProcessId;// Идентификатор нового процесса
DWORD dwThreadId; // Идентификатор нового потока
}
PROCESS_INFORMATION;
Дескрипторы нового процесса и его главного потока передаются в порождающий процесс в полях hProcess и hThread, а идентификаторы нового процесса и потока – в полях dwProcessId и dwThreadId. Программа может использовать или игнорировать эти значения по своему усмотрению.
|
Функция CreateProcess() возвращает ненулевое значение при успешном завершении и нуль в противном случае.
Вновь созданный процесс практически полностью независим от создавшего его процесса. Вместе с тем родительский процесс может принудительно завершить порожденный процесс. Для этого используется функция API TerminateProcess():
BOOL TerminateProcess(HANDLE hProcess, UINT status);
Параметр hProcess задает дескриптор порожденного процесса. Это дескриптор из поля hProcess информационной структуры, указатель на которую lpPInfo используется в качестве параметра в функции создания процесса CreateProcess(). Значение параметра status задает код возврата завершаемого процесса. Функция возвращает ненулевое значение при успешном завершении и нуль при возникновении ошибки.
Пример 12-1. Программа порождения процессов
Следующая программа демонстрирует создание и завершение процессов. Эта программа предоставляет возможность создавать до пяти порожденных процессов одновременно. Она также позволяет завершать порожденные процессы в порядке, обратном их созданию. Порождаемый в ней процесс будет иметь имя Test.exe, и файл с этим именем должен находиться в текущем каталоге Вашей программы. Однако Вы можете заменить имя Test.exe именем любой другой программы, работающей под Windows.
В приведенной ниже программе, как и в других примерах главы, используется технология виртуального окна для отображения и обновления содержимого реального окна.
// Демонстрация процессной многозадачности,
|
// с использованием виртуального окна
#include <Windows.h>
#include <String.h>
#include <Stdio.h>
#include "Proc.h"
#define Procmax 5
LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);
char szWinName[] = "МоеОкно"; // Имя класса окна
char str[255]; // Буфер строки вывода
int X=0, Y=0; // Текущие координаты строки
int procnum=0; // Количество активных процессов
int maxX, maxY; // Размеры экрана
HDC memdc; // DC виртуального окна
HBITMAP hbit; // Растр - это виртуальное окно
HBRUSH hbrush; // Дескриптор кисти
PROCESS_INFORMATION pinfo[Procmax];
int WINAPI WinMain (HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASS wcl;
HACCEL hAccel;
// Определить класс окна
wcl.hInstance=hThisInst; // Дескриптор приложения
wcl.lpszClassName=szWinName; // Имя класса окна
wcl.lpfnWndProc=WindowFunc; // Функция окна
wcl.style=0; // Стиль по умолчанию
wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION); // Иконка
wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор
wcl.lpszMenuName="MYMENU"; // Меню
wcl.cbClsExtra=0; // Без дополнительной
wcl.cbWndExtra=0; // информации
// Определить заполнение окна белым цветом
wcl.hbrBackground=
(HBRUSH)GetStockObject(WHITE_BRUSH);
if(!RegisterClass(&wcl)) // Зарегистр. класс окна
return 0;
// Создать окно
hwnd=CreateWindow(szWinName, // Имя класса
"Порождение новых процессов",
WS_OVERLAPPEDWINDOW,// Стиль окна
CW_USEDEFAULT, // Х-координата
CW_USEDEFAULT, // Y-координата
CW_USEDEFAULT, // Ширина окна
CW_USEDEFAULT, // Высота окна
HWND_DESKTOP, // Нет родит. окна
NULL, // Нет меню
hThisInst, // Дескрип. приложения
NULL); // Без дополит. аргументов
// Загрузить акселераторы
hAccel=LoadAccelerators(hThisInst,"MYMENU");
ShowWindow(hwnd,nWinMode); // Показать окно и
UpdateWindow(hwnd); // перерисовать содержимое
// Запустить цикл обработки сообщений
while(GetMessage (&msg,NULL,0,0))
if(!TranslateAccelerator(hwnd,hAccel,&msg))
{
TranslateMessage(&msg); // Использ.Клавиатуры
|
DispatchMessage (&msg); // Возврат к Windows
}
return msg. wParam;
}
// Следующая функция вызывается операционной системой
// Windows и получает в качестве параметров сообщения
// из очереди сообщений данного приложения
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT paintstruct;
TEXTMETRIC tm;
STARTUPINFO startin;
switch(message)
{
case WM_CREATE: // Получаем размеры экрана
maxX=GetSystemMetrics(SM_CXSCREEN);
maxY=GetSystemMetrics(SM_CYSCREEN);
hdc=GetDC(hwnd); // Совмест. с окном растр
memdc=CreateCompatibleDC(hdc);
hbit=CreateCompatibleBitmap(hdc,maxX,maxY);
SelectObject(memdc,hbit);
hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH);
SelectObject(memdc,hbrush);
PatBlt(memdc,0,0,maxX,maxY,PATCOPY);
ReleaseDC(hwnd,hdc);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_PROCESS:
if(procnum == Procmax)
{
MessageBox(hwnd,
"Нельзя создать больше",
"Ошибка", MB_OK);
break;
} // Не более чем Procmax
// Получить метрики текста */
GetTextMetrics(memdc, &tm);
sprintf(str, "Порождается процесс %d",
procnum);
TextOut(memdc, X, Y, str, strlen(str));
Y = Y+tm.tmHeight+tm.tmExternalLeading;
InvalidateRect(hwnd,NULL,1); //Сообщить
// Порождение нового процесса
startin.cb=sizeof(STARTUPINFO);
startin.lpReserved = NULL;
startin.lpDesktop = NULL;
startin.lpTitle = NULL;
startin.dwFlags =STARTF_USESHOWWINDOW;
startin.cbReserved2 = 0;
startin.lpReserved2 = NULL;
startin.wShowWindow = SW_SHOWMINIMIZED;
CreateProcess(NULL, "Test.exe", NULL,
NULL, FALSE, 0, NULL,
NULL, &startin,
&(pinfo[procnum]));
procnum++;
break;
case ID_KILLPROC:
if(procnum)
procnum--;
else
{
MessageBox(hwnd,
"Больше процессов нет",
"Ошибка", MB_OK);
break;
}
// Получить метрики текста
GetTextMetrics(memdc, &tm);
TerminateProcess
(pinfo[procnum].hProcess, 0);
sprintf(str, "Процесс %d завершен",
procnum);
TextOut(memdc, X, Y, str, strlen(str));
Y = Y+tm.tmHeight+tm.tmExternalLeading;
InvalidateRect(hwnd,NULL,1); //Сообщить
break;
case ID_HELP:
MessageBox(hwnd,
"F2: Новый процесс\n"
"F3: Завершить процесс",
"Помощь:", MB_OK);
InvalidateRect(hwnd,NULL,1); //Сообщить
break;
}
break;
case WM_PAINT: // Перерисовка окна
hdc=BeginPaint(hwnd,&paintstruct); // Пол. DC
// Теперь копируем растр из памяти на экран
BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);
EndPaint(hwnd,&paintstruct); // Освободить DC
break;
case WM_DESTROY: // Завершение программы
DeleteDC(memdc); // Удалить виртуальное окно
PostQuitMessage(0);
break;
default:
// Все сообщения, не обрабатываемые в данной
// функции, направляются на обработку по
// умолчанию
return DefWindowProc(hwnd,message,
wParam,lParam);
}
return 0;
}
Прежде чем компилировать эту программу, нужно создать файл определений Proc.h, приведенный ниже.
#define ID_PROCESS 100
#define ID_KILLPROC 101
#define ID_HELP 103
Кроме того, придется создать следующий файл ресурсов Process.rc:
#include <Windows.h>
#include "Proc.h"
MYMENU MENU
{
POPUP "Процессы"
{
MENUITEM "Новый процесс", ID_PROCESS
MENUITEM "Завершить процесс", ID_KILLPROC
}
MENUITEM "Помощь", ID_HELP
}
MYMENU ACCELERATORS
{
VK_F2, ID_PROCESS, VIRTKEY
VK_F3, ID_KILLPROC, VIRTKEY
VK_F1, ID_HELP, VIRTKEY
}
Рис. 12.1. Индикация создания и завершения процессов
Пример окна этой программы представлен на рис. 12.1.