流浪汉17 2023-05-04 16:57 采纳率: 75%
浏览 85
已结题

怎么给GDI绘制加双缓存防止闪烁

这是GDI绘制源码,怎么加上给他加上双缓存防止闪烁


#include <stdio.h>
#include<Windows.h>
#include<stdlib.h>

LRESULT __stdcall callback(HWND hwnd, UINT usermsg, WPARAM wparam, LPARAM lparam)
{
    switch (usermsg) {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(1);
        break;


    }
    return DefWindowProc(hwnd, usermsg, wparam, lparam);

}



HWND createlaiedwindow(const char wndname[255], RECT rect_layedwindow)//创建一个透明的绘制窗口
{
    WNDCLASSEX Layedwindow = { 0 };
    Layedwindow.cbSize = sizeof WNDCLASSEX;
    Layedwindow.lpfnWndProc = callback;
    Layedwindow.lpszClassName = "w;";
    Layedwindow.style = CS_HREDRAW | CS_VREDRAW;
    Layedwindow.hCursor = LoadCursor(NULL, IDC_ARROW);
    Layedwindow.hbrBackground = ((HBRUSH)RGB(0, 0, 0));
    Layedwindow.hInstance = GetModuleHandle(0);

    RegisterClassEx(&Layedwindow);//注册窗口类

    //利用窗口类创建一个实体窗口
    HWND hwnd_layedwindow = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT, Layedwindow.lpszClassName, wndname,
        WS_POPUP, rect_layedwindow.left, rect_layedwindow.top,
        rect_layedwindow.right - rect_layedwindow.left, rect_layedwindow.bottom - rect_layedwindow.top,
        NULL, NULL, Layedwindow.hInstance, NULL);

    SetLayeredWindowAttributes(hwnd_layedwindow, RGB(0, 0, 0), 0, 1);//设置窗口透名

    ShowWindow(hwnd_layedwindow, SW_SHOW);

    UpdateWindow(hwnd_layedwindow);

    return hwnd_layedwindow;
}
void UpdateLayedWindow(HWND hwnd_layedwindow, HWND hwnd_game)//刷新窗口
{
    RECT rect_layedwindow{};
    GetWindowRect(hwnd_game, &rect_layedwindow);
    SetWindowPos(hwnd_layedwindow, HWND_TOPMOST,
        rect_layedwindow.left, rect_layedwindow.top,
        rect_layedwindow.right - rect_layedwindow.left, rect_layedwindow.bottom - rect_layedwindow.top, SWP_SHOWWINDOW);

    MoveWindow(hwnd_layedwindow, rect_layedwindow.left, rect_layedwindow.top,
        rect_layedwindow.right - rect_layedwindow.left, rect_layedwindow.bottom - rect_layedwindow.top, TRUE);


}

void clear(HWND hwnd_overlay, RECT rect_window)//删除上一贞数据,防满屏绘制
{
    RECT rect = { 0,0,rect_window.right - rect_window.left,rect_window.bottom - rect_window.top };
    HWND hwnd = GetForegroundWindow();
    HDC hdc = GetDC(hwnd_overlay);
    HBRUSH hbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
    SelectObject(hdc, hbrush);
    FillRect(hdc, &rect, hbrush);
    DeleteObject(hbrush);
    ReleaseDC(hwnd_overlay, hdc);


}


namespace gdi
{
    void drawbox(HDC hdc_layedwindow, int x, int y, int boxwidth, int boxheight)
    {
        Rectangle(hdc_layedwindow, x, y, x + boxwidth, y + boxheight);


    }
    void drawline(HDC hdc_layedwindow, int x1, int y1, int x2, int y2)
    {
        MoveToEx(hdc_layedwindow, x1, y1, NULL);
        LineTo(hdc_layedwindow, x2, y2);

    }
    void drawstring(HDC hdc_layedwindow, int x, int y, COLORREF color, const char* text)
    {
        SetTextColor(hdc_layedwindow, color);
        SetBkMode(hdc_layedwindow, RGB(0, 0, 0));
        TextOutA(hdc_layedwindow, x, y, text, strlen(text));

    }
    


}


