Discussion:
simple 80 * 25
(too old to reply)
Paul Edwards
2023-07-19 04:32:43 UTC
Permalink
I remembered that a long time ago I wrote a very simple
Win32 graphics program. I can't remember where I got
the concepts from. I'm pretty sure this was before I was
even on the internet.

Original source is here:

https://sourceforge.net/p/mvs380/mvssrc/ci/master/tree/ozpd/c/simpwin.c

And I have made modifications (below) after consulting some
online documentation.

I was able to see that I got a stack of messages.

However, if I press a key, I don't get a WM_CHAR message.

And when I move the window, I don't get another WM_WINDOWPOSCHANGED message.

Which suggests to me that there is something technically
incorrect about my original simple program, even though
it nominally works (ie if you don't inspect the messages
that are being received and given to the default handler).

So the first thing I'd like is for that bug to be fixed.

It's a simple program. I'm not trying to win Miss America
(any such competition can be done another day). But I
do want it to be technically correct.

I also want it to conform to Win32s 1.25 (the last version
to be supported by OS/2) as well as Windows 11.

After that I can see (via experimentation) that I am currently
getting proportional fonts, when I actually want console
fonts I believe. But any fixed width font will do (highest
quality for 80 * 25 to help distinguish between B and 8).

Note that when the keyboard is actually working, I will want
a fullscreen window, not the default one that I am apparently
getting now.

Note that I am after simplicity, so if an application wants to
print a single character, and my handler updates a 80 * 25
buffer and repaints the entire screen - that's perfectly fine.
If there is an alternative that is almost as simple and much
more efficient, that's fine too.

The goal is to get my 32-bit Win32 console back, on two
environments where that is gone/difficult.

Also I'm guessing that to position on the second row, I
need to divide the number of pixels high (from WM_SIZE)
by 25. And it would be convenient to do the same for
width and use TextOut one character at a time. This would
circumvent the problem of proportional fonts too, but
perhaps not the best solution.

Current code below.

Thanks. Paul.



/*********************************************************************/
/* */
/* This Program Written by Paul Edwards. */
/* Released to the Public Domain */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* simpwin - the simplest windows program (roughly speaking) */
/* */
/*********************************************************************/

#include <stdio.h>

#include <windows.h>

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam);

int WINAPI WinMain(IN HINSTANCE inst,
IN HINSTANCE previnst,
IN LPSTR cmd,
IN int cmdshow)
{
WNDCLASS wndClass = { 0, (WNDPROC)simpwin, 0, 0, 0, NULL, NULL,
(HBRUSH)(COLOR_WINDOW+1), "simpwin", "simpwin" };
HWND hwnd;
MSG msg;

(void)previnst;
(void)cmd;
wndClass.hInstance = inst;
RegisterClass(&wndClass);
hwnd = CreateWindow("simpwin", "Simple Windows",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, inst, NULL );
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam)
{
int calldefault = 1;
LONG ret = 0;

switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* DrawText(hdc, "Hello There", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER); */
/* TextOut(hdc, 0, 0, "WWWW", 4); */
/* TextOut(hdc, 1, 1, "IIII", 4); */
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
calldefault = 0;
break;

case WM_NCPAINT:
case WM_GETICON:
case WM_WINDOWPOSCHANGING:
case WM_ACTIVATEAPP:
case WM_NCACTIVATE:
case WM_ACTIVATE:
case WM_IME_NOTIFY:
break;

case WM_IME_SETCONTEXT:
lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
break;

case WM_SETFOCUS:
ret = 0;
calldefault = 0;
break;

case WM_ERASEBKGND:
/* not sure how to actually erase the background - print spaces? */
ret = 1;
calldefault = 0;
break;

case WM_WINDOWPOSCHANGED:
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
static int cnt = 0;

sprintf(buf, "%d %d %X %X\n",
cnt++, (int)msg, (int)wparam, (int)lparam);
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
break;
}
/* lparam is WINDOWPOS and may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_SIZE:
/* low 16 bits of lparam are width - in pixels it seems */
/* high 16 bits are height */
/* unclear why this message is being received in the first
place when the documentation says if I handle WINDOWPOSCHANGED
then these messages are not generated. Maybe what they mean
is that the WM_SIZE will just be a once-off message */
ret = 0;
calldefault = 0;
break;

