最近我在学习Windows窗口编程。之前使用easyx图形库编写了一个贪吃蛇小程序,但是easyx图形库只能用在vs上,且不支持在纯C语言中使用,而且之前尝试在32位系统上编译失败报错了,所以想要尝试弄懂easyx图形库的原理,自己使用纯C语言编写一个简易的图形库。
如上图所示,如果在一个黑色背景的窗口中绘制一个白色的矩形,使用easyx可以很简单的做到:
#include "graphics.h"
int main() {
initgraph(800, 600);
setlinecolor(WHITE);
setfillcolor(WHITE);
fillrectangle(50, 50, 100, 100);
system("pause");
}
但是如果不使用easyx图形库来还原这个效果,我想到的方法是创建一个子窗口,代码如下:
#include <windows.h>
LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
WNDCLASS wc;
HWND hwndParent, hwndChild;
MSG msg;
// 注册父窗口类
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = ParentWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("ParentWndClass");
RegisterClass(&wc);
// 注册子窗口类
wc.lpfnWndProc = ChildWndProc;
wc.lpszClassName = TEXT("ChildWndClass");
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
RegisterClass(&wc);
// 创建父窗口
hwndParent = CreateWindow(TEXT("ParentWndClass"),
TEXT("Parent Window"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
300,
300,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwndParent, iCmdShow);
UpdateWindow(hwndParent);
// 消息循环
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
// 创建子窗口
CreateWindow(TEXT("ChildWndClass"),
TEXT("Child Window"),
WS_CHILD | WS_VISIBLE,
10,
10,
50,
50,
hwnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
break;
case WM_SIZE:
// 调整子窗口的大小和位置
MoveWindow(GetDlgItem(hwnd, 1),
10,
10,
LOWORD(lParam) - 100,
HIWORD(lParam) - 100,
TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
运行结果: