|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||
| 06.01.2013, 07:55 [ТС] | ||||||
|
Win32 API. Урок 7c. Фокусы с иконкой и курсором В качестве курсора и иконки используем иконку из файла Cursor.cur. Убеждаемся, что разницы между курсором и иконкой нет.(часть первая) Скачайте пример здесь. ПРАКТИКА, СЕСТРА ШИЗОФРЕНИИ
Кликните здесь для просмотра всего текста
________________________________
© Mikl___ 2013
5
|
||||||
| 06.01.2013, 07:55 | |
|
Ответы с готовыми решениями:
120
Уроки Iczelion'a на FASM Запрос сам в себе |
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
|||||||||||
| 06.01.2013, 09:41 [ТС] | |||||||||||
|
Win32 API. Урок 7d. Фокусы с иконкой и курсором Добавляем курсор и иконку из файла Cursor.cur в секцию ресурсов. В MASM нет возможности добавлять содержимое бинарных файлов директивой incbin как в NASM'е мы либо должны воспользоваться компилятором ресурсов и в нем указать:
(часть вторая) ТЕОРИЯ, МАТЬ СКЛЕРОЗА Кликните здесь для просмотра всего текста
Скачайте пример здесь. ПРАКТИКА, СЕСТРА ШИЗОФРЕНИИ
Кликните здесь для просмотра всего текста
______________________________________
© Mikl___ 2013
5
|
|||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||
| 06.01.2013, 09:49 [ТС] | ||||||||||||||||||||||
|
Win32 API. Урок 7e. Добавляем курсор и иконку из секции данных функцией CreateIconFromResource В секцию данных добавим рисунок из файла Cursor.cur, воспользовавшись программкой bintodb.exe из "\masm32\tools", которая превратит рисунок в текстовый файл состоящий из наборов DB. При помощи функции CreateIconFromResource получаем указатель на иконку, и, передав его DrawIcon, выводим рисунок из Cursor.cur на клиентскую область окна.Скачайте пример здесь. Функция CreateIconFromResource создает пиктограмму или курсор из битов ресурса, описывающих пиктограмму. Синтаксис Кликните здесь для просмотра всего текста
Если функция завершается успешно, величина возвращаемого значения ― дескриптор пиктограммы или курсора. Если функция не выполняет задачу, величина возвращаемого значения ― NULL. Чтобы получать расширенные данные об ошибках, вызовите GetLastError. Функция DrawIcon рисует пиктограмму в рабочей области окна заданным контекстом устройства. Синтаксис Кликните здесь для просмотра всего текста
Если функция завершается успешно, величина возвращаемого значения отличная от нуля. Если функция не выполняет задачу, величина возвращаемого значения нулевая. Чтобы получать расширенные данные об ошибках, вызовите GetLastError. Пpимеp:
Кликните здесь для просмотра всего текста
__________________________
© Mikl___ 2013
5
|
||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 07.01.2013, 09:10 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 7f. Не используем функции LoadIcon и LoadCursor Заполняя WNDCLASS(EX) можно и не использовать функции LoadIcon и LoadCursor. Дело в том, что эти функции нужны, если загружаемая иконка или курсор изготовлены собственноручно или позаимствованы из какой-либо понравившейся программы. Для стандартных (системных) иконок, битмапов и курсоров идентификаторы неизменны и их можно посмотреть при помощи программы System Resources by The Svin, находящейся на WASM.RU Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
6
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 08.01.2013, 04:04 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Кликните здесь для просмотра всего текста
________________________________ © Mikl___ 2013
4
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 08.01.2013, 09:56 [ТС] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 8. Меню В этом туториале мы научимся, как вставить в наше окно меню.Скачайте пример #1 и пример #2. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Меню ― это один из важнейших компонентов вашего окна. Меню ― список всех возможностей, которые программа предлагает пользователю.Пользователь не обязан читать мануал, поставляемый с программой, чтобы использовать ее (весьма спорная точка зрения ― прим. пер.), он может досконально исследовать меню, чтобы получить представление о возможностях данной программы и начать 'играть' с ней немедленно. Так как меню ― это инструмент для того, чтобы дать пользователю 'быстрый старт', вы должны следовать стандарту. Короче говоря, первые два пункта меню обязательно "File" и "Edit", а последний ― "Help". Вы можете вставить ваши собственные пункты между "Edit" и "Help". Если пункт меню вызывает диалоговое окно, вам нужно заканчивать название пункта эллипсисом (...). Меню ― это разновидность ресурсов. Есть несколько видов ресурсов, таких как диалоговые окна, строковые таблицы, иконки, битмапы, меню и т.д. Ресурсы описываются в отдельном файле, называющемся файлом ресурсов, который, как правило, имеет расширение .rc. Вы можете соединять ресурсы с исходным кодом во время линковки. Окончательный продукт ― это исполняемый файл, который содержит как инструкции, так и ресурсы. Файлы ресурсов можно создать используя любой текстовый редактор. Они состоят из набора фраз, определяющих внешний вид и другие атрибуты ресурсов, используемых в программе. Хотя вы можете писать файлы ресурсов в текстовом редакторе, это довольно тяжело. Лучшая альтернатива ― использовать редактор ресурсов, который позволит визуально создавать дизайн ваших ресурсов не отвлекаясь на текстовую рутину. Редакторы ресурсов обычно входят в пакет с IDE, таких как Visual C++, Borland C++ и т.д. В ресурсах меню описано примерно так: Кликните здесь для просмотра всего текста
MyMenu ― это имя меню, за ним следует ключевое слово MENU и список пунктов меню, заключенный в фигурные скобки. Вместо них вы можете использовать BEGIN и END. Этот вариант больше понравится программистам на Паскале. Список меню включает в себя выражения 'MENUITEM' или 'POPUP'.
Если вы хотите, чтобы каждое окно, созданное из одного класса, имело разное меню, вы можете выбрать второй вариант. В этом случае, любое окно, которому передается хэндл меню в функции CreateWindowEx будет иметь меню, которое замещает меню по умолчанию, указанное в структуре WNDCLASSEX. Сейчас мы узнаем, как меню уведомляет процедуру окна о том, что пользователь выбрал пункт меню. Когда пользователь выберет пункт меню, процедура окна получит сообщение WM_COMMAND. Младшее слово wParam'а содержит ID выбранного пункта меню. Теперь у нас достаточно информации для того, чтобы создать и использовать меню. Давайте сделаем это. ПРАКТИКА, СЕСТРА ШИЗОФРЕНИИ Первый пример показывает нам как создать и использовать меню, указав имя меню в классе окна.
Кликните здесь для просмотра всего текста
Menu.rc
Кликните здесь для просмотра всего текста
Разбор полетов Давайте сначала проанализируем файл ресурсов.
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Далее мы изучим исходный код. Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Если пользователь выбирает пункт 'Exit', мы вызываем DestroyWindow с хэндлом нашего окна в качестве его параметра, которое закрывает наше окно. Как вы можете видеть, указание имени меню в классе окна довольно просто и прямолинейно. Тем не менее, вы также можете использовать альтернативный метод для того, чтобы загружать меню в ваше окно. Я не буду воспроизводить здесь весь исходный код. Файл ресурсов такой же. Есть небольшие изменения в исходнике, которые я покажу ниже. Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
____________________________
© Iczelion, пер. Aquila.
4
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||
| 08.01.2013, 12:34 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 8a. Создание меню через файл ресурсов В этом туториале мы научимся, как вставить в наше окно меню.Скачайте пример. Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Важно! Комментарии в файлах ресурсов, как и комментарии в программах на C++, начинаются с двойного символа наклонной черты.В следующих четырех строках определяются четыре константы Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Добавление меню в класс окна Далее вы должны указать меню в классе окна. Если взглянуть на определение структуры WNDCLASS в основном приложении, можно найти следующую строку
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Обработка команд меню Теперь, когда в главном окне нашего приложения появилось меню, вам наверняка хочется знать, как реагировать на действия пользователя при выполнении им определенной команды. При выполнении команды меню Windows посылает вашему приложению сообщение ― в данном случае WM_COMMAND. Это означает, что вы должны включить в процедуру окна обработку сообщения WM_COMMAND. Когда приложение получает сообщение WM_COMMAND в параметре wParam хранится идентификатор выполненной команды меню.При выборе пунктов меню "Say Hello", "Say GoodBye" и "Test" должны быть выведены мессаджбоксы с сообщениями "Hello, my friend", "See you again, bye" и "You selected Test menu item" соответственно, а при выборе пункта меню "Exit" мы должны закрыть приложение. Iczelion на нашем месте три раза повторяет одинаковые фрагменты Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Сам себе компилятор ресурсов. Теперь уменьшим размер с 972 до 892 байт за счет уменьшения размера заголовка и ручной сборки ресурсов.Скачайте ещё один пример. Кликните здесь для просмотра всего текста
_____________________________________
© Mikl___ 2013
4
|
||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 09.01.2013, 11:49 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 8 b. Создание меню через функцию LoadMenu
Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
6
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10.01.2013, 05:08 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 8 i. Работа с инструментальной панелью (toolbar)
Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
3
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
|||||||||||||||||||||
| 10.01.2013, 07:55 [ТС] | |||||||||||||||||||||
|
Win32 API. Урок 8 j. Всплывающие подсказки Скачайте пример.Теория ― мать склероза В современных программах, управляемых с помощью меню и инструментальных панелей, принято включать в состав меню всплывающие подсказки (tooltips) ― небольшие текстовые окошки, открываемые автоматически и содержащие краткое описание назначения кнопок, когда курсор мыши помещается на соответствующую кнопку инструментальной панели.Для организации всплывающих подсказок следует прежде всего создать инструментальную панель, как это было описано в предыдущем подразделе, дополнив ее стиль, указываемый в качестве второго параметра функции CreateToolbarEx, константой TBSYLE_TOOLTIPS. Отслеживание положения курсора мыши и вывод на экран требуемых подсказок осуществляется в ответ на сообщение Windows WM_NOTIFY, для обработки которого придется дополнить функцию WinProc. В момент прихода сообщения WM_NOTIFY параметр lParam имеет указатель на структуру NMHDR, Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Таким образом, допустимы, в частности, следующие обращения:
Следующий фрагмент обрабатывает запросы подсказок в нашей программе Кликните здесь для просмотра всего текста
Практика ― сестра шизофрении
Кликните здесь для просмотра всего текста
________________________________________ __________
© Mikl___ 2013
2
|
|||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10.01.2013, 08:14 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 8k. Инструментальная панель Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
4
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10.01.2013, 09:51 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 8l. Подключаем стандартные диалоги к инструментальной панели
Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
5
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 11.01.2013, 11:50 [ТС] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 10. Диалоговое окно как основное Теперь время для действительно интересной темы, относящейся к GUI, о диалоговом окне. В этом туториале (и в следующем) мы научимся как использовать диалоговое окно в качестве основного.Скачайте первый и второй примеры. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Если вы изучили примеры в предыдущем туториалe достаточно подробно, вы заметили, что вы не могли перемещать фокус ввода от одного дочернего окна на другое, используя кнопку Tab. Вы могли сделать это только кликнув на нужном контроле, чтобы перевести на него фокус. Это довольно неудобно. Также вы могли заметить, что изменился цвет родительского окна на серый. Это было сделано для того, чтобы цвет дочерних окон не контрастировал с клиентской областью родительского окна. Есть путь, чтобы обойти эту проблему, но он не очень прост. Вы должны сабклассить все дочерние элементы управления в вашем родительском окне.Причина того, почему возникают подобные неудобства состоят в том, что дочерние окна изначально проектировались для работы с диалоговым окном, а не с обычным. Цвет дочернего окна по умолчанию серый, так как это обычный цвет диалогового окна. Прежде чем мы углубимся в детали, мы должны сначала узнать, что такое диалоговое окно. Диалоговое окно ? это не что иное, как обычное окно, которое спроектировано для работы с дочерними элементами управления. Windows также предоставляет внутренний «менеджер диалоговых окон», который воплощает большую часть диалоговой логики, такую как перемещение фокуса ввода, когда юзеp нажимает Tab, нажатие кнопки по умолчанию, если нажатие на кнопку 'Enter, и так далее, так чтобы программисты могли заниматься более высокоуровневыми задачами. Поскольку диалоговое окно можно считать «черным ящиком» (это означает то, что вы не обязаны знать, как работает диалоговое окно, для того, чтобы использовать его), вы должно только знать, как с ним взаимодействовать. Это принцип объектно-ориентированного программирования, называемого скрытием информации. Если черный ящик спроектирован совершенно, пользователь может использовать его не зная, как он работает. Правда, загвоздка в том, что черный ящик должен быть совершенным, это труднодостижимо в реальном мире. Win32 API также спроектирован как черный ящик. Ладно, похоже, что мы немного отклонились. Давайте вернемся к нашему сюжету. Диалоговые окна спроектированы так, чтобы снизить нагрузку на программиста. Обычно, если вы помещает дочерний элемент управления на обычное окно, вы должны сабклассить их и самостоятельно обрабатывать нажатия на клавиши. Hо если вы помещаете их на диалоговое окно, оно обработает их за вас. Вы только должны как получать информацию, вводимую пользователем, или как посылать команды окну. Диалоговое окно определяется как ресурс (похожим образом, как и меню). Вы пишете шаблон диалогового окна, описывая характеристики диалогового окна и его элементов управления, а затем компилируете его с помощью редактора ресурсов. Обратите внимание, что все ресурсы располагаются в одном скрипте ресурсов. Вы можете использовать любой текстовый редактор, чтобы написать шаблон диалогового окна, но я бы не рекомендовал это. Вы должны использовать редактор ресурсов, чтобы сделать визуально расположить дочерние окна. Существует несколько прекрасных редакторов ресурсов. К большинству из основных компиляторов прилагаются подобные редакторы. Вы можете использовать их, чтобы создать скрипт ресурса. После этого стоит вырезать лишние строки, например, те, которые относятся к MFC. Есть два основных вида диалоговых окон: модальные и независимые. Независимые диалоговые окна дают вам возможность перемещать фокус ввода на другие окна. Пример ? диалоговое окно 'Find' в MS Word. Есть два подтипа модальных диалоговых окон: модальные к приложению и модальные к системе. Первые не дают вам переключаться на другое окно того же приложения, но вы можете переключиться на другое приложение. Вторые не дают вам возможности переключиться на любое другое окно. Независимое диалоговое окно создается с помощью вызова функции CreateDialogParam. Модальное диалоговое окно создается вызовом DialogBoxParam. Единственное различие между диалоговым окном, модальным отношению к приложению, и диалоговым окном, модальным по отношению к системе, ? это стиль DS_SYSMODAL. Если вы включите стиль DS_SYSMODAL в шаблон диалогового окна, это диалоговое окно будет модальным к системе. Вы можете взаимодействовать с любым дочерним элементом управления на диалоговом окне с помощью функции SendDlgItemMessage. Ее синтаксис следующий: Кликните здесь для просмотра всего текста
Например, если вы хотите получить текст с элемента управления типа edit, вы можете сделать следующее:
Windows также предоставляет несколько специальных API-функций, заточенных под дочерние окна, для быстрого получения и установки нужных данных, например, GetDlgItemText, CheckDlgButton и т.д. Эти специальные функции создание, чтобы программисту не приходилось выяснять каждый раз значения wParam и lParam. Как правило, вы должны использовать данные функции, если хотите, чтобы управление кодом было легче. Используйте SendDlgItemMessage только, если нет соответствующей API-функции. Менеджер диалоговых окон посылает некоторые сообщения специальной callback-функции, называемой процедурой диалогового окна, которая имеет следующий формат: Кликните здесь для просмотра всего текста
Диалоговое окно можно использовать в двух целях. Вы можете использовать ее как основное окно или как вспомогательное для получения информации, вводимой пользователем. В этом туториале мы изучим первый вариант. «Использование диалогового окна как основное окно» можно понимать двояко.
ПРАКТИКА, СЕСТРА ШИЗОФРЕНИИ
текст файла dialog.asm Кликните здесь для просмотра всего текста
Текст файла Dialog.rc
Кликните здесь для просмотра всего текста
Разбор полетов Давайте проанализируем первый пример.Этот пример показывает, как зарегистрировать диалоговый шаблон как класс окна и создает «окно» из этого класса. Это упрощает вашу программу, так как вам не нужно создавать дочерние элементы управления самостоятельно. Давайте проанализируем шаблон диалогового окна. Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Теперь мы углубляемся непосредственно в ассемблерный код. Интересующая нас часть находится в структуре класса окна. Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
В этот момент, диалоговое окно и его дочерние элементы управления создаются Windows. Ваша процедура окна получит сообщение WM_CREATE как обычно. Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Теперь давайте перейдем ко второму подходу использования диалогового окна как основного окна. В следующем примере, я создам программно-модальное диалоговое окно. Вы не увидите цикл сообщений или процедуру окна, потому что они не нужны! текст файла dialog.asm (вариант 2)
Кликните здесь для просмотра всего текста
Текст файла dialog.rc (вариант 2)
Кликните здесь для просмотра всего текста
Разбор полетов
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
Внутренний менеджер диалогового окна не посылает нашей процедуре сообщение WM_DESTROY, а вот WM_CLOSE шлет. Поэтому если мы хотим отреагировать на то, что пользователь нажимает кнопку закрытия на нашем диалоговом окне, мы должны обработать сообщение WM_CLOSE. В нашем примере мы посылаем сообщение WM_CLOSE со значение IDM_EXIT в wParam. Это произведет тот же эффект, что и выбор пункта 'Exit' в меню. EndDialog вызывается в ответ на IDM_EXIT. Обработка сообщений WM_COMMAND остается такой же. Когда вы хотите уничтожить диалоговое окно, единственный путь ? это вызов функции EndDialog. Не пробуйте DestroyWindow! EndDialog не уничтожает диалоговое окно немедленно. Она только устанавливает флаг для внутреннего менеджера диалогового окна и продолжает выполнять следующие инструкции. Теперь давайте изучим файл ресурсов. Заметное изменение ? это то, что вместо использования текстовой строки в качестве имени меню, мы используем значение IDR_MENU1. Это необходимо, если вы хотите прикрепить меню к диалоговому окну, созданному DialogBoxParam'ом. Заметьте, что в шаблоне диалогового окна вы должны добавить ключевое слово 'MENU', за которым будет следовать ID ресурса меню. Различие между двумя примерами в этом туториале, которое вы можете легко заметить ? это отсутствие иконки в последнем примере. Тем не менее, вы можете установить иконку, послав сообщение WM_SETICON диалоговому окну во время обработки WM_INITDIALOG. ______________________________________
© Iczelion, пер. Aquila.
3
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 12.01.2013, 12:57 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 10a. Комментарии kero к 10 и 11 урокам Iczelion'a
Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
4
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 12.01.2013, 14:58 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 10b. Создания диалогового окна через CreateDialogParam и DlgProc и WndProc
Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
4
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 14.01.2013, 05:10 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 10d. Создания диалогового окна через CreateDialogParam и WndProc и RegisterClassEx Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
3
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 14.01.2013, 05:21 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 10 e. Создания диалогового окна через DialogBoxParam и DlgProc
Кликните здесь для просмотра всего текста
В этом Уроке мы создадим полнофункциональную Windows программу, которое выводит сообщение — "Win32 assembly is great!".
Скачайте пример здесь. ТЕОРИЯ, МАТЬ СКЛЕРОЗА Windows предоставляет огромное количество ресурсов Windows-программам через Windows API (Application Programming Interface). Windows API — это большая коллекция очень полезных функций, располагающихся непосредственно в операционной системе и готовых для использования программами. Эти функции находятся в нескольких динамически подгружаемых библиотеках (DLLs), таких как kernel32.dll, user32.dll и gdi32.dll. Kernel32.dll содержит API-функции, взаимодействующие с памятью и управляющие процессами. User32.dll контролирует пользовательский интерфейс. Gdi32.dll ответственен за графические операции. Кроме этих трех "основных", существуют также другие dll, которые вы можете использовать, при условии, что вы обладаете достаточным количеством информации о нужных API-функциях. Windows программы динамически подсоединяется к этим библиотекам, то есть код API-функций не включается в исполняемый файл. Информация находится в библиотеках импорта. Вы должны слинковать ваши программы с правильными библиотеками импорта, иначе они не смогут найти эти функции. Когда Windows программа загружается в память, Windows читает информацию, сохраненную в программе. Эта информация включает имена функций, которые программа использует и DLL-ей, в которых эти функции располагаются. Когда Windows находит подобную информацию в программе, она вызывает библиотеки и исправляет в программе вызовы этих функций, так что контроль всегда будет передаваться по правильному адресу.Существует две категории API функций: одни работают с ANSI-строками, а другие с Unicode-строками. Имена API-функций использующих ANSI-строки заканчиваются на "A", например, MessageBoxA. В конце имен функций для Unicode находится "W". Windows 95/98 от природы поддерживают ANSI, а Windows NT и производные от нее 2k/XP/Vista поддерживают Unicode. Обычно мы имеем дело с ANSI строками (массивы символов, оканчивающиеся NULL-ом. размер ANSI-символа — 1 байт. В то время как ANSI достаточна для европейских языков, она не поддерживает некоторые восточные языки, в которых есть несколько тысяч уникальных символов. Вот в этих случаях в дело вступает UniCode. размер символа UNICODE — 2 байта, и поэтому может поддерживать 65536 различных символов. Hо по большей части, вы будете использовать include-файл, который может определить и выбрать подходящую для вашей платформы функцию. Просто обращайтесь к именам API-функций без постфикса. ПРАКТИКА, МАТЬ ШИЗОФРЕНИИ Я приведу голый скелет программы ниже. Позже мы разберем его.
Кликните здесь для просмотра всего текста
Большинство прототипов для API-функций содержатся в include-файлах. Если вы используете hutch'евский MASM32, они будут находится в директории MASM32/INCLUDE. Файлы подключения имеют расширение .inc и прототипы функций DLL находятся в .inc файле с таким же именем, как и у этой DLL. Hапример, ExitProcess экспортируется из kernel32.lib, так что прототип ExitProcess находится в kernel32.inc. Вы также можете создать прототипы для ваших собственных функций. Во всех моих экземплярах я использую hutch'евский windows.inc, который вы можете скачать с http://win32asm.cjb.net Возвращаясь к ExitProcess: параметр uExitCode - это значение, которое программа вернет Windows после окончания программы. Вы можете вызвать функцию ExitProcess так:
Кликните здесь для просмотра всего текста
В вышеприведенном примере, мы вызываем функцию, экспортированную из kernel32.dll, для чего мы должны подключить прототипы функций из kernel32.dll. Этот файл - kernel32.inc. Если вы открываете его текстовым редактором, вы увидите, что он состоит из прототипов функций из соответствующей dll. Если вы не подключите kernel32.inc, вы все еще можете вызвать ExitProcess, но уже с помощью ассемблерной команды call. Вы не сможете вызвать эту функцию с помощью invoke. Дело вот в чем: для того, чтобы вызвать функцию через invoke, вы должны поместить в исходном коде ее прототип. В примере выше, если вы не подключите kernel32.inc, вы можете определить прототип для ExitProcess где-нибудь до вызова этой функции и это будет работать. Файлы подключения нужны для того, что избавить вас от лишней работы и вам не пришлось набирать все прототипы самим. Теперь мы встречаем новую директиву — includelib. Она работает не так, как include. Это всего лишь способ сказать ассемблеру какие библиотеки использует ваша программа должна прилинковать. Хотя вы вовсе не обязаны использовать именно этот метод. Вы можете указать имена библиотек импорта к командной строке при запуске линкера, но поверьте мне, это весьма скучно и утомительно, да и командная строка может вместить максимум 128 символов. Теперь возьмите весь исходный текст примера этого Урока, сохраните его как msgbox.asm и ассемблируйте его так:
/Cр говорит MASM'у сохранять регистр имен, заданных пользователем. Если вы используете hutch'евский MASM32 пакет, вы можете вставить "option casemaр:none" в начале вашего исходника, сразу после директивы .model, чтобы добиться того же эффекта. После успешной компиляции msgbox.asm, вы получите msgbox.obj. Это объектный файл, от которого один шаг до екзешника. Obj содержит инструкции/данные в двоичной форме. Отсутствуют только необходимая корректировка адресов, которая проводится линкером. Теперь сделайте следующее:
/LIBPATH:<путь к библиотекам импорта> говорит линкеру, где находятся библиотеки импорта. Если вы используете MASM32, они будут в MASM32\lib. Линкер читает объектный файл и корректирует его, используя адреса, взятые из библиотек импорта. После окончания линковки вы получите файл msgbox.exe. Запустите его. Вы увидите, что она ничего не делает. Да, мы не поместили в код ничего не интересного. Hо тем не менее полноценная Windows программа. И посмотрите на размер! Hа моем PC — 1.536 байт. Теперь мы готовы создать окно с сообщением. Прототип функции, которая нам для этого необходима следующая:
lрText — это указатель на текст, который вы хотите отобразить в клиентской части окна сообщения. Указатель ― это адрес чего-либо. Указатель на текстовую строку = адрес этой строки. lpCaption — это указатель на заголовок окна сообщения. uType — устанавливает иконку, число и вид кнопок окна. Давайте изменим msgbox.asm для отображения сообщения. Кликните здесь для просмотра всего текста
Давайте снова взглянем на исходник. Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними. 1. addr не может быть использован с метками, которые определены впереди, а offset может. Например, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать. Кликните здесь для просмотра всего текста
2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная — это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет ― глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:
________________________________________ ____
© Iczelion, пер. Aquila.
3
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||
| 14.01.2013, 05:59 [ТС] | ||||||
|
Win32 API. Урок 10f. Создания диалогового окна через DialogBoxParam и DlgProc и WndProc Урок сделан по мотивам Iczelion и "main variants" от keroСкачайте пример. Кликните здесь для просмотра всего текста
________________________________________ _
© Mikl___ 2013
3
|
||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||
| 14.01.2013, 06:29 [ТС] | ||||||
|
Win32 API. Урок 10g. Создания диалогового окна через DialogBoxParam и WndProc и RegisterClassEx Урок сделан по мотивам Iczelion и "main variants" от kero Скачайте пример. Кликните здесь для просмотра всего текста
_______________________________________
© Mikl___ 2013
3
|
||||||
|
Ушел с форума
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,768
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 14.01.2013, 07:06 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Win32 API. Урок 11. Больше о диалоговых окнах В этом туториале мы узнаем больше о диалоговых окнах. В частности, мы узнаем, как использовать диалоговые окна в качестве устройств ввода-вывода. Если вы читали предыдущий туториал, то этот будет для вас достаточно прост, так как небольшая модификация ― все, что требуется для использования диалоговых окон как дополнение к основному окну. Также в этом туториале мы научимся тому, как использовать предопределенные диалоговые окна. Скачайте примеры здесь и здесь. Пример предопределенного диалогового окна скачайте здесь. ТЕОРИЯ МАТЬ СКЛЕРОЗА Очень немногое будет сказано о том, как использовать диалоговые окна в качестве устройств ввода-вывода. Программа создает основное окно как обычно, и когда вы хотите отобразить диалоговое окно, просто-напросто вызовите CreateDialogParam или DialogBoxParam. Вызвав DialogBoxParam, вам не нужно делать что-либо еще, просто обработайте сообщения в процедуре диалогового окна. При использовании CreateDialogParam, вам будет нужно вставить вызов IsDialogMessage в цикле сообщений, чтобы позволить менеджеру диалогового окна обработать навигацию клавиатуры в вашем диалоговом окне за вас. Поскольку эти два случая тривиальны, я не привожу здесь исходный код. Вы можете скачать примеры и изучить их самостоятельно.Давайте перейдем к предопределенным диалоговым окнам, которые Windows предоставляет для использования вашими приложениями. Эти диалоговые окна существуют, чтобы обеспечить стандартизованный пользовательский интерфейс. Существуют файловое диалоговое окно, принтер, цвет, шрифт и поисковое диалоговое окно. Вам следует использовать их так часто, как это возможно. Диалоговые окна находятся в comdlg32.dll. Чтобы использовать их, вы должны прилинковать comdlg32.lib. Вы создаете эти диалоговые окна вызовом соответствующих функций из библиотеки предопределенных диалоговых окон. Для открытия файлового диалогового окна существует функция GetOрenFileName, для сохранения ― GetSaveFileName, для диалогового окна принтера ― PrintDlg и так далее. Каждая из этих функций берет указатель на структуру в качестве параметра. Вам следует посмотреть их в справочнике Win32 API. В этом туториале я продемонстрирую как создавать и использовать файловое диалоговое окно. Hиже приведен прототип функции GetOрenFileName.
ПРАКТИКА СЕСТРА ШИЗОФРЕНИИ Нижеприведенная программа отображает окно диалога открытия файла, когда пользователь выбирает пункт File
Разбор полётов
_______________________________________
© Iczelion, пер. Aquila.
3
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 14.01.2013, 07:06 | |
|
ПК перезагружается сам по себе А не навред(ж)ю ли я сам себе? ПК сам по себе перезагружается Выключается сам по себе Вырубается ПК сам по себе Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
|
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства.
Жизнь действительно предъявляет каждому. . .
|
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
|
Лето уходит
kumehtar 17.08.2026
|
|
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
|
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины".
За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html
Задача: . . .
|
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
|
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет:
1. Использовать системное время и дату,
2. Есть возможность вводить время и дату вручную.
3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
|