【问题标题】:Custom color shape on a WIN32 dialogboxWIN32 对话框上的自定义颜色形状
【发布时间】:2014-07-24 20:13:40
【问题描述】:

我的对话框以 Windows Vista 中声音管理器的方式显示当前选定的音频输入:

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

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

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

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

我进行了一些额外的调查。似乎 GDI 被 GDI+ 取代了,它更易于使用,并且具有抗锯齿和 Alpha,这对我来说很重要。 如果您仔细查看他们在声音管理器中使用的图像,您会亲眼看到:

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

【问题讨论】:

  • 你用什么语言编程?
  • @ZeroWorks:非托管 C++
  • 如果您使用蒙版位图资源,您可以绘制背景,然后在顶部透明地渲染位图。附言。我经常使用 HIMAGELIST 来完成这项工作,因为它在内部处理所有透明度。
  • @user1793036 请记住,我不会选择图像。我需要以作为参数给我的任意颜色绘制一个圆圈。

标签: c++ winapi custom-controls dialog


【解决方案1】:

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

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,不要调用 base WinProc。

MSDN Reference

【讨论】:

  • 它肯定有帮助。是否可以将此动态位图用于静态控件?我想使用 resource 文件放置位图。或者也许创建一个控件,使用它的位置并使控件不可见?
  • 哦!使用资源文件更容易,因为所有工作都是在 WM_PAINT 中完成的,我想我会创建一个没有文本的简单标签控件,并且在这个标签的 WM_PÂINT 上将绘制资源。使用自定义控件或 WM_PAINT 是一样的:只需一次绘制所有控件以避免闪烁。编辑以绘制资源。
  • 是的...您可以将此动态位图用于静态控件,因为您可以绘制它和显示的 WM_PAINT。
  • 请参考我的编辑[1]部分
猜你喜欢
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多