Solved

Precise alignment of text with toolbar button

Posted on 2013-11-25
7
349 Views
Last Modified: 2013-11-26
Hi!

First: I hope this is the right forum for this question, I couldn't find any "MFC" forum?

I am struggling to align a static text directly under a toolbar button in an MFC dialog. But I can't get it totally precise, it seems to be offset to the left by a small amount.

// I start finding the existing window of the text to be moved. It should keep it's vertical //placement.

  CRect rcText;
  GetDlgItem(textId)->GetWindowRect(rcText);
  ScreenToClient(rcText);

  // Then I find the window of the button
  int nIndex = m_wndToolBar.GetToolBarCtrl().CommandToIndex(buttonId);
  CRect rcButton;
  m_wndToolBar.GetToolBarCtrl().GetItemRect(nIndex, &rcButton);

  // I change the left/right values of the window of the text
    rcText.left = rcButton.left;
    rcText.right = rcButton.right;
    GetDlgItem(textId)->MoveWindow(rcText, TRUE);

but the text ends up a little too far to the left. I expect GetItemRect is returning it's coordinates relative to some client window upperleft corner inside the toolbar. But how do I find those values? Calling GetClientRect on the toolbar has both left and top 0.

Thanks for any help!
0
Comment
Question by:khun
  • 5
  • 2
7 Comments
 
LVL 32

Expert Comment

by:sarabande
ID: 39676872
Calling GetClientRect on the toolbar has both left and top 0.
you can try to calling GetWindowRect(...) for the toolbar window and the window you get by  m_wndToolBar.GetParent().GetWindowRect(...). the difference of the TopLeft points of the rectangles you get should be the offset you need to add to the text control.

if your dialog is parent window of the toolbar you also could try ScreenToClient member function though I don't know whether the function works for rectangles outside of the client area.

another way is to consider widths of frames which you could retrieve by GetSystemMetrics, for example

rcText.left += GetSystemMetrics(SM_CXSIZEFRAME);

Open in new window


a list of all metrics codes can be found at

http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385(v=vs.85).aspx

Sara
0
 
LVL 8

Author Comment

by:khun
ID: 39676987
Thank you for what seems like a very valid tip, I was sure you got the solution. Only it doesn't quite work, now the text comes a little too much to the right!

I checked that the dialog is the parent of both the toolbar and the static text.

m_wndToolBar.GetParent().GetWindowRect() gives a left 9 units lower than m_wndToolBar.GetWindowRect(). But if I add 9 to the text horizontal placement, it goes noticably to far right!

By hardcoding I can find the correct offset for this display is 6.

And I am still wondering how I can get that parameter correctly?
0
 
LVL 8

Author Comment

by:khun
ID: 39676997
Oh, I forgot:

GetSystemMetrics(SM_CXSIZEFRAME);

returns 9...
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 32

Accepted Solution

by:
sarabande earned 500 total points
ID: 39677199
the size of the frame and the offset to the toolbar is identical. that is an expected result and means that the GetItemRect returns client coordinates.

the offset still missing could be the offset from the toolbar control to the window that you get by m_wndToolBar.GetToolBarCtrl().


if that is 0, the offset you have to consider could be the offset in the toolbar to the first button. you could retrieve that by calling the GetItemRect for the first button.


how is the text displayed in the control? is it centered or left-aligned? are you sure that the text fits to the button at all? did you consider to add the text to the bitmap of the button rather than making an overlay with a text control of the parent window? you also could override the OnPaint member function of the dialog and make the drawings directly to the button. that would keep the bitmap as it is. you also could derive from toolbar class and then use the OnPaint of the derived toolbar class to do the text drawings. that would be the best design if possible.

Sara
0
 
LVL 8

Author Comment

by:khun
ID: 39677253
Well, m_wndToolBar.GetToolBarCtrl().GetWindowRect and m_wndToolBar.GetWindowRect return exactly the same. GetItemRect for the first button returns 0 for left and top (as specified in the documentation, which for once is quite specific).

The text fits the button, yes (I calculate the necessary dimension with DrawText first and am quite confident that this part is correct. I have done other tests to verify that the problem is to find the offset from the main client area (parent of both toolbar and text) to the buttons). To be more specific about what I'm doing, I want to center align text under one or several buttons in the toolbar, not overlay anything on the buttons.

I am trying to avoid changing anything more than I have to in existing code, that's why I'm doing it this way.

And somehow it must be possible to calculate this offset, right?
0
 
LVL 8

Author Comment

by:khun
ID: 39677322
Finally! The trick was to understand what window's ScreenToClient/ClientToScreen you should call:

  CRect rcToolbar;
 
 // I could actually just as well initialize rcToolbar with zeros, since
// I only need the upperleft corner, which will be (0, 0) after the next function anyway
// But if you need bottom or right, do this
  m_wndToolBar.GetClientRect(&rcToolbar);

  m_wndToolBar.ClientToScreen(rcToolbar);
 // rcToolbar is now in absolute screen coordinates

  ScreenToClient(rcToolbar);
 // rcToolbar is now the toolbar client area's offset from my dialog's client area.

  const int rcHorOffset = rcToolbar.left; // Voilá

This gives me an rcHorOffset of 6 in my case, which is precise.
0
 
LVL 8

Author Closing Comment

by:khun
ID: 39677331
Although you didn't provide an exact answer, you helped me search in the right direction.

Thank you!
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

This article shows how to make a Windows 7 gadget that accepts files dropped from the Windows Explorer.  It also illustrates how to give your gadget a non-rectangular shape and how to add some nifty visual effects to text displayed in a your gadget.…
In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

757 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

23 Experts available now in Live!

Get 1:1 Help Now