[MFC]SDI在图片背景上实现文本跟随鼠标移动
SDI是单文档接口应用程序的简称。本文要实现的是在视图区域显示一张图片,然后在图片表层显示文字,并且文字跟随鼠标移动。思考一下,可以判断这个问题一共分为以下几个部分:1、显示图片;2、找到鼠标的位置;3、插入文字;4、自动移动文字。以下分步骤说明。
1、首先是使用“打开”方式打开一张图片并显示,出于方便这里仅仅针对bmp格式的图片,具体是在CYourView类内部的OnDraw函数内添加如下代码:
if(GetDocument()->GetPathName() != "")//载入图片
{
HBITMAP bitmap;
bitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
GetDocument()->GetPathName(), IMAGE_BITMAP, , ,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
HBITMAP OldBitmap;
CBitmap cbitmap;
cbitmap.Attach(bitmap);
cbitmap.GetBitmap(&m_bitmap); CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CRect rect;
GetClientRect(&rect);
OldBitmap = (HBITMAP)MemDC.SelectObject(bitmap);
pDC->BitBlt(, , m_bitmap.bmWidth, m_bitmap.bmHeight, &MemDC, , , SRCCOPY);
MemDC.SelectObject(OldBitmap);
MemDC.DeleteDC();
}
其中m_bitmap是一个BITMAP对象。显示图片的方法是比较常见的,这里不再说明。
2、接下来需要知道有个消息处理函数OnMouseMove用来处理鼠标移动消息。所以首先要添加这个函数,这个可以在Class Wizard中找到。先添加这个函数。
OnMouseMove(UINT nFlags, CPoint point);
这个函数的第二个参数CPoint对象就是鼠标所在位置,可以使用如下方法找到对应坐标:
Xcoords = point.x;
Ycoords = point.y;
3、然后就要插入文字了,在SDI中特定位置插入文字其实很简单,使用CDC->DrawText方法就可以实现。这个函数可以实现在指定的矩形框内添加格式化文本,有点像word中的插入对话框。具体语法如下:
int DrawText(const CString& str, LPRECT lpRect, UINT nFormat);
第一个参数是要输出的CString对象,第二个参数是显示文本的矩形区域,最后一个参数是文本的格式,比如居左居中等,一个使用例子如下:
CClientDC cdc(this);
cdc.DrawText("text", CRect(left, top, reight, bottom), DT_LEFT);
4、插入文字实现之后,就要进行文字的移动了。首先我想到的是SDI中图形的移动。比如画一个矩形CDC->Rectangle方法,然后移动这个矩形框。有一个常用的图形移动方式是进行异或画图,即使用CDC->SetROP2(R2_XORPEN)这个方法画图。使用与原来画笔异或屏幕颜色再画一遍,可以实现清除已画图形的效果,因此图形的移动也就是如下过程:
(1)异或画图
(2)在原位置再次异或画图
(3)在新位置异或画图
(4)...
把画图与OnMouseMove结合就能容易实现图形跟随鼠标移动。但是同样的方法可以用于文本的移动吗?答案是否定的。因为DrawText与其他画图函数有本质的区别,因为其没有用到画笔,所以SetROP2这个方法整个对文本没有效果。不过,有了移动图形的方法,可以容易想到所谓移动(图形或者文本)的本质其实就是首先把原位置的内容清除,然后在新位置重新画(好像是废话)。
因此,移动文字的关键就在于如何把原位置的文字清除。(用DrawText插入一个空文本的方法实行不同的,因为不会影响已经插入的文本。)一个容易想到的方法是将原位置(DrawText对应的矩形)整个复制下来,然后在插入文字后重新绘制上去,就用覆盖的方式清除了文字。于是有了如下的方法。
首先添加一个截图函数,叫做ScreenShot。
CBitmap* CYourView::ScreenShot(CDC* pDC, CBitmap *memBitmap, int Xcoords, int Ycoords, int Width, int Height)
{
CDC memDC;
memDC.CreateCompatibleDC(pDC); memBitmap->CreateCompatibleBitmap(pDC, Width, Height);
memDC.SelectObject(memBitmap);
memDC.BitBlt(, , Width, Height, pDC, Xcoords, Ycoords, SRCCOPY);
memDC.DeleteDC(); return memBitmap; }
这个函数的处理过程很简单,将指定位置和大小的矩形内部的图片内容保存起来。
具体的实现文本跟随鼠标移动的代码在OnMouseMove函数中:
void CYourView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CClientDC cdc(this);
Xcoords = point.x;
Ycoords = point.y;
if(m_loaded_flag)
{
if(m_first_show_flag == false)
{ OldX = Xcoords+;
OldY = Ycoords-;
memBitmap.DeleteObject();
memBmp = ScreenShot(&cdc, &memBitmap, OldX, OldY, , ); cdc.SetBkMode(TRANSPARENT);
cdc.DrawText("text",CRect(OldX,OldY, OldX+, OldY+),DT_LEFT);
m_first_show_flag = true;
}
else
{
cdc.SetBkMode(TRANSPARENT);//去除原来位置的文字
BITMAP bm;
memBmp->GetObject (sizeof(BITMAP),&bm);
CDC MemDC;
MemDC.CreateCompatibleDC(&cdc);
CBitmap *pOldBitmap=MemDC.SelectObject(memBmp);
cdc.BitBlt(OldX,OldY,bm.bmWidth ,bm.bmHeight,&MemDC,,,SRCCOPY);
MemDC.SelectObject (pOldBitmap);
MemDC.DeleteDC(); //新坐标作为下次使用的前一次坐标
OldX = Xcoords+;
OldY = Ycoords-;
memBitmap.DeleteObject();
memBmp = ScreenShot(&cdc, &memBitmap, OldX, OldY, , );
cdc.DrawText("text",CRect(OldX, OldY, OldX+, OldY+),DT_LEFT);//在新位置添加文字 } } CScrollView::OnMouseMove(nFlags, point);
}
由于第一次鼠标放上去的状态跟后面的移动状态有点区别,说以代码中分开处理,因此还需要在OnDraw函数中if(GetDocument()->GetPathName() != "")语句内添加如下内容:
m_loaded_flag = true;
if(m_first_show_flag == true)
{
Invalidate();
m_first_show_flag = false;
}
当载入图片后才显示跟随鼠标的文字。并且当移动图片时刷新以清除文字。
总的来说整个过程是比较简单的,曾经看到过一个采用OnTimer实现的文字跟随鼠标移动的例子,其实就是不断地刷新屏幕来显示不同的文字,当有背景图时会出现严重的闪烁,需要采用其他方法来避免闪烁,但是使用我的方法就没有这个问题。一小部分的重绘在视觉上是没有影响的。
另外要注意使用到CDC对象的回收,如果使用CDC *pDC = this->DetDC()这样的方法创建一个设备上下文则需要在不用的时候使用pDC->DeleteDC()删除DC,不然就会导致严重的内存泄露。但是使用CClientDC cdc(this)创建的CDC对象系统能够自动回收,所以以上代码中采用的是这种方法。
[MFC]SDI在图片背景上实现文本跟随鼠标移动的更多相关文章
- 文本跟随鼠标并且显示x轴和y轴位置
一.文本跟随鼠标并且显示x轴和y轴位置 代码如下: window.onload=function(){ var mydiv = document.createElement("div&quo ...
- java实现在图片上编辑文本内容
package com.yin.text; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; impor ...
- EasyUI实现图片的上传后与其他文本框的提交以及DataGrid中图片的展示
图片即文件,在jsp中文件上传很简单,一个type为file的input,一个form指定enctype为multipart/form-data,通过post提交到后台利用apache的commons ...
- C# 给PDF添加图片背景
C# 给PDF添加图片背景 今天要实现的是给PDF文件添加图片背景这个功能.PDF是近年来最流行的文件之一,无论是办公还是日常生活中都经常会用到,很多时候,PDF文件的背景色都是白色,看多了难免觉得累 ...
- android 自定义scrollview 仿QQ空间效果 下拉伸缩顶部图片,上拉回弹 上拉滚动顶部title 颜色渐变
首先要知道 自定义scrollview 仿QQ效果 下拉伸缩放大顶部图片 的原理是监听ontouch事件,在MotionEvent.ACTION_MOVE事件时候,使用不同倍数的系数,重置布局位置[ ...
- C#从Image上读取文本
今天通过C#来实现一个读取Image上文本的功能. 1. 环境准备: 1). 下载 Microsoft Office SharePoint Designer 2007. 2). 安装请参考KB:htt ...
- OneThink实现多图片批量上传功能
OneThink原生系统中的图片上传功能是uploadify.swf插件进行上传的,默认是只能上传一张图片的,但是uploadify.swf是支持多图片批量上传的,那么我们稍加改动就可实现OneThi ...
- jquery 图片背景透明度(支持IE5/IE6/IE7)
设置背景图片,以突出透明度的效果及jquery png背景透明插件实例教程 <head> <title>toggle()</title> <style typ ...
- 用shader使图片背景透明
转自:http://blog.csdn.net/dawn_moon/article/details/8631783 好吧,终于抽时间写这篇文章了. 手头上有很多人物行走图,技能特效图等,但这些图都有个 ...
随机推荐
- 程序中图片透明 函数(使用SetBkColor API函数)
void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart, short yStart, COLORREF c ...
- Altium Designer如何删除以布的线
- javascript的组成
ECMAScript:(3/5/6/7) 它是JS语言的标准,规定了JS的编程语法和基础核心知识. DOM:document object model 文档对象模型,提供给JS很多的操作页面中元素的属 ...
- Docker---(1)Docker 简介
原文:Docker---(1)Docker 简介 版权声明:欢迎转载,请标明出处,如有问题,欢迎指正!谢谢!微信:w1186355422 https://blog.csdn.net/weixin_39 ...
- 原生js大总结一
001.浅谈堆和栈的理解? js变量存储有栈存储和堆存储,基本数据类型的变量存储在栈中,引用数据类型的变量存储在堆中 引用类型数据的地址也存在栈中 当访问基础类型变量时,直接从栈中取值.当访问 ...
- Android ViewGroup使用小结
ViewGroup定义 在api中是这么描写叙述ViewGroup的:A ViewGroup is a special view that can contain other views. 依据意思我 ...
- 强力推荐微信小程序之简易计算器,很适合小白程序员
原文链接:https://mp.weixin.qq.com/s/gYF7GjTRpeZNoKPAPI9aXA 1 概述 前几日QQ群里的朋友问我有没有计算器小程序案例,今天我们说下小程序计算器,然后就 ...
- [Yarn] Use Yarn to Create an Alternative Import Name of an Installed Library
In this lesson we'll show how to use yarn to alias the names of same npm libraries but install diffe ...
- 并查集(disjoint set)的实现及应用
这里有一篇十分精彩.生动的 并查集详解 (转): "朋友的朋友就是朋友"⇒ 传递性,建立连通关系 disjoint set,并查集(一种集合),也叫不相交集,同时也是一种树型的数据 ...
- Cannot find module "element-ui/lib/theme-default/index.css"——解决办法
在vuejs中使用element-ui 1.安装 cnpm install style-loader --save-dev cnpm install css-loader --save-dev cnp ...