2009-10-24 79 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和 鼠标点击他们。

该缺点是需要添加到父窗口的附加代码,但是您可以为所有父窗口创建一个基类,这将处理非窗口控件的问题。