[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(&amp;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, &amp;bmInfo, DIB_RGB_COLORS, &amp;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, &amp;rc, &amp;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 in

    0 _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::drawItemText

    If use Format_RGB32 - crash does'n happens.
    If don't perform call DrawThemeTextEx - crash does'n happens.

    WTF? I'm stuck.



  • Quote from docs

    bq. Note: Do not render into ARGB32 images using QPainter. Using QImage::Format_ARGB32_Premultiplied is significantly faster.

    Maybe if you use QImage::Format_ARGB32_Premultiplied, will work ...



  • bq. Maybe if you use QImage::Format_ARGB32_Premultiplied, will work …

    no.

    OMG!
    Build with MSVC 2008 - works!
    both QImage::Format_ARGB32_Premultiplied and QImage::Format_ARGB32
    mingw still crash



  • bq. Build with MSVC 2008 – works!

    Dubug only

    Release killed by DEP protection



  • 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 BITMAPINFO

    VOID* 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!!!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.