case WM_MOVE:
/* low 16 bits of lparam are x-pos (start). high 16 bits are
y-pos - same consideration as WM_SIZE */
ret = 0;
calldefault = 0;
break;

case WM_KEYDOWN:
case WM_CHAR:
default:
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

sprintf(buf, "%d %X %X\n", (int)msg, (int)wparam, (int)lparam);
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* DrawText(hdc, "Hello There", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER); */
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
break;
}
}
if (calldefault)
{
ret = DefWindowProc(hwnd, msg, wparam, lparam);
}
return (ret);
}
JJ
2023-07-19 10:07:55 UTC
Permalink
Post by Paul Edwards
I remembered that a long time ago I wrote a very simple
Win32 graphics program. I can't remember where I got
the concepts from. I'm pretty sure this was before I was
even on the internet.
https://sourceforge.net/p/mvs380/mvssrc/ci/master/tree/ozpd/c/simpwin.c
And I have made modifications (below) after consulting some
online documentation.
I was able to see that I got a stack of messages.
However, if I press a key, I don't get a WM_CHAR message.
And when I move the window, I don't get another WM_WINDOWPOSCHANGED message.
It's because there are more than one code which writes text at the same
window client position - overwriting each other's text. So you only see the
last written one.
Paul Edwards
2023-07-19 12:11:34 UTC
Permalink
Post by JJ
Post by Paul Edwards
And when I move the window, I don't get another WM_WINDOWPOSCHANGED message.
It's because there are more than one code which writes text at the same
window client position - overwriting each other's text. So you only see the
last written one.
Thanks. I had a static counter, but it turned out that I was
indeed missing some messages. So I have added those,
but I'm still back at the same spot.

I'm getting PPP 1 0 ... printed, and when I move the window,
that doesn't change. Nor do keypresses get through.

The 0 means that there are no messages that haven't
been handled.

The 1 means that poschanged is only called once.

Any ideas?

Thanks. Paul.


/*********************************************************************/
/* */
/* This Program Written by Paul Edwards. */
/* Released to the Public Domain */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* simpwin - the simplest windows program (roughly speaking) */
/* */
/*********************************************************************/

#include <stdio.h>

#include <windows.h>

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam);

int WINAPI WinMain(IN HINSTANCE inst,
IN HINSTANCE previnst,
IN LPSTR cmd,
IN int cmdshow)
{
WNDCLASS wndClass = { 0, (WNDPROC)simpwin, 0, 0, 0, NULL, NULL,
(HBRUSH)(COLOR_WINDOW+1), "simpwin", "simpwin" };
HWND hwnd;
MSG msg;

(void)previnst;
(void)cmd;
wndClass.hInstance = inst;
RegisterClass(&wndClass);
hwnd = CreateWindow("simpwin", "Simple Windows",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, inst, NULL );
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam)
{
int calldefault = 1;
LONG ret = 0;
static int cnt = 0;
static char newbuf[80];

switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
calldefault = 0;
break;

case WM_NCPAINT:
case WM_GETICON:
case WM_WINDOWPOSCHANGING:
case WM_ACTIVATEAPP:
case WM_NCACTIVATE:
case WM_ACTIVATE:
case WM_IME_NOTIFY:
case WM_SHOWWINDOW:
break;

case WM_IME_SETCONTEXT:
lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
break;

case WM_SETFOCUS:
ret = 0;
calldefault = 0;
break;

case WM_ERASEBKGND:
/* not sure how to actually erase the background - print spaces? */
ret = 1;
calldefault = 0;
break;

case WM_WINDOWPOSCHANGED:
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
static int loccnt = 0;

loccnt++;
sprintf(buf, "PPP %d %d %d %X %X\n",
loccnt, cnt, (int)msg, (int)wparam, (int)lparam);
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
break;
}
/* lparam is WINDOWPOS and may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_SIZE:
/* low 16 bits of lparam are width - in pixels it seems */
/* high 16 bits are height */
/* unclear why this message is being received in the first
place when the documentation says if I handle WINDOWPOSCHANGED
then these messages are not generated. Maybe what they mean
is that the WM_SIZE will just be a once-off message */
ret = 0;
calldefault = 0;
break;

