我想实现一个可拖动的子窗口,拖动的时候半透明,半透明是通过带ALPHA通道的PNG图片贴出来的,
透明 子窗口 可拖动三个条件中,任何两个的组合我都可以实现,就是不能实现三个同时满足,,要不就是背景不能刷新,,要不就是闪烁严重,
至于双缓冲,裁剪重绘区域,SetLayeredWindowAttributes,那些方法我都试过,不能同时满足三个条件,不知道是不是我的代码有问题,,将关键代码贴上来,,请各位帮小弟看看:
                  绘图的关键代码
template<class windowT>
class Drawer{
protected:
Bitmap  *m_pMemBitmap;
CachedBitmap *m_pCachedBitmap;
Graphics     *m_pMemGraphic; BOOL m_blDirty; windowT *m_pTargetWnd;public:
// 此处省略。
protected:
BOOL Draw(Graphics& g)
{
if(!m_pMemBitmap || m_blDirty)
{
if(m_blDirty)
{
if(m_pMemBitmap)
::delete m_pMemBitmap;
if(m_pMemGraphic)
delete m_pMemGraphic;
if(m_pCachedBitmap)
delete m_pCachedBitmap;
}

CRect rcWindow;
 m_pTargetWnd->GetClientRect(rcWindow); m_pMemBitmap = ::new Bitmap(rcWindow.Width(), rcWindow.Height());
m_pMemGraphic = Graphics::FromImage(m_pMemBitmap);
if(!m_pTargetWnd->Draw(*m_pMemGraphic))
{
m_pCachedBitmap = 0;
return FALSE;
}else
m_pCachedBitmap = new CachedBitmap(m_pMemBitmap, &g); m_blDirty = FALSE;
} if(!m_pCachedBitmap)
return FALSE; if(Gdiplus::Ok != g.DrawCachedBitmap(m_pCachedBitmap, 0, 0))
return FALSE; return TRUE;
};
};
如果建议用:
BeginDeferWindowPos
DeferWindowPos
EndDeferWindowPos
请提供详细的代码,,因为我也想这么做来组织重绘,将子窗口的类风格置成CS_OWNDC,然后禁止重画,只是移动后提交原来的DC内容,但是不知道具体怎么弄,,,,如果解决,小弟另开一贴散分,见者有份,,,,,

解决方案 »

  1.   

    没试过,给一个假想思路:子窗口开始拖动时,去掉其 WS_CHILD 风格,设置 WS_EX_LAYERED 风格, 然后调用SetLayeredWindowAttributes 设置透明度, 
    移动到指定位置后,
    去掉 WS_EX_LAYERED, 设置 WS_CHILD 风格,设置父窗口
    仅供参考
      

  2.   

    楼上的大哥,先谢了,,这个思路我做过,也确实是可行,并补充一下:开始移动之前SetParent(NULL),, 移动后,SetParent(m_pParent),,移动中,裁剪窗口可视区域。改变框架属性后,调用SetWindowPos生效,具体参数查看MSDN,这个方法是可以,但是不是我要的效果啊,并且也比较麻烦,,我想看看有没有简单一点的办法,既然楼上的大哥提出来了,就顺便把我已经试验过的结果作为补充,供大家讨论一下,,,,
    注:楼主ID是我同事的ID,,呵呵,
      

  3.   

    WS_EX_LAYERD 不能应用为child窗口的属性
    也就是说子窗口不能真正意义上的透明,事实上也不能是异形建议用popup类型的窗口模拟.或者在拖动的时候临时制定为popup类型,结束后在设回child可以实验下,让子窗口不画背景,在OnErabkg里面画那个半透明的PNG图片,为避免闪烁父窗口更改属性为
    ModifyStyle( WS_CLIPSIBLINGS,  WS_CLIPCHILDREN );仅供参考
      

  4.   

    SetWindowPos中有一个这样的标识:SWP_NOCOPYBITS
    如果有这个标志,那移动时就会闪烁,如果没有这个标识则不会重画背景,我就想能不能利用
    BeginDeferWindowPos 
    DeferWindowPos 
    EndDeferWindowPos 
    三个函数来替换SetWindowPos,然后高效的重画来避免闪烁,,不知道哪位有没有这个经验?
    楼上所说的Layered Widnow我已经实现了,PS CS4就是这样做的,,但是,如果不用LAYERED WIDNOW而直接用带ALPHA通道的PNG做背景,那么透明度可以通过替换PNG图片来实现,不必更改程序代码,岂不是更灵活?
    各位还有何高见?
      

  5.   

    拖动的时候 LockWindowUpdate()
      

  6.   

    用BeginDeferWindowPos 
    DeferWindowPos 
    EndDeferWindowPos  是正确的,网上有很多例子,在Google上搜一下,一大堆
      

  7.   


    MSDN:A locked window cannot be moved. ??????哪位兄台能实作一份?
      

  8.   

    楼主能否给个代码,告诉我怎样实现child窗口透明
      

  9.   


    WM_ERASEBKGND: 直接return TRUE;
    在WM_PAINT里面 DrawImage(...);
    如果父窗口具有WS_CLIPCHILDREN风格,则刷新子窗口时,必须先GetParent()->InvalidateRect(...);
    或者还有一个组合窗口的属性,设置这个的话WINDOWS会优化重绘,最先绘制底层窗口,依次往上重绘,
    这个网上很多的,,搜一下就有了,不过最好注意重绘的效率,我贴出来的代码就是一个优化,,但是优化还不彻底,,。
    建议设置WS_CLIPCHILDREN风格,子窗口刷新时,手动刷新父窗口,这样重画时不会因为父子窗口不在同一个周期内完成而造成的闪烁。
      

  10.   


    实现半透明的方法很多了,,CSDN有很多这种帖子,,
      

  11.   

    要是需要自己去考虑如何merge背景那就没意思了,我以为子窗口可以简单的设定为某个   alpha植呢