Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Brainstorm
  4. [SOLVED] (WINAPI!!!) Crash while render HBITMAP (Vista Glow)

[SOLVED] (WINAPI!!!) Crash while render HBITMAP (Vista Glow)

Scheduled Pinned Locked Moved Brainstorm
10 Posts 2 Posters 6.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SeTosha
    wrote on 25 Jul 2011, 03:01 last edited by
    #1

    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.

    1 Reply Last reply
    0
    • C Offline
      C Offline
      cincirin
      wrote on 25 Jul 2011, 06:47 last edited by
      #2

      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 ...

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SeTosha
        wrote on 25 Jul 2011, 07:02 last edited by
        #3

        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

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SeTosha
          wrote on 25 Jul 2011, 07:18 last edited by
          #4

          bq. Build with MSVC 2008 – works!

          Dubug only

          Release killed by DEP protection

          1 Reply Last reply
          0
          • C Offline
            C Offline
            cincirin
            wrote on 25 Jul 2011, 07:34 last edited by
            #5

            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);
            @

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SeTosha
              wrote on 25 Jul 2011, 07:57 last edited by
              #6

              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?

              1 Reply Last reply
              0
              • C Offline
                C Offline
                cincirin
                wrote on 25 Jul 2011, 08:08 last edited by
                #7

                [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.

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SeTosha
                  wrote on 25 Jul 2011, 08:48 last edited by
                  #8

                  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

                  1 Reply Last reply
                  0
                  • C Offline
                    C Offline
                    cincirin
                    wrote on 25 Jul 2011, 10:26 last edited by
                    #9

                    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);
                    }
                    @

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      SeTosha
                      wrote on 25 Jul 2011, 11:33 last edited by
                      #10

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

                      1 Reply Last reply
                      0

                      9/10

                      25 Jul 2011, 10:26

                      • Login

                      • Login or register to search.
                      9 out of 10
                      • First post
                        9/10
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved