CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9

Thread: MFC GDI+ loading ttf font resource

  1. #1
    Join Date
    Nov 2019
    Posts
    4

    MFC GDI+ loading ttf font resource

    Hi

    I am using VS 2012 and making a app which displays several texts via GDI+ DrawText. When using ARIAL font, text looks okay, no problems.
    But I wanted to use my own ttf fonts for the texts. So I added the ttf files to the resources and made an BINARY Object out of this ttf files.
    When I use one font only all text are displayed ok. But when I use different fonts in the same WM_PAINT loop, the text looks completely garbage, strange letters are displayed.

    Here is my code for displaying the text, it is called in my own method (DrawText) and is called for every text element, so local variables are destroyed.

    Does the LoadResource/LockResource need a unlock or something???? I think it allocates some wrong memory when loading a second font..??

    Code:
            Gdiplus::PrivateFontCollection fntcol;
    	HINSTANCE hResInstance = (HINSTANCE)GetModuleHandle(NULL);
    	HRSRC res = ::FindResource(hResInstance, MAKEINTRESOURCE(font.id), L"BINARY");
    	if (res) {
    		HGLOBAL mem = ::LoadResource(hResInstance, res);
    		void *data = ::LockResource(mem);
    		size_t len = ::SizeofResource(hResInstance, res);
    		Gdiplus::Status nResults = fntcol.AddMemoryFont(data,len);
    	}
    
    	FontFamily fontFamily;
    	int nNumFound=0;
    	Gdiplus::Status nResults = fntcol.GetFamilies(1,&fontFamily, &nNumFound);
    	Gdiplus::Font fnt(&fontFamily,(float)font.size,FontStyleRegular,UnitPixel);
    	
    	LinearGradientBrush brush(Rect(x,y, 1000, (int)fnt.GetHeight(&rgraphics)), col1, col2, LinearGradientModeVertical);
    	rgraphics.DrawString(text, -1, &fnt, origin, &fmt, &brush);
    Here are 3 example images, the first two are ok, the third one is not:

    The first uses only one font resource (IDR_FNT_ROBOTO_COND_BOLD):
    Name:  1._modjsa.png
Views: 212
Size:  10.7 KB


    The second uses a second font resource, but only that one (IDR_FNT_BEBASNEUE_REG):
    Name:  2_gtw9st.png
Views: 218
Size:  9.4 KB

    And here the third example, where I use both fonts:
    Name:  3_kpeo7m.png
