Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Unicode: набор широких символов




Unicode — стандарт, первоначально разработанный Apple и Xerox в 1988 г В 1991 г был создан консорциум для совершенствования и внедрения Unicode В него вошли компании Apple, Compaq, Hewlett-Packard, IBM, Microsoft, Oracle, Silicon Graphics, Sybase, Unisys и Xcrox.

Строки в Unicode просты и логичны. Все символы в них представлены 16-битными значениями (по 2 байта на каждый). В них нет особых байтов, указывающих, чем является следующий байт — частью того же символа или новым символом. Это значит, что прохождение по строке реализуется простым увеличением или уменьшением значения указателя. Функции CharNext, CharPrev и lsDBCSLeadByte больше не нужны.

Так как каждый символ — 16-битное число, Unicode позволяет кодировать 65 536 символов, что более чем достаточно для работы с любым языком. Разительное отличие от 256 знаков, доступных в однобайтовом наборе!

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

Эти 65 536 символов разбиты на отдельные группы Некоторые группы, а также включенные в них символы показаны в таблице

16-битный код Символы 16-битный код Символы
0000-007F ASCII 0300-U36F Общие диакритические
0080-00FF Символы Latin 1 0400-04FF Кириллица
0100-017F Европейские латинские 0530-058F Армянский
01 80-01FF Расширенные латинские 0590-05FF Еврейский
0250-02AF Стандартные фонетические 0600-06FF Арабский
02BO-02FF Модифицированные литеры 0900-097F Деванагари

Около 29 000 кодовых позиций пока не заняты, но зарезервированы на будущее. Примерно 6 000 позиций оставлено специально для программистов (на их усмотрение).

Microsoft разработала Windows API так, чтобы как можно меньше влиять на Ваш код. В самом деле, у Вас появилась возможность создать единственный файл с исходным кодом, компилируемый как с применением Unicode, так и без него, — достаточно определить два макроса (UNICODE и _UNICODE), которые отвечают за нужные изменения.

Unicode и библиотека С

Для использования Unicode-строк были введены некоторые новые типы данных. Стандартный заголовочный файл String.h модифицирован в нем определен wchar_t — тип данных для Unicode-символа

typedef unsigned short wchar_t

Если Вы хотите, скажем, создать буфер для хранения Unicode-строки длиной до 99 символов с нулевым символом в конце, поставьте оператор:

wchar_t szBuffer[100];

Он создает массив из ста 16-битных значений. Конечно, стандартные функции библиотеки С для работы со строками вроде strcpy, strchr и strcat оперируют только с ANSI-строками — они не способны корректно обрабатывать Unicode-строки. Поэтому в ANSI С имеется дополнительный набор функций. Ниже приведен список строковых функций ANSI C и эквивалентных им Unicode-функций:

char * strcat(char *, const char *); wchar_t * wcscat(wchar_t *, const wchar t *);
char * strchr(const char *, int); wchar_t * wcschr(const wchar_t *, wchar_t);
int strcmp(const char *, const char *); int wcscmp(const wchar_t *, const wchar_t *);
char * strcpy(char *, const char *); wchar_t * wcscpy(wchar_t *, const wchar_t *);
size_t strlen(const char *); size_t wcslen(const wchar_t *);

Обратите внимание, что имена всех новых функций начинаются с wcs — это аббревиатура wide character set (набор широких символов) Таким образом, имена Unicode-функций образуются простой заменой префикса str соответствующих ANSI-функций на wcs.

Код, содержащий явные вызовы str- или wcs-функций, просто так компилировать с использованием и ANSI, и Unicode нельзя. Чтобы реализовать возможность компиляции "двойного назначения", замените в своей программе заголовочный файл String.h на TChar.h Он помогает создавать универсальный исходный код, способный задействовать как ANSI, так и Unicode, — и это единственное, для чего нужен файл TChar.h. Он состоит из макросов, заменяющих явные вызовы str- или wcs-функций. Если при компиляции исходного кода Вы определяете _UNICODE, макросы ссылаются на wcs-функции, а в его отсутствие — на str-фупкции

