位图

 

Bit-Block Transfer

相比图元文件,位图有两个大缺点,一是易受设备依赖性问题影响。比如在一个单色设备上显示位图经常不会令人满意;还有位图的缩放,经常涉及到行或列的重复或丢弃,这样会造成缩放位图的混乱。第二个缺点是位图占用存储空间大。然而,位图最大的优点是速度,显示位图要比图元文件快得多。

GetDeviceCaps的BITSPIXEL和PLANES参数获取显卡的颜色参数。

BitBlt(hdcDst,xDst,yDst,cx,cy,hdcSrc,xSrc,ySrc,dwROP):把hdcSrc(xSrc,ySrc,xSrc+cx,ySrc+cy)显示到hdcDst(xDst,yDst,xDst+cx,yDst+cy)。要用这个函数,两个DC必须兼容。

StretchBlt(hdcDst,xDst,yDst,cxDst,cyDst,hdcSrc,xSrc,ySrc,cxSrc,cySrc,dwROP):BitBlt只能按原始大小显示,StretchBlt可以拉伸位图。这个函数可以解决两个DC物理显示不同的问题。StretchBlt还可以翻转位图,把xDst改为xSrc+cxSrc,cxDst改为-cxSrc试试。

SetStretchBltMode(hdc,iMode):设置StretchBlt模式。当目标位图比原来位图小时,StretchBlt需要减少一些行或列,它有四种模式,由iMode指定。BLACKONWHITE或STRETCH_ANDSCANS(默认):把需要合并的像素按位与,用在白背景主要为黑色为主的位图较好。WHITEONBLACK或STRETCH_ORSCANS:按位或,用在黑底白图的位图。COLORONCOLOR或STRETCH_DELETESCANS:简单删除不要的像素,是彩色位图最好的模式。HALFTONE或STRETCH_HALFTONE:取平均值(以后介绍)。

GetStretchBltMode

 

ROP(Raster  Operation,Bitblt的最后一个参数)

BitBlt和StretchBlt并不是简单的复制,而是对三个图片做位操作:

1.Source 拉伸或压缩为目标位图大小

2.Destination 调用BitBlt或StretchBlt前的目标区域位图

3.Pattern 目标设备DC的画刷在水平或垂直重复绘制与目标区域大小相同的位图。

对这三个位图的变换有:

定义 操作

BLACKNESS 0

NOTSRCERASE ~(S|D)

NOTSRCCOPY ~S

SRCERASE S&~D

DSINVERT ~D

PATINVERT P^D

SRCINVERT S^D

SRCAND S&D

MERGEPAINT ~S&D

MERGECOPY P&S

SRCCOPY S

SRCPAINT S|D

PATCOPY P

PATPAINT P|~S|D

WHITENESS 1

PatBlt(hdc,x,y,cx,cy,dwROP):没有源位图,FillRect和InvertRect就用这个函数实现。

BitBlt、PatBlt和StretchBlt是GDI中仅有的以一个点、长和宽参数绘制矩形,其他函数都要以左上角和右下角坐标为参数。这三个函数中点可以是任意一个点的坐标,长和宽可以为负。如果Y坐标正方向向上,简单的方法是(x,y)为左上角,cy用负数。

 

创建位图

位图分两种DDB(Device-Dependent Bitmap)和DIB(Device-Independent Bitmap)。

CreateBitmap(cx,cy,cPlanes,cBitsPixel,bits):返回HBITMAP。cx,cy是长和高,cPlanes是调色板数,cBitsPixel是像素深度,bits是位图指针,如果不想初始化DDB设为NULL。分配空间每行以两字节为单位,计算公式iWidthBytes=((cx*cBitsPixel+15)&~15)>>3。CreateBitmap为DDB分配的空间iBitmapBytes=cy*cPlanes*iWidthBytes。

CreateBitmap在实际中只用以下两类参数:

1.cPlanes和cBitsPixel都为1,显示单色

2.cPlanes和cBitsPixel与设为某个DC的值,用GetDeviceCaps的PLANES和BITSPIXEL获取。

第二种用法完成可以用CreateCompatibleBitmap替代。

CreateCompatibleBitmap(hdc,cx,cy)

