0.写在前面
这篇文章主要整理介绍了关于VC6.0使用GDI对控制台进行贴图的内容, 需要引入头文件windows.h
。
1.获取上下文句柄(GetDC)
1.1.函数原型
HDC GetDC(HWND hWnd);
1.2.函数介绍
GetDC
函数是用来获取显示设备的上下文环境DC的句柄(HDC, 显示设备可以是某个窗口或者是整个屏幕), 之后可以使用GDI函数通过这个句柄对显示设备进行绘图操作。
1.3.函数封装
在向控制台贴图之前, 需要先向GetDC
函数传入控制台窗口句柄(hWnd)来获得DC的句柄(HDC); 而为了获得控制台窗口句柄, 可以通过GetConsoleTitle
取得控制台窗口的标题之后, 再使用FindWindow
根据窗口标题获得HDC。
下面可以把这些步骤封装成一个函数来实现, 便于之后的调用:
HDC NtkGetDC()
{
TCHAR title[256];
HDC hdc = NULL;
GetConsoleTitle(title,256);
hdc = GetDC(FindWindow(0,title));
return hdc;
}
2.装载位图(LoadImage)
2.1.函数原型
HANDLE LoadImage(HINSTANCE hinst,LPCTSTR lpszName,UINT uType,int cxDesired,int cyDesired,UINT fuLoad);
2.2.函数介绍
LoadImage
函数用来装载图标,光标,或位图。
2.3.函数封装
因为本文的主题是介绍VC6.0的控制台贴图, 那么接下来的使用以装载.bmp位图为例。
同样的, 可以将其封装为一个函数: 传入HBITMAP *pImg
来存储加载的位图数据, filename
为需要加载位图的文件路径(使用绝对路径或相对路径均可), width
和height
为将位图拉伸或者收缩的宽高尺寸(若要按原图载入则都传入0即可)
void NtkLoadImage(HBITMAP* pImg, char* filename, int width, int height)
{
*pImg = (HBITMAP)LoadImage(NULL,filename,IMAGE_BITMAP,width,height,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);
}
如果要了解LoadImage
的详细参数可以参考网上的文档
3.输出位图到控制台前的准备
3.1.概念明确
Windows系统是不允许直接访问硬件的, 因此对于屏幕的操作(绘图等)是通过上下文环境DC来实现的, 不能直接将位图数据拷贝至表示控制台窗口的DC。但由于DC之间的数据是可以相互拷贝的, 在输出位图到控制台窗口之前, 可以建立不属于控制台窗口的DC用于存储位图数据, 在通过DC间的拷贝间接将位图输出到控制台窗口。
3.2.创建兼容的上下文环境(CreateCompatibleDC)
CreateCompatibleDC
函数用于创建一个与指定设备兼容的内存设备上下文环境(DC)。
函数原型为: HDC CreateCompatibleDC(HDC hdc);
使用时只需要传入GetDC
函数所获得的DC句柄(HDC)即可。
hdcMem = CreateCompatibleDC(hdc);
hdcMem使用完成后可通过DeleteDC(hdcMem);
进行删除。
4.输出位图到控制台
有了之前的准备, 现在可以使用GDI函数在控制台窗口上贴图了, 常用的贴图GDI函数有BitBlt
、StretchBlt
、TransparentBlt
这三个。
4.1.BitBlt
4.1.1.函数原型
BitBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, hdc hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);
hdcDest为标题1GetDC
函数所获得的HDC, nXDest和nYDest为输出的坐标(矩形左上角点坐标), nWidth和nHeight为输出的宽高(小于位图的宽高时会隐藏多余的部分), nXSrc和nYSrc通常填0即可(后面会讲到特殊用法), dwRop为光栅操作符(有点类似于PS图层混合模式中的一些选项, 仅贴图通常填SRCCOPY即可)
4.1.2.使用举例
#include <windows.h>
int main()
{
TCHAR title[256];
HDC hdc,hdcMem;
HBITMAP img,hOldBmp;
GetConsoleTitle(title,256);
hdc = GetDC(FindWindow(0,title));
hdcMem = CreateCompatibleDC(hdc);
img = (HBITMAP)LoadImage(NULL,"image.bmp",IMAGE_BITMAP,226,229,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);
hOldBmp = (HBITMAP)SelectObject(hdcMem,img);
BitBlt(hdc,12,13,226,229,hdcMem,0,0,SRCCOPY);
SelectObject(hdcMem,hOldBmp);
DeleteDC(hdcMem);
return 0;
}
4.2.StretchBlt
4.2.2.与Bitblt的关系
StretchBlt
和Bitblt
的参数其实是类似的, 但不同的是当设置的宽高与图片自身宽高不一致时, StretchBlt
不会隐藏掉图片多余的部分(不会对图片进行裁剪), 而是对图片进行拉伸或者收缩。
4.2.2.函数原型
StretchBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop);
参数与Bitblt是类似的, 而需要对图片进行拉伸时, nWidth和nHeight是拉伸后的宽高(目标矩形的宽高), nWidthSrc和nHeightSrc则是位图自身的宽高
4.2.3.使用举例
将原图宽为226px高为229px的图像拉伸到宽100px高300px:
#include <windows.h>
int main()
{
TCHAR title[256];
HDC hdc,hdcMem;
HBITMAP img,hOldBmp;
GetConsoleTitle(title,256);
hdc = GetDC(FindWindow(0,title));
hdcMem = CreateCompatibleDC(hdc);
img = (HBITMAP)LoadImage(NULL,"image.bmp",IMAGE_BITMAP,226,229,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);
hOldBmp = (HBITMAP)SelectObject(hdcMem,img);
StretchBlt(hdc,12,13,100,300,hdcMem,0,0,226,229,SRCCOPY);
SelectObject(hdcMem,hOldBmp);
DeleteDC(hdcMem);
return 0;
}
4.3.TransparentBlt
4.3.1.函数介绍
当需要以某个颜色作为背景色透明时, TransparentBlt
是一个不错的选择, 根据不同的参数,它也可以像Bitblt
或者StretchBlt
那样对位图进行裁剪或者是拉伸和收缩。但是TransparentBlt
没有光栅操作符的参数dwRop
4.3.2.函数原型
TransparentBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, int nWidthSrc, int nHeightSrc, UINT crTransparent);
crTransparent参数是用来指定以某个颜色作为背景色透明的, 该颜色可通过RGB
函数得到。
4.3.3.可能遇到的问题
在使用MARKDOWN_HASH0eabf4fc8c988228ba9ef479040f99ddMARKDOWNHASH
函数编译时, VC6.0可能会提示如下错误: error LNK2001: unresolved external symbol __imp\_TransparentBlt@44
此时打开项目设置, 为链接器添加Msimg32.lib库即可:
4.3.4.使用举例
以品红(RGB(255,0,254))为透明色:
#include <windows.h>
int main()
{
TCHAR title[256];
HDC hdc,hdcMem;
HBITMAP img,hOldBmp;
GetConsoleTitle(title,256);
hdc = GetDC(FindWindow(0,title));
hdcMem = CreateCompatibleDC(hdc);
img = (HBITMAP)LoadImage(NULL,"image.bmp",IMAGE_BITMAP,226,229,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);
hOldBmp = (HBITMAP)SelectObject(hdcMem,img);
TransparentBlt(hdc,12,13,226,229,hdcMem,0,0,226,229,RGB(255,0,254));
SelectObject(hdcMem,hOldBmp);
DeleteDC(hdcMem);
return 0;
}
5.nXSrc和nYSrc
(待编写…)
Note: 如果
GetDC
函数的HWND hWnd参数传入NULL, 则将会获得整个屏幕的上下文句柄(HDC), 之后GDI函数可以通过该HDC针对整个屏幕进行绘制操作。Note: 为了使用
TransparentBlt
其实也可以不修改链接器设置, 使用#pragma comment(lib,"Msimg32.lib")
为Msimg32.lib添加引用即可(注意语句末尾无分号)。