Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС / Лаб_5.doc
Скачиваний:
148
Добавлен:
11.04.2015
Размер:
245.76 Кб
Скачать

Лабораторная работа № 5. Управление виртуальной памятью в Windowsприложениях вWin32api Цель работы

  1. Изучение функций управления виртуальной памятью процесса в Windows приложениях.

  2. Изучение функций механизма отображения файлов в память в Windows приложениях.

  3. Изучение функций управления динамически распределяемой памятью в Windows приложениях.

  4. Овладение навыками использования функций по управлению памятью при разработке Windows приложений.

Краткие теоретические сведения

Операционные системы, основанные на Win32, реализуют три механизма управления с памятью:

  • виртуальная память (virtual memory) – наиболее подходящая для операций с большими массивами объектов или структур;

  • файлы, проецируемые в память (memory-mapped files) – наиболее подходящие для операций с интенсивными потоками данных (обычно из файлов) и для обеспечения процессам совместного доступа к данным;

  • кучи (heaps) – наиболее подходящие для операций с большим количеством малых объектов.

Виртуальная память процесса может находиться в одном из трех состояний:

  • свободная – память, которая может быть зарезервирована или размещена;

  • зарезервированная – память в некотором диапазоне адресов, которая зарезервирована для будущего использования (защищена от последующих запросов на выделение памяти, но остается недоступной поскольку физическая память этому диапазону адресов еще не выделена);

  • размещенная – память, которая была зарезервирована и которой выделена физическая память.

Адресное пространств, выделенное процессу в момент создания, практически все свободно (не зарезервировано). Чтобы воспользоваться какой-либо его частью, нужно выделить в нем определенную область – зарезервировать регион. Регион всегда состоит из целого числа страниц и начинается с 64-килобайтной страницы (по объему может быть меньше 64 Кбайт). Для использования зарезервированного региона ему нужно выделить физическую память и спроецировать ее на этот регион. Такая операция называется передачей физической памяти (размещением). Физическая память может быть передана и не всему региону, а лишь части его страниц. Если физическая память региону больше не нужна, она может быть освобождена. Региону могут быть назначены любые допустимые атрибуты защиты.

Функции получения информации о памяти в системе.

VOID GetSystemInfo(LPSYSTEM_INFO psinf) - функции необходимо передать адрес структуры SYSTEM_INFO, и функция инициализирует элементы этой структуры:

typedef struct _SYSTEM_INFO {

union {

DWORD dwOemId; // Устарел; больше не используется

struct {

WORD wProcessorArchitecture; /* Используется только в Windows 2000; сообщает тип архитектуры процессора. */

WORD wReserved; // Зарезервирован на будущее; пока не используется

};

};

DWORD dwPageSize; // Размер страницы памяти.

LPVOID lpMinimumApplicationAddress; /* Минимальный адрес памяти доступного адресного пространства для каждого процесса. */

LPVOID lpMaximumApplicationAddress; /* Максимальный адрес памяти доступного адресного пространства, отведенного в «личное пользование» каждому процессу. */

DWORD_PTR dwActiveProcessorMask; /* Битовая маска, которая сообщает, какие процессоры активны (выполняют потоки). */

DWORD dwNumberOfProcessors; // Число процессоров в компьютере

DWORD dwProcessorType; /* Используется только в Windows 98; сообщает тип процессора. */

DWORD dwAllocationGranularity; /* Гранулярность резервирования регионов адресного пространства. */

WORD wProcessorLevel; /* Используется только в Windows 2000; сообщает дополнительные подробности об архитектуре процессора. */

WORD wProcessorRevision; /* Используется только в Windows 2000; сообщает дополнительные подробности об уровне данной архитектуры процессора. */

} SYSTEM_INFO, *LPSYSTEM_INFO;

VOID GlobalMemoryStatus (LPMEMORYSTATUS pmst) – позволяет отслеживать текущее состояние памяти; при вызове функции ей необходимо передать адрес структуры MEMORYSTATUS, и функция инициализирует элементы этой структуры:

typedef struct _MEMORYSTATUS {

DWORD dwLength;

DWORD dwMemoryLoad; /* Позволяет оценить, насколько занята подсистема управления памятью. Это число может быть любым в диапазоне от 0 до 100. */

DWORD dwTotalPhys; /* Отражает общий объем физической (оперативной) памяти в байтах. */

DWORD dwAvailPhys; /* Дает число байтов свободной физической памяти. */

DWORD dwTotalPageFile; /* Сообщает максимальное количество байтов, которое может содержаться в страничном файле (файлах) на жестком диске (дисках). */

DWORD dwAvailPageFile; /* Подсказывает, сколько в данный момент байтов в страничном файле свободно и может быть передано любому процессу. */

DWORD dwTotalVirtual; /* Отражает общее количество байтов, отведенных под закрытое адресное пространство процесса. */

DWORD dwAvailVirtual; /* Сумма размеров всех свободных регионов в адресном пространстве вызывающего процесса (специфичен для конкретного процесса). */

} MEMORYSTATUS, *LPMEMORYSTATUS;

Перед вызовом GlobalMemoryStatus надо записать в элемент dwLength размер структуры в байтах. После вызова GlobalMemoryStatus инициализирует остальные элементы структуры.

Основные функции управления виртуальной и физической памятью.

PVOID VirtualAlloc (PVOID pvAddress, DWORD dwSize, DWORD fdwAllocationType, DWORD fdwProtect) – резервирует регионы или передает зарезервированным регионам память. Возвращает базовый адрес зарезервированного региона при успешном выполнении и значение NULL, если регион требуемого размера по заданному адресу выделить не удалось.

Параметр pvAddress содержится адрес памяти, указывающий, где именно система должна зарезервировать адресное пространство. Регионы выделяются с учетом гранулярности, поэтому система округляет переданный адрес до меньшей величины кратной гранулярности. Если передано значение NULL, то адрес резервируемого региона выбирается по усмотрению системы. Чтобы зарезервировать регион в диапазоне самых старших, насколько это возможно, адресов в параметре pvAddress необходимо передать NULL, а в параметре fdwAllocationType флаг MEM_RESERVE, скомбинированный с флагом MEM_TOP_DOWN.

Параметр dwSize указывает размер резервируемого региона в байтах. Размер зарезервированного региона округляется в большую сторону до величины кратной размеру страницы в байтах.

Параметр fdwAllocationType сообщает системе, что именно необходимо сделать: зарезервировать регион или передать физическую память. Чтобы зарезервировать регион адресного пространства, в этом параметре нужно передать идентификатор MEM_RESERVE.

