Print out a Score?

Hey, I'm not sure how to go about printing text to the window. I've used WM_PAINT but it only prints it out once and then disappears, any help would be great.
You need to learn about Windows GUI programming. I hear the tutorial @ www.winprog.org is good except for the fact that it DOESN'T use the correct function names with the correct data types (this is the Unicode/ANSI dilemma). Read this to get the names and data types issue corrected: http://www.cplusplus.com/forum/general/56526/
What you are describing is the classic case of the mis-use of GetDC() instead of BeginPaint() properly used in a WM_PAINT handler - one of my pet peeves.
Ah sorry for doing it! I'm a novice in windows programming. Anyway, I was using BeginPaint but changing to GetDC doesnt work either, a quick example would be greatly appreciated.
No problem, but I'm a bit pressed for time right now. Have doctors app in a few minutes. Will post and explain in few hours.
Thanks :)
If your wanting to use Win32 then here is code I was working on last night using Code::Blocks IDE with MinGW. It works on MS Visual C++ too.

It prints text that are transparent as well as background and foreground colors. And a box.

Make sure not to choose console or windows forms, but choose Win32 GUI as your default for your IDE. That is if your wanting to use Win32 GUI and not windows forms.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <windows.h>
using namespace std;

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "PrintTextExample";

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = 0;
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Print Text Example",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           800,                 /* The programs width */
           600,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC         hDC;
        PAINTSTRUCT Ps;
	COLORREF    clrBlue = RGB(25, 55, 200);
	RECT        Recto = { 20, 28, 188, 128 };
	COLORREF    clrAqua = RGB(128, 255, 255);

	switch(message)
	{
	case WM_DESTROY:
		PostQuitMessage(WM_QUIT);
		break;
	case WM_PAINT:
		hDC = BeginPaint(hwnd, &Ps);
		SetTextColor(hDC, clrBlue);
		SetBkColor(hDC, clrAqua);
		ExtTextOut(hDC, 50, 42, OPAQUE, &Recto, "SCORE ! I have a Box !", 22, NULL);
		SetTextColor(hDC, clrBlue);
		SetBkMode(hDC, TRANSPARENT);
                ExtTextOut(hDC, 130, 82, NULL, 0, "Get a Clue !!!", 14, NULL);
		EndPaint(hwnd, &Ps);
		break;
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
	}
	return 0;
}
Last edited on
Hey, thanks for trying to help. But that code still only prints out the text once, I need it to reprint every frame.
You mean Updated Text ? When I run this code it prints it out and it stays on the screen, so I am guessing you mean to Update the text. Just making sure I understand you correctly.
Your text stays on the screen because you dont update the window every frame. If I take my game loop out of my code it will stay on the screen but thats not much use.
I should have realized you were a game programmer. Game programmers seem to more or less break the rules, and are usually told so when they post here. I suppose that's why running games usually requires laptop coolers, heavy duty coolers, etc. It seems in game programming (which I know absolutely nothing about; I've been using computers for 36 years and have never even played played my first game) one repeatedly runs Windows drawing routines through loops which basically pegs the processor right up to about 100% continually. Windows wasn't designed to run that way, and that's why it burns hardware up. I expect that's what you are working on right now. Anyway, I made a short program showing the problems with GetDC(). I might as well post it as I said I would, but it likely won't help you any more than WinwordExonar did...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//Form1.cpp
#include <windows.h>
#include <tchar.h>
#define IDC_RIGHT  1500   // Identifier Of Button Control Right
#define IDC_WRONG  1510   // Identifier Of Button Control Wrong


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
   case WM_CREATE:
    {
        HINSTANCE hIns=((LPCREATESTRUCT)lParam)->hInstance;            //Create two button controls.  Top button
        TCHAR szRight[]=_T("Here Is The Right Way To Paint!");         //draws text to window correctly with
        TCHAR* pStr=(TCHAR*)GlobalAlloc                                //TextOut() in a WM_PAINT handler.  2nd
        (                                                              //button draws text to main window
         GPTR,sizeof(TCHAR)*(_tcslen(szRight)+1)                       //incorrectly with GetDC() and TextOut()
        );                                                             //within WM_COMMAND handler.
        _tcscpy(pStr,szRight);
        SetWindowLong(hwnd,0,(long)pStr);                              //Note I allocated 8 bytes of extra storage
        HWND hCtrl=CreateWindowEx                                      //within the class structure with the
        (                                                              //WNDCLASSEX::cbWndExtra bytes.  In the 1st
         0,_T("button"),_T("Right Way To Paint"),WS_CHILD|WS_VISIBLE,  //four bytes I'm storing a pointer to the
         45,30,200,30,hwnd,(HMENU)IDC_RIGHT,hIns,0                     //string 'Here Is The Right Way To Paint'.
        );                                                             //I allocated memory to persist this string
        hCtrl=CreateWindowEx                                           //with GlobalAlloc() and stored the pointer
        (                                                              //at offset zero within the .cbWndExtra bytes
         0,_T("button"),_T("Wrong Way To Paint"),WS_CHILD|WS_VISIBLE,  //allocation.  It is retrieved in the WM_PAINT
         45,130,200,30,hwnd,(HMENU)IDC_WRONG,hIns,0                    //handler and drawn.  Note that memory is
        );                                                             //released in WM_DESTROY.  Further note that
        return 0;                                                      //bytes 4 through 7 of the cbWndExtra bytes
    }                                                                  //holds a bool for me.  It is initially false
   case WM_COMMAND:                                                    //but when you click the top button it is set
    {                                                                  //to true and an InvalidateRect() call forces
        switch(LOWORD(wParam))                                         //a repaint.  That's how the text shows up
        {                                                              //when you click the top button.  This is the
          case IDC_RIGHT:                                              //correct way to paint under Windows.  The
            {                                                          //text drawn will persist.
               SetWindowLong(hwnd,4,(long)true);
               InvalidateRect(hwnd,NULL,false);                        //The incorrect way to paint in Windows is
            }                                                          //exemplified by the behavior of the 2nd
            break;                                                     //button.  When you click it a HDC is
          case IDC_WRONG:                                              //obtained and a text string drawn to the
            {                                                          //window.  Its behavior is truely funny.
               TCHAR szWrong[]=_T("And Here Is The Wrong Way!");       //What I like to do is open Notepad and
               HDC hDC=GetDC(hwnd);                                    //resize Notepad until its real small like
               SetBkMode(hDC,TRANSPARENT);                             //an old blackboard eraser.  Then pretend
               TextOut(hDC,48,185,szWrong,_tcslen(szWrong));           //I'm erasing a blackboard by wiping the
               ReleaseDC(hwnd,hDC);                                    //incorrectly drawn text string with the
            }                                                          //'eraser' of my miniturized Notepad!
            break;
        }
        return 0;
    }
   case WM_PAINT:
    {
        PAINTSTRUCT ps;
        TCHAR* pStr=(TCHAR*)GetWindowLong(hwnd,0);                     //Offset 0 (bytes 0 - 3) hold the ptr
        HDC hDC=BeginPaint(hwnd, &ps);                                 //to the 'right' string.  Offset 4 - 7
        SetBkMode(hDC,TRANSPARENT);                                    //hold a flag as to whether the string
        if(GetWindowLong(hwnd,4))                                      //should be output in WM_PAINT.  The flag
           TextOut(hDC,38,90,pStr,_tcslen(pStr));                      //is set to true when you click the top
        EndPaint(hwnd,&ps);                                            //button.

        return 0;
    }
   case WM_DESTROY:
    {
        TCHAR* pStr=NULL;                                              //You need to release the memory for the
        pStr=(TCHAR*)GetWindowLong(hwnd,0);                            //string allocated in your WM_CREATE handler.
        if(pStr)
           GlobalFree(pStr);
        PostQuitMessage(0);
        return 0;
    }
 }

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


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Form1");
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName;                wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX);               wc.style=CS_DBLCLKS;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);     wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);  wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;    wc.cbWndExtra=8;  //1st four bytes holds pStr
 wc.lpszMenuName=NULL;                        wc.cbClsExtra=0;  //2nd four bytes boolean flag
 RegisterClassEx(&wc);
 hWnd=CreateWindow(szClassName,_T("Form1"),WS_OVERLAPPEDWINDOW,300,200,300,250,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
  TranslateMessage(&messages);
  DispatchMessage(&messages);
 }

 return messages.wParam;
}
I like what you have there freddie.

