Autor Beitrag
FinalFantasy
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 127

Windows XP
Delphi 5 Professional, Visual Studio 7 .NET (C#)
BeitragVerfasst: Di 20.09.05 15:46 
Hi,

Ich bin auf der Suche nach allen Fenstern auf meinem Desktop. FindWindow liefert mir aber Tausende von Handles die zu irgendwelchen Sachen gehören... Jetzt bin ich schonmal auf die Idee gekommen, alle Fenster die Parentfenster haben oder bei denen length(caption) = 0 zutrifft, auszufiltern. Das hat meine Liste schonmal deutlich minimiert, aber ich finde immernoch sehr viele Handles, die offensichtlich nicht zu einem richtigem Fenster gehören.
So, wie kann ich jetzt die Fenster rausfiltern, die wirklich ein Fenster sind (also eigentlich alles, was auch bei Alt+Tab auftaucht, nicht mehr und nicht weniger), und zusätzlich müsste ich noch rausfinden, ob die Fenster auf Always on Top gesetzt sind....
Hat jemand eine Idee, wie man das machen kann/könnte?

Achja, und das Fenster meiner Applikation sollte unsichtbar sein (also auch nicht in der Taskleiste auftauchen), die Visible-Property des Forms scheint Delphi aber nicht sonderlich zu interessieren, und im OnCreate kann ich ja Hide() noch nicht aufrufen, weil das Fenster ja noch gar nicht existiert....
matze
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: Di 20.09.05 15:57 
Wenn du 2 Fragen hast, dann stell bitte jede Frage in einem seperaten Topic.

_________________
In the beginning was the word.
And the word was content-type: text/plain.
FinalFantasy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 127

Windows XP
Delphi 5 Professional, Visual Studio 7 .NET (C#)
BeitragVerfasst: Di 20.09.05 16:20 
Ja, sorry.

EnumWindows scheint genau das zu sein, was ich Suche.
Allerdings krieg ich bei dem Aufruf der Funktion den Fehler "Variable erforderlich":
ausblenden Delphi-Quelltext
1:
  EnumWindows(@EnumWinProc, 0);					


EnumWinProc sieht dabei so aus:
ausblenden Delphi-Quelltext
1:
function TfrmOnTopControl.EnumWinProc(Wnd: THandle; LParam: LongInt): Boolean; stdcall;					


Ist also eine Memberfunktion der Klasse.
Bekomme aber den selben Fehler, wenn ich es als Funktion deklariere.

Das ganze stammt von hier: www.delphi-forum.de/...ighlight=enumwindows
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Di 20.09.05 19:20 
nimm Suche im MSDN ENUMDESKTOPWINDOWS, damit kriegst du alle top-level windows.
die enumwindowsproc darf übrigens kein mitglied einer klasse sein.

_________________
es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 20.09.05 19:26 
EnumWindows liestet auch nur Top-Level-Fenster auf, aber nicht jedes Top-Level-Fenster ist auch automatisch in der Taskleiste bzw im Alt-Tab-Fenster.
EnumDesktopWindows ist was ganz andres - hier werden die Fenster eines bestimmten Desktops aufgelistet, wobei ein "Desktop" hier ein absolut andere Bedeutung als im üblichen Sprachgebrauch hat, hier ist ein Desktop nämlich ein Security-Objekt - ein Teil einer WindowStation.

Gruß, Motzi

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Di 20.09.05 19:31 
user profile iconMotzi hat folgendes geschrieben:

EnumDesktopWindows ist was ganz andres...

ok, und was würdest du vorschlagen ? ich habe das mal so gemacht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
//style: integer
    style:=getwindowlong(wnd,GWL_STYLE);
    if (style and WS_VISIBLE) <> 0 then           //inttostr(style) + ',' +
    if (style and WS_SYSMENU) <> 0 then

das liefert ganz brauchbare ergebnise, aber es entspricht nicht genau dem resultat der taskbar.

_________________
es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 20.09.05 20:08 
Mit GetWindowLong() bist du schon am richtigen Weg, allerdings solltest du statt GWL_STYLE GWL_EXSTYLE nehmen und auf WS_EX_APPWINDOW testen...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Di 20.09.05 21:21 
das funktioniert nicht wirklich.
nimm z.b. den VLC mediaplayer (0.8.2) , der hat folgende Styles:
ausblenden Quelltext
1:
2:
3:
4:
5:
WS_OVERLAPPEDWINDOW
WS_VISIBLE
WS_CLIPSIBLINGS
WS_CLIPCHILDREN
WS_OVERLAPPED


Extended:
ausblenden Quelltext
1:
2:
3:
4:
WS_EX_LEFT
WS_EX_LTRREADING
WS_EX_RIGHTSCROLLBAR
WS_EX_WINDOWEDGE


von WS_EX_APPWINDOW keine spur, trotzdem ists in der taskleiste drin ^^

_________________
es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
FinalFantasy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 127

Windows XP
Delphi 5 Professional, Visual Studio 7 .NET (C#)
BeitragVerfasst: Mi 21.09.05 08:43 
Habs jetzt EnumWindows zum laufen gebracht... allerdings findet EnumWindows auch viel zu viele Fenster, ähnlich wie FindWindow...

GetWindowsLong findet dagegen kein einziges Fenster mit der WS_VISIBLE-Eigenschaft, aber da sind definitiv welche da!!

Mit WS_EX_APPWINDOW wird mein Feierabendcountdown gefunden (der hat zwar ein Fenster, ist aber ins Systemtray minimiert), Outlook und die MSDN werden gefunden... Opera, Delphi, Delphi-Hilfe und sich selbst findet es damit jedoch auch nicht....

Was für ein gefummel...

[EDIT]:

Sorry, war mein Fehler... die Flags von GWL_STYLE sind nicht in GWL_EXSTYLE enthalten.... logisch, dass kein Fenster WS_VISIBLE hat, wenn ich GetWindowLong mit GWL_EXSTYLE aufrufe...
Ich hole mir jetzt beide Styles, weil ich gesehen hab, dass im Ex-Style die TopMost Eigenschaft drin steckt... (womit eine weitere Frage beantwortet wäre)
WS_VISIBLE liefert (wenn man es richtig macht :-)) doch ganz brauchbare Ergebnisse, da ich ja nur die Fenster haben will, die man auch sehen kann *gg*
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Do 22.09.05 14:17 
Ok, du hast recht, nicht jedes Fenster das in der Taskbar ist hat WS_EX_APPWINDOW gesetzt, aber jedes Fenster das WS_EX_APPWINDOW gesetzt hat, ist auch in der Taskbar! ;)
Weiters - jedes Fenster, das WS_EX_TOOLWINDOW gesetzt hat ist nicht in der Taskbar.

Ich hab mal einen bisschen Code von mir zusammengesucht und mal das zusammengeklickt:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
function GetWindowText(wnd: Hwnd): String;
var
  dwResult: DWord;
  pBuffer: PChar;
begin
  SetLastError(0);
  if SendMessageTimeOut(wnd, WM_GETTEXTLENGTH, 00, SMTO_NORMAL,
    750, dwResult) = 0 then
  begin
    if GetLastError = ERROR_TIMEOUT then
      Result := '<SendMessage timed out>'
    else
      Result := '<SendMessage failed>';
    Exit;
  end;
  Inc(dwResult);

  pBuffer := GetMemory(dwResult);
  try
    if SendMessageTimeOut(wnd, WM_GETTEXT, dwResult, Integer(pBuffer),
      SMTO_NORMAL, 750, dwResult) = 0 then
    begin
      if GetLastError = ERROR_TIMEOUT then
        Result := '<SendMessage timed out>'
      else
        Result := '<SendMessage failed>';
    end
    else
      Result := String(pBuffer);
  finally
    FreeMemory(pBuffer);
  end;
end;


function GetClassName(wnd: Hwnd): String;
var
  szBuffer: array [0..255of Char;
  iCount: Integer;
begin
  ZeroMemory(@szBuffer, SizeOf(szBuffer));
  iCount := Windows.GetClassName(wnd, szBuffer, SizeOf(szBuffer));
  if wnd = GetDesktopWindow then
    StrPCopy(@szBuffer[iCount], 'Desktop');

  Result := String(szBuffer);
end;

function enumProc(wnd: Hwnd; Listbox: TListBox): Boolean; stdcall;
var
  dwStyle: DWord;
  bAdd: Boolean;
begin
  Result := true;
  if IsWindowVisible(wnd) then
  begin
    bAdd := True;
    dwStyle := GetWindowLong(wnd, GWL_STYLE);
    bAdd := bAdd and (dwStyle and WS_POPUP = WS_POPUP);

    dwStyle := GetWindowLong(wnd, GWL_EXSTYLE);
    bAdd := bAdd or (dwStyle and WS_EX_APPWINDOW = WS_EX_APPWINDOW);
    bAdd := bAdd and not (dwStyle and WS_EX_TOOLWINDOW = WS_EX_TOOLWINDOW);

    if bAdd then
      Listbox.Items.Add('0x' + IntToHex(wnd, 8) + ' - ' + GetClassName(wnd) +
      ' - ' + GetWindowText(wnd));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  EnumWindows(@enumProc, Integer(ListBox1));
end;


Das funktioniert schon ganz gut, man muss es aber noch ein bisschen verfeinern, bei mir findet er alle Fenster bis auf den Firefox.

Gruß, Motzi

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!