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添加引用即可(注意语句末尾无分号)。