UpdateLayeredWindow and DrawText

前端 未结 1 609
北海茫月
北海茫月 2020-12-15 02:03

I\'m using UpdateLayeredWindow to display an application window. I have created my own custom buttons and i would like to create my own static text. The problem is that when

相关标签:
1条回答
  • 2020-12-15 02:49

    I know this is an old post ... but I just had this very same problem ... and it was driving me CRAZY.

    Eventually, I stumbled upon this post by Mike Sutton to the microsoft.public.win32.programmer.gdi newsgroup ... from almost 7 years ago!

    Basically, the DrawText (and TextOut) do not play nicely with the alpha channel and UpdateLayeredWindow ... and you need to premultiply the R, G, and B channels with the alpha channel.

    In Mike's post, he shows how he creates another DIB (device independent bitmap) upon which he draws the text ... and alpha blends that into the other bitmap.

    After doing this, my text looked perfect!

    Just in case, the link to the newsgroup post dies ... I am going to include the code here. All credit goes to Mike Sutton (@mikedsutton).

    Here is the code that creates the alpha blended bitmap with the text on it:

    HBITMAP CreateAlphaTextBitmap(LPCSTR inText, HFONT inFont, COLORREF inColour)
    { 
        int TextLength = (int)strlen(inText); 
        if (TextLength <= 0) return NULL; 
    
        // Create DC and select font into it 
        HDC hTextDC = CreateCompatibleDC(NULL); 
        HFONT hOldFont = (HFONT)SelectObject(hTextDC, inFont); 
        HBITMAP hMyDIB = NULL; 
    
        // Get text area 
        RECT TextArea = {0, 0, 0, 0}; 
        DrawText(hTextDC, inText, TextLength, &TextArea, DT_CALCRECT); 
        if ((TextArea.right > TextArea.left) && (TextArea.bottom > TextArea.top))
        { 
            BITMAPINFOHEADER BMIH; 
            memset(&BMIH, 0x0, sizeof(BITMAPINFOHEADER)); 
            void *pvBits = NULL; 
    
            // Specify DIB setup 
            BMIH.biSize = sizeof(BMIH); 
            BMIH.biWidth = TextArea.right - TextArea.left; 
            BMIH.biHeight = TextArea.bottom - TextArea.top; 
            BMIH.biPlanes = 1; 
            BMIH.biBitCount = 32; 
            BMIH.biCompression = BI_RGB; 
    
            // Create and select DIB into DC 
            hMyDIB = CreateDIBSection(hTextDC, (LPBITMAPINFO)&BMIH, 0, (LPVOID*)&pvBits, NULL, 0); 
            HBITMAP hOldBMP = (HBITMAP)SelectObject(hTextDC, hMyDIB); 
            if (hOldBMP != NULL)
            { 
                // Set up DC properties 
                SetTextColor(hTextDC, 0x00FFFFFF); 
                SetBkColor(hTextDC, 0x00000000); 
                SetBkMode(hTextDC, OPAQUE); 
    
                // Draw text to buffer 
                DrawText(hTextDC, inText, TextLength, &TextArea, DT_NOCLIP); 
                BYTE* DataPtr = (BYTE*)pvBits; 
                BYTE FillR = GetRValue(inColour); 
                BYTE FillG = GetGValue(inColour); 
                BYTE FillB = GetBValue(inColour); 
                BYTE ThisA; 
                for (int LoopY = 0; LoopY < BMIH.biHeight; LoopY++) { 
                    for (int LoopX = 0; LoopX < BMIH.biWidth; LoopX++) { 
                        ThisA = *DataPtr; // Move alpha and pre-multiply with RGB 
                        *DataPtr++ = (FillB * ThisA) >> 8; 
                        *DataPtr++ = (FillG * ThisA) >> 8; 
                        *DataPtr++ = (FillR * ThisA) >> 8; 
                        *DataPtr++ = ThisA; // Set Alpha 
                    } 
                } 
    
                // De-select bitmap 
                SelectObject(hTextDC, hOldBMP); 
            } 
        } 
    
        // De-select font and destroy temp DC 
        SelectObject(hTextDC, hOldFont); 
        DeleteDC(hTextDC); 
    
        // Return DIBSection 
        return hMyDIB; 
    }
    

    Here is the code that drives the CreateAlphaTextBitmap method:

    void TestAlphaText(HDC inDC, int inX, int inY)
    { 
        const char *DemoText = "Hello World!\0"; 
        RECT TextArea = {0, 0, 0, 0}; 
        HFONT TempFont = CreateFont(50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Arial\0"); 
        HBITMAP MyBMP = CreateAlphaTextBitmap(DemoText, TempFont, 0xFF); 
        DeleteObject(TempFont); 
        if (MyBMP)
        {
            // Create temporary DC and select new Bitmap into it 
            HDC hTempDC = CreateCompatibleDC(inDC); 
            HBITMAP hOldBMP = (HBITMAP)SelectObject(hTempDC, MyBMP); 
            if (hOldBMP)
            {
                // Get Bitmap image size
                BITMAP BMInf;
                GetObject(MyBMP, sizeof(BITMAP), &BMInf); 
    
                // Fill blend function and blend new text to window 
                BLENDFUNCTION bf; 
                bf.BlendOp = AC_SRC_OVER; 
                bf.BlendFlags = 0; 
                bf.SourceConstantAlpha = 0x80; 
                bf.AlphaFormat = AC_SRC_ALPHA; 
                AlphaBlend(inDC, inX, inY, BMInf.bmWidth, BMInf.bmHeight, hTempDC, 0, 0, BMInf.bmWidth, BMInf.bmHeight, bf); 
    
                // Clean up 
                SelectObject(hTempDC, hOldBMP); 
                DeleteObject(MyBMP); 
                DeleteDC(hTempDC); 
            } 
        } 
    } 
    
    0 讨论(0)
提交回复
热议问题