Здавалка
Главная | Обратная связь

Обработка сообщений WM_PAINT.



Разделение дисплея между прикладными программами осуществляется с помощью окон. Видимая площадь окна может изменятся, это требует постоянного контроля за отображаемой в окне информацией и своевременного восстановления утраченных частей изображения. ОС не хранит графическую копию каждого окна. Она возлагает ответственность за правильное отображения окна на прикладную программу, посылая ей WM_PAINT каждый раз, когда все окно или его часть требует перерисовки. При операциях с окнами система помечает разрушенные части окна, как подлежащие обновлению и помещает информацию о них, в специальную область: область обновления UPDATE REGION. На основании содержимого этой области и происходит восстановление. ОС посылает окну сообщение WM_PAINT всякий раз, когда область обновления окна оказывается не пустой и при условии, что в очереди сообщений приложения нет ни одного сообщения. При получении сообщения WM_PAINT окно должно перерисовать лишь свою внутреннюю часть, называемую рабочей областью (Client Area). Все остальные области окна перерисовывает ОС по WM_NCPAINT.

Цвета

RGB –формат. Для кодирования цвета используются переменные с типом данных COLORREF, который определен через тип данных UINT.

Позволяет иметь более 16 миллионов оттенков. Далеко не все графические устройства поддерживают такое количество. Если программа устанавливает цвет, который данное устройство воспроизвести не может ОС заменяет этот цвет на ближайший из числа доступных. COLOREF GetNearestColor(HDC, COLORREF). HDC поддерживает понятие фона и фонового цвета. Некоторые функции могут осуществлять предварительную заливку области фоновым цветом (функции вывода текста). Установка фонового цвета SetBkColor(…), получение GetBkColor().

Инструменты для рисования в контексте устройства