Параметр fdwProtect указывает атрибут защиты, присваиваемый региону. Можно использовать любой из следующих атрибутов защиты: PAGE_NOACCESS, PAGE_READWRITE, PAGE_READONLY, PAGE_EXECUTE, PAGE_EXECUTE_READ или PAGE_EXECUTE_READWRITE. Указывать атрибуты PAGE_WRITECOPY или PAGE_EXECUTE_WRITECOPY. При резервировании региона флаги PAGE_GUARD, PAGE_WRITECOMBINE или PAGE_NOCACHE применять тоже нельзя - они присваиваются только передаваемой памяти.

Для передачи физической памяти зарезервированному региону необходимо вызвать функцию VirtualAlloc еще раз, указав в параметре fdwAllocationType не MEM_RESERVE, а MEM_COMMIT. Обычно указывают тот же атрибут защиты, что и при резервировании региона, хотя можно задать и другой. Необходимо также передать функции VirtualAlloc в параметр pvAddress адрес, по которому требуется передать физическую память, и в параметр dwSize - размер передаваемой физической памяти в байтах. Передавать физическую память сразу всему региону необязательно.

Страница является минимальной единицей памяти, которой можно присвоить собственные атрибуты защиты. Следовательно, в регионе могут быть страницы с разными атрибутами защиты.

Иногда нужно одновременно зарезервировать регион и передать ему физическую память. В таком случае при вызове VirtualAlloc в параметре fdwAllocationType следует передать оба атрибута MEM_RESERVE и MEM_COMMIT.

BOOL VirtualFree (LPVOID pvAddress, DWORD dwSize, DWORD fdwFreeType) – возвращает физическую память, отображенную на регион, или освобождает весь регион адресного пространства. При успешном завершении возвращает TRUE, иначе – FALSE.

В параметр pvAddress передается базовый адрес региона, т. е. значение, возвращенное функцией VirtualAlloc после резервирования данного региона, если необходимо освободить этот регион. В параметр pvAddress передается адрес, указывающий на первую возвращаемую страницу, если необходимо, не освобождая регион, вернуть в систему часть физической памяти, переданной региону.

В параметре dwSize передается 0, если необходимо освободить регион. В параметре dwSize задается количество освобождаемых байтов, если необходимо системе возвратить все страницы памяти, попадающие в диапазон от pvAddress до pvAddress + dwSize.

В параметре fdwFreeType необходимо передать идентификатор MEM_RELEASE, если необходимо возвратить системе всю физическую память, отображенную на регион, и освободить сам регион. В параметре fdwFreeType необходимо передать идентификатор MEM_DECOMMIT, если необходим, не освобождая регион, вернуть в систему часть физической памяти, переданной региону.

BOOL VirtualProtect(PVOID pvAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD pflOldProtect) – изменяет атрибуты защиты страницы памяти. При успешном завершении возвращает TRUE, иначе – FALSE.

Параметр pvAddress указывает на базовый адрес памяти (который должен находиться в пользовательском разделе Вашего процесса).

Параметр dwSize определяет число байтов, для которых необходимо изменить атрибут защиты.

Параметр flNewProtect содержит новые атрибуты защиты. Может принимать значение одного из идентификаторов PAGE_*, кроме PAGE_WRITECOPY и PAGE_EXECUTE_WRITECOPY.

Параметр pflOldProtect содержит адрес переменной типа DWORD, в которую VirtualProtect заносит старое значение атрибута защиты для данной области памяти.

Естественно, атрибуты защиты связаны с целыми страницами памяти и не могут присваиваться отдельным байтам.

DWORD VirtualQuery (PCVOID pvAddress, PMEMORY_BASIC_INFORMATION pmbi, DWORD dwLength) - запрашивает информацию об участке памяти по заданному адресу (в пределах адресного пространства вызывающего процесса): размер, тип памяти и атрибуты защиты.

DWORD VirtualQueryEx (HANDLE hProcess, LPCVOID pvAddress, PMEMORY_BASIC_INFORMATION pmbi, DWORD dwLength) – сообщает ту же информацию о памяти, что и функция VirtualQuery, но в другом процессе (дескриптор которого передается в функцию через параметр hProcess).

При вызове VirtualQuery(Ex) параметр pvAddress должен содержать адрес виртуальной памяти, о которой необходимо получить информацию.

Параметр pmbi – это адрес структуры MEMORY_BASIC_INFORMATION, которую надо создать перед вызовом функции. Данная структура определена в файле WinNT.h так:

typedef struct _MEMORY_BASIC_INFORMATION {

PVOID BaseAddress; /* Сообщает то же значение, что и параметр pvAddress, но округленное до ближайшего меньшего адреса, кратного размеру страницы. */

PVOID AllocationBase; /* Идентифицирует базовый адрес региона, включающего в себя адрес, указанный в параметре pvAddress. */

DWORD AllocationProtect; /* Идентифицирует атрибут защиты, присвоенный региону при его резервировании. */

DWORD RegionSize; /* Сообщает суммарный размер (в байтах) группы страниц, которые начинаются с базового адреса BaseAddress и имеют те же атрибуты защиты, состояние и тип, что и страница, расположенная по адресу, указанному в параметре pvAddress. */

DWORD State; /* Сообщает состояние (MEM_FREE, MEM_RESERVE или MEM_COMMIT) всех смежных страниц, которые имеют те же атрибуты защиты, состояние и тип, что и страница, расположенная по адресу, указанному в параметре pvAddress. */

DWORD Protect; /* Идентифицирует атрибут защиты (PAGE_*) всех смежных страниц, которые имеют те же атрибуты защиты, состояние и тип, что и страница, расположенная по адресу, указанному в параметре pvAddress. */

DWORD Type; /* Идентифицирует тип физической памяти (MEM_IMAGE, MEM_MAPPED или MEM_PRIVATE), связанной с группой смежных страниц, которые имеют те же атрибуты защиты, состояние и тип, что и страница, расположенная по адресу, указанному в параметре pvAddress. */

} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

Параметр dwLength задает размер структуры MEMORY_BASIC_INFORMATION.

Функция VirtualQuery(Ex) возвращает число байтов, скопированных в буфер. Используя адрес, указанный в параметре pvAddress, функция VirtualQuery(Ex) заполняет структуру информацией о диапазоне смежных страниц, имеющих одинаковые состояние, атрибуты защиты и тип.

При MEM_FREE элементы AllocationBase, AllocationProtect, Protect и Type содержат неопределенные значения, а при MEM_RESERVE неопределенное значение содержит элемент Protect.

