位图图像(Bitmap),亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个

点组成的。BMP文件的图像深度(用多少个二进制位来表示每个点的颜色)可选1bit、4bit、8bit及24bit,

BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。

Windows下绘制位图使用双缓冲技术,直接将位图选到内存兼容DC中,然后一次显示到窗口DC上。

位图绘制步骤

第一步:

使用CreateCompatibleDC创建一个内存兼容DC,但这个DC尺寸很小,通常是1*1像素大小,不能直接绘制。

第二步:

使用LoadlmageLoadBitmap加载现有位图,使用SelectObject将位图选入到兼容DC,这时位图尺寸大小就相当于了内存设备环境尺寸大小。

第三步:

使用BitBltStretchBlt将兼容DC一次性显示到窗口DC上。

步骤详细说明

绘制位图跟双缓冲绘制技术原理差不多,

所以,第一步,和第三步的函数介绍请参考:http://qingzhouquanzi.com/292.html

只不过 那个是创建位图,而这个是加载现有的位图,可以先看 那一篇再看这个 更容易理解

第二步加载位图函数说明:

HANDLE WINAPl LoadImage (

HINSTANCE    hinst,//模块句柄,如果要加载独立资源,如c: \ my.bmp,那么此参数设为NULL

LPCTSTR    lpszName,//图片路径或MAKEINTRESOURCE(iDB_XXX)宏产生的字符串

UINT    uType,//IMAGE_BITMAP位图、IMAGE_CURSOR光标、IMAGE_ICON图标

int    cxDesired,//图标或光标的宽度、如果此参数为零并且未使用LR_DEFAULTSIZE,

                                则该函数将使用实际的资源高度。

int    cyDesired,    //图标或光标的高度

UINT    fuLoad    //标识

) ;

fuLoad 可以是以下值 

LR_CREATEDIBSECTION    

当uType参数指定IMAGE_BITMAP时,会导致函数返回DIB段位图而不是兼容的位图。该标志对于加载位图而不将其映射到显示设备的颜色很有用。

LR_DEFAULTCOLOR    

默认标志;它什么也没做。它的意思是“不是LR_MONOCHROME”。

LR_DEFAULTSIZE    

如果cxDesired或cyDesired值设置为零,则使用游标或图标的系统度量值指定的宽度或高度。

如果未指定此标志且cxDesired和cyDesired设置为零,则该函数将使用实际的资源大小。如果资源包含多个图像,则该函数使用第一个图像的大小。

LR_LOADFROMFILE    (一般这个用的比较多)

从由lpszName(图标,光标或位图文件)指定的文件加载独立映像。


返回值:

如果函数成功,则返回值是新加载的图像的句柄。

如果函数失败,返回值为NULL。要获得扩展的错误信息,请调用GetLastError。

备注:

使用完毕后调用DeleteObject释放位图,DestroyCursor释放光标,Destroylcon释放图标

代码例子

case WM_PAINT:
{
	PAINTSTRUCT ps;//绘图结构体
	HDC hdc=BeginPaint(hwnd, &ps);
	

	//第一步:=创建一个内存兼容DC,此时它的大小是1*1,很小,不能绘制
	HDC hMenDC = CreateCompatibleDC(hdc);


	//第二步:加载现有位图
	HBITMAP hMenBmp = (HBITMAP)LoadImage(NULL,
		TEXT("D:/c++练习/精通Windows API高级编程_练习/58GDI绘图 加载图片 显示到窗口上(可对图片进行绘制)/1.bmp"),
		IMAGE_BITMAP,
		0, 0, LR_LOADFROMFILE);
	//并且把兼容位图选到兼容内存DC中,此时DC的大小与位图一致,可以绘制
	SelectObject(hMenDC, hMenBmp); 


	//第三步:在内存兼容DC上绘制各种图形
	//SetTextColor(hMenDC,RGB(255, 0, 0));
	//TextOut(hMenDC, 0, 0, TEXT("这是一个简单的绘图例子"), lstrlen(TEXT("这是一个简单的绘图例子")));
	//Rectangle(hMenDC, 30, 30, 80, 80);

	//第四步 把内存中的图像一次性画到窗口DC上

	//不拉伸
	BitBlt(hdc, 0, 0, 100, 100, hMenDC, 0, 0,SRCCOPY);
	//拉伸
	StretchBlt(hdc,0, 100, 200, 200, hMenDC, 0, 0, 800, 800, SRCCOPY);
	//缩放
	StretchBlt(hdc, 300, 0, 50, 50, hMenDC, 0, 0, 800, 800, SRCCOPY);


	//最后不要忘记释放资源
	DeleteDC(hMenDC);
	DeleteObject(hMenBmp);


	EndPaint(hwnd,&ps);
	break;
}

运行结果(此时图片失真!):

QQ截图20200908052307.bmp

图片失真解决方法:

StretchBlt会碰到一些与点阵图放大缩小缩放相关的一些问题:

操作会造成产生的图像有些失真。

1、在扩展一个点阵图时,StretchBlt必须复制图素行或列。如果放大倍数不是原图的整数倍,那么此

2、当目标矩形比源矩形小的时候,必须要将一些点去掉,默认做法是将要去掉的点与旁边的点做AND运算,所以导致像素错误,引起失真。