Например, в TChar.h есть макрос _tcscpy. Если Вы включили этот заголовочный файл, но UNlCODE не определен, _tcscpy раскрывается в ANSI-функцию strcpy, а если _UNICODE определен — в Unicode-функцию wcscpy, В файле TChar.h определены универсальные макросы для всех стандартных строковых функций С. При использовании этих макросов вместо конкретных имен ANSI- или Unicode-функций Ваш код можно будет компилировать в расчете как на Unicode, так и на ANSI.

Но, к сожалению, это ещe не все. В файле TChar.h есть дополнительные макросы.

Чтобы объявить символьный массив универсального назначения" (ANSI/Unicode), применяется тип данных TCHAR. Если _UNICODE определен, TCHAR объявляется так:

typedef wchar_L TCHAR;

А если UNICODE не определен, то:

typedef char TCHAR

Используя этот тип данных, можно объявить строку символов как:

TCHAR szString[100];

Можно также определять указатели на строки:

TCHAR *szError = "Error";

Правда, в этом операторе есть одна проблема. По умолчанию компилятор Microsoft С++ транслирует строки как состоящие из символов ANSI, а не Unicode. B итоге этот оператор нормально компилируется, если UNICODE не определен, но в ином случае дает ошибку. Чтобы компилятор сгенерировал Unicode-, a не ANSI-строку, оператор надо переписать так

TCHAR *szFrror = L"Error";

Заглавная буква L перед строковым литералом указывает компилятору, что его надо обрабатывать как Unicode-строку. Тогда, размещая строку в области данных программы, компилятор вставит между всеми символами нулевые байты. Но возникает другая проблема — программа компилируется, только если _UNICODE определен Следовательно, нужен макрос, способный избирательно ставить L перед строковым литералом. Эту работу выполняет макрос TEXT, также содержащийся в Tchar.h. Если _UNICODE определен, TEXT определяется как

#define TEXT(x) L ## x

В ином случае TEXT определяется следующим образом:

#define TEXT(x) x

Используя этот макрос, перепишем злополучный оператор так, чтобы его можно было корректно компилировать независимо от того, определен _UNICODE или нет:

TCHAR *szError = TEXT("Error");

Макрос TEXT применяется и для символьных литералов. Например, чтобы проверить, является ли первый символ строки заглавной буквой J:

if (szError[0] == TEXT('J')) {
// первый символ - J
} else {
// первый символ - не J
}

Типы данных, определенные в Windows для Unicode

В заголовочных файлах Windows определены следующие типы данных.

Тип данных Описание
WCHAR Unicode-символ
PWSTR Указатель на Unicode –строку
PCWSTR Указатель на стоковую константу в Unicode

Эти типы данных относятся исключительно к символам и строкам в кодировке Unicode. B заголовочных файлах Windows определены также универсальные (ANSI) Unicode) типы данных PTSTR и PCTSTR, указывающие — в зависимости от того, определен ли при компиляции макрос UNICODE, — на ANSI или на Unicode-строку

Кстати, на этот раз имя макроса UNICODE не предваряется знаком подчеркивания Дело в том, что макрос _UNICODE используется в заголовочных файлах библиотеки С, а макрос UNICODE — в заголовочных файлах Windows Для компиляции модулей исходного кода обычно приходится определять оба макроса.

Например, существует две функции CreateWindowEx: одна принимает строки в Umcode, другая — в ANSI, но прототипы этих функций чуть-чуть отличаются

HWND WINAPI CreateWindowExW(
DWORD dwExStyle,
PCWSTR pClassName,
PCWSTR pWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hHenu,
HINSTANCE hInstance,
PVOID pParam);

 

