GDI图像显示

一:BitBlt函数显示位图

BOOL BitBlt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,DWORD dwRop);

调用形式:
dc.BitBlt(x,y,nWidth,nHeight,pSrcDC,xSrc,ySrc,dwRop);

理解:pSrcDC(内存)中含有一张位图,dwRop参数决定了对该位图进行不同的操作,以dwRop=SRCCOPY为例,他表示将pSrcDC中的位图拷贝到dc上,(xSrc,ySrc)决定了从哪个像素点开始进行拷贝。将拷贝的图像画在起点为(x,y),宽高分别为nWidth,nHeight的矩形区域内进行显示。

实验源码(在OnPaint中添加):

CPaintDC dc(this);
BITMAP bm;
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
CDC memdc;		
memdc.CreateCompatibleDC(&dc);    //创建与显示DC相兼容的内存DC
bmp.GetBitmap(&bm);                       //填充BITMAP结构
CBitmap *pOldBmp=memdc.SelectObject(&bmp);   //将选定的位图选入内存DC
dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,&memdc,100,0,SRCCOPY);		
memdc.SelectObject(pOldBmp);
memdc.DeleteDC();
bmp.DeleteObject(); 

实验结果:


将源码修改为:dc.BitBlt(70,0,bm.bmWidth,bm.bmHeight,&memdc,0,0,SRCCOPY);运行结果为:


即在坐标(70,0)处开始进行图像显示。

将源码修改为:dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,&memdc,100,0,SRCCOPY);运行结果为:


即从图像(100,0)位置处的像素开始进行拷贝。BitBlt函数不能缩放图像。而StretchBlt可以。

二:StretchBlt

BOOL StretchBlt( int x, int y, int nWidth,  int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop);

理解:StretchBlt和BitBlt参数的理解一样的,只是StretchBlt增加了nSrcWidth,nSrcHeight两个参数。结合点

(xSrc,ySrc)就确定了一个矩形,它表示将图像中该矩形区的像素点拷贝到起点为(x,y),宽高为nWidth, nHeight的矩形内,进行显示。

实验源码:

CPaintDC dc(this);
BITMAP bm;
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
CDC memdc;		
memdc.CreateCompatibleDC(&dc);    //创建与显示DC相兼容的内存DC
bmp.GetBitmap(&bm);                       //填充BITMAP结构
CRect rectClient;
GetClientRect(&rectClient);
CBitmap *pOldBmp=memdc.SelectObject(&bmp);   //将选定的位图选入内存DC		
//dc.SetStretchBltMode(HALFTONE);
dc.StretchBlt(0,0,rectClient.Width(),rectClient.Height(),&memdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
memdc.SelectObject(pOldBmp);
memdc.DeleteDC();
bmp.DeleteObject();
运行结果:


可以看到,图像有很明显的失真。这是因为图像原本的大小与显示大小相差很多,造成图像大尺度拉伸或缩小而造成的,可以使用函数SetStretchBltMode来解决。将以上注释的代码去掉注释,运行结果为:


哇,秀色可餐。大笑

三:实验证明用TransparentBlt来显示不会出现失真。

CPaintDC dc(this);
BITMAP bm;
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
CDC memdc;		
memdc.CreateCompatibleDC(&dc);    //创建与显示DC相兼容的内存DC
bmp.GetBitmap(&bm);                       //填充BITMAP结构
CRect rectClient;
GetClientRect(&rectClient);
CBitmap *pOldBmp=memdc.SelectObject(&bmp);   //将选定的位图选入内存DC				
dc.TransparentBlt(0,0,rectClient.Width(),rectClient.Height(),&memdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
memdc.SelectObject(pOldBmp);
memdc.DeleteDC();
bmp.DeleteObject(); 
实验结果:




  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++中使用GDI(Graphics Device Interface)显示一张图片,可以按照以下步骤进行操作: 1. 包含必要的头文件: ```cpp #include <Windows.h> ``` 2. 在窗口过程中添加绘图代码: ```cpp LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 创建并加载图片 HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, L"path_to_image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // 获取设备上下文 HDC hdcBitmap = CreateCompatibleDC(hdc); SelectObject(hdcBitmap, hBitmap); // 绘制图片 BITMAP bitmap; GetObject(hBitmap, sizeof(BITMAP), &bitmap); BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcBitmap, 0, 0, SRCCOPY); // 清理资源 DeleteObject(hBitmap); DeleteDC(hdcBitmap); EndPaint(hwnd, &ps); break; } case WM_DESTROY: { PostQuitMessage(0); break; } default: { return DefWindowProc(hwnd, msg, wParam, lParam); } } return 0; } ``` 3. 创建窗口并运行消息循环: ```cpp int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc = { 0 }; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszClassName = L"ImageWindowClass"; RegisterClass(&wc); // 创建窗口 HWND hwnd = CreateWindow(L"ImageWindowClass", L"Image Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL); // 显示窗口 ShowWindow(hwnd, nCmdShow); // 进入消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } ``` 注意: - 将"path_to_image.bmp"替换为你自己的图片路径。 - 以上代码是基于Windows操作系统的。如果你使用其他操作系统,可能需要使用不同的图形库或API来实现类似的功能。 希望这能帮助到你!如果还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值