Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.134.78.106] |
|
Сообщ.
#1
,
|
|||||||
|
Синтаксис: function FindWindow(ClassName, WindowName: PChar): HWnd; Описание: Находит родительское окно верхнего уровня с совпадающими ClassName и WindowName. Не осуществляет поиск дочерних окон. Параметры:
Описатель окна; 0 - если такого окна нет. Итак, функция FindWindow находит все окна верхнего уровня по названию класса и заголовку окна. Если Ваша задача определить запущено ли определенное окно (с известными именем класса и заголовком) в настоящий момент, можно использовать Procedure WindowPresent(ClassName,WindowName:PChar): Boolean; Begin Result := FindWindow(ClassName,WindowName)<>0; End;Но, зачастую требуется определить все окна, или окна, для которых не известен класс и/или заголовок. Для решения нашей задачи, также можно использовать функцию FindWindow Но посмотрим, что еще у нас есть из функций работы с окнами. Функция GetNextWindow Синтаксис: function GetNextWindow(Wnd: HWnd; Flag: Word): Hwnd; Описание: Считывает из Wnd следующее или предыдущее окно. В случае окна верхнего уровня ищется следующее окно верхнего уровня, а в случае дочернего окна ищется следующее дочернее окно. параметры:
возвращаемое значение: Идентификатор окна. Функция GetNextWindow находит все окна текущего уровня (если задано окно верхнего уровня, - то ищет окно верхнего уровня, если дочернее окно - то список дочерних) Осталось определить, как найти исходный описатель окна, от которого будем плясать (параметр WND функции) Можно попробовать начать поиски с верхнего окна системы. Его можно определить при помощи следующей функции API: Функция: GetForegroundWindow Синтаксис: function GetForeGroundWindow: Hwnd; Описание: Показывает верхнее окно системы. Параметры: нет. Возвращаемое значение: Идентификатор окна. А можно при помощи все той же функции FindWindow и все-таки для определения окон верхнего уровня, на мой взгляд, предпочтительней использовать функцию FindWindow. Давайте попробуем описать первый вариант функции, которая составляет список всех окон верхнего уровня системы, пусть у нас есть на форме некий ListBox1:TlistBox, будем помещать в него найденные окна. И процедура поиска окон будет выглядеть тогда следующим образом: procedure Tform1.GetAllWindow; Var Wd : HWnd; begin ListBox1.Items.Clear; // Очистим список перед началом поисков Wd:=FindWindow(0,0); // Найдем первое окно верхнего уровня любого класса While (Wd<>0) do // Если такое окно существует Begin ListBox1.Items.Add(IntToStr(Wd)); // Добавим описатель в виде текста в список Application.ProcessMessages; // Дадим возможность поработать другим Wd:=GetNextWindow(Wd,GW_HWNDNEXT); // Найдем следующее окно в системе. End; end;Работает??? Работает, но как-то не совсем так, как хотелось, ряд окон не отображается (например, системные окна, такие как System Tray), возможно некое зацикливание программы в некоторых случаях. Просто потому, что для этих целей существует совсем другой способ. Функция EnumWindows Синтаксис: function EnumWindows(EnumFunc: TFarProc, lParam: Longint): Bool; Описание: Пеpечисляет все pодительские окна на экpане, пеpедавая функции обpатного вызова ( т.е объявленная как stdcall функция) описатель окна и lParam. Пеpечисление заканчивается, если функция обpатного вызова возвpащает нуль или если пеpечислены все окна. Параметры:
Вот эта функция прям-таки и просится, чтобы перечислить все окна в системе. Для этого нам потребуется вспомогательная функция (хотя конечно она то и будет основной) И так: function EnumProc (Wd: HWnd; Param: LongInt): Boolean; stdcall; // Обязательно stdcall !!! Begin ListBox1.Items.Add(IntToStr(Wd)); // Добавляем текущий описатель окна EnumProc := TRUE; end; Procedure TForm1.GetAllWindow; Begin ListBox1.Items.Clear; // Очистим список перед началом поисков EnumWindows (@EnumProc, 0); // и скажем - искать End;И получается проще. В дальнейшем все изменения будут идти относительно текста 2, хотя все это будет справедливо и для текста 1.
Для начала получим информацию о классе окна и заголовке окна: Функция GetClassName Синтаксис: function GetClassName(Wnd: HWnd; ClassName: PChar; MaxCount: Integer): Integer; Описание: Считывает имя класса окна. Параметры:
Функция GetWindowText Синтаксис: function GetWindowText(Wnd: HWnd; Str: PChar; MaxCount: Integer): Integer; Описание: Копиpует в Str заголовок окна или текст оpгана упpавления. Параметры:
Описатели окна мы уже имеем, так что самое время получить имя класса и заголовок. Изменим полученную функцию EnumProc следующим образом: function EnumProc (Wd: HWnd; Param: LongInt): Boolean; stdcall; // Обязательно stdcall !!! Var Nm:Array[0..255] of Char; // буфер для имени Cs: Array[0..255] of Char; // буфер для класса Begin GetWindowText(Wd,Nm,255); // считываем текст заголовка окна GetClassName(Wd,Cs,255); // считываем название класса окна ListBox1.Items.Add(String(Nm)+'/'+String(Cs)); // Добавляем название окна и класс в список EnumProc := TRUE; // продолжать искать окна: end;Конечно, красоты ради, стоило бы сначала определить необходимый размер буфера, но в подавляющем большинстве случаев вполне хватает 255 символов. Для желающих поразвлечься самостоятельно предлагаю определить размер заголовка помощи следующих функции: Функция GetWindowTextLength Синтаксис: function GetWindowTextLength(Wnd: HWnd): Integer; Описание: Считывает длину заголовка окна или текста оpгана упpавления. Параметры: Wnd: Идентификатор окна. Возвращаемое значение: Длина заголовка окна в символах. Вот теперь мы видим какие окна верхнего уровня у нас загружены в системе, и даже можем понемногу разбираться какие окна к чему относятся. Но появляются разные странности. Во-первых количество окон в системе оказывается больше чем то, что мы видим. Во-вторых появляются окна вообще с непонятными классами и/или названиями или вообще без них. Спешу Вас успокоить, список содержит ВСЕ окна которые есть в системе, включая скрытые, системные (например ProgMan не что иное как рабочий стол). В том числе и Вашу программу. Встает вопрос, как бы убрать собственную программу из списка ? Для этого коротенько намекну, что описатель, который мы так долго и муторно получали, на самом деле, совпадает с Handle, который есть у любой формы. Чтобы исключить свою программу из списка достаточно просто поставить проверку В тексте 3: If Wd<>Form1.Handle then ListBox1.Items.Add(String(Nm)+'/'+String(Cs)); Для пущей красоты можно сделать переключатель, который отвечает за то, будет ли в список добавляться Ваша программа. Если у Вас не одно окно, а несколько, то нужно проверять все окна. Что из общих параметров можно узнать еще об окне ??? Ну например можно узнать состояние окна, то есть : Функция IsIconic Синтаксис: function IsIconic(Wnd: HWnd): Bool; Описание: Опpеделяет, является ли окно пиктогpаммой (минимизиpованным). Параметры: Wnd: Идентификатор окна. Возвращаемое значение: Не нуль, если минимизиpовано; 0 - если нет. Функция IsWindow Синтаксис: function IsWindow(Wnd: HWnd): Bool; Описание: Опpеделяет, является ли окно допустимым существующим окном. Параметры: Wnd: Идентификатор окна. Возвращаемое значение: Не нуль, если окно достовеpно; 0 - если нет. Функция IsWindowEnabled Синтаксис: function IsWindowEnabled(Wnd: HWnd): Bool; Описание: Опpеделяет, является ли окно pазpешенным для ввода с мыши и с клавиатуpы. Параметры: Wnd: Идентификатор окна. Возвращаемое значение: Не нуль, если окно pазpешено; 0 - если нет. Функция IsWindowVisible Синтаксис: function IsWindowVisible(Wnd: HWnd): Bool; Описание: Опpеделяет, сделано ли окно видимым функцией ShowWindow. Параметры: Wnd: Идентификатор окна. Возвращаемое значение: Не нуль, если окно существует на экpане (даже если полностью закpыто); 0 - если нет. Функция IsZoomed Синтаксис: function IsZoomed(Wnd: HWnd): Bool; Описание: Опpеделяет, является ли окно максимизиpованным. Параметры: Wnd: Идентификатор окна. Возвращаемое значение: Не нуль, если окно максимизиpовано; 0 - если нет. Простой пример использования этих функций: function EnumProc (Wd: HWnd; Param: LongInt): Boolean; stdcall; // Обязательно stdcall !!! Var Nm:Array[0..255] of Char; // буфер для имени Cs: Array[0..255] of Char; // буфер для класса Ch:Char; //символ обозначающий, что окно минимизиравано Begin GetWindowText(Wd,Nm,255); // считываем текст заголовка окна GetClassName(Wd,Cs,255); // считываем название класса окна If IsIconic(Wd) then Ch:='+' Else Ch:='-'; // Добавляем название окна и класс в список первый символ + означает, что окно - иконка If Wd<>Form1.Handle then ListBox1.Items.Add(Ch+' '+String(Nm)+'/'+String(Cs)); EnumProc := TRUE; end;Работа с остальными функциями этой группы проводиться таким же образом, Вы получаете значение типа boolean, и что-то где-то отображаете. Кроме того, можно так же предусмотреть возможность отображать только окна определенного вида. Например, только видимые. Для этого достаточно вставить вместо строки If Wd<>Form1.Handle :: условие вида If ISWindowVisble(Wd) and (Wd<>Form1.Handle) then :.Впрочем, это уже на Ваш вкус, что отображать и как.
Все примеры, как бы являются функциями, которые можно вставлять в EnumProc например, и вызывать из нее передавая необходимые параметры. Получение данных о расположении окна: Процедура GetWindowRect Синтаксис: procedure GetWindowRect(Wnd: HWnd; var Rect); Описание: Считывает в ARect pазмеpности огpаничивающего пpямоугольника окна (в кооpдинатах экpана). Параметры:
Ничего сложного в этой функции нет, просто как пояснение к использованию: Function GetWinRect(Wd:HWND):TRect; Begin GetWindowRect(Wd,Result); End;Пpоцедуpа GetClientRect Синтаксис: procedure GetClientRect(Wnd: HWnd; var Rect: TRect); Описание: Считывает кооpдинаты пользователя окна. Параметры:
Синтаксис: function GetWindowDC(Wnd: HWnd): HDC; Описание: Считывает контекст дисплея, обычно используемый для pаскpаски в окне областей, не являющихся областями пользователя. Параметры: Wnd: Идентификатор окна. Возвращаемое значение: Идентификатор контекста дисплея; 0 - если ошибка. Функция возвращает контекст устройства, грубо говоря, то где это окно рисуется. А теперь реализуем пару своих функций, которые возвращают текущее окно в виде картинки BMP: Скопировать все окно в BMP Function WindowToBMP(WD: HWND ): TBitmap; Var WinDC: HDC; ARect : TRect; begin Result := TBitmap.Create; // Создаем рисунок, куда будем копировать GetWindowRect(WD, ARect); // Узнаем размер with Result, ARect do begin Width := ARect.Right - ARect.Left; Height := ARect.Bottom - ARect.Top; If (Width=0) or (Height=0) then Begin MessageDlg('Размер области формы равен нулю', mtWarning,[mbOk],0); // А вдруг у него нет размера ??? Exit; // Тогда выходим End; WinDC:=GetWindowDC(Wd); // получаем для окна контекст устройства ShowWindow(Wd, SW_SHOW); // на всякий случай выведем окно BringWindowToTop(WD); // и поместим поверх окон try // копируем оттуда прямоугольную область на канву // растрового изображения BitBlt( Canvas.Handle, 0, 0, Width, Height, WinDC, 0, 0, SRCCOPY); finally end; end; end;и функция, которая копирует только клиентскую часть окна в BMP Function WindowToBMP(WD: HWND ): TBitmap; Var WinDC: HDC; ARect : TRect; begin Result := TBitmap.Create; // Создаем рисунок, куда будем копировать GetClientRect(WD, ARect); // Узнаем размер with Result, ARect do begin Width := ARect.Right - ARect.Left; Height := ARect.Bottom - ARect.Top; If (Width=0) or (Height=0) then Begin MessageDlg('Размер области формы равен нулю', mtWarning,[mbOk],0); // А вдруг у него нет размера ??? Exit; // Тогда выходим End; WinDC:=GetWindowDC(Wd); // получаем для окна контекст устройства ShowWindow(Wd, SW_SHOW); // на всякий случай выведем окно BringWindowToTop(WD); // и поместим поверх окон try // копируем оттуда прямоугольную область на канву // растрового изображения BitBlt( Canvas.Handle, 0, 0, Width, Height, WinDC, 0, 0, SRCCOPY); finally end; end; end;Видно, что эти функции отличаются только определением области окна, которое будет скопировано. Сложностей с пониманием работы этих функций быть не должно, получили область копирования по описателю, вычислили размеры области копирования, получили контекст устройства, и скопировали. Кстати сказать, для того, чтобы скопировать весь экран или часть экрана можно использовать подобные функции. Единственное, что в таком случае придется поменять так это контекст устройства. Контекст устройства всего экрана 0. Ну и вместо того, чтобы получать область окна, нужно будет явно передавать координаты области, которую необходимо скопировать. Очень много информации об окне можно получить при помощи следующей функции: Функция GetWindowLong Синтаксис: function GetWindowLong(Wnd: HWnd; Index: Integer): Longint; Описание: Считывает инфоpмацию об окне или о значениях дополнительного байта окна. Паpаметpы:
Как пользоваться подобной функцией ?? Например получаем экземпляр приложения: Function GetHinstanse(WD:HWND):LongInt; Begin Result:=GetWindowLong(Wd, GWL_HINSTANCE); End;Похожим образом получается любая информация, только в качестве второго параметра Вы передаете тот флаг, который Вам необходим. Для интереса, можете посмотреть еще описание функции GetWindowWord она сходна с функцией GetWindowLong, но возможно получение несколько других параметров окна. Еще ряд параметров можно вытащить используя функцию: Функция GetClassLong Синтаксис: function GetClassLong(Wnd: HWnd; Index: Integer): Longint; Описание: Считывает из стpуктуpы окна TWndClass со смещением Index длинное значение. Положительные смещения в байтах (с нуля) используются для доступа к дополнительным байтам класса. Паpаметpы:
Function WinIconToBMP(Wd:HWND); Var Icon:HICON; // Тип указатель на иконку Begin Result:=TbitMap.Create; Icon:=GetClassLong(Wd,GCL_HICON); // Получаем иконку по описателю If ICON > 0 then // Если получена действительно иконка With Result do Begin Height:=31; Width:=31; Canvas.Brush.Color:=clWhite; Canvas.FillRect(Rect(0,0,31,31)); // На всякий случай заливаем белым DrawIcon(Canvas.Handle, 0, 0, Icon); // И отрисовываем ее на канве End; End;Как видно, процедура не такая уж и сложная. Для полноты информации можно еще извлечь идентификатор нити, к которой относиться окно. Функция GetWindowThreadProcessId Синтаксис: DWORD GetWindowThreadProcessId(Wnd: HWND; lpdwProcessId : LPDWORD); Описание: Возвращает идентификатор процесса к которому принадлежит данное окно Параметры: Wnd: Идентификатор окна. lpdwProcessId : 32битное значение идентификатора процесса Возвращаемое значение: идентификатор нити Как использовать данную функцию ?? Var mProcessID,mThreadID : Dword; Begin ...// Получение описателя в WD mThreadID:= GetWindowThreadProcessId(Wd,@mProcessID); // Получения идентификаторов. ... End;Эта функция хороша тем, что для всех окон одного приложения этот идентификатор будут един, если они запущены внутри одной нити (что зачастую и делается). То есть Вы можете разбить окна по нитям и /или по процессам, к которым они относятся. А так же Вы можете определять, какие окна данного приложения в настоящий момент доступны, видны, свернуты и т.д.
Описание функций API
Список текстов
Дмитрий Богданов |
Сообщ.
#2
,
|
|||||
|
Теперь, попробуем менять, что-то в чужих окнах. И вообще попробуем сделать с ними то же, что мы делаем со своими окнами. Сразу скажу, что тема эта неисчерпаема. Ей можно посвятить не одно скромное обозрение, а детальное многотомное издание. Я не ставлю своей задачей.
Несколько предварительных сурьезных слов. Вынужден сказать, что многое изложенное ниже может привести к неприятным последствиям. Например, к тому, что программа или система будет зависать. Поэтому будем считать, что читатель находиться в трезвом уме и здравой памяти и не будет совершать необдуманные действия. Прежде чем убить или закрыть чужое окно, подумайте, а зачем это окно вообще висит. Помните, что если окна висят в системе значит это кому то нужно ?! (почти Маяковский). Ну а теперь немного попугав для проформы перейдем к делу. Содержание:
Итак:
Для этого можно использовать одну из следующих функций:
Можно, так же, показать или скрыть окно, используя функцию API:
Давайте теперь попробуем решить ряд наиболее часто встречающихся проблем:
Далее попробуем определить, что именно содержится в системном меню (надо сказать, что приведенные ниже функции API справедливы для любых меню, а не только системных, но об этом несколько позже):
Если 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 указывает, что такого пункта в системном меню нет. ИМХО первый вариант более пригоден для получения списка строк системного меню, в то время как второй - для определения присутствует ли данная команда в системном меню. Количество элементов меню можно получить при помощи функции
Получение списка системного меню окна. :.. 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;Итак, мы получили список пунктов системного меню. Пустые строки, скорее всего, означают разделители. Так же используются акселераторы (&) Следующим шагом будет определение состояния того или иного пункта меню.
:.. 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;Точно так же можно определять и многие другие параметры пунктов меню. Для получения большего количества информации о пункте меню можно использовать
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;Как уже было сказано, это процедура будет работать далеко не для всех пунктов меню, например кнопку и пункт меню закрыть она будет запрещать очень даже хорошо, а вот например пункт развернуть далеко не всегда. Для того, чтобы сделать это наверняка нужно просто удалить такую возможность. Т.е. удалить соответствующий пункт системного меню.
// Отключает или разрешает так же пункт меню, и комбинацию 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. Ну, и, наконец, для развлечения тех, кто продрался сквозь все эти кошмары работы с системным меню, предлагаю маленькое развлечение. Иногда появляется необходимость нарисовать, что-нибудь (например, кнопку) в заголовке чужого окна (а возможно и своего). Это можно сделать очень и очень просто.
Заметьте, что это функция только рисует элемент заголовка. 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;
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;Теперь поговорим о, так называемом, подсвечивание окон. Например, при установке точки останова в программе главное окно начинает мерцать. И делает это до тех пор, пока пользователь не переключится в это окно. Как это делается ??? Существует пара функций:
Куда Вы все это вставите Ваши сложности можно в отдельный модуль можно в тот же что и программа. Если будете делать отдельный модуль, это будет выглядеть приблизительно так: 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;
ОПИСАНИЕ ФУНКЦИЙ API 19. SetForegroundWindow20. BringWindowToTop 21. ShowWindow 22. GetSystemMenu 23. GetMenuString 24. GetMenuItemCount 25. GetMenuState 26. GetMenuItemInfo 27. EnableMenuItem 28. DeleteMenu 29. AppendMenu 30. InsertMenuItem 31. DrawFrameControl 32. SetWindowText 33. FlashWindow 34. FlashWindowEx Список текстов 8. Свернуть все окна кроме текущего окна программы9. Закрыть все окна, содержащие определенную подстроку в заголовке 10. Получение списка системного меню окна. 11. Получение списка состояния системного меню окна. 12. Включение/выключение пункта меню 13. Удаление или восстановление кнопки закрыть окно [х]. 14. Отрисовка <фальшивой> кнопки закрыть в заголовке окна. 15. Замена текста в заголовке окна. 16. Определение не является ли данное окно зависшим 17. Мигающий заголовок окна Дмитрий Богданов |
Сообщ.
#3
,
|
|
|
Оригиналы статей взяты отсюда:
http://www.delphikingdom.ru/helloworld/wininf.htm http://www.delphikingdom.ru/helloworld/wininf01.htm |