Why is ComboBox font bold after a Create()

When I create a simple CComboBox in a dialog that is to overlay a placeholder, then the font that I when I enter characters in the edit box is boldface.  If the box is created from a resource, then the font is normal.

What I want to do is create simple combobox with normal dialog box font.

Here is the code snippet from OnInitDialog():

    // this will overlay the placeholder text with a simple
    // combobox of the same size
    // ?? the problem is that the text is boldface in the edit box
    CWnd* pPlaceHolder = GetDlgItem(IDC_PLACEHOLDER);
    CRect rect;
    pPlaceHolder->GetWindowRect(&rect);
    pPlaceHolder->DestroyWindow();
    ScreenToClient(&rect);
    m_cbNewBox.Create(CBS_SIMPLE | CBS_SORT | CBS_AUTOHSCROLL
       | WS_CHILD | WS_VISIBLE
       | WS_TABSTOP | WS_VSCROLL
     , rect, this, IDC_COMBO3);

    // now we look at the style and font
    CWnd* pWnd;
    CFont* pFont;
    HWND hwnd;
    long style;
    pWnd = GetDlgItem(IDC_COMBO3);
    hwnd = pWnd->GetSafeHwnd();
    style = GetWindowLong(hwnd, GWL_STYLE);
    // ?? why is this font return null?
    pFont = pWnd->GetFont();
    if(pFont) {
        LOGFONT lf;
        pFont->GetLogFont(&lf);
        pFont = NULL;
    }

When I step thru this with the debugger, the style is 0x50010341 which corresponds to a simple combobox created from a resource.  The combobox that is actually created is the correct size and is a simple box with no list so it looks just like an edit control - fine so far!  However when I type, the characters are boldface.  In the code above, I thought I could check the font but the pFont returned is null.

When I put a combobox into the dialog via the resource editor, and doing the same thing as above, then the pFont points somewhere and I get the LOGFONT struct filled.  Inside the lf struct as seen from the debugger are the following nonzero items:

lfHeight 0xfffffff3
lfWeight 0x00000190
lfFaceName "MS Sans Serif"

I'm not  sure what the weight means but typing in the box produces normal weight characters for a dialog box.

emitchellAsked:
Who is Participating?
 
mikeblasConnect With a Mentor Commented:
When Windows creates a dialog box, it also creates all the controls. The controls are created to have the same font as the dialog box resource. That way, everything looks homogenous.

When you create a control with CreateWindow(), Windows doesn't look at the parent and pull its font info. It just creates the window for you.

If you want, you can set the font yourself. Just send WM_GETFONT to the dialog, and use WM_SETFONT to set the resulting font to your new control. If you're using MFC, you can use the GetFont() and SetFont() members.

When you create a new window and call GetFont() on it, you get NULL because no font has ever been set to that window. That means that Windows is using the default font system stock object.

The lfWeight value is 0x0190, which is the same as FW_NORMAL. The FW_constants are described in the documentation for the lfWeight member of the LOGFONT structure in the SDK documentation.

..B ekiM
0
 
emitchellAuthor Commented:
This is a perfect answer!
0
 
emitchellAuthor Commented:
Maybe I was a little premature since in trying to implement the change in font, I still see bold face text, not the FW_NORMAL that is seen in the LOGFONT struct.  Since I thought that there may be a difference in using a CombBox since the Edit control is buried inside, I switched to creating a CEdit member that as before I used Create to draw the window in the Dialog box.  The symptoms are the same.  The text in the created control is boldface.

 Here is the code in test OnInitDialog().

BOOL CDDTestDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // this will overlay the placeholder text with a simple
    // edit box of the same size
    CWnd* pPlaceHolder = GetDlgItem(IDC_DD_PLACEHOLDER);
    CRect rect;
    pPlaceHolder->GetWindowRect(&rect);
    pPlaceHolder->DestroyWindow();
    ScreenToClient(&rect);
    m_ebNewBox.Create(ES_AUTOHSCROLL
       | WS_CHILD | WS_VISIBLE | WS_BORDER
       | WS_TABSTOP
     , rect, this, IDC_DD_EDIT2);

    LOGFONT lf;
    {
        // these braces are only so that I don't have to worry about
        // multiple definitions of pWnd, pFont, etc. It fills "lf."

        // extract the font from the normal edit built from
        // resource file
        CWnd* pWnd = GetDlgItem(IDC_DD_EDIT1);
        HWND  hwnd = pWnd->GetSafeHwnd();
        CFont* pFont = pWnd->GetFont();
        if(pFont) {
            pFont->GetLogFont(&lf);
            pFont = NULL;
        }
    }
    // here the LOGFONT (lf) contains a weight of 0x190 (FW_NORMAL)
    // and a font of "MS Sans Serif"

    // set this font into the edit control that was created above
    // so that we get the normal font.
    // ?? this still makes the font bold!
    CWnd* pWnd = GetDlgItem(IDC_DD_EDIT1);
    CFont font;
    // the return here is true
    BOOL ret = font.CreateFontIndirect(&lf);
    pWnd->SetFont(&font);
    // read the font back to make sure that the normal font
    // has made it into the control. it is the same as was
    // set with a weight of 0x190 (400) or FW_NORMAL
    CFont* pFont = pWnd->GetFont();
    if(pFont) {
        pFont->GetLogFont(&lf);
        // the "lf" struct contains the same as was set into the control
        pFont = NULL;
    }
    return TRUE;
}

I wish there were a way to actually examine the Windows structures to see what they were actually working on!

0
Learn to develop an Android App

Want to increase your earning potential in 2018? Pad your resume with app building experience. Learn how with this hands-on course.

 
mikeblasCommented:
I don't understand your code.

You're getting the IDC_DD_EDIT1 control and setting its font.  Don't you really mean to be setting the font on IDC_DD_EDIT2?  IDC_DD_EDIT2 is the ID you give when you call Create(), not IDC_DD_EDIT1.

..B ekiM
0
 
emitchellAuthor Commented:
I had been through a variety of tests and I screwed up.  I had left the last one in place where I was setting the same font back when I copied the code.  As you point out, I really mean to be setting the font on IDC_DD_EDIT2.  If I change the line though, the font in the created box is still bold face!

One other piece of info was that when I set the EDIT1 box back to the font that came from it, the font then changes to bold face.

Adding these lines at the bottom:
    {
        CWnd* pWnd = GetDlgItem(IDC_DD_EDIT1);
        pWnd->SetFont(&font);
    }

makes the original edit box show as  bold face.  Unfortunately, SetFont() doesn't have any return to say whether it failed or not.

Incidentally, this is on Windows98 with VC6.0 if that may make a difference.
0
 
mikeblasCommented:
> this is on Windows98 with VC6.0 if that may make a difference.

Not as much difference as actually posting the correct code, no.

You're creating the font on the stack. When your function returns, you're destroying it before the window has a chance to even use it.  The font you create needs to stick around.  Make your CFont object live past your function, and I think you'll see things clear up.

..B ekiM
0
 
emitchellAuthor Commented:
A perfect diagnosist!  When I make the CFont a member (m_font) of   my dialog class everything now works as expected.  I must admit I expected the pWnd->SetFont(&CFont ...) to make a copy of the font down in the innards of Windows but apparently not!

It appears the the LOGFONT struct can be on the stack. The create of the CFont object via:

BOOL ret = m_font.CreateFontIndirect(&LOGFONT...)

must make a copy of the LOGFONT since it is the m_font that has to live beyond the exit from OnInitDialog().

I wish the doc had some indication of which objects had to be kept around and which could be ephemeral.

I really appreciate the help.

0
All Courses

From novice to tech pro — start learning today.