那么 可以使用 SetStretchBltMode函数可以设置指定设备环境中的位图拉伸模式解决失真问题。

int SetStretchBltMode(

HDC    hdc,//设备上下文句柄

int    iStretchMode //位图伸展模式

);

iStretchMode  可选值:

BLACKONWHITE: 使用消除和现在的像素颜色值进行逻辑AND(与)操作运算。如果该位图是单色位图,那么该模式以牺牲白色像素为代价,保留黑色像素点。

COLORONCOLOR:删除像素。该模式删除所有消除的像素行,不保留其信息。

HALFTONE:将源矩形区中的像素映射到目标矩形区的像素块中,覆盖目标像素块的一般颜色与源像素的颜

色接近。在设置完HALFTONE拉伸模之后,应用程序必须调用SetBrushOrgEx函数来设置刷子的起始点。如果没有成功,那么会出现刷子没对准的情况。

STRETCH_ANDSCANS: 与BLACKONWHITE一样。

STRETCH_DELETESCANS: 与COLORONCOLOR一样。

STRETCH_HALFTONE:与HALFTONE相同。

STRETCH_ORSCANS: 与WHITEONBLACK相同。

更多模式请参考msdn

返回值:

如果函数成功,返回值为非零。

如果函数失败,返回值为零,调用GetLastError获得扩展的错误信息.

代码实例,在拉伸之前设置拉伸模式

//解决拉伸失真问题
SetStretchBltMode(hdc, COLORONCOLOR);

//不拉伸
BitBlt(hdc, 0, 0, 100, 100, hMenDC, 0, 0,SRCCOPY);
//拉伸
StretchBlt(hdc,0, 100, 200, 200, hMenDC, 0, 0, 800, 800, SRCCOPY);
//缩放
StretchBlt(hdc, 300, 0, 50, 50, hMenDC, 0, 0, 800, 800, SRCCOPY);

运行结果:

QQ截图20200908053552.bmp

相关推荐

c/c++ gdi 双缓冲绘制技术 解决gdi绘图效率问题

Windows绘图原理我们在Windows环境下看到各种元素,如菜单、按钮、窗口、图像,都是“画”出来的。这时的屏幕,就相当于一块黑板,而Windows下的各种GDI要素,如画笔、画刷等,就相当于彩色

gdiplus基础:gdigdi+的区别、设备环境dc的概念、以及对象的使用方法

gdi和gdi+的区别1.GDI是gdi32.dll这个库,而GDI+是GDIplus.dll这个库2.GDI是硬件加速的,而GDI+不是3.GDI是有状态的,而GDI+是无状态的4.GDI绘图要使用

MFc组件 属性与方法大全

所有控件的公共属性:Visiable:控件是否可见。Disabled:控件是否被禁止、被禁止的控件无法接受键盘和鼠标输入。Group:是否从这个空间开始一个新组。指定基于Tab 键顺序的一组控件中的第

74Hc245芯的作用 引脚图以及功能 (解决机输出功率不足的问题)

以下仅为简单总结,详情请参阅购买开发板附带的资料作用: 由于单片机输出的功率不足,所以可以通过74HC245来增强他的电流上限功能:八个输入信号原封不动的输出,只不过可接的电流更大一些。可解决led太

16、新手如何快速获得权重站以及赚钱方法

新手如何快速获得权重站以及赚钱方法该方法适合新手做大量垃圾站,搞seo的与精品站的,bc站的,土豪的,黑帽子高手的都可以跳过1,新站想快速获取权重,就是选词,选择大指数词,指数小难以获得权重2,一般选

vmware15虚拟机安装Win11系统 方法 这台电脑无运行windows11解决方法 装系统提示 Attempting to start up from:解决方法

跟安装其他系统流程一样 正常的流程就不写了 跟安装其他系统一样但是安装win11 有点不太一样 记录一下四个关键点设置 关键点一: 访问控制 >>加密 设置一个密码关键点二:勾选UEFI

易语言静态编译解决方法

安装完后 再安装目录下找到 tools 这个文件夹 里面有个 VC6linker文件夹然后里面有个 link.e 直接打开 运行一下就自动把配置改好了 路径都会自动识别附上 VC6的下载地址吧~链接

小米手机 亲情守护 服务器异常(完美解决方法)

当红米或者小米手机打开亲情守护的时候.发现提示服务器异常的原因:一直在转啊转.二维码加载不出来怎么办呢?原因:这个软件是系统自带的.版本可能有点老了,服务器地址发生了变化,所以会显示服务器异常解决方

帝国cms分类页的分页第一页和第二页全都一样 (解决方法)

最近用帝国cms做了个网站,过了几天才发现一个问题分类页的第一页和第二页竟然完全一样比如:五年级作文第一页:http://www.lingganzuowen.com/wunianji/五年级作文第二页

zblog数据量多 访问速度慢解决方法 实测300万文章秒开不卡

如果你曾因为网站文章数量多 而导致网站打开缓慢,那么恭喜你.发现了这个屌爆了的神器!本插件已经经过很多网站的测试,和版本的迭代, 目前已兼容大部分主题.如果个别主题使用不正常的.或者使用中有任何疑问.