HWND WINAPI CreatcWindowExA(
DWORD dwExStyle,
PCSTR pClassName,
PCSTR pWindowName,
DWORD dwStyle,
int X
int Y,
int nWidth,
inT nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCF hInstance,
PVOID pParam);

 

Создание программ, способных использовать и ANSI, и Unicode

Главное, что для этого нужно:

· привыкайте к тому, что текстовые строки — это массивы символов, а не массивы байтов или значений типа char;

· используйте универсальные типы данных (вроде TCHAR или PTSTR) для текстовых символов и строк;

· используйте явные типы данных (вроде BYTE или PBYTE) для байтов, указателей на байты и буферов данных;

· применяйте макрос TEXT для определения символьных и строковых литералов;

· предусмотрите возможность глобальных замен (например, PSTR на PTSTR);

· модифицируйте логику строковой арифметики. Например, функции обычно принимают размер буфера в символах, а не в байтах Это значит, что вместо sizeof(szBuffer) Вы должны передавать (sizeof(szBuffer) / sizeof(TCHAR)). Но блок памяти для строки известной длины выделяется в байтах, а не символах, т. e. вместо malloc(nCharacters) нужно использовать malloc(nCbaracters *sizeof(TCHAR)).

В Windows есть набор функций для работы с Unicode-строками. Эти функции перечислены ниже.

Функция Описание
StringCchCat Выполняет конкатенацию строк
lstrcmp Сравнивает две строки с учетом регистра букв
lstrcmpi Сравнивает две строки без учета регистра букв
StringCchСopy Копирует строку в другой участок памяти
StringCchLength Возвращает длину строки в символах

Они реализованы как макросы, вызывающие либо Unicode-, либо ANSI-версию функции в зависимости от того, определен ли UNICODE при компиляции исходного модуля Например, если UNICODE не определен, StringCchCat раскрывается в StringCchCatA, определен — в StringCchCatW.

Строковые функции lstrcmp и lstrcmpi ведут себя не так, как их аналоги из библиотеки С (strcmp, strcmpi, wcscmp и wcscmpf), которые просто сравнивают кодовые позиции в символах строк. Игнорируя фактические символы, они сравнивают числовое значение каждого символа первой строки с числовым значением символа второй строки. Но lstrcmp и lstrcmpi реализованы через вызовы Windows-функции CompareString

Многие функции С-библиотеки с Unicode-строками толком не работают. Так, tolower и toupper неправильно преобразуют регистр букв со знаками ударения. Поэтому для Unicode-строк лучше использовать соответствующие Windows-функции. К тому же они корректно работают и с ANSI-строками.

2. Введение в WinAPI

Windows представляет собой систему в виде набора объектов, основным из которых является окно. В процессе работы Windows "общается" с каждым объектом посредством системных сообщений. При возникновении определенных событий (нажатие клавиши, перемещение мыши, истечение времени таймера) Windows сообщает об этом окну приложения, посылая ему соответствующее сообщение. Окно, после получения сообщения, должно обработать его и возвратить результат обратно в систему.

Каждое Windows-приложение построено на основе цикла обработки сообщений, который принимает эти сообщения и отправляет их к соответствующим функциям – обработчикам сообщений.

С точки зрения пользователя, окно - это прямоугольная область экрана, которую занимает каждая программа Windows. Одна программа может создать несколько окон, но всегда имеется одно окно верхнего уровня, которое называется “главным окном” приложения.

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

ОС Windows являются многозадачными и многопоточными. Они позволяют запускать несколько процессов (задач) в виде приложений, каждое из которых может состоять из одного или более потоков. Различные приложения и потоки делят между собой эти ограниченные ресурсы ПК, распределение которых осуществляет операционная оболочка Windows. Имеются специальные механизмы управления процессами и потоками, которые будут рассмотрены позже.

