Paul Edwards
2023-07-19 04:32:43 UTC
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);
}
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);
}