2009-10-24 111 views
0

我在寫一個控件,它的某些部分可能有透明或半透明。基本上這個控制顯示一個PNG圖像(與alpha通道)。控件的父窗口上有一些圖形。因此,要使png控件正確呈現,需要獲取父窗口在其下面繪製的圖像。父對話框可能會設置WS_CLIPCHILDREN標誌,這意味着父窗口不會在png控件下繪製任何東西,在這種情況下,png控件將無法正常工作。 此控件也必須在Windows Mobile上工作,所以它不能有WS_EX_TRANSPARENT透明子控件

回答

0

有趣的你應該問。我昨天寫了代碼來做這件事。它位於Project Resistance的代碼庫中。看看ResistorView(具有透明度的PNG)如何與MainForm(具有背景圖像)進行交互。

0

我沒有在做C#,所以我不認爲這可能會有所幫助。我試圖查看你的代碼,即使你完成了和我一樣的任務,我也沒有看到任何可以解決我的問題的東西。 爲了給出更多細節,我的控件還支持gif動畫,並且我也使用了與您的項目中相同的來自流的IImage加載。根據我的經驗,來自流的IImage加載是令人難以置信的垃圾代碼,速度非常慢。我不知道這可能會如此緩慢。加載32x32 gif與31幀需要1.5secods使用垃圾IImage的東西。我寫了自己的加載器(使用一些開源的gif庫),沒有任何優化,整個gif幀的解碼/加載需要不到100ms。我正在使用TouchPro2 ......我無法想象這種代碼在低端設備上的表現有多糟糕。

作爲一個快速替代這裏有一個可能的解決我的問題:

在繪製圖像(GIF或PNG)的子控件的WM_PAINT處理

我做到以下幾點:

第一,我稱之爲SetRedraw (假)在自己和父窗口。 然後我隱藏子控件,併發送WM_PAINT父窗口與可選的HDC(作爲wParam)。父窗口將所有內容渲染到離屏位圖(通過hdc傳遞給WM_PAINT),並且在WM_PAINT成功返回後,我獲取離屏位圖的相關部分。 然後,我啓用顯示子窗口並在子窗口和父窗口上調用SetRedraw(true)。這個技巧很有效,但有一些明顯的缺點(我需要創建一個巨大的離屏位圖來捕捉整個屏幕區域,即使我需要父窗口中間的32x32像素)。

的代碼如下:

bool pic_control::get_parent_bg(MyBitmap & bg) 
{ 
    CWindow parent = GetParent(); 
    CClientDC dc(parent); 
    bool is_visible = IsWindowVisible() && parent.IsWindowVisible(); 
    if(!is_visible){ 
     return false; 
    } 

    parent.SetRedraw(false); 
    SetRedraw(false); 

    CRect rect; 
    parent.GetClientRect(rect); 
    MyBitmap bmp; 
    bmp.create(rect.Width(), rect.Height()); 

    ShowWindow(SW_HIDE); 
    parent.SendMessage(WM_PAINT, (WPARAM)(HDC)bmp.dc()); 
    ShowWindow(SW_SHOW); 

    GetWindowRect(rect); 
    parent.ScreenToClient(rect); 
    bg.create(rect.Width(), rect.Height()); 
    bg.dc().BitBlt(0, 0, rect.Width(), rect.Height(), bmp.dc(), rect.left, rect.top, SRCCOPY); 

    IF_DEBUG SAL::saveHBITMAPToJpeg(bg.GetBitmap(), "frames/BG.jpg", 100); 

    SetRedraw(true); 
    parent.SetRedraw(true); 
    return true; 
} 
0

WS_CLIPCHILDREN被迫在WINCE,你不能切換它。我不知道爲什麼,也許這是出於性能原因。 從我的經驗,我在這種情況下做了什麼。 1)如果父窗口bacgkround是動態的(例如包含地圖的窗口,它可以被移動),那麼它首先被繪製到內存畫布上,然後被繪製到屏幕上,內存畫布被保存並用於繪製透明的孩子。內存畫布不會包含空洞來代替子窗口,所以它可以用於進一步的像素合併。這裏的缺點是在內存中保存畫布的內存消耗。 2)如果父窗口背景是靜態的(對話框,菜單等),那麼你可以製作非窗口孩子。

class CImageButton 
{ 
public: 
bool IsPointInside(POINT pt); 
void OnPaint(HDC canvas); 
void OnClick(); 
void SetRect(RECT& rc); 
private: 
RECT m_rc; 
}; 

你的父窗口將包含這樣的對象的陣列和重定向WM_PAINT和 鼠標點擊他們。

該缺點是需要添加到父窗口的附加代碼,但是您可以爲所有父窗口創建一個基類,這將處理非窗口控件的問題。