Типичное Win32-приложение состоит из одного или более потоков, которые выполняются параллельно (потоки можно понимать как многозадачность в рамках отдельного приложения, например, один поток обрабатывает данные, вводимые пользователем, в то время как другой поток занят передачей документа на принтер).

 

Win API

Win API (Application Programming Interface - интерфейс программирования приложений) - это набор функций разработанных фирмой Microsoft, позволяющих программисту создавать приложения для Windows. Win API является основой для каждой Windows-программы.

Для взаимодействия с Windows приложение запрашивает функции API, с помощью которых реализуются все необходимые системные действия, такие как выделение памяти, вывод на экран, создание окон и т.п.

Функции API содержатся в библиотеках динамической загрузки (Dynamic Link Libraries, или DLL), таких как Kernel32.dll/ Kernel64.dll, User32.dll/ User64.dll и Gdi32.dll/ Gdi64.dll и др. Kernel32.dll/ Kernel64.dll содержит API-функции, работающие с памятью и управляющие процессами. User32.dll/User64.dll управляет пользовательским интерфейсом программы. Gdi32.dll/ Gdi64.dll содержит графические функции.

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

2.1. Тема: Сообщения Windows. Типы сообщений

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

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

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

typedef struct tagMSG

{

HWND hwnd; // окно, которому посылается это сообщение

UINT message; // значение самого сообщение

WPARAM wParam; // для передачи дополнительной инф-и

LPARAM lParam; // для передачи дополнительной инф-и

DWORD time; // время, когда произошло событие

POINT pt; // точка, где произошло события (для мыши)

} MSG;

Типы данных в Windows

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

Основные типы данных, используемых в Win32 API приведены в таблице.

Обозначение типа Назначение типа
BOOL, BOOLEAN Булевый. Имеет только 2 значения: TRUE или FALSE
CHAR 8-битный символ (ANSI Windows)
BYTE 8-битное беззнаковое целое или символьное значение
WCHAR 16-битный символ (Unicode)
TCHAR CHAR или WCHAR (если используется Unicode)
USHORT, WORD Целое беззнаковое 16-битное число
DWORD, DWORD32, UINT Целое беззнаковое 32-битное число
DWORD64, UINT64, ULONGLONG Целое беззнаковое 64-битное число
FLOAT Число с плавающей точкой
SHORT Целое знаковое 16-битное число
INT, INT32, LONG, LONG32 Целое знаковое 32-битное число
INT64, LONG64, LONGLONG Целое знаковое 64-битное число
HANDLE 32-битное целое, используемое в качестве дескриптора
HWND 32-битное целое – дескриптор окна
LPSTR Длинный указатель на строку
LPCSTR Константный (const) указатель на строку

Соглашение об именах (Венгерская нотация)

При задании имен функциям и переменным в Windows-программах рекомендуется соблюдать ряд правил, называемых "Венгерская нотация" или соглашением об именах идентификаторов. Автором этого соглашения является д-р Чарльз Симонии, венгр по происхождению.

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

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

1. Мнемоническое значение: идентификатор должен легко запоминаться

2. Смысловое значение: роль идентификатора должена быть ясна из его названия

3. Преемственность: похожие объекты должны иметь похожие идентификаторы.

4. Скорость решения: задание, ввод и редактирование идентификатора не должны занимать слишком много времени, идентификатор не должен быть слишком длинным.

Для функций используются имена, построенные из глаголов и существительных, причем первые буквы этих слов — заглавные. Например, GetFreeDiskSpace – функция для получения объема свободного дискового пространства.

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

Префикс Назначение Тип в программе
g_ префикс для глобальной переменной  
l длинное целое со знаком long
p указатель *
lp дальний указатель far *
c символ, 1 байт char
b логическое значение BOOL
u целое без знака, 32 бита UINT
w 16-битное слово (2 байта) WORD, unsigned short
dw 32-битное слово (4 байта) DWORD, unsigned long
n, i целое со знаком, 32 бита int
fn функция  
sz ASCII строка char[]
psz ASCII строка char *
pcsz константная ASCII строка const char *
pv произвольный указатель void *
h дескриптор объекта, хендл HANDLE, void *

 

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