case WM_MOVE:
/* low 16 bits of lparam are x-pos (start). high 16 bits are
y-pos - same consideration as WM_SIZE */
ret = 0;
calldefault = 0;
break;

case WM_GETMINMAXINFO:
/* MINMAXINFO in lparam may be useful or need to be set */
ret = 0;
calldefault = 0;
break;

case WM_NCCALCSIZE:
/* if 0, this may have useful information in RECT */
if (wparam == 0)
{
ret = 0;
/* if we don't call the default, we don't get a window! */
calldefault = 1;
}
else
{
cnt += 50000; /* detect if we're getting true */
}
break;

case WM_NCCREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 1;
calldefault = 0;
break;

case WM_CREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_KEYDOWN:
case WM_CHAR:
default:
{
char buf[80] = "DUMMY";
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

cnt++;
sprintf(newbuf, "ZZZ %d %X %X\n", (int)msg, (int)wparam, (int)lparam);
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
break;
}
}
if (calldefault)
{
ret = DefWindowProc(hwnd, msg, wparam, lparam);
}
return (ret);
}
Uwe Sieber
2023-07-21 07:11:51 UTC
Permalink
MSDN:
"An application should not call BeginPaint except in response to a WM_PAINT message."

Replace BeginPaint + EndPaint by GetDC + ReleaseDC in any other place then WM_PAINT.

