实现文字跟随鼠标移动--[转]
可能首先会想到SetROP2()函数,利用这个函数在鼠标移动的时候将上次的文字擦除再显示当前文字,可SetROP2()对于DrawText()输出文本不起作用,因
为其没有用到画笔,所以SetROP2()可以用来当作“橡皮线”而不是整块“橡皮”......
一种实现方法:在鼠标移动事件函数中绘制文字,首次产生鼠标移动事件的时候先保存要输出的文字区域的背景,然后在文字区域输出文字,以后的鼠标
事件发生后则先利用保存的原文字区域的背景去除原文字区域的文字(即绘制原文字区域背景到原文字区域),然后再保存要输出的文字区域的背景,然
后在文字区域输出文字。
多说一点,鼠标移动事件函数OnMouseMove的第一个参数nFlags为一些特定的按键是否被按下的标志,
MK_CONTROL Set if the CTRL key is down.
MK_LBUTTON Set if the left mouse button is down.
MK_MBUTTON Set if the middle mouse button is down.
MK_RBUTTON Set if the right mouse button is down.
MK_SHIFT Set if the SHIFT key is down.
eg:
void Cmfc_testDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if(nFlags == MK_LBUTTON) { ...... } if(nFlags == (MK_CONTROL | MK_SHIFT)) { ...... } ...... CDialogEx::OnMouseMove(nFlags, point); }
以下为实现代码:
//保存指定区域的背景到参数MemBitmap void ScreenShot(CBitmap *MemBitmap, CDC* pDC, int Xcoords, int Ycoords, int Width, int Height) { CDC memDC; memDC.CreateCompatibleDC(pDC); MemBitmap->CreateCompatibleBitmap(pDC, Width, Height); memDC.SelectObject(MemBitmap); memDC.BitBlt(0, 0, Width, Height, pDC, Xcoords, Ycoords, SRCCOPY); memDC.DeleteDC(); } //鼠标移动事件函数 void CXXXDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 CClientDC cdc(this); if(!m_first_show_flag) { m_OldX = point.x+10; m_OldY = point.y-20; m_MemBitmap.DeleteObject(); ScreenShot(&cdc, &m_MemBitmap, m_OldX, m_OldY, 110, 50);//保存要输出的文字区域的背景图片 cdc.SetBkMode(TRANSPARENT); CString strPointMove; strPointMove.Format(_T("%d, %d"), point.x, point.y); cdc.DrawText(strPointMove, CRect(m_OldX,m_OldY, m_OldX+110, m_OldY+50), DT_LEFT);//在文字区域输出坐标 m_first_show_flag = true; } else { BITMAP bm; m_MemBitmap.GetObject (sizeof(BITMAP), &bm); CDC MemDC; MemDC.CreateCompatibleDC(&cdc); CBitmap *pOldBitmap=MemDC.SelectObject(&m_MemBitmap); cdc.BitBlt(m_OldX, m_OldY, bm.bmWidth , bm.bmHeight, &MemDC, 0, 0, SRCCOPY);//利用保存的原文字区域的背景图片去除原来文字区域的 文字 MemDC.SelectObject(pOldBitmap); MemDC.DeleteDC(); m_OldX = point.x+10;//新坐标作为下次使用的前一次坐标 m_OldY = point.y-20; m_MemBitmap.DeleteObject(); ScreenShot(&cdc, &m_MemBitmap, m_OldX, m_OldY, 110, 50);//保存要输出的文字区域的背景图片 cdc.SetBkMode(TRANSPARENT); CString strPointMove; strPointMove.Format(_T("%d, %d"), point.x, point.y); cdc.DrawText(strPointMove, CRect(m_OldX, m_OldY, m_OldX+110, m_OldY+50), DT_LEFT);//在文字区域输出坐标 } CDialog::OnMouseMove(nFlags, point); }
在实际运行中发现,如果窗口为自绘,比如在OnPaint()中整个窗口被绘制成了白色,那么窗口显示的时候,如果鼠标在当前窗口区域则会出现文字区域
背景没有自绘的情况,我猜是窗口显示的时候如果鼠标在当前窗口则会产生鼠标移动事件,而窗口重绘事件在其后产生,即先进入OnMouseMove(),再进
入OnPaint(),所以才导致这种情况。一个解决方法就是设置一个全局或成员标志,当自绘完成后设置该标志为真,在OnMouseMove中先判断该标志,如果
为假的话则什么都不做。
参考原文:http://www.cnblogs.com/lcyty/p/3327237.html#commentform,作者Ginsan