Для идентификаторов сообщений обычно используются символьные представления (WM_PAINT, WM_TIMER), а не числовые значения. Эти символьные значения определены в стандартных файлах заголовков Windows (приложению необходимо включать в свой исходный текст только файл windows.h – он содержит директивы #include для остальных файлов). В среде Visual C++ в приложение необходимо включать заголовочный файл stdafx.h, который содержит включения всех стандартных заголовочных файл, в т.ч. и windows.h

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

· сообщения DDE (dynamic data exchange),

· сообщения буфера обмена (clipboard),

· сообщения мыши,

· сообщения клавиатуры,

· сообщения неклиентской (non-client) области окна,

· сообщения MDI (multiple-document interface),

· другие типы.

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

Приведем обзор наиболее часто обрабатываемых сообщений:

· WM_CREATE - это первое сообщение, которое получает оконная процедура созданного класса. Оно посылается перед тем, как окно станет видимым, и перед завершением функций CreateWindow или CreatWindowEx. В ответ на это сообщение приложение может выполнить необходимые функции инициализации перед тем, как окно станет видимым.

· WM_DESTROY - посылается оконной процедуре окна, которое уже удалено с экрана и должно быть разрушено.

· WM_CLOSE - указывает, что окно должно быть закрыто. Обработчик по умолчанию в функции DefWindowProc при получении этого сообщения вызывает DestroyWindow. Приложение может, например, вывести диалоговое окно подтверждения и вызвать DestroyWindow только в случае подтверждения пользователем закрытия окна.

· WM_QUIT - это обычно последнее сообщение, которое получает основное окно приложения. Получение этого сообщения приводит к возврату нулевого значения функцией GetMessage, что в свою очередь приводит к завершению цикла сообщений большинства приложений. Это сообщение требует завершить приложение. Оно генерируется в ответ на вызов функции PostQuitMessage.

· WM_LBUTTONDOWN -одиночное нажатие левой кнопки мыши

· WM_RBUTTONDOWN одиночное нажатие правой кнопки мыши

· WM_LBUTTONDBLCLK -двойной щелчок мышьюлевой кнопкой мыши

· WM_RBUTTONDBLCLK -двойной щелчок мышьюправой кнопкой мыши

· WM_QUERYENDSESSION - уведомляет приложение о намерении Windows закончить сеанс. Приложение может возвратить значение FALSE в ответе на это сообщение, предотвратив этим выключение Windows. После обработки сообщения WM_QUERYENDSESSION Windows посылает всем приложениям сообщение WM_ENDSESSION с результатами этой обработки.

· WM_ENDSESSION - посылается приложениям после обработки сообщения WM_QUERYENDSESSION. Оно указывает, должна ли Windows выключиться, или выключение отложено. При указании выключения сеанс Windows может закончиться в любое время после обработки сообщения WM_ENDSESSION всеми приложениями. Поэтому важно, чтобы приложения выполнили все задачи по обеспечению безопасного завершения работы.

· WM_ACTIVATE - указывает, что окно верхнего уровня будет активизировано или деактивизировано. Сообщение сначала посылается окну, которое должно быть деактивизировано, а потом окну, которое должно быть активизировано.

· WM_SHOWWINDOW - указывает, что окно должно быть скрыто или отображено. Окно может быть скрыто в результате вызова функции ShowWindow или в результате максимизации другого окна.

· WM_ENABLE – посылается окну, когда оно становится доступным или недоступным. Это может произойти после вызова функции EnableWindow. Недоступное окно не может принимать вводимые данные от мыши или клавиатуры.

· WM_MOVE – указывает, что расположение окна изменилось.

· WM_SIZE – указывает,что размер окна был изменен.

· WM_SETFOCUS – указывает получение окном фокуса клавиатуры.

· WM_KILLFOCUS – указывает, что окно должно потерять фокус клавиатуры.

· WM_GETTEXT – посылается окну, запрашивая копирование текста окна в буфер. Для большинства окон текстом является их заголовок. Для элементов управления типа кнопок и т.д. текстом окна является текст, отображаемый в этих элементах. Обычно это сообщение обрабатывается функцией DefWindowProc.

· WM_SETTEXT – запрашивает установку текста окна из содержимого буфера. Функция DefWindowProc в ответ на это сообщение устанавливает текст окна и соответственно его отображает.

 

 

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

· Первый способ пригоден только для случая, если сообщение пересылается между окнами (частями) одного и того же приложения. Для этого необходимо определить символическое имя нового сообщения при помощи директивы #define, например:

#define СимволичИмяОдногоСообщения (WM_USER +1)

#define СимволичИмяДругогоСообщения (WM_USER +2)

 

Вторым способом определения собственного сообщения является использование функции RegisterWindowMessage, которая возвращает уникальный идентификатор для сообщения. Использование собственных типов сообщений, полученных таким способом, позволяет частям приложения связываться между собой; разные приложения также могут обмениваться информацией таким способом. Однако для взаимодействия приложений доступны более мощные механизмы, например, отображаемые в память файлы.

 

Тема: Классы и стили окон

 

Основное поведение окна определяется классом окон. Класс окна (он не является классом языка программирования C++) несет информацию о начальном внешнем виде окна, пиктограмме по умолчанию, курсоре и ресурсе меню, связанном с окном; и – об адресе функции, называемой оконной процедурой.

Набор используемых ресурсов класса окна задают в структуре типа WNDCLASS. Эта структура описана следующим образом:

typedef struct

{ UINT style;

WNDPROC lpfnWndProc;

int cbClsExtra;

int cbWndExtra;

HANDLE hInstance;

HICON hlcon;

HCURSOR hCursor;

HBRUSH hbrBackground;

LPCTSTR lpszMenuName;

LPCTSTR lpszClassName;
} WNDCLASS;

 

Например, если описана структура для класса окна

WNDCLASS wc;

затем присваивают определенные значения ее полям.

 

Назначение полей этой структуры:

1. style определяет стиль класса окна и поведение окна, например:
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

2. lpfnWndProc указывает на функцию окна. Она будет рассмотрена позже.

3. cbClsExtra равно количеству дополнительных байтов класса.

4. cbWndExtra равно количеству дополнительных байтов окна этого класса.

5. hlnstance указывает на дескриптор текущего приложения.

6. hlcon указывает на имя пиктограммы (иконки), в которую превращается окно при минимизации.

7. hCursor задает вид курсора мыши при его прохождении над окном.

8. hbrBackground задает дескриптор кисти закрашивания фона окна.
9. lpszMenuName указывает на имя ресурса главного меню окон этого класса. Если задать NULL, окна этого класса не имеют заданного по умолчанию меню. Например: we.lpszMenuName = (LPCTSTR)NULL;

10. lpszClassName указывает на текстовую строку, содержащую имя ре­гистрируемого класса окон, например:

wc.lpszClassName = szName;

 

Стиль класса окна

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

Чаще всего используются стиль CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS. Если для класса заданы стили CS_HREDRAW и CS_VREDRAW, то при изменении размеров окна функция окна может получить сообщение WM_PAINT. В этом случае функция окна должна перерисовать часть окна или все окно.

Стиль CS_DBLCLKS используется при необходимости отслеживать двойные щелчки мышью. При этом в функцию окна посылаются сообщения WM_LBUTTONDBLCLK и WM_RBUTTONDBLCLK. Если этот стиль не будет задан, функция окна получит только идущие парами сообщения об одиночном нажатии клавиш мыши WM_LBUTTONDOWN и WM_RBUTTONDOWN.

Стили окон, окна основных стилей

Определенный в классе окна стиль класса окна используется при создании всех окон на базе этого класса. Для дальнейшего уточнения внешнего вида и поведения окна используется другая характеристика - стиль окна. Стиль окна указывается при создании окна функцией CreateWindow. Для определения стиля окна используются символические константы с префиксом WS_.

Рассмотрим чаще всего используемые основные стили:

- перекрывающиеся окна (overlapped window),

- всплывающие (или временные, или выпадающие) окна (pop-up window),

- дочерние окна (child window).

Перекрывающиеся окна

Перекрывающиеся окна имеют заголовок (title bar), рамку и внутреннюю часть окна (client region). Дополнительно перекрывающиеся окна могут иметь системное меню, кнопки для максимального увеличения размера окна и для свертки окна в пиктограмму, вертикальную и горизонтальную полосу просмотра и меню.

Перекрывающиеся окна обычно используются в качестве главного окна приложения.

Для определения стиля перекрывающегося окна существует символическая константа WS_OVERLAPPEDWINDOW, определенная как поразрядное ИЛИ нескольких констант:

#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED|WS_CAPTION|

WS_SYSMENU|WS_THICKFRAME|

WS_MINIMIZEBOX|WS_MAXIMIZEBOX)