CreateDiscardableBitmap(hdc,cx,cy):与上一个相同,在以前的Windows版本中,用它创建的DDB在内存低时会被Windows回收。

CreateBitmapIndirect(&bitmap):bitmap是BITMAP结构体,不用初始化bmWidthBytes字段,Windows会自动计算。所有创建的DDB都要用DeleteObject销毁。

GetObject(hBitmap,sizeof(BITMAP),&bitmap):得到hBitmap的位图信息。

LoadBitmap(hInstance,szBitmapName):hInstance为NULL,加载系统位图(以OBM开头宏)。如果位图资源与一个ID关联而不是名字,则用MAKEINTRESOURCE宏转化。返回的bitmap句柄总与DC兼容。

CreatePatternBrush(hBitmap):返回HBRUSH,把hBitmap加载到画刷中,Bitmap至少为8*8。也可用CreateBrushIndirect创建,LOGBRUSH的lpStyle字段设为BS_PATTERN。Bitmap和Brush都是GDI对象,都要在程序结束前调用DeleteObject。当基于Bitmap创建Brush时,Brush中会有一个Bitmap拷贝,这时就可以删除Bitmap了。

 

位图像素

SetBitmapBits(hBitmap,cBytes,&bits):DDB并没有自己的调色板,在彩色位图中,bits只是一个数值,并不表示一个特定的颜色。
GetBitmapBits(hBitmap,cBytes,&bits)
SetBitmapDimesionEx和GetBitmapDimesionEx:设置或获得以0.1毫米为单位的位图大小。
Memory Device Context或叫兼容DC
CreateCompatibleDC(hdc):创建与hdc兼容的DC,它是在内在中虚拟的设备,参数为NULL则自动创建显示设备的DC。必须销毁,调用DeleteDC。创建之后只有一位的显示页(Display surface),什么也做不了,我们下一步要把显示页加大。
SelectObject(hdcMem,hBitmap):兼容DC是惟一的可以选择hBitmap的DC。只有当选择的位图是单色或与兼容的DC的调色板和颜色深度相同时SelectObject才有效。这就是CreateBitmap只用两类方法创建DDB的原因。
GetTextExtentPoint32(hdc,szText,iLength,&size):得到文本长和高
EnumDisplaySettings:获得可显卡可用的显示模式(分辨率),可用这个函数获得最大分辨率,做为内存DC大小,就可将客户区外的绘图保存。
位图菜单
可以用AppendMenu或InsertMenu加载位图菜单,菜单类型加MF_BITMAP并把最后一个参数传入Bitmap句柄。可能Bitmap大小不同,就需要用两个内存DC来调整大小,其中hdcMem1为菜单大小,载入Bitmap1,hdcMem2为初始位图大小,载入Bitmap,用StretchBlt把hdcMem2复制到hdcMem1。
当顶级菜单有位图时,GetSystemMetrics(SM_CYMENU)无效。
使用位图菜单没法用菜单快捷键,这时候就要用到WM_MENUCHAR消息。当按下ALT+字符键没有对应的菜单快捷键时,Windows就会发送WM_MENUCHAR消息,这个消息我们检查wParam,如果是我们需要的快捷键,就返回一个双字,高字为2,低字是要激活的菜单索引。
位图遮盖
 在WM_CREATE消息中,创建两个MDC:hdcMemImag和hdcMemMask。hdcMemImag载入要显示的位图,hdcMemMask载入相同大小的单色位图,在hdcMemMask上画一个黑底白色的椭圆,用BitBlt的SRCAND方式把hdcMemMask复制到hdcMemImag,这时候hdcMemImag要遮盖的部位就是黑色了。
在WM_PAINT消息中,先用MERGEPAINT(D&~S)方式,把hdcMemMask复制到显卡,这时显示器的是一个黑色椭圆,底色是客户区背景色,再用SRCPAINT(S|D)方式,把hdcMemImag复制到显卡,这时就显示了一个用椭圆遮盖的位图。
如果要用复杂图形遮盖,就自己画一个图。
如果在程序只运行在Windows NT,可用BltMask函数,只需要少数函数就可以完成相同的工作。Windows NT还提供类似于BitBlt的函数PlgBlt,它还可以旋转与倾斜位图。
一个位图的应用例子(截屏)  

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值