BOOL VirtualLock(LPVOID lpAddress, DWORD dwSize ) – делает область резидентной в памяти (запрещает вытеснение этой области в страничный файл). При успешном завершении возвращает TRUE, иначе – FALSE. Блокирует в оперативной памяти dwSize байт, начиная с адреса lpAddress. Блокирование производится целыми страницами.

BOOL VirtualUnlock(LPVOID lpAddress, DWORD dwSize ) – разрешает выгрузку области в страничный файл. При успешном завершении возвращает TRUE, иначе – FALSE. Разблокирует в оперативной памяти dwSize байт, начиная с адреса lpAddress. Разблокирование производится целыми страницами.

Как и виртуальная память, проецируемые файлы позволяют резервировать регион адресного пространства и передавать ему физическую память. Различие между этими механизмами заключается в том, что в последнем случае физическая память не выделяется из страничного файла, а берется из файла, уже находящегося на диске. Как только файл спроецирован в память, к его данным можно обращаться так, будто он целиком в неё загружен, то есть по указателям.

Проецируемые файлы применяются в следующих случаях:

  • загрузка и выполнение EXE- и DLL- файлов. Это позволяет существенно экономить как на размере страничного файла, так и на времени, необходимом для подготовки приложения к выполнению;

  • организация доступа к файлу данных, размещенному на диске. При этом можно исключить операции файлового ввода-вывода и буферизацию его содержимого;

  • разделение данных между несколькими процессами, выполняемыми на одной машине.

Для того, чтобы спроецировать на адресное пространство процесса файл данных нужно выполнить следующие операции: создать или открыть объект ядра «файл», идентифицирующий дисковый файл, который предполагается использовать, как проецируемый в память; создать объект ядра «проекция файла»; указать системе, как спроецировать в адресное пространство процесса объект «проекция файла» - целиком или частично.

Закончив работу с проецируемым в память файлом, следует выполнить следующие операции: отменить проецирование на адресное пространство процесса объекта ядра «проекция файла»; закрыть объект «проекция файла»; закрыть объект «файл».

Функции механизма отображения файла в память.

HANDLE CreateFile (PCSTR pszFileName, DWORD dwDesiredAccess, DWORD dwShareMode, PSECURITY_ATTRIBUTES psa, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) – открывает или создает файл. Создав или открыв указанный файл, функция возвращает его описатель, в ином случае идентификатор INVALID_HANDLE_VALUE (=0xFFFFFFFF).

Параметр pszFileName идентифицирует имя создаваемого или открываемого файла (при необходимости вместе с путем).

Параметр dwDesiredAccess указывает способ доступа к содержимому файла. Задается одно из четырех значений:

  • 0 – содержимое файла нельзя считывать или записывать; указывается

  • если необходимо всего лишь получить атрибуты файла;

  • GENERIC_READ – чтение файла разрешено;

  • GENERIC_WRITE – запись в файл разрешена;

  • GENERIC_READ | GENERIC_WRITE – разрешено и то и другое.

Создавая или открывая файл данных с намерением использовать его в качестве проецируемого в память, можно установить либо флаг GENERIC_READ (только для чтения), либо комбинированный флаг GENERIC_READ | GENERIC_WRITE (чтение/запись).

Параметр dwShareMode указывает тип совместного доступа к данному файлу. Возможны следующие значения:

  • 0 – другие попытки открыть файл закончатся неудачно;

  • FILE_SHARE_READ – попытка постороннего процесса открыть файл с флагом GENERIC_WRITE не удастся;

  • FILE_SHARE_WRITE – попытка постороннего процесса открыть файл с флагом GENERIC_READ не удастся;

  • FILE_SHARE_READ | FILE_SHARE_WRITE – посторонний процесс может открывать файл без ограничений.

HANDLE CreateFileMapping (HANDLE hFile, PSECURITY_ATTRIBUTES psa, DWORD fdwProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, PCSTR pszName) – выделяет адресное пространство виртуальной памяти для отображения открытого файла, то есть создает проекцию файла. Функция возвращает описатель созданного объекта «проекция файла» в вызвавший функцию поток. Если объект создать не удалось, возвращается нулевой описатель (NULL).

Параметр hFile идентифицирует описатель файла, проецируемого на адресное пространство процесса. Если в описатель файла передать (HANDLE) INVALID_HANDLE_VALUE, то физическая память будет выделена из страничного файла.

Параметр psa указатель на структуру SECURITY_ATTRIBUTES, которая относится к объекту ядра «проекция файла»; для установки защиты по умолчанию ему присваивается NULL.

В параметре fdwProtect необходимо указать желательные атрибуты защиты. Обычно используются следующие:

  • PAGE_READONLY – отобразив объект «проекция файла» на адресное пространство, можно считывать данные из файла (необходимо передать в CreateFile флаг GENERIC_READ);

  • PAGE_READWRITE – отобразив объект «проекция файла» на адресное пространство, можно считывать данные из файла и записывать их. (необходимо передать в CreateFile комбинацию флагов GENERIC_READ | GENERIC_WRITE);

  • PAGE_WRITECOPY – отобразив объект «проекция файла» на адресное пространство, можно считывать данные из файла и записывать их; запись приведет к созданию закрытой копии страницы (необходимо передать в CreateFile либо GENERIC_READ, либо GENERIC_READ | GENERIC_WRITE).

Кроме того в параметр fdwProtect можно ввести еще четыре атрибута раздела побитовой операцией OR (раздел (section) – всего лишь еще одно название проекции памяти):

  • SEC_NOCACHE – сообщает системе, что никакие страницы файла, проецируемого в память, кэшировать не надо;

  • SEC_IMAGE – указывает системе, что данный файл является переносимым исполняемым файлом (portable executable, PE). Отображая его на адресное пространство процесса, система просматривает содержимое файла, чтобы определить, какие атрибуты защиты следует присвоить различным страницам проецируемого образа (mapped image). Заставляет систему спроецировать образ файла и автоматически подобрать подходящие атрибуты защиты страниц;

  • SEC_RESERVE и SEC_COMMIT взаимоисключают друг друга и неприменимы для проецирования в память файла данных. CreateFileMapping их игнорирует.

В параметре dwMaximumSizeHigh необходимо указать старшие 32 бита 64-разрядного значения максимального размер файла в байтах. Для файлов размером менее 4 Гб dwMaximumSizeHigh всегда равен 0.

В параметре dwMaximumSizeLow необходимо указать младшие 32 бита 64-разрядного значения максимального размер файла в байтах.

