FindWindow question.

Posted on 2004-11-23
Last Modified: 2011-10-03

this question is related to icq.

ICQ's messenger window name is #32770.

So I do: handlexyz := FindWindow('#32770', nil);
The textbox of icq is a RichEdit20A.

In that messenger (#32770) window there is one RichEdit20A for the textbox where you type messenges and one RichEdit20A for the messeges of the other person.

So when I do a handlendxyz := FindWindowEx(WIN, 0, 'RichEdit20A', nil);
and then a SendMessage(hwndxyz, WM_GETTEXT, 255, integer(@Buffer));
then it sometimes returns the text of the input textbox and sometimes the text of the other person.

Do you have any ideas why sometimes it returns the input textbox text and sometimes the text of the other person. I guess it has something to do with the focus. The question is, do you have any idea how to get a handle on both textboxes?

Question by:TonyJiz
    LVL 12

    Expert Comment

    you have 2 controls with name "RichEdit20A" ... ?

    I recommend you to check it again. As I a tool, I can recomment you is:

    > "FindWindowEx(WIN, 0, 'RichEdit20A', nil);"
    WIN is the the handle of the parent window. So you should do it like this:

    handlexyz := FindWindow('#32770', nil);
    handlendxyz := FindWindowEx(handlexyz, 0, 'RichEdit20A', nil);
    LVL 14

    Expert Comment

    Hmm... with ICQ it is a bit hard huh... relying on #32770 alone is quite 'dangerous', because that is the name used by all standard dialogs.

    I guess what you can do after the FindWindowEx is... to check the caption of the window? Because ICQ message windows contain the phrase "Message Session" at the back.

    Or, you can actually enumerate through all windows and find the one that contains "Message Session" as its windows title...
    LVL 26

    Expert Comment

    Dragon Slayer, the second parameter of FindWindow is the Window Title, no need to use FindWindowEx.
    From MSDN:

      HWND FindWindow(      
        LPCTSTR lpClassName,
        LPCTSTR lpWindowName

            [in] Pointer to a null-terminated string that specifies the class name or a class atom created
                  by a previous call to the RegisterClass or RegisterClassEx function. The atom must be in
                  the low-order word of lpClassName; the high-order word must be zero.

            If lpClassName points to a string, it specifies the window class name. The class name can
            be any name registered with RegisterClass or RegisterClassEx, or any of the predefined
            control-class names.

            If lpClassName is NULL, it finds any window whose title matches the lpWindowName parameter.

            [in] Pointer to a null-terminated string that specifies the window name (the window's title).
                  If this parameter is NULL, all window names match.

    Return Value

        If the function succeeds, the return value is a handle to the window that has the specified class
        name and window name.

        If the function fails, the return value is NULL. To get extended error information, call GetLastError."

    Author Comment


    I used that tool. The ICQ message window is just a textbox (RichEdit20A) with a line that seperates the textbox for input and the textbox for messages from the other user. So maybe that there only is one RichEdit20A, that's possible since sometimes the GETTEXT returns the input message and sometimes it returns the messages from the other user. I have no idea why.
    About the WIN handle, i copy pasted that wrong, I did do it with the handlexyz and not the win handle.


    I don't just rely on #32770, also on the filename, so no need for the message window. It's just that sometimes RichEdit20A returns the input messages and sometimes the messages from the other user. I just want to retrieve the text from both message windows.

    LVL 26

    Accepted Solution


    To answer your question, FindWindow(ex) works by finding the first window in the z-order that matches your criteria. FindWindowEx is a little more advanced, as you can specify a child window to start the search from, for example, in cases when you want to continue a search...

    What is happening (I believe) is that the z-order is changing depending on focus, thus depending on when you call findwindowex, you may get either the upper or lower edit window.

    An easy solution, and one that will give you both handles, is to call FindWindowEx twice. Once with a child handle of zero, and the second time with  the child handle from the first call. Then check the client rects to determine which is the upper, and which is the lower.


    var  hwndICQ:       HWND;
         hwndSwap:      HWND;
         hwndEdit1:     HWND;
         hwndEdit2:     HWND;
         rcEdit1:       TRect;
         rcEdit2:       TRect;

      // Get base window
      hwndICQ:=FindWindow('#32770', nil);

      // Check handle
      if (hwndICQ <> 0) then
         // Get first edit window in z-order
         hwndEdit1:=FindWindowEx(hwndICQ, 0, 'RichEdit20A', nil);
         // If non null, get next edit window
         if (hwndEdit1 <> 0) then hwndEdit2:=FindWindowEx(hwndICQ, hwndEdit1, 'RichEdit20A', nil);
         // Check handles
         if (hwndEdit1 <> 0) and (hwndEdit2 <> 0) and (hwndEdit1 <> hwndEdit2) then
            // Get rects for both windows
            Windows.GetClientRect(hwndEdit1, rcEdit1);
            Windows.GetClientRect(hwndEdit2, rcEdit2);
            // Swap if out of order (edit2's top is less than edit1's top)
            if (rcEdit2.Top < rcEdit1.Top) then
               // Swap handles


    This will give you both handles, and it also allows you to determine which is which.

    Hope this helps,


    Author Comment

    That's some great stuff Russell! Points given.

    Hey could you also goto maybe you know that too.

    Anyway, thnx!

    Featured Post

    Looking for New Ways to Advertise?

    Engage with tech pros in our community with native advertising, as a Vendor Expert, and more.

    Join & Write a Comment

    Suggested Solutions

    A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
    In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
    This video is in connection to the article "The case of a missing mobile phone (". It will help one to understand clearly the steps to track a lost android phone.
    This video discusses moving either the default database or any database to a new volume.

    754 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    24 Experts available now in Live!

    Get 1:1 Help Now