提问人:MyDoomH 提问时间:10/23/2023 最后编辑:MyDoomH 更新时间:10/26/2023 访问量:125
在带有 BS_OWNERDRAW 标志的按钮中显示透明位图
Displaying a transparent bitmap in a button with the BS_OWNERDRAW flag
问:
在按钮上显示透明位图时出现问题。新图像只是相互叠加,我在互联网上找不到任何关于这一点的合理信息。
这是我拥有的代码:
VOID DrawButton(LPDRAWITEMSTRUCT DrawStruct, HBITMAP* BitmapArray)
{
HBITMAP CurrentBitmap = BitmapArray[BM_UP];
switch (DrawStruct->itemAction)
{
case ODA_SELECT:
if (DrawStruct->itemState & ODS_SELECTED)
{
if (DrawStruct->itemState & ODS_FOCUS)
CurrentBitmap = BitmapArray[BM_DOWN_FOCUS];
else
CurrentBitmap = BitmapArray[BM_DOWN];
}
break;
case ODA_DRAWENTIRE:
if (DrawStruct->itemState & ODS_DISABLED)
CurrentBitmap = BitmapArray[BM_DISABLE];
break;
case ODA_FOCUS:
if (DrawStruct->itemState & ODS_FOCUS)
CurrentBitmap = BitmapArray[BM_FOCUS];
break;
}
HDC CompatibleDC = CreateCompatibleDC(DrawStruct->hDC);
HBITMAP hOld = (HBITMAP)SelectObject(CompatibleDC, CurrentBitmap);
SelectObject(CompatibleDC, CurrentBitmap);
AlphaBlend(DrawStruct->hDC, 0, 0, 50, 24, CompatibleDC, 0, 0, 50, 24, { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA });
SelectObject(DrawStruct->hDC, hOld);
DeleteDC(CompatibleDC);
DeleteObject(CurrentBitmap);
}
UPD:所以,我添加了 FillRect,但现在在我按下按钮并释放它后,图像就消失了。
VOID DrawButton(LPDRAWITEMSTRUCT DrawStruct, HBITMAP* BitmapArray)
{
...
FillRect(DrawStruct->hDC, &DrawStruct->rcItem, CreateSolidBrush(RGB(127, 127, 127)));
HDC CompatibleDC = CreateCompatibleDC(DrawStruct->hDC);
...
}
UPD_2:我终于发现了一些问题,AlphaBlend 在第三次调用后返回错误。错误代码:87(参数不正确)。我不明白是哪一个?我检查了调试器 - hdcDest,hdcSrc 似乎正常,不是 NULL,其他参数没有改变
答:
-1赞
YangXiaoPo-MSFT
10/23/2023
#1
正如@JonathanPotter所说,您需要使该区域失效或擦除。
有一个 Microsoft 示例 ChooseFont 可以解释这一点。
/******************************************************************
* *
* ChooseFontDialog::OnFontSizeSelect *
* *
* Record the new font size and redraw the sample text. *
* *
******************************************************************/
HRESULT ChooseFontDialog::OnFontSizeSelect()
{
HRESULT hr = S_OK;
// Signal the sample text window to redraw itself.
InvalidateRect(GetDlgItem(m_dialog, ID_SAMPLE_BOX), NULL, false);
return hr;
}
编辑:
InvalidateRect 只是在窗口的更新区域不为空且该窗口的应用程序队列中没有其他消息时向窗口发出消息。WM_PAINT
它被擦除在 .WM_DRAWITEM
if (SUCCEEDED(hr))
{
// Fill the DWrite surface with the background color
HDC dwriteDC = textRenderer->GetDC();
SetDCBrushColor(dwriteDC, GetSysColor(COLOR_BTNFACE));
FillRect(dwriteDC, &sampleBounds, GetStockBrush(DC_BRUSH));
...
}
评论
0赞
MyDoomH
10/23/2023
InvalidateRect 将再次调用 DrawButton...
0赞
IInspectable
10/24/2023
“你需要 [...]擦除该区域“ - 我相信有比将参数作为参数传递到 InvalidateRect
调用更有前途的方法来实现这一目标。false
bErase
0赞
YangXiaoPo-MSFT
10/24/2023
@MyDoomH,我更新了我的答案。它与 Windows 绘图相同。答案是 Windows 要求窗口过程将窗口重绘为两步过程。首先,它发送一条WM_ERASEBKGND消息,然后发送一条WM_PAINT消息。WM_ERASEBKGND消息的默认处理方式是用当前窗口背景色填充该区域。因此,事件的顺序是首先用纯色填充该区域,然后在上面绘制文本。
0赞
MyDoomH
10/25/2023
因此,我添加了 FillRect,但现在图像消失了。UPD 中附有一个示例。
0赞
MyDoomH
10/26/2023
我终于发现了一些问题,AlphaBlend 在第三次调用后返回错误。错误代码:87(参数不正确)。我不明白是哪一个?我检查了调试器 - hdcDest,hdcSrc 似乎正常,不是 NULL,其他参数没有改变
评论
CurrentBitmap
CompatibleDC
CurrentBitmap