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在图片背景上实现文本跟随鼠标移动的更多相关文章

  1. 文本跟随鼠标并且显示x轴和y轴位置

    一.文本跟随鼠标并且显示x轴和y轴位置 代码如下: window.onload=function(){ var mydiv = document.createElement("div&quo ...

  2. java实现在图片上编辑文本内容

    package com.yin.text; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; impor ...

  3. EasyUI实现图片的上传后与其他文本框的提交以及DataGrid中图片的展示

    图片即文件,在jsp中文件上传很简单,一个type为file的input,一个form指定enctype为multipart/form-data,通过post提交到后台利用apache的commons ...

  4. C# 给PDF添加图片背景

    C# 给PDF添加图片背景 今天要实现的是给PDF文件添加图片背景这个功能.PDF是近年来最流行的文件之一,无论是办公还是日常生活中都经常会用到,很多时候,PDF文件的背景色都是白色,看多了难免觉得累 ...

  5. android 自定义scrollview 仿QQ空间效果 下拉伸缩顶部图片,上拉回弹 上拉滚动顶部title 颜色渐变

    首先要知道  自定义scrollview 仿QQ效果 下拉伸缩放大顶部图片 的原理是监听ontouch事件,在MotionEvent.ACTION_MOVE事件时候,使用不同倍数的系数,重置布局位置[ ...

  6. C#从Image上读取文本

    今天通过C#来实现一个读取Image上文本的功能. 1. 环境准备: 1). 下载 Microsoft Office SharePoint Designer 2007. 2). 安装请参考KB:htt ...

  7. OneThink实现多图片批量上传功能

    OneThink原生系统中的图片上传功能是uploadify.swf插件进行上传的,默认是只能上传一张图片的,但是uploadify.swf是支持多图片批量上传的,那么我们稍加改动就可实现OneThi ...

  8. jquery 图片背景透明度(支持IE5/IE6/IE7)

    设置背景图片,以突出透明度的效果及jquery png背景透明插件实例教程 <head> <title>toggle()</title> <style typ ...

  9. 用shader使图片背景透明

    转自:http://blog.csdn.net/dawn_moon/article/details/8631783 好吧,终于抽时间写这篇文章了. 手头上有很多人物行走图,技能特效图等,但这些图都有个 ...

随机推荐

  1. 电脑c盘清理

    https://www.cnblogs.com/btchenguang/archive/2012/01/20/2328320.html

  2. 推荐一款稳定快速免费的前端开源项目 CDN 加速服务

    前面学习到什么是CDN,全称是Content Delivery Network,即内容分发网络.CDN的通俗理解就是网站加速,CPU均衡负载. CDN的基本思路是尽可能避开互联网上有可能影响数据传输速 ...

  3. 【Struts2三】拦截器

    拦截器:就是在訪问action之前.对其进行拦截!能够在拦截器中做一些逻辑的处理! 比方权限验证.没有权限就不给予訪问! 拦截器等效于servlet中的过滤器! 使用拦截器步骤: 1.定义自己的拦截器 ...

  4. BP神经网络公式推导及实现(MNIST)

    BP神经网络的基础介绍见:http://blog.csdn.net/fengbingchun/article/details/50274471,这里主要以公式推导为主. BP神经网络又称为误差反向传播 ...

  5. POJ 1201 Intervals || POJ 1716 Integer Intervals 差分约束

    POJ 1201 http://poj.org/problem?id=1201 题目大意: 有一个序列,题目用n个整数组合 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai, ...

  6. Log Explorer 使用说明(原创)

    关于Log Explorer (我抄的) 介绍Log Explorer主要用于对MSSQLServer的事物分析和数据恢复.你可以浏览日志.导出数据.恢复被修改或者删除的数据(包括执行过update, ...

  7. 推荐一下《聊聊JVM》的专栏

    依照惯例新开了一个专栏后要单推一下.推荐一下<聊聊JVM的专栏>,网上关于JVM的文章太多,这个专栏希望能在已有的资料的基础上写出点新意,对一些重要的概念归纳总结,说说自己的观点.理解和实 ...

  8. UI组件之AdapterView及其子类关系,Adapter接口及事实上现类关系

    AdapterView本身是一个抽象基类,它派生的的子类在使用方法上十分类似.AdapterView直接派生的三个子类:AbsListView.AbsSpinner,AdapterViewAnimat ...

  9. Android系统开发(5)——Eclipse for C/C++

    一.下载JDK 官方下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 二 ...

  10. 10、V4L2摄像头获取单幅图片测试程序(MMAP模式)

    #include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h> ...