Для создания объекта «проекция файла» таким, чтобы он отражал текущий размер файла, необходимо передать в обоих параметрах нули. Так же следует поступить, если необходимо ограничиться считыванием или как-то обработать файл, не меняя его размер. Для дозаписи данных в файл необходимо выбирать его размер максимальным. Вызов CreateFileMapping с флагом PAGE_READWRITE заставляет систему проверять, чтобы размер соответствующего файла данных на диске был не меньше, чем указано в параметрах dwMaximumSizeHigh и dwMaximumSizeLow. Если файл окажется меньше заданного, CreateFileMapping увеличит его размер до указанной величины. Если объект «проекция файла» создан с флагом PAGE_READONLY или PAGE_WRITECOPY, то размер, переданный функции CreateFileMapping, не должен превышать физический размер файла на диске.

В параметр pszName необходимо передать строку с нулевым байтом в конце; в ней указывается имя объекта «проекция файла», которое используется для доступа к данному объекту из другого процесса. Если совместное использование проецируемого в память файла не требуется, то в данном параметре можно передать NULL.

PVOID MapViewOfFile (HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap) –проецирует файл или его часть на адресное пространство процесса. При успешном завершении возвращает начальный адрес оконного представления файла, в противном случае NULL.

Параметр hFileMappingObject идентифицирует описатель объекта «проекция файла», возвращаемый предшествующим вызовом либо CreateFileMapping, либо OpenFileMapping.

Параметр dwDesiredAccess идентифицирует вид доступа к данным:

  • FILE_MAP_WRITE – файловые данные можно считывать и записывать; в функцию CreateFileMapping необходимо передать атрибут PAGE_READWRITE;

  • FILE_MAP_READ – файловые данные можно только считывать; функцию CreateFileMapping необходимо было вызвать с любым из следующих атрибутов: PAGE_READONLY, PAGE_READWRITE или PAGE_WRITECOPY;

  • FILE_MAP_ALL_ACCESS – то же, что и FILE_MAP_WRITE;

  • FILE_MAP_COPY – файловые данные можно считывать и записывать, но запись приводит к созданию закрытой копии страницы; необходимо было вызвать функцию CreateFileMapping с любым из следующих атрибутов: PAGE_READONLY, PAGE_READWRITE или PAGE_WRITECOPY.

В параметре dwFileOffsetHigh передаются старшие 32 бита смещения в файле.

В параметре dwFileOffsetLow передаются младшие 32 бита смещения в файле.

Смещение в файле должно быть кратно гранулярности выделения памяти в данной системе.

В параметре dwNumberOfBytesToMap указывается размер представления, то есть сколько байтов файла данных должно быть спроецировано на адресное пространство. Если этот параметр равен 0, система попытается спроецировать представление, начиная с указанного смещения и до конца файла.

Если при вызове MapViewOfFile указан флаг FILE_MAP_COPY, система передаст физическую память из страничного файла. Размер передаваемого пространства определяется параметром dwNumberOfBytesToMap. Создав копию исходной страницы, система меняет ее атрибут защиты с PAGE_WRITECOPY на PAGE_READWRITE.

PVOID MapViewOfFileEx (HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, PVOID pvBaseAddress) – делает тоже, что и функция MapViewOfFile. Содержит один дополнительный параметр.

В параметре pvBaseAddress можно задать начальный адрес файла, проецируемого в память. Базовый адрес должен быть кратным гранулярности выделения памяти в системе иначе MapViewOfFileEx вернет NULL, сообщив тем самым об ошибке (в Windows 98 базовый адрес будет округлен до ближайшего меньшего значения, кратного гранулярности выделения памяти; в Windows 2000 GetLastError вернет код 1132 (ERROR_MAPPED_ALIGNMENT)). Если указать NULL в параметре pvBaseAddress, то функция поведет себя идентично MapViewOfFile.

HANDLE OpenFileMapping (DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName) – предоставляет доступ к проекции файла, созданной в другом процессе. Функция возвращает описатель объекта «проекция файла», созданного в другом процессе, в вызвавший функцию поток. Если объект открыть не удалось, возвращается нулевой описатель (NULL).

Параметр dwDesiredAccess определяет атрибуты защиты объекта «проекция файла». Возможны следующие значения: FILE_MAP_WRITE, FILE_MAP_READ, FILE_MAP_ALL_ACCESS, FILE_MAP_COPY (описаны выше).

Параметр bInheritHandle определяет: будет ли возвращенный функцией дескриптор объекта «проекция файла» наследоваться дочерними процессами. Значение TRUE означает, что дочерний процесс будет наследовать дескриптор, FALSE – нет.

Параметр lpName указывает на строку с именем открываемого объекта «проекция файла».

BOOL FlushViewOfFile (PVOID pvAddress, DWORD dwNumberOfBytesToFlush) – записать на диск все измененные страницы. При успешном завершении возвращает TRUE, в противном случае – FALSE.

Параметр pvAddress принимает адрес байта, который содержится в границах представления файла, проецируемого в память. Переданный адрес округляется до значения, кратного размеру страниц.

Параметр dwNumberOfBytesToFlush определяет количество байтов, которые надо записать в дисковый образ файла.

Если FlushViewOfFile вызывается в отсутствие измененных данных, она просто возвращает управление. В случае проецируемых файлов, физическая память которых расположена на сетевом диске, FlushViewOfFile гарантирует, что файловые данные будут перекачаны с рабочей станции, но не гарантирует, что сервер, обеспечивающий доступ к этому файлу, запишет данные на удаленный диск, так как он может просто кэшировать их.

Чтобы обеспечить при вызове функции FlushViewOfFile сохранение на диске сервера всех файловых данных, при создании объекта «проекция файла» и последующем проецировании его представления необходимо использовать флаг FILE_FLAG_WRITE_THROUGH.

Если первоначально представление было спроецировано с флагом FILE_MAP_COPY, любые изменения, внесенные в файловые данные, на самом деле производятся над копией этих данных, хранящихся в страничном файле.

BOOL UnmapViewOfFile (PVOID pvBaseAddress) – отключает файл от адресного пространства процесса. При успешном завершении возвращает TRUE, в противном случае – FALSE.

Параметр pvBaseAddress указывает базовый адрес возвращаемого системе региона. Он должен совпадать со значением, полученным после вызова MapViewOfFile.

Закрыть проекцию файла либо файл можно вызовом функции CloseHandle, передав ей в качестве параметра дескриптор соответствующего объекта.

