我想实现一个可拖动的子窗口,拖动的时候半透明,半透明是通过带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内容,但是不知道具体怎么弄,,,,如果解决,小弟另开一贴散分,见者有份,,,,,
透明 子窗口 可拖动三个条件中,任何两个的组合我都可以实现,就是不能实现三个同时满足,,要不就是背景不能刷新,,要不就是闪烁严重,
至于双缓冲,裁剪重绘区域,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内容,但是不知道具体怎么弄,,,,如果解决,小弟另开一贴散分,见者有份,,,,,
移动到指定位置后,
去掉 WS_EX_LAYERED, 设置 WS_CHILD 风格,设置父窗口
仅供参考
注:楼主ID是我同事的ID,,呵呵,
也就是说子窗口不能真正意义上的透明,事实上也不能是异形建议用popup类型的窗口模拟.或者在拖动的时候临时制定为popup类型,结束后在设回child可以实验下,让子窗口不画背景,在OnErabkg里面画那个半透明的PNG图片,为避免闪烁父窗口更改属性为
ModifyStyle( WS_CLIPSIBLINGS, WS_CLIPCHILDREN );仅供参考
如果有这个标志,那移动时就会闪烁,如果没有这个标识则不会重画背景,我就想能不能利用
BeginDeferWindowPos
DeferWindowPos
EndDeferWindowPos
三个函数来替换SetWindowPos,然后高效的重画来避免闪烁,,不知道哪位有没有这个经验?
楼上所说的Layered Widnow我已经实现了,PS CS4就是这样做的,,但是,如果不用LAYERED WIDNOW而直接用带ALPHA通道的PNG做背景,那么透明度可以通过替换PNG图片来实现,不必更改程序代码,岂不是更灵活?
各位还有何高见?
DeferWindowPos
EndDeferWindowPos 是正确的,网上有很多例子,在Google上搜一下,一大堆
MSDN:A locked window cannot be moved. ??????哪位兄台能实作一份?
WM_ERASEBKGND: 直接return TRUE;
在WM_PAINT里面 DrawImage(...);
如果父窗口具有WS_CLIPCHILDREN风格,则刷新子窗口时,必须先GetParent()->InvalidateRect(...);
或者还有一个组合窗口的属性,设置这个的话WINDOWS会优化重绘,最先绘制底层窗口,依次往上重绘,
这个网上很多的,,搜一下就有了,不过最好注意重绘的效率,我贴出来的代码就是一个优化,,但是优化还不彻底,,。
建议设置WS_CLIPCHILDREN风格,子窗口刷新时,手动刷新父窗口,这样重画时不会因为父子窗口不在同一个周期内完成而造成的闪烁。
实现半透明的方法很多了,,CSDN有很多这种帖子,,