Содержание статьи
Нет в мире совершенства
Народная молва гласит, что в основе мироздания лежит закон подлости, из которого следуют все остальные фундаментальные законы природы. К таковым относится и закон неубывающей энтропии, в соответствии с которым материальные предметы со временем приходят в негодность. На моем мониторе этот закон проявился в виде горизонтальных полос в верхней части экрана, которые выглядят как нотный стан, если под ними радикально черный фон, и как интерференционная картина в двухщелевом эксперименте, если фон светлый.
Ознакомившись с обзорами аналогичных проблем по роликам на YouTube, я составил для себя общее представление об этом дефекте. Он может быть вызван либо плохим контактом шлейфа, соединяющего матрицу монитора с контроллером, либо неисправностью в электронных компонентах самого контроллера. Поскольку гарантийный срок уже закончился, я разобрал монитор и пришел к выводу, что с отсутствием опыта и инструментов шансы на успешный ремонт у меня примерно 50 на 50: либо устраню дефект, либо испорчу все окончательно.
Какие еще остаются варианты? Знаю по опыту, что официальный сервис, скорее всего, выставит заградительную цену, а отдавать боевого товарища в очумелые ручки кустаря‑одиночки совесть не позволяет. Наиболее здравой кажется мысль пойти в ближайший магазин, купить новый монитор и не дурить голову ни себе, ни читателям. Именно так я бы и поступил, если бы монитор не работал совсем. Но он почти работает, и выбрасывать его попросту жалко.
А ведь если подумать, ремонт необязательно предполагает восстановление исходного качества изделия — зачастую допускается некоторая утрата потребительских свойств. Как, например, поступает хакер, обнаружив в один прекрасный день дыру... нет, не в безопасности, а в любимых домашних брюках? Достает свой толстый кошелек и спешит в ближайший бутик за новыми? Нет, он вспоминает уроки Марьванны и, применяя методологию «вперед иголка», накладывает заплатку! Или другой пример. В не менее прекрасный день инженеры NASA обнаружили, что основная антенна радиосвязи запущенного к Юпитеру зонда не раскрылась полностью. Разве они бросили неисправное устройство на произвол судьбы и обратились к правительству за финансированием нового? Нет, они проявили находчивость и техническую смекалку, в результате чего пусть и не без труда, но успешно провели многолетнюю исследовательскую миссию.
Выбор цели и средства
Рассматриваемая в статье ситуация находится где‑то между этими крайними случаями. Наибольшие неудобства описанный дефект доставляет при использовании развернутых на весь экран программ, потому что попадает либо на адресную строку браузера, либо на главное меню приложения. Использование же программ в оконном режиме, с подгонкой их местоположения после каждого запуска, грозит нервным расстройством. Я готов пожертвовать частью полезной площади экрана, если изображение не будет попадать на дефектную область.
Основная операционная система на моем компьютере — Windows. Как исключить полосу в верхней части экрана из доступного пространства рабочего стола, чтобы окна приложений при развертывании не попадали на нее? Идею мне подсказала панель задач: она монополизирует нижнюю часть экрана и никогда не перекрывается окнами программ. Может быть, достаточно будет прикрепить ее к верхней части экрана? Нет, во‑первых, она не совсем подходит по размеру, а во‑вторых, сама приобретает неприглядный вид из‑за дефекта. А нельзя ли сделать «заплатку» с такими же свойствами, но чтобы пользователь мог контролировать ее размер и цвет?
Оказывается, можно, и ответ быстро нашелся в справочнике по Win32 API — это панель инструментов рабочего стола. Направление работы прояснилось, осталось выбрать подходящий инструмент для ее выполнения. Основное средство разработки с использованием Win32 API — компилятор С. Но для вызова нескольких функций операционной системы хочется воспользоваться чем‑то более простым и изящным. Поэтому я отправился в темную кладовую своей памяти и нашел там пыльную шкатулку с плоским монтажником. Если кто‑то еще не догадался, то так звучит по‑русски Flat Assembler в варианте Яндекс‑переводчика. Удивительно, но продукт, с которым я познакомился еще в середине 2000-х, продолжает жить и здравствовать.
Что умеет Flat Assembler?
Давай прямо сейчас разберемся со средой, в которой будем работать. На странице загрузки выбери архив с последней версией сборки для Windows, загрузи его и распакуй куда‑нибудь на диск. В трех мегабайтах папки FASMW
есть все, что нам потребуется.
Создай пустую папку Appbar
для рабочего проекта и скопируй в нее исходный текст шаблона типового приложения Windows FASMW\
. Запусти интегрированную среду разработки FASMW\
и с помощью пункта меню File → Open... загрузи в нее этот файл. Обрати внимание, что в нашем распоряжении есть текстовый многооконный редактор с подсветкой синтаксиса ассемблера.
Шаблон Windows-приложения на ассемблере состоит из следующих основных частей:
- заголовка с указанием формата целевого исполняемого файла и точки входа в приложение;
- секции кода
.
, где меткаtext start
указывает команду, с которой должно начинаться выполнение программы; - секции данных
.
, содержащей глобальные переменные программы;data - секции импорта
.
, в которой перечислены используемые программой динамические библиотеки и подключаются объявления содержащихся в них функций.idata
В целом текст программы должен быть понятен любому, кто использовал Win32 API. Во‑первых, сам API предельно прост. Параметры всех функций ожидают 32-битных значений аргументов, а если данные не укладываются в этот размер, то передается 32-битный указатель на массив или структуру опять же 32-битных значений. Исключение, пожалуй, только строки. Возвращаемое функцией значение (например, код завершения) передается через регистр EAX
или, если оно превышает 32 бита, через структуру, на которую указывал один из аргументов.
Во‑вторых, Flat Assembler на основе своего набора макроинструкций предлагает синтаксический сахар, который делает использование API максимально приближенным к высокоуровневым языкам программирования. Скажем, довольно сложный вызов функции создания окна описывается одной строкой:
invoke CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,256,192,NULL,NULL,[wc.hInstance],NULL
Здесь invoke
— это команда вызова подпрограммы в соответствии с соглашением STDCALL, CreateWindowEx
— имя вызываемой API-функции, а далее через запятую следуют аргументы в том порядке, в котором они описаны в документации. С‑программисты могут считать, что имена всех переменных здесь — это указатели (_class
, _title
), для разыменования которых используются квадратные скобки ([
). Отметим привычную «точечную» нотацию доступа к элементам структуры.
Описание оконной процедуры WindowProc тоже не должно вызвать затруднений:
proc WindowProc uses ebx esi edi, hwnd,wmsg,wparam,lparam ... retendp
Соглашение Win32 API требует, чтобы после возврата из процедур обратного вызова (callback-процедур) значения регистров EBX
, ESI
и EDI
были такими же, как и перед вызовом. Для этого в заголовке присутствует указание на сохранение этих регистров в виде фразы uses
. А дальше через запятую идет список формальных параметров процедуры, которые соответствуют документации.
Теперь ты можешь скомпилировать и выполнить эту программу. Но сначала укажи путь к папке с подключаемыми директивой include
файлами в пункте меню Options → Compiler setup так, чтобы он соответствовал фактическому местоположению FASMW\
. После этого выполни пункт меню Run → Run или просто нажми клавишу F9. Если все было сделано правильно, то в рабочей папке Appbar
появится свежесобранный файл TEMPLATE.
, а на экране отобразится крошечное окно Win32 program template.
Создание обработчика сообщения WM_CREATE
Со средой разработки разобрались, приступим к работе над программой. Если раньше ты никогда не программировал панели рабочего стола Windows, то сейчас самое время изучить документацию. Но перед этим хочу обратить внимание на основные моменты. Панель рабочего стола не является каким‑то уникальным объектом операционной системы. Роль панели может играть любое окно, созданное функцией CreateWindowEx
. Все средства Windows, обеспечивающие функционирование панели, сосредоточены в единственной функции SHAppBarMessage, с помощью которой можно:
- узнать границы области рабочего стола, в пределах которых можно разместить новую панель инструментов;
- зарезервировать на этой области участок для размещения новой панели;
- указать манипулятор (
handle
) окна с панелью, которому будут отправляться системные уведомления, связанные с изменением обстановки на рабочем столе.
После резервирования новой области операционная система запрещает ее использование окнами приложений при их максимизации, освобождает от значков рабочего стола (если таковые на ней были) — и, в общем‑то, всё. За внешний вид панели отвечает ассоциированное с нею окно, которое теоретически должно закрыть собой освобожденное пространство и принять соответствующий стиль. Но по большому счету может этого и не делать.
С помощью пункта меню File → Save as... сохрани открытый в редакторе файл под именем appbar.
. В нашей программе панелью будет главное окно приложения. Зарезервируем для нее полосу в верхней части рабочего стола. Это можно сделать в обработчике сообщения WM_CREATE
, которое отправляется операционной системой окну приложения непосредственно перед тем, как отобразить его на экране. Для этого в начале оконной процедуры WindowProc
вставим строки перехода к обработчику сообщения:
cmp [wmsg],WM_CREATEje .wmcreate
и напишем сам обработчик перед меткой .
:
.wmcreate: stdcall wmCreateProc, [hwnd] jmp .finish
info
Метки, которые начинаются с точки, являются локальными по отношению к процедуре, где они используются (в данном случае — WindowProc
). Это еще одна фишка Flat Assembler, которая позволяет не беспокоиться о том, что в разных процедурах имена меток могут повторяться.
Наш обработчик вызывает пока еще не существующую процедуру wmCreateProc
и передает ей значение манипулятора созданного окна. В этой процедуре надо описать действия по резервированию полосы и позиционированию главного окна, после чего обнулить регистр EAX
для сигнализирования об успешном завершении процедуры. Если после обработки сообщения WM_CREATE
значение регистра EAX
будет равно (
, операционная система воспримет это как сигнал о проблеме, что приведет к завершению работы программы. Текст процедуры wmCreateProc
можно разместить после оператора endp
, закрывающего блок описания оконной процедуры WindowProc
:
proc wmCreateProc,hwnd invoke MessageBox,[hwnd],_title,_class,MB_OK+MB_ICONINFORMATION xor eax,eax retendp
info
Вот промежуточный вариант программы, который выводит отладочное сообщение: appbar-ver1.asm.
Процедура wmCreateProc
в таком виде не делает ничего полезного, но при запуске программы выводит окно с информационным сообщением, которое дает понять, что на этом этапе все работает так, как ожидается.
info
Внимательно следи за тем, чтобы количество и порядок аргументов в команде вызова процедуры всегда соответствовали количеству и порядку параметров в ее описании. FASMW это не контролирует, и, если допустить небрежность, можно получить трудно обнаруживаемые ошибки.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»