Views: 211
Size:  9.0 KB

    As you can see, every font alone works fine, but when I use more than one, the output text is garbage.

    thanks for any help.
    regards
    Erich

  2. #2
    Join Date
    Nov 2004
    Posts
    4

    Re: MFC GDI+ loading ttf font resource

    Hi Mike,
    I'm having the same problem as you. I have 3 fonts installed (same way you did it) using DrawString for 3 different texts, but every time the dialog opens, the text shows different (fonts interchanged, sometimes one of the phrases doesn't appear,etc).
    Did you find the reason?

  3. #3
    Join Date
    Nov 2019
    Posts
    4

    Re: MFC GDI+ loading ttf font resource

    Hi

    Yes, I got it to work. Here is my function drawing the text:

    Code:
    RectF CMiachFieldDlg::DrawText(Graphics& rgraphics, COwnFont font, int x, int y, Color col1, Color col2, int align, CString& text)
    {
    	RectF size;
    	PointF origin((float)(x+font.xoffs[align]),(float)(y+font.yoffs));
       
    	StringFormat fmt;
    	fmt.SetLineAlignment(StringAlignment::StringAlignmentNear);
    	switch(align) {
    		case 0:	fmt.SetAlignment(StringAlignment::StringAlignmentFar); break;
    		case 1:	fmt.SetAlignment(StringAlignment::StringAlignmentCenter); break;
    		case 2:	fmt.SetAlignment(StringAlignment::StringAlignmentNear);	break;
    	}
    
    	PrivateFontCollection privateFontCollection;
    	HINSTANCE hResInstance = (HINSTANCE)GetModuleHandle(NULL);
    	HRSRC res = ::FindResource(hResInstance, MAKEINTRESOURCE(font.id), L"BINARY");
    	if (res) {
    		HGLOBAL mem = ::LoadResource(hResInstance, res);
    		void* data = ::LockResource(mem);
    		size_t len = ::SizeofResource(hResInstance, res);
    		Gdiplus::Status nResults = privateFontCollection.AddMemoryFont(data,len);
    	}
    	FontFamily* pFontFamily;
    	int nNumFound=privateFontCollection.GetFamilyCount();
    	if(nNumFound == 0) {
    		return size;
    	}
    	pFontFamily = (FontFamily*)malloc(nNumFound * sizeof(FontFamily));
    	Gdiplus::Status nResults = privateFontCollection.GetFamilies(1, pFontFamily, &nNumFound);
    	if(nResults != Gdiplus::Ok) {
    		return size;
    	}
    	WCHAR familyName[50];
    	pFontFamily[0].GetFamilyName(familyName);
    	Gdiplus::Font* pFont = ::new Gdiplus::Font(familyName, (float)font.size, FontStyleRegular, UnitPixel, &privateFontCollection);
    
    	LinearGradientBrush brush(Rect(x+font.xoffs[align],y+font.yoffs, 1000, (int)pFont->GetHeight(&rgraphics)), col1, col2, LinearGradientModeVertical);
    	rgraphics.DrawString(text, -1, pFont, origin, &fmt, &brush);
    
    	rgraphics.MeasureString(text, -1, pFont, origin, &size);
    
    	::delete(pFont);
    	free(pFontFamily);
    	
    	return size;
    }

  4. #4
    Join Date
    Nov 2019
    Posts
    4

    Re: MFC GDI+ loading ttf font resource

    Hi

    When I remember correctly, the problem was that you must not delete the privateFontCollection Object. It should stay in memory all the time.

  5. #5
    Join Date
    Nov 2019
    Posts
    4

    Re: MFC GDI+ loading ttf font resource

    Cannot edit my posts....

    I saw that privateFontCollection is a local object, so that was not the problem. I really cannot remember the reason anymore, but above code works.

  6. #6
    Join Date
    Nov 2004
    Posts
    4

    Re: MFC GDI+ loading ttf font resource

    Ok, thank you very much.
    I'll try it!

  7. #7
    Join Date
    Nov 2004
    Posts
    4

    Re: MFC GDI+ loading ttf font resource

    Well, I don't know why, but id doesn't work for me.
    This is my code:
    Code:
    void CMiDialogo::DrawMyText(Graphics& rgraphics, WCHAR* text, int typeFont, float x, float y, Brush* myBrush)
    {
    	PrivateFontCollection privateFontCollection;
    	PointF origin(x, y);
    	
    	int fResource;
    	switch (typeFont) {
    	case 1:
    		fResource = IDR_MYFONT_1FEDRA;
    	case 2:
    		fResource = IDR_MYFONT_3FEDRA;
    	case 3:
    		fResource = IDR_MYFONT_5FEDRA;
    	}
    	HINSTANCE hResInstance = (HINSTANCE)GetModuleHandle(NULL);
    	HRSRC res = ::FindResource(hResInstance, MAKEINTRESOURCE(fResource), "BINARY");
    	if (res) {
    		HGLOBAL mem = ::LoadResource(hResInstance, res);
    		void* data = ::LockResource(mem);
    		size_t len = ::SizeofResource(hResInstance, res);
    		Gdiplus::Status nResults = privateFontCollection.AddMemoryFont(data, len);
    	}
    	FontFamily* pFontFamily;
    	int nNumFound = privateFontCollection.GetFamilyCount();
    	
    	pFontFamily = (FontFamily*)malloc(nNumFound * sizeof(FontFamily));
    	Gdiplus::Status nResults = privateFontCollection.GetFamilies(1, pFontFamily, &nNumFound);
    	
    	WCHAR familyName[50];
    	pFontFamily[0].GetFamilyName(familyName);
    	Gdiplus::Font* pFont = ::new Gdiplus::Font(familyName, 13, FontStyleRegular, UnitPoint, &privateFontCollection);
    	rgraphics.DrawString(text, -1, pFont, origin,  myBrush);
    
    	::delete(pFont);
    	free(pFontFamily);
    }
    Then I make my calls this way:
    Code:
    DrawMyText(graphics, L"My first text", 3 , 20.0, 9.0 , &brushB);
    DrawMyText(graphics, L"My second text", 2 , 110.0 , 55.0 , &brushN);
    DrawMyText(graphics, L"My third text", 1 ,  110.0 , 75.0 , &brushB);
    DrawMyText(graphics, L"My fourth text", 2 , 110.0 , 95.0 , &brushN);
    DrawMyText(graphics, L"My fifth text", 1 , 110.0, 115.0 , &brushN );
    But the text is always rendered with the font called in the first call (in the example everything is called with type 3, IDR_MYFONT_5FEDRA, but if I change the first call to type 2, each text is rendered with IDR_MYFONT_3FEDRA font).
    Any suggestion?

  8. #8
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,189

    Re: MFC GDI+ loading ttf font resource

    Code:
    case 1:
    		fResource = IDR_MYFONT_1FEDRA;
    	case 2:
    		fResource = IDR_MYFONT_3FEDRA;
    	case 3:
    		fResource = IDR_MYFONT_5FEDRA;
    You are missing the break statements after the assignments!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.7.0)

  9. #9
    Join Date
    Nov 2004
    Posts
    4

    Re: MFC GDI+ loading ttf font resource

    Quote Originally Posted by 2kaud View Post
    Code:
    case 1:
    		fResource = IDR_MYFONT_1FEDRA;
    	case 2:
    		fResource = IDR_MYFONT_3FEDRA;
    	case 3:
    		fResource = IDR_MYFONT_5FEDRA;
    You are missing the break statements after the assignments!
    Right! What a stupid mistake!
    Thanks.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)