At WM_CHAR you print to newbuf but TextOut(buf)
Post by Paul Edwards
Post by JJ
Post by Paul Edwards
And when I move the window, I don't get another WM_WINDOWPOSCHANGED message.
It's because there are more than one code which writes text at the same
window client position - overwriting each other's text. So you only see the
last written one.
Thanks. I had a static counter, but it turned out that I was
indeed missing some messages. So I have added those,
but I'm still back at the same spot.
I'm getting PPP 1 0 ... printed, and when I move the window,
that doesn't change. Nor do keypresses get through.
The 0 means that there are no messages that haven't
been handled.
The 1 means that poschanged is only called once.
Any ideas?
Thanks. Paul.
/*********************************************************************/
/* */
/* This Program Written by Paul Edwards. */
/* Released to the Public Domain */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* simpwin - the simplest windows program (roughly speaking) */
/* */
/*********************************************************************/
#include <stdio.h>
#include <windows.h>
LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam);
int WINAPI WinMain(IN HINSTANCE inst,
IN HINSTANCE previnst,
IN LPSTR cmd,
IN int cmdshow)
{
WNDCLASS wndClass = { 0, (WNDPROC)simpwin, 0, 0, 0, NULL, NULL,
(HBRUSH)(COLOR_WINDOW+1), "simpwin", "simpwin" };
HWND hwnd;
MSG msg;
(void)previnst;
(void)cmd;
wndClass.hInstance = inst;
RegisterClass(&wndClass);
hwnd = CreateWindow("simpwin", "Simple Windows",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, inst, NULL );
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam)
{
int calldefault = 1;
LONG ret = 0;
static int cnt = 0;
static char newbuf[80];
switch (msg)
{
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
EndPaint(hwnd, &ps);
break;
}
PostQuitMessage(0);
calldefault = 0;
break;
break;
lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
break;
ret = 0;
calldefault = 0;
break;
/* not sure how to actually erase the background - print spaces? */
ret = 1;
calldefault = 0;
break;
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
static int loccnt = 0;
loccnt++;
sprintf(buf, "PPP %d %d %d %X %X\n",
loccnt, cnt, (int)msg, (int)wparam, (int)lparam);
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
break;
}
/* lparam is WINDOWPOS and may have useful information */
ret = 0;
calldefault = 0;
break;
/* low 16 bits of lparam are width - in pixels it seems */
/* high 16 bits are height */
/* unclear why this message is being received in the first
place when the documentation says if I handle WINDOWPOSCHANGED
then these messages are not generated. Maybe what they mean
is that the WM_SIZE will just be a once-off message */
ret = 0;
calldefault = 0;
break;
/* low 16 bits of lparam are x-pos (start). high 16 bits are
y-pos - same consideration as WM_SIZE */
ret = 0;
calldefault = 0;
break;
/* MINMAXINFO in lparam may be useful or need to be set */
ret = 0;
calldefault = 0;
break;
/* if 0, this may have useful information in RECT */
if (wparam == 0)
{
ret = 0;
/* if we don't call the default, we don't get a window! */
calldefault = 1;
}
else
{
cnt += 50000; /* detect if we're getting true */
}
break;
/* lparam is CREATESTRUCT which may have useful information */
ret = 1;
calldefault = 0;
break;
/* lparam is CREATESTRUCT which may have useful information */
ret = 0;
calldefault = 0;
break;
{
char buf[80] = "DUMMY";
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
cnt++;
sprintf(newbuf, "ZZZ %d %X %X\n", (int)msg, (int)wparam, (int)lparam);
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
break;
}
}
if (calldefault)
{
ret = DefWindowProc(hwnd, msg, wparam, lparam);
}
return (ret);
}
Paul Edwards
2023-07-21 14:35:23 UTC
Permalink
Post by Uwe Sieber
"An application should not call BeginPaint except in response to a WM_PAINT message."
Replace BeginPaint + EndPaint by GetDC + ReleaseDC in any other place then WM_PAINT.
At WM_CHAR you print to newbuf but TextOut(buf)
Thanks. I didn't really need it printed at that exact spot, so I
just changed it to stop printing. Am I expecting to get a
fresh WM_PAINT message after moving the window or
pressing a key?

Because currently I'm getting PPP 1 1 ...

which means that I'm just getting a single position changed, and
I'm not getting any keystrokes at all.

Unless I'm only ever receiving a single WM_PAINT message,
which would explain why I don't see any more action.

Thanks. Paul.


/*********************************************************************/
/* */
/* This Program Written by Paul Edwards. */
/* Released to the Public Domain */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* simpwin - the simplest windows program (roughly speaking) */
/* */
/*********************************************************************/

#include <stdio.h>

#include <windows.h>

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam);

int WINAPI WinMain(IN HINSTANCE inst,
IN HINSTANCE previnst,
IN LPSTR cmd,
IN int cmdshow)
{
WNDCLASS wndClass = { 0, (WNDPROC)simpwin, 0, 0, 0, NULL, NULL,
(HBRUSH)(COLOR_WINDOW+1), "simpwin", "simpwin" };
HWND hwnd;
MSG msg;

(void)previnst;
(void)cmd;
wndClass.hInstance = inst;
RegisterClass(&wndClass);
hwnd = CreateWindow("simpwin", "Simple Windows",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, inst, NULL );
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam)
{
int calldefault = 1;
LONG ret = 0;
static int cnt = 0;
static char newbuf[80];

switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, newbuf, strlen(newbuf));
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
calldefault = 0;
break;

case WM_NCPAINT:
case WM_GETICON:
case WM_WINDOWPOSCHANGING:
case WM_ACTIVATEAPP:
case WM_NCACTIVATE:
case WM_ACTIVATE:
case WM_IME_NOTIFY:
case WM_SHOWWINDOW:
break;

