Чтение онлайн

ЖАНРЫ

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

sStatus.dwCheckPoint = 0;

return 0;

 }

}

Функция Handler

А вот код функции Handler и вспомогательных потоков:

// Обработчик запросов от SCM

void WINAPI ServiceHandler(DWORD dwCode) {

 switch (dwCode) {

 case SERVICE_CONTROL_STOP:

 case SERVICE_CONTROL_SHUTDOWN:

ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0, 1000);

hSendStopPending = CreateEvent(NULL, TRUE, FALSE, NULL);

hSendStopThread = CreateThread(NULL, 0, SendStopPending, NULL, 0, & dwThreadId);

SetEvent(hWork);

if (WaitForSingleObject(hServiceThread, 1000) != WAIT_OBJECT_0) {

TerminateThread(hServiceThread, 0);

}

SetEvent(hSendStopPending);

CloseHandle(hServiceThread);

CloseHandle(hWork);

if(WaitForSingleObject(hSendStopThread, 2000) != WAIT_OBJECT_0) {

TerminateThread(hSendStopThread, 0);

}

CloseHandle(hSendStopPending);

sStatus.dwCurrentState = SERVICE_STOPPED;

SetServiceStatus(hSS, &sStatus);

break;

 case SERVICE_CONTROL_PAUSE:

bPause = true;

sStatus.dwCurrentState = SERVICE_PAUSED;

SetServiceStatus(hSS, &sStatus);

break;

 case SERVICE_CONTROL_CONTINUE:

bPause = true;

sStatus.dwCurrentState = SERVICE_RUNNING;

SetServiceStatus(hSS, &sStatus);

break;

 case SERVICE_CONTROL_INTERROGATE:

SetServiceStatus(hSS, &sStatus);

break;

 default:

SetServiceStatus(hSS, &sStatus);

break;

 }

}

//
Функция потока, аналогичная SendStartPending

// для останова службы.

DWORD WINAPI SendStopPending(LPVOID) {

 sStatus.dwCheckPoint = 0;

 sStatus.dwCurrentState = SERVICE_STOP_PENDING;

 sStatus.dwWaitHint = 2000;

 while (true) {

SetServiceStatus(hSS, &sStatus);

sStatus.dwCheckPoint++;

if (WaitForSingleObject(hSendStopPending, 1000) != WAIT_TIMEOUT) break;

 }

 sStatus.dwCheckPoint = 0;

 return 0;

}

Для запросов "Stop" и "Shutdown" используется алгоритм корректного останова службы, аналогичный тому, который используется при старте службы, с той лишь разницей, что вместо параметра SERVICE_START_PENDING в SetserviceStatus передается параметр SERVICE_STOP_PENDING, а вместо SERVICE_RUNNING — SERVICE_STOPPED.

В идеале для запросов "Pause" и "Continue" тоже следует использовать этот подход. Любознательный читатель без труда сможет реализовать его, опираясь на данные примеры.

Заключение

В заключение хотелось бы отметить, что с переходом на Windows 2000 разработка служб не претерпела изменений. Службы по-прежнему остаются важной частью программного обеспечения на платформе Windows, что предоставляет разработчикам широкое поле деятельности.

ВОПРОС-ОТВЕТ

Q. Хотелось бы побольше узнать о предварительном просмотре. В русской программе он смотрится инородным телом на своем иностранном языке. Можно ли его как-то настраивать под себя?

В этой же связи: не могу решить проблему.

В программе 3 меню и, соответственно, 3 панели инструментов, которые создал в Create. Переключая

меню, вызываю ShowControlBar – прячу ненужные панели и показываю необходимую. Но после вызова PRINT PREVIEW, в окне появляются сразу все 3 панели инструментов.

Попутно: что означает AFX_IDS_PREVIEW_CLOSE в String Table?

Serg Petukhov 

A. Отвечу по порядку. 

1. Все языко-зависимые компоненты для печати и предварительного просмотра (панель инструментов, диалог и строки) в соответствии с идеологией MFC оформлены как ресурсы. Эти ресурсы лежат в файле MFC42.DLL, но программа будет искать их там только если они отсутствуют в головной программе. Если же программа статически линкуется с MFC, ресурсы для печати/предварительного просмотра берутся из файла afxprint.rc. Чтобы в этом всём убедиться, достаточно открыть rc-файл, сгенерённым визардом, и найти там строчки: 

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)

#include "afxprint.rc" // printing/print preview resources

#endif
 

Теперь понятно, как поправить ситуацию.

– Копируем ресурсы из файла afxprint.rc (без окантовочных директив, то есть от строчки "// Printing Resources") в файл ресурсов нашей программы. При этом нужно проследить, чтобы новые ресурсы попали между директивами #ifdef APPSTUDIO_INVOKED и соответствующего #endif (иначе новые ресурсы нельзя будет изменить в редакторе).

– Убираем из файла ресурсов строчку #include "afxprint.rc" (вручную или через View→Resource includes). На самом деле, это необходимо сделать только при статической линковке с MFC, так как при динамической линковке эта строчка не используется (как я уже говорил, в этом случае ресурсы берутся из MFC42.DLL).

– Затем запускаем редактор ресурсов Visual Studio и русифицируем новые ресурсы. Не забудьте предварительно установить для каждого ресурса в свойствах Language:Russian, иначе вместо русского языка получите иероглифы!

– Пересобираем проект и убеждаемся, что теперь предварительный просмотр говорит по-русски. 

2. После выхода из Print Preview запускается функция CView::OnEndPrintPreview (файл viewcore.cpp). Из неё вызывается ещё одна функция – CFrameWnd::OnSetPreviewMode (файл winfrm.cpp). Просмотрев код этой функции, нетрудно убедиться, что она делает видимыми все стандартные панели с идентификаторами от AFX_IDW_CONTROLBAR_FIRST до AFX_IDW_CONTROLBAR_FIRST+31 включительно. Таким образом, чтобы MFC не вмешивалась в вашу работу с панелями инструментов, нужно назначить им идентификаторы за пределами этого диапазона (например, AFX_IDW_CONTROLBAR_LAST-N, где N = 0, 1, 2, …):

m_wndToolBar.CreateEx(..., AFX_IDW_CONTROLBAR_LAST);

3. Что касается строки AFX_IDS_PREVIEW_CLOSE, она просто содержит подсказку для команды Close предварительного просмотра. Если вам интересно, где она появляется, запустите режим предварительного просмотра, а затем наведите курсор на пункт Close из системного меню программы (которое раскрывается по щелчку на иконке в левом верхнем углу главного окна). При этом текст подсказки о закрытии предварительного просмотра появится в строке состояния. Можете заменить его на любой другой (на русском языке).

Александр Шаргин (rudankort@mail.ru) 
В ПОИСКАХ ИСТИНЫ 

Q. Есть приложение на базе диалога. По некоторым причинам необходимо уже внутрь этого диалога вставить закладки (страницы свойств, как хотите). Все это нормально делается и проблем тут не возникает. Но вот при использовании клавиши Tab для прогулки по диалогу фокус с последнего контрола, не принадлежащего Property Page, перемещается не на закладку страницы, а на ее первый определенный в Tab Layout контрол, и только после пробегания по всем элементам Property Page попадает на закладку. Как это вылечить?

George Orlov 

Это все на сегодня. Счастливо! 

Алекс Jenter jenter@mail.ru Красноярск, 2001.

Программирование на Visual C++

Выпуск №39 от 1 апреля 2001 г.

Добрый день, уважаемые подписчики! С праздником вас!

СТАТЬЯ

Диагностические средства MFC

Автор: Олег Быков 

Поделиться с друзьями: