Несколько предварительных сурьезных слов. Режимы отображение окон верхнего уровня. Системное меню и кнопки заголовка. Некоторые дополнительные возможности. Итоги
Итак…
Режимы отображение окон верхнего уровня.
Давайте попробуем для начала сделать чужое окно активным (мы уже это делали, когда спасали чужое окно в картинку). Для этого можно использовать одну из следующих функций:
Функция SetForegroundWindow
Синтаксис: function SetForeGroundWindow(Wd: Hwnd):Boolean;
Описание: Показывает верхние окно системы.
Параметры:
Wnd: Идентификатор окна. Возвращаемое значение: True- если функция отработала, False- при ошибке.
Процедура BringWindowToTop
Синтаксис: procedure BringWindowToTop(Wnd: HWnd);
Описание: Активизирует и перемещает Wnd в вершину стека перекрывающихся окон.
параметры:
Wnd: Всплывающее или дочернее окно. Возвращаемое значение: Нет
Теперь попробуем проделать с неким окном, имеющим идентификатор окна HD:HWnd некие стандартные действия:
Существуют и другие константы, для сообщений вида WM_SYSCOMMAND:
SC_CLOSE Закрывает окно. SC_CONTEXTHELP Изменяет курсор на вопросительный знак. SC_DEFAULT Выбирает элемент по умолчанию; эмулирует двойное нажатие на Системное меню. SC_HOTKEY Инициирует окно, связанное с текущим - указанной комбинацией горячих клавиш. SC_HSCROLL Прокручивается горизонтально окно. SC_KEYMENU Открывает Системное меню как результат нажатия клавиши. SC_MAXIMIZE (или SC_ZOOM) Разворачивает окно. SC_MINIMIZE (или SC_ICON) Сворачивает окно. SC_MONITORPOWER Устанавливает состояние дисплея. SC_MOUSEMENU Открывает Системное меню как результат щелчка мыши. SC_MOVE Перемещает окно. SC_NEXTWINDOW Переходит к следующему окну. SC_PREVWINDOW переходит к предыдущему окну. SC_RESTORE Восстанавливает окно к его нормальной позиции и размеру. SC_SCREENSAVE Запускает стандартный скринсейвер. SC_SIZE Задает размеры окно. SC_TASKLIST Выполняет или инициирует Windows Task Manager. SC_VSCROLL Прокручивается окно вертикально.
Первый параметр - описатель искомого окна, второй сообщение (в нашем случае WM_SYSCOMMAND) третий одна из констант приведенных выше, четвертый параметр - координаты (x- младшее слово y - старшее).
Можно, так же, показать или скрыть окно, используя функцию API:
Процедура ShowWindow
Синтаксис: function ShowWindow(Wnd: HWnd; CmdShow: Integer);
Описание: отображает или прячет окно образом, указанным параметром CmdShow.
параметры:
Wnd: Всплывающее или дочернее окно. CmdShow - одна из констант:
Возвращаемое значение: Не нуль, если окно было ранее видимым; нуль - если оно было ранее спрятанным.
Константы позволяют скрыть/показать окно с различными типами (распахнутым, свернутым, неактивным и пр.)
Давайте теперь попробуем решить ряд наиболее часто встречающихся проблем:
1) Как свернуть все окна системы ??? (как свернуть все окна системы кроме окна программы) // Любимая наша процедура. {Для того чтобы использовать данный пример необходимо наличие кнопки Button1.}
function EnumMiniProc (Wd: HWnd; Param: LongInt): Boolean; stdcall; // Обязательно stdcall !!! Begin If Wd<>Form1.Handle then // если это не наша программа If IsWindowVisible(WD) then // если окно видимо If not IsIconic(WD) then // если окно не свернуто If isWindow(WD) then // и вообще это - окно. ShowWindow(WD, SW_MINIMIZE); // свернем его. EnumProc := TRUE; // продолжаем перебирать все окна системы. end;
procedure TForm1.Button1Click(Sender: : TObject); // допустим, закрываем по нажатию на клавишу begin EnumWindows (@EnumMiniProc, 0); // отрабатываем сворачивание окон. end;
Для того чтобы окно программы тоже сворачивалось достаточно убрать строку If Wd<>Form1.Handle then в EnumMiniProc
Конечно, можно поставить еще массу условий, по которым будут минимизироваться окна, но это уже дело конкретной задачи.
Еще один пример, который бывает зачастую нужен:
2) Как закрыть (или постоянно закрывать) окна, например содержащие в заголовке подстроку «Реклама»
Закрыть все окна, содержащие определенную подстроку в заголовке. Const ReclamaName : String = 'Реклама' ; // строка, по которой мы узнаем, что это - реклама. TimeInterval : Integer = 500; // Интервал, с которым будем проверять наличие окон {Для того чтобы использовать данный пример необходимо наличие таймера Timer1.} // Любимая наша процедура function EnumCloseProc (Wd: HWnd; Param: LongInt): Boolean; stdcall; // Обязательно stdcall !!! Var Nm:Array[0..255] of Char; // буфер для имени zName:String;
Begin GetWindowText(Wd,Nm,255); // считываем текст заголовка окна ZName:=AnsiUpperCase(String(Nm)); // преобразуем к верхнему регистру т.е РЕКЛАМА If Pos(ReclamaName,zName)<>0 then SendMessage(WD,WM_SYSCOMMAND,SC_CLOSE,0); EnumProc := TRUE; // продолжаем перебирать все окна системы. end;
procedure Tform1.Timer1Timer(Sender: TObject); // будем проверять по таймеру… begin Timer1.Interval:= TimeInterval; // установим время до следующего вызова EnumWindows (@EnumCloseProc, 0); // отрабатываем закрытие окон. end;
Понятно, что настоящая реклама не дает себе таких заголовков, но общий принцип останется тем же, а так попробуйте поискать общее в заголовках окна, названии классов окна и т.п. Кроме того, использование таймера чревато тем, что окон в системе очень много и за установленный интервал времени все окна не будут отработаны, это приведет к замедлению работы системы. Но решение данной подзадачки автор оставляет за читателем, благо особых сложностей с этим нет (увеличения интервала времени, установка логического условия о том, что проверка уже идет, вставка оператора Application.ProcessMessages и проч.)
На этом все возможности этих функций API не исчерпываются, но общий принцип отображения чужих окон, закрытия, перемещения и прокрутки изложен, дальше нужно от конкретной задачи.
Системное меню и кнопки заголовка.
Системное меню, отображает обычно ряд доступных стандартных функций применимых к окнам.
Обычно к таким функциям относятся следующие команды (применительно к локализованным Windows, в англоязычных названия будут другие, есть подозрения, что английские J):
Восстановить - восстанавливает размер окна. Переместить - перемещает окно. Размер - позволяет изменить размер окна. Свернуть - сворачивает окно до иконки (минимизирует). Развернуть - разворачивает окна до максимально возможного размера Закрыть - закрывает окно.
Все эти команды, а так же ряд других (например, добавленных пользователем) доступны при нажатии на иконку, расположенную в левой части заголовка окна.
Ряд команд имеет кнопку, расположенную в правой части заголовка. Обычно таких кнопок три: свернуть, восстановить, закрыть. Иногда добавляется кнопка помощь.
Зачем манипулировать доступными командами системного окна ??? Ну, например, есть окошко, у которого кнопка закрыть - недоступна, а в системном меню пункта закрыть нет, да и на Alt+F4 она не откликается. А убрать программку ужас как хочется.
Процедура GetSystemMenu
Синтаксис: function GetSystemMenu(Wnd: HWnd; Revert: Bool): HMenu;
Описание: Считывает системное меню окна для копирования и модификации.
параметры:
Wnd: Всплывающее или дочернее окно. Revent: Нуль, чтобы возвращался описатель для копирования системного меню, и не нуль, чтобы возвращался описатель исходного системного меню. Возвращаемое значение: идентификатор системного меню; 0 - если Revert отлична от нуля и системное меню не модифицировано.
Для начала надо получить идентификатор системного меню. При помощи приведенной выше функции.
Далее попробуем определить, что именно содержится в системном меню (надо сказать, что приведенные ниже функции API справедливы для любых меню, а не только системных, но об этом несколько позже):
Описание: копирует метку элемента меню в Str. параметры:
Menu: идентификатор меню. IDItem: идентификатор элемента меню. Str: принимающий буфер. MaxCount: размер буфера. Flag: Одна из констант меню
mf_ByPosition - определять пункт меню по порядковому номеру mf_ByCommand - определять пункт меню по выполняемой команде.
Возвращаемое значение: Количество реально скопированных байт.
Как видно из описания функции возможно два варианта определения списка по номеру или по выполняемой команде.
Если Flag = mf_ByCommand тогда в качестве IDItem передаются стандартные команды (см. константы в WM_SYSCOMMAND. Предыдущий раздел).
Например I:=GetMenuString (hMenu, SC_CLOSE, Mn,255,mfByCommand);
Возвращает название пункта системного меню, отвечающего за закрытие окна. I=0 указывает, что такого пункта в системном меню нет.
Если Flag = mf_ByPosition тогда в качестве IDItem передается порядковый номер искомого пункта меню, начиная с 0
Например I:=GetMenuString (hMenu, 0, Mn,255,mfByPosition);
Возвращает название самого первого по порядку пункта системного меню (обычно это восстановить). I=0 указывает, что такого пункта в системном меню нет. ИМХО первый вариант более пригоден для получения списка строк системного меню, в то время как второй - д ля определения присутствует ли данная команда в системном меню.
Количество элементов меню можно получить при помощи функции
Процедура GetMenuItemCount
Синтаксис: function GetMenuItemCount(Menu: HMenu): Word;
Описание: определяет число меню и элементов меню верхнего уровня в указанном меню.
параметры:
Menu: идентификатор меню. Возвращаемое значение: В случае успешного завершения возвращается число элементов меню; 0 - в противном случае.
Вот как приблизительно может выглядеть функция, которая определяет системное меню окна:
Получение списка системного меню окна. ... ListBox1 : TlistBox; // Полученный список запихиваем сюда ... ...
Procedure GetSysMenuItem (Wd:HWND); // Передаем идентификатор окна. Var I,K,Q:Word; hMenuHandle : HMENU; Nm:Array[0..255] of Char; Begin ListBox1.Clear; // Очистим список перед использованием. hMenuHandle:=GetSystemMenu(Wd, FALSE); // Получим идентификатор if (hMenuHandle = 0) then Exit; // Если такого меню нет, то выходим Q:=GetMenuItemCount(hMenuHandle); // Определяем количество пунктов меню. For k:=0 to Q-1 do Begin i:=GetMenuString(hMenuHandle,k,Nm,255,MF_BYPOSITION); // Считываем название ListBox1.Items.Add(String(Nm)); // Добавляем в список. End; End;
Итак, мы получили список пунктов системного меню. Пустые строки, скорее всего, означают разделители. Так же используются акселераторы (&)
Следующим шагом будет определение состояния того или иного пункта меню.
Процедура GetMenuState
Синтаксис: function GetMenuState(Menu: HMenu; ID, Flags: Word):
Описание: Считывает инфоpмацию состояния для указанного элемента меню.
параметры:
Menu: идентификатор меню. IDItem: идентификатор элемента меню. Flag: Одна из констант меню
mf_ByPosition - определять пункт меню по порядковому номеру mf_ByCommand - определять пункт меню по выполняемой команде.
Возвращаемое значение: Маски флагов из следующих значений:
mf_Checked - отмеченное галочкой mf_Disabled - недоступное mf_Enabled - доступное mf_MenuBarBreak - в новой строке или столбце с рисовкой разделителя mf_MenuBreak - в новой строке или столбце без линий mf_Separator - строка -разделитель mf_UnChecked - неотмеченное.
в случае всплывающего меню старший байт содержит число элементов; -1 в случае неверного идентификатора. Давайте слегка улучшим наш предыдущий текст, будем отображать, кроме названия пунктов меню, еще и такую насущную информацию как является ли данный пункт разделителем и доступен ли данный пункт для пользователя : Получение списка состояния системного меню окна. ... ListBox1 : TlistBox; // Полученный список запихиваем сюда ... ...
Procedure GetSysMenuStatus (Wd:HWND); // Передаем идентификатор окна. Var K,Q,l:Word; hMenuHandle : HMENU; Nm:Array[0..255] of Char; S:String; Begin Form1.ListBox1.Clear; // Очистим список перед использованием. hMenuHandle:=GetSystemMenu(Wd, FALSE); // Получим идентификатор if (hMenuHandle = 0) then Exit; // Если такого меню нет, то выходим Q:=GetMenuItemCount(hMenuHandle); // Определяем количество пунктов меню. For k:=0 to Q-1 do Begin GetMenuString(hMenuHandle,k,Nm,255,MF_BYPOSITION); // Считываем название S:=String(Nm); l:=GetMenuState(hMenuHandle,k,MF_BYPOSITION); // Считываем состояние пункта меню If (L and mf_Separator=mf_Separator) then S:='----------------'; // Если это разделитель If (l and mf_Grayed<>mf_Grayed) then S:='(a)'+S; // Если пункт меню подсвечен Form1.ListBox1.Items.Add(S); // Добавляем в список. End; End;
Точно так же можно определять и многие другие параметры пунктов меню. Для получения большего количества информации о пункте меню можно использовать
Пpоцедуpа GetMenuItemInfo
Синтаксис: function GetMenuItemInfo(Menu: HMenu; ID, Flags: Word; Info:TMenuItemInfo): Word;
Описание: Выдает информацию о пункте меню.
параметры:
Menu: идентификатор меню. ID: Идентификатор элемента меню. Flag: Одна из констант меню mf_ByPosition - определять пункт меню по порядковому номеру (или TRUE) mf_ByCommand - определять пункт меню по выполняемой команде (или False). Info : Указатель на структуру MENUITEMINFO MENUITEMINFO = Record CbSize : Word; // размер структуры в байтах FMask : Word; // Определяет какие поля записи должны быть установлены или выбраны FType : Word; // Тип пункта меню (основные) //mft_BitMap - отображаемое с растровым изображением // mft_Separator - строка -разделитель // mft_String - строка // mft_RadioCheck - строка с возможностью выбора // mft_OwnerDraw - рисуемое пользователем FState : Word; //Состояние пункта меню (основные). // mfs_Checked - отмеченное галочкой // mfs_UnChecked - неотмеченное. // mfs_Default - по умолчанию // mfs_Grayed - серое. wID : Word; // Идентификатор пункта меню hSubMenu : HMENU; // Идентификатор подменю. Если подменю нет то Null hBmpChecked : HBITMAP; // Дескриптор растра для выбранного пункта hBmpUnChecked : HbitMap; // Дескриптор растра для не выбранного пункта dwItemData : DWORD; // Определяемое приложением значение dwTypeData ; PAnsiChar; // Содержимое пункта меню cch : Word; // Длина текста hBmpItem: HBITMAP; // Дескриптор отображаемого изображения пункта меню. End;
Возвращаемое значение: В случае успешного завершения возвращается 1; 0 - в противном случае. Эта функция является упрощенным вариантом монстроподобной GetMenuInfo, которая, к сожалению, поддерживается не везде (Делфа 3 не поддерживает), поэтому описывать и привязываться к этой функции не буду. Итак, мы получили список пунктов системного меню окна . Теперь можно
1) Изменять статус пунктов меню (и соответствующих им кнопок заголовка) 2) Удалять «лишние» пункты меню 3) Добавлять «необходимые» пункты меню.
Будем решать эти вопросы по порядку.
процедура EnableMenuItem
Синтаксис: function EnableMenuItem(Menu: HMenu; IDEnableItem, Enable: Word): LongBool;
Описание: разрешает, блокирует или затеняет элемент меню в соответствии со значением параметра Enable.
Menu: Идентификатор меню. IDEnableItem: идентификатор или позиция элемента меню или помечаемый всплывающий элемент. Enable: Комбинация констант
mf_ByCommand - пункты меню по команде или mf_ByPosition - пункты меню по порядку
Возвращаемое значение: Пpедыдущее состояние элемента меню; -1, если элемент не существует..
Следует заметить, что некоторые пункты системного меню связаны с состоянием окна (такие которые задают положение окна и возможность перемещать и изменять его размеры) и даже если удается формально запретить некий пункт (например развернуться) это не значи т, что он будет действительно недоступен.
Включение/выключение пункта меню procedure EnableSysItem(WD:HWND;Number:Integer); // передаем описатель окна и номер пункта Var hMenuHandle : HMENU; i : LongInt; l,r : word; begin If (Number<0) then Exit; // Если такого пункта точно быть не может hMenuHandle:=GetSystemMenu(Wd,False); // Получим идентификатор if hMenuHandle=0 then Exit; // Если меню нет R:=mf_ByPositon; //Прочтем текущее состояние l:=GetMenuState(hMenuHandle,Number,MF_BYPOSITION); // Переключим состояние if l and mfs_Disabled <> mfs_Disabled then R:=R or mfs_Disabled else R:=R or mfs_Enabled; i:=LongInt(EnableMenuItem(hMenuHandle,Number,R)); end;
Как уже было сказано, это процедура будет работать далеко не для всех пунктов меню, например кнопку и пункт меню закрыть она будет запрещать очень даже хорошо, а вот например пункт развернуть далеко не всегда. Для того, чтобы сделать это наверняка нужно п росто удалить такую возможность. Т.е. удалить соответствующий пункт системного меню.
Описание: Удаляет элемент из Menu. Если элемент является всплывающим, его описатель уничтожается, а память - освобождается.
Menu: Идентификатор меню. Position: Положение или идентификатоp команды. Flags: Одна из констант меню: mf_ByPosition, mf_ByCommand. Возвращаемое значение: В случае успешного завеpшения - не нуль; в пpотивном случае - 0.
Описание стандартное, поэтому никаких сложностей при использовании данной функции возникнуть не должно. ИМХО использование как раз этой функции - тот случай, когда в качестве параметра flags лучше передавать значение mf_ByCommand явно указывая какую коман ду Вы собираетесь удалить из меню. Так же следует заметить, что удаление пункта меню, которому соответствует кнопка заголовка приведет не к исчезновению кнопки из заголовка, а только к ее затенению.
Добавить пункт меню можно двумя способами: просто добавить пункт в конец меню:
Пpоцедуpа AppendMenu
Синтаксис: function AppendMenu(Menu: HMenu; Flags, IDNewItem: Word; Name: PChar): Bool;
Описание: Пpисоединяет в конец меню новый элемент, состояние котоpого опpеделяется Flags.
Menu: Идентификатор меню. IDNewItem: Положение или идентификатоp команды. Flags: Одна из констант меню: mf_ByPosition, mf_ByCommand. Name: Название пункта меню. Возвращаемое значение: В случае успешного завеpшения - не нуль; в пpотивном случае - 0.
Или вставить пункт меню настроив все необходимые параметры
Menu: Идентификатор меню. IDNewItem: Положение или идентификатоp команды. Flags: Одна из констант меню: mf_ByPosition, mf_ByCommand. Item: Структура определяющая пункт меню (см. описание GetMenuItemInfo) Возвращаемое значение: В случае успешного завеpшения - не нуль; в пpотивном случае - 0.
Ну и как результат всех наших стараний напишем процедуру, которая разрешает или запрещает кнопку, строку системного меню «закрыть» (а так же комбинацию клавиш Alt+F4):
Удаление или восстановление кнопки закрыть окно. // Отключает или разрешает так же пункт меню, и комбинацию Alt+F4 Procedure CloseXbtn (Wd:HWND; Enable:Boolean); Var hMenuHandle : HMENU; Begin hMenuHandle:=GetSystemMenu(Wd,False); // Получим идентификатор if hMenuHandle=0 then Exit; // Если меню нет If Enable then // Если надо добавить пункт меню AppendMenu (hMenuHandle, mf_ByCommand, SC_Close,'&Закрыть Alt+F4'); Else DeleteMenu(hMenuHandle, SC_Close, mf_ByCommand); End;
Конечно, куда правильнее было бы использовать функцию InserMenuItem вместо AppendMenu, тогда можно было бы поставить слева значек «закрыть». Но это уже для любителей самим повозиться с API, очень уж не хочется лишать их этого удовольствия J.
Ну, и, наконец, для развлечения тех, кто продрался сквозь все эти кошмары работы с системным меню, предлагаю маленькое развлечение.
Иногда появляется необходимость нарисовать, что-нибудь (например, кнопку) в заголовке чужого окна (а возможно и своего). Это можно сделать очень и очень просто.
Пpоцедуpа DrawFrameControl
Синтаксис: function DrawFrameControl (DC:HDC;Rc :Trect; uType,uStyle:Word ): Bool;
Описание: Рисует один из элементов в заголовке окна. DC : контекст устройства в котором происходит рисование. Rc : Область в которой будет происходить рисование UType: Тип элемента одна из констант:
DFC_BUTTON Кнопка DFC_CAPTION Заголовок DCF_MENU Меню DFC_SCROLL Полоса прокрутки Ustyle : Стиль элемента одна из констант:
Для кнопок
DFCS_BUTTON3STATE Кнопка с тремя состояниями DFCS_BUTTONCHECK Флажок DFCS_BUTTONPUSH Кнопка DFCS_BUTTONRADIO Переключатель DFCS_BUTTONRADIOIMAGE Картинка для переключателя DFCS_BUTTONRADIOMASK Маска для переключателя
Для заголовков
DFCS_CAPTIONCLOSE Кнопка закрыть DFCS_CAPTIONHELP Кнопка помощь (только Window 9x) DFCS_CAPTIONMAX Кнопка развернуть DFCS_CAPTIONMIN Кнопка свернуть DFCS_CAPTIONRESTORE Кнопка восстановить
Возвращаемое значение: В случае успешного завеpшения - не нуль; в пpотивном случае - 0.
Заметьте, что это функция только рисует элемент заголовка.
14 Отрисовка «фальшивой» кнопки закрыть в заголовке окна. Procedure DrawFalseClose (Wd:HWND; xPos:Integer); Var DC:HDC; begin DC:=GetWindowDC(Wd); // Получим контекст устройства окна If DC>0 then Begin DrawFrameControl (DC,Rect(xPos,4,xPos+16,020),DFC_Caption,DFCS_CaptionClose); ReleaseDC(Wd,DC); // Освободим контекст устройства. End; end;
Некоторые дополнительные возможности
С приложениями (и окнами верхнего уровня в частности) можно делать огромное количество вещей. Если быть честным, то останавливаться подробно на этих возможностях я не собирался. Но оказалось, что решение этих задач интересует достаточно многих. В этом раз деле попробуем привести некоторые, на мой взгляд, наиболее полезные из них.
Самым простым, и наиболее часто используемой является возможность изменять заголовок чужих окон. И действительно, почему в заголовке Дельфы пишется например Delphi ? J Непорядок !
Описание: Устанавливает название заголовка для окна или текст оpгана упpавления с помощью стpоки, указанной в Str. Wnd: Идентификатоp окна или оpгана упpавления. Str: Стpока (заканчивающаяся пустым символом). Возвращаемое значение:Нет.
И текст, который иллюстрирует работу данной функции, например, находит окно Дельфы и меняет ее заголовок с «Delphi» на любой другой
Замена текста в заголовке окна. // Передаем новое название например Дельфи Procedure ChangeDelphi (NewName:String); Var Wd:HWND; Nm:Array[0..255] of Char St : String; I:Integer; Begin Wd:= FindWindow('TAppBuilder',Nil); // Находим заголовок по классу окна Delphi If Wd<=0 then Exit; // Такого окна нет. GetWindowText(Wd,Nm,255); // Считываем заголовок окна St:=String(Nm); // Переводим в строку I:=Pos('Delphi',St); // Находим положения заголовка If I>0 then // Если слово Дельфи есть в заголовке Begin Delete(St,i,Lenght('Delphi'); // Удаляем Insert(NewName,St,i); // Вставляем SetWindowText(Wd,Pchar(St)); // Отправляем новый заголовок окну. End; // Все end;
Зачастую необходимо выяснить, не зависло ли окно (или вернее насколько живо оно откликается на попытки системы достучаться до него) Для этих целей можно использовать следующий текст
16 Определение не является ли данное окно зависшим. // Результат True- рабочее окно, False - возможно окно висит function WinTimeOut (Wd:HWND;Time:Integer):Boolean; //Описатель окна и время в секундах Var dwRes:DWORD begin Time:=Time*1000; // Переводим время в миллисекунды Result:=Not SendMessageTimeOut(WD,WM_USER,0,0,SMTO_NORMAL, Time, @dwRes); end;
Теперь поговорим о, так называемом, подсвечивание окон. Например, при установке точки останова в программе главное окно начинает мерцать. И делает это до тех пор, пока пользователь не переключится в это окно. Как это делается ???
Существует пара функций:
Пpоцедуpа FlashWindow
Синтаксис: function FlashWindow(Wnd: HWnd; Invert: Bool): Bool;
Описание: Делает окно или пиктогpамму мигающими. Активное состояние откpытого окна инвеpтиpуется. Wnd: Идентификатоp окна или оpгана упpавления. Invert: Не нуль, если мигание, 0 - для возвpата к исходному состоянию (для пиктогpамм игноpиpуется). Возвращаемое значение: Не нуль, если окно до вызова было активным; 0 - в пpотивном случае.
И вторая функция, которая описана для Delphi 5 а для 3 нет, что обидно, но мы это исправим.
Пpоцедуpа FlashWindowEx
Синтаксис: function FlashWindowEx(var pfwi: FLASHWINFO): BOOL;
Описание: Делает окно или пиктогpамму мигающими. Активное состояние откpытого окна инвеpтиpуется. FLASHWINFO = record cbSize: UINT; // Размер структуры в байтах hwnd: HWND; // Идентификатоp окна или оpгана упpавления. dwFlags: DWORD; // один из следующих флагов: FLASHW_STOP = $0; // Не мигать FLASHW_CAPTION = $1; // Мигающий заголовок FLASHW_TRAY = $2; // Мигающая кнопка FLASHW_ALL = FLASHW_CAPTION or FLASHW_TRAY; // Мигать FLASHW_TIMER = $4; // Мигать пока не будет запущен СТОП FLASHW_TIMERNOFG = $C; // Мигать пока не станет верхним uCount: UINT; // Сколько раз мигать dwTimeout: DWORD; // Интервал мигания end;
Возвращаемое значение: Не нуль, если окно до вызова было активным; 0 - в пpотивном случае. Сначала опишем функцию для несчастных, которые как и я ютятся в 3 версии. Куда Вы все это вставите Ваши сложности можно в отдельный модуль можно в тот же что и программа. Если будете делать отдельный модуль, это будет выглядеть приблизительно так: interface Const FLASHW_STOP = $0; FLASHW_CAPTION = $1; FLASHW_TRAY = $2; FLASHW_ALL = FLASHW_CAPTION or FLASHW_TRAY; FLASHW_TIMER = $4; FLASHW_TIMERNOFG = $C; type FLASHWINFO = record cbSize: UINT; hwnd: HWND; dwFlags: DWORD; uCount: UINT; dwTimeout: DWORD; end; PFLASHWINFO = ^FLASHWINFO; TFlashWInfo = FLASHWINFO;
function FlashWindowEx(var pfwi: FLASHWINFO): BOOL; stdcall; implementation function FlashWindowEx; external user32 name 'FlashWindowEx'; end;
А теперь сама программа, не забудьте подключить модуль кому нужно:
17 Мигающий заголовок окна // Результат True- рабочее окно, False - возможно окно висит procedure SetOnFlash (Wd:HWND;):Boolean; //Описатель окна Var f: TFlashWInfo; Begin f.Hwnd:=Wd; f.dwFlags:= FLASHW_ALL; f.dwTimeout:=10; f.uCount:=100; f.cbSize:=SizeOf(F); FlashWindowEx(F) end;
Итоги
Итак, мы научились управлять чужими окнами верхнего уровня:
1. Изменять их положение, размеры 2. Закрывать, сворачивать и восстанавливать