Издание четвертое windows ® для профессионалов создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows


Раздел Windows Version Build Option



Pdf просмотр
страница67/68
Дата28.11.2016
Размер3.57 Mb.
Просмотров12589
Скачиваний0
1   ...   60   61   62   63   64   65   66   67   68
Раздел Windows Version Build Option
Поскольку часть моих программ обращается к новым функциям, появившимся только в Windows 2000, в этом разделе определяется идентификатор _WIN32_WINNT:
#define _WIN32_WINNT Мне пришлось это сделать, так как прототипы новых функций в заголовочных файлах Windows задаются так:

699
П Р ИЛ ОЖЕ НИ Е А
Среда разработки (_WIN32_WINNT >= 0x0500)
M
WINBASEAPI
BOOL
WINAPI
AssignProcessToJobObject(
IN HANDLE hJob,
IN HANDLE hProcess
);
M
#endif /* _WIN32_WINNT >= 0x0500 Пока Вы сами не определите _WIN32_WINNT (до включения файла прототипы новых функций не будут объявлены, и компилятор, встретив попытки вызова этих функций, сообщит об ошибках. Microsoft специально защитила эти функции идентификатором _WIN32_WINNT, чтобы разработчики, ориентирующиеся на разные версии Windows, случайно не использовали функции, существующие пока только в Windows 2000.
Раздел Unicode Build Option
Все примеры написаны так, чтобы их можно было компилировать с использованием как ANSI, таки. При компиляции для процессоров
x86 — чтобы программы работали ив по умолчанию принимается кодировка ANSI. Но для других процессорных платформ при сборке применяется Unicode, что ускоряет работу программ.
Если Вы хотите создать Unicode версию программы для процессоров
x86, раском ментируйте всего одну строку, в которой определяется макрос UNICODE, и переком пилируйте программу. Определяя макрос UNICODE в файле CmnHdr.h, я упрощаю себе управление сборкой программ примеров. Подробнее о Unicode см. главу 2.
Раздел Windows Definitions и диагностика уровня 4
Разрабатывая программы, я всегда стараюсь, чтобы компилятор мог транслировать их,
не выдавая предупреждений и сообщений об ошибках. Кроме того, я предпочитаю устанавливать при компиляции наивысший уровень диагностики. В этом случае компилятор делает за меня максимум работы и проверяет в коде даже самые незначительные мелочи. Для компиляторов Microsoft C/C++ это означает, что я компилировал все примеры с использованием диагностики уровня Увы, отдел операционных систем вне разделяет моих сантиментов насчет компиляции с применением диагностики уровня 4. В итоге, когда я установил такой уровень, компилятор выдал предупреждения по множеству строк из заголовочных файлов самой Windows. К счастью, они не свидетельствуют о каких то проблемах в коде — большинство из них генерируется из за нетипичного употребления конструкций языка C, в которых используются расширения, реализованные практически всеми поставщиками Windows совместимых компиляторов.
Поэтому в данном разделе CmnHdr.h я указываю уровень диагностики 3, включаю стандартный заголовочный файла потом задаю уровень диагностики На этом уровне компилятор часто выдает предупреждения по таким ерундовым поводам, что приходится вставлять директиву
#pragma warning для подавления некоторых предупреждений.