case WM_IME_SETCONTEXT:
lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
break;

case WM_SETFOCUS:
ret = 0;
calldefault = 0;
break;

case WM_ERASEBKGND:
/* not sure how to actually erase the background - print spaces? */
ret = 1;
calldefault = 0;
break;

case WM_WINDOWPOSCHANGED:
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
static int loccnt = 0;

loccnt++;
cnt++;
sprintf(newbuf, "PPP %d %d %d %X %X\n",
loccnt, cnt, (int)msg, (int)wparam, (int)lparam);
#if 0
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
#endif
break;
}
/* lparam is WINDOWPOS and may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_SIZE:
/* low 16 bits of lparam are width - in pixels it seems */
/* high 16 bits are height */
/* unclear why this message is being received in the first
place when the documentation says if I handle WINDOWPOSCHANGED
then these messages are not generated. Maybe what they mean
is that the WM_SIZE will just be a once-off message */
ret = 0;
calldefault = 0;
break;

case WM_MOVE:
/* low 16 bits of lparam are x-pos (start). high 16 bits are
y-pos - same consideration as WM_SIZE */
ret = 0;
calldefault = 0;
break;

case WM_GETMINMAXINFO:
/* MINMAXINFO in lparam may be useful or need to be set */
ret = 0;
calldefault = 0;
break;

case WM_NCCALCSIZE:
/* if 0, this may have useful information in RECT */
if (wparam == 0)
{
ret = 0;
/* if we don't call the default, we don't get a window! */
calldefault = 1;
}
else
{
cnt += 50000; /* detect if we're getting true */
}
break;

case WM_NCCREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 1;
calldefault = 0;
break;

