We help IT Professionals succeed at work.

Window Handlers

VoidHawk
VoidHawk asked
on
452 Views
Last Modified: 2013-12-03
Due to a lack of reference material on my behalf, I'm having difficulty in implementing the following:

I wish to execute an installed application, say an instance of MS Internet Explorer, and return the window handle of the browser window it opens so that I may retrieve its coordinates, send commands such as maximise, setfocus, set the window size, retrieve the title bar contents, etc.

Additionally (or if the above is not possible) I want to be able to return the handles of all top level windows belonging to a running process eg "iexplore.exe". I've attempted using EnumWindows in conjunction with EnumWindowsProc, searching for handles based in title contents. I know its not the best solution, but I'd like to know where I went wrong since I always get stuck in an infinite loop. The code is as follows:

What I tried to do here is append the title of each window to a message box's contents. If it weren't for the counter to forcibly stop the process, it would simply loop infinately through the titles of each window over and over again.

I'm using Borland C++ Builder 5.

//--------------------------------------

TForm1 *Form1;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
      char text[200];
      GetWindowText(hwnd,text,200);
      Form1->Memo1->Lines->Add(text);
      Form1->counter++;
      if (Form1->counter == 1000) return FALSE;
      return TRUE;
};

//--------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{

      HWND hwnd;
      LPARAM lParam = 0;

    Form1->counter = 0;

      while(EnumWindows((WNDENUMPROC)EnumWindowsProc, lParam))
      {
            EnumWindowsProc(hwnd,lParam);
      }

}
//--------------------------------------


I would greatly appreciate code examples.
Comment
Watch Question

Commented:
The reason you're getting an infinite loop is because you appear to have misunderstood how EnumWindows() works. EnumWindows() does all the calling of EnumWindowsProc() for you, and it only returns FALSE if it encounters an error. Therefore, what your WHILE loop above will do is: firstly enumerate all the windows on the system via EnumWindows(). EnumWindows() will almost certainly succeed, so you then call EnumWindowsProc() with a garbage window handle (since you never assign anything to hWnd). It then goes round the loop again, enumerating the windows again.

*All* the windows EnumXXX functions work this way, which is why you pass them the address of the enumeration procedure in the first place!
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION

Commented:
pjknibbs is completely right. Just one addition: If you've enumerated all windows of that main thread, the question is still: Which one is (or are) the main window(s)?
Main windows (that is windows that are visible as buttons in the taskbar) don't have a parent window nor an owner window. Also they must be visible and must not have the WS_EX_TOOLWINDOW style bit set in the extended window style. (APIs GetWindow(window, GW_OWNER), GetParent(window), GetWindowLong(window, GWL_EXSTYLE))

Regards, Madshi.

Commented:
.. and IsWindowVisible(window)...

Author

Commented:
Thanks very much for that - It really clears things up. I was using a code example written by someone else for EnumWindows. I have altered it to the following.

//--------------------------------------

TForm1 *Form1;

bool EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
      char text[200];
      GetWindowText(hwnd,text,200);
      Form1->Memo1->Lines->Add(text);
      return TRUE;
};

//--------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
      EnumWindows((WNDENUMPROC) EnumWindowsProc,NULL);
}
//--------------------------------------

Just for clarification, Why must I use (WDENUMPROC) in EnumWindows? And why won't it work without the brackets?

As for CreateProcess(), I was looking at ShellExecute() which only returned the application's instance handle.

One last thing, as I asked in my initial question, is it possible to go through all of the active processes and return the window handles from a process of a particular name without knowing its process ID? eg. search for all instances of iexplore.exe and return its top level window handles?

Oh to be able to afford a decent reference book. (Student budget)

Commented:
>> Just for clarification, Why must I use (WDENUMPROC) in EnumWindows? And why won't it work without the brackets?

Well, I'm using (and loving) Delphi, there are no such syntax mysteriums...  :-)

>> As for CreateProcess(), I was looking at ShellExecute() which only returned the application's instance handle.

You can't do anything with the instance handle. Neither can you do something (that helps you with finding the windows) with the process handle that you can get from ShellExecuteEx. So CreateProcess is the way to go here.

>> is it possible to go through all of the active processes and return the window handles from a process of a particular name without knowing its process ID? eg. search for all instances of iexplore.exe and return its top level window handles?

I told you how to find the top level windows from the PID. So the only part missing is: How to get the PID of all running iexplore.exe instances? That's quite ugly. It's different under win9x and winNT. Under win9x you have to use the toolhelp functions, under winNT the library "psApi.dll" (which you have to distribute with your app).

Regards, Madshi.

Commented:
(WNDENUMPROC) is just there to keep your compiler happy. It tells it that yes, the function you are supplying *is* of the correct form for an EnumWindows() callback even if the compiler doesn't think it is. You could avoid using this if you declared EnumWindowsProc() *exactly* as it is in the header files rather than the documentation, but who has time to search the headers when a cast is quicker?

As for searching for all instances of a running application, Madshi's right--it's different under Win9x and NT, and it's probably not something you want to get into unless you enjoy grubbing around in the guts of Windows.

Author

Commented:
Thanks a lot for that. I think I'm just going to have to dig deep and get myself a decent reference book or two.

Id love to be able to throw a few well earned points Madshi's way, but unfortunately I you only get to designate one recipient. I think I'll throw that into the suggestions box.

Commented:
No problem for me...  :-)

Yes, please do that suggestion. A lot of people have suggested that already, but nothing changed yet. But the more people say something the better are our chances that we'll see a point splitting feature soon.
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.