离屏绘图GDI +

Mik*_*łaj 5 c++ winapi

我有一个问题 - 我需要绘制两个png文件,一个在另一个上.当我按常规方式进行时,会出现"闪烁"效果(第一张图片在很短的时间内透过第二张图片).我使用GDI +库,我的WM_PAINT处理如下所示:

case WM_PAINT:
{
    PAINTSTRUCT ps; 
    HDC hdc = BeginPaint( hwnd, & ps );
    displayImage(firstImage, hwnd);
    displayImage(secondImage, hwnd);
    EndPaint( hwnd, & ps );
    break;
}
Run Code Online (Sandbox Code Playgroud)

displayImage函数:

void displayImage(HBITMAP mBmp, HWND mHwnd)
{
    RECT myRect;
    BITMAP bm;
    HDC screenDC, memDC;
    HBITMAP oldBmp;
    BLENDFUNCTION bf;

    GetObject(mBmp, sizeof(bm), &bm);

    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 0xff;

    bf.AlphaFormat = AC_SRC_ALPHA;

    screenDC = GetDC(mHwnd);
    GetClientRect(mHwnd, &myRect);

    if (mBmp == NULL)
        FillRect(screenDC, &myRect, WHITE_BRUSH);

    else
    {
        memDC = CreateCompatibleDC(screenDC);
        oldBmp = (HBITMAP)SelectObject(memDC, mBmp);
        AlphaBlend (screenDC, 0, 0, myRect.right,myRect.bottom, memDC, 0, 0, bm.bmWidth,bm.bmHeight, bf);
        SelectObject(memDC, oldBmp);
        DeleteDC(memDC);
        ReleaseDC(mHwnd, screenDC);
    }
}
Run Code Online (Sandbox Code Playgroud)

将文件加载到变量:

HBITMAP mLoadImg(WCHAR *szFilename)
{
   HBITMAP result=NULL;

   Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(szFilename,false);
   bitmap->GetHBITMAP(NULL, &result);
   delete bitmap;
   return result;
}


firstImage = mLoadImg(L"data\\img\\screen.png");
secondImage = mLoadImg(L"data\\img\\screen2.png");
Run Code Online (Sandbox Code Playgroud)

我听说我应该做一个离屏绘图.应该怎么样?

Bar*_*ani 6

你不需要所有这些.您可以直接使用GDI +:

static Gdiplus::Image *firstImage;
static Gdiplus::Image *secondImage;

case WM_CREATE: // or WM_INITDIALOG if it's dialog
{
    firstImage = new Gdiplus::Image(L"data\\img\\screen.png");
    secondImage = new Gdiplus::Image(L"data\\img\\screen2.png");
    return 0;
}

case WM_PAINT:
{
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hwnd, &ps);

    Gdiplus::Graphics gr(hdc);
    gr.DrawImage(firstImage, 0, 0);
    gr.DrawImage(secondImage, 0, 0);//<== this will draw transparently

    EndPaint(hwnd, &ps);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,此代码仍然可以连续绘制2个图像,可能会闪烁(就像您的原始代码一样).使用双缓冲,WM_PAINT以便只BltBlt完成一个.只需更改为:

if (msg == WM_PAINT)
{
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hwnd, &ps);

    RECT rc;
    GetClientRect(hwnd, &rc);
    HDC memdc = CreateCompatibleDC(hdc);
    HBITMAP hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
    HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);

    FillRect(memdc, &rc, WHITE_BRUSH);
    Gdiplus::Graphics gr(memdc);
    gr.DrawImage(firstImage, 0, 0);
    gr.DrawImage(secondImage, 0, 0);

    BitBlt(hdc, 0, 0, rc.right, rc.bottom, memdc, 0, 0, SRCCOPY);

    SelectObject(memdc, oldbmp);
    DeleteObject(hbitmap);
    DeleteDC(memdc);

    EndPaint(hwnd, &ps);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

至于原始代码:

void displayImage(HBITMAP mBmp, HWND mHwnd)
{
HDC hdc = GetDC(mHwnd);
...
}
Run Code Online (Sandbox Code Playgroud)

您应该更改函数声明,void displayImage(HBITMAP mBmp, HWND mHwnd, HDC hdc)然后您可以hdc直接传递WM_PAINT