WIN32对话框上的自定义颜色形状

时间:2014-06-04 08:55:46

标签: c++ winapi custom-controls dialog

我的对话框以Sound Manager在Windows Vista中的方式显示当前选定的音频输入:

Sound manager

这是我的WIN32对话框。使用箭头指向所需的形状位置: My Dialogbox

绘制这种形状的最佳策略是什么。自定义绘制控件? GDI?

请注意,应用程序已经完成(所以没有WPF也没有Direct2D)并且颜色在COLORREF中给出,因此没有选项来准备可供选择的图标列表。

编辑[1] \\\\\\\\\\\\\\

我做了一些额外的调查。似乎GDI被GDI +取代,它更易于使用并且具有抗锯齿和Alpha,这对我来说很重要。 如果您仔细查看它们在Sound Manager中使用的图像,您将亲自看到:

Audio jack close up

所以我写了GDI +代码,它运行正常。也就是说,图像是合理的,但我用每个WM_PAINT创建整个位图,这很难看。 我没有找到一种方法(在 GDI + 中)在内存中创建位图(相当于CreateCompatibleDC),然后将其复制到目标(等效于BitBlt)。我见过混合GDI和GDI +的例子。这是正确的方法吗?

1 个答案:

答案 0 :(得分:2)

最好的策略是使用GDI和HBITMAP绘制,它将充当缓冲区,每次颜色更改时只重新创建该位图。然后在WndProc的形状中,当控制WM_PAINT时,只需绘制它:

case WM_PAINT:
    PAINTSTRUCT     ps;
    HDC             hdc;
    BITMAP          bitmap;
    HDC             hdcMem;
    HGDIOBJ         oldBitmap;

    hdc = BeginPaint(hWnd, &ps);

    hdcMem = CreateCompatibleDC(hdc);
    oldBitmap = SelectObject(hdcMem, hBitmap);

    GetObject(hBitmap, sizeof(bitmap), &bitmap);
    BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);

    SelectObject(hdcMem, oldBitmap);
    DeleteDC(hdcMem);

    EndPaint(hWnd, &ps);        
break;

为了简化所需的绘图(圆圈内的圆圈),您可以在WM_PAINT中绘制所有内容,但最好按照建议创建缓冲区,这样可以更快,避免闪烁,还可以绘制部件而不是整个图像。要创建缓冲区,请使用:CreateCompatibleBitmap创建内存DC:

HDC hDC;
int width = 16;
int height= 16;

HDC     hMemDC = ::CreateCompatibleDC(NULL);
HBITMAP hBmp   = ::CreateCompatibleBitmap(hDC, width, height);
::SelectObject(hMemDC, hBmp);

使用WINAPI绘制,看看Win32 GDI Drawing a circle

如果要从资源中绘制,请在WM_CREATE中加载位图:

HBITMAP g_hbmBall = NULL;

case WM_CREATE:
    g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
    if(g_hbmBall == NULL)
        MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
break;

然后只绘制WM_PAINT:

case WM_PAINT:
{
    BITMAP bm;
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hwnd, &ps);

    HDC hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hbmOld = SelectObject(hdcMem, g_hbmBall);

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

    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);

    SelectObject(hdcMem, hbmOld);
    DeleteDC(hdcMem);

    EndPaint(hwnd, &ps);
}
break;

只是因为它是一个小图标,你可以在窗口的WndProc的WM_PAINT上进行绘制...但只是为了避免创建另一个控件,因为它是一个小位图。

希望它有帮助!

修改

如果你打算使用GDI +(我虽然你对它不感兴趣......我很抱歉)。当然,您可以使用GDI +绘制位图。所有的事情都改变了,只需要创建一个图形并制作图纸。此外,您可以加载一个位图并使用`DrawImage'绘制它,例如从MSDN中获取:

Image image(L"Grapes.jpg");
graphics.DrawImage(&image, 60, 10);

当您使用WinProc时,您可以从hDC创建一个Graphics然后绘制。请记住处理Graphics并且不要调用基本WinProc。

MSDN Reference