Determine Control Coordinates

Does anyone know of a good way to retrive coordinates of window controls, such as list boxes, combo boxes, etc.?

For example, if I have a list box in my resource file and I start it at 10, i.e., 10, 10, 100, 14, yet that does not compute accurately if I do a GetClientRect() in my code functions.

That is, if do GetClientRect(hwnd, &rc), I cannot then equate that to rc.left+10 as being equal to the 10 in the resource file for the beginning point of the list box.

What I want is a way to accurately calucate the coordinates between the window procedure and the resource file, but thus far I have found no good way to do this.
iirc, resource files store their info in "dialog units" whereas everything else everywhere is in pixels.

The reason for the difference is because the actual size of buttons and whatnot may change depending on the user's display settings. "Dialog units" are intentionally somewhat ambiguous so that they can fluidly adapt to different user display themes. You throw that adaptation out the window if you use just pixels.

I've never had to make such a conversion... but upon a little research, I discovered MapDialogRect:

http://msdn.microsoft.com/en-us/library/ms645502(VS.85).aspx

Which appears to be what you're looking for
Last edited on
Thanks for the explanation and the link. MapDialogRect() may be what I need, but I'll have to figure out how to use it and play with it.

Bascially what I want to to do is to know what postion my controls are are in within the dialog. For example, where is my listbox relative to the dialog in which it resides. This so I can pick up when the mouse, for example, is inside that space.

I don't know if MapDialogRect() will do that, but it looks like it might. Thanks again.
This so I can pick up when the mouse, for example, is inside that space.


Err... well I don't see why you'd need dialog units in that case. You can just use the window coords you get with GetWindowRect.
You can't use GetWindowRect to determine if the mouse is over a list box which is in your window. That is what I'm trying to accomplish, i.e., determine when the mouse is inside a list box, or an edit control, etc.
Okay... so then this has nothing to do with converting dialog units to pixels -- and has everything to do with the mouse and mouse messages. Your original post threw me off.

I probably can't be of much help here. My first thought would be to catch the WM_MOUSEMOVE message and use it to get the mouse's position, then you can compare that position to the GetWindowRect() of your control to see if the mouse is inside the rect (and therefore over the control).

However I'd bet that your dialog does not receive WM_MOUSEMOVE messages when the mouse is over a control (because the message would be sent to the control instead of your dialog). So you'd either have to find a way to intercept messages sent to the control... or you'll need to make the control echo mouse events to the dialog.

I really have no idea how you'd accomplish either of these on WinAPI.
There is a way to do this because I've seen other programs where I know for a fact they are using straight C/Win32 API, and they are able to trap the right mouse in list boxes, edit controls, etc. But it must be tough to do because none of the MS MVP people can tell me how to do it.
Wait... so now you want to trap the mouse in a control? There's a function for that (though I forget the name).


Back up and tell me exactly what it is you're trying to do. You keep leaving me to make assumptions, and I keep assuming wrong. Spell it out for me.
I'm actually trying to trap the right mouse click when the mouse is in the listbox, as per this thread...

http://cplusplus.com/forum/windows/13171/

I tried the code in the above thread and it doesn't work.
Okay. This has nothing to do with anything talked about in this thread. You need to either catch a notification, or catch the right-click message.

After searching MSDN for NM_RDOWN it said it's "not currently supported":

http://social.msdn.microsoft.com/Search/en-US/?query=NM_RDOWN&ac=8

and NM_RCLICK seems to be only available on WinCE, which might explain why it wasn't working for you. Or at least I couldn't find any NM_RCLICK info that didn't relate to WinCE.


My next thought was to just bypass the message handler for the listbox and catch the WM_RBUTTONDOWN message directly. You should be able to do this with GetWindowLongPtr (to get the original window proc) and SetWindowLongPtr (to make your own).

Note I have no idea if this code will work or not, I'm just throwing out ideas at you. If this doesn't work, I'm out of ideas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//  if WNDPROC is not already typedef'd... it might be
//typedef LRESULT CALLBACK *WNDPROC(HWND,UINT,WPARAM,LPARAM);

