Software 版 (精华区)
发信人: checcy (老巴夺), 信区: Software
标 题: 设备场境(DC)在GDI中的应用
发信站: 哈工大紫丁香 (Sat Apr 11 13:20:17 1998), 转信
设备场境(DC)在GDI中的应用
□成都 李火亘
现在有很多Windows开发工具,如Borland
C++、Visual C++,都对Windows图形设备界面(GDI)
进行了封装,这使得对Windows图形进行操作相当方便,可
以使用大量现成的GDI类,通过少许代码,就可以完成很强
大的功能。譬如,在Borland C++中,对于大量的文本或很
大的一幅位图,要想加入滚动功能是非常简单的,只需初始
化TScroller类的一个内部变量,并且把窗口的风格设为可滚
动的即可。本文通过一个放大镜实例来说明Windows设备场境
类的应用(使用Borland C++ 开发工具)。
本程序演示了一个桌面上的放大镜,运行以后出现一个窗口及
一个放大镜。你可以在桌面上移动放大镜,经过放大后的图像
出现在窗口中,还可把此程序加入到其他程序中,这样,得到
的程序就具有了放大浏览功能。
在Borland C++中,提供了很多设备场境类,如TWindowDC,
TMemoryDC, TScreenDC等。这些类的基类都是TDC。每个类继
承了基类的特征,并且每个类又扩展了各自的功能。本程序主
要用到了TMemoryDC, TScreenDC, 以及TClientDC。TClientDC
提供进入某个窗口客户区的句柄,通过这个句柄,就可直接进入
绘图区进行绘图。TScreenDC提供了进入屏幕位图的直接句柄,
通过它,就可获得屏幕位图。而TMemoryDC提供了进入内存场境
的句柄,这个类相当有用,当你想产生动画效果时,可先在内存
位图中绘图,然后把位图传输到屏幕当前设备场境中,即可达到
无延迟的显示了。
程序一开始构造框架窗口,并且声明了一些成员变量和成员函数
,以及消息响应表。消息响应表是用来把消息和消息响应函数链
接起来。接下来,建立应用程序实例,并且重载了虚函数
InitMainWindow(),此函数主要用于创建主窗口,及设立窗口风
格、光标类型。下面的OwlMain() 函数启动应用程序。再下来定
义了消息响应表,把事件与响应函数链接起来。程序的主体在
EvMouseMove() 函数中,首先用SetCapture() 来捕获鼠标移动
事件,以使鼠标移动事件得到正确处理。下面定义了TScreenDC和
TClientDC两个设备场境句柄,ClientToScreen() 函数将鼠标坐
标从客户区坐标转化为屏幕坐标,只有这样窗口才能捕获所有的
鼠标事件(包括窗口之外的)。TBitmap类用于构造一个位图,其
大小为120 ( 120像素),此位图被选入内存场境中。这样,只要
作图时选用内存场境句柄,则所画内容就被记录在此位图中,要
对所画内容进行修改,比如放大,缩小等,就可直接对此位图进
行。PatBlt()函数用来对内存位图进行填色。获取屏幕上的图像
并转化为位图是通过GetPixel() 和SetPixel() 函数实现的,此
两函数用于取得或设置像素颜色。对图像进行放大是通过函数
StretchBlt() 来进行的,这个函数对位图进行缩放。BitBlt()
函数把内存位图传送到当前屏幕上。只有通过内存位图作为中间
存储,才不会导致屏幕上有明显的延迟。除了源文件外,还需要
一个资源文件,其中包括一个光标资源,该资源用Borland C++
中的Resource WorkShop生成。这个光标就是一个放大镜形状,
需要注意的是,设计好光标后,应把它的“热点”(hot spot)设
立在放大镜的中心。本例所设计的放大镜的有效区为所画圆的内
接矩形,其长为14,宽为10。设计时可先画出圆,然后在其中找
到一个最合适的内接矩形,并根据屏幕提示找出其长和宽尺寸。
如果尺寸与本例不一致,请修改程序中EvMouseMove() 函数中的
GetPixel() 和SetPixel() 函数的参数,以适应实际需要。
下面附源程序:(本程序在Borland C++4.5版本下调试通过,
编译时请注意选择OWL类库)
#include<owl\applicat.h>
#include<owl\framewin.h>
#include<stdlib.h>
#include<stdio.h>
#include″draw.rh″ // draw.rh文件是建立资源时自
// 动产生的
class TDWin: public TFrameWindow{
public:
TDWin();
~TDWin()
{}
int n;
TBitmap bit1;
TMemoryDC memdc;
void EvLButtonDown(uint,TPoint& point);
void EvRButtonDown(uint,TPoint& point);
void EvMouseMove(uint,TPoint& point);
DECLARE_RESPONSE_TABLE(TDWin);
};
class TDApp : public TApplication{
public:
virtual void InitMainWindow()
{
TDWin frame=new TDWin();
SetMainWindow(frame);
frame->Attr.W=150;
frame->Attr.H=150;
frame->Attr.Style&
=~WS_MAXIMIZEBOX&~WS_MINIMIZEBOX;
frame->SetCursor(
GetMainWindow()->GetModule(),CURSOR_1);} };
int OwlMain(int ,char [])
{
return TDApp().Run();
}
DEFINE_RESPONSE_TABLE1(TDWin,TFrameWindow)
EV_WM_LBUTTONDOWN,
EV_WM_RBUTTONDOWN,
EV_WM_MOUSEMOVE,
END_RESPONSE_TABLE;
TDWin::TDWin(): TFrameWindow(0,″放大镜″){}
void TDWin::EvLButtonDown(uint, TPoint& point)
{
ReleaseCapture();}
void TDWin::EvRButtonDown(uint,TPoint& point)
{
PostQuitMessage(0);} //退出
void TDWin::EvMouseMove(uint,TPoint & point)
{
SetCapture();
TScreenDC sdc;
TClientDC dc(this);
TColor col;
ClientToScreen(point);
TBitmap bit2(dc,120,120);
TMemoryDC memdc(dc);
memdc.SelectObject(bit2);
memdc.PatBlt(0,0,120,120,WHITENESS);
for(int i=0;i<7;i++) //其中7代表有效区的长度
//的一半
for(int j=0;j<5;j++) //5代表有效区宽度的一半
{
col=sdc.GetPixel(point.x-j,point.y-i);
memdc.SetPixel(5-j,7-i,col);
col=sdc.GetPixel(point.x+j,point.y-i);
memdc.SetPixel(5+j,7-i,col);
col=sdc.GetPixel(point.x-j,point.y+i);
memdc.SetPixel(5-j,7+i,col);
col=sdc.GetPixel(point.x+j,point.y+i);
memdc.SetPixel(5+j,7+i,col);
}
memdc.StretchBlt(0,0,120,120,memdc,0,0,10,14);
dc.BitBlt(0,0,125,125,memdc,0,0);
memdc.RestoreBitmap();
}
--
Chengyan Che - Software Freelancer, Harbin, P.R.China
-----------------------------------------------------------
Do you need a software developer for your project or just
for your killer money-making idea? Drop me a line and let
me know how I can help you out!
mailto:checcy@public.hr.hl.cn
ICQ:5116726
--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: checcy@public.hr.hl.]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.407毫秒