Chinaunix首页 | 论坛 | 博客
  • 博客访问: 368475
  • 博文数量: 715
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:46
文章分类

全部博文(715)

文章存档

2011年(1)

2008年(714)

我的朋友

分类:

2008-10-13 16:31:29

        透明文本实现比较简单,也就是一个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);
}




    看
的一篇随笔《 》,里面提到这样一个问题:
    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 莫问春秋 阅读(1699)   

--------------------next---------------------

阅读(160) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~