[Webinar] Streamline your web hosting managementRegister Today

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1002
  • Last Modified:

window handle

Hi 2 U,

I built myself up a handle to the edit field of my msn-chatwindow, like this:

HWND hwnd = FindWindow("imwindowClass",0 );

    if (hwnd != NULL)
      hwnd = FindWindowEx(hwnd, 0, "richedit20w", 0);
              if (hwnd != NULL)
                     .....and so on....

The problem is, that the field where you type in your message has THE SAME NAME like the field above where the hole chat conversation is displayed.
I placed text to the clipboard, and while trying to paste it, the handle is not on the "Input-field", but on the conversation window, where I can´t paste something of course.
Is there a chance to skip the handle somehow to the "input-field"???

  • 6
  • 5
1 Solution
Not sure how that chat program is constructed, there are essentially two ways to construct stuff like that:

         application window
             /           \
    input window     chat window


         application window
            user window
            /         \
     input window    chat window

The point is that I am pretty sure that the two windows are different windows. However, usually only the application window has an actual title, so the FindWindowEx will most likely not find either the input window nor the chat window.

I am not sure how the FindWindowEx API works, if it can only return top level windows for applications other than your own then the application handle is all you get and you simply cannot get the handle to either the input window or the chat window.

If you can get it, then I it is a simple case of browsing through the child windows of the application window until you find a window that satisfies your request.

I would believe the chat window is probably a window which is either read-only or where most of the stuff is read only while the input window is a writable window. However, to see the difference between them you have to be able to tell them apart using some easily recognizable difference.

For example if the input window is always below the chat window you can check their position and see which one is above or below the other, if the input window is such that property P always has the value V while the chat window never has the value V for property P then you can simply check that property of the window to see which one is which and if it is not the right one you just check the next sibling or child window until you find the window you're looking for.

FindWindowEx isn't really that bad function, it has an argument to specify where you should search, so if the current window wasn't the one you wanted you can repeat FindWindowEx in such a way that it will find the next occurrence. Check out the arguments hwndChildAfter etc which can direct FindWindowEx to start the search AFTER the given child window.

Example 1: Chat program layout is something like this:

        /    \
      input  Chat

That is, there's a window W which is parent to both the input and the chat window:

HANDLE hinp = FindWindowEx(hwndapp,NULL,....);
while (hinp != 0 && hinp is not input window) {
   hinp = FindWindowEx(hwndapp,hinp,....);
// hinp == 0 || hinp is handle to input window.

if hinp == 0 we couldn't find the window, it is possible it is still somewhere but not directly under application but rather in a window somewhere in a subtree of application (not directly under). If so we need to do a more extensive recursive search. This is also possible but more complicated:

HANDLE recursive_find(HANDLE hwnd)
   // search windows recursively until we find
   // our window.
   if (hwnd == 0 || hwnd is input window)
      return hwnd;
   HANDLE hw = 0;
   while ((hw = FindWindowEx(hwnd,hw,....)) != 0) {
      HANDLE hw2 = recursive_find(hw);
      if (hw2 != 0 && hw2 is input window)
         return hw2;
   return 0;

ScotchmanAuthor Commented:
I tried the hwndChieldAfter argument, but there was no other window found of the class "richedit20w"!!???

winSight shows me two editfields, both of the classname "richedit20w", but of course with different "handle numbers", so actually I should find another one!!??
FindWindowEx only offers to search for the class name or the window text.

The funny thing is that when I put a handle on this
"richedit20w" and if i use the gettext message

SendMessage(hwnd, WM_GETTEXT, iLen, (LPARAM)text);

I reveave the hole chat-conversation which is displayed in the upper editfield, so I now that the handle is on this one. But I also tried using the WM_CHAR Message on the SAME handle ...

SendMessage(hwnd, WM_CHAR, "g", 0);

...and the letter "g" showed up in the  INPUT FIELD!!!!!!!!!!!

How could that be?
I am totaly confused now...
It is possible that the chat window redirect WM_CHAR messages to the input window. In this case sending WM_CHAR to the chat window will insert characters to the correct input window. This is very natural since the user may set the chat window as focus and then type and the text should still go to the input window.

You could also try to check with your viewer what is the parent window of each of those Rich edit windows. The childafter parent only works if the parent window is the immediate parent of the window you want to find.

if you have a tree like this:

    /   \
   One   Two
        /   \
       Three Four

Then if you do a FindWindowEx with App as parent handle and One as Child after handle you won't find the window named Three. So if you search for a RichEdit window and Two isn't  a rich edit window (but Three is) then you won't find that window. Instead you should just find the sibling of One (which is Two) and if that isn't the window you search for you should do a recursive search using Two as parent window and NULL as child after (this means start from beginning and search for children of Two). Then the first child is Three and it is the window you can find.

It is quite possible that you instead of using FindWindowEx should just do the search manually by retrieving the handle to next sibling etc until you find the window you're looking for.

HANDLE find_window(HANDLE hwnd)
   if (hwnd == 0 || hwnd is the window I am looking for)
      return hwnd;
   HANDLE hw = GetFirstChild(hwnd);
   HANDLE hw2 = 0;

   while (hw != 0 && (hw2 = find_window(hw)) == 0)
      hw = GetNextSibling(hw);
   return hw2;

This doesn't use the FindWindowEx at all but does a recursive search through the whole tree of children of the window given as argument.

The GetFirstChild and GetNextSibling isn't directly available in Win32 as I remember, it is a generic function which can find first child, last child, next sibling, previous sibling or parent window by specifying various arguments, can't recall what the name of that function is.

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

If you're using MFC, you can simply call GetDlgItem(IDC_YOURINPUTFIELD) that return a pointer to a user interface control.
If you need *handle*, use "GetDlgItem(IDC_YOURINPUTFIELD)->m_hWnd"

I think scotchman's problem is that the control isn't in his application but in some other application. Therefore that method you suggest cannot be used directly. You can use it if you create an CRichEdit or whatever it's called and then find the handle and then just store it in that object. Then you have a simpler way to communicate with the control than sending window messages directly.

However, he first have to get the handle of that rich edit window and since that handle is a handle in some other application's window he need to search for it.

The very fact that you can do stuff like that indicates that windows isn't really very secure. If a program runs on my machine it can take total control of the whole machine, grab all input and monitor and control EVERYTHING I do.

Is it time to get paranoid?

Currently sitting on a Linux machine but I got a win2K machine at home...

ScotchmanAuthor Commented:
Salte, you wrote:
>It is possible that the chat window redirect WM_CHAR messages to the input window. In this case sending WM_CHAR to the chat window will insert characters to the correct input window. This is very natural since the user may set the chat window as focus and then type and the text should still go to the input window.

I thought of the same but I also used this call...
SendMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)"Thats so funny...");
...and it doesn´t appeared in the INPUT field, but in the upper chat window!!!!!!! Strange isn´t it?

