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.
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.
On Wednesday, July 19, 2023 at 6:07:59 PM UTC+8, JJ wrote:
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);
}
On Friday, July 21, 2023 at 3:40:56 PM UTC+8, Uwe Sieber wrote:
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)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);
}
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)
That should be the vast bulk of what I need (at least as
far as Windows graphics code, anyway).
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.
I checked on win32s under Windows for Workgroups 3.11.
Although my program (compiled with Open Watcom 1.6)
worked, the window was transparent.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 379 |
Nodes: | 16 (2 / 14) |
Uptime: | 42:05:13 |
Calls: | 8,141 |
Calls today: | 4 |
Files: | 13,085 |
Messages: | 5,857,792 |