Thread: Strange behaviour

  1. #1
    Registered User
    Join Date
    Jul 2002
    Posts
    36

    Strange behaviour

    Look at this Function I made:

    Code:
    BOOL SetWFont( HWND handle, UINT winIdent, UINT fontSize, LPSTR fontFamily )
    {
        HFONT hFont;
        HDC hdc;
        long lfHeight;
    
        hdc = GetDC(handle);
        lfHeight = -MulDiv(fontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
        ReleaseDC(handle, hdc);
    
        hFont = CreateFont(lfHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fontFamily);
    
        if(!SendDlgItemMessage(handle, winIdent, WM_SETFONT, (WPARAM)hFont, TRUE)) return 0;
    
        hFont = CreateFont(lfHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fontFamily);
    
        DeleteObject(hFont);
    
        return 1;
    }
    You notice the second call of CreateFont? It's completely unneccessary, you mean? Well, if you ask me, I'd say the same. BUT. Without this line the function doesn't work. It just does nothing if I cut this unlogical 2nd call of CreateFont. And now I'm wondering why!

    Has anybody an idea? (well it's not that serious cause the function now works and does what I want, but I think it's strange nevertheless!)

    Pry
    "I don't know with what weapons World War III will be fought... but World War IV will be fought with sticks and stones." - Albert Einstein

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    SendMessage with a WM_SETFONT does not return a value.


    If you create a font and then create another, over the top of the first without DeleteObject()'ing it, as you are doing, you have created a GDI memory leak.

    The best way to do this is with a global HFONT, or a static HFONT in the main callback.

    Create the font as the app starts up,
    call the setfont at WM_INIT / WM_CREATE
    clean the font up at the WM_CLOSE (when the app exits).
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User
    Join Date
    Jul 2002
    Posts
    36
    Mh yeah you're right and I'm going to do it the way you suggested... but can you maybe explain to me why the code without this erroneous line (the 2nd call of createfont), doesn't work?

    Thanks so far,

    Pry
    "I don't know with what weapons World War III will be fought... but World War IV will be fought with sticks and stones." - Albert Einstein

  4. #4
    Code Monkey Davros's Avatar
    Join Date
    Jun 2002
    Posts
    812
    Not an expert with CreateFont, but think I can see your problem.

    You are calling CreateFont twice, thus creating two instances of HFONT , but calling DeleteObject only once. Wouldn't this result in a leak?

    Therefore, it maybe for your function SetWFont to be effective, an instance of HFONT must remain existence. You in advertently seem to do this by leaving a leaked HFONT instanced.

  5. #5
    Registered User
    Join Date
    Jul 2002
    Posts
    36
    Yeah but novacain mentioned that allready. I'm not quite sure u understood me right :P

    Once again:


    If I leave the 2nd call of CreateFont in the source (what is a bad thing cause it causes a mem leak, but apart from that) the whole stuff does what it should: changing the font of the control.

    Of course I have to change that so it doesn't leak any more.

    But the strange thing is when I delete the second call of CreateFont (that doesnt make sense anyway!!!) the function does nothing any more!

    Here the code to make things clear:

    Code:
    BOOL SetWFont( HWND handle, UINT winIdent, UINT fontSize, LPSTR fontFamily )
    {
        HFONT hFont;
        HDC hdc;
        long lfHeight;
    
        hdc = GetDC(handle);
        lfHeight = -MulDiv(fontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
        ReleaseDC(handle, hdc);
    
        hFont = CreateFont(lfHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fontFamily);
    
        if(!SendDlgItemMessage(handle, winIdent, WM_SETFONT, (WPARAM)hFont, TRUE)) return 0;
    
        DeleteObject(hFont);
    
        return 1;
    }
    This function doesn't work! I was playing around and accidentially added the second call of CreateFont. And then it worked and I went "huh???" and posted it here.


    So... what do you think?
    "I don't know with what weapons World War III will be fought... but World War IV will be fought with sticks and stones." - Albert Einstein

  6. #6
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    I think the if() on a SendMessage() that has no return will create some undefined behaviour, so I don't know why.

    I forgot to mention that the HFONT may have to be global or static. If it is local it will loose scope once the function exits. I am not sure if the HFONT must remain valid for the entire apps execution or if it is stored and so can be local.

    Davros
    >>Therefore, it maybe for your function SetWFont to be effective, an instance of HFONT must remain existence. You in advertently seem to do this by leaving a leaked HFONT instanced.<<

    Davros's opinion that the second call to CreateFont() causes a leak of the HFONT, which allows the SetFont() HFONT to be used, is my guess as well.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  7. #7
    Registered User
    Join Date
    Jul 2002
    Posts
    36
    I see... thanks.
    "I don't know with what weapons World War III will be fought... but World War IV will be fought with sticks and stones." - Albert Einstein

  8. #8
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Your function shouldn't work! You forgot to select it into the HDC.
    That is imperative. Also you should know that when you DO select it with SelectObject(), that function will return a handle to the previous font, should you wish to restore it later.

    ie:


    Code:
    HFONT font = CreateFont( 25, 15, 0, 0, FW_EXTRABOLD, 0, 0, 0, ANSI_CHARSET, 10, PROOF_QUALITY, VARIABLE_PITCH, FF_ROMAN, "courier");
    
    HFONT previous = (HFONT)SelectObject(hdc, font);


    Try this:


    Code:
    
    HFONT SetWFont( HWND handle, UINT winIdent, UINT fontSize, LPSTR fontFamily )
    {
        HFONT hFont;
        HDC hdc;
        long lfHeight;
    
    hdc = GetDC(handle);
    
    lfHeight = -MulDiv(fontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
        
    hFont = CreateFont(lfHeight, 20, 0, 0, 0, 0, 0, 0, ANSI_CHARSET,10, PROOF_QUALITY, VARIABLE_PITCH, FF_ROMAN, fontFamily);
    
    SelectObject(hdc, hFont);
    
    ReleaseDC(handle, hdc);
    
    return hFont;
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #9
    Registered User
    Join Date
    Jul 2002
    Posts
    36
    Well thanks, I figured it out now

    Pry
    "I don't know with what weapons World War III will be fought... but World War IV will be fought with sticks and stones." - Albert Einstein

  10. #10
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Ahhh...Sebastiani

    He does not have to select the font into a DC, he just needs the handle to the font (look at FillRect(), FrameRect() as examples with brushes used but not selected into a DC).

    In fact your code is a memory leak.

    You have lost the original font in the DC.

    You have returned a local variable that will loose scope as soon as the function ends.

    Also the new font may not be able to be deleted successfully as you have left it in a DC and DeleteObject() will not work on an object still selected into a DC. (the only way to get it out is to create another and SelectObject() it in, and so on)

    (You say, very correctly, that you must conserve the return from SelectObject() then give an example where you don't??)
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  11. #11
    Registered User
    Join Date
    Jul 2002
    Posts
    36
    well I "solved" the problem by making hFont global, creating the font using the function I showed u without the DeleteObject() and deleting it finally during the processing of the WM_DESTROY message.... is this still a mem leak this way?
    "I don't know with what weapons World War III will be fought... but World War IV will be fought with sticks and stones." - Albert Einstein

  12. #12
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    When you use SelectObject() the return is the GDI object already in the DC. You can not delete a GDI object while it is selected into a DC.

    As you are not selecting it into a DC it should not cause a problem. If concerned check the return from the DeleteObject() and call GetLastError() if there is a problem.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. strange fopen behaviour
    By AngKar in forum C Programming
    Replies: 2
    Last Post: 01-09-2006, 06:58 AM
  2. Strange behaviour of scanf()
    By chris1985 in forum C Programming
    Replies: 3
    Last Post: 01-15-2005, 02:41 PM
  3. strange behaviour of sscanf
    By BeBu in forum C Programming
    Replies: 7
    Last Post: 12-17-2004, 10:12 AM
  4. Strange behaviour of ODBC cursor
    By knutso in forum Windows Programming
    Replies: 6
    Last Post: 05-07-2003, 07:39 AM
  5. GetClientRect strange behaviour
    By btq in forum Windows Programming
    Replies: 2
    Last Post: 10-02-2002, 02:13 PM