2011-03-07 21 views
2

最終的な目的は、透明度を使用するウィンドウにスプラッシュ画面を表示することですが、それは今のところ止まっていません。GDIを使用したWindowsのスプラッシュ画面

透明なウィンドウを作成するには、まずスプラッシュ画面とテキストをGDI +を使用してオフスクリーンバッファに合成しようとしています。

現在、私はバッファを合成し、 'WM_PAINT'メッセージに応答してそれを表示しようとしています。これは現時点では機能していません。私が見るのは黒い窓だけです。私はGDI +でのレンダーターゲットを設定し、その後

(私はまっすぐ進むGDIブリットを使用して画面を描画しようとしている)、それらをレンダリングに関して何かを誤解してきた想像

はとにかく、ここではこれまでのコードです:長い記事のため

---8<----------------------- 
//Paint message snippit 

    case WM_PAINT: 
    { 
     BITMAP bm; 
     PAINTSTRUCT ps; 

     HDC hdc = BeginPaint(vg->m_hwnd, &ps); //get the HWNDs DC 

     HDC hdcMem = vg->m_gdi_dc->GetHDC(); //get the HDC from our offscreen GDI+ object 

     unsigned int width = vg->m_gdip_offscreen_bm->GetWidth(); //width and height seem fine at this point 
     unsigned int height = vg->m_gdip_offscreen_bm->GetHeight(); 
     BitBlt(hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY); //this blits a black rectangle 

     DWORD last_error = GetLastError();    //this was '0' 

     vg->m_gdi_dc->ReleaseHDC(hdcMem); 

     EndPaint(vg->m_hwnd, &ps); //end paint 

     return 1; 
    } 

    ---8<----------------------- 

私の謝罪:

//my window initialisation code 
void MyWindow::create_hwnd(HINSTANCE instance, const SIZE &dim) 
{      
    DWORD ex_style = WS_EX_LAYERED ; //eventually I'll be making use of this layerd flag 
    m_hwnd = CreateWindowEx(
      ex_style, 
      szFloatingWindowClass , 
      L"", 
      WS_POPUP , 
      0, 
      0,  
      dim.cx, 
      dim.cy, 
      null, 
      null, 
      instance, 
      null);  


     m_display_dc = GetDC(NULL); 
     //This was sanity check test code - just loading a standard HBITMAP and displaying it in WM_PAINT. It worked fine 
     //HANDLE handle= LoadImage(NULL , L"c:\\test_image2.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);  
     m_gdip_offscreen_bm = new Gdiplus::Bitmap(dim.cx, dim.cy); 

     m_gdi_dc = Gdiplus::Graphics::FromImage(m_gdip_offscreen_bm);//new Gdiplus::Graphics(m_splash_dc);//window_dc ;m_splash_dc  

     //this draws the conents of my splash screen - this works if I create a GDI+ context for the window, rather than for an offscreen bitmap. 
     //For all I know, it might actually be working but when I try to display the contents on screen, it shows a black image 
     draw_all(); 
     //this is just to show that drawing something simple on the offscreen bit map seems to have no effect 
     Gdiplus::Pen pen(Gdiplus::Color(255, 0, 0, 255)); 
     m_gdi_dc->DrawLine(&pen, 0,0,100,100); 

     DWORD last_error = GetLastError(); //returns '0' at this stage     
} 

そしてここでWM_PAINTメッセージを処理snipitです。誰かが、私がGDI +(またはGDIその点で)を使ってオフスクリーンバッファに書き込む方法に関してかなり理解していないことを知っていますか?それを画面に表示しますか?

ありがとうございます。

+0

私は、画面の別のGDI +コンテキストを作成し、それを使って合成したものをペイントするとうまくいきますが、私がGDI-メソッドを使用しようとしていた理由は、 UpdateLayeredWindow 'を呼び出します。GDIを使ってGDI +イメージをどのようにblitするかについての私の質問は、まだまだ立っています。 – Luther

+1