#include <iostream>
#include "GDI.h"



HWND hwnd = NULL;
HWND hwnd_layedwindow = NULL;
unsigned long processid = NULL;
RECT rect = { 0 };
HDC hdc = NULL;
HPEN hpen = NULL;
HBRUSH hbrush = NULL;

void init(const char wndname[255]);

int main()
{
    MessageBoxA(NULL, "按下确定开始绘制", "tips", MB_ICONERROR);
    init("新建文本文档.txt - 记事本");
    while (true)
    {
        
        for (size_t i = 0; i < 700; i=i+12)
        {
            
            GetWindowRect(hwnd, &rect);
            UpdateLayedWindow(hwnd_layedwindow, hwnd);
            clear(hwnd_layedwindow, rect);
            hdc = GetDC(hwnd_layedwindow);
            hpen = CreatePen(PS_INSIDEFRAME, 1, RGB(255, 0, 0));
            hbrush = (HBRUSH)GetStockObject(DEFAULT_GUI_FONT);
            SelectObject(hdc, hpen);
            SelectObject(hdc, GetStockObject(NULL_BRUSH));
            SelectObject(hdc, hbrush);//选择对象

            gdi::drawstring(hdc, 30+i, 80, RGB(255, 0, 0), "草");
            gdi::drawbox(hdc, 30+(i-5), 70, 20, 30);

            gdi::drawstring(hdc, 30 + i, 150, RGB(255, 0, 0), "草");
            gdi::drawbox(hdc, 30 + (i - 5), 140, 20, 30);
            
            gdi::drawstring(hdc, 30 , 250, RGB(255, 0, 0), "草");
            gdi::drawbox(hdc, 25 , 240, 20, 30);


            DeleteObject(hbrush);
            DeleteObject(hpen);
            ReleaseDC(hwnd_layedwindow, hdc);


        }



    }
    

}



void init(const char wndname[255])//初始化函数
{



    hwnd = FindWindow(NULL, wndname);
    if (!hwnd) {
        MessageBoxA(NULL, "未找到窗口", "tips", MB_ICONERROR);
        PostQuitMessage(0);

    }
    GetWindowThreadProcessId(hwnd, &processid);
    if (processid == NULL) {
        MessageBoxA(NULL, "取Pid失败", "tips", MB_ICONERROR);


    }
    GetWindowRect(hwnd, &rect);
    hwnd_layedwindow = createlaiedwindow(" ", rect);
    if (!hwnd_layedwindow)
    {
        MessageBoxA(NULL, "创建窗口失败", "tips", MB_ICONERROR);

    }


}

  • 写回答

