透明文本实现比较简单,也就是一个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, 1, 1, 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(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);
// Do the work - True Mask method - cool if not actual display
pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, 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(10, 20, "xxx");
else
dcMem.TextOut(10, 20, "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。使用前者创建父窗口表示在父窗口进行绘制时,子窗口占据的空间是排除在外的。使用后者创建的兄弟子窗口之间的绘制不会相互影响。
发表于 莫问春秋 阅读(1699) | |
--------------------next---------------------
阅读(132) | 评论(0) | 转发(0) |