ウィンドウにWS_EX_LAYEREDスタイルがこのように追加されている場合、WM_PAINTメッセージは送信されないため、このコードは機能しません。これにより、ウィンドウは、UpdateLayeredWindowが更新するウィンドウのオフスクリーンビットマップのコピーのみをblitします。 –

+0

チップChrisに感謝します。今のところ階層化フラグをオフにしていますが、まだアルファブレンドされた画像を描画するのに問題があります。私は現在、アルファブレンディングされた画像をレンダリングするための代替のfpr BitBltと思われる 'AlphaBlend'を使用しようとしています。今のところサイコロはありませんが、GetLastErrorを 'ERROR_INVALID_PARAMETER'に設定するだけですが、詳しいことはしません。私はWin32とGDIの友人になることはありません。彼らはちょうどいい遊びません!アルファブレンドは簡単ではありません。 – Luther

答えて

2

解決済みですが、これは最適ではないと確信しています。 まず、Chris Becke氏が示唆するように、WM_PAINTメッセージには応答しないでください.'UpdateLayeredWindow 'を使用して更新する必要があります。私が持っていた問題の1つは、UpdateLayeredWindowにいくつかの悪い座標を与えたことです。具体的には、ソースとデスティネーションをスワップしました(doh!)

GDI +サーフェスからUpdateLayeredWindowを呼び出すコードは次のとおりです。最適ではありませんが動作します。

void TOPLEVEL_FLOATING_WINDOW::update_layered_window() 
{ 
    BLENDFUNCTION blend_func = { 0 };  //build the blend function object... I guess microsoft doesn't/didn't like constructors 
    blend_func.AlphaFormat = AC_SRC_OVER; 
    blend_func.BlendFlags = 0; 
    blend_func.SourceConstantAlpha = 255; 
    blend_func.AlphaFormat = AC_SRC_ALPHA; 

    POINT_2i pt = m_screen_pos; 
    VECTOR_2i dim = m_bounds.dimensions(); 

    POINT_2i pt_src (0,0) ;    

    Gdiplus::Color bg(0,0,0,0); 
    m_gdip_offscreen_bm->GetHBITMAP(bg, &m_offscreen_bm); //get the Hbitmap from my GDI+ bitmap - I think this is allocating a whole new bitmap off the heap. Yuck, very inefficient! 
    HDC splash_dc = CreateCompatibleDC(m_display_dc);  //create a temporary HDC   
    HGDIOBJ oldobj = SelectObject(splash_dc , m_offscreen_bm); //'select' the bitmap.  
    UpdateLayeredWindow(m_hwnd,m_display_dc, (POINT*)&pt, (SIZE*)&dim, splash_dc , (POINT*)&pt_src, 0 ,&blend_func,ULW_ALPHA); //this call works and updates our splash screens hidden buffer  
    SelectObject(splash_dc, oldobj); //some tidy up code 
    DeleteObject(m_offscreen_bm);  //free the bitmap. Memory fragmentation HO! 
    DeleteDC(splash_dc); //Delete the DC   
} 

そして、ここでは、私はは動作しませんがすべきだと思うものです。私は理由を教えてくれる人にいくつか指摘します!これはHDCが生まれておらず、UpdateLayeredWindow関数が特定のソースによって作成されたHDCしか一定の方法で受け入れることができないためだと思います。これのルールがもっと明白であればいいだろう。

void TOPLEVEL_FLOATING_WINDOW::update_layered_window_in_an_ideal_world() 
    { 
     m_refresh_needed = false; 
     BLENDFUNCTION blend_func = { 0 }; 
     blend_func.AlphaFormat = AC_SRC_OVER; 
     blend_func.BlendFlags = 0; 
     blend_func.SourceConstantAlpha = 255; 
     blend_func.AlphaFormat = AC_SRC_ALPHA; 

     POINT_2i pt = m_screen_pos; 
     VECTOR_2i dim = m_bounds.dimensions(); 

     POINT_2i pt_src (0,0) ;    

     HDC gdi_HDC = m_screen_gdi_dc->GetHDC(); //I have a GDI+ 'Graphics' object whose back buffer is the image I want to composite on to the desktop  
     UpdateLayeredWindow(m_hwnd,m_display_dc, (POINT*)&pt, (SIZE*)&dim, gdi_HDC , (POINT*)&pt_src, 0 ,&blend_func,ULW_ALPHA); 
     m_screen_gdi_dc->ReleaseHDC(gdi_HDC); //be nice and release the gdi_HDC 
    } 