4条回答 默认 最新

  • CF2301_77400554X 2023-05-04 17:21
    关注

    引用chatgpt部分指引作答:
    要使用双缓存,需要在程序中创建两个内存DC,一个用于绘制图像,另一个用于显示。在每个绘制周期中,先绘制到内存DC中,然后再将其复制到显示DC中,从而消除闪烁。

    以下是修改后的代码:

    #include <stdio.h>
    #include<Windows.h>
    #include<stdlib.h>
    
    LRESULT __stdcall callback(HWND hwnd, UINT usermsg, WPARAM wparam, LPARAM lparam)
    {
        switch (usermsg) {
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(1);
            break;
    
    
        }
        return DefWindowProc(hwnd, usermsg, wparam, lparam);
    
    }
    
    HWND createlaiedwindow(const char wndname[255], RECT rect_layedwindow)//创建一个透明的绘制窗口
    {
        WNDCLASSEX Layedwindow = { 0 };
        Layedwindow.cbSize = sizeof WNDCLASSEX;
        Layedwindow.lpfnWndProc = callback;
        Layedwindow.lpszClassName = "w;";
        Layedwindow.style = CS_HREDRAW | CS_VREDRAW;
        Layedwindow.hCursor = LoadCursor(NULL, IDC_ARROW);
        Layedwindow.hbrBackground = ((HBRUSH)RGB(0, 0, 0));
        Layedwindow.hInstance = GetModuleHandle(0);
    
        RegisterClassEx(&Layedwindow);//注册窗口类
    
        //利用窗口类创建一个实体窗口
        HWND hwnd_layedwindow = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT, Layedwindow.lpszClassName, wndname,
            WS_POPUP, rect_layedwindow.left, rect_layedwindow.top,
            rect_layedwindow.right - rect_layedwindow.left, rect_layedwindow.bottom - rect_layedwindow.top,
            NULL, NULL, Layedwindow.hInstance, NULL);
    
        SetLayeredWindowAttributes(hwnd_layedwindow, RGB(0, 0, 0), 0, 1);//设置窗口透名
    
        ShowWindow(hwnd_layedwindow, SW_SHOW);
    
        UpdateWindow(hwnd_layedwindow);
    
        return hwnd_layedwindow;
    }
    
    void UpdateLayedWindow(HWND hwnd_layedwindow, HWND hwnd_game)//刷新窗口
    {
        RECT rect_layedwindow{};
        GetWindowRect(hwnd_game, &rect_layedwindow);
        SetWindowPos(hwnd_layedwindow, HWND_TOPMOST,
            rect_layedwindow.left, rect_layedwindow.top,
            rect_layedwindow.right - rect_layedwindow.left, rect_layedwindow.bottom - rect_layedwindow.top, SWP_SHOWWINDOW);
    
        MoveWindow(hwnd_layedwindow, rect_layedwindow.left, rect_layedwindow.top,
            rect_layedwindow.right - rect_layedwindow.left, rect_layedwindow.bottom - rect_layedwindow.top, TRUE);
    
    
    }
    
    void clear(HDC hdc_overlay, RECT rect_window)//删除上一贞数据,防满屏绘制
    {
        HBRUSH hbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
        SelectObject(hdc_overlay, hbrush);
        FillRect(hdc_overlay, &rect_window, hbrush);
        DeleteObject(hbrush);
    }
    
    namespace gdi
    {
        void drawbox(HDC hdc, int x, int y, int boxwidth, int boxheight)
        {
            Rectangle(hdc, x, y, x + boxwidth,x + boxwidth, y + boxheight);
    }
    void drawtext(HDC hdc, const char* text, int x, int y, int width, int height, UINT format)
    {
        RECT rect = { x, y, x + width, y + height };
        DrawTextA(hdc, text, -1, &rect, format);
    }
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
    HWND hwnd_game = FindWindow(NULL, "MyGame");
    if (!hwnd_game)
    {
    MessageBox(NULL, "Could not find game window!", "Error", MB_OK);
    return 1;
    }
    HWND hwnd_overlay = createlaiedwindow("MyOverlay", RECT{ 0, 0, 800, 600 });
    
    HDC hdc_game = GetDC(hwnd_game);
    HDC hdc_overlay = CreateCompatibleDC(hdc_game);
    HBITMAP hbm_overlay = CreateCompatibleBitmap(hdc_game, 800, 600);
    HGDIOBJ hOld = SelectObject(hdc_overlay, hbm_overlay);
    
    MSG msg{};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        switch (msg.message)
        {
        case WM_QUIT:
            break;
        default:
            clear(hdc_overlay, RECT{ 0, 0, 800, 600 });
    
            //绘制Overlay内容
            gdi::drawbox(hdc_overlay, 100, 100, 50, 50);
            gdi::drawtext(hdc_overlay, "Hello, world!", 200, 200, 100, 20, DT_CENTER | DT_VCENTER);
    
            //将Overlay绘制到屏幕上
            UpdateLayedWindow(hwnd_overlay, hwnd_game);
            BitBlt(hdc_game, 0, 0, 800, 600, hdc_overlay, 0, 0, SRCCOPY);
            break;
        }
    
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    //释放资源
    SelectObject(hdc_overlay, hOld);
    DeleteObject(hbm_overlay);
    DeleteDC(hdc_overlay);
    ReleaseDC(hwnd_game, hdc_game);
    
    return 0;
    }
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 5月12日
  • 已采纳回答 5月4日
  • 赞助了问题酬金15元 5月4日
  • 创建了问题 5月4日

悬赏问题

  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库
  • ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
  • ¥15 请问怎么才能复现这样的图呀