case WM_CREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_KEYDOWN:
case WM_CHAR:
default:
{
char buf[80] = "DUMMY";
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

cnt++;
sprintf(newbuf, "ZZZ %d %X %X\n", (int)msg, (int)wparam, (int)lparam);
/* hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps); */
break;
}
}
if (calldefault)
{
ret = DefWindowProc(hwnd, msg, wparam, lparam);
}
return (ret);
}
Paul N
2023-07-21 14:58:15 UTC
Permalink
Post by Paul Edwards
Post by Uwe Sieber
"An application should not call BeginPaint except in response to a WM_PAINT message."
Replace BeginPaint + EndPaint by GetDC + ReleaseDC in any other place then WM_PAINT.
At WM_CHAR you print to newbuf but TextOut(buf)
Thanks. I didn't really need it printed at that exact spot, so I
just changed it to stop printing. Am I expecting to get a
fresh WM_PAINT message after moving the window or
pressing a key?
Because currently I'm getting PPP 1 1 ...
which means that I'm just getting a single position changed, and
I'm not getting any keystrokes at all.
Unless I'm only ever receiving a single WM_PAINT message,
which would explain why I don't see any more action.
Thanks. Paul.
/*********************************************************************/
/* */
/* This Program Written by Paul Edwards. */
/* Released to the Public Domain */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* simpwin - the simplest windows program (roughly speaking) */
/* */
/*********************************************************************/
#include <stdio.h>
#include <windows.h>
LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam);
int WINAPI WinMain(IN HINSTANCE inst,
IN HINSTANCE previnst,
IN LPSTR cmd,
IN int cmdshow)
{
WNDCLASS wndClass = { 0, (WNDPROC)simpwin, 0, 0, 0, NULL, NULL,
(HBRUSH)(COLOR_WINDOW+1), "simpwin", "simpwin" };
HWND hwnd;
MSG msg;
(void)previnst;
(void)cmd;
wndClass.hInstance = inst;
RegisterClass(&wndClass);
hwnd = CreateWindow("simpwin", "Simple Windows",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, inst, NULL );
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam)
{
int calldefault = 1;
LONG ret = 0;
static int cnt = 0;
static char newbuf[80];
switch (msg)
{
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, newbuf, strlen(newbuf));
EndPaint(hwnd, &ps);
break;
}
PostQuitMessage(0);
calldefault = 0;
break;
break;
lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
break;
ret = 0;
calldefault = 0;
break;
/* not sure how to actually erase the background - print spaces? */
ret = 1;
calldefault = 0;
break;
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
static int loccnt = 0;
loccnt++;
cnt++;
sprintf(newbuf, "PPP %d %d %d %X %X\n",
loccnt, cnt, (int)msg, (int)wparam, (int)lparam);
#if 0
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
#endif
break;
}
/* lparam is WINDOWPOS and may have useful information */
ret = 0;
calldefault = 0;
break;
/* low 16 bits of lparam are width - in pixels it seems */
/* high 16 bits are height */
/* unclear why this message is being received in the first
place when the documentation says if I handle WINDOWPOSCHANGED
then these messages are not generated. Maybe what they mean
is that the WM_SIZE will just be a once-off message */
ret = 0;
calldefault = 0;
break;
/* low 16 bits of lparam are x-pos (start). high 16 bits are
y-pos - same consideration as WM_SIZE */
ret = 0;
calldefault = 0;
break;
/* MINMAXINFO in lparam may be useful or need to be set */
ret = 0;
calldefault = 0;
break;
/* if 0, this may have useful information in RECT */
if (wparam == 0)
{
ret = 0;
/* if we don't call the default, we don't get a window! */
calldefault = 1;
}
else
{
cnt += 50000; /* detect if we're getting true */
}
break;
/* lparam is CREATESTRUCT which may have useful information */
ret = 1;
calldefault = 0;
break;
/* lparam is CREATESTRUCT which may have useful information */
ret = 0;
calldefault = 0;
break;
{
char buf[80] = "DUMMY";
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
cnt++;
sprintf(newbuf, "ZZZ %d %X %X\n", (int)msg, (int)wparam, (int)lparam);
/* hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps); */
break;
}
}
if (calldefault)
{
ret = DefWindowProc(hwnd, msg, wparam, lparam);
}
return (ret);
}
WM_PAINT is sent when the computer thinks that what is actually on the screen needs to be updated. So you don't normally get one just because you have decided to change the content of the window. If you want what is actually on the screen to reflect what you now think ought to be there, the easiest way is to use the command InvalidateRect which will cause an WM_PAINT to be sent.
Paul Edwards
2023-07-21 15:26:29 UTC
Permalink
Post by Paul N
WM_PAINT is sent when the computer thinks that what is
actually on the screen needs to be updated. So you don't
normally get one just because you have decided to change
the content of the window. If you want what is actually on
the screen to reflect what you now think ought to be there,
the easiest way is to use the command InvalidateRect which
will cause an WM_PAINT to be sent.
Thanks! That literally brought a smile to my face when I
started seeing activity, and I could indeed see the ASCII
character codes come through when I press keys.

That should be the vast bulk of what I need (at least as
far as Windows graphics code, anyway).

BFN. Paul.




/*********************************************************************/
/* */
/* This Program Written by Paul Edwards. */
/* Released to the Public Domain */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* simpwin - the simplest windows program (roughly speaking) */
/* */
/*********************************************************************/

#include <stdio.h>

#include <windows.h>

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam);

int WINAPI WinMain(IN HINSTANCE inst,
IN HINSTANCE previnst,
IN LPSTR cmd,
IN int cmdshow)
{
WNDCLASS wndClass = { 0, (WNDPROC)simpwin, 0, 0, 0, NULL, NULL,
(HBRUSH)(COLOR_WINDOW+1), "simpwin", "simpwin" };
HWND hwnd;
MSG msg;

(void)previnst;
(void)cmd;
wndClass.hInstance = inst;
RegisterClass(&wndClass);
hwnd = CreateWindow("simpwin", "Simple Windows",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, inst, NULL );
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam)
{
int calldefault = 1;
LONG ret = 0;
static int cnt = 0;
static char newbuf[80];

switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, newbuf, strlen(newbuf));
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
calldefault = 0;
break;

