Create HBITMAP from Fl_RGB_Image

      Comments Off on Create HBITMAP from Fl_RGB_Image

Here is a simple code for convert Fl_RGB_Image to HBITMAP.

HBITMAP GetHBMPfromFlRGBImg( const Fl_RGB_Image* src )
{
    if ( src == NULL )
        return NULL;

    if ( src->d() != 4 ) /// Accepts only for RGBA 4 depth.
        return NULL;

    BITMAPINFOHEADER bmih = {0};

    bmih.biSize             = sizeof(BITMAPINFOHEADER);
    bmih.biWidth            = src->w();
    bmih.biHeight           = -(src->h());
    bmih.biPlanes           = 1;
    bmih.biBitCount         = 32;
    bmih.biCompression      = BI_RGB ;
    bmih.biXPelsPerMeter    = 10;
    bmih.biYPelsPerMeter    = 10;

    BITMAPINFO dbmi = {0};

    dbmi.bmiHeader = bmih;
    dbmi.bmiColors->rgbBlue = 0;
    dbmi.bmiColors->rgbGreen = 0;
    dbmi.bmiColors->rgbRed = 0;
    dbmi.bmiColors->rgbReserved = 0;

    unsigned psz = src->w() * src->h();
    const uchar* refbuff = (const uchar*)src->data()[0];
    uchar* pixels = new uchar[ psz * 4 ];

    if ( pixels == NULL )
        return NULL;

    // need to convert RGBA to BGRA
    for( unsigned cnt=0; cnt<psz; cnt++ )
    {
        pixels[ cnt * 4 + 0 ] = refbuff[ cnt * 4 + 2 ];
        pixels[ cnt * 4 + 1 ] = refbuff[ cnt * 4 + 1 ];
        pixels[ cnt * 4 + 2 ] = refbuff[ cnt * 4 + 0 ];
        pixels[ cnt * 4 + 3 ] = refbuff[ cnt * 4 + 3 ];
    }

    HDC hdc = GetDC(NULL);

    HBITMAP hbmp = CreateDIBitmap(hdc, &bmih, CBM_INIT, pixels, &dbmi, DIB_RGB_COLORS);

    delete[] pixels;

    return hbmp;
}

 

It should be help to convert Fl_RGB_Image ( must have depth 4 for RGBA ) to HBITMAP. And it works for changing Fl_Window to Layered window easily like this.

Fl_Window*  winTest = NULL;
const char*  strSplash[] = { "Code by Raphael Kim, (C)2018, Copyright\n",
                             "Programming FLTK is funny !\n",
                             "Thank you." };

int main (int argc, char ** argv)
{
    Fl_RGB_Image* imgBg = new Fl_PNG_Image( "testbg.png" );

    if ( imgBg == NULL )
        return 0;

    int img_w = imgBg->w();
    int img_h = imgBg->h();

    winTest = new Fl_Window( img_w, img_h, "Splash Test" );
    if ( winTest != NULL )
    {
        winTest->color( 0 );
        winTest->end();
        winTest->show();

        // Make window layered splash for Windows32.
        HWND hWnd = fl_xid( winTest );
        HDC  hDC  = GetDC( hWnd );

        POINT ptPos = {0,0};
        SIZE sizeWnd = { winTest->w(), winTest->h() };

        SetWindowLong( hWnd, GWL_EXSTYLE,
                       GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);

        HDC hdcMem = CreateCompatibleDC( hDC );
        HBITMAP hbmp = GetHBMPfromFlRGBImg( imgBg );

        fl_begin_offscreen( hbmp );
        imgBg->draw( 0, 0 );

        fl_font( FL_HELVETICA_ITALIC, 18 );
        fl_color( 0xFFFFFFFF );

        int tput_x = imgBg->w() / 10;
        int tput_y = imgBg->h() / 2;

        for( int cnt=0; cnt<3; cnt++ )
        {
            fl_draw( strSplash[cnt], tput_x, tput_y );
            tput_y += 20;
        }

        fl_end_offscreen();

        HGDIOBJ oldBitmap = SelectObject(hdcMem, hbmp);

        BLENDFUNCTION blend = {0};
        blend.BlendOp = AC_SRC_OVER;
        blend.SourceConstantAlpha = 255;
        blend.AlphaFormat = AC_SRC_ALPHA;

        UpdateLayeredWindow( hWnd, NULL,
                             &ptPos, &sizeWnd,
                             hdcMem, &ptPos,
                             0, /// RGB(255,255,255),
                             &blend,
                             ULW_ALPHA );

        RedrawWindow( hWnd,
                      NULL, NULL,
                      RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN );

        SelectObject( hdcMem, oldBitmap );
        DeleteObject( hbmp );
    }

    return Fl::run();
}

And it may runs as this.