Решение
Благодаря ответам @RemyLebeau @IInspectable @Raymond Chen и @BarmakShemirani, вот решение.
Теперь я успешно обновляю окно в соответствии с буфером, полученным с помощьюФункция CreateDIBSection()
, без прохождения через событие WM_PAINT
.
Я использую функцию UpdateLayeredWindow()
для обновления пикселей окна.
Вот код решения:
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, таких как я: Живопись и рисование .
Надо было прочитать это перед допросом ...