数组缓冲区和 winapi
Array buffer and winapi
上下文:
- Windows 10
- WinAPI 和 C 代码
问题:
我有一个表示为 uint8_t buffer[width * height * PIXEL_SIZE]
的像素缓冲区,我想定期修改内容数据并将缓冲区重新绘制到 window。
我遇到了 winapi 的两个问题,其中一个我迷路了:
- 如何将像素缓冲区打印到 window 上?
- 我如何稍后在女士修改缓冲区的代码中重绘?
我进行了很多研究,但没有任何代码片段能够成功帮助我解决我的问题。
这里是一个不工作的代码示例,以展示我想用我拥有的代码元素实现的目标:
new_image.c
// Global variables
static HDC hdc;
static HDC context_hdc;
static HBITMAP hDib;
static HGDIOBJ obj;
static void set_bmi_object(BITMAPINFO *bmi, int width, int height) {
memset(bmi, 0, sizeof(BITMAPINFO));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi->bmiHeader.biWidth = width;
bmi->bmiHeader.biHeight = -height;
bmi->bmiHeader.biPlanes = 1;
bmi->bmiHeader.biBitCount = 32;
bmi->bmiHeader.biCompression = BI_RGB;
}
// Allocate a new image buffer
void *new_image(HWND hwnd, int width, int height)
{
BITMAPINFO bmi;
BYTE *bits = NULL;
void *buffer;
if (NULL == (buffer = (char*)malloc(width * height * PIXEL_SIZE)))
return (NULL);
set_bmi_object(&bmi, width, height);
hdc = GetDC(hwnd);
hDib = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)(&bits),
NULL, 0);
if (hDib != NULL) {
context_hdc = CreateCompatibleDC(hdc);
if (context_hdc == NULL) {
DeleteObject(hDib);
} else {
obj = SelectObject(context_hdc, hDib);
CopyMemory(bits, buffer, width * height * sizeof(PIXEL_SIZE));
}
}
return (newimg);
}
// Print the buffer of pixel on the window
void put_image_to_window(HWND hwnd, void *buffer, int x, int y)
{
(void)hwnd;
// Void buffer because i should use directly HDCcontext_hdc linked to HGDIOBJ obj ?
(void)buffer;
BitBlt(hdc, // destination
x,
y,
500, // width of the region
500, // height
context_hdc, // source
0, // x
0, // y
SRCCOPY);
UpdateWindow(hwnd);
}
main.c
static const char g_szClassName[] = "myWindowClass";
static void paint(HWND hwnd) {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
paint(hwnd);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main(void) {
MSG Msg;
HINSTANCE hInstance;
HWND hwnd;
STARTUPINFOA startup_info;
WNDCLASSEX wc;
HWND hwnd;
GetStartupInfoA(&startup_info);
hInstance = GetModuleHandle(NULL);
memset(&wc, 0, sizeof(wc));
// Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
// ... etc
wc.lpszClassName = TEXT(g_szClassName);
if (!RegisterClassEx(&wc)) {
return (-1);
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Title,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
NULL,
NULL,
hInstance,
NULL);
if (hwnd == NULL) {
return (-1);
}
ShowWindow(hwnd, startup_info.wShowWindow);
image = new_image(hwnd, 500, 500);
put_image_to_window(hwnd, image, 0, 0);
UpdateWindow(hwnd);
// The Message Loop
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (Msg.wParam);
}
这里是 new_image.c
一个函数 new_image
returns 像素缓冲区上的指针,
函数 put_image_to_window
显示 window 上的像素缓冲区。
CopyMemory(bits, buffer, width * height * sizeof(PIXEL_SIZE));
sizeof
运算符的用法不正确。位图可以是 1、4、8、16、24 或 32 位。 32 位位图每个像素有 4 个字节。如果 PIXEL_SIZE
被声明为 int32_t
那么巧合的是你得到了正确的大小。否则使用正确的公式计算尺寸。
此外,将 buffer
复制到 bits
也没有意义。可以直接使用bits
。只要你没有销毁hDib
,bits
就会有效
hdc = GetDC(hwnd);
对 GetDC
的调用应以 ReleaseDC
结束,否则可能会导致资源泄漏。 Windows 设备上下文并不意味着存储为常量。将其用作临时值。
您还已将 HDC context_hdc
声明为全局变量。这对于内存设备上下文是可以的,但不是必需的。您唯一需要的全局变量是 hDib
,也许 buffer
#include <windows.h>
static const char g_szClassName[] = "myWindowClass";
static HBITMAP hDib;
BYTE *new_image(int width, int height)
{
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
BYTE *buffer;
HDC hdc = GetDC(HWND_DESKTOP);
hDib = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)(&buffer), NULL, 0);
ReleaseDC(HWND_DESKTOP, hdc);
return buffer;
}
static void paint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if(hDib)
{
HDC context_hdc = CreateCompatibleDC(hdc);
HGDIOBJ old_obj = SelectObject(context_hdc, hDib);
BitBlt(hdc, 0, 0, 500, 500, context_hdc, 0, 0, SRCCOPY);
SelectObject(context_hdc, old_obj);
DeleteDC(context_hdc);
}
EndPaint(hwnd, &ps);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
paint(hwnd);
break;
case WM_MOUSEMOVE:
{
if(hDib)
{
//draw something
HDC context_hdc = CreateCompatibleDC(NULL);
HGDIOBJ old_obj = SelectObject(context_hdc, hDib);
SetDCBrushColor(context_hdc, RGB(255, 0, 0));
int x = (int)(short)LOWORD(lParam);
int y = (int)(short)HIWORD(lParam);
RECT rc = { x, y, x + 10, y + 10};
FillRect(context_hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));
SelectObject(context_hdc, old_obj);
DeleteDC(context_hdc);
InvalidateRect(hwnd, NULL, FALSE);
}
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main(void) {
MSG Msg;
HINSTANCE hInstance;
HWND hwnd;
STARTUPINFOA startup_info;
WNDCLASSEX wc;
GetStartupInfoA(&startup_info);
hInstance = GetModuleHandle(NULL);
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = TEXT(g_szClassName);
RegisterClassEx(&wc);
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName, "Title",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 500, NULL, NULL, hInstance, NULL);
BYTE* image = new_image(500, 500);
ShowWindow(hwnd, SW_SHOW);//startup_info.wShowWindow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
if (hDib)
DeleteObject(hDib);
return (Msg.wParam);
}
解决方案
感谢@RemyLebeau @IInspectable @Raymond Chen 和@BarmakShemirani 的回答,这里有一个解决方案。
现在我根据 CreateDIBSection()
函数获得的缓冲区成功更新了 window,没有通过 WM_PAINT
事件。
我使用 UpdateLayeredWindow()
函数来更新 window 的像素。
这里是解决代码:
new_image.c
// global variables
static HBITMAP hDib;
static void set_bmi_object(BITMAPINFO *bmi, int width, int height) {
memset(bmi, 0, sizeof(BITMAPINFO));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi->bmiHeader.biWidth = width;
bmi->bmiHeader.biHeight = -height;
bmi->bmiHeader.biPlanes = 1;
bmi->bmiHeader.biBitCount = 32;
bmi->bmiHeader.biCompression = BI_RGB;
}
// Allocate a new image buffer
void *new_image(HWND hwnd, int width, int height)
{
BITMAPINFO bmi;
void *buffer;
HDC hdc;
set_bmi_object(&bmi, width, height);
hdc = GetDC(hwnd);
hDib = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)(&buffer), NULL, 0);
ReleaseDC(instance->win_list->hwnd, hdc);
return (buffer);
}
// Print the buffer of pixel on the window
void put_image_to_window(HWND hwnd, void *buffer, int x, int y)
{
HDC hdc;
HDC context_hdc;
HGDIOBJ old_obj;
hdc = GetDC(hwnd);
context_hdc = CreateCompatibleDC(hdc);
old_obj = SelectObject(context_hdc, hDib);
BitBlt(hdc,
0,
0,
500,
500,
context_hdc,
0,
0,
SRCCOPY);
SelectObject(context_hdc, old_obj);
DeleteDC(context_hdc);
ReleaseDC(hwnd, hdc);
// Call UpdateLayeredWindow
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 128;// half transparent
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptLocation = {x, y};
SIZE szWnd = {500, 500};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(hwnd, hdc, &ptLocation, &szWnd, context_hdc, &ptSrc, 0, &blend, ULW_ALPHA);
}
main.c
static const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main(void) {
MSG Msg;
HINSTANCE hInstance;
HWND hwnd;
STARTUPINFOA startup_info;
WNDCLASSEX wc;
HWND hwnd;
GetStartupInfoA(&startup_info);
hInstance = GetModuleHandle(NULL);
memset(&wc, 0, sizeof(wc));
// Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
// ... etc
wc.lpszClassName = TEXT(g_szClassName);
if (!RegisterClassEx(&wc)) {
return (-1);
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Title,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
NULL,
NULL,
hInstance,
NULL);
if (hwnd == NULL) {
return (-1);
}
ShowWindow(hwnd, startup_info.wShowWindow);
image = new_image(hwnd, 500, 500);
put_image_to_window(hwnd, image, 0, 0);
// The Message Loop
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (Msg.wParam);
}
这是@IInspectable 为像我这样的 WinAPI 初学者提供的必读内容:Painting and Drawing。
应该在提问前阅读此内容...
上下文:
- Windows 10
- WinAPI 和 C 代码
问题:
我有一个表示为 uint8_t buffer[width * height * PIXEL_SIZE]
的像素缓冲区,我想定期修改内容数据并将缓冲区重新绘制到 window。
我遇到了 winapi 的两个问题,其中一个我迷路了:
- 如何将像素缓冲区打印到 window 上?
- 我如何稍后在女士修改缓冲区的代码中重绘?
我进行了很多研究,但没有任何代码片段能够成功帮助我解决我的问题。
这里是一个不工作的代码示例,以展示我想用我拥有的代码元素实现的目标:
new_image.c
// Global variables
static HDC hdc;
static HDC context_hdc;
static HBITMAP hDib;
static HGDIOBJ obj;
static void set_bmi_object(BITMAPINFO *bmi, int width, int height) {
memset(bmi, 0, sizeof(BITMAPINFO));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi->bmiHeader.biWidth = width;
bmi->bmiHeader.biHeight = -height;
bmi->bmiHeader.biPlanes = 1;
bmi->bmiHeader.biBitCount = 32;
bmi->bmiHeader.biCompression = BI_RGB;
}
// Allocate a new image buffer
void *new_image(HWND hwnd, int width, int height)
{
BITMAPINFO bmi;
BYTE *bits = NULL;
void *buffer;
if (NULL == (buffer = (char*)malloc(width * height * PIXEL_SIZE)))
return (NULL);
set_bmi_object(&bmi, width, height);
hdc = GetDC(hwnd);
hDib = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)(&bits),
NULL, 0);
if (hDib != NULL) {
context_hdc = CreateCompatibleDC(hdc);
if (context_hdc == NULL) {
DeleteObject(hDib);
} else {
obj = SelectObject(context_hdc, hDib);
CopyMemory(bits, buffer, width * height * sizeof(PIXEL_SIZE));
}
}
return (newimg);
}
// Print the buffer of pixel on the window
void put_image_to_window(HWND hwnd, void *buffer, int x, int y)
{
(void)hwnd;
// Void buffer because i should use directly HDCcontext_hdc linked to HGDIOBJ obj ?
(void)buffer;
BitBlt(hdc, // destination
x,
y,
500, // width of the region
500, // height
context_hdc, // source
0, // x
0, // y
SRCCOPY);
UpdateWindow(hwnd);
}
main.c
static const char g_szClassName[] = "myWindowClass";
static void paint(HWND hwnd) {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
paint(hwnd);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main(void) {
MSG Msg;
HINSTANCE hInstance;
HWND hwnd;
STARTUPINFOA startup_info;
WNDCLASSEX wc;
HWND hwnd;
GetStartupInfoA(&startup_info);
hInstance = GetModuleHandle(NULL);
memset(&wc, 0, sizeof(wc));
// Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
// ... etc
wc.lpszClassName = TEXT(g_szClassName);
if (!RegisterClassEx(&wc)) {
return (-1);
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Title,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
NULL,
NULL,
hInstance,
NULL);
if (hwnd == NULL) {
return (-1);
}
ShowWindow(hwnd, startup_info.wShowWindow);
image = new_image(hwnd, 500, 500);
put_image_to_window(hwnd, image, 0, 0);
UpdateWindow(hwnd);
// The Message Loop
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (Msg.wParam);
}
这里是 new_image.c
一个函数
new_image
returns 像素缓冲区上的指针,函数
put_image_to_window
显示 window 上的像素缓冲区。
CopyMemory(bits, buffer, width * height * sizeof(PIXEL_SIZE));
sizeof
运算符的用法不正确。位图可以是 1、4、8、16、24 或 32 位。 32 位位图每个像素有 4 个字节。如果 PIXEL_SIZE
被声明为 int32_t
那么巧合的是你得到了正确的大小。否则使用正确的公式计算尺寸。
此外,将 buffer
复制到 bits
也没有意义。可以直接使用bits
。只要你没有销毁hDib
bits
就会有效
hdc = GetDC(hwnd);
对 GetDC
的调用应以 ReleaseDC
结束,否则可能会导致资源泄漏。 Windows 设备上下文并不意味着存储为常量。将其用作临时值。
您还已将 HDC context_hdc
声明为全局变量。这对于内存设备上下文是可以的,但不是必需的。您唯一需要的全局变量是 hDib
,也许 buffer
#include <windows.h>
static const char g_szClassName[] = "myWindowClass";
static HBITMAP hDib;
BYTE *new_image(int width, int height)
{
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
BYTE *buffer;
HDC hdc = GetDC(HWND_DESKTOP);
hDib = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)(&buffer), NULL, 0);
ReleaseDC(HWND_DESKTOP, hdc);
return buffer;
}
static void paint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if(hDib)
{
HDC context_hdc = CreateCompatibleDC(hdc);
HGDIOBJ old_obj = SelectObject(context_hdc, hDib);
BitBlt(hdc, 0, 0, 500, 500, context_hdc, 0, 0, SRCCOPY);
SelectObject(context_hdc, old_obj);
DeleteDC(context_hdc);
}
EndPaint(hwnd, &ps);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
paint(hwnd);
break;
case WM_MOUSEMOVE:
{
if(hDib)
{
//draw something
HDC context_hdc = CreateCompatibleDC(NULL);
HGDIOBJ old_obj = SelectObject(context_hdc, hDib);
SetDCBrushColor(context_hdc, RGB(255, 0, 0));
int x = (int)(short)LOWORD(lParam);
int y = (int)(short)HIWORD(lParam);
RECT rc = { x, y, x + 10, y + 10};
FillRect(context_hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));
SelectObject(context_hdc, old_obj);
DeleteDC(context_hdc);
InvalidateRect(hwnd, NULL, FALSE);
}
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main(void) {
MSG Msg;
HINSTANCE hInstance;
HWND hwnd;
STARTUPINFOA startup_info;
WNDCLASSEX wc;
GetStartupInfoA(&startup_info);
hInstance = GetModuleHandle(NULL);
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = TEXT(g_szClassName);
RegisterClassEx(&wc);
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName, "Title",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 500, NULL, NULL, hInstance, NULL);
BYTE* image = new_image(500, 500);
ShowWindow(hwnd, SW_SHOW);//startup_info.wShowWindow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
if (hDib)
DeleteObject(hDib);
return (Msg.wParam);
}
解决方案
感谢@RemyLebeau @IInspectable @Raymond Chen 和@BarmakShemirani 的回答,这里有一个解决方案。
现在我根据 CreateDIBSection()
函数获得的缓冲区成功更新了 window,没有通过 WM_PAINT
事件。
我使用 UpdateLayeredWindow()
函数来更新 window 的像素。
这里是解决代码:
new_image.c
// global variables
static HBITMAP hDib;
static void set_bmi_object(BITMAPINFO *bmi, int width, int height) {
memset(bmi, 0, sizeof(BITMAPINFO));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi->bmiHeader.biWidth = width;
bmi->bmiHeader.biHeight = -height;
bmi->bmiHeader.biPlanes = 1;
bmi->bmiHeader.biBitCount = 32;
bmi->bmiHeader.biCompression = BI_RGB;
}
// Allocate a new image buffer
void *new_image(HWND hwnd, int width, int height)
{
BITMAPINFO bmi;
void *buffer;
HDC hdc;
set_bmi_object(&bmi, width, height);
hdc = GetDC(hwnd);
hDib = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)(&buffer), NULL, 0);
ReleaseDC(instance->win_list->hwnd, hdc);
return (buffer);
}
// Print the buffer of pixel on the window
void put_image_to_window(HWND hwnd, void *buffer, int x, int y)
{
HDC hdc;
HDC context_hdc;
HGDIOBJ old_obj;
hdc = GetDC(hwnd);
context_hdc = CreateCompatibleDC(hdc);
old_obj = SelectObject(context_hdc, hDib);
BitBlt(hdc,
0,
0,
500,
500,
context_hdc,
0,
0,
SRCCOPY);
SelectObject(context_hdc, old_obj);
DeleteDC(context_hdc);
ReleaseDC(hwnd, hdc);
// Call UpdateLayeredWindow
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 128;// half transparent
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptLocation = {x, y};
SIZE szWnd = {500, 500};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(hwnd, hdc, &ptLocation, &szWnd, context_hdc, &ptSrc, 0, &blend, ULW_ALPHA);
}
main.c
static const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main(void) {
MSG Msg;
HINSTANCE hInstance;
HWND hwnd;
STARTUPINFOA startup_info;
WNDCLASSEX wc;
HWND hwnd;
GetStartupInfoA(&startup_info);
hInstance = GetModuleHandle(NULL);
memset(&wc, 0, sizeof(wc));
// Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
// ... etc
wc.lpszClassName = TEXT(g_szClassName);
if (!RegisterClassEx(&wc)) {
return (-1);
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Title,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
NULL,
NULL,
hInstance,
NULL);
if (hwnd == NULL) {
return (-1);
}
ShowWindow(hwnd, startup_info.wShowWindow);
image = new_image(hwnd, 500, 500);
put_image_to_window(hwnd, image, 0, 0);
// The Message Loop
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (Msg.wParam);
}
这是@IInspectable 为像我这样的 WinAPI 初学者提供的必读内容:Painting and Drawing。
应该在提问前阅读此内容...