case WM_NCPAINT:
case WM_GETICON:
case WM_WINDOWPOSCHANGING:
case WM_ACTIVATEAPP:
case WM_NCACTIVATE:
case WM_ACTIVATE:
case WM_IME_NOTIFY:
case WM_SHOWWINDOW:
break;

case WM_IME_SETCONTEXT:
lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
break;

case WM_SETFOCUS:
ret = 0;
calldefault = 0;
break;

case WM_ERASEBKGND:
/* not sure how to actually erase the background - print spaces? */
ret = 1;
calldefault = 0;
break;

case WM_WINDOWPOSCHANGED:
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
static int loccnt = 0;

loccnt++;
cnt++;
sprintf(newbuf, "PPP %d %d %d %X %X\n",
loccnt, cnt, (int)msg, (int)wparam, (int)lparam);
InvalidateRect(hwnd, NULL, TRUE);
#if 0
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
#endif
break;
}
/* lparam is WINDOWPOS and may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_SIZE:
/* low 16 bits of lparam are width - in pixels it seems */
/* high 16 bits are height */
/* unclear why this message is being received in the first
place when the documentation says if I handle WINDOWPOSCHANGED
then these messages are not generated. Maybe what they mean
is that the WM_SIZE will just be a once-off message */
ret = 0;
calldefault = 0;
break;

case WM_MOVE:
/* low 16 bits of lparam are x-pos (start). high 16 bits are
y-pos - same consideration as WM_SIZE */
ret = 0;
calldefault = 0;
break;

case WM_GETMINMAXINFO:
/* MINMAXINFO in lparam may be useful or need to be set */
ret = 0;
calldefault = 0;
break;

case WM_NCCALCSIZE:
/* if 0, this may have useful information in RECT */
if (wparam == 0)
{
ret = 0;
/* if we don't call the default, we don't get a window! */
calldefault = 1;
}
else
{
cnt += 50000; /* detect if we're getting true */
}
break;

case WM_NCCREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 1;
calldefault = 0;
break;

case WM_CREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_KEYDOWN:
case WM_CHAR:
{
char buf[80] = "DUMMY";
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

cnt++;
sprintf(newbuf, "ZZZ %d %X %X\n", (int)msg, (int)wparam, (int)lparam);
InvalidateRect(hwnd, NULL, TRUE);
/* hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps); */
break;
}
/* we're still getting some of these, but we no longer care */
default:
break;
}
if (calldefault)
{
ret = DefWindowProc(hwnd, msg, wparam, lparam);
}
return (ret);
}
Paul Edwards
2023-07-21 15:44:40 UTC
Permalink
Post by Paul Edwards
That should be the vast bulk of what I need (at least as
far as Windows graphics code, anyway).
I checked on win32s under Windows for Workgroups 3.11.

Although my program (compiled with Open Watcom 1.6)
worked, the window was transparent.

Under Windows 10 I instead get a clean window with a
clean white background.

It may be related to the fact that Watcom says it is creating
a console mode application, when it is actually graphics.
Not sure what the wcl386 option is to set that.

BFN. Paul.
Paul Edwards
2023-07-21 21:41:56 UTC
Permalink
Post by Paul Edwards
I checked on win32s under Windows for Workgroups 3.11.
Although my program (compiled with Open Watcom 1.6)
worked, the window was transparent.
The problem was that I still had my "debug" code left when
I was trying to figure out which message I needed to do
something with.

I commented out the obvious one, and the default window
proc did the trick, so the background is fixed now.

Thanks. Paul.



/*********************************************************************/
/* */
/* This Program Written by Paul Edwards. */
/* Released to the Public Domain */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* simpwin - the simplest windows program (roughly speaking) */
/* */
/*********************************************************************/

#include <stdio.h>

