Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Как найти все видимые окна


Автор: Тутанхамец 20.1.2007, 16:45
Здравствуйте. Вывожу в listbox все верхнеуровневые видимые окна с помощью EnumWindows. Получилось следующее:
Код

function MyEWP(handle:HWND; param:LPARAM):boolean;
var
  s:string;
  n:integer;
  ws:DWORD;
begin
  n:=getwindowtextlength(handle);
  if n>255 then n:=255;
  if n>0 then begin
    ws:=GetWindowLong(handle,GWL_STYLE);

    if (ws and WS_VISIBLE)=WS_VISIBLE then begin
      setlength(s,n);
      getwindowtext(handle,pansichar(s),255);
      form1.listbox1.items.add(inttostr(n)+'  '+s);
    end;
  end;
  result:=true;
end;


Однако в списке есть окна, которых на экране нет. Например моя же прога, у которой одна форма с visible=false. А еще Program Manager. Как мне найти только те окна, которые на самом деле видно? 

Автор: Romikgy 20.1.2007, 17:50
имхо
EnumWindows+IsWindowVisible

Автор: Тутанхамец 20.1.2007, 18:13
Нет, результат тот же. Например для дельфы находится три окна, для которых GetWindowText дает: Delphi 7 - Project 1[running], Unit1.pas и Delphi7. Последнего окна на экране не наблюдаю. То же самое для некоторых других программ. А вот например для Блокнота - всё в порядке, одно окно. Что бы это значило?

Добавлено @ 18:23 
Такое чувство, что дельфа создает несколько обычных окон, которые все привыкли видеть, и одно как бы основное, особенное. Эта особенность - та же самая, что у окна Program Manager, которое я на экране тоже не вижу. Но в списке оно есть. Сформулируем вопрос так: в чем состоит особенность этих окон и как их отфильтровать из списка? 

Автор: Romikgy 20.1.2007, 18:27
у дельфи приложений, есть 2 окна визуальных(это если одна форма) имхо, одно отвечает за форму
а второе за отображение окна на панельке( таск бар)

Автор: Тутанхамец 20.1.2007, 18:27
Въехал! "Лишнее" окно Delphi7 - это его "закладка" на Панели Задач! Теперь остается понять, как его отфильтровать.

Добавлено @ 18:28 
Синхронно мыслим. 

Автор: Romikgy 20.1.2007, 18:32
имхо окно на палеле будет иметь класс типа Tapplication или унаследован от него

Автор: Тутанхамец 20.1.2007, 18:38
Это, я так понимаю, в случае с делфи. А мне еще надо избавиться в списке от:
1) окна Program Manager - что это кстати такое? Рабочий стол что ли?
2) всех окон, которые находятся на таскбаре.

Ну если програм манагер это рабочий стол, то можно проверять хэндл найденного окна на равенство GetDesktopWindow... Правильно? А со вторым пунктом как быть? 

Если окно на таскбаре, то таскбар является его owner'ом? А как взять окно самого таскбара?

Автор: Sunvas 20.1.2007, 18:47
Код

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;

Оттестеный первоклассный код.  smile 

Автор: Тутанхамец 20.1.2007, 19:04
Sunvas, Код первоклассный, но это немножко не то, что мне надо. 
Прога моя должна работать так:
1) она вывела в CheckListBox список окон на экране. 
2) юзер ставит галочки напротив окон
3) те окна, которые он пометил галочками, становятся TOPMOST.

Трабл в том, что окно "Delphi - Project1 [running]" мне нужно иметь в списке. Такое окно юзер, возможно, захочет иметь на переднем плане. 

А окно "Delphi7", которое на таскбаре, из списка надо вычеркнуть. На фиг его делать TOPMOST.

Ты, Sunvas, предлагаешь такое исключительно таскбарное окно отличать по (GetWindow(Wnd, gw_Owner) = 0). Но в этом случае, из списка вылетает и например Acrobat Reader, который юзер минимизировал на таскбар. А он в списке нужен. 

А теперь, когда я это написал, мне думается вот что: наверное, когда я минимизирую Acrobat, его окно становится невидимым, а на таскбаре возникает совсем другое окно. То есть описываемым способом я не могу сделать TOPMOST минимизированный Acrobat. Я прав?

Добавлено @ 19:18 
Был не прав. Acrobat Reader становится TOPMOST даже в свернутом виде (когда его потом разворачиваю). Это проги, написанные на делфи, почему-то отличаются от других прог. 

