[SOLVED] (WINAPI!!!) Crash while render HBITMAP (Vista Glow)
-
I want to draw Glow text in Aero Vindows style. Simple!
QProxyStyle subclass
Create bitmap
DrawThemeTextEx
Draw bitmap
...
Profit!
Lets go! (Wall of win API code)
@void GlassStyle::drawItemText(QPainter painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const
{
if(DrawThemeTextEx && OpenThemeData && CloseThemeData && rect.isValid() && !rect.isEmpty()) {
const int glowSize = 10;
qDebug() << "drawItemText: " << text << "\nrect: " << rect;
QWidget widget = dynamic_cast<QWidget*>(painter->device());
if(widget) {
HWND hwnd = widget->winId();
HDC hdcWidget = GetDC(hwnd);
HDC hdcMemory = CreateCompatibleDC(hdcWidget);QRect r = rect.adjusted(-glowSize, -glowSize, glowSize, glowSize); HTHEME htheme = OpenThemeData(hwnd, L"toolbar button;button"); HRESULT hr = S_OK; if(htheme){ BITMAPINFO bmInfo; ZeroMemory(&bmInfo, sizeof(bmInfo)); const uint alignment = 4; uint alignedWidth = r.width()+1; const uint pixelAlignment = alignment/4; if(alignedWidth%(pixelAlignment)) alignedWidth+=pixelAlignment-alignedWidth%pixelAlignment; bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmInfo.bmiHeader.biWidth = alignedWidth; bmInfo.bmiHeader.biHeight = r.height()+1; bmInfo.bmiHeader.biPlanes = 1; bmInfo.bmiHeader.biBitCount = 32; bmInfo.bmiHeader.biCompression = 0; LPVOID pvBits = NULL; HBITMAP hbmp = CreateDIBSection(hdcMemory, &bmInfo, DIB_RGB_COLORS, &pvBits, NULL, 0); HGDIOBJ oldBitmap = SelectObject(hdcMemory, hbmp); HGDIOBJ oldFont = SelectObject(hdcMemory, painter->font().handle()); DTTOPTS dttopts; dttopts.dwSize = sizeof(DTTOPTS); dttopts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE; dttopts.iGlowSize = glowSize; RECT rc={glowSize, glowSize, rect.width()+glowSize+1, rect.height()+glowSize+1}; DWORD uFormat = DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX; hr = DrawThemeTextEx(htheme, hdcMemory, 0, 0, reinterpret_cast<const WCHAR*>(text.utf16()), text.length(), uFormat, &rc, &dttopts); if(FAILED(hr)) qDebug() << "DrawThemeTextEx failed: " << hr; hr = CloseThemeData(htheme); if(FAILED(hr)) qDebug() << "CloseThemeData: " << hr; SelectObject(hdcMemory, oldFont); SelectObject(hdcMemory, oldBitmap); if(!GdiFlush()) qDebug() << "GdiFlush failed";
@
Variants:- Direct QImage
@
QImage image(reinterpret_cast<uchar*>(pvBits), bmInfo.bmiHeader.biWidth, bmInfo.bmiHeader.biHeight, QImage::Format_ARGB32);
painter->drawImage(r.topLeft(), image); // Crash
@ - Copy bits to existetn image
@
QImage img(bmInfo.bmiHeader.biWidth, bmInfo.bmiHeader.biHeight, QImage::Format_ARGB32);
if(!GetDIBits(hdcMemory, hbmp, 0, bmInfo.bmiHeader.biHeight, img.bits(), &bmInfo, DIB_RGB_COLORS))
qDebug() << "GetDIBits failed";// or memcpy(image.bits(), pvBits2, bmInfo.bmiHeader.biWidthbmInfo.bmiHeader.biHeight4);
painter->drawImage(r.topLeft(), img); // Crash@
- QPixmap from HBITMAP
@
painter->drawPixmap(r.topLeft(), QPixmap::fromWinHBITMAP(hbmp, QImage::Format_ARGB32); // Crash
@
@
DeleteDC(hdcMemory);
ReleaseDC(hwnd, hdcWidget);
DeleteObject(hbmp);
}
return;
}
}
QProxyStyle::drawItemText(painter, rect, flags, pal, enabled, text, textRole);
}@mingw
All crashes in0 _mm_andnot_si128 emmintrin.h 1239 0x1af63f5
1 comp_func_SourceOver_sse2 qdrawhelper_sse2.cpp 156 0x1af63f5
2 blend_untransformed_generic<(SpanMethod)0> qdrawhelper.cpp 3764 0x1cbc0f1
3 blend_untransformed_argb<(SpanMethod)0> qdrawhelper.cpp 3787 0x1cc0514
4 qBlendTexture qdrawhelper.cpp 6960 0x1cad876
...
GlassStyle::drawItemTextIf use Format_RGB32 - crash does'n happens.
If don't perform call DrawThemeTextEx - crash does'n happens.WTF? I'm stuck.
- Direct QImage
-
Do you use alpha channel for your image ? If not, QImage::Format_RGB32 is the solution.
However I see something suspicious in your code.
@
HDC hdcMemory = CreateCompatibleDC(hdcWidget);
LPVOID pvBits = NULL;
HBITMAP hbmp = CreateDIBSection(hdcMemory, &bmInfo;, DIB_RGB_COLORS, &pvBits;, NULL, 0);
HGDIOBJ oldBitmap = SelectObject(hdcMemory, hbmp);
...
@
I would do something like :
@
HDC hdcBitmap = CreateCompatibleDC(hdcWidget);
LPVOID pvBits = NULL;
HBITMAP hbmp = CreateDIBSection(hdcBitmap, &bmInfo;, DIB_RGB_COLORS, &pvBits;, NULL, 0);
HGDIOBJ oldBitmap = SelectObject(hdcMemory, hbmp);
@ -
bq. QImage::Format_RGB32 is the solution.
no. If i use Format_RGB32 parts of toolbar bitmaps, overlaped by extended rect is filled by transparent color.
bq. However I see something suspicious in your code.
What do you mean?
I try to
create memoryDC
select devce independent bitmap to render to
Render glow text
Render this result bitmap to painter
Why I should create 2-nd HDC?
-
[quote author="SeTosha" date="1311580661"]
If i use Format_RGB32 parts of toolbar bitmaps, overlaped by extended rect is filled by transparent color.
[/quote]
Then really you need the alpha channel information.[quote author="SeTosha" date="1311580661"]
create memoryDC
select devce independent bitmap to render to
Why I should create 2-nd HDC?
[/quote]
You created memory device context, created DIB in this DC, and then select DIB in the same DC, in that you created.
I know I had problems with this. -
bq. You created memory device context, created DIB in this DC, and then select DIB in the same DC, in that you created.
@HBITMAP hbmp = CreateDIBSection(hdcWidget, &bmInfo, DIB_RGB_COLORS, &pvBits, NULL, 0);
HGDIOBJ oldBitmap = SelectObject(hdcMemory, hbmp);
@crash
-
Maybe you have another problem somewhere else. Is impossible that this code is not good.
I just did a little test, and it works perfectly:
@
void test(HDC hdc/* = NULL*/)
{
BITMAPINFO bi;
// ... fill BITMAPINFOVOID* pDIBBits = NULL;
HBITMAP hDIBBitmap = CreateDIBSection(hdc, &bi;, DIB_RGB_COLORS, &pDIBBits;, NULL, 0UL);
DeleteDC(hdcDIB);HDC testDC = CreateCompatibleDC(hdc);
SelectObject(testDC, hDIBBitmap);
}
@ -
code works if I comment call of DrawThemeTextEx
It draws
may be need to set clipping before call it?OMG!
@typedef HRESULT (*PDrawThemeTextEx)(
HTHEME hTheme,
HDC hdc,
int iPartId,
int iStateId,
LPCWSTR pszText,
int iCharCount,
DWORD dwFlags,
LPRECT pRect,
const DTTOPTS *pOptions
);@I forget typedef WINAPI
Should be
@HRESULT (WINAPI *PDrawThemeTextEx)(
HTHEME hTheme,
HDC hdc,
int iPartId,
int iStateId,
LPCWSTR pszText,
int iCharCount,
DWORD dwFlags,
LPRECT pRect,
const DTTOPTS *pOptions
);@All works!!! Thanks all
PS. never ever copy-paste function declaration from MSDN!!!