Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
// следующего уведомления.
while (true) {
SetServiceStatus(hSS, &sStatus);
sStatus.dwCheckPoint++;
if (WaitForSingleObject(hSendStartPending, 1000) != WAIT_TIMEOUT) break;
}
sStatus.dwCheckPoint = 0;
return 0;
}
// Функция, инициализирующая службу. Чтение данных,
// распределение памяти и т.п.
void InitService() {
...
}
// Функция, содержащая «полезный» код службы.
DWORD WINAPI ServiceFunc(LPVOID) {
while (true) {
if (!bPause) {
// Здесь содержится код, который как правило
// выполняет какие-либо циклические операции...
}
if (WaitForSingleObject(hWork, 1000) != WAIT_TIMEOUT) break;
sStatus.dwCheckPoint = 0;
return 0;
}
}
А вот код функции 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 PetukhovA. Отвечу по порядку.
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 попадает на закладку. Как это вылечить?
Читать дальшеИнтервал:
Закладка: