凌云窟
南山巅上火麟烈,北海潜深雪饮寒。可怜两锋未缘见,雪刀封隐孤剑鸣。
<2008年8月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

留言簿(0)

随笔分类

随笔档案

文章档案

相册

简历下载

搜索

最新评论

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-22 文章-0 评论-38 Trackbacks-0
        透明文本实现比较简单,也就是一个SetBkMode(TRANSPARENT),通过它一个应用程序就可以用透明文本,透明风格的线条和透明形状的刷子。

      用一个STATIC控件简单说明一下如何实现,我们需要在控件创建或者刷新的时候设置控件的“背景模式”,所以我们在控件父窗口的OnCtlColor处理函数中如下实现:

     
 HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
           HBRUSH hbr 
= CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
           
if(nCtlColor == CTLCOLOR_STATIC)
         
{
               pDC
->SetBkMode(TRANSPARENT);
           }

           
return hbr;
 }
      


     透明位图的实现方案是从codeguru上面看到的,我搜索了几遍,觉得“透明蔽屏”的方案比较好。这种方案是利用“光栅操作”实现的。
    
void DrawTransparen(CDC * pDC, int x, int y, COLORREF crColour/*transparent color*/)
{
  CDC dcImage, dcTrans;

  
// Create two memory dcs for the image and the mask
  dcImage.CreateCompatibleDC(pDC);
  dcTrans.CreateCompatibleDC(pDC);

       
// Select the image into the appropriate dc
  CBitmap* pOldBitmapImage = dcImage.SelectObject(this);

       
// Create the mask bitmap
  CBitmap bitmapTrans;
  
int nWidth = Width();
  
int nHeight = Height();
  bitmapTrans.CreateBitmap(nWidth, nHeight, 
11, NULL);

  
// Select the mask bitmap into the appropriate dc
  CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);

  
// Build mask based on transparent colour
  dcImage.SetBkColor(crColour);
  dcTrans.BitBlt(
00, nWidth, nHeight, &dcImage, 00, SRCCOPY);

  
// Do the work - True Mask method - cool if not actual display
  pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 00, SRCINVERT);
  pDC
->BitBlt(x, y, nWidth, nHeight, &dcTrans, 00, SRCAND);
  pDC
->BitBlt(x, y, nWidth, nHeight, &dcImage, 00, SRCINVERT);

  
// Restore settings
  dcImage.SelectObject(pOldBitmapImage);
  dcTrans.SelectObject(pOldBitmapTrans);
}




    看
HateMath的一篇随笔《Static控件背景透明时文字覆盖问题的解决方案 》,里面提到这样一个问题:
    static控件设置“透明”后,再更改文字时会与之前的文字覆盖,怎么解决?
pDC->SetBkMode(TRANSPARENT)
 设置透明后,要改变控件的文字就会发生文字重叠,如果不使用透明就不会,
请问在透明状态下改变文字如何不发生重叠?

    首先,有必要介绍一下SetBkMode(TRANSPARENT),通过它一个应用程序就可以用透明文本,透明风格的线条和透明形状的刷子。
    在HateMath的实例代码中,实际上可以不使用RedrawWindow使对话框窗口重绘,只需要在OnCtlColor中为STATIC控件的背景提供一个有效的画刷。
  实际上,在我的实践过程中,只要两个窗口存在相交,也就是上面的窗口遮住了下面窗口的某一部分,如果上面的窗口使用SetBkMode(TRANSPARENT),则在两个窗口相交的区域就会出现文字重叠的现象。
   HateMath兄认为SetBkMode(TRANSPARENT)后上面窗口的文字实际上是画在下面的窗口上的!使用下面窗口的RedrawWindow可以解决我们的问题。
     
     另一个解决的方案就是利用双缓冲,用代码来说话吧!
 /**************************************************************/
 
/* pDC为上面窗口的CDC * */
 
CDC dcMem;
 CBitmap bmpCache;
 CRect rc;
 GetClientRect(rc);
 bmpCache.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
 dcMem.CreateCompatibleDC(pDC);
 CBitmap 
*pOldBmp = dcMem.SelectObject(&bmpCache);
 dcMem.SetBkMode(TRANSPARENT);

  
static bool ss = false;
 
if (ss == false)
  dcMem.TextOut(
1020"xxx");
 
else
  dcMem.TextOut(
1020"yyyy"); 

 pDC
->BitBlt(0,0,rc.Width(),rc.Height(),&dcMem,0,0,SRCCOPY);
 dcMem.SelectObject(pOldBmp);
 /**************************************************************/  

  可以把上面的代码周期执行,结果是两个TextOut操作的结果相互之间不会产生任何影响。

    鉴于双缓冲能够解决这个问题,我怀疑HateMath的观点“文字实际上是画在下面的窗口上的”的结论!因为在双缓冲的情况下,我们不需要刷新下面的窗口。那位有没有关于这个问题权威一点的解释,在此拜求!!



------------------------------------------------------------
   附录:
   1、UpdateWindow和RedrawWindow允许同步绘制。如果更新区域非空,UpdateWindow直接给这个窗口发送WM_PAINT消息。RedrawWindow也发送WM_PAINT消息,但就如何绘制窗口给了应用程序更多的控制,例如是否绘制非客户区和窗口背景,是否不管更新区域空与非空都发送消息。
   2、父子关系的窗口的裁剪以及兄弟子窗口的裁剪分别表述为WS_CLIPCHILDREN和WS_CLIPSIBLINGS。使用前者创建父窗口表示在父窗口进行绘制时,子窗口占据的空间是排除在外的。使用后者创建的兄弟子窗口之间的绘制不会相互影响。
posted on 2006-05-06 21:36 莫问春秋 阅读(1854) 评论(2)  编辑 收藏
Comments
  • # re: 双缓冲解决“透明窗口”文字覆盖的问题
    pAnic
    Posted @ 2006-05-07 09:28
    双缓冲。。呵呵~
  • # re: 透明文本、位图的实现方案
    yaowei
    Posted @ 2008-08-04 10:37
    双缓冲的确不是画在父窗口,之所以透明,是因为内存dc背景为父窗口背景.
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]