-1
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

HDC             hdc;
PAINTSTRUCT     ps;
TCHAR           szBuffer[1];



switch (message)
{
case WM_CHAR:
    szBuffer[1] = (TCHAR) wParam;
    cout << wParam << " " << szBuffer[1] << " ";

    break;

case WM_PAINT:
    InvalidateRect(hwnd, NULL, TRUE);
    hdc = BeginPaint(hwnd, &ps);
    SelectObject(hdc,GetStockObject(SYSTEM_FIXED_FONT));
    TextOut(hdc, 1, 1, szBuffer, 1);
    EndPaint(hwnd, &ps);
    return 0;

Hello all, I am trying to run the above code and simply print a single letter at a time on my window. However, I cannot seem to get the characters to appear on the window with the TextOut function but am able to display the characters in the terminal window. I am new to WinApi and am lost!

thanks in advance!

  • 1
    `static TCHAR szBuffer[2];` ... `szBuffer[0] = (TCHAR)wParam; szBuffer[1] = '\0';` – Jonathan Potter Nov 18 '14 at 22:57
  • @JonathanPotter the joys of GDI text APIs that not only don't require null-terminated strings but also don't allow them outright... (Really, I wish the functions would accept -1 to mean null-terminated like the charset conversion functions :| ) I'm guessing that this person is coming from some other programming language (one with 1-based indexing) so I tried to reflect that in my answer :/ But yes, learning about null-terminated strings may be important – andlabs Nov 18 '14 at 23:00
  • 2
    Do NOT have an InvalidateRect() call inside your WM_PAINT handler. InvalidateRect() is what you call to force WM_PAINT to be called in the first place. You might want to put it in your WM_CHAR handler though. – Joseph Willcoxson Nov 18 '14 at 23:13
  • @andlabs: Yes it's best to get into good habits from the very start :) – Jonathan Potter Nov 18 '14 at 23:13

1 Answers1

3

Your szBuffer is local to WndProc() and by default local variables in C have automatic storage: each time your WndProc() is called, a new szBuffer is created, so by the time your WM_PAINT is reached, whatever was typed in WM_CHARwas lost. You will need to store szBuffer somewhere else, such as outside WndProc(), or declare it as static, which will keep the buffer around (but beware that static storage is NOT safe for recursion).

Also in C the first element of an array has index 0, not 1; the line szBuffer[1] = (TCHAR) wParam; needs to be szBuffer[0] = (TCHAR) wParam; to do what you want.


Since I am running on the assumption you are new to C, see Jonathan Potter's comment about having an extra character in your strings whose value is zero (not the character code for the digit zero, but the numerical value 0, or '\0' or L'\0'). While TextOut() and the other GDI text drawing functions don't use these null-terminated strings, everything else in C does. Watch out.


And Joe Willcoxson's comment is also correct. InvalidateRect() queues the given rectangle as needing repaint. Using it in your WM_PAINT handler will cause you to always get WM_PAINT messages over and over again, which will have negative effects on performance as your programs become larger and larger.

andlabs
  • 11,290
  • 1
  • 31
  • 52