Часто требуется организовать задержку в выполнении кода, но что бы при этому приложение не зависало, могло реагировать на сообщения Windows, в часности могло перерисовываться..

 

 

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

 

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

С чего все начиналось:

 С начала. Мне нужно было написать перехватчик вызовов WinSock. Дабы любая программа могла работать через SOCKS5-проксик. Я посчитал, что перехват вызовов DLL'ки проще, чем судорожные попытки написать драйвер (да и сейчас так считаю). Енота, правда, ехидно улыбалась и говорила "ну-ну", но я-таки справился. SOCKS сниффер еще пишу, но в принципах перехвата уже разобрался :-) [Енота: разобраться-то он действительно разобрался, а соксифиера нет до сих пор...]

 Как все будет:

 

Иногда требуется работать с объектами WINDOWS не используя VCL. Где это может пригодиться?

 

Например:

 

При отсутствии у приложения окна - консольный проект.

Если нужно работать быстро, а известно, что функции WinApi работают на порядок быстрее, чем стандартные классы Delphi.

Работа с устройствами ввода - вывода. Многие вещи в Дельфи можно делать через только через дескриптор, например чтение сообщений из MailSlot, работа с процессами и thread и т.д.

Что это такое?

Для получения информации о множественных объектах Windows (окнах, принтерах, шрифтах, настройках экрана и так далее - всего несколько десятков вариантов) используются функции, начинающиеся с Enum. Эти функции работают по принципу, аналогичному итератору TCollection.FirstThat, то есть они вызывают функцию, переданную им в качестве параметра для каждого перечисляемого объекта, передавая ей в параметрах данные объекта и, в последнем параметре, указатель на пользовательские данные, переданный функции EnumXXX. Перечисление продолжается до тех пор, пока не будут перечислены все объекты. Немедленно прекратить перечисление можно, возвратив False. Ниже приведен пример заполнения списка ListBox1 данными по всем окнам Windows в виде " класс - заголовок" по нажатию кнопки Button1.

 

 

Code:

PostMessage(FindWindow(Nil, Pchar('Название Окна')), WM_QUIT, 0, 0);

Автор: Radmin

Используем WM_WININICHANGED в качестве примера :

 Объявление метода в TForm позволит вам обрабатывать сообщение WM_WININICHANGED:

procedure WMWinIniChange(var Message: TMessage); message WM_WININICHANGE;

 Код в implementation может выглядеть так:

 

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

· RegisterEventSource - Открывает handle для доступа к журналу на локальной или удаленной машине.
· ReportEvent - Собственно записывает сообщение.

Для записи сообщений в журнал в упрощенной манере просто произведите вызов RegisterEventSource с именем машины (UNC), в журнал которой вы хотите поместить сообщение (nil для локальной машины), и именем события. Имя события это обычно имя приложения, но может быть чем-то более информативным. Как только источник событий зарегистрирован, можно записывать события при помощи ReportEvent с handle, который вернула RegisterEventSource.

WinAPI - это те функции которыми управляется работа приложений в Windows. Они являются частью системы, и подгружаются вместе с виндос в библиотеке kernel32.dll.

В Делфи эти функции приемущественно описанны в библиотеке Windows, которая автоматически включается в ваш новый проект. Вы можете открыть эту библиотеку и посмотреть сами. Большая часть VCL - это надстройка над WinAPI.

Для каждого запущенного приложения создается процесс и в этом процессе основной поток (приложение может создавать свои дополнитльные потоки - все они будут принадлежать его процессу), а уж потоки создают окна. Каждый поток имеет уникальный числовой индификатор называемый ThreadID. Это просто целое число которое дается (ассоциируется) этому потоку. Точно так же имеет свой уникальный индификатор каждое окно в системе, называемый Handle. Он обозначается обычно типом HWND, но это просто целое. 4-х байтное.

Code:

 

EnableMenuItem(GetSystemMenu(FindWindow(Nil, Pchar('Название Окна')),False)

,SC_CLOSE,MF_BYCOMMAND or MF_GRAYED);

 

Автор: Radmin

Главная пробема, возникающая при написании WinAPI приложений - это неудобство ручного создания всех окон приложения. Требуется вызывать функцию CreateWindow для каждого (в том числе и дочернго) окна программы, а затем еще и менять шрифт в некоторых из них. Лучшим на мой взгляд выходом из этой ситуации является использование ресурсов диалоговых окон (dialog box resources) для соэдания всех окон приложения. В этой статье я расскажу как это делается в Delphi на примере простоо приложения с одним главным и двумя (модальными) окнами.