700
Windows для профессионалов
Вспомогательный макрос Pragma Message
Мне всегда хочется, чтобы какая то часть программы, которую я еще пишу, сразу же начала работать, а доводку обычно откладываю на потом. Раньше, когда мне надо было напомнить себе, дескать, этот участок кода еще потребует внимания, я включал в код строки типа message("Fix this Встречая такую строку, компилятор выдавал мне сообщение, напоминающее, что в этом месте работа еще не закончена. Увы, толку от него не очень много. Было бы куда полезнее, если бы он сообщал имя исходного файла и номер строки, где стоит эта директива. Тогда я не только узнавал бы, что какая то работа не доделана, но и мог бы тут же найти нужный участок кода.
А для этого не обойтись без набора макросов. В итоге я создал макрос вызываемый так chMSG(Fix this Дойдя до соответствующей строки, компилятор выдает что то вроде this Теперь, работая в Microsoft Visual Studio, можно дважды щелкнуть это сообщение в окне вывода, и тогда открывается соответствующий файла курсор ввода переходит на нужную строку.
И еще одна удобная мелочь — макрос chMSG не требует заключать текстовую строку в кавычки.
Макросы chINRANGE и chDIMOF
Это весьма полезные макросы, которыми я часто пользуюсь в своих программах.
Первый макрос проверяет, укладывается ли какое то значение в заданный диапазона второй просто возвращает число элементов в массиве. Делается это так оператор
sizeof вычисляет размер массива в байтах, а результат делится на число байтов, занимаемых одним элементом.
Макрос chBEGINTHREADEX
Все многопоточные программы из этой книги используют вместо Windows функции
CreateThread функцию _beginthreadex из библиотеки Microsoft C/C++. Это связано стем, что
_beginthreadex подготавливает новый поток так, чтобы он мог вызывать библиотечные функции, а при его завершении гарантирует уничтожение информации,
используемой библиотекой в данном потоке (подробнее см. главу 6). К сожалению,
прототип этой функции имеет вид long __cdecl _beginthreadex(
void *,
unsigned,
unsigned (__stdcall *)(void *),
void *,
unsigned,
unsigned Хотя значения параметров
_beginthreadex идентичны значениям параметров функции, их типы не совпадают. Вот прототип CreateThread:

701
П Р ИЛ ОЖЕ НИ Е А
Среда разработки typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(PVOID pvParam);
HANDLE CreateThread(
PSECURITY_ATTRIBUTES psa,
DWORD cbStack,
PTHREAD_START_ROUTINE pfnStartAddr,
PVOID pvParam,
DWORD fdwCreate,
PDWORD Типы данных Windows функции и ее библиотечного аналога так отличаются потому, что группа разработчиков библиотеки Microsoft C/C++ не пожелала зависеть от группы разработчиков операционных систем. Похвальное решение, но оно затруднило использование функции
_beginthreadex.
В том, как Microsoft объявила прототип
_beginthreadex, есть целых две проблемы.
Во первых, некоторые типы данных, используемые этой функцией, не совпадают с базовыми типами, примененными в
CreateThread. Например, в Windows API тип данных определен как unsigned long К этому типу данных относятся параметры
cbStack и fdwCreate функции Create
Thread. Нов прототипе _beginthreadex эти параметры объявлены как unsigned, что наделе означает
unsigned int. Компилятор считает типы unsigned int и unsigned long разными и выдает предупреждение. Поскольку
_beginthreadex не является частью стандартной библиотеки C/C++ и существует лишь как альтернатива Windows функции
CreateThread, я полагаю, что Microsoft следовало бы объявить прототип _beginthreadex
так, чтобы предупреждения не генерировались long __cdecl _beginthreadex(
void *psa,
unsigned long cbStack,
unsigned (__stdcall *) (void *pvParam),
void *pvParam,
unsigned long fdwCreate,
unsigned long Вторая проблема — продолжение первой. Функция
_beginthreadex возвращает значение типа
unsigned long — описатель только что созданного потока. Обычно программа сохраняет это значение в переменной типа HANDLE:
HANDLE hThread = Эта строка заставит компилятор выдать другое предупреждение. Чтобы избежать этого предупреждения, надо переписать строку с явным преобразованием типов hThread = (HANDLE) Это, конечно, неудобно. Чтобы компилятор ко мне не приставал, я определил в файле CmnHdr.h макрос chBEGINTHREADEX, который сам делает эти преобразования unsigned (__stdcall *PTHREAD_START) (void *);
#define chBEGINTHREADEX(psa, cbStack, pfnStartAddr,
\
pvParam, fdwCreate, pdwThreadId)
\
((HANDLE)_beginthreadex(
\
см. след. стр.

702
Windows для профессионалов
(void *)
(psa),
\
(unsigned)
(cbStack),
\
(PTHREAD_START)
(pfnStartAddr),
\
(void *)
(pvParam),
\
(unsigned)
(fdwCreate),
\
(unsigned *)
(pdwThreadId)))
Моя реализация DebugBreak для платформы x86
Иногда мне нужно прервать код в какой то точке, даже если процесс не выполняется под управлением отладчика. Для этого поток должен вызвать функцию
DebugBreak,
которая содержится в Kernel32.dll. Она позволяет подключить к процессу отладчик.
Как только отладчик подключается к процессу, регистр указателя команд позиционируется на машинную команду, вызвавшую прерывание (останов. Эта команда находится в функции
DebugBreak из Kernel32.dll, и, чтобы увидеть свой исходный код, я должен выйти из
DebugBreak, используя режим пошагового выполнения кода.
На процессорной платформе
x86 выполнение кода прерывается инструкцией 3». Поэтому я переопределил
DebugBreak для платформы x86, включив эту ассемблерную инструкцию и сделав функцию подставляемой в код. При выполнении моей
DebugBreak перехода вне происходит, прерывание возникает непосредственно в моем коде, и регистр указателя команд позиционируется наследующий оператор языка C/C++. Так удобнее.
Определение кодов программных исключений
Работая с программными исключениями, Вы должны определить собственные 32
битные коды исключений. Эти коды имеют специфический формат, о котором я рассказывал в главе 24. Чтобы упростить определение кодов программных исключений,
я использую макрос MAKESOFTWAREEXCEPTION.
Макрос chMB
Он просто выводит окно, в заголовке которого показывает полное (вместе с путем)
имя исполняемого файла вызывающего процесса.
Макросы chASSERT и chVERIFY
Чтобы упростить выявление ошибок при разработке программ, я часто вкраплял в код макросы chASSERT. Этот макрос проверяет, истинно ли выражение
x, и, если нет, выводит окно с именем файла, строкой и выражением, вычисление которого закончилось неудачно. В готовой программе макрос chASSERT раскрывается в пустое определение. Макрос chVERIFY практически идентичен предыдущему за исключением того,
что выражения проверяются не только при отладке, но ив готовой программе.
Макрос chHANDLE_DLGMSG
Используя распаковщики сообщений (message crackers) при работе с диалоговыми окнами, нельзя обращаться к макросу HANDLE_MSG из заголовочного файла Win dowsX.h. Дело в том, что он не возвращает TRUE или FALSE в зависимости от того,
обработано сообщение процедурой диалогового окна или нет. Чтобы устранить эту проблему, я и написал макрос chHANDLE_DLGMSG.

703
П Р ИЛ ОЖЕ НИ Е А
Среда разработки
Макрос chSETDLGICONS
Поскольку во многих программах примерах диалоговое окно выступает как главное,
его значок надо изменять вручную, чтобы он корректно показывался и на панели задачи в окне переключения задачи в заголовке самого окна программы. Макрос chSETDLGICONS, вызываемый всякий раз, когда диалоговое окно получает сообщение, обеспечивает корректную обработку значков.
Встраиваемые функции для проверки версии операционной системы
Большинство программ примеров работает на всех платформах, но некоторые из них требуют функций, не поддерживаемых Windows 95 и Windows 98, а какая то часть использует функции, имеющиеся только в Windows 2000. Поэтому каждая программа проверяет при инициализации версию системы и выводит соответствующее сообщение, если ей нужна более современная операционная система.
В функции
_tWinMain программ примеров, неработающих в Windows 95 и Win dows 98, Вы увидите вызов моей функции
chWindows9xNotAllowed, а в аналогичном месте программ примеров, работающих только в Windows 2000, — вызов моей функции
chWindows2000Required.
Проверка на поддержку Unicode
Windows 98 не поддерживает Unicode в той мере, как Windows 2000, и фактически приложения, вызывающие Unicode функции, просто не будут работать в ней К сожалению не предупреждает о запуске приложения, использующего Применительно к моим программам это означало бы, что они будут немедленно завершаться без всякой диагностики. Спятить можно!
Поскольку надо было как то узнавать, что программа, скомпилированная под, запускается в Windows 98, я создал C++ класс CUnicodeSupported. Его конструктор проверяет, полностью ли поддерживает данная операционная система и, если нет, сообщает об этом — только после этого процесс завершается.
Вы заметите, что в CmnHdr.h я создаю глобальный статический экземпляр этого класса. Когда моя программа запускается, стартовый код из библиотеки C/C++ вызывает конструктор данного объекта. Если конструктор обнаруживает, что операционная система полностью поддерживает Unicode, он просто возвращает управление, и программа продолжает выполнение. Поскольку я создаю глобальный экземпляр класса, мне не приходится включать специальный код в каждый модуль исходного кода программы. В программах, не использующих Unicode, C++ класс CUnicodeSupported не объявляется, и его экземпляр не создается.
Принудительное указание компоновщику входной функции (w)WinMain
Некоторые читатели предыдущих изданий этой книги, включавшие мои модули исходного кода в новые проекты Visual C++, получали при их сборке сообщения об ошибках от компоновщика. Проблема была в том, что они создавали проект Win32
Console Application, заставляя компоновщик искать входную функцию
(w)main. Но,
поскольку все мои программы примеры являются GUI приложениями, в их исходном коде используется входная функция
_tWinMain — вот почему компоновщик сообщал об ошибках.
Мой стандартный ответ этим читателям был таков удалите текущий проект, создайте в Visual C++ проект Win32 Application (в названии шаблона проектов этого типа не должно быть слова «Console») и добавьте в него мои файлы с исходным кодом. Тогда

704
Windows для профессионалов
компоновщик будет искать входную функцию
(w)WinMain, которая и присутствует в моем коде, — никаких ошибок при сборке не возникнет.
В конце концов, чтобы сократить поток почты поэтому поводу, я добавил в файл директиву
pragma, которая заставляет компоновщик искать входную функцию, даже если Вы создали в Visual C++ проект Win32 Console Чем отличаются эти типы проектов Visual C++, как компоновщик выбирает нужный вид входных функций и как изменить стандартное поведение компоновщика, я подробно объяснил в главе 4.
CmnHdr.h
/******************************************************************************
Модуль: Автор Copyright (c) 2000, Джеффри Рихтер (Jeffrey Назначение Общий заголовочный файл, содержащий полезные макросы и определения, используемые во всех примерах из этой книги once // включайте этот заголовочный файл только в главный модуль Windows Version Build Option /////////////////////////
#define _WIN32_WINNT 0x0500
//#define WINVER 0x0500
//////////////////////////// Unicode Build Option /////////////////////////////
// если мы компилируем не для x86, используем только Unicode
#ifndef _M_IX86
#define UNICODE
#endif
// чтобы компилировать нас использованием Unicode,
// раскомментируйте следующую строку UNICODE
// работая с Unicode версиями Windows функций, надо применять и Unicode функции из библиотеки C
#ifdef UNICODE
#define _UNICODE
#endif
///////////////////////////// Windows Definitions /////////////////////////////
#pragma warning(push, 3)
#include
#pragma warning(pop)
#pragma warning(push, 4)
////////// проверка на использование корректных заголовочных файлов ///////////
#ifndef WT_EXECUTEINPERSISTENTIOTHREAD
Рис. A-1.
Заголовочный файл CmnHdr.h

705
П Р ИЛ ОЖЕ НИ Е А
Среда разработки
Рис. A-1.
продолжение
#pragma message("You are not using the latest Platform SDK header/library ")
#pragma message("files. This may prevent the project from building correctly.")
#endif
///////// обеспечиваем корректную компиляцию при диагностике уровня 4 /////////
/* нестандартное расширение однострочный комментарий */
#pragma warning(disable:4001)
// неиспользуемый формальный параметр warning(disable:4100)
// Внимание создается предкомпилированный заголовочный файл warning(disable:4699)
// функция не подставлена warning(disable:4710)
// подставляемая функция, на которую нет ссылок, удалена warning(disable:4514)
// не удалось создать оператор присвоения warning(disable:4512)
//////////////////// вспомогательный макрос Pragma Message когда компилятор встречает строку вида chMSG(Fix this он генерирует сообщение вроде this Вы можете перейти прямо на эту строку и проверить окружающий ее код chSTR2(x) #x
#define chSTR(x) chSTR2(x)
#define chMSG(desc) message(__FILE__ "(" chSTR(__LINE__) "):" #desc)
////////////////////////////// макрос chINRANGE ///////////////////////////////
// этот макрос возвращает TRUE, если число укладывается в заданный диапазон chINRANGE(low, Num, High) (((low) <= (Num)) && ((Num) <= (High)))
//////////////////////////////// макрос chDIMOF ///////////////////////////////
// этот макрос сообщает количество элементов в массиве
#define chDIMOF(Array) (sizeof(Array) / sizeof(Array[0]))
см. след. стр.

706
Windows для профессионалов
Рис. A-1.
продолжение
//////////////////////////// макрос chBEGINTHREADEX ///////////////////////////
// Макрос chBEGINTHREADEX вызывает библиотечную функцию _beginthreadex.
// Библиотека построена так, чтобы не зависеть от типов данных Windows, например HANDLE. Таким образом, при вызове _beginthreadex Windows программист должен приводить значения к типам данных Windows. Это жутко неудобно, поэтому я написал макрос, который сам выполняет необходимые преобразования типов unsigned (__stdcall *PTHREAD_START) (void *);
#define chBEGINTHREADEX(psa, cbStack, pfnStartAddr,
\
pvParam, fdwCreate, pdwThreadId)
\
((HANDLE)_beginthreadex(
\
(void *)
(psa),
\
(unsigned)
(cbStack),
\
(PTHREAD_START)
(pfnStartAddr),
\
(void *)
(pvParam),
\
(unsigned)
(fdwCreate),
\
(unsigned *)
(pdwThreadId)))
///////////////// моя реализация DebugBreak для платформы x86 /////////////////
#ifdef _X86_
#define DebugBreak() _asm { int 3 }
#endif
///////////// макрос для определения кодов программных исключений /////////////
#define MAKESOFTWAREEXCEPTION(Severity, Facility, Exception) \
((DWORD) ( \
/* код степени "тяжести" */ (Severity ) |
\
/* MS (0) или польз. (1) */ (1 << 29) |
\
/* Зарезервирован (0) */ (0 << 28) |
\
/* Код подсистемы */ (Facility << 16) |
\
/* Код исключения */ (Exception << 0)))
/////////////////////////// макрос Quick MessageBox ///////////////////////////
inline void chMB(PCSTR s) {
char szTMP[128];
GetModuleFileNameA(NULL, szTMP, chDIMOF(szTMP));
MessageBoxA(GetActiveWindow(), s, szTMP, MB_OK);
}
///////////////////////// макросы chASSERT и chVERIFY /////////////////////////
inline void chFAIL(PSTR szMsg) {
chMB(szMsg);
DebugBreak();
}
// выводим окно, которое сообщает о невыполнении условия inline void chASSERTFAIL(LPCSTR file, int line, PCSTR expr) {

707
П Р ИЛ ОЖЕ НИ Е А
Среда разработки
Рис. A-1.
продолжение
char sz[128];
wsprintfA(sz, "File %s, line %d : %s", file, line, expr);
chFAIL(sz);
}
// выводим окно, если условие не выполнено в отладочном режиме _DEBUG
#define chASSERT(x) if (!(x)) chASSERTFAIL(__FILE__, __LINE__, #x)
#else
#define chASSERT(x)
#endif
// chASSERT работает только в режиме отладки а chVERIFY из готовой программы не удаляется _DEBUG
#define chVERIFY(x) chASSERT(x)
#else
#define chVERIFY(x) (x)
#endif
/////////////////////////// макрос chHANDLE_DLGMSG ////////////////////////////
// Обычный макрос HANDLE_MSG из WindowsX.h для диалоговых окон работает некорректно, так как DlgProc функции возвращают BOOL вместо LRESULT
// (подобно WndProc). Макрос chHANDLE_DLGMSG устраняет эту проблему chHANDLE_DLGMSG(hwnd, message, fn)
\
case (message): return (SetDlgMsgResult(hwnd, uMsg,
\
HANDLE_##message((hwnd), (wParam), (lParam), (fn))))
//////////////////////////// макрос chSETDLGICONS /////////////////////////////
// настраивает значки диалоговых окон inline void chSETDLGICONS(HWND hwnd, int idi) {
SendMessage(hwnd, WM_SETICON, TRUE, (LPARAM)
LoadIcon((HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
MAKEINTRESOURCE(idi)));
SendMessage(hwnd, WM_SETICON, FALSE, (LPARAM)
LoadIcon((HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
MAKEINTRESOURCE(idi)));
}
////////////// макросы для проверки версии операционной системы ///////////////
inline void chWindows9xNotAllowed() {
OSVERSIONINFO vi = { sizeof(vi) };
GetVersionEx(&vi);
if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
chMB("This application requires features not present in Windows 9x.");
ExitProcess(0);
}
}
см. след. стр.

708
Windows для профессионалов
Рис. A-1.
продолжение
inline void chWindows2000Required() {
OSVERSIONINFO vi = { sizeof(vi) };
GetVersionEx(&vi);
if ((vi.dwPlatformId != VER_PLATFORM_WIN32_NT) && (vi.dwMajorVersion < 5)) {
chMB("This application requires features present in Windows 2000.");
ExitProcess(0);
}
}
//////////////////// макрос для проверки поддержки UNICODE ////////////////////
// Поскольку Windows 98 не поддерживает Unicode, выдаем сообщение об ошибке
// и завершаем процесс — если в Windows 98 запущена программа, рассчитанная
// на Unicode. Для этого создается глобальный C++ объект. Его конструктор
// выполняется до WinMain.
#ifdef UNICODE
class CUnicodeSupported {
public:
CUnicodeSupported() {
if (GetWindowsDirectoryW(NULL, 0) <= 0) {
chMB("This application requires an OS that supports Unicode.");
ExitProcess(0);
}
}
};
// так как объект объявлен статическим, компоновщик не жалуется на наличие
// нескольких экземпляров объекта в тех случаях, когда в одном проекте
// содержится несколько файлов исходного кода static CUnicodeSupported g_UnicodeSupported;
#endif
//////////////////////// используем подсистему Windows ////////////////////////
#pragma comment(linker, "/subsystem:Windows")
///////////////////////////////// Конец файла /////////////////////////////////

709
П Р ИЛ ОЖЕ НИ Е Б
Распаковщики сообщений,
макросы для дочерних элементов управления и API-макросы
Н
а конференциях я часто спрашиваю Применяете ли Вы распаковщики сообщений и обычно получаю один ответ — нет. Оказывается, многие даже не знают,
что это такое. Используя в программах примерах язык C/C++ совместно с распаков щиками сообщений, я стремился показать всем эти малоизвестные, но очень полезные макросы.
Распаковщики содержатся в файле WindowsX.h, поставляемом с Microsoft Visual Этот файл обычно включается сразу после Windows.h, ион нечто иное, как набор директив
#define, определяющих макросы трех групп распаковщики сообщений (mes sage crackers), макросы для дочерних элементов управления (child control macros) и макросы (API macros). Эти макросы дают разработчикам ряд дополнительных возможностей.
í
Сокращают число явных преобразований типов в коде программы, а также возникающих при этом ошибок. Большой объем таких преобразований — одна из насущных проблем в программировании для Windows на C/C++. Редко когда вызов Windows функции не требует преобразования типов. В тоже время явных преобразований типов следует избегать — они препятствуют выявлению возможных ошибок при компиляции. Явно преобразуя типы, Выговорите компилятору Здесь передается неправильный тип, но это нормально. Мне лучше знать, что надо, а что не надо Однако при большом количестве таких преобразований ошибиться очень легко. А потому позвольте компилятору максимально помочь Вам в выявлении ошибок.
í
Делают код более читабельным.
í
Упрощают перенос программ между 16 , 32 и 64 разрядными версиями
Windows.
í
Они просты и понятны — в конце концов это всего лишь макросы.
í
Их легко включить в уже написанную программу и использовать для написания нового кода, расширяющего ее функциональность. Переделка существующего кода не потребуется.
í
Их можно применять в коде, написанном как на C, таки на C++, хотя в них нет нужды при работе с библиотекой классов Если Вам понадобится что то, чего макросы дать не могут, Вы сами напишете то, что нужно, следуя модели, используемой в заголовочном файле.

710
Windows для профессионалов
í
Работая с этими макросами, Вам не придется обращаться к справочной информации или запоминать туманные конструкции Windows. Например, многие функции в Windows принимают параметр типа LONG, в младшем слове которого содержится одна величина, а в старшем — совсем другая. Перед вызовом функции из двух этих значений надо собрать одно (типа LONG). Обычно это делается с помощью макроса MAKELONG, определенного в файле Сколько разя ошибался при его использовании — не сосчитать, а ведь в результате функция получала неверный параметр. И здесь тоже помогут макросы из WindowsX.h.
Макросы — распаковщики сообщений
Распаковщики сообщений упрощают написание оконных процедур. Последние обычно представляют собой один огромный оператор
switch. Мне случалось видеть в оконных процедурах операторы
switch, содержавшие свыше 500 строк кода. Все мы знаем,
что это образец плохого стиля, но. продолжаем писать именно так. Я и сам этим грешу. А распаковщики заставляют разбивать оператор
switch на небольшие функции по одной на оконное сообщение. Это значительно улучшает внутреннюю структуру кода.
Другая проблема с оконными процедурами в том, что у каждого сообщения есть параметры
wParam и lParam, смысл которых зависит от типа сообщения. Бывает, что в сообщении WM_COMMAND параметр
wParam содержит два разных значения. Старшее его слово — код уведомления, младшее — идентификатор элемента управления.
Или наоборот Вечно я это путаю. Но если Вы используете распаковщики, Вам не придется запоминать эту информацию или искать ее в справочниках. Такие макросы названы распаковщиками потому, что они распаковывают параметры заданного сообщения. Чтобы обработать WM_COMMAND, Вы просто пишете функцию, которая выглядит примерно так Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {
switch (id) {
case ID_SOMELISTBOX:
if (codeNotify != LBN_SELCHANGE)
break;
// обрабатываем LBN_SELCHANGE
break;
case Смотрите, как просто Распаковщики берут параметры
wParam и lParam, расщепляют их на отдельные компоненты и вызывают Вашу функцию.
Чтобы использовать распаковщики, нужно внести кое какие изменения в оператор
оконной процедуры:

711
ПРИЛОЖЕНИЕ Б
Распаковщики сообщений, макросы для дочерних элементов управления и макросы WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand);
HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint);
HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
default:
return(DefWindowProc(hwnd, uMsg, wParam, В файле WindowsX.h макрос HANDLE_MSG определен так HANDLE_MSG(hwnd, message, fn) \
case (message): \
return HANDLE_##message((hwnd), (wParam), (lParam), (Для сообщения WM_COMMAND эта строка после обработки препроцессором выглядит как (WM_COMMAND):
return HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (Макросы HANDLE_WM_
* определены тоже в WindowsX.h. Это и есть настоящие распаковщики сообщений. Они распаковывают содержимое параметров
wParam и
lParam, выполняют нужные преобразования типов и вызывают соответствующую функцию — обработчик сообщения (вроде показанной ранее функции
Cls_OnCom
mand). Вот макрос HANDLE_WM_COMMAND:
#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn) \
((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), \
(UINT)HIWORD(wParam)), Результат раскрытия препроцессором этого макроса — вызов функции
Cls_OnCom
mand, которой передаются (после соответствующих преобразований типов) распакованные части параметров
wParam и lParam.
Чтобы использовать распаковщик для обработки сообщения, откройте файл Win dowsX.h и найдите сообщение, которое Вы собираетесь обрабатывать. Например, если
Вас интересует сообщение WM_COMMAND, ищите фрагмент файла, содержащий строки void Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify); */
#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn) \
((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), \
(UINT)HIWORD(wParam)), 0L)
#define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \
(void)(fn)((hwnd), WM_COMMAND, \
MAKEWPARAM((UINT)(id), (UINT)(codeNotify)), Первая строка — комментарий, показывающий прототип функции, которую Вы должны написать. Следующая строка — уже рассмотренный нами макроса последняя содержит предописатель сообщения (message forwarder). Допустим, при обработке сообщения WM_COMMAND Вы хотите вызвать оконную процедуру, используемую по умолчанию. Это выглядело бы так.

712
Windows для профессионалов
void Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {
// выполняем обычную обработку обработка по умолчанию, id, hwndCtl, codeNotify, Макросы FORWARD_WM_
* принимают распакованные параметры сообщения и воссоздают их эквиваленты
wParam и lParam, после чего вызывают указанную Вами функцию. В приведенном примере это
DefWindowProc, но также легко можно использовать или PostMessage. Фактически, чтобы отправить (синхронно или асинхронно) сообщение какому то окну в системе, можно применить макрос FOR
WARD_WM_
* — это поможет скомбинировать отдельные параметры сообщения.
Макросы для дочерних элементов управления
Эти макросы упрощают посылку сообщений дочерним элементам управления. Они очень похожи на макросы FORWARD_WM_
*. Имя каждого из них начинается с типа управляющего элемента, которому передается сообщение, затем идут знак подчеркивания и имя сообщения. Например, чтобы послать сообщение LB_GETCOUNT окну списка, задействуйте такой макрос из файла WindowsX.h:
#define ListBox_GetCount(hwndCtl) \
((int)(DWORD)SendMessage((hwndCtl), LB_GETCOUNT, 0, Позвольте сделать несколько замечаний поэтому макросу. Во первых, у него только один параметр (
hwndCtl) — описатель окна списка. Так как сообщение LB_GET
COUNT игнорирует параметры
wParam и lParam, Вам вообще нет нужды беспокоиться о них. Макрос, как Вы уже видели, автоматически передаст нули. Во вторых, тип значения, возвращаемого
SendMessage, преобразуется в int, в связи с чем ненужно самому преобразовывать тип.
Что мне не нравится в этих макросах, так это необходимость передавать им описатель окна элемента управления. Чаще всего элементы управления, которым Вы посылаете сообщения, являются дочерними окнами диалогового окна. Из за этого придется все время вызывать
GetDlgItem примерно так n = ListBox_GetCount(GetDlgItem(hDlg, Этот код выполняется ничуть не медленнее, чем код с использованием
SendDlgItem
Message, но объем программы увеличивается из за дополнительных вызовов GetDlg
Item. Если надо послать несколько сообщений одному и тому же элементу управления, Вы, возможно, захотите обратиться к
GetDlgItem лишь раз, сохранить описатель дочернего окна, а затем вызвать все необходимые макросы hwndCtl = GetDlgItem(hDlg, ID_LISTBOX);
int n = ListBox_GetCount(hwndCtl);
ListBox_AddString(hwndCtl, "Another Если Выпишете код именно так, приложение заработает быстрее, поскольку не будет повторных вызовов
GetDlgItem. Эта функция вообще то выполняется довольно медленно, если в диалоговом окне много элементов управления, а искомый элемент находится где тов конце Z цепочки.

713
ПРИЛОЖЕНИЕ Б
Распаковщики сообщений, макросы для дочерних элементов управления и API-макросы
API-макросы
Они упрощают выполнение некоторых распространенных операций — например,
создание нового шрифта, выбор его в контекст устройства и сохранение описателя исходного шрифта. Необходимый для этого код выглядит как то вроде hfontOrig = (HFONT) SelectObject(hdc, (HGDIOBJ) Этот оператор требует два преобразования типов, чтобы избежать предупреждений при компиляции. Как раз для этого и предназначен один из макросов, определенных в файле WindowsX.h:
#define SelectFont(hdc, hfont) \
((HFONT) SelectObject((hdc), (HGDIOBJ) (HFONT) (При его использовании строка кода в программе станет такой hfontOrig = SelectFont(hdc, Этот код читать гораздо легче, ион меньше подвержен ошибкам.
В файле WindowsX.h есть еще несколько API макросов, помогающих в реализации распространенных операций. Ознакомьтесь сними самостоятельно и почаще их используйте Предметный указатель
A
Address Windowing Extensions
387–391
D
DLL
476–526
— адресное пространство процесса внедрение в чужое адресное пространство известные отложенная загрузка перенаправление
518–5191
— поиск системой проецирование связывание — неявное — явное создание — для использования со средствами разработки, отличными от Visual C++
485–486
— функция входа/выхода;
см. функция, DllMain
— экспорт функций по порядковым номерам явная выгрузка
494–496
E
EXE модуль запуск проецирование связывание создание
486–479
P
Performance Data Helper
83
Performance Monitor
111, 339
T
Terminal Server
42
U
Unicode
11–27
— COM
15
— Windows 2000 13
— Windows 98 13–14
— Windows CE
14
— библиотека C
15–16
— типы данных в Windows
17–18
V
VDM
70
А
адрес
— базовый, 410
— — модификация — предпочтительный — файла, проецируемого в память виртуальный — относительный — трансляция на физический
322
архитектура
— NUMA
182–183
— памяти
314–341
Б
библиотека
— C/C++
142–151
— — глобальные переменные, доступные программам многопоточная версия ImgWalk.dll
578–561
блок

catch 642

except 602

finally 595

try 642
— переменных окружения — потока — процесса
320
блокировка, взаимная
206
В
ввод вывод, асинхронный (на устрой ствах)
240–241
волокно
303–312
выравнивание данных
337–341
Г
«голодание»
167

715
Предметный указатель
Д
директива

#pragma comment 417, 487, 517

#pragma data_seg 415–416
доступ, атомарный
187–192
З
задание
98–129
— завершение всех процессов ограничения
101–107
захват мыши
677
защита
— дескрипторы копирование при записи страниц
324–325
И
идентификатор
— _MT
150
— _WIN32_WINNT
699
— CONTEXT_FULL
165–166
— EXCEPTION_ACCESS_VIOLATION
613
— EXCEPTION_ARRAY_BOUNDS_
EXCEEDED
613
— EXCEPTION_BREAKPOINT
614
— EXCEPTION_CONTINUE_EXECUTION
602,
609–610
— EXCEPTION_CONTINUE_SEARCH
602,
611–612
— EXCEPTION_DATATYPE_MISALIGNMENT
613
— EXCEPTION_EXECUTE_HANDLER
602–608
— EXCEPTION_FLT_DENORMAL_OPERAND
614
— EXCEPTION_FLT_DIVIDE_BY_ZERO
614
— EXCEPTION_FLT_INEXACT_RESULT
614
— EXCEPTION_FLT_INVALID_OPERATION
614
— EXCEPTION_FLT_OVERFLOW
614
— EXCEPTION_FLT_STACK_CHECK
614
— EXCEPTION_FLT_UNDERFLOW
614
— EXCEPTION_GUARD_PAGE
613
— EXCEPTION_ILLEGAL_INSTRUCTION
613
— EXCEPTION_IN_PAGE_ERROR
613
— EXCEPTION_INT_DIVIDE_BY_ZERO
614
— EXCEPTION_INT_OVERFLOW
614
— EXCEPTION_INVALID_DISPOSITION
613
— EXCEPTION_INVALID_HANDLE
614
— EXCEPTION_NONCONTINUABLE_EXCEP
TION
613
— EXCEPTION_PRIV_INSTRUCTION
613
— EXCEPTION_SINGLE_STEP
614
— EXCEPTION_STACK_OVERFLOW
613
— HWND_BROADCAST
654
— MAXIMUM_PROCESSORS
185
— MAXIMUM_SUSPEND_COUNT
157
— MAXIMUM_WAIT_OBJECTS
210
— STATUS_ACCESS_VIOLATION
467
— STATUS_NO_MEMORY
467
— STILL_ACTIVE
80
— TLS_MINIMUM_AVAILABLE
528
— класса приоритета локализации относительного приоритета потока
173
исключение
599
— C++
642–644
— EXCEPTION_STACK_OVERFLOW
400
— аппаратное необработанное обработка — системой — структурная (SEH)
583–646
— обработчик завершения отключение вывода сообщений отладчик программное структурное в C++
644–646
— фильтры и обработчики формат кодов
616
К
каталог, текущий
60–61
класс
— CAddrWindow
391
— CAddrWindowStorage
391
— CAPIHook
588–589
— CGuard
257
— CInterlockedScalar
259
— CInterlockedType
258
— CJob
115
— CMMFSparse
452
— COptex
246–247
— CQueue
232–234
— CResGuard
257–258
— CSE
645
— CSomeClass
469–470
— CSparseStream
452
— CStopwatch
162
— CSWMRG
269
— CSystemInfo
391
— CVMArray
634–635
— ключ /3GB
317
— /ABOVENORMAL
172
— /BELOWNORMAL
172
— /Delay:unload
509
— /DelayLoad
507
— /DLL
477
— /FIXED
410, 522

716
Windows для профессионалов
— /Gf
66
— /GF
66
— /HEAP
462
— /HIGH
172
— /LARGEADDRESSAWARE
317–318
— /Lib:DelayImp.lib
507
— /NORMAL
172
— /REALTIME
172
— /SECTION
417
— /STACK
135, 398
— /SUBSYSTEM:CONSOLE
50–51
— /SUBSYSTEM:CONSOLE, 5.0 522
— /SUBSYSTEM:WINDOWS
50–51
— /SUBSYSTEM:WINDOWS, 5.0 522
— ключевое слово

__except 599

__finally 585

__leave 594

__try 585
код подсистемы
616
куча
461–473
— выделение блока памяти дополнительная — создание изменение размера блока использование в программах на C++
469–471
— определение размера блока освобождение блока стандартная уничтожение
468–469
кэш линия
193–194
М
макрос
— _TEXT
17
— API
713
— CACHE_ALIGN
194
— chASSERT
702
— chBEGINTHREADEX
144, 700–701
— chDIMOF
700
— chHANDLE_DLGMSG
702
— chINRANGE
700
— chMB
702
— chSETDLGICONS
703
— chVERIFY
702
— Pragma Message
700
— UNALIGNED
341
— VER_SET_CONDITION
63–64
— для дочерних элементов управления распаковщик сообщений
710–712
модель аппаратного ввода
672
модификатор

__declspec(dllexport) 483

__declspec(dllimport) 483, 487

__declspec(thread) 532

__unaligned 340

allocate 416

extern 483

volatile 196
О
обработка ошибок режимы
59–60
объект
— дублирование описателей критическая секция — обработка ошибок — спин блокировка, 202
— наследование описателя — пример оптекс
245–256
— проверка на принадлежность ядру таймер (объект ядра закрытие защита именование мьютекс
229–231
— — и критические секции — отказ ожидаемый таймер — APC очередь побочные эффекты успешного ожидания проекция файла — закрытие — создание семафор — инверсный синхронизирующий событие совместное использование несколькими процессами создание состояние таблица описателей — флаги учет пользователей файл — закрытие — создание или открытие
422–423
окно, адресное
387
оператор

delete 469, 471

new 469, 471
— запятая
617
описатель
29

717
Предметный указатель
— преобразование из псевдоописателя
152–154
— экземпляра процесса, 54
— — предыдущего
54
определение версии системы
61–64
отладка по запросу
625–626
очередь
— аппаратного ввода, системная (SHIQ)
671
— виртуального ввода (VIQ)
671
— сообщений потока
649
П
память
— гранулярность выделения динамически распределяемая
см. куча физическая — возврат, 373–374
— — передача, 370
— — сброс содержимого
383–384
переменная окружения
56–59
перехват API вызовов
563–567
позиция, кодовая
12–13
поток
130–154
— завершение контекст локальная память (TLS)
527–532
— — динамическая — статическая необработанного ввода (RIT)
671–673
— определение периодов выполнения первичный переключение планирование привязка к процессорам — жесткая — нежесткая
182
— приостановка и возобновление пул — компоненты поддержки распределение процессорного времени синхронизация — в пользовательском режиме — в сценарии один писатель/группа читателей полезные средства — с использованием объектов ядра создание и инициализация стек — особенности в Windows 98 приложение многопоточное
132
— типы
49–50
приоритет
167–171
— абстрагирование динамическое изменение классы, 168–170
— относительный, 174
— программирование уровень, программа пример AppInst
417–420
— AWE
391–397
— CopyData
666–669
— Counter
306–312
— DelayLoadApp
510–516
— ErrorShow
7–10
— FileRev
431–437
— Handshake
216–221
— InjLib
553–558
— InterlockedType
260–267
— JobLab
114–129
— LastMsgBoxInfo
567–581
— LISLab
680–692
— LISWatch
692–697
— MemReset
384–386
— MMFShare
444–448
— MMFSparse
450–460
— Optex
247–256
— ProcessInfo
83–97
— Queue
232–239
— SchedLab
176–182
— SEHTerm
596–698
— Spreadsheet
633–642
— Summation
404–408
— SWMRG
269–275
— SysInfo
343–347
— TimedMsgBox
296–298
— VMAlloc
375–382
— VMMap
360–367
— VMStat
348–351
— процесс адресное пространство — особенности в Windows 98 333
— — отключение файла данных — разделы — регионы — увеличение пользовательского раздела до Гб (в 32 разрядной Windows 2000)
317
— — уменьшение пользовательского раздела до Гб (в 64 разрядной Windows 2000)
318
— активный — подстройка планировщика включение в задание дочерний — обособленный завершение карта адресного пространства

718
Windows для профессионалов
— — в Windows 2000 327–333
— — в Windows 98 333–337
— командная строка перечисление приостановка и возобновление совместный доступ к данным через проецирование преобразование в настоящий описатель
152–154
Р
раздел
— в EXE и DLL файлах импорта, 564
— — отложенного переадресации
521
раскрутка
— глобальная, 605–609
— — остановка локальная
587
регион
— блоки освобождение передача физической памяти, 370
— резервирование, 368–370
— — с одновременной передачей физической памяти типы
328
С
сообщение
— LB_GETTEXT
539–540
— LVM_GETITEM
539
— LVM_GETITEMPOSITION
539
— WM_COPYDATA
665–666
— WM_GETTEXT
664
— WM_KILLFOCUS
674
— WM_SETFOCUS
674
— WM_SETTEXT
664
— WM_SETTINGCHANGE
57
— алгоритм выборки из очереди потока оконное передача данных
664–666
состояние ввода, локальное
673–675
страница
319
— атрибуты защиты — изменение номер фрейма
388
— ошибка
322
структура
— CONTEXT
141, 162–167
— COPYDATASTRUCT
665–666
— CRITICAL_SECTION
198–200
— DelayLoadInfo
508
— DelayLoadProc
508
— ELEMENT
233
— EXCEPTION_POINTERS
616
— EXCEPTION_RECORD
618–619
— FILETIME
222–223
— IO_COUNTERS
110
— JOB_OBJECT_BASIC_LIMIT_INFOR
MATION
101–102
— JOBOBJECT_BASIC_ACCOUNTING_INFOR
MATION
109
— JOBOBJECT_BASIC_AND_IO_ACCOUN
TING_INFORMATION
109
— JOBOBJECT_BASIC_LIMIT_INFORMA
TION
103
— JOBOBJECT_BASIC_PROCESS_ID_LIST
110
— JOBOBJECT_BASIC_UI_RESTRICTIONS
105
— JOBOBJECT_EXTENDED_LIMIT_INFORMA
TION
104
— JOBOBJECT_SECURITY_LIMIT_INFORMA
TION
106–107
— LARGE_INTEGER
222–223
— LV_ITEM
539
— MEMORY_BASIC_INFORMATION
352
— MEMORYSTATUS
348
— OSVERSIONINFOEX
62–64
— OVERLAPPED
301
— PROCESS_ HEAP_ENTRY
473
— PROCESS_INFORMATION
75–76
— SECURITY_ATTRIBUTES
29–30, 67
— SHAREDINFO
247
— STARTUPINFO
71–75
— SYSTEM_INFO
342–343
— SYSTEMTIME
222
— THREADINFO
649, 651
— tiddata
146–147
— VMQUERY
353–354
У
уведомление
— DLL_PROCESS_ATTACH
498–499
— DLL_PROCESS_DETACH
499–501
— DLL_THREAD_ATTACH
501–502
— DLL_THREAD_DETACH
502
— задания
112–113
утилита
— AXPAlign
338–339
— Bind
524–525
— DIPS
539–539
— DumpBin
413, 516
— Error Lookup
5

719
Предметный указатель
— ImageCfg
185
— Microsoft Spy++
105–106
— Rebase
523
Ф
файл
— APIHook.cpp
568
— APIHook.h
568
— CmnHdr.h
698–708
— DelayImp.lib
510
— Excpt.h
601
— Mtdll.h
146
— PDH.dll
83
— String.h
15–16
— TChar.h
16
— Threadex.c
147–148
— WinError.h
3–4, 616
— WinNT.h
157
— WinUser.h
653
— данных (проецируемый в память проецируемый — когерентность — на физическую память из страничного файла — особенности на разных платформах применение — с частичной передачей физической памяти разреженный страничный
320–324
флаг
— AC
338
— CREATE_BREAKAWAY_FROM_JOB
70
— CREATE_DEFAULT_ERROR_MODE
60, 70
— CREATE_FORCEDOS
70
— CREATE_NEW_CONSOLE
69
— CREATE_NEW_PROCESS_GROUP
70
— CREATE_NO_WINDOW
69
— CREATE_SEPARATE_WOW_VDM
70
— CREATE_SHARED_WOW_VDM
70
— CREATE_SUSPENDED
69, 107, 137, 141
— CREATE_UNICODE_ENVIRONMENT
70
— DEBUG_ONLY_THIS_PROCESS
69
— DEBUG_PROCESS
69
— DETACHED_PROCESS
69
— DONT_RESOLVE_DLL_REFERENCES
494
— DUPLICATE_CLOSE_SOURCE
43
— DUPLICATE_SAME_ACCESS
43
— EXCEPTION_NONCONTINUABLE
618, 621
— FILE_MAP_READ
30
— FORMAT_MESSAGE_ALLOCATE_BUFFER
7
— FORMAT_MESSAGE_FROM_SYSTEM
7
— FREE
528
— GENERIC_READ
423
— GENERIC_WRITE
423
— HANDLE_FLAG_INHERIT
38
— HANDLE_FLAG_PROTECT_FROM_CLOSE
38
— HEAP_GENERATE_EXCEPTIONS
465–467, 620
— HEAP_NO_SERIALIZE
465–467, 470
— HEAP_REALLOC_IN_PLACE_ONLY
468
— HEAP_ZERO_MEMORY
467
— IMAGE_FILE_RELOCS_STRIPPED
522
— INUSE
528
— ISMEX_CALLBACK
656
— ISMEX_NOTIFY
656
— ISMEX_REPLIED
656
— ISMEX_SEND
656
— JOB_OBJECT_LIMIT_ACTIVE_PROCESS
102
— JOB_OBJECT_LIMIT_AFFINITY
102–103
— JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_
EXCEPTION
104
— JOB_OBJECT_LIMIT_JOB_TIME
102–103
— JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME
103
— JOB_OBJECT_LIMIT_PRIORITY_CLASS
103
— JOB_OBJECT_LIMIT_PROCESS_TIME
102
— JOB_OBJECT_LIMIT_SCHEDULING_CLASS
103
— JOB_OBJECT_LIMIT_WORKINGSET
102
— JOB_OBJECT_UILIMIT_DESKTOP
105
— JOB_OBJECT_UILIMIT_DISPLAYSETTINGS
105
— JOB_OBJECT_UILIMIT_EXITWINDOWS
105
— JOB_OBJECT_UILIMIT_GLOBALATOMS
105
— JOB_OBJECT_UILIMIT_HANDLES
105
— JOB_OBJECT_UILIMIT_READCLIPBOARD
105
— JOB_OBJECT_UILIMIT_SYSTEMPARAME
TERS
105
— JOB_OBJECT_UILIMIT_WRITECLIPBOARD
105
— KEY_ALL_ACCESS
31
— KEY_QUERY_VALUE
30
— LOAD_LIBRARY_AS_DATAFILE
494
— LOAD_WITH_ALTERED_SEARCH_PATH
494
— MEM_COMMIT
370
— MEM_DECOMMIT
373
— MEM_PHYSICAL
388
— MEM_RELEASE
373
— MEM_RESERVE
388
— MEM_RESET
383–384
— MEM_TOP_DOWN
369
— MWMO_ALERTABLE
662
— MWMO_INPUTAVAILABLE
662–663
— MWMO_WAITALL
662
— NORM_IGNORECASE
21
— NORM_IGNOREKANATYPE
21
— NORM_IGNORENONSPACE
21
— NORM_IGNORESYMBOLS
21
— NORM_IGNOREWIDTH
21
— PAGE_GUARD
326, 398, 400
— PAGE_NOCACHE
326

720
Windows для профессионалов
— PAGE_WRITECOMBINE
326
— QS_PAINT
658
— QS_POSTMESSAGE
658
— QS_QUIT
658
— QS_SENDMESSAGE
652, 658
— QS_TIMER
658
— SEC_IMAGE
425
— SEC_NOCACHE
424
— SEM_FAILCRITICALERRORS
59
— SEM_NOALIGNMENTFAULTEXCEPT
59, 339
— SEM_NOGPFAULTERRORBOX
59
— SEM_NOOPENFILEERRORBOX
59
— SMTO_ABORTIFHUNG
653
— SMTO_BLOCK
653
— SMTO_NORMAL
653
— SMTO_NOTIMEOUTIFNOTHUNG
653
— SORT_STRINGSORT
21
— STARTF_FORCEOFFFEEDBACK
74
— STARTF_FORCEONFEEDBACK
74
— STARTF_RUN_FULLSCREEN
74
— STARTF_USECOUNTCHARS
73
— STARTF_USEFILLATTRIBUTE
73
— STARTF_USEPOSITION
73
— STARTF_USESHOWWINDOW
73
— STARTF_USESIZE
73
— STARTF_USESTDHANDLES
73
— WT_ EXECUTEINPERSISTENTTHREAD
294
— WT_EXECUTEDEFAULT
292–293
— WT_EXECUTEINIOTHREAD
292–293, 299
— WT_EXECUTEINPERSISTENTTHREAD
299
— WT_EXECUTEINTIMERTHREAD
294
— WT_EXECUTEINWAITTHREAD
299
— WT_EXECUTELONGFUNCTION
292, 294, 299
— WT_EXECUTEONLYONCE
299–300
— атрибута защиты наследования, связанный с описателем состояния очереди
657–658
функция

__delayLoadHelper 507–509

__FUnloadDelayLoadedDLL 509

_beginthread 151

_beginthreadex 144–146, 150–151

_DllMainCRTStartup 505

_endthread 151

_endthreadex 148–149, 152

_getptd 149

_threadstartex 147–148

AbnormalTermination 595

AllocateUserPhysicalPages 388–389

AllowSetForegroundWindow 676
— APC
224–225

AssignProcessToJobObject 108

AttachThreadInput 678–679

BaseProcessStart 142, 623

BaseThreadStart 141–142, 623

BindImageEx 524–525

BindIoCompletionCallback 301

BringWindowToTop 675

CallWindowProcA 670

CallWindowProcW 670

CancelWaitableTimer 224

ChangeTimerQueueTimer 295

CharLower 21–22

CharLowerBuff 22

CharNext 12

CharPrev 12

CharUpper 21

CharUpperBuff 22

ClipCursor 677

CloseHandle 33–34

CommandLineToArgvW 55

CompareString 21

ConvertThreadToFiber 304

CreateEvent 213

CreateFiber 304

CreateFile 422–423

CreateFileMapping 423–426

CreateJobObject 100

CreateMutex 40, 229

CreateProcess 64–76, 409
— — поиск заданного файла
66

CreateRemoteThread 549–551

CreateSemaphore 228

CreateThread 134–137

CreateTimerQueue 293

CreateTimerQueueTimer 293

CreateWaitableTimer 221

DebugActiveProcess 627

DebugBreak 248

DeleteCriticalSection 200

DeleteFiber 305

DeleteTimerQueueEx 295

DeleteTimerQueueTimer 294–295

DisableThreadLibraryCalls 504, 506

DllMain 497–498
— — библиотека C/C++
505–506
— — упорядочение вызовов
503–505

DuplicateHandle 43–45, 153–154

EnterCriticalSection 199–201

ExitProcess 77–79

ExitThread 138

ExpandEnvironmentStrings 58

FlushViewOfFile 429

FormatMessage 5

FreeEnvironmentStrings 71

FreeLibrary 496

FreeLibraryAndExitThread 495

FreeUserPhysicalPages 390

721
Предметный указатель

GetActiveWindow 675

GetAsyncKeyState 676

GetCommandLine 55

GetCurrentDirectory 60

GetCurrentFiber 305

GetCurrentProcess 152

GetCurrentThread 152

GetEnvironmentStrings 71

GetEnvironmentVariable 58

GetExceptionCode 612–615

GetExceptionInformation 616–617, 619

GetExitCodeProcess 80

GetExitCodeThread 140

GetFiberData 305

GetFileSize 431

GetForegroundWindow 675

GetFullPathName 61

GetHandleInformation 38

GetKeyState 676

GetLastError 2–4

GetMessage 540

GetModuleFileName 496

GetModuleHandle 54, 496

GetPriorityClass 172

GetProcAddress 496–497

GetProcessAffinityMask 183

GetProcessHeap 462

GetProcessHeaps 472

GetProcessIoCounters 110

GetProcessPriorityBoost 175

GetProcessTimes 152, 161

GetQueuedCompletionStatus 113

GetQueueStatus 657

GetStartupInfo 75

GetSystemInfo 342

GetThreadContext 165–166

GetThreadLocale 21

GetThreadPriority 173–174

GetThreadPriorityBoost 175

GetThreadTimes 152, 160–161

GetVersion 61

GetVersionEx 61–62

GetWindowThreadProcessId 650–651

GlobalMemoryStatus 347–348

GlobalMemoryStatusEx 348

HeapAlloc 466–467

HeapCompact 472

HeapCreate 465–466

HeapDestroy 468–469

HeapFree 468

HeapLock 473

HeapReAlloc 467–468

HeapSize 468

HeapUnlock 473

HeapValidate 472

HeapWalk 473

InitializeCriticalSection 200

InitializeCriticalSectionAndSpinCount 202–203

InSendMessage 656

InSendMessageEx 656

InterlockedCompareExchange 192

InterlockedCompareExchangePointer 192

InterlockedDecrement 193

InterlockedExchange 190

InterlockedExchangeAdd 189

InterlockedExchangePointer 190

InterlockedIncrement 193

IsCharAlpha 22

IsCharAlphaNumeric 22

IsCharLower 22

IsCharUpper 22

IsDBCSLeadByte 12

IsTextUnicode 23–24

IsWindowUnicode 669

LeaveCriticalSection 199, 202

LoadIcon 53

LoadLibrary 410, 492, 495, 519, 550

LoadLibraryEx 492–495, 519

LockSetForegroundWindow 676

MapUserPhysicalPages 389

MapViewOfFile 426–429, 441–442

MapViewOfFileEx 439–440

MoveMemory 430

MsgWaitForMultipleObjects 242, 661–662

MsgWaitForMultipleObjectsEx 242, 661–663

MultiByteToWideChar 24–25

OpenEvent 214

OpenJobObject 100

OpenMutex 230

OpenProcess 553

OpenSemaphore 228

OpenThread 158

OpenWaitableTimer 221

OverlappedCompletionRoutine 301

PostMessage 619

PostQuitMessage 651

PostThreadMessage 540, 650–651

PulseEvent 216

QueryInformationJobObject 107

QueryPerformanceCounter 162

QueryPerformanceFrequency 162

QueueUserWorkItem 290

RaiseException 621

ReadProcessMemory 552

ReBaseImage 523

RegisterWaitForSingleObject 298–299

RegOpenKeyEx 30–31

ReleaseMutex 230

722
Windows для профессионалов

ReleaseSemaphore 228–229

ReplaceIATEntryInOneMod 564–566

ReplyMessage 655

ResetEvent 214

ResultCallBack 654

ResumeThread 157

RobustHowManyToken 604–605

RobustMemDup 605

RobustStrCpy 603

SendMessage 651–652, 664–665

SendMessageCallback 654

SendMessageTimeout 653

SendNotifyMessage 655

SetActiveWindow 674

SetCriticalSectionSpinCount 203

SetCurrentDirectory 60

SetEndOfFile 432–433

SetEnvironmentVariable 59

SetErrorMode 59, 339

SetEvent 214

SetFilePointer 432

SetForegroundWindow 675–676

SetHandleInformation 37–38

SetInformationJobObject 101

SetLastError 6

SetPriorityClass 172

SetProcessAffinityMask 183

SetProcessPriorityBoost 175

SetThreadAffinityMask 183–184

SetThreadContext 166

SetThreadIdealProcessor 185

SetThreadPriority 173

SetThreadPriorityBoost 175

SetUnhandledExceptionFilter 627–629

SetWaitableTimer 221, 223–224

SetWindowLongPtr 534–535

SetWindowLongPtrA 619

SetWindowLongPtrW 670

SetWindowPos 675

SetWindowsHookEx 537

SignalObjectAndWait 242–244

Sleep 159

StackCheck 403–404

StartRestrictedProcess 98–100

StatusRoutine 525

StringReverse 26–27

strlen 12

SuspendProcess 157–158

SuspendThread 157

SwitchToFiber 304–305

SwitchToThread 159–160

TerminateJobObject 108

TerminateProcess 79

TerminateThread 138–139

TlsAlloc 528–529

TlsFree 529

TlsGetValue 529

TlsSetValue 529
— ToolHelp (вспомогательные информационные и ANSI версии
18–19

UnmapViewOfFile 429–430

UnregisterWaitEx 300

UserHandleGrantAccess 106

VerifyVersionInfo 63–64

VirtualAlloc 368–371, 449

VirtualAllocEx 551

VirtualFree 373

VirtualFreeEx 552

VirtualProtect 382–383

VirtualQuery 351–352

VirtualQueryEx 351–352

VMQuery 353–359

WaitForDebugEvent 242

WaitForInputIdle 241

WaitForMultipleExpressions 275–280

WaitForMultipleObjects 210–211

WaitForSingleObject 81, 209–210

WaitOrTimerCallback 293

WaitOrTimerCallbackFunc 299

WideCharToMultiByte 25

WorkItemFunc 291

WriteProcessMemory 318, 552

ZeroMemory 385
— волокна входная запись о переадресации вызова значение, свидетельствующее об ошибке переадресованная потока семейства —
Interlocked 187–193
— —
printf 22
— стартовая (из библиотеки C/C++)
50–53

Об авторе
Джеффри Рихтер ведет семинары по программированию (
http://
www.SolSem.com) и консультирует разработчиков программного обеспечения по различным вопросам. В число его клиентов входят такие компании, как Bradley, AT&T, Caterpillar,
Digital, DreamWorks,
GE Medical Systems, Hewlett
Packard, IBM, Intel, Intuit,
Microsoft, Pitney Bowes, Sybase,
Tandem и Unisys.
Джефф регулярно выступает на отраслевых конференциях, в том числе на Software
Development, COMDEX,
WinDev (при Бостонском
Университете), Microsoft
Professional Developer’s
Conference и Tech Ed. Кроме того, Джефф — один из пишущих редакторов журнала
Microsoft
Systems Journal, в котором ведет колонку Вопросы и ответы пои публикует свои статьи.
Сейчас Джефф живет в Белльвю (штат Вашингтон. Его хобби полеты на вертолете, фокусы и играна барабанах. Ему очень нравятся телесериал
The
Simpsons, классический рок и джаз в стиле «фьюжн».

ЛИЦЕНЗИОННОЕ СОГЛАШЕНИЕ MICROSOFT
(прилагаемый к книге компакт диск)
ЭТО ВАЖНО — ПРОЧИТАЙТЕ ВНИМАТЕЛЬНО. Настоящее лицензионное соглашение (далее «Со
глашение») является юридическим документом, оно заключается между Вами (физическим или юриди
ческим лицом) и Microsoft Corporation (далее корпорация Microsoft») на указанный выше продукт
Microsoft, который включает программное обеспечение и может включать сопутствующие мультимедий
ные и печатные материалы, а также электронную документацию (далее Программный Продукт. Лю
бой компонент, входящий в Программный Продукт, который сопровождается отдельным Соглашением,
подпадает под действие именно того Соглашения, а не условий, изложенных ниже. Установка, копирова
ние или иное использование данного Программного Продукта означает принятие Вами данного Соглаше
ния. Если Вы не принимаете его условия, тоне имеете права устанавливать, копировать или как то иначе
использовать этот Программный Продукт.
ЛИЦЕНЗИЯ НА ПРОГРАММНЫЙ ПРОДУКТ
Программный Продукт защищен законами Соединенных Штатов по авторскому праву и международными договорами по авторскому праву, а также другими законами и договорами по правам на интеллектуальную собственность.
1. ОБЪЕМ ЛИЦЕНЗИИ. Настоящее Соглашение дает Вам право) Программный продукт. Вы можете установить и использовать одну копию Программного Продукта на одном компьютере. Основной пользователь компьютера, на котором установлен данный Программный
Продукт, может сделать только для себя вторую копию и использовать ее на портативном компьютере) Хранение или использование в сети. Вы можете также скопировать или установить экземпляр Программного Продукта на устройстве хранения, например на сетевом сервере, исключительно для установки или запуска данного Программного Продукта на других компьютерах в своей внутренней сети, но тогда Вы должны приобрести лицензии на каждый такой компьютер. Лицензию на данный Программный продукт нельзя использовать совместно или одновременно на других компьютерах) License Pak. Если Выкупили эту лицензию в составе Microsoft License Pak, можете сделать ряд дополнительных копий программного обеспечения, входящего в данный Программный Продукт, и использовать каждую копию так, как было описано выше. Кроме того, Вы получаете право сделать соответствующее число вторичных копий для портативного компьютера в целях, также оговоренных выше) Примеры кода. Это относится исключительно к отдельным частям Программного Продукта, заявленным как примеры кода (далее Примеры, если таковые входят в состав Программного Продукта) Использование и модификация. Microsoft дает Вам право использовать и модифицировать исходный код Примеров при условии соблюдения пункта (d)(iii) ниже. Вы не имеете права распространять в виде исходного кода ни Примеры, ни их модифицированную версию) Распространяемые файлы. При соблюдении пункта (d)(iii) Microsoft дает Вам право на свободное от отчислений копирование и распространение в виде объектного кода Примеров или их модифицированной версии, кроме тех частей (или их модифицированных версий, которые оговорены в файле, относящемся к данному Программному Продукту, как не подлежащие распространению) Требования к распространению файлов. Вы можете распространять файлы, разрешенные к распространению, при условии, что а) распространяете их в виде объектного кода только в сочетании со своим приложением и как его часть б) не используете название, эмблему или товарные знаки для продвижения своего приложения в) включаете имеющуюся в Программном Продукте ссылку на авторские права в состав этикетки и заставки своего приложения г) согласны освободить от ответственности и взять на себя защиту корпорации Microsoft от любых претензий или преследований по закону, включая судебные издержки, если таковые возникнут в результате использования или распространения Вашего приложения и дне допускаете дальнейшего распространения конечным пользователем своего приложения. По поводу отчислений и других условий лицензии применительно к иным видам использования или распространения распространяемых файлов обращайтесь в
Microsoft.

2. ПРОЧИЕ ПРАВА И ОГРАНИЧЕНИЯ
ț Ограничения на реконструкцию, декомпиляцию и дизассемблирование. Вы не имеете права реконструировать, декомпилировать или дизассемблировать данный Программный Продукт, кроме того случая, когда такая деятельность (только в той мере, которая необходима) явно разрешается соответствующим законом, несмотря на это ограничение Разделение компонентов. Данный Программный Продукт лицензируется как единый продукт. Его компоненты нельзя отделять друг от друга для использования более чем на одном компьютере Аренда. Данный Программный Продукт нельзя сдавать в прокат, передавать во временное пользование или уступать для использования в иных целях Услуги по технической поддержке. Microsoft может (ноне обязана) предоставить Вам услуги потех нической поддержке данного Программного Продукта (далее Услуги. Предоставление Услуг регулируется соответствующими правилами и программами Microsoft, описанными в руководстве пользователя, электронной документации и/или других материалах, публикуемых Microsoft. Любой дополнительный программный код, предоставленный в рамках Услуг, следует считать частью данного Программного
Продукта и подпадающим под действие настоящего Соглашения. Что касается технической информации, предоставляемой Вами корпорации Microsoft при использовании ее Услуг, то Microsoft может задействовать эту информацию в деловых целях, в том числе для технической поддержки продукта и разработки. Используя такую техническую информацию, Microsoft не будет ссылаться на Вас Передача прав на программное обеспечение. Вы можете безвозвратно уступить все права, регулируемые настоящим Соглашением, при условии, что не оставите себе никаких копий, передадите все составные части данного Программного Продукта (включая компоненты, мультимедийные и печатные материалы, любые обновления, Соглашение и сертификат подлинности, если таковой имеется) и принимающая сторона согласится с условиями настоящего Соглашения Прекращение действия Соглашения. Без ущерба для любых других прав Microsoft может прекратить действие настоящего Соглашения, если Вы нарушите его условия. В этом случае Вы должны будете уничтожить все копии данного Программного Продукта вместе со всеми его компонентами.
3. АВТОРСКОЕ ПРАВО. Все авторские права и право собственности на Программный Продукт (в том числе любые изображения, фотографии, анимации, видео, аудио, музыку, текст, примеры кода, распространяемые файлы и апплеты, включенные в состав Программного Продукта) и любые его копии принадлежат корпорации Microsoft или ее поставщикам. Программный Продукт охраняется законодательством об авторских правах и положениями международных договоров. Таким образом, Вы должны обращаться сданным Программным Продуктом, как с любым другим материалом, охраняемым авторскими правами, с тем исключением, что Вы можете установить Программный Продукт на один компьютер при условии, что храните оригинал исключительно как резервную или архивную копию. Копирование печатных материалов, поставляемых вместе с Программным Продуктом, запрещается.
ОГРАНИЧЕНИЕ ГАРАНТИИ
ДАННЫЙ ПРОГРАММНЫЙ ПРОДУКТ (ВКЛЮЧАЯ ИНСТРУКЦИИ ПО ЕГО ИСПОЛЬЗОВАНИЮ) ПРЕДОСТАВЛЯЕТСЯ БЕЗ КАКОЙ ЛИБО
ГАРАНТИИ. КОРПОРАЦИЯ MICROSOFT СНИМАЕТ С СЕБЯ ЛЮБУЮ ВОЗМОЖНУЮ ОТВЕТСТВЕННОСТЬ, В ТОМ ЧИСЛЕ ОТВЕТСТВЕННОСТЬ ЗА КОММЕРЧЕСКУЮ ЦЕННОСТЬ ИЛИ СООТВЕТСТВИЕ ОПРЕДЕЛЕННЫМ ЦЕЛЯМ. ВЕСЬ РИСК ПО ИСПОЛЬЗОВАНИЮ ИЛИ
РАБОТЕ С ПРОГРАММНЫМ ПРОДУКТОМ ЛОЖИТСЯ НА ВАС.
НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ КОРПОРАЦИЯ MICROSOFT, ЕЕ РАЗРАБОТЧИКИ, А ТАКЖЕ ВСЕ, ЗАНЯТЫЕ В СОЗДАНИИ, ПРОИЗВОДСТВЕ И РАСПРОСТРАНЕНИИ ДАННОГО ПРОГРАММНОГО ПРОДУКТА, НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ЗА КАКОЙ ЛИБО
УЩЕРБ (ВКЛЮЧАЯ ВСЕ, БЕЗ ИСКЛЮЧЕНИЯ, СЛУЧАИ УПУЩЕННОЙ ВЫГОДЫ, НАРУШЕНИЯ ХОЗЯЙСТВЕННОЙ ДЕЯТЕЛЬНОСТИ,
ПОТЕРИ ИНФОРМАЦИИ ИЛИ ДРУГИХ УБЫТКОВ) ВСЛЕДСТВИЕ ИСПОЛЬЗОВАНИЯ ИЛИ НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ
ДАННОГО ПРОГРАММНОГО ПРОДУКТА ИЛИ ДОКУМЕНТАЦИИ, ДАЖЕ ЕСЛИ КОРПОРАЦИЯ MICROSOFT БЫЛА ИЗВЕЩЕНА О ВОЗМОЖНОСТИ ТАКИХ ПОТЕРЬ, ТАК КАК В НЕКОТОРЫХ СТРАНАХ НЕ РАЗРЕШЕНО ИСКЛЮЧЕНИЕ ИЛИ ОГРАНИЧЕНИЕ ОТВЕТСТВЕННОСТИ ЗА НЕПРЕДНАМЕРЕННЫЙ УЩЕРБ, УКАЗАННОЕ ОГРАНИЧЕНИЕ МОЖЕТ ВАС НЕ КОСНУТЬСЯ.
РАЗНОЕ
Настоящее Соглашение регулируется законодательством штата Вашингтон (США, кроме случаев (и лишь в той мере, насколько это необходимо) исключительной юрисдикции того государства, на территории которого используется Программный Продукт.
Если у Вас возникли какие либо вопросы, касающиеся настоящего Соглашения, или если Вы желаете связаться с Microsoft по любой другой причине, пожалуйста, обращайтесь в местное представительство Microsoft или пишите по адресу Microsoft Sales Information
Center, One Microsoft Way, Redmond, WA 98052 6399.




Поделитесь с Вашими друзьями:
1   ...   60   61   62   63   64   65   66   67   68


База данных защищена авторским правом ©nethash.ru 2019
обратиться к администрации

войти | регистрация
    Главная страница


загрузить материал