Thread: No text appears on the screen with CreateFont() and DrawFont()?

  1. #1
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288

    No text appears on the screen with CreateFont() and DrawFont()?

    Hello, to learn about Windows GUI objects, I have written the below code. Another main reason I have written it is to hopefully be able to have access to the API to make it easier to draw text on my SDL GUI's client window, since it should work as long as I own the process. In any case, my code displays absolutely nothing. It also receives no error messages, so I'm not sure what I got wrong in my window procedure. It seems to also be a little misbehaved on Windows XP, because although it handles the escape key message, it doesn't exit right away on Windows XP. It doesn't have this problem on Windows 7. Currently, no text appears on the screen and it is just plain black. I hope someone knows more about how to format GDI objects than I do, because I based my setup of my text object off of Microsoft's example.


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    
    #define WIN_32_LEAN_AND_MEAN
    #include <windows.h>
    
    
    #include <stdint.h>
    
    
    #define GUI_WIDTH 500
    #define GUI_HEIGHT 750
    
    
    #define BACKGROUND_COLOR RGB( 0, 0, 0 )
    
    
    void win_error( char * message, BOOL exit )
    {
        char buffer[BUFSIZ] = { 0 };
        DWORD error_code = GetLastError( );
    
    
        FormatMessage
        (
            FORMAT_MESSAGE_FROM_SYSTEM,
            NULL,
            error_code,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) buffer,
            BUFSIZ,
            NULL
        );
    
    
        MessageBox(NULL, buffer, "Error from System :", MB_ICONWARNING | MB_OK );
    
    
        if ( exit ) ExitProcess( error_code );
    
    
        return;
    }
    
    
    LRESULT CALLBACK window_procedure( HWND window_handle, UINT message, WPARAM wParam, LPARAM lParam )
    {
        static HDC window_device_context = NULL;
        HDC drawing_context = NULL;
        PAINTSTRUCT paint_struct = { 0 };
        RECT window_region = { 0 };
        RECT text_rect = { 0 };
        HBRUSH brush_object = CreateSolidBrush( BACKGROUND_COLOR );
        HFONT h_font = NULL;
    
    
        switch( message )
        {
            case WM_CREATE :
                if ( !( window_device_context = GetDC( window_handle ) ) )
                    win_error( "GetDC( )", TRUE );
                GetWindowRect( window_handle, &window_region );
            break;
    
    
            case WM_PAINT :
                drawing_context = BeginPaint( window_handle, &paint_struct );
    
    
                h_font = CreateFont(
                                     0,
                                     0,
                                     0,
                                     0,
                                     FW_BOLD,
                                     FALSE,
                                     FALSE,
                                     FALSE,
                                     ANSI_CHARSET,
                                     OUT_OUTLINE_PRECIS,
                                     CLIP_DEFAULT_PRECIS,
                                     DEFAULT_QUALITY,
                                     VARIABLE_PITCH | FF_DECORATIVE,
                                     TEXT("Rockwell Ultra Bold")
                                   );
    
    
                if ( !h_font )
                {
                    win_error( "CreateFont( )", FALSE );
                    PostQuitMessage( 0 );
                }
    
    
                text_rect = window_region;
                SelectObject( drawing_context, h_font );
                SetTextColor( drawing_context, RGB( 255, 255, 255 ) );
    
    
                if ( !DrawText( drawing_context, TEXT("Hello Windows!"), -1, &text_rect, DT_CENTER ) )
                {
                    win_error( "DrawText( )", FALSE );
                    PostQuitMessage( 0 );
                }
    
    
                DeleteObject( h_font );
                h_font = NULL;
    
    
                EndPaint( window_handle, &paint_struct );
            break;
    
    
            case WM_MOVE :
                GetWindowRect( window_handle, &window_region );
                UpdateWindow( window_handle );
            break;
    
    
            case WM_CLOSE :
                DestroyWindow( window_handle );
            break;
    
    
            case WM_DESTROY :
                ReleaseDC( window_handle, window_device_context );
                DeleteObject( brush_object );
            break;
    
    
            case WM_KEYDOWN :
                switch ( wParam )
                {
                    case VK_ESCAPE :
                        PostQuitMessage( 0 );
                    break;
    
    
                    default :
                        printf( "Unhandled key message : %X\n", ( unsigned )wParam );
                        printf( "Character : %c\n\n", ( char )wParam );
                    break;
                }
            break;
    
    
            case WM_LBUTTONDOWN :
                printf( "Left mouse click.\n" );
            break;
    
    
            case WM_RBUTTONDOWN :
                printf( "Right mouse click.\n" );
            break;
    
    
            default:
                return DefWindowProc( window_handle, message, wParam, lParam );
            break;
        }
    
    
        return 0;
    }
    
    
    int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdArgs, int nCmdShow )
    {
        WNDCLASSEX window_class;
        HWND window_handle;
        MSG message;
        HBRUSH window_color = CreateSolidBrush( BACKGROUND_COLOR );
    
    
        window_class.cbSize = sizeof( WNDCLASSEX );
        window_class.style = 0;
        window_class.lpfnWndProc = window_procedure;
        window_class.cbClsExtra = 0;
        window_class.cbWndExtra = 0;
        window_class.hInstance = hInstance;
        window_class.hIcon = LoadIcon( NULL, IDI_APPLICATION );
        window_class.hCursor = LoadCursor( NULL, IDC_ARROW );
        window_class.hbrBackground = window_color;
        window_class.lpszMenuName = NULL;
        window_class.lpszClassName = "NewClass";
        window_class.hIconSm = NULL;
    
    
        if( !RegisterClassEx( &window_class ) )
            win_error( "RegisterClassEx( )", TRUE );
    
    
        window_handle = CreateWindowEx
                                (
                                  WS_EX_CLIENTEDGE,
                                 "NewClass",
                                 "Hello",
                                  WS_TILEDWINDOW,
                                  CW_USEDEFAULT,
                                  CW_USEDEFAULT,
                                  GUI_HEIGHT,
                                  GUI_WIDTH,
                                  NULL,
                                  NULL,
                                  hInstance,
                                  NULL
                                );
    
    
        if( !window_handle )
        {
            UnregisterClass( "NewClass", hInstance );
            win_error( "CreateWindowEx( )", TRUE );
        }
    
    
        ShowWindow( window_handle, SW_SHOW );
        UpdateWindow( window_handle );
    
    
        while( GetMessage( &message, window_handle, 0, 0 ) > 0 )
        {
            TranslateMessage( &message );
            DispatchMessage( &message );
        }
    
    
        UnregisterClass( "NewClass", hInstance );
    
    
        return 0;
    }
    The desired effect is for the text "Hello Windows" to be displayed in white in the Rockwell Ultra Bold font on the center of the screen, with the optional escape key exiting immediately.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

  2. #2
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    I am by no means any good at programming but I'll give it a shot...First off the return for your WinMain function should be message.wParam and not 0. Secondly, setting the text color to white via "SetTextColor( drawing_context, RGB( 255, 255, 255 ) );" is not going to work since the text box created by DrawText() will be white and therefore a white colored font in a white box will not show up....Use a different color for the font (i.e. 255, 0 ,0 for red). Thirdly, I believe the DrawText() function utilizes the text box (size of the text to be rendered) and not the window client area for the Format parameter. Therefore, the DT_CENTER parameter would be the middle of the string "Hello Windows!"....Roughly around were the "i" is. Try the following and see if it helps in showing the text:

    DrawText( drawing_context, TEXT("Hello Windows!"), -1, &text_rect, DT_NOCLIP | DT_SINGLELINE | DT_LEFT );

    Your WM_CLOSE should also have DeleteObject( h_font );

    Likewise, WM_DESTROY should also have PostQuitMessage (0);

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    I think the problem with your DrawText() function has to do with the parameter &text_rect not getting the proper coordinates stored in the RECT structure. If you manually fill the RECT structure with the following:
    SetRect( &text_rect, 0, 225, GUI_WIDTH, GUI_HEIGHT );

    then the text displays in the correct position within the window using your original (somewhat original) line of code:
    DrawText( drawing_context, TEXT("Hello Windows!"), -1, &text_rect, DT_NOCLIP | DT_SINGLELINE | DT_CENTER );

  4. #4
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288
    Thanks, that helped me fix it. I also got the text to be transparent and flash different colors now using timers. I moved the deletion of the GDI objects to the proper place too.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

  5. #5
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    In general your paint should not be creating objects or working out where to draw things. All that work should have already been done prior to you generating the paint message.

    This is because other events on the PC will also generate ppaint messages and your code is too slow.

    All my paint handlers are simply;

    Code:
    case WM_PAINT:
    PAINTSTRUCT ps = {0};
    BeginPaint(window_handle, &ps);	
    
    BitBlt(	ps.hdc, 
    	ps.rcPaint.left,
    	ps.rcPaint.top,
    	ps.rcPaint.right - ps.rcPaint.left,
    	ps.rcPaint.bottom - ps.rcPaint.top,
    	drawing_context,
    	ps.rcPaint.left, 
    	ps.rcPaint.top,
    	SRCCOPY);
    
    EndPaint(window_handle, &ps);
    break;
    >>text_rect = window_region;

    Wrong area.

    Use GetClientRect() as this is the area you can draw on. GetWindowRect() is the total area of your app, including the non client area (menu, toolbar, border, system menu, etc).

    When you understand how to do GDI drawing properly (not the crap you are using in this code) then use the rect element in the PAINTSTRUCT.

    Why are you using PostQuitMessage() outside of a WM_DESTROY handler?
    You do understand that it will send a WM_QUIT to your message pump? (so no GDI clean up...)

    >>HBRUSH brush_object = CreateSolidBrush( BACKGROUND_COLOR );

    Do you understand that this creates a GDI object every message, including the hundreds of messages you do not process?

    You are not managing your GDI objects correctly.

    Code:
    //create GDI object
    HFONT hFont = CreateFont(.....);
    HFONT *hDefault = NULL;
    
    //select the font into the DC
    //catching the current, default font
    hDefault = SelectObject( memDc, hFont);
    
    //write the text
    
    
    //return the default GDI objects to the DC
    SelectObject( memDC, hDefault); //no need to catch the font as it is hFont
    
    //clean up any GDI we created
    DeleteObject( hFont);
    EDIT: Please note all code is from memory and so is wrong, full of bugs and may cause harm to your PC / pets / chances to have children.
    Last edited by novacain; 11-19-2013 at 02:32 AM.
    "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. CreateFont and CreateWindowEx
    By Joelito in forum Windows Programming
    Replies: 1
    Last Post: 10-29-2005, 05:26 PM
  2. Capturing dos text screen in C
    By hednast in forum C Programming
    Replies: 13
    Last Post: 08-11-2005, 07:49 PM
  3. CreateFont arguments
    By nickname_changed in forum Windows Programming
    Replies: 1
    Last Post: 05-31-2003, 06:56 AM
  4. get text from screen
    By ipe in forum C Programming
    Replies: 5
    Last Post: 03-28-2003, 04:40 PM
  5. Text on graphics screen
    By bjbouchard in forum C++ Programming
    Replies: 1
    Last Post: 04-04-2002, 10:38 PM