Well, I will check out your thought about an recursive search....and a nother day goes by....
ScotchmanAuthor Commented:
GOT IT!!!!
Thanx Salte, that was just the idea I needed.
And by the way...it´s also possible to send things like

PostMessage(hwnd, WM_KEYDOWN , VK_RETURN, 0);
PostMessage(hwnd, WM_KEYDOWN , VK_SPACE, 0);

And so it´s actually easy to control other apps.
You only have to know their class names. For this just use WinSight, its free and one of my favourites.....

Well thanks again for your long comments...

Not so strange,

WM_SETTEXT is a direct order to that window to insert the text. Normally users won't override that message but will just let the window insert the text.

WM_CHAR on the other hand is input from keyboard and is very likely redirected. Sending WM_CHAR to the application's top level window will redirect keyboard input to the right place.
WM_KEYDOWN is just an even lower level keyboard input message.

When you press a key at the keyboard, windows will first send a WM_KEYDOWN to the application with the raw key code in untranslated form. You get WM_KEYDOWN for function keys (F1, F2 etc), for return key etc etc.

Then if the character is 'worthy' of translation such as a regular letter key A-Z or digit key 0-9 etc - in fact all printable characters) windows will also send a WM_CHAR message holding the character code. This is a message where the key has been translated to a character, so you get a notification such as 'g' has been pressed or 'A'. The WM_KEYDOWN is a message that send the key in an 'untranslated' form. Actually it isn't so untranslated as it probably once was, since you send virtual keys such as VK_RETURN etc. The physical scan codes from the keyboard are never sent and they are on the whole very uninteresting since they just tell which key has been pressed and without caring about keyboard layout.

WM_SETTEXT on the other hand is a direct order to the window you send to that it should receive the given text. An edit box will place the text in the edit field, a button will set the text in its caption, a label window will set the text in its label etc etc.

Note though, that text sent by WM_SETTEXT will most likely NOT be processed by the chat program, for example the text won't be sent to the other machines that participates in the chat. It is a raw command to just set the text in the window and all so-called controls can act on that message and do whatever is appropriate for that control. So WM_SETTEXT will bypass the chat program completely and just set the text in the chat window without the chat program ever recognizing the text or at least not acting upon it.

WM_CHAR and WM_KEYDOWN however are messages to the chat program that a keyboard key has been pressed and it will act as if that key was input by the user and handle it accordingly.

ScotchmanAuthor Commented:
Well I used WM_SETTEXT to set the text of the input-box and after that I passed another WM_KEYDOWN Message so the message will be REALLY send just like I would press the SEND-Button or Simply press Enter, thanks again 4 your help
Depends on how the 'send button' is implemented. If it reads the raw text from the input box by using WM_GETTEXT (which it probably does) that should work fine.

If it instead has a second buffer where it keeps the data from WM_CHAR or whatever and uses that it won't work. However, it is most unlikely that it would use such a double buffering scheme. Why have a second buffer when the buffer for the input edit box works just fine as buffer?

So, yes, your strategy of doing WM_SETTEXT to the input box and then send WM_KEYDOWN with VK_RETURN should probably work just fine.

You want to spam other people in a chat with lots of messages? If so you should reconsider, most people will notce if the other end is a 'bot' or some form of automaton and not a real human. If you send too fast people will react  to it.

If the chat is connected to some form of game the people maintaining that game will probably notice that your responses comes really fast and acurate and will most likely block you from participating in the game.

If it is to make some form of eliza program or other humorous or automated response then it's just fine I guess.

However, the bare fact that you can at all do things like this invokes the paranoia mode in me. Windows is - on the whole - a very unsecure system. Perhaps I should drop windows on the machine at home also and just run Linux?

ScotchmanAuthor Commented:
I am learning c++ and I am always trying to build something interessting with it, so I don´t want to spamm anybody, I was just interested if its possible at all....
Unfortunately it is....

It's scary, isn't it?


Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

  • 6
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now