Куча (динамически распределяемая область памяти) – это регион зарезервированного адресного пространства. Первоначально большей его части физическая память не передается. По мере того как программа занимает эту область под данные, специальный диспетчер, управляющий кучами (heap manager), постранично передает ей физическую память из страничного файла. При освобождении блоков в куче диспетчер возвращает системе соответствующие страницы физической памяти. Преимущество динамически распределяемой памяти заключается в том, что она позволяет игнорировать гранулярность выделения памяти и размер страниц и сосредоточиться непосредственно на задаче. Кучи часто используются для обработки списков и деревьев. Недостатком куч является более медленное выделение и освобождение памяти.

Основные функции по управлению динамически распределяемой области памяти.

HANDLE GetProcessHeap() – возвращает описатель стандартной кучи процесса.

HANDLE HeapCreate (DWORD fdwOptions, DWORD dwInitialSize, DWORD dwMaximumSize) – создает дополнительные кучи в процессе. При успешном создании кучи функция возвращает описатель, идентифицирующий новую кучу.

Параметр fdwOptions модифицирует способ выполнения операций над кучей. В нем можно указать 0, HEAP_NO_SERIALIZE, HEAP_GENERATE_EXCEPTIONS или HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS.

По умолчанию действует принцип последовательного доступа к куче, что позволяет не опасаться одновременного обращения к ней сразу нескольких потоков.

Флаг HEAP_GENERATE_EXCEPTIONS заставляет систему генерировать исключение при любом провале попытки выделения блока в куче вместо возвращения NULL.

Флаг HEAP_NO_SERIALIZE определяет, что взаимное исключение не будет использоваться, когда функции кучи будут выделять и освобождать память этой кучи.

При отсутствии флага HEAP_NO_SERIALIZE два или более потока могут одновременно размещать и освобождать память из одной и той же кучи.

Параметр dwInitialSize определяет количество байтов, первоначально передаваемых куче. При необходимости функция округляет это значение до ближайшей большей величины, кратной размеру страниц.

Параметр dwMaximumSize указывает максимальный объем, до которого может расширяться куча (предельный объем адресного пространства, резервируемого под кучу). Если он больше 0, то создается куча именно такого размера и ее нельзя увеличить. А если этот параметр равен 0, система резервирует регион и, если надо, расширяет его до максимально возможного объема.

PVOID HeapAlloc (HANDLE hHeap, DWORD fdwFlags, DWORD dwBytes) – выделяет блок памяти в куче. При успешном выделении блока HeapAlloc возвращает его адрес. Если памяти недостаточно и флаг HEAP_GENERATE_EXCEPTIONS не указан, функция возвращает NULL.

Параметр hHeap идентифицирует описатель кучи, из которой выделяется память.

Параметр dwBytes определяет число выделяемых в куче байтов. Параметр fdwFlags позволяет указывать флаги, влияющие на характер выделения памяти. В настоящее время поддерживается только три флага: HEAP_ZERO_MEMORY, HEAP_GENERATE_EXCEPTIONS и HEAP_NO_SERIALIZE. Флаг HEAP_ZERO_MEMORY приводит к заполнению содержимого блока нулями перед возвратом из HeapAlloc. Флаг HEAP_GENERATE_EXCEPTIONS заставляет эту функцию генерировать программное исключение, если в куче не хватает памяти для удовлетворения запроса. Если данный флаг включен при вызове HeapCreate, то при вызове HeapAlloc указывать его уже не нужно.

Если функция HeapAlloc завершилась неудачно и при этом разрешено генерировать исключения, она может вызвать одно из двух исключений:

  • STATUS_NO_MEMORY – попытка выделения памяти не удалась из-за ее нехватки;

  • STATUS_ACCESS_VIOLATION – попытка выделения памяти не удалась из-за повреждения кучи или неверных параметров функции.

Флаг HEAP_NO_SERIALIZE заставляет HeapAlloc при данном вызове не применять принцип последовательного доступа к куче.

PVOID HeapReAlloc (HANDLE hHeap, DWORD fdwFlags, PVOID pvMem, DWORD dwBytes) – изменяет размер блока памяти в куче. Функция HeapReAlloc возвращает либо адрес нового, измененного блока, либо NULL, если размер блока изменить не удалось и не установлен флаг HEAP_GENERATE_EXCEPTIONS.

Параметр hHeap идентифицирует кучу, в которой содержится изменяемый блок.

Параметр fdwFlags указывает флаги, используемые при изменении размера блока: HEAP_GENERATE_EXCEPTIONS, HEAP_NO_SERIALIZE, HEAP_ZERO_MEMORY или HEAP_REALLOC_IN_PLACE_ONLY.

Первые два флага имеют тот же смысл, что и при использовании с HeapAlloc. Флаг HEAP_ZERO_MEMORY полезен только при увеличении размера блока памяти. В этом случае дополнительные байты, включаемые в блок, предварительно обнуляются. Флаг HEAP_REALLOC_IN_PLACE_ONLY сообщает функции, что данный блок памяти перемещать внутри кучи не разрешается. Если функция сможет расширить блок без его перемещения, она расширит его и вернет исходный адрес блока. Если для расширения блока его надо переместить, она возвращает адрес нового, большего по размеру блока. Если блок затем снова уменьшается, функция вновь возвращает исходный адрес первоначального блока.

Параметр pvMem определяет текущий адрес изменяемого блока.

Параметр dwBytes определяют новый размер блока (в байтах).

DWORD HeapSize (HANDLE hHeap, DWORD fdwFlags, LPCVOID pvMem) – определяет истинный размер выделенного блока памяти.

Параметр hHeap идентифицирует кучу.

Параметр pvMem сообщает адрес блока.

Параметр fdwFlags принимает два значения: 0 или HEAP_NO_SERIALIZE.

BOOL HeapFree (HANDLE hHeap, DWORD fdwFlags, PVOID pvMem) – освобождает блок памяти в куче и при успешном вызове возвращает TRUE.

Параметр hHeap идентифицирует кучу.

Параметр pvMem сообщает адрес блока.

Параметр fdwFlags принимает два значения: 0 или HEAP_NO_SERIALIZE.

Кучу можно уничтожить вызовом HeapDestroy:

BOOL HeapDestroy (HANDLE hHeap) – освобождает все блоки памяти внутри кучи и возвращает системе физическую памяти из зарезервированного региона адресного пространства, занятого кучей. При успешном выполнении функция возвращает TRUE.

DWORD GetProcessHeaps (DWORD dwNumHeaps, PHANDLE pHeaps) – позволяет получить описатели всех куч. Возвращает число куч.

