Solved

Convert dialog units + font info into pixels?

Posted on 2002-04-02
13
917 Views
Last Modified: 2013-12-03
I am trying to scan a variety of binary resource files (.res files) for dialog box resources that match a certain size restriction in PIXELS.  The problem is that the dialog resource structures supply dialog resource sizes in abstracted dialog units which the OS then converts to pixels at run-time depending on certain modes and the font used.

I start out with the following information:
dialog_units_x - dialog width in dialog units
dialog_units_y - dialog height in dialog units
font typeface name (UNICODE string)
font point size

I want to translate this information into the width and height of the dialog in PIXELS.  According to MSDN, the conversion factor is like this:
dialog_pixels_x = (dialog_units_x * average_font_character_width_pixels) / 4
dialog_pixels_y = (dialog_units_y * average_font_character_height_pixels) / 8

My problem is determining the average font character width and height in pixels from the font face and point size.  I have tried using a CFont and doing something like this:

CFont MyFont;
LOGFONT MyLogFont;
MyFont.CreatePointFont(pointsize*10, typeface);
MyFont.GetLogFont(&MyLogFont);

Unfortunately, the data in the LOGFONT structure is also in abstracted/special units rather than pixels.  I think what I probably need is the information in a TEXTMETRIC structure, but I can't tell how to get from a pointsize and typeface name to a TEXTMETRIC structure.  Any ideas?

My program is a command-line app using MFC (for data structures and some API encapsulation like CFont, etc) and I plan to run it under Windows 2000, NT, and XP to analyze .res files that are used to build Windows CE images.
0
Comment
Question by:ris
  • 7
  • 6
13 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 6913699
Well, you can always obtain the actual text size in pixels using 'GetTextExtentPoint32()'
0
 
LVL 86

Expert Comment

by:jkr
ID: 6913712
0
 
LVL 1

Author Comment

by:ris
ID: 6913856
I've noticed both of those functions, but I can't figure out how I should use them to achieve my goal.  The problem is that both functions (GetTextExtentPoint32 and GetDialogBaseUnits) return information based on a device context, not on arbitrary font information.  So - keeping in mind that I'm in a command-line environment - how do I get a handle to a device context that is set up with the font that I want to test?
0
 
LVL 86

Expert Comment

by:jkr
ID: 6913878
>>how do I get a handle to a device context that is set up
>>with the font that I want to test?

By creating an invisible window (simply don't call 'ShowWindow()') and selecting the font used into the device context. That all can be done from a console app.
0
 
LVL 1

Author Comment

by:ris
ID: 6913886
GetDialogBaseUnits is a particularly nice function for what I want.  Unfortunately, it only works on the system font, and I need to do it on arbitrary fonts other than the system font, making it completely useless for my needs.  At least with the other ones you could change the font on your device context (however that is achieved) and get applicable information...
0
 
LVL 86

Expert Comment

by:jkr
ID: 6913918
>>Unfortunately, it only works on the system font

That's why they have created 'MapDialogRect()' (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/dlgboxes_4hf8.asp)
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 1

Author Comment

by:ris
ID: 6913922
Oh duh, create an invisible window.  Of course, Why didn't I think of that??  Thanks, I'll try it!
0
 
LVL 1

Author Comment

by:ris
ID: 6915423
I tried your suggestion but without success.  Here's the problem:

I create an invisible dialog like this:

CDialog* pMyDialog = new CDialog;
pMyDialog->Create(IDD_BLANK_DIALOG_TEMPLATE);

It all returns success codes so it seems to work.  Before calling MapDialogRect I need to change the font on the dialog, because my whole problem is to convert dialog units to pixels using ARBITRARY font settings.  So I create a CFont object like this:

CFont DesiredFont;
DesiredFont.CreatePointFont(nDesiredPointSize * 10, szDesiredFontFace);

Everything works, or at least returns success codes, to this point.  So now I need to set my dialog to use my desired font, so I do this:

pMyDialog->SetFont(&DesiredFont);

Now unfortunately CWnd::SetFont returns void so there's no immediate way to know that it worked.  At first I assumed that it must not be able to fail, but the results of my program were indicating that it probably was failing, so I added some test code like this:

LOGFONT DesiredFontInfo;
LOGFONT ActualFontInfo;
DesiredFont.GetLogFont(&DesiredFontInfo);
pMyDialog->GetFont()->GetLogFont(&ActualFontInfo);

At this point, an examination of ActualFontInfo compared to DesiredFontInfo shows that CWnd::SetFont() failed.  None of the font attributes from DesiredFont make it into the actual font loaded in the dialog.  Which means that when I get to my data conversion call:

MapDialogRect(pMyDialog->GetSafeHWnd(), pRect);

It succeeds, but it uses the default system font only.

What else can I do?  Do I need to set the font differently?  Create the dialog differently?  Any thoughts?  I assume that since the SetFont call is silently failing that none of the other API calls I could use will work either because they will meet the same limitation of working on the default system font only rather than my arbitrarily selected font.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6915438
Why are you using a dialog? A simple window would do it...
0
 
LVL 1

Author Comment

by:ris
ID: 6915496
From the MSDN documentation on MapDialogRect():

hDlg
[in] Handle to a dialog box. This function accepts only handles returned by one of the dialog box creation functions; handles for other windows are not valid.
0
 
LVL 1

Author Comment

by:ris
ID: 6915694
I tried using a CWnd instead, but I can't create the window.  CWnd::CreateEx always fails because "the handle is not valid"  My function call looks like this:

m_pPixelConversionWindow->CreateEx(
    NULL,
    AfxRegisterWndClass(NULL),
    TEXT("Conversion Window"),
    WS_CHILD,
    0,0,1,1,
    NULL,
    NULL)

What am I doing wrong?  I have tried changing all of the parameters.  The only window handle I pass it is the parent window handle, which has to be NULL to indicate the desktop.  I fear that it won't create because I am in a command line environment and it knows that... The CDialog method created OK, but do you think the font couldn't be set because the window is invisible? or because I am in a command line environment? or for some other reason?
0
 
LVL 86

Accepted Solution

by:
jkr earned 100 total points
ID: 6915870
Argl, it seems that things are more difficult than I thought :o)

If you want to use "non-standard" fonts with dialogs, you need a DLGTEMPLATEEX struct to specify which one... as this isn't available that easy (and I got the impression that you prefer to use MFC), why not overriding 'CDialog::OnSetFont()'?
0
 
LVL 1

Author Comment

by:ris
ID: 6916426
Hey good idea using DLGTEMPLATEEX to create the dialog with the appropriate font through CDialog::CreateIndirect().  That worked!  Even though CDialog::SetFont() would silently fail after creation, CDialog::CreateIndirect will create the dialog with any font I want. Following that, calls to MapDialogRect work correctly for translating the dialog units into pixels.

So thanks!  I have it working now.  I really appreciate your help on this!!
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
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…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

758 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

20 Experts available now in Live!

Get 1:1 Help Now