唯一の他の選択肢は、GDI +を無視して、任意のオフスクリーンバッファにレンダリングすることは非常に満足している私自身のラスターライブラリを使用して、すべてをレンダリングすることです。しかし、それはこのプロジェクトのための過酷なことです。

2

レイヤードウィンドウにGDI +ビットマップを取得する方法を次に示します。これにより、複数のビットマップオーバーレイ、配置およびサイズ変更が可能になります。

void SetSplashImage() 
{ 
    // Default to upper left of screen 
    POINT ptOrigin = { 0, 0 }; 
    SIZE sizeSplash = { 128, 128 }; 

    // Get the actual screen location 
    GetPointOfOrigin(ptOrigin, sizeSplash); 

    // Our in memory database of GDI+ Bitmaps 
    data::image::BoxOfBits *box = 
    dynamic_cast<data::image::BoxOfBits *>(&Images.get_package("skin_layout_008")); 

    // Create a display context as a canvas to draw the images 
    HDC hdcScreen = GetDC(NULL); 
    HDC hdcMem = CreateCompatibleDC(hdcScreen); 
    HBITMAP bmMem = CreateCompatibleBitmap(hdcScreen, sizeSplash.cx, sizeSplash.cy); 

    // Prep canvas for rendering graphic 
    HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, bmMem); 
    Gdiplus::Graphics graphics(hdcMem); 

    // Base image is a pic of a folder 
    Gdiplus::RectF canvasDest(0,0,128,128); 
    graphics.DrawImage(box->grab("black_folder").pBitmap_, 
    canvasDest, 0,0,128,128, Gdiplus::UnitPixel); 

    // Overlay a pic of some tools in center of folder 
    Gdiplus::RectF canvasDest2(30,50,64,64); // resize half actual size 
    graphics.DrawImage(box->grab("work_tools").pBitmap_, 
    canvasDest2, 0,0,128,128, Gdiplus::UnitPixel); 

    // Overlay a pic of a cog in upper left corner of folder 
    Gdiplus::RectF canvasDest1(16,16,32,32); // resize half actual size 
    graphics.DrawImage(box->grab("cog_edit").pBitmap_, 
    canvasDest1, 0,0,32,32, Gdiplus::UnitPixel); 

    // Prepare to alpha blend the canvas with the screen 
    BLENDFUNCTION blend = { 0 }; 
    blend.BlendOp = AC_SRC_OVER; 
    blend.SourceConstantAlpha = 255; 
    blend.AlphaFormat = AC_SRC_ALPHA; 

    // Composite the canvas with the screen into the layered window 
    POINT ptZero = { 0 }; 
    UpdateLayeredWindow(hwnd_, hdcScreen, &ptOrigin, &sizeSplash, 
     hdcMem, &ptZero, RGB(0, 0, 0), &blend, ULW_ALPHA); 

    // Delete temporary objects used for canvas 
    SelectObject(hdcMem, hbmpOld); 
    DeleteObject(bmMem); 
    DeleteDC(hdcMem); 
    ReleaseDC(NULL, hdcScreen); 

    // Update mouse hit-test coordinates 
    GetWindowRect(hwnd_, &rcMousedown_); 
} 

3つのビットマップで構成レイヤードウィンドウが画面上に次のようになります。 - しかし、私は画像:(ここ

を投稿するのに十分な評判を持っていないリンクだと思う - http://i.stack.imgur.com/HmU7H.png

関連する問題