Параметр pHeaps – массив описателей куч.

Параметр dwNumHeaps – число куч.

BOOL HeapValidate (HANDLE hHeap, DWORD fdwFlags, LPCVOID pvMem) – проверяет целостность кучи.

В параметр hHeap передается описатель кучи.

В параметр в fdwFlags можно передать 0 или флаг HEAP_NO_SERIALIZE.

В параметр pvMem можно передать NULL (тогда функция просматривает все блоки в куче, чтобы убедиться в отсутствии поврежденных блоков), или адрес конкретного блока. Тогда функция проверит только этот блок.

UINT HeapCompact (HANDLE hHeap, DWORD fdwFlags) – объединяет свободные блоки в куче, а также для возвращает системе любые страницы памяти, на которых нет выделенных блоков.

В параметре fdwFlags передают 0 (обычно) или флаг HEAP_NO_SERIALIZE.

BOOL HeapLock (HANDLE hHeap) делает поток, вызвавшим эту функцию владельцем кучи hHeap. Если другой поток обращается к этой куче, указывая тот же описатель кучи, система приостанавливает его выполнение до тех пор, пока куча не будет разблокирована вызовом HeapUnlock. При успешном завершении возвращает TRUE, в противном случае – FALSE.

BOOL HeapUnlock (HANDLE hHeap) разблокирует кучу ранее заблокированную функцией HeapLock. При успешном завершении возвращает TRUE, в противном случае – FALSE.

Функции HeapAlloc, HeapSize, HeapFree и другие . все обращаются к HeapLock и HeapUnlock, чтобы обеспечить последовательный доступ к куче.

Последняя функция, предназначенная для работы с кучами, . HeapWalk:

BOOL HeapWalk (HANDLE hHeap, PPROCESS_HEAP_ENTRY pHeapEntry) – позволяет просматривать содержимое кучи. Возвращает FALSE, если блоков в куче больше нет, иначе – TRUE.

В параметр hHeap необходимо передать дескриптор кучи.

В параметр PPROCESS_HEAP_ENTRY pHeapEntry необходимо передать адрес структуры PROCESS_HEAP_ENTRY.

typedef struct _PROCESS_HEAP_ENTRY {

PVOID lpData;

DWORD cbData;

BYTE cbOverhead;

BYTE iRegionIndex;

WORD wFlags;

union {

struct {

HANDLE hMem;

DWORD dwReserved[ 3 ];

} Block;

struct {

DWORD dwCommittedSize;

DWORD dwUnCommittedSize;

LPVOID lpFirstBlock;

LPVOID lpLastBlock;

} Region;

};

} PROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY, *PPROCESS_HEAP_ENTRY.

Прежде чем перечислять блоки в куче, присвойте NULL элементу lpData, и это заставит функцию HeapWalk инициализировать все элементы структуры. Чтобы перейти к следующему блоку, необходимо вызвать HeapWalk еще раз, передав ей тот же описатель кучи и адрес той же структуры PROCESS_HEAP_ENTRY.

HGLOBAL GlobalAlloc (UINT fuAlloc, DWORD cbAlloc) – выделяет блок памяти (из кучи процесса).

HGLOCAL GlobalReAlloc (HGLOCAL hglb, DWORD cbNewSize, UINT fuAlloc) – изменяет размер блока памяти.

DWORD GlobalSize (HGLOCAL hglb) – возвращает размер блока памяти.

LPVOID GlobalLock (HGLOCAL hglb) – зафиксировать блок памяти.

BOOL GlobalUnlock (HGLOCAL hglb) – снять фиксацию блока памяти.

HGLOCAL GlobalFree (HGLOCAL hglb) - освободить блок памяти.

Дополнительные сведения о разработке графического интерфейса приложений, необходимые для выполнения работы.

Распаковщики сообщений.

Для написания оконных процедур часто используют распаковщики сообщений. Распаковщики заставляют разбивать оператор switch в оконной процедуре на небольшие функции по одной на оконное сообщение. Это значительно улучшает внутреннюю структуру кода. Распаковщики берут параметры wParam и lParam, расщепляют их на отдельные компоненты и вызывают функцию обработчик соответствующего сообщения.

Оконная функция при этом выглядит примерно так:

LRESULT 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, lParam));

}

}

Остается только написать обработчики соответствующих сообщений.

Так, функция Cls_OnCommand может иметь примерно такой вид:

void Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {

switch (id) {

case ID_SOMELISTBOX:

if (codeNotify != LBN_SELCHANGE)

break;

// обрабатываем LBN_SELCHANGE

break;

case ID_SOMEBUTTON:

break;

M

}

}

В файле WindowsX.h макрос HANDLE_MSG определен так:

#define HANDLE_MSG(hwnd, message, fn) \

case (message): \

return HANDLE_##message((hwnd), (wParam), (lParam), (fn));

Для сообщения WM_COMMAND эта строка после обработки препроцессором выглядит как:

case (WM_COMMAND):

return HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (Cls_OnCommand));

Макросы HANDLE_WM_* определены тоже в WindowsX.h. Это и есть настоящие распаковщики сообщений.

Вот макрос HANDLE_WM_COMMAND:

#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn) \

((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), \

(UINT)HIWORD(wParam)), 0L)

Результат раскрытия препроцессором этого макроса – вызов функции Cls_OnCommand, которой передаются (после соответствующих преобразований типов) распакованные части параметров wParam и lParam.

Чтобы использовать распаковщик для обработки сообщения, откройте файл WindowsX.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)), \

(LPARAM)(HWND)(hwndCtl))

Первая строка . комментарий, показывающий прототип функции, которую Вы должны написать. Следующая строка – макрос HANDLE_WM_*, а последняя содержит предописатель сообщения (message forwarder). Допустим, при обработке сообщения WM_COMMAND Вы хотите вызвать оконную процедуру, используемую по умолчанию. Это выглядело бы так:

void Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {

// выполняем обычную обработку

// обработка по умолчанию

FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, DefWindowProc);

}

Макросы FORWARD_WM_* принимают распакованные параметры сообщения и воссоздают их эквиваленты wParam и lParam, после чего вызывают указанную Вами функцию.

Окна диалога.

int DialogBox (HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc) – выводит на экран модальное диалоговое окно. Функция не возвращает управление в оконную функцию родительского окна до тех пор, пока окно диалога не будет закрыто. Возвращаемым значением функции DialogBox является второй параметр функции EndDialog, которая вызывается в процедуре диалога.

