Re: FindWindow is hanging....

From: Joseph M. Newcomer (newcomer_at_flounder.com)
Date: 06/11/04


Date: Fri, 11 Jun 2004 17:27:55 -0400

Personally, I believe this is not only the worst possible way to find another window, but
it is so unreliable that it cannot be trusted. Not because the call is unreliable, but
because any string you have depends on the fact that you are looking for a specific window
in a specific version of the app, in a spectic language. So while the call works reliably,
the program that uses it would have to take all of these conditions into account, and
therefore the chances that it will work correctly in all conditions is minimal. For
example, it is possible to edit the resource segment of an app and merely change the
language strings (our European distributors do this all the time), so another app that
expects to find English language strings would be doomed. I've had to fix these problems
in many of my clients' programs, which is one reason I never do anything that has the
potential to be language-specific, and I never hardwire an English-language string
anywhere in my apps.

Since you are on CE, you could have additional problems that we don't see in desktop
systems.

But if you are writing both apps, there are a number of things you can do. For example, a
shared data segment in a DLL where the app that is the "service" puts its handle, and the
app that is the "client" can read the handle, would be a more reliably approach. Of
course, the "server" should, on its ExitInstance, set this handle to NULL, and the
"client" should occasionaly do an ::IsWindow, just to be sure everything is valid

If you are looking for some other app that you didn't write, you are probably in trouble.

If you use "Dialog", this gives you an 8-bit character string. This will not work on CE,
which uses Unicode. You could explicitly say L"Dialog", and it would only work in Unicode
versions, which would be fine for CE but if you wanted a desktop version, this might be an
annoyance. _T("Dialog") says "Make this an 8-bit or 16-bit literal depending on the
compilation mode", and is the preferred method.

Since I don't trust FindWindow as far as I can throw a mainframe, I can't answer the
question about whether or not there would be any difference in the nature of the calls.
And I've never written a CE program, so I'm not sure what other properties of CE differ
from desktop systems (CE is a totally separate code base, written from scratch, and shares
only the abstract API interface with the desktop systems. There are substantial
differences, some necessary, some merely gratuitous).

                        joe

On Fri, 11 Jun 2004 10:49:16 -0700, Wes Jones <nospam@spam.com> wrote:

>Hi all,
>
>I have an app that uses FindWindow to find the window handle to another
>app's window, and it looks like it is hanging. It doesn't do it every
>time, but from my logging statements, I can tell that FindWindow is the
>last thing called when it's hung up.
>
>I've seen the various articles/comments about the dangers of using
>FindWindow, ie: uses SendMessage internally & can hang if another app's
>thread is waiting/hung, etc.
>
>I have written an alternative function for some other purpose that works
>similarly to FindWindow but checking all the top level windows, starting
>w/ the desktop window, but that too uses GetWindowText (ie:
>SendMessage()) & I think will have the same liability.
>
>My question is: What's a good alternative to using FindWindow ?
>
>I would alter my similar function to use SendMessageTimeout, but I am
>using Windows CE, and that function is not supported.
>
>Please help, won't you?
>
>What are the alternatives to using FindWindow?
>
>Here are some details about how I'm using FindWindow:
>-------------
>LPCTSTR szPossibleNames[] = { _T("name1"), _T("name2"),...,_T("nameN") };
>for(int i=0; i < X; ++i){
> if( FindWindow(NULL, szPossibleNames[i]) )
> break;
>}
>//other stuff...
>-------------
>
>
>Is using FindWindow in a loop like this just asking for trouble? It's
>like I'm making it do risky things over & over again....
>
>
>Just for fun, and in the case it can help somebody point out an
>alternative to me, here's the code for my 'alternative func':
>
>-----------------------------------
>HWND FindChildAmongManyChildDialogs(
>HWND hWndMain,
>LPCTSTR szClassName,
>LPCTSTR szWindowTitle)
>//
>//This function was written to
>//find a child window when there is a main
>//window, and then several dialogs that
>//are children, and the window we want
>//is on one of those dialogs.
>//
>//This is based on the AirCard 555 watcher program,
>//and Remote Spy++
>//
>//
>//
>{
> CString str, strTitle;
> TCHAR szClass[ 200 + 1 ] = {0};
> CWnd * pChild = CWnd::FromHandle(::GetWindow(hWndMain, GW_CHILD)
>); CWnd * pLast = NULL;
> if( pChild )
> pLast = pChild->GetWindow(GW_HWNDLAST);
> if( !pChild )
> return NULL;
>
> do{
> GetClassName(pChild->GetSafeHwnd(), szClass, 200);
> pChild->GetWindowText(strTitle);
> if(_tcsicmp(szClass, _T("Dialog")) == 0 )
> {
> HWND hChild = FindChildWindow(pChild,
> szClassName,
> szWindowTitle);
> if( hChild )
> return hChild;
> }
> pChild = pChild->GetWindow(GW_HWNDNEXT);
> }while( pChild && (pChild != pLast) );
>
> return NULL;
>}
>
>HWND FindChildWindow(CWnd * pParent,
> LPCTSTR szClassName,
> LPCTSTR szWindowTitle)
>{
> ASSERT( szClassName || szWindowTitle );
> ASSERT( pParent );
> CString strTitle;
> TCHAR szClass[ 200 + 1] = {NULL};
>
> CWnd * pChild = pParent->GetWindow(GW_CHILD);
> ASSERT( pChild );
> CWnd * pLast = NULL;
> if( pChild )
> pLast = pChild->GetWindow(GW_HWNDLAST);
> if( !pChild )
> return NULL;
> do
> {
> GetClassName(pChild->GetSafeHwnd(), szClass, 200);
> pChild->GetWindowText(strTitle);
>
> if( (!szClassName || _tcsicmp(szClass, szClassName) == 0)
> && (!szWindowTitle || strTitle.CompareNoCase(szWindowTitle)
> == 0) )
> {
> return pChild->GetSafeHwnd();
> }
> pChild = pChild->GetWindow(GW_HWNDNEXT);
> }while( pChild && (pChild != pLast) );
>
> return NULL;
>}
>-----------------------------------
>
>
>Last question:
>Is using FindWindow(_T("dialog"), )
>better than using FindWindow("dialog", ) ?
>Does specifying the class name prevent it from using the sendmessage
>call internally for those cases where the window is obviously not a dialog?
>
>
>
>Thanks for any help...
>Wes

Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm



Relevant Pages

  • Re: Only One Instance.
    ... the secondary app the handle info of the original app along with what ... use the FINDWIndow in the Main Source before The ... The name of the mutex has no effect on anything else in your program, ... Creating a window, on the ...
    (comp.lang.pascal.delphi.misc)
  • Re: Search for component which makes drag & drop possible
    ... if your doing this with in the same app then you should be able to us ... a window to accept A drag and drop of a name string. ...
    (alt.comp.lang.borland-delphi)
  • Re: passing multiple parameters to an application via windows explorer
    ... >> Thanks for the reply Jamie, but my problem isn't working out how to ... > main program via the createProcess, then a findWindow can be done ... > again to get the window handle of the main program. ... > to the window of your main app, ...
    (alt.comp.lang.borland-delphi)
  • Re: how to bring dialog to front
    ... smart phone 6.0 ... When checking whether your app is already running, ... FindWindow is not quite sufficient. ... This call will wait until the window responds. ...
    (microsoft.public.pocketpc.developer)
  • Re: Only One Instance.
    ... use the FINDWIndow in the Main Source before The ... you could simply create a mutex. ... created the window that the other process is looking for. ... > your app responed to .. ...
    (comp.lang.pascal.delphi.misc)

Loading