Приложение Windows может создавать несколько перекрывающихся окон, связанных между собой “узами родства” и “отношениями собственности”. При создании окон при помощи функции CreateWindow в качестве восьмого параметра функции можно указать дескриптор окна-владельца (переменная типа HWND). Окно-владелец уже должно существовать на момент создания окна, имеющего владельца.

Основные особенности перекрывающихся окон:

· Если окно-хозяин сворачивается в пиктограмму, все окна, которыми оно владеет, становятся невидимыми.

· Если сначала свернули в пиктограмму окно, которым владеет другое окно, а затем и окно-хозяина, то пиктограмма подчиненного окна исчезнет.

· При уничтожении окна-владельца автоматически уничтожаются и все принадлежащие ему окна.

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

· Координаты создаваемых функцией CreateWindow перекрывающихся окон указываются по отношению ко всему экрану, т.е. при создании окна с координатами (0,0), оно будет расположено в верхнем левом углу экрана.

· При изменении размеров перекрывающегося окна функция окна получает сообщение WM_SIZE, в параметрах которого указаны новые размеры окна.

Временные окна

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

Часто для создания выпадающих окон, имеющих рамку, используется стиль WS_POPUPWINDOW, определенный как поразрядное ИЛИ нескольких констант (для того чтобы к временному окну добавить системное меню и заголовок, следует использовать комбинацию WS_POPUPWINDOW | WS_CAPTION):