Also, I have a solution to this problem. But I am in the middle of family issues at this moment. So as soon as possible, sometime tonight I'll rewrite what I have and post a working text that updates. Maybe a number in the WM_PAINT that counts up. Stay Tuned...
Ok, here you go. This prints in graphics text using GDI to the Win32 generated window. Sorry it took me so long to get back to you. Family life can slow my programming skillz down some. haha. Anyhow I hope this helps.

What I did is add 2 timers and every second it prints up the next number higher. It counts from 0 to 99 and then repeats.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#define IDT_ITEMHERE1 1		// first timer identified by integer 1
#define IDT_ITEMHERE2 2		// second timer identified by integer 2

#include <windows.h>
#include <iostream>
#include <stdio.h>

using namespace std;
int t=0;
char szMyString[3]={0};

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "PrintTextExample";

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = 0;
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Print Text Example",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           320,                 /* The programs width */
           240,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{


	HDC                hDC;
        PAINTSTRUCT Ps;
	COLORREF     clrBlue = RGB(25, 55, 200);
	RECT              Recto = { 20, 28, 188, 128 };
	RECT              Recto2 = { 228, 90, 275, 110 };
	COLORREF    clrAqua = RGB(128, 255, 255);

    _snprintf(szMyString, 2, "%d" , t);

	switch(message)
	{

    case WM_CREATE:
    {
         SetTimer(hwnd, IDT_ITEMHERE1, 1000, NULL); // 1000 equals 1 second
         SetTimer(hwnd, IDT_ITEMHERE2, 250, NULL); // 250 equals 1/4th of a second
         return 0;
    }
    break;

	case WM_PAINT:
	{
		hDC = BeginPaint(hwnd, &Ps);
		SetTextColor(hDC, clrBlue);
		SetBkColor(hDC, clrAqua);
		ExtTextOut(hDC, 50, 42, OPAQUE, &Recto, "SCORE ! I have a Box !", 22, NULL);
		SetTextColor(hDC, clrBlue);
                SetBkMode(hDC, TRANSPARENT);
                TextOut(hDC, 50, 72, "Hey this text has transparency !", 33);
                TextOut(hDC, 30, 92, "It will repeat 0 to 99.", 24);
		EndPaint(hwnd, &Ps);
		return 0;
	}
	break;

	case WM_DESTROY:
	{
		PostQuitMessage(0);
        return 0;
	}
	break;

    case WM_TIMER:
    {
        switch(wParam)
        {
           case IDT_ITEMHERE1:
             t++;
             if(t>99)
               {
                   t=0;
               }
             break;
           case IDT_ITEMHERE2:
             _snprintf(szMyString, 3, "%d" , t);
            hDC = GetDC(hwnd);
            SetTextColor(hDC, clrBlue);
            SetBkMode(hDC, TRANSPARENT);
	    ExtTextOut(hDC, 230, 92, OPAQUE, &Recto2, szMyString, 3, NULL);
        }
        return 0;
	}
    break;

   	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}
Last edited on
Wow thanks for all the help guys :) Turns out just throwing TextOut in the main loop on its own seems to work.
Topic archived. No new replies allowed.