在扩展框架中绘制会产生奇怪的颜色 [英] Drawing in the extended frame gives strange colors

查看:432
本文介绍了在扩展框架中绘制会产生奇怪的颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有这样的扩展框架的窗口:

I have a window with extended frame made like this:

自定义窗口框架使用DWM

但是在扩展框架中绘制的任何东西都有非常奇怪的颜色除了白色,唯一的颜色保持不变),像这样(忽略中心的杂乱内容和右边的凌乱工具栏。

But anything drawn in the extended frame has very strange colors (except for white, the only color that stays the same), like this (ignore the messy content in the center and the messy toolbar at the right.

粉红色矩形( 0xFFC9FF )应该是 0x8000FF 。如果我把DirectX11内容(中心事物)在扩展帧,alpha混合我的FPS计数器搞乱

The pink rectangle (0xFFC9FF) was supposed to be 0x8000FF. If I put the DirectX11 content (the center thing) in the extended frame, alpha blending for my FPS counter gets messed up. If I do the same to the right dialog, the same happens.

那么我该如何正确地做?我已经尝试先绘制内存DC,然后使用 BitBlt 。我使用GDI +(加上 CreateCompatibleDC CreateCompatibleBitmap 和其他函数来处理内存DC)。

So how can I do this correctly? I've already tried to draw first to a memory DC and then use BitBlt. I'm using GDI+ (plus CreateCompatibleDC, CreateCompatibleBitmap and other functions to handle the memory DC).

PS:因为你问,这里是 WndProc

PS: Because you asked, here is WndProc:

LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT ReturnValue;
    if (DwmDefWindowProc(hWnd, uMsg, wParam, lParam, &ReturnValue)) return ReturnValue;

    switch (uMsg)
    {
    case WM_CREATE:
    {
        // ...

        RECT rcClient;
        GetWindowRect(hWnd, &rcClient);

        SetWindowPos(hWnd,
            NULL,
            rcClient.left, rcClient.top,
            rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
            SWP_FRAMECHANGED);

        return 0;
    }
    case WM_ACTIVATE:
    {
        MARGINS Margins;
        Margins.cxLeftWidth = LEFT_BORDER;
        Margins.cxRightWidth = RIGHT_BORDER;
        Margins.cyTopHeight = TOP_BORDER;
        Margins.cyBottomHeight = BOTTOM_BORDER;
        if (DwmExtendFrameIntoClientArea(hWnd, &Margins) != S_OK)
        {
            MessageBox(hWnd, L"Erro ao configurar janela.", NULL, MB_ICONERROR);
            PostQuitMessage(WM_QUIT);
        }

        if (LOWORD(wParam))
        {
            fActive = true;
        }
        else
        {
            fActive = false;
        }
        InvalidateRect(hWnd, NULL, false);

        return 0;
    }

    case WM_SIZE:
        /* ... */

    case WM_NCCALCSIZE:
        return 0;

    case WM_NCHITTEST:
        /* ... */

    case WM_GETMINMAXINFO:
        ((LPMINMAXINFO)lParam)->ptMinTrackSize = { 640, 400 };
        return 0;

    case WM_PAINT:
    {
        using namespace Gdiplus;

        PAINTSTRUCT ps;
        HDC hDC = BeginPaint(hWnd, &ps);

        RECT rcWindow;
        GetWindowRect(hWnd, &rcWindow);
        POINT ptSize = { rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top };

        HDC hBuffer = CreateCompatibleDC(hDC);
        HBITMAP hBitmap = CreateCompatibleBitmap(hDC, ptSize.x, ptSize.y);
        SelectObject(hBuffer, hBitmap);

        Graphics graphics(hBuffer);
        Pen Outline(Color(128, 128, 128));
        SolidBrush Selected(Color(128, 0, 255));
        Rect Tab1(10, 10, 200, 50);

        graphics.FillRectangle(&Selected, Tab1);
        graphics.DrawRectangle(&Outline, Tab1);

        /* ... */

        BitBlt(hDC, 0, 0, ptSize.x, ptSize.y, hBuffer, 0, 0, SRCCOPY);

        EndPaint(hWnd, &ps);
        return 0;
    }

    /* ... */

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}


推荐答案

我提到,你几乎在那里与AlphaBlend。我不能记得/意识到,你需要使用一个32位的DibSection持有紫色矩形。你还需要确保你使用32bit感知绘图功能。这意味着您必须直接写入Dib的位,在调用GetDIBits(或在从某些位创建DIB之前)检索它们之后,,您需要使用GDI +绘制紫色长方形。你可以在WM_INITDIALOG处理程序中看到我注释掉的代码。这给出了第二个图像中显示的结果。

As I mentioned, you were almost there with AlphaBlend. What I'd failed to remember/realize though was that you need to use a 32 bit DibSection that holds the purple rectangle. You also need to make sure you use 32bit aware drawing functions. That means you either have to write directly to the bits of the Dib, after retrieving them with a call to GetDIBits (or before creating a DIB from some bits) or you need to use GDI+ to draw the purple rectangle. You can see my commented-out code in the WM_INITDIALOG handler. This gives the result shown in the second image.

在我尝试了一些建议后,我在一个我删除的答案,我认识到一个熟悉的问题。

After trying some advice I gave in an answer I've since deleted, I recognized a familiar problem. The colour of the purple rectangle changed depending on on the colour of the window that my window was obscurring.

这是另一个代码示例,已经过测试,并在Win7s实现下工作DWM。我不知道Glass在这里有什么区别,或者如果Win 8的行为类似。

Here's another code sample that has been tested and works under Win7s implementation of the DWM. I'm not sure if Glass makes a difference here, or if Win 8 will behave similarly.

这里是图片:(绘制时颜色是正确的,一个8位的索引已略有改变)

Here's the image: (The colour was correct when drawn, making the image an 8bit indexed one has changed it slightly)

注意编辑框中的文本是有点时髦,从好的改变为不好的背景受益的窗口从黑色变成白色。这是当我使用GDI绘制紫色矩形展示同样的效果。当我使用GDI +时,问题消失了。快速地拖动窗口可以使紫色框的边缘看起来有点奇怪。我认为这是Windows7中DWM实现的许多失败中的另一个失败。

Notice that the text in the edit-box is a bit funky, changing from okay to not okay as the background beneat the window changes from black to white. This is the same effect that the purple rectangle was exhibiting when I used GDI to draw it. When I used GDI+ instead, the problem went away. Dragging the window around rapidly can make the edges of the purple box appear a little strange. I think this is another one of the many failings of the DWM implementation in Windows7.

这里是这个窗口的完整代码:

And here's the complete code for this window:

#define _WIN32_IE 0x0501
#define _WIN32_WINNT 0x0501
#define WINVER 0x0510

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"
#include <dwmapi.h>
#include <gdiplus.h>
#include <wingdi.h>
using namespace Gdiplus;
HINSTANCE hInst;

// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP mLoadImageFile(wchar_t *filename)
{
    HBITMAP result = NULL;
    Bitmap bitmap(filename, false);
    Color colBkg(0,0,0,0);
    bitmap.GetHBITMAP(colBkg, &result);
    return result;
}

HBITMAP zCreateDibSection(HDC hdc, int width, int height, int bitCount)
{
    BITMAPINFO bi;
    ZeroMemory(&bi, sizeof(bi));
    bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
    bi.bmiHeader.biWidth = width;
    bi.bmiHeader.biHeight = height;
    bi.bmiHeader.biPlanes = 1;
    bi.bmiHeader.biBitCount = bitCount;
    bi.bmiHeader.biCompression = BI_RGB;
    return CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, 0,0,0);
}

HRESULT ExtendGlassIntoClient(HWND hwnd, int left, int right, int top, int bottom)
{
   MARGINS margins = {left,right,top,bottom};
   HRESULT hr = S_OK;

   hr = DwmExtendFrameIntoClientArea(hwnd,&margins);
   if (SUCCEEDED(hr))
   {
      // ...
   }
   return hr;
}

HBITMAP mImg, mStackOverflowBitmap;
HDC memDC, memDC2;
HBITMAP oldBmp, oldBmp2;
LRESULT CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_INITDIALOG:
    {
        ExtendGlassIntoClient(hwndDlg, 0,0,50,0);
        mImg = mLoadImageFile(L"girl.png");
        mStackOverflowBitmap = zCreateDibSection(NULL, 200, 50, 32);

        memDC = CreateCompatibleDC(NULL);
        memDC2 = CreateCompatibleDC(NULL);

        oldBmp = (HBITMAP)SelectObject(memDC, mImg);
        oldBmp2 = (HBITMAP)SelectObject(memDC2, mStackOverflowBitmap);

// ** DOESNT WORK ** - produces a washed-out pink rectangle *****
//        HBRUSH mBrush = CreateSolidBrush( RGB(128,0,255) );
//        RECT mRect = {0,0,200,50};
//        FillRect(memDC2, &mRect, mBrush);
//        DeleteObject(mBrush);

            Color mCol(255,128,0,255);
            SolidBrush mBrush(mCol);
            Graphics graphics(memDC2);
            graphics.FillRectangle(&mBrush, (int)0, (int)0, 200, 50);

    }
    return TRUE;

    case WM_ERASEBKGND:
        {
            HDC hdc;
            RECT mRect, topRect;
            hdc = (HDC)wParam;
            GetClientRect(hwndDlg, &mRect);
            topRect = mRect;
            topRect.bottom = 50;
            FillRect(hdc, &topRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
            mRect.top += 50;
            FillRect(hdc, &mRect, (HBRUSH)GetStockObject(WHITE_BRUSH));

            BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
            AlphaBlend(hdc, 0,0, 55,96, memDC, 0, 0, 55,96, bf);

            AlphaBlend(hdc, 100,32,200,50, memDC2, 0,0,200,50, bf);

            return 1;
        }


    case WM_CLOSE:
    {
        EndDialog(hwndDlg, 0);
    }
    return TRUE;

    case WM_COMMAND:
    {
        switch(LOWORD(wParam))
        {
        }
    }
    return TRUE;
    }
    return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR           gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

        hInst=hInstance;
        InitCommonControls();
        int retVal = DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);

    GdiplusShutdown(gdiplusToken);
    return retVal;
}

这篇关于在扩展框架中绘制会产生奇怪的颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