#define WS_POPUPWINDOW (WS_POPUP|WS_BORDER|WS_SYSMENU)

Перечислим особенности временных окон.

· Временные окна могут иметь окно-владельца и могут сами владеть другими окнами. Замечания относительно владения перекрывающимися окнами, справедливы и для временных окон.

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

· При изменении размеров временного окна функция окна получает сообщение WM_SIZE, в параметрах которого указаны новые размеры окна.

Дочерние окна

Дочерние окна чаще всего используются приложениями Windows. Эти окна нужны для создания органов управления, таких, как кнопки или списки. Все органы управления - дочерние окна.

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

Особенности дочерних окон следующие:

· Дочерние окна должны иметь окно-родителя. Только дочерние окна могут иметь родителей, перекрывающиеся и временные окна могут иметь окно-хозяина, но не родителя. У дочерних окон могут быть “братья” (или “сестры”).

· Дочерние окна всегда располагаются на поверхности окна-родителя.

· При создании дочернего окна начало системы координат расположено в левом верхнем углу внутренней поверхности окна-родителя (но не в верхнем углу экрана, как для перекрывающихся и временных окон).

· Так как дочернее окно как бы “прилипает” к поверхности окна-родителя, то при щелчке мышью над поверхностью дочернего окна, сообщение от мыши попадет в функцию дочернего, а не родительского окна.

