win32-StretchDIBits - PrintDlg
使用StretchDIBits将位图数据传输到printer的dc中
#include <Windows.h>
#include <algorithm> int main()
{
int nWidth = 16, nHeight = 16;
BYTE byteBitmap[768];
std::fill_n(byteBitmap, 768, 0xFF); // Test for a red cross bitmap
int nIndices[] = { 0, 1, 45, 46, 51, 52, 90, 91, 102, 103, 135, 136, 153, 154, 180, 181, 204, 205, 225, 226, 255, 256, 270, 271, 306, 307, 315, 316, 357, 358, 360, 361, 405, 406, 408, 409, 450, 451, 459, 460, 495, 496, 510, 511, 540, 541, 561, 562, 585, 586, 612, 613, 630, 631, 663, 664, 675, 676, 714, 715, 720, 721, 765, 766 };
int nNbElements = sizeof(nIndices) / sizeof(nIndices[0]);
for (int i = 0; i < nNbElements; i++) { byteBitmap[nIndices[i]] = 0; } HDC hDC = GetDC(NULL); BITMAPINFO bi;
memset(&bi, 0, sizeof(bi));
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nWidth;
bi.bmiHeader.biHeight = nHeight;
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biSizeImage = nWidth * nHeight * 24 / 8;
bi.bmiHeader.biPlanes = 1;
/*bi.bmiHeader.biXPelsPerMeter = 7874;
bi.bmiHeader.biYPelsPerMeter = 7874;*/
//HBITMAP hBitmap = CreateDIBitmap(hDC, &bi.bmiHeader, CBM_INIT, byteBitmap, &bi, DIB_RGB_COLORS); PRINTDLG pdlg = { 0 };
pdlg.lStructSize = sizeof(pdlg);
pdlg.Flags = PD_RETURNDC;
if (PrintDlg(&pdlg) == TRUE)
{
HDC hPrinterDC = pdlg.hDC;
DOCINFO di;
ZeroMemory(&di, sizeof(di));
di.cbSize = sizeof(di);
di.lpszDocName = TEXT("Test");
if (StartDoc(hPrinterDC, &di) > 0)
{
if (StartPage(hPrinterDC) > 0)
{
int nPrinterWidth = GetDeviceCaps(hPrinterDC, HORZRES);
int nPrinterHeight = GetDeviceCaps(hPrinterDC, VERTRES); int nLogPixelsXScreen = GetDeviceCaps(hDC, LOGPIXELSX);
int nLogPixelsYScreen = GetDeviceCaps(hDC, LOGPIXELSY);
int nLogPixelsXPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
int nLogPixelsYPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
int nScaleX = max(nLogPixelsXScreen, nLogPixelsXPrinter) / min(nLogPixelsXScreen, nLogPixelsXPrinter);
int nScaleY = max(nLogPixelsYScreen, nLogPixelsYPrinter) / min(nLogPixelsYScreen, nLogPixelsYPrinter); SetMapMode(hPrinterDC, MM_ISOTROPIC);
SetWindowExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0);
SetViewportExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0);
SetViewportOrgEx(hPrinterDC, 0, 0, 0); SetStretchBltMode(hPrinterDC, COLORONCOLOR);
StretchDIBits(hPrinterDC, 0, 0, nWidth * nScaleX, nHeight * nScaleY, 0, 0, nWidth, nHeight, byteBitmap, (LPBITMAPINFO)&bi, DIB_RGB_COLORS, SRCCOPY); EndPage(hPrinterDC);
}
EndDoc(hPrinterDC);
}
}
ReleaseDC(NULL, hDC);
}
上面是打印一个红色就×
也可以结合官方示例,将屏幕截图打印到printer的dc中
int CaptureAnImage(HWND hWnd)
{
HDC hdcScreen;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP bmpScreen; // Retrieve the handle to a display device context for the client
// area of the window.
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd); // Create a compatible DC which is used in a BitBlt from the window DC
hdcMemDC = CreateCompatibleDC(hdcWindow); if (!hdcMemDC)
{
MessageBox(hWnd, L"CreateCompatibleDC has failed", L"Failed", MB_OK);
// goto done;
} // Get the client area for size calculation
RECT rcClient;
GetClientRect(hWnd, &rcClient); //This is the best stretch mode
SetStretchBltMode(hdcWindow, HALFTONE); //The source DC is the entire screen and the destination DC is the current window (HWND)
if (!StretchBlt(hdcWindow,
0, 0,
rcClient.right, rcClient.bottom,
hdcScreen,
0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
SRCCOPY))
{
MessageBox(hWnd, L"StretchBlt has failed", L"Failed", MB_OK);
// goto done;
} // Create a compatible bitmap from the Window DC
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); if (!hbmScreen)
{
MessageBox(hWnd, L"CreateCompatibleBitmap Failed", L"Failed", MB_OK);
// goto done;
} // Select the compatible bitmap into the compatible memory DC.
SelectObject(hdcMemDC, hbmScreen); // Bit block transfer into our compatible memory DC.
if (!BitBlt(hdcMemDC,
0, 0,
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
hdcWindow,
0, 0,
SRCCOPY))
{
MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
// goto done;
} // Get the BITMAP from the HBITMAP
GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen); BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi; bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0; DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight; // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
// call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
// have greater overhead than HeapAlloc.
HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
char* lpbitmap = (char*)GlobalLock(hDIB); // Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpbitmap.
GetDIBits(hdcWindow, hbmScreen, 0,
(UINT)bmpScreen.bmHeight,
lpbitmap,
(BITMAPINFO*)&bi, DIB_RGB_COLORS); PRINTDLG pdlg = { 0 };
pdlg.lStructSize = sizeof(pdlg);
pdlg.Flags = PD_RETURNDC;
if (PrintDlg(&pdlg) == TRUE)
{
HDC hPrinterDC = pdlg.hDC;
DOCINFO di;
ZeroMemory(&di, sizeof(di));
di.cbSize = sizeof(di);
di.lpszDocName = TEXT("Test");
if (StartDoc(hPrinterDC, &di) > 0)
{
if (StartPage(hPrinterDC) > 0)
{
int nPrinterWidth = GetDeviceCaps(hPrinterDC, HORZRES);
int nPrinterHeight = GetDeviceCaps(hPrinterDC, VERTRES); int nLogPixelsXScreen = GetDeviceCaps(hdcScreen, LOGPIXELSX);
int nLogPixelsYScreen = GetDeviceCaps(hdcScreen, LOGPIXELSY);
int nLogPixelsXPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
int nLogPixelsYPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
int nScaleX = max(nLogPixelsXScreen, nLogPixelsXPrinter) / min(nLogPixelsXScreen, nLogPixelsXPrinter);
int nScaleY = max(nLogPixelsYScreen, nLogPixelsYPrinter) / min(nLogPixelsYScreen, nLogPixelsYPrinter); SetMapMode(hPrinterDC, MM_ISOTROPIC);
SetWindowExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0);
SetViewportExtEx(hPrinterDC, nPrinterWidth, nPrinterHeight, 0);
SetViewportOrgEx(hPrinterDC, 0, 0, 0); SetStretchBltMode(hPrinterDC, COLORONCOLOR);
StretchDIBits(hPrinterDC, 0, 0, bmpScreen.bmWidth * nScaleX, bmpScreen.bmHeight * nScaleY, 0, 0, bmpScreen.bmWidth, bmpScreen.bmHeight, lpbitmap, (LPBITMAPINFO)&bi, DIB_RGB_COLORS, SRCCOPY); EndPage(hPrinterDC);
}
EndDoc(hPrinterDC);
}
} //Clean up
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL, hdcScreen);
ReleaseDC(hWnd, hdcWindow); return 0;
}
Note: 输出到printer截图会因为纸张的限制而被截取一部分,具体解决方法,参考: https://stackoverflow.com/questions/47642947/windows-gdi-scaling-a-screen-dc-to-a-printer-dc-without-modifying-the-draw-f
win32-StretchDIBits - PrintDlg的更多相关文章
- Microsoft Win32 to Microsoft .NET Framework API Map
Microsoft Win32 to Microsoft .NET Framework API Map .NET Development (General) Technical Articles ...
- 重温 Win32 API ----- 截屏指定窗体并打印
朋友说在一个VC++6.0开发的项目中要增加打印窗体的功能,让帮忙写个代码供其调用. 这么老的IDE当然不想碰了,并且也不喜欢MFC笨拙不清晰的封装.所以决定採用纯Win32 API,然后用C++类简 ...
- Win32汇编学习(11):对话框(2)
我们将进一步学习对话框,探讨如何把对话框当成输入设备.如果您看了前一篇文章,那就会发现这次的例子只有少量的改动,就是把我们的对话框窗口附属到主窗口上.另外,我们还要学习通用对话框的用法. 理论: 把对 ...
- 【C++】从零开始,只使用FFmpeg,Win32 API,实现一个播放器(一)
前言 起初只是想做一个直接读取视频文件然后播放字符动画的程序.我的设想很简单,只要有现成的库,帮我把视频文件解析成一帧一帧的原始画面信息,那么我只需要读取里面的每一个像素的RGB数值,计算出亮度,然后 ...
- C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper
前言 在开发应用程序时,通常只让程序运行一个实例.所以,就要判断程序是否已经运行. 下面是我自己在项目中使用到,封装好的帮助类.有 普通的 C# 应用程序 和 Windows CE 和 Windows ...
- java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序。
JNA 调用 dll 库时,保错: ///////////////// 通过 JNA 引入 DLL 库 //////////// /** * ID_FprCap.dll 负责指纹的采集, 指纹仪的初始 ...
- 初次认识 C# win32 api
第一次接触win32api,刚开始的时候有点迷迷糊糊的. Windows API 就是windows应用程序接口. win api向上就是windows应用程序,向下就是windows操作系统核心. ...
- [老文章搬家] [翻译] 深入解析win32 crt 调试堆
09 年翻译的东西. 原文见: http://www.nobugs.org/developer/win32/debug_crt_heap.html 在DeviceStudio的Debug编译模式下, ...
- Virus.Win32.Virlock.b分析
0x00 样本说明 分析样本是被0b500d25f645c0b25532c1e3c9741667的样本感染得到.感染前的文件是Tcpview.exe,一款windows网络连接查看工具. 感染前后文件 ...
- cocos2d-x 从win32到android移植的全套解决方案
引言:我们使用cocos2d-x引擎制作了一款飞行射击游戏,其中创新性地融入了手势识别功能.但是我们在移植过程中遇到了很多的问题,同时也发现网上的资料少而不全.所以在项目行将结束的时候,我们特地写了这 ...
随机推荐
- [转帖]JVM 输出 GC 日志导致 JVM 卡住,我 TM 人傻了
https://www.jianshu.com/p/51380e04eab1 最近,我们升级了 Java 17.后来,我们的 k8s 运维团队为了优化我们的应用日志采集, 将我们所有 pod (你可以 ...
- [转帖]Centos使用chrony做时间同步
https://www.cnblogs.com/lizhaoxian/p/11260041.html Chrony是一个开源的自由软件,在RHEL 7操作系统,已经是默认服务,默认配置文件在 /etc ...
- [转帖]k8s对接ceph,ceph-csi方式
1.上传ceph-csi-yaml和ceph-csi-image 两个文件夹到服务器 2.加载 ceph-csi-image里面的镜像 3.将加载好的镜像上传到本地harbor上. 4.修改ceph- ...
- [转帖]01-rsync备份方式
https://developer.aliyun.com/article/885783?spm=a2c6h.24874632.expert-profile.284.7c46cfe9h5DxWK 简介: ...
- Docker 运行 Redis Rabbitmq seata-server ftp 的简单办法
公司里面用到了很多组件, 发现安装二进制太麻烦了, 所以想用Docker 进行安装. 这里面简单给总结一下就不在折腾了.. 1. redis docker run -d -p 6379:6379 -- ...
- 一台不容错过的Java单元测试代码“永动机”
作者:京东零售 陈志良 作为一名京东的软件匠人,我们开发的软件支撑着数亿的用户,责任是重大的,因此我们深深地敬畏每一行代码,那如何将我们的失误降到最低呢?那就是单元测试,它会让我们树立对代码的自信心. ...
- VUe2.0 和 Vue3.0 的生命周期作对比
VUe2.0 和 Vue3.0 的生命周期作对比 beforeCreate -> 请使用 setup() created -> 请使用 setup() beforeMount -> ...
- Git的使用(一):创建本地仓库并在其中添加、修改、删除文件
创建本地版本库 版本库又名仓库,英文名repository,可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者 ...
- 【四】AI Studio 项目详解【VisualDL工具、环境使用说明、脚本任务、(四)图形化任务、在线部署及预测】PARL
相关文章 [一]-环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简介 [五]-Sarsa&Qlear ...
- 【二】gym初次入门一学就会---代码详细解析简明教程----平衡杆案例
相关文章: [一]gym环境安装以及安装遇到的错误解决 [二]gym初次入门一学就会-简明教程 [三]gym简单画图 [四]gym搭建自己的环境,全网最详细版本,3分钟你就学会了! [五]gym搭建自 ...