На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: jack128, Rouse_, Krid
  
    > Перечисление окон в системе
      procedure TForm1.Button1Click(Sender: TObject);
      VAR
      Wnd : hWnd;
      buff: ARRAY [0..127] OF Char;
      begin
      ListBox1.Clear;
      Wnd := GetWindow(Handle, gw_HWndFirst);
      WHILE Wnd <> 0 DO BEGIN {Не показываем:}
      IF (Wnd <> Application.Handle) AND {-Собственное окно}
      IsWindowVisible(Wnd) AND {-Невидимые окна}
      (GetWindow(Wnd, gw_Owner) = 0) AND {-Дочернии окна}
      (GetWindowText(Wnd, buff, sizeof(buff)) <> 0) {-Окна без заголовков}
      THEN BEGIN
      GetWindowText(Wnd, buff, sizeof(buff));
      ListBox1.Items.Add(StrPas(buff));
      END;
      Wnd := GetWindow(Wnd, gw_hWndNext);
      END;
      ListBox1.ItemIndex := 0;
      end;


      Также эту задачу можно выполнить через EnumWindows(), EnumChildWindows() более красиво.
        Очень часто функции косвенного вызова используются при перечислении некоторых объектов. В качестве примера рассмотрим перечисление окон с помощью функции EnumWindows. В справке она описана так:
        BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
        Соответственно, в Windows.pas она имеет вид
        ExpandedWrap disabled
          function EnumWindows(lpEnumFunc: TFNWndEnumProc; lParam: LPARAM): BOOL; stdcall;


        тип TFNWndEnumProc совпадает с типом Pointer. Здесь должен стоять указатель на callback функцию. Синтаксис этой функции описан так:
        ExpandedWrap disabled
          BOOL CALLBACK EnumWindowsProc(HWND  hwnd, LPARAM  lParam);

        Функции с таким именем не существует в Win API. Это так называемый прототип функции, согласно которому следует описывать callback функцию. На самом деле этот прототип предоставляет большую свободу, чем это может показаться на первый взгляд. Как я уже сказал выше, имя может быть любым. Любыми могут быть и типы функции и параметров, при условии что новые типы совпадают по размерам с теми, которые указываются. Что касается типа функции и типа первого параметра, то они имеют определённый смысл и менять их тип практически бессмысленно. Другое дело со вторым параметром. Он предназначен специально для передачи значения, которое программист волен использовать по своему усмотрению, система не имеет на него никаких видов. А программисту может показаться удобнее работать не с типом LPARAM (то есть LongInt), а, например, с указателем или же с массивом из четырёх байт. Лишь бы были именно четыре байта, а не восемь, шестнадцать или ещё какое-то число. Можно даже превратить этот параметр в параметр-переменную, так как при этом функции будут передаваться всё те же четыре байта - адрес переменной. Но эти удовольствия для тех, кто хорошо разбирается с тем, как используется стек для передачи параметров при различных моделях вы-зова.

        Как же работает EnumWindows? После вызова эта функция начинает по очереди перебирать все имеющиеся в данный момент окна верхнего уровня, то есть те, у которых нет родителя. Для каждого такого окна вызывается эта самая callback функция, в качестве первого параметра ей передаётся дескриптор данного окна (каждый раз, естественно, новый), в качестве второго - то, что было передано самой функции EnumWindows в качестве второго параметра (каждый раз одно и то же). Что же может делать callback функция с этим дескриптором? А всё, на что у программиста хватит фантазии. Например, можно минимизировать или вообще закрыть все эти окна, хотя не понятно, с чего бы вдруг устраивать такую диверсию. Или можно проверять все эти окна на соответствие какому-то условию, пытаясь найти нужное. А значение, возвращаемое callback функцией, влияет на работу EnumWindows. Если она возвращает False, значит, всё, что нужно, уже сделано, можно не перебирать остальные окна.

        Окончательный код для того случая, когда второй параметр имеет тип Pointer, выглядит так:
        ExpandedWrap disabled
          function MyCallbackFunction(Wnd:HWnd; P: Pointer):Bool; stdcall;
           begin
            {  что-то делаем  }
           end;
          ..............
          var MyPointer:Pointer;
          ..............
          EnumWindows(@MyCallbackFunction, LongInt(MyPointer));


        Что бы мы ни делали с типом второго параметра callback функции, тип соответствующего параметра EnumWindows не меняется. Поэтому необходимо явное приведение передаваемого параметра к типу LongInt. Обратное преобразование типов при вызове MyCallbackFunction осуществляется автоматически.

        В 16-разрядных версиях Windows вызов callback функций осложнялся тем, что для них необходимо было делать специальный код, называемый прологом. Пролог создавался с помощью функции MakeProcInstance, удалялся после завершения с помощью FreeProcInstance. То есть вызов EnumWindows должен был бы выглядеть так:
        ExpandedWrap disabled
          var MyProcInstnace: TFarProc;
          ...................
          MyProcInstance := MakeProcInstance(@MyCallbackFunction, HInstance);
          EnumWindows(MyProcInstance, LongInt(MyPointer));
          FreeProcInstance(MyProcInstance);


        WM_SetIcon должно вернуть дескриптор иконки, которая была установлена ранее. Если программист не хочет обрабатывать сообщение самостоятельно, он должен вызвать для его обра-ботки функцию DefWindowProc.

        Это сообщение было перенесено сюда или объединено из темы "Перечисление окон в системе"
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script execution time: 0,0202 ]   [ 16 queries used ]   [ Generated: 28.04.24, 08:46 GMT ]