Simulating the Windows API's FindWindow function with Kylix

By: Matthias Thoma

Abstract: This article descripes a very handy FindWindow function. By Matthias Thoma.

The XWindow interface library, XLib, doesn't have a ready-to-use equivalent of the Windows API's FindWindow function. However, it is possible to get the name of a window with a known ID very easily. The XFetchName function delivers it to you:

function XFetchName(Display: PDisplay; W: TWindow; 
 WindowNameReturn: PPChar): TStatus; cdecl;

The harder step is to get the IDs of every window. For that, you need XLib's XQueryTree function, which retrieves, for a given window, the list of children, the root, the parent, and the number of children. By combining these two functions and a standard search algorithm you can get the same functionality as the Windows FindWindow function:


function XQueryTree(Display: PDisplay; W: TWindow; RootReturn: PWindow; 
 ParentReturn: PWindow; _para5: PPWindow; NChildrenReturn: PCardinal): TStatus;

The following code shows how to do it. It is a Kylix translation of a public domain source by Brian Paul.


{ FindWindow Function

  Derived from an original C source by Brian Paul. Released
  to public domain.

  Kylix Translation: Matthias Thoma


  Input:  dpy   - the X display
          scr   - the X screen number
          start - where to start search, usually root window
          name  - the window name to search for
}


function FindWindow(Display: PDisplay; Screen: Integer; Start: TWindow; Name: PChar): TWindow;
type
   AChildren = array[0..0] of Window;
   PChildren = ^AChildren;

var
  stat: TStatus;
  n: Integer;
  num: Cardinal;
  w: Window;
  root: Window;
  parent: Window;
  Children: PChildren;
  Title: PChar;


begin
   if (XFetchName(Display, Start, @Title) = 1) then
   begin
      if (strcmp(Name, Title )=0) then
      begin
         XFree(Title);
         Result := Start;
         Exit;
      end;
      XFree(Title);
   end;

   stat := XQueryTree(Display, start, @root, @parent, @children, @num);

   if (stat = 1) then
   begin
      { search each child window for a match: }
      for n := num-1 downto 0 do
      begin
         if (XFetchName(Display, start, @title )=1) then
         begin
            if (strcmp(name, title)=0) then
            begin
               { found it }
               XFree(Title);
               Result := Start;
               Exit;
            end;
            XFree(Title);
         end;
      end;

      { search the descendents of each child for a match: }

      for n := num-1 downto 0 do
      begin
         w := FindWindow(Display, Screen, Children^[n], Name);
         if (w <> 0) then
         begin
            XFree(Children);
            Result := w;
            Exit;
         end;
      end;

      if (children <> Nil) then
      begin
         XFree(Children);
      end;
   end;

   Result := 0;
end;

You can use this function to find out if Kylix is running:


function IsKylixRunning: Boolean;
begin
  Result := FindWindow(QtDisplay,XDefaultScreen(QtDisplay),XDefaultRootWindow(QtDisplay),'Kylix') <> 0;
end;

Or maybe you'll want some IFDEFs, since Delphi is now cross-platform:


function IsDelphiRunning: Boolean;
begin
  Result := False;

{$IFDEF LINUX}
  Result := FindWindow(QtDisplay,XDefaultScreen(QtDisplay),XDefaultRootWindow(QtDisplay),'Kylix') <> 0;
{$ENDIF}

{$IFDEF WIN32}
   Result := FindWindow('TAppBuilder', nil) <> 0;
{$ENDIF}
end;

Server Response from: SC1