WNDPROC OriginalListWndProc;


LRESULT CALLBACK ListWindowProc(HWND wnd,UINT msg,WPARAM w,LPARAM l)
{
  if(msg == WM_RBUTTONDOWN)
  {
    // message box here
    //   should trip when you right click on the listbox
  }
  return CallWindowProc(OriginalListWndProc,wnd,msg,w,l);
}

//-----------------------------------------
//  in WM_INITDIALOG for your dialog's message handler:
//  assume 'lstwnd' is the HWND to your listbox
OriginalListWndProc = (WNDPROC)(GetWindowLongPtr(lstwnd,GWLP_WNDPROC);
SetWindowLongPtr(lstwnd,GWLP_WNDPROC, (LONG_PTR)(&ListWindowProc) );
Last edited on
Thanks for taking the time to answer. I'll try the above later today and see where it goes.

In the meantime, FWIW, you can use WM_CONTEXTMENU to trap the right mouse in a listbox, but then you need to determine the coordinates of the listbox within your window/dialog, hence my question about dialog coordinates.

IOW, I have been able to trap the right mouse, but the ONLY way I have been able to make sure the mouse is WITHIN the listbox coordinates is to use a POINT struct and do...

pt.x=GET_X_LPARAM(lParam), etc., but I have to work out the xy coordinates by trial and error, which is why I started this thread, i.e., I would like to be able to automatically calculate the coordinates of the listbox so I can tell when the mouse is within that region.
*facepalm*

Why didn't you say all of this from the beginning? You would've saved me a lot of work. Instead I went on a wild goose chase.

Okay -- disregard everything I said again.

WM_CONTEXTMENU:
http://msdn.microsoft.com/en-us/library/ms647592(VS.85).aspx

According to that page it returns the coordinates in screen coords. IE: 0,0 would be the upper left corner of the monitor, regardless of where your dialog is positioned, or where the listbox is on the dialog.

GetWindowRect:
http://msdn.microsoft.com/en-us/library/ms633519(VS.85).aspx

Also says the coords are in screen coords.

So you don't need to be doing any conversion at all, if I'm reading this right:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case WM_CONTEXTMENU:
{
  POINT pt;
  pt.x = GET_X_LPARAM(lParam);
  pt.y = GET_Y_LPARAM(lParam);

  RECT rc;
  GetWindowRect( hwnd_to_your_listbox, &rc );

  if( PtInRect(&rc,pt) )
  {
    // clicked on listbox
  }
}
break;


If WM_CONTEXTMENU is sent to the dialog when you click on the listbox, then the only thing I can see going wrong here is if the coords need translating somehow. Like if they're not screen coords, but are relative to the parent window. In which case you might need a ClientToScreen() call slipped in there somewhere.

But if I'm reading the MSDN docs right, that shouldn't be the case.
Last edited on
Thanks, between you and the MVP guys I got it worked out with WM_CONTEXTMENU, GetWindowRect, ScreenToClient, GET_X_LPARAM, and so on.

The only thing that WM_CONTEXTMENU won't intercept is an edit box, but I'll worry about that at another time.

As for making you work extra, I do apologize, but since I got no responses on the other thread I thought I would try this other approach.

So as the Shakespeare said, "All's well that ends well." -:)

Thanks again.
Read the Petzold (http://www.charlespetzold.com/pw5/index.html, easy to find in ebook), MS SDK samples and Win32 api ng (http://tinyurl.com/cmhb5g )
because these notions are really Win32 basis, answered hundreds of times for more than 15 years...
Last edited on
I have several editions of Petzold's Programming Windows and nowhere does he deal with this issue. He only deals with mouse-overs in a window, not in right-clicking controls or dealing with intercepting mouse clicks in controls, etc.
Last edited on
Disch, I really do appreciate all your help. I did not mean to meander so much in my request. You and several others have been a great help to myself and others here. FWIW.
Topic archived. No new replies allowed.