Параметр hInstance содержит описатель экземпляра приложения.

Параметр lpTemplate определяет имя шаблона окна диалога (как оно определено в файле описания ресурсов). Если вместо имени шаблона окна диалога используется число, то с помощью макрокоманды MAKEINTRESOURCE его можно преобразовать в строку.

Параметр hWndParent содержит описатель родительского окна приложения.

Параметр lpDialogFunc содержит указатель на функцию диалоговую процедуру.

BOOL CALLBACK DialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) – диалоговая процедура – обрабатывает сообщения, получаемые окном диалога; вызывается оконной процедурой окна диалога. Возвращает TRUE, если обрабатывает сообщение, и возвращает FALSE (0), если она не обрабатывает сообщение.

Параметр hwndDlg содержит дескриптор диалогового окна.

Параметр uMsg содержит идентификатор сообщения.

Параметр wParam содержит первый параметр сообщения.

Параметр lParam содержит второй параметр сообщения.

Процедура диалога не получает сообщения WM_CREATE; вместо этого она выполняет инициализацию при обработке специального сообщения WM_INITDIALOG.

Сообщение WM_INITDIALOG является первым сообщением, которое получает процедура диалога. Это сообщение посылается только процедурам диалога.

Процедура диалога не обрабатывает сообщения WM_PAINT и WM_DESTROY.

Сообщения для модального окна диалога не проходят через очередь сообщений программы.

. The EndDialog function destroys a modal dialog box, causing the system to end any processing for the dialog box.

BOOL EndDialog (HWND hDlg, int nResult) – закрывает (разрушает) модальное диалоговое окно.

Параметр HWND hDlg содержит дескриптор модального диалогового окна.

Параметр nResult содержит значение, которое должно быть возвращено приложению функцией, создавшей диалоговое окно.

Элементы управления диалоговых окон.

HWND GetDlgItem (HWND hDlg, int nIDDlgItem) - возвращает описатель дочернего элемента управления диалогового окна. В случае неудачи возвращает NULL.

В параметр hDlg передается описатель диалогового окна.

В параметр nIDDlgItem передается идентификатор элемента управления диалогового окна.

LONG GetWindowLong (HWND hWndСtrl, GWL_ID) – возвращает идентификатор элемента управления диалогового окна по его описателю hWndСtrl.

LONG SendDlgItemMessage (

HWND hDlg, // описатель диалогового окна

int nIDDlgItem, /* идентификатор элемента управления в диалоговом окне */

UINT Msg, // идентификатор сообщения

WPARAM wParam, // первый параметр сообщения

LPARAM lParam // второй параметр сообщения

) – посылает сообщение элементу управления диалогового окна. Вызов функции SendDlgItemMessage (hDlg, nIDDlgItem, Msg, wParam, lParam ) эквивалентен вызову SendMessage(GetDlgItem(hDlg, nIDDlgItem), Msg, wParam, lParam).

BOOL CheckRadioButton (

HWND hDlg, // описатель диалогового окна

int nIDFirstButton, // идентификатор первого переключателя в группе

int nIDLastButton, // идентификатор второго переключателя в группе

int nIDCheckButton // идентификатор помечаемого переключателя

) – снимает контрольные метки со всех переключателей с идентификаторами от nIDFirstButton до nIDLastButton, за исключением переключателя с идентификатором nIDCheckButton, который, наоборот, включается. Идентификаторы должны быть заданы последовательно. Возвращает TRUE при успешном завершении и FALSE – при неудачном завершении.

