Jump to content
  • Advertisement
Sign in to follow this  
SteveHatcher

Getting debug information using TextOut()

This topic is 687 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all,

 

I am trying to get some debug information using Microsoft inbuilt text display e.g. TextOut(). I am trying to make a very simple base game engine (for learning purposes) and before adding its graphics class I want to test a game state system and some other things.

 

My game uses this demo to get the win32 window up

 

https://msdn.microsoft.com/en-us/library/windows/desktop/ff381409(v=vs.85).aspx

 

and after ShowWindow(hwnd, nCmdShow);, I create my game Game myGame; and then call its init() function myGame.init().

In the message loop I peek messages and if no messages are to be dispatched I run game.run().

 

This is where I get confused: I want to write out to the things like e.g. the current game state (I am trying for a 1 second splash screen, then main menu). I can see it is working when I debug and look at my m_state variable, but I want to see it change in real time on the window, so I thought i could use TextOut. The problem is I seem to need all of the information from WM_PAINT to use textout (like the PAINTSTRUCT), but my game does not hit WM_PAINT...

 

Am I going about this the right way?

 

Thanks for all your help

 

 

 

 

 

Share this post


Link to post
Share on other sites
Advertisement

You can use OutputDebugString() which will print to your console window in the debugger if you are using Visual Studio or you can see this by using DebugView without a debugger.

When dealing with GDI as TextOut is you need a WM_PAINT or similar message to update the screen in.

Edited by NightCreature83

Share this post


Link to post
Share on other sites

It's been quite awhile since I've written a Win32 game but if I'm not mistaken, calling InvalidateRect() causes a WM_Paint messages to be sent. Setup a timer to periodically call InvalidateRect() and you should see your text output update. You'll probably want to store that hwnd value from when you create the window so that you'll have access to it for the first parameter. You can use a NULL for the rect parameter to paint the entire window's contents and then it's just whether you want to erase the current contents of the window or not.

Share this post


Link to post
Share on other sites

You can use OutputDebugString() which will print to your console window in the debugger if you are using Visual Studio or you can see this by using DebugView without a debugger.

When dealing with GDI as TextOut is you need a WM_PAINT or similar message to update the screen in.

 

Hi, thanks for your response. I am a bit confused first of all. I don't seem to have a 'console' window, just the win32 window that the demo creates, so I dont know where this output goes? I will have a look into DebugView.

 

 

It's been quite awhile since I've written a Win32 game but if I'm not mistaken, calling InvalidateRect() causes a WM_Paint messages to be sent. Setup a timer to periodically call InvalidateRect() and you should see your text output update. You'll probably want to store that hwnd value from when you create the window so that you'll have access to it for the first parameter. You can use a NULL for the rect parameter to paint the entire window's contents and then it's just whether you want to erase the current contents of the window or not.

 

Thank you, I have kind of got it to work. I am seeing the debug text flicker on the screen, as if it is getting overwritten with a blank white fill or something... I am not sure why. Win32 stuff is so confusing...

 

My message loop now looks like this

    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            game.run(hwnd);
            InvalidateRect(hwnd, NULL, false);
        }
    }

 

with WM paint

 

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        //Textout output
        wchar_t text[] = L"tess test test";
        
        TextOut(hdc, 1, 1, text, ARRAYSIZE(text));
        //Textout output end

        //FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

        EndPaint(hwnd, &ps);
    }

 

When FillRect is not commented out the screen stays white. Thanks for all your help guys.

 

 

Edited by SteveHatcher

Share this post


Link to post
Share on other sites
What value are you returning after handling WM_PAINT? It should be zero; do not pass it on to DefWindowProc, if you draw things yourself.

The flickering could well be WM_ERASEBKGND. If you do all your drawing in WM_PAINT, you can handle WM_ERASEBKGND doing nothing and return a non zero value.


Remember: The return value of a handled message is important. And, if not told otherwise in the messages docs, pass the message on to DefWindowProc. A good WindowProc looks like this:

switch ( MessageType )
{
  case WM_xxx:
    // do stuff
    return or break, depending on what the message docs say
  case WM_other_xxx:
    // do other stuff
    return or break, depending on what the message docs say
}
return DefWindowProc( arguments );

Share this post


Link to post
Share on other sites

What value are you returning after handling WM_PAINT? It should be zero; do not pass it on to DefWindowProc, if you draw things yourself.