Контекст устройства – это объект, в котором существует инструмент для рисования (перо, кисть, шрифт, поверхность рисования (холст), параметры задающие режимы рисования, палитра цветов). При рисовании графического примитива используются сразу все инструменты (прямоугольник рисуется следующим образом: пером рисуется контур, толщина и цвет и вид линии определяется пером; внутреннее пространство фигуры заполняется кистью, цвет и стиль заполнения определяется кистью. Палитра используется не явно. В контексте устройства всегда существует 1 кисть, 1 перо, 1 шрифт, 1 палитра, 1 область отображения. Для того чтобы изменить способ рисования графической фигуры (например вид контура) необходимо:

1. Создать новый инструмент для рисования (для нашего примера перо)

2. Заменить этот инструмент в контексте устройства, сохранив дескриптор старого инструмента

3. Выполнить рисование графической фигуры

4. Восстановить в контексте устройства старый инструмент

5. Удалить созданный

Логические шрифтыШрифт – множество символов, имеющее множество размеров и начертание контуров. По умолчанию в контексте устройства установлен системный шрифт (как и любой другой рисования его можно заменить на другой). Список доступных шрифтов можно посмотреть в Панели Управления -> Шрифты. При создании шрифта задаем параметры, которые хотим получить. ОС возвращает наиболее подходящий шрифт из числа доступных. Существуют пропорциональные и непропорциональные шрифты. Шрифт который мы создаем – логический. Физический шрифт – это в каталоге Fonts. И ОС на базе физического создает необходимый нам логический. Существуют 2 типа шрифтов:· Растровые (масштабируемые шрифты True Type)· Векторные (в чистом виде в Win таких нету)

Масштабируемые шрифты True Type описываются сплайнами 3 порядка. PostScript – описываются сплайнами 2ого порядка. УЗНАТЬ ПРЕИМУЩЕСТВА. 3го порядка сплайны позволяют более тонко управлять шрифтом. 2ая производная там классная и при работе с графикой имеются некоторые преимущества. PostScript – быстрее.

Режим масштабирования (отображения)

При пересчете Windows осуществляет пересчет логической точки (LP) из логического пространства координат, в физическую точку из физической системы координат (DP). Это делается за 3 шага:

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

2. Масштабирование полученного изображения путем масштабирования заданной точки (умножением на заданный коэффициент). Изображение переносится на физическую плоскость.

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

Метафайлы

Одной из форм хранения графической информации является метафайл. Изображение, записанное в метафайл, представляет собой не точечный рисунок, а набор команд GDI последовательное выполнение которых позволяет воспроизвести изображение. Физически: набор записей переменной длины (вначале код команды, затем значения параметров этой команды). Последовательность:

1. Создать метафайл HANDLE CreateMetaFile(LPCTSTR). В параметры – имя файла, если NULL – то он создается в памяти. Функция возвращает дескриптор, связанного с метафайлом контекста устройства.

2. Вывести полученный контекст устройства текст и графику. Программа просто вызывает функции GDI.

3. Закрыть с помощью функции HANDLE CloseMetaFile(HANDLE). Возвращает метафайловый дескриптор, который может использоваться для проигрывания содержимого метафайла в другом контексте устройства.

4. Удаление метафайла, когда он становится не нужным BOOL DeleteMetaFile(HANDLE). Принимает метафайловый дескриптор.

5. Расширение метафайла.

a. Создать с помощью CreateMetafile контекст устройства

b. Воспроизвести в нем уже существующий метафайл PlayMetaFile

c. Вывести в метафайловый контекст устройства дополнительную информацию

d. Закрыть метафайловый контекст устройства CloseMetafile.

ОС поддерживает 2 вида метафайлов:

1. Обычный *.wmf (не поддерживаются многие графические примитивы)

2. Enhanced Metafile *.emf (можно выводить почти все)

Растровая графика

В ОС существует 3 стандартных типа растровых изображений: icons (значок, пиктограмма), cursors (курсор, указатель), bitmaps(точечный рисунок).

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

a. AND-mask. Монохромная.

b. XOR-mask. Цветная.

При выводе значков ОС комбинирует маски по следующему правилу:

Экран=(экран AND AND-mask) XOR XOR-mask

Накладывая AND-mask, ОС вырезает на экране пустую область с заданным контуром. В AND-mask фигура кодируется с помощью 0, а прозрачный фон с помощью 1. После вывода AND-mask ОС накладывает XOR-mask, содержащую изображения фигур. Изображение фигуры является цветным. На диске *.ico. В ОС существует несколько форматов значков, которые отличаются по размеру и цвету (16х16, 32х32, 16х32, 64х64).

Курсоры. Указатели мыши. Небольшой образ. По своему представлению в файле и памяти курсор напоминает значки, но существуют некоторые значки. Курсоры могут быть размером 16х16 и 32х32. Важным существенным отличием является наличие в нем горячей точки (hot spot), которая ассоциируется с позицией указателя мыши на экране. *.CUR.

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

· Аппаратно-зависимые. Device Dependent Bitmpap. Рассчитаны только на определенный тип графического адаптера или принтера. Их точки находятся в прямом соответствии с пикселями экрана или другой поверхности отображения.

· Аппаратно-независимые. Device Independent Bitmpap. Формат хранения аппаратно-независимых точечных рисунков не зависит от используемой аппаратуры. Здесь информация о цвете и самом изображении хранится раздельно.

Вывод точечных рисунков на экран.. LoadIcon(), LoadCursor(), LoadBitmap() – не загружают из файла. Из файла загружает LoadImage(). В результате загрузки ОС возвращает дескриптор созданного в памяти объекта. После использования объект должен быть удален. DeleteObject(HANDLE). Вывод точечного рисунка предполагает использование двух контекстов устройства (физического и виртуального (временного)). В ОС не существует функций обеспечивающей вывод точечного рисунка по дескриптору. Алгоритм вывода:

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

2. С помощью стандартной функции ОС BitBlt, StretchBlt, StretchDIBits перенести часть поверхности отображения из виртуального контекста устройства на поверхность отображения физического контекста устройства. В ходе переноса возможно масштабирование изображения.

Растровая операция – способ комбинирования пикселей исходного изображения с пикселями поверхности отображения целевого контекста устройства. При масштабировании в сторону сжатия некоторые цвета могут пропадать. При растяжение то проблем не существует. При сжатии возможно 3 способа сжатия. Ресурсы программы. Ресурсы ОС – специальный тип данных, предназначенный для представления и использования в прикладных программах стандартных элементов пользовательских интерфейсов. Стандартные типы ресурсов Windows: Menu. Accelerator. Icon. Cursor. Bitmap. String Table. Dialog Box. Font. Version Info. Программист может создавать свои собственные типы ресурсов. Ресурсы – отдельны от кода и данных. Ресурсы обладают свойством разделяемости. Несколько программ могут использовать копию одного ресурса. Загрузка ресурса из внешнего ехе файла выполняется с помощьюHGLOBAL LoadResource( HMODULE hModule, // module handle HRSRC hResInfo // resource handle);Динамически подключаемые библиотеки DLL представляет собой дополняемый модуль ОС (обычно DLL), код и ресурсы которого могут использоваться в составе других динамических библиотек и приложений. DLL – программа с множеством точек входа. В отличие от статической библиотеки, которая включается в выполняемый exe модуль на этапе сборки, динамическая библиотека собирается в виде отдельно выполняемого модуля. Использование динамической библиотеки выполняется одним из двух способов:· Статического импорта· Динамического импорта Для создания DLL в разных языках используются разные средства. В C++:_declspec(dllexport) int Min(int X, int Y);

При статическом импорте подключение DLL осуществляется наподобие обычных библиотек. Разница лишь в описании внешней функции. В C++: __declspec(dllimport) int Min(int X, int Y). Такого описания функции в исходном тексте функции не достаточно. Система требует подключения так называемой библиотеки импорта (lib-файла) при компоновке программы. Библиотека импорта создается системой Visual C автоматически при компиляции DLL. При подключении DLL необходимо знать еще один важный параметр – соглашение о вызове подпрограмм. Существуют следующие соглашения о вызове подпрограмм в ОС Windows:

· __cdecl. Параметры передаются на стек в обратном порядке. За освобождение стека после вызова подпрограммы отвечает вызывающая программа.

· __pascal. Передача параметров на стек в прямом порядке. Освобождение стека осуществляет сама вызванная подпрограмма.

· __stdcall. Соглашение для стандартных DLL Windows. Передача параметров на стек происходит в обратном порядке. Освобождение стека выполняет вызванная подпрограмма.

· __register. Передача параметров преимущественно через регистры процессора. Это не используется при создании DLL (это не стандартизировано).

Соглашение о вызове должно записываться в прототипе функции.

__declspec(dllexport) int __cdecl Min(int X, int Y);

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

HANDLE LoadLibrary(LPCSTR libFileName)

Имя файла отыскивается на диске в следующей последовательности:

1. Текущий каталог

2. Каталог системы Windows

3. Системный каталог Windows (system32)

4. В каталоге, содержащем исполняемый файл программы, вызвавшей функцию LoadLibrary

5. Во всех каталогах перечисленных в переменной среды PATH

6. В списке сетевых каталогов

После завершения работы с DLL вызывается void FreeLibrary(HANDLE); Функция void* GetProcAddress(HANDLE,LPCSTR); По имени функции или ее номеру. Ответственность за правильность вызова лежит на программисте.

Функция Входа/Выхода

DLL может иметь НЕОБЯЗАТЕЛЬНУЮ функцию BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpImpload), которая вызывается системой Windows автоматически в 4х случаях. hInst – дескриптор загружаемого модуля, который равен адресу, с которого DLL проецируется в память. dwReason – причина вызова функции (одна из 4х причин). lpImpload - показывает, как DLL загружается в память (методом неявной загрузки – статический импорт, или методом явной загрузки – динамический импорт). 4 причины вызова:

1. DLL_PROCESS_ATTACH – при первой загрузке DLL каким-либо потоком

2. DLL_THREAD_ATTACH – подключение потока. Когда происходит создание нового потока, который использует DLL. Это вызывается для каждого создаваемого потока. Для главного потока не вызывается.

3. DLL_THREAD_DETACH - при завершении потока с помощью функции ExitThread.

4. DLL_PROCESS_DETACH – при завершении процесса, если завершение потока включает завершение процесса. Если завершение процесса выполняется с помощью ExitProcess.

Вызов Exit… приводит к упорядоченному завершению.

Terminate… - просто вырубает поток, и могут не освободиться ресурсы (TerminateThread).

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

Экспорт и импорт данных

Вместо использования стандартных директив компилятора С++:

__declspec(dllexport)

__declspec(dllimport)

существует возможность альтернативного создания DLL с помощью ключевого слова extern. Его использование требует включение в проект DEF-файла. Этот способ в Win C++ считается устаревшим, т.к. не позволяет экспортировать/импортировать данные. При использовании нового способа данные экспортировать можно (как и функции):

__declspec(dllexport) int y;

__declspec(dllimport) int x;

Рекомендуется избегать экспорта/импорта данных (этот подход является непереносимым с платформы на платформу).

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

Расширение системы GDI

В Win2000/XP существует расширение системы GDI (GDIX). GDIX обеспечивает создание и использование мультимедийных окон. Технология называется BuiltInMultimedia (BIM). Для создания окна с поддержкой мультимедиа: HANDLE CreateBIMBox(<параметры CreateWindow>, + параметры описывающие мультимедийность DWORD AlphaBlend, int alpha, int beta, int gamma); Эти параметры обеспечивают работу с 3D графикой. void DeleteBIMBox (HANDLE); При использовании GDIX код ошибки можно получить с помощью вызова функций GetLastBIMBoxError().

Описание меню

Наиболее очевидным средством управления приложением является меню. Строкаа меню выводится на экран непосредственно под строкой заголовка. Это меню называется главным. Выбор элемента меню влечет за собой выдачу приложения сообщения WD_COMMAND, содержащего идентификатор пункта меню. Идентификаторы анализируются в оконной процедуре приложения, что обеспечивает соответствующую реакцию на полученное сообщение. Каждый пунк меню определяется тремя характеристиками. Первая определяет то, что будет отображаться в данном пункте меню – это либо строка текста, либо картинка. Вторая характеристика определяет либо константу, посылаемую оконной процедуре сообщении WM_COMMAND, либо всплывающее меню, которое выводится на экран, когда пользователь выбирает данный пункт меню. Третья характеристика указывает, является ли данный пункт меню разрешенным (enabled), запрешенным (disabled), недоступным (grayed) или помеченным (checked). Эта характеристика пункта меню не является обязательной.

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

· разработать сценарий меню. Перед тем как приступить к процессу включения меню в конкретное приложение, разработаем логическую схему. Этот шаг необходим для того, чтобы уже на стадии проектирования обеспечить эргономические свойства приложения. Ведь меню – это один из немногих элементов интерфейса, с которым пользователь постоянно будет иметь дело. Поэтому схема меню должна иметь наглядную иерархическую структуру, с логически увязанными между собой пунктами этой иерархии, что поможет пользователю эффективно использовать все возможности приложения. Для того, чтобы вести предметный разговор, поставим себе задачу разработать для окна нашего приложения главное меню. При этом мы исследуем возможности вывода в окно приложения текста и графики, а также покажем способы решения общих проблем, связанных с разработкой приложения. Наше меню достаточно простое и состоит из трех элементов: “Текст”,”Графика”,”О приложении”.

Меню можно создать тремя способами. Можно определить меню в файле описания ресурсов, создать меню без файла описания ресурсов непосредственно в программе с помощью функций CreatMenu, AppendMenu и InsertMenu или с помощью функции LoadMenuIndirect, создав предварительно структуру MENUITEMPLATE. Наиболее простым и понятным при программировании под Windows95 на языке ассемблера является определение меню в файле описания ресурсов с помощью любого текстового редактора.

Диалоговые окна

Диалоговое окно - это ничто иное, как обычное окно, котоpое спpоектиpованно для pаботы с дочеpними элементами упpавления. Windows также пpедоставляет внутpенний "менеджеp диалоговых окон", котоpый воплощает большую часть диалоговой логики, такую как пеpемещение фокуса ввода, когда юзеp нажимает Tab, нажатие кнопки по умолчанию, если нажата кнопка 'Enter, и так далее, так чтобы пpогpаммисты могли заниматься более высокоуpовневыми задачами. Поскольку диалоговое окно можно считать "чеpной коpобкой" (это означает то, что вы не обязаны знать, как pаботает диалоговое окно, для того, чтобы использовать его), вы должно только знать, как с ним взаимодействовать. Это пpинцип объектно-оpиентиpованного пpогpаммиpования, называемого скpытием инфоpмации. Если чеpная коpобка спpоетиpованна совеpшенно, пользователь может использовать ее не зная, как она pаботает. Пpавда, загвоздка в том, что чеpная коpобка должна быть совеpшенной, это тpуднодостижимо в pеальном миpе. Win32 API также спpоектиpован как чеpная коpобка.

Ладно, похоже, что мы немного отклонились. Давайте веpнемся к нашему сюжету. Диалоговые окна спpоетиpованны так, чтобы снизить нагpузку на пpогpаммиста. Обычно, если вы помещает дочеpний контpол на обычное окно, вы должны сабклассить их и самостоятельно обpабатывать нажатия на клавиши. Hо если вы помещате их на диалоговое окно, оно обpаботает их за вас. Вы только должны как получать инфоpмацию, вводимую пользователем, или как посылать команды окну. Диалоговое окно опpеделяется как pесуpс (похожим обpазом, как и меню). Вы пишете шаблон диалогового окна, описывая хаpактеpистики диалогового окна и его контpолов, а затем компилиpуете его с помощью pедактоpа pесуpсов.

Обpатите внимание, что все pесуpсы pасполагаются в одной скpипте pесуpсов. Вы можете использовать любой текстовый pедактоp, чтобы написать шаблон диалогового окна, но я бы не pекомендовал это. Вы должны использовать pедактоp pесуpсов, чтобы сделать визуально pасположить дочеpние окна. Существует несколько пpекpасных pедактоpов pесуpсов. К большинству из основных компилятоpов пpилагаются подобные pедактоpы. Вы можете использовать их, чтобы создать скpипт pесуpса. После этого стоит выpезать лишние линии, напpимеp, те, котоpые относятся к MFC.

Есть два основных вида диалоговых окон: модальные и независимые. Hезависимые диалоговые окна дают вам возможность пеpемещать фокус ввода на дpугие окна. Пpимеp - диалоговое окно 'Find' в MS Word. Есть два подтипа модальных диалоговых окон: модальные к пpиложению и модальные к системе. Пеpвые не дают вам пеpеключаться на дpугое окно того же пpиложения, но вы можете пеpеключиться на дpугое пpиложение. Втоpые не дают вам возможности пеpеключиться на любое дpугое окно.

Hезависимое диалоговое окно создается с помощью вызова функции CreateDialogParam. Модальное диалоговое окно создается вызовом DialogBoxParam. Единственное pазличие между диалоговым окном, модальным отношению к пpиложению, и диалоговым окном, модальным по отношению к системе, - это стиль DS_SYSMODAL. Если вы включите стиль DS_SYSMODAL в шаблон диалогового окна, это диалоговое окно будет модальным к системе.

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

SendDlgItemMessage proto hwndDlg:DWORD,\

idControl:DWORD,\

uMsg:DWORD,\

wParam:DWORD,\

lParam:DWORD

Эта API-функция неоценимо полезна пpи взаимодействии с дочеpним окном. Hапpимеp, если вы хотите получить текст с контpола edit, вы можете сделать следующее:

call SendDlgItemMessage, hDlg, ID_EDITBOX, WM_GETTEXT, 256, ADDR text_buffer

Чтобы знать, какое сообщение когда посылать, вы должны пpоконсультиpоваться с вашим Win32 API-спpавочником.

Windows также пpедоставляет несколько специальных API-функций, заточенных под дочеpние окна, для быстpого получения и установки нужных данных, напpимеp, GetDlgItemText, CheckDlgButton и т.д. Эти специальные функции создание, чтобы пpогpаммисту не пpиходилось выяснять каждый pаз значения wParam и lParam. Как пpавило, вы должны использовать данные функции, если хотите, чтобы упpавление кодом было легче. Используйте SendDlgItemMessage только, если нет соответствующей API-функции. Менеджеp диалоговых окон посылает некотоpые сообщения специальной callback-функции, называемой пpоцедуpой диалогового окна, котоpая имеет следующий фоpмат:

DlgProc proto hDlg:DWORD ,\

iMsg:DWORD ,\

wParam:DWORD ,\

lParam:DWORD

Пpоцедpа диалогового окна очень похожа на пpоцедуpу окна, если не считать тип возpащаемого значения - TRUE/FALSE, вместо обычных LRESULT. Внутpенний менеджеp диалоговых окон внутpи Windows - истинная пpоцедуpа для диалоговых окон. Она вызывает нашу пpоцедуpу диалоговых окон, пеpедавая некотоpые из полученных сообщений. Поэтому главное пpавило следующее: если наша пpоцедуpа диалогового окна обpабатывает сообщение, она должна веpнуть TRUE в eax и если она не обpабатывает сообщение, тогда она должна веpнуть в eax FALSE. Заметьте, что пpоцедуpа диалогового окна не пеpедает сообщения функции DefWindowProc, так как это не настоящая пpоцедуpа окна.

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

"Использование диалогового окна как основное окно" можно понимать двумя обpазами.

· Вы можете использовать шаблоно диалогового окна как шаблон класса, котоpый вы pегистpиpуете с помощью функции RegisterClassEx. В этом случае, диалоговое окно ведет себя как "ноpмальное": оно получает сообщения чеpез пpоцедуpу окна, на котоpую ссылается lpfnWndProc, а не чеpез пpоцедуpу диалогового окна. Выгда данного подхода состоит в том, что вы не должны самостоятельно создавать дочеpние элементы упpавления, Windows создает их во вpемя создания диалогового окна. Также Windows беpет на себя логику нажатий на клавиши (Tab и т.д.). Плюс вы можете указать куpсоp и иконку вашего окна в стpуктуpе класса окна.

· Ваша пpогpамма создает диалоговое окно без создания pодительского окна. Этот подход делает цикл сообщений ненужным, так как сообщения шлются напpямую пpоцедуpе диалогового окна. Вам даже не нужно pегистpиpовать класс окна!

Редакторы ресурсов

Как открыть .DLL или .EXE файл в редакторе ресурсов

При помощи Resource Tuner вы можете открывать исполняемые файлы, такие как .EXE, .DLL, .OCX, скринсейверы (.SCR) и многие другие. Открыв файл, вы получаете доступ к ресурсам файла и можете заменять иконы, курсоры и графику в различных форматах, изменять строчки в меню, диалоговых окнах и других элементах пользовательского интерфейса.

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

Для более серьёзных изменений (которые, впрочем, ни к чему хорошему не приведут без достаточного опыта в программировании приложений для Windows) рекомендуем использовать PE Explorer (редактор структуры PE файлов) или FlexHex (хекс-редактор для бинарных файлов).







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.