Продолжаем тему пятиминутных шуток. Сегодня я решил рассказать вам подробней про работу с чужими окнами из Delphi.
Для обращения к чужому окну и управления им используются WinApi функции. Простыми словами WindowsApi (application programming interfaces) функции- это функции, реализованные самими программистами Windows и доступные любому другому программисту. Ну вот к примеру есть функция для нахождения окна в системе FindWindow, которая имеет два параметра. Так вот для того, чтобы ее использовать, нам не нужно знать, как она работает, не нужно ее понимать, а уж тем более писать. Все, что нам нужно- это знать как она правильно пишется и какие параметры ей задать. WinApi функций превеликое множество и рассматривать их все в этой статье слишком долго и бессмысленно. Я просто покажу некоторые из них и покажу как с помощью них мы можем напакостить соседу. Итак немного общих понятий.
Во-первых, для того, чтобы работать с чужим окном нам нужно его найти. Делается это с помощью функции FindWindow, которую мы использовали в статье “Прячем кнопку “Пуск” и другие гадости с окнами”. Эта функция имеет два параметра. Первый- это имя класса окна, а второй- заголовок окна. Если мы не знаем какой-нибудь параметр, то указываем вместо него “nil”. В результате эта функция выдает нам указать на найденное окно. В Delphi есть специальный тип данных, в который мы можем записать результат функции FindWindow. Это тип hwnd. После нахождения нужного нам окна мы можем сделать с ним почти все, что угодно. Чтобы сильно не грузить вас всем этим покажу небольшой пример. Допустим мы хотим знать есть ли сейчас в системе открытое окно “Диспетчер задач Windows”. Для этого создадим на новой форме кнопку и в обработчике событий при ее нажатии пишем следующий код:
var
h:hwnd;//Переменная, куда запишется указатель на окно
begin
h:=FindWindow(nil,’Диспетчер задач Windows’); // Ищем окно с заголовком ‘Диспетчер задач Windows’
if h<>0 then ShowMessage(‘Окно найдено’) // проверяем есть ли такое окно и выдаем
else ShowMessage(‘Окно не найдено’); // соответствующее сообщение
end;
Как видно из примера мы проверяем значение переменной h. Дело в том, что если окна нет, то результатом функции FindWindow будет не указатель на окно, а значение 0. С этим все просто и не должно вызывать никаких сложностей. Теперь попробуем поуправлять немного нашим окном. Например программно из нашей программы закроем окно “Диспетчер задач Windows”. Для этого нам нужно послать этому окну сообщение о его закрытии. Делается это с помощью функции SendMessage, которая имеет четыре параметра. Первый- это то окно, которому мы отправляем сообщение, второй параметр- это само сообщение, а оставшиеся два параметра нас не интересуют, поэтому . Как найти окно мы знаем, то есть качестве первого параметра мы будем указывать переменную h. В качестве второго параметра мы отправим сообщение WM_CLOSE. Немного изменим предыдущий код:
var h:hwnd;
begin
h:=FindWindow(nil,’Диспетчер задач Windows’);
if h<>0 then
begin ShowMessage(‘Окно закрыто’);
SendMessage(h,WM_CLOSE,0,0);
end
else ShowMessage(‘Окно не найдено’);
end;
Отправить сообщение окну можно еще так:
SendMessage(HD,WM_SYSCOMMAND,SC_CLOSE,0);
Как видите в этом примере мы используем и третий параметр функции SendMessage. В качестве этого параметра можно указать SC_MINIMIZE и окно свернется или SC_MAXIMIZE и окно развернется. Подробнее об этом вы можете узнать в справочниках по WinApi функциям, а мы едем дальше. Теперь я покажу как можно перебрать все окна, открытые в системе и послать им какое-нибудь сообщение. Пишем функцию:
function EnumProc (Wd: HWnd; Param: LongInt): Boolean; stdcall; // Обязательно укадите stdcall.
Begin
End;
Между Begin и End мы будем писать, что делать с найденными окнами. Теперь создадим кнопку, при нажатии на которую будет срабатывать эта функция:
procedure TForm1.Button1Click(Sender: TObject);
begin
EnumWindows (@EnumProc, 0);
end;
Давайте теперь попробуем найти все видимые окна и отобразить их названия в Memo:
function EnumProc (Wd: HWnd; Param: LongInt): Boolean; stdcall; // Обязательно stdcall !!!
Var
WinName:Array[0..255] of Char; // Сюда мы запишем имя окна
Begin
If IsWindowVisible(WD) then // проверяем видимо ли текущее найденное окно
begin
GetWindowText(Wd,WinName,255); // Узнаем название этого окна
Form1.Memo1.Lines.Add(String(WinName));// Записываем его в Memo
end;
EnumProc := TRUE; // запускаем поиск следующего окна
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
EnumWindows (@EnumProc, 0);
end;
Ну а теперь перейдем к пакостям. Как то раз я сидел за чужим компьютером. Пользоваться проводником мне было неудобно и я решил установить Total Commander. Поставив его я сделал все, что мне надо и ушел. Total Commander естественно не удалил (прога то нормальная. Кстати она вроде тоже на Delphi написана). Потом ко мне пришел владелец компа и начал наезжать из-за того, что я установил Total Commander. Ну слово за слово и в шутливой форме мы пришли к выводу, что у него фобия Total Commander. Тут и пришла идея в голову переименовать все его открытые окна в этот самый Total Commander.
В Delphi есть такая функция, которая переименовывает окно – SetWindowText, которой в качестве параметров передается указатель на окно и текст, который будет его новым названием. Текст программы:
function EnumProc (Wd: HWnd; Param: LongInt): Boolean; stdcall;
begin
If IsWindowVisible(Wd) then
If isWindow(Wd) then
SetWindowText(Wd,’Total Commander’);
EnumProc := true;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
EnumWindows (@EnumProc, 0);
end;
После этого прописываем программу в автозапуск, прячем и ставим интервал таймера 500 или 300. Все, теперь все окна называются Total Commander. В строке SetWindowText(Wd,’Total Commander’); вместо ‘Total Commander’ вы можете указать все, что угодно.