The flickering could well be WM_ERASEBKGND. If you do all your drawing in WM_PAINT, you can handle WM_ERASEBKGND doing nothing and return a non zero value.


Remember: The return value of a handled message is important. And, if not told otherwise in the messages docs, pass the message on to DefWindowProc. A good WindowProc looks like this:
 

switch ( MessageType )
{
  case WM_xxx:
    // do stuff
    return or break, depending on what the message docs say
  case WM_other_xxx:
    // do other stuff
    return or break, depending on what the message docs say
}
return DefWindowProc( arguments );

 

Hi Endurion, thanks for your reply. Sorry I should have showed my whole WindowProc:

 

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        //Textout output
        wchar_t text[] = L"tess test test";

        TextOut(hdc, 1, 1, text, ARRAYSIZE(text));
        //Textout output end

        //FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

        EndPaint(hwnd, &ps);
    }
    return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

 

Once I include my graphics class, DirectX will do the drawing, but for now I just want to work with testing values. I cant quite work how how to use WM_ERASEBKGND to avoid flickering? I thought the false flag in InvalidateRect should do this?

Thanks
 

Share this post


Link to post
Share on other sites

 

You can use OutputDebugString() which will print to your console window in the debugger if you are using Visual Studio or you can see this by using DebugView without a debugger.

When dealing with GDI as TextOut is you need a WM_PAINT or similar message to update the screen in.

 

Hi, thanks for your response. I am a bit confused first of all. I don't seem to have a 'console' window, just the win32 window that the demo creates, so I dont know where this output goes? I will have a look into DebugView.

 

 

It's been quite awhile since I've written a Win32 game but if I'm not mistaken, calling InvalidateRect() causes a WM_Paint messages to be sent. Setup a timer to periodically call InvalidateRect() and you should see your text output update. You'll probably want to store that hwnd value from when you create the window so that you'll have access to it for the first parameter. You can use a NULL for the rect parameter to paint the entire window's contents and then it's just whether you want to erase the current contents of the window or not.

 

Thank you, I have kind of got it to work. I am seeing the debug text flicker on the screen, as if it is getting overwritten with a blank white fill or something... I am not sure why. Win32 stuff is so confusing...

 

My message loop now looks like this

    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            game.run(hwnd);
            InvalidateRect(hwnd, NULL, false);
        }
    }

 

with WM paint

 

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        //Textout output
        wchar_t text[] = L"tess test test";
        
        TextOut(hdc, 1, 1, text, ARRAYSIZE(text));
        //Textout output end

        //FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

        EndPaint(hwnd, &ps);
    }

 

When FillRect is not commented out the screen stays white. Thanks for all your help guys.

 

Your console window is the output window in Visual Studio, were you can see which Dlls and symbols are loaded on application start up.

Share this post


Link to post
Share on other sites
There's other possibilities for WM_ERASEBKGND to fire than InvalidateRect calls (moving the window off screen and back on screen for example).

The handler for doing nothing is simple:

case WM_ERASEBKGND:
  return 1;

Share this post


Link to post
Share on other sites

There's other possibilities for WM_ERASEBKGND to fire than InvalidateRect calls (moving the window off screen and back on screen for example).

The handler for doing nothing is simple:
 

case WM_ERASEBKGND:
  return 1;

Hi Endurion,

I have added that but I am still getting the flickering. If i resize or move the window indeed my text does no flicker, but it does when I do nothing...

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	case WM_ERASEBKGND:
		return 1;

	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);

		//Textout output
		wchar_t text[] = L"test test test";

		TextOut(hdc, 1, 1, text, ARRAYSIZE(text));
		//Textout output end

		//FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

		EndPaint(hwnd, &ps);
	}
	return 0;

	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Sorry guys, I have tried everything I have read online so am a bit stuck with this...

Thanks

Edited by SteveHatcher

Share this post


Link to post
Share on other sites

The flicker is inevitable if you first draw a background, then draw the text. The only way to be truly flicker free is to draw the background and then the text to an offscreen buffer, then draw the offscreen buffer to the screen in one go.

 

Otherwise there is a brief period where the background has been drawn but the text has not been.

 

When you are using DirectX this will all be handled for you. You'll be by-default drawing to an offscreen buffer which will then be dumped to the screen in one go. You can simulate it using the Win32 API but if you are planning to switch to DirectX at some point anyway, I wouldn't worry.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!