BOOL CheckDlgButton (

HWND hDlg, // описатель диалогового окна

int nIDButton, // идентификатор элемента управления

UINT uCheck /* состояние, в которое переводится элемент управления *

) – переводит элемент управления в заданное параметром uCheck состояние. Возвращает TRUE при успешном завершении и FALSE – при неудачном завершении.

Допустимые значения параметра uCheck:

  • BST_CHECKED – контрольная метка установлена;

  • BST_UNCHECKED – контрольная метка сброшена;

  • BST_INDETERMINATE – неопределенное состояние элемента управления (используется только, если элемент управления имеет стиль BS_3STATE или BS_AUTO3STATE).

UINT IsDlgButtonChecked (

HWND hDlg, // описатель диалогового окна

int nIDButton // идентификатор элемента управления

) – возвращает состояние элемента управления. Если элемент управления создан с одним из стилей BS_AUTOCHECKBOX, BS_AUTORADIOBUTTON, BS_AUTO3STATE, BS_CHECKBOX, BS_RADIOBUTTON, or BS_3STATE, то возможные возвращаемые значения: BST_CHECKED (контрольная метка установлена), BST_UNCHECKED (контрольная метка сброшена), BST_INDETERMINATE (используется только, если элемент управления имеет стиль BS_3STATE или BS_AUTO3STATE). В противном случае возвращает 0.

HWND GetNextDlgTabItem (

HWND hDlg, // описатель диалогового окна

HWND hCtl, // описатель известного элемента управления

BOOL bPrevious // флаг направления

) – возвращает описатель предыдущего (bPrevious=TRUE) или следующего (bPrevious=FALSE) элемента управления, имеющего стиль WS_TABSTOP. Стартовой точкой является элемент управления с описателем hCtl. Если этот параметр определен как NULL, то стартовой точкой служит первый (bPrevious=FALSE) или последний (bPrevious=TRUE) элемент управления диалогового окна.

HWND GetNextDlgGroupItem (

HWND hDlg, // описатель диалогового окна

HWND hCtl, // описатель известного элемента управления

BOOL bPrevious // флаг направления

) – возвращает описатель предыдущего (bPrevious=TRUE) или следующего (bPrevious=FALSE) элемента управления группы. Стартовой точкой является элемент управления с описателем hCtl. Если этот параметр определен как NULL, то стартовой точкой служит первый (bPrevious=FALSE) или последний (bPrevious=TRUE) элемент управления группы.

BOOL EnableWindow (

HWND hWndCtrl, // описатель элемента управления

BOOL bEnable // флаг доступности или недоступности ввода

) – делает элемент управления доступным (bEnable=TRUE) или недоступным (bEnable=FALSE) для ввода. Если окно элемента управления недоступно, то оно не реагирует ни на клавиатуру, ни на мышь. Нельзя делать недоступным окно элемента управления, имеющее фокус ввода.

BOOL InvalidateRect (

HWND hWnd, // описатель окна

CONST RECT *lpRect, // адрес координат прямоугольника

BOOL bErase // флаг стирания фона

) – добавляет прямоугольник в области клиентской части окна в регион, который необходимо перерисовать (посредством посылки окну сообщения WM_PAINT). Если параметр bErase = TRUE, то фон стирается, иначе – нет. Возвращает TRUE при успешном завершении и FALSE – при неудачном завершении.

BOOL SetDlgItemText (

HWND hDlg, // описатель диалогового окна

int nIDDlgItem, // идентификатор элемента управления

LPCTSTR lpString // указатель на нуль-терминированную строку

) – устанавливает заголовок или текст в элементе управления диалогового окна. Возвращает TRUE при успешном завершении и FALSE – при неудачном завершении.

Другой способ установки текста в элементе управления – послать сообщение WM_SETTEXT, в параметре wParam передать 0, а в параметре lParam передать адрес нуль-терминированной текстовой строки.

UINT GetDlgItemText (

HWND hDlg, // описатель диалогового окна

int nIDDlgItem, // идентификатор элемента управления

LPTSTR lpString, // адрес буфера для текста

int nMaxCount // максимальное число копируемых символов в строке

) – записывает заголовок или текст элемента управления диалогового окна в буфер в количестве символов не более определенном в параметре nMaxCount. При успешном завершении возвращает число скопированных символов, исключая символ конца строки. При неудачном завершении возвращает 0.

BOOL SetDlgItemInt (

HWND hDlg, // описатель диалогового окна

int nIDDlgItem, // идентификатор элемента управления

UINT uValue, // устанавливаемое значение

BOOL bSigned // знаковое или беззнаковое значение

) – устанавливает текст элемента управления в диалоговом окне в строку, полученную преобразованием целого числа. Если параметр bSigned = TRUE, то параметр uValue интерпретируется как знаковое целое. Если параметр bSigned = FALSE, то параметр uValue интерпретируется как беззнаковое целое.

UINT GetDlgItemInt (

HWND hDlg, // описатель диалогового окна

int nIDDlgItem, // идентификатор элемента управления

BOOL *lpTranslated, /* указатель на переменную для возвращения в нее индикатора успешности *.

BOOL bSigned // определяет знаковое или беззнаковое значение

) – транслирует текст элемента управления диалогового окна в целое значение и возвращает его в качестве результата. Если параметр bSigned = TRUE и первый символ текста равен «минус», то функция возвращает знаковое число, в противном случае возвращается беззнаковое число. Если параметр lpTranslated не равен NULL, то в переменную, на которую указывает lpTranslated записывается TRUE в случае успешного преобразования текста в целое число, и возвращается FALSE – в противном случае.

Для установки фокуса ввода на элемент управления с описателем hWndCtrl используется вызов SetFocus(hWndCtrl).

При посылке сообщения WM_COMMAND через параметр lParam передается описатель элемента управления, в LOWORD(wParam) содержится идентификатор элемента управления и в параметре HIWORD(wParam) содержится код уведомления. Код уведомления определяет событие, произошедшее с элементом управления.

Описание диалоговых окон в ресурсах.

Шаблон окна диалога:

Имя или иденификатор DIALOG xPos, yPos, Width, Hight

[STYLE style1 | style2 |…| styleN]

[CAPTION “Заголовок”]

BEGIN

Control-template1

Control-template2

……………………

Control-templateN

END

Скобки [] означают необязательность данной инструкции в шаблоне. Если не задана инструкция STYLE, то по умолчанию у окна устанавливается стиль WS_POPUP | WS_BORDER. Если к инструкции STYLE добавить инструкцию CAPTION, то по умолчанию у окна устанавливается стиль WS_POPUP | WS_CAPTION | WS_SYSMENU. Стиль WS_DLGFRAME определяет рамку.

Числа xPos и yPos определяют положение верхнего левого угла диалогового окна относительно родительского окна. Числа Width и Hight определяют ширину и высоту диалогового окна. Величины xPos и Width задаются в ¼ средней ширины символа системного шрифта. Величины yPos и Hight задаются в 1/8 высоты символа системного шрифта.

Шаблон элементов управления EDITTEXT, SCROLLBAR, LISTBOX, COMBOBOX диалогового окна задается инструкцией:

Control-type id, xPos, yPos, Width, Height, [, iStyle]

Шаблон остальных элементов управления диалогового окна задается инструкцией:

Control-type “text”, id, xPos, yPos, Width, Height, [, iStyle]

Элемент iStyle задает дополнительные стили.

Возможны следующие элементы управления:

Тип элемента управления

Класс окна

Стиль окна

PUSHBUTTON

Button

BS_PUSHBUTTON | WS_TABSTOP

DEFPUSHBUTTON

Button

BS_DEFPUSHBUTTON | WS_TABSTOP

CHECKBOX

Button

BS_CHECKBOX | WS_TABSTOP

RADIOBUTTON

Button

BS_RADIOBUTTON | WS_TABSTOP

GROUPBOX

Button

BS_GROUPBOX | WS_TABSTOP

LTEXT

Static

SS_LEFT | WS_GROUP

CTEXT

Static

SS_CENTER | WS_GROUP

RTEXT

Static

SS_RIGHT | WS_GROUP

ICON

Static

SS_ICON

EDITTEXT

Edit

ES_LEFT | WS_BORDER | WS_TABSTOP

SCROLLBAR

Scrollbar

SBS_HORZ

LISTBOX

Listbox

LBS_NOTIFY | WS_BORDER | WS_VSCROLL

COMBOBOX

Combobox

CBS_SIMPLE | WS_TABSTOP

Кроме показанных выше стилей окна, каждое из представленных дочерних окон элементов управления имеет стиль: WS_CHILD | WS_VISIBLE.

Если необходимо задать класс окна и полностью определить стиль окна, то можно использовать следующую инструкцию:

CONTROL “text”, id, “class”, iStyle, xPos, yPos, Width, Height

Для всех дочерних окон элементов управления, к которым необходим доступ с помощью клавиши <Tab>, задается стиль окна WS_TABSTOP.

Для объединения элементов управления в группу, внутри которой можно использовать клавиши управления ввода для передачи фокуса ввода с одного элемента на другой, необходимо задать им стиль WS_GROUP.

Кнопке “Ok” задается системный идентификатор IDOK. Кнопке “Cancel” задается системный идентификатор IDCANCEL. Элементам класса static не требующим ввода текста присваивается единый идентификатор IDC_STATIC.

Ресурс значок может быть описан в файле ресурсов инструкцией:

Имя или идентификатор ICON [DISCARDABLE] "Имя файла.ico"

Соседние файлы в папке ОС