Sign in to follow this  
SteveHatcher

Getting debug information using TextOut()

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

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

The flicker is inevitable...

 

Hi Aardvajk,

 

Thanks, that makes sense. So are you saying that because win32 is generally based on event driven programs, not ones that run in a loop, it is only expecting a refresh or an update based on user input. And directX draws to the back buffer and then flips to the front buffer which keeps this smooth (no flickering because of the continual update of only whats changed... or something like that).

 

So basically with my engine like it is now I should just not worry about the flicker since I am just using it for very primitive output purposes?

 

Thanks

Share this post


Link to post
Share on other sites

Right, I couldn't remember until Aardvajk mentioned it. With the Win32 API it was something like you want to blt to a memory DC first and then you could either blt that to your display DC or you could setup something to do page flipping. There should be examples that you can google to do this. Any examples I have are from before the revamped the API but I seem to remember you wanted to be careful about releasing any objects you're using properly. And as I recall I was able to use the Win32 API to get some ok graphics response with just setting up a timer to call InvalidateRect with a short interval.

 

That said, your code as it is in your example writes the text first and then (when uncommented) paints a solid rectangle next, so you're not going to see your text very well whether it goes to a back buffer or not.

Edited by kseh

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this