Автор: Sunvas 20.1.2007, 19:27
Цитата(Тутанхамец @  20.1.2007,  19:04 Найти цитируемый пост)
Трабл в том, что окно "Delphi - Project1 [running]" мне нужно иметь в списке. Такое окно юзер, возможно, захочет иметь на переднем плане. 

А окно "Delphi7", которое на таскбаре, из списка надо вычеркнуть. На фиг его делать TOPMOST.

Ты, Sunvas, предлагаешь такое исключительно таскбарное окно отличать по (GetWindow(Wnd, gw_Owner) = 0). Но в этом случае, из списка вылетает и например Acrobat Reader, который юзер минимизировал на таскбар. А он в списке нужен. 

Закоментируй строку: 
Код

//(GetWindow(Wnd, gw_Owner) = 0) AND {-Дочернии окна}

И будет тебе счастье.
Цитата(Тутанхамец @  20.1.2007,  19:04 Найти цитируемый пост)
А теперь, когда я это написал, мне думается вот что: наверное, когда я минимизирую Acrobat, его окно становится невидимым, а на таскбаре возникает совсем другое окно. То есть описываемым способом я не могу сделать TOPMOST минимизированный Acrobat. Я прав? 

Нет. То, что мы видим на таскбаре, это как бы "главное окно", а все остальные - дочерные. Свернутое окно <> невидимому на программном уровне.

Автор: Тутанхамец 20.1.2007, 19:46
Цитата

Нет. То, что мы видим на таскбаре, это как бы "главное окно", а все остальные - дочерные. Свернутое окно <> невидимому на программном уровне. 

Ага. В общем ситуация проясняется. Спасибо. 

Но почему-то прога, написанная на VB, тоже видна в списке, хотя у нее form1.visible=false. 
Цитата

И будет тебе счастье

Мое счастье "будет неполным", потому что одни окна с нулевым родителем я хочу видеть в списке, а другие нет. smile  Я тут прочитал в нете, что это специфика дельфовских прог - они создают специальное окошко на таскбаре. Наверное, надо, как советовал Romikgy, проверять их класс на TApplication. Но это уже завтра... Всем спасибо smile 

Автор: Sunvas 20.1.2007, 20:03
Получилось примерно так:
Код

VAR
Wnd : hWnd;
buff: ARRAY [0..127] OF Char;
wclass:string;
begin
ListBox1.Clear;
Wnd := GetWindow(Handle, gw_HWndFirst);
WHILE Wnd <> 0 DO BEGIN {Íå ïîêàçûâàåì:}
        setLength(wclass,12);
        GetClassName(wnd,@wclass[1],Length(wclass)+1);
IF (Wnd <> Application.Handle) AND {-Ñîáñòâåííîå îêíî}
IsWindowVisible(Wnd) AND {-Íåâèäèìûå îêíà}
//(GetWindow(Wnd, gw_Owner) = 0) AND {-Äî÷åðíèè îêíà}
(GetWindowText(Wnd, buff, sizeof(buff)) <> 0)
and (wclass<>'TApplication')
THEN BEGIN
GetWindowText(Wnd, buff, sizeof(buff));
ListBox1.Items.Add(StrPas(buff));
END;
Wnd := GetWindow(Wnd, gw_hWndNext);
END;
ListBox1.ItemIndex := 0;


Автор: Тутанхамец 21.1.2007, 09:37
Да, точно smile Спасибо smile 

Я еще отфильтровываю Program Manager и главное окно VB-шных прог:

Код

function MyEWP(handle:HWND; param:LPARAM):boolean;
var
  s:string;
  n,k:integer;
  styles:DWORD;
  class_name:string;
begin
  n:=getwindowtextlength(handle);
  if n>255 then n:=255;
  if n>0 then begin
    setlength(class_name,255);
    k:=GetClassName(handle,pansichar(class_name),255);
    setlength(class_name,k);
        if ((iswindowvisible(handle)) 
          and (class_name<>'Progman') 
                  and (class_name<>'TApplication') 
                          and (class_name<>'ThunderRT6Main'))  then begin
      setlength(s,n);
      getwindowtext(handle,pansichar(s),255);
          if (trim(s)<>'') then begin
          //  s:=s+'   '+class_name;
            if IsIconic(handle) then s:=s+' (on taskbar)';
            n:=form1.clbWindows.items.add(s);
            handles.Add(inttostr(handle));
            styles:=GetWindowLong(handle,GWL_EXSTYLE);
            form1.clbWindows.Checked[n]:=  ((styles and WS_EX_TOPMOST)=WS_EX_TOPMOST);
          end;
     end;
  end;
  result:=true;
end;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)