#include <windows.h>

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam);

int WINAPI WinMain(IN HINSTANCE inst,
IN HINSTANCE previnst,
IN LPSTR cmd,
IN int cmdshow)
{
WNDCLASS wndClass = { 0, (WNDPROC)simpwin, 0, 0, 0, NULL, NULL,
(HBRUSH)(COLOR_WINDOW+1), "simpwin", "simpwin" };
HWND hwnd;
MSG msg;

(void)previnst;
(void)cmd;
wndClass.hInstance = inst;
RegisterClass(&wndClass);
hwnd = CreateWindow("simpwin", "Simple Windows",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, inst, NULL );
ShowWindow(hwnd, cmdshow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

LONG FAR PASCAL simpwin(HWND hwnd, WORD msg, WORD wparam, LONG lparam)
{
int calldefault = 1;
LONG ret = 0;
static int cnt = 0;
static char newbuf[80];

switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, newbuf, strlen(newbuf));
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
calldefault = 0;
break;

case WM_NCPAINT:
case WM_GETICON:
case WM_WINDOWPOSCHANGING:
case WM_ACTIVATEAPP:
case WM_NCACTIVATE:
case WM_ACTIVATE:
case WM_IME_NOTIFY:
case WM_SHOWWINDOW:
break;

case WM_IME_SETCONTEXT:
lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
break;

case WM_SETFOCUS:
ret = 0;
calldefault = 0;
break;

#if 0
case WM_ERASEBKGND:
/* not sure how to actually erase the background - print spaces? */
ret = 1;
calldefault = 0;
break;
#endif

case WM_WINDOWPOSCHANGED:
{
char buf[80];
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
static int loccnt = 0;

loccnt++;
cnt++;
sprintf(newbuf, "PPP %d %d %d %X %X\n",
loccnt, cnt, (int)msg, (int)wparam, (int)lparam);
InvalidateRect(hwnd, NULL, TRUE);
#if 0
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
/* TextOut(hdc, 0, 0, newbuf, strlen(newbuf)); */
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps);
#endif
break;
}
/* lparam is WINDOWPOS and may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_SIZE:
/* low 16 bits of lparam are width - in pixels it seems */
/* high 16 bits are height */
/* unclear why this message is being received in the first
place when the documentation says if I handle WINDOWPOSCHANGED
then these messages are not generated. Maybe what they mean
is that the WM_SIZE will just be a once-off message */
ret = 0;
calldefault = 0;
break;

case WM_MOVE:
/* low 16 bits of lparam are x-pos (start). high 16 bits are
y-pos - same consideration as WM_SIZE */
ret = 0;
calldefault = 0;
break;

case WM_GETMINMAXINFO:
/* MINMAXINFO in lparam may be useful or need to be set */
ret = 0;
calldefault = 0;
break;

case WM_NCCALCSIZE:
/* if 0, this may have useful information in RECT */
if (wparam == 0)
{
ret = 0;
/* if we don't call the default, we don't get a window! */
calldefault = 1;
}
else
{
cnt += 50000; /* detect if we're getting true */
}
break;

case WM_NCCREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 1;
calldefault = 0;
break;

case WM_CREATE:
/* lparam is CREATESTRUCT which may have useful information */
ret = 0;
calldefault = 0;
break;

case WM_KEYDOWN:
case WM_CHAR:
{
char buf[80] = "DUMMY";
PAINTSTRUCT ps;
HDC hdc;
RECT rect;

cnt++;
sprintf(newbuf, "ZZZ %d %X %X\n", (int)msg, (int)wparam, (int)lparam);
InvalidateRect(hwnd, NULL, TRUE);
/* hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, buf, strlen(buf));
EndPaint(hwnd, &ps); */
break;
}
/* we're still getting some of these, but we no longer care */
default:
break;
}
if (calldefault)
{
ret = DefWindowProc(hwnd, msg, wparam, lparam);
}
return (ret);
}

Loading...