· При создании дочернего окна в качестве девятого параметра (вместо идентификатора меню, которого не может быть у дочернего окна) функции CreateWindow необходимо указать идентификатор дочернего окна (переменная типа int, любое целое число).

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

· Дочернее окно “прилипает” к поверхности родительского окна и перемещается вместе с ним. Оно никогда не может выйти за пределы родительского окна.

· Все дочерние окна скрываются при сворачивании окна-родителя в пиктограмму и появляются вновь при восстановлении родительского окна.

· При изменении размеров родительского окна дочерние окна получаютсообщение WM_PAINT, но не получают сообщения WM_SIZE, это сообщение попадает только в родительское окно.

Примеры создания окон различных стилей

Ниже приведе фрагмент функции WinMain, создающей окна разных стилей на основе двух классов окон:

// регистрация классов окон с именами "MainWindow”, "Window1", "Window2"

...

// создание главного перекрывающегося окна

HWND hWndMain = CreateWindow("MainWindow", "OVERLAPPEDWINDOW",

WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance,NULL);

if(hWndMain == 0) return FALSE;

ShowWindow(hWndMain, nCmdShow);

UpdateWindow(hWndMain);

 

// создание временного окна

HWND hWndPopup = CreateWindow("Window1","POPUPWINDOW",

WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX|

WS_MAXIMIZEBOX|WS_VISIBLE,100,100,300,300,

hWndMain,NULL,hInstance,NULL);

if(hWndPopup == 0) { DestroyWindow(hWndMain); return FALSE; }

ShowWindow(hWndPopup, nCmdShow);

UpdateWindow(hWndPopup);

 

// создание дочернего окна

HWND hWndChild = CreateWindow("Window2","CHILDWINDOW",

WS_CHILDWINDOW|WS_CAPTION|WS_MINIMIZEBOX|

WS_MAXIMIZEBOX, 150,150,250,250, hWndMain, NULL,

hInstance,NULL);

if(hWndChild== 0)

{ DestroyWindow(hWndMain);

DestroyWindow(hWndPopup);

return FALSE;

}

ShowWindow(hWndChild, nCmdShow);

UpdateWindow(hWndChild);

 

// цикл обработки очереди сообщений

...

 

 

Тема: Общая структура Windows-приложения

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

Любая программа под Windows состоит минимум из двух функций - WinMain() и оконной функции.
Функция WinMain() должна выполнять следующие операции:

1. Определять класс окна

2. Регистрировать класс окна

3. Поиск уже запущенной копии приложения

4. Создавать окно данного класса

5. Отображать окно

6. Запускать цикл обработки сообщений

Оконная функция предназначена для обработки сообщений, относящихся к данному окну

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

// --- Обязательный включаемый файл

#include "stdafx.h"

// --- Прототип функции главного окна

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// --- Объявление глобальных переменных

HINSTANCE hInst; // Дескриптор экземпляра приложения

char ClassName[]="Window"; // Название класса окна

char AppTitle[]="Application Win32"; // Заголовок главн окна

// --- Главная функция приложения WinMain

int APIENTRY _tWinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

WNDCLASS wc; // Структура для инф-ции о классе окна

HWND hWnd; // Дескриптор главного окна приложения

MSG msg; // Структура для хранения сообщения

// --- Проверяем, было ли приложение запущено ранее.

if((hWnd=FindWindow(ClassName, NULL))!=NULL)

{

// Если прилож. было запущено ранее, активизировать

// и выдвинуть на передний план его главное окно

if(IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE);

SetForegroundWindow(hWnd);

// Работа новой копии прекращается.

return FALSE;

}

// Заполнени

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...