zoukankan      html  css  js  c++  java
  • 重温 Win32 API ----- 截屏指定窗体并打印

    朋友说在一个VC++6.0开发的项目中要增加打印窗体的功能,让帮忙写个代码供其调用。

    这么老的IDE当然不想碰了,并且也不喜欢MFC笨拙不清晰的封装。所以决定採用纯Win32 API,然后用C++类简单封装一下。

    1 基本思路

    窗体DC和打印机DC是两类不兼容的DC。所以它们之间传送位图仅仅能通过DIB。首先,通过BitBlt()把要打印窗体的客户区复制到DDB内存位图中,然后通过GetDIBits()把DDB转换为DIB,最后通过StretchDIBits()向打印机DC输出。

    2 代码实现

    头文件 WinowPrinter.h

    #pragma once
    
    /********************************************************************************
                             WindowPrinter 打印窗体类
    功能描写叙述:
    提供截屏窗体并通过默认打印机,自己主动进行居中缩放打印
    
    使用说明:
    例子代码例如以下。 
    	HWND hwnd = this->GetSafeWnd();
    	WindowPrinter::PrintWindowClientArea(hwnd);
    ********************************************************************************/
    class WindowPrinter
    {
    public:
    	WindowPrinter();
    	~WindowPrinter();
    public:
    	/*
    	功能:获取当前默认打印机的DC
    	返回:成功返回打印机的DC,失败返回NULL
    	*/
    	static HDC GetPrinterDC();
    
    	/*
    	功能:打印窗体客户区内容到打印机。自己主动缩放居中打印
    	參数: hWnd-被打印窗体的句柄
    	*/
    	static void PrintWindowClientArea(HWND hwnd);
    };
    
    


     

    实现文件 WindowPrinter.cpp

    #include "stdafx.h"
    #include "WindowPrinter.h"
    #include <Winspool.h>
    
    
    WindowPrinter::WindowPrinter()
    {
    }
    
    
    WindowPrinter::~WindowPrinter()
    {
    }
    
    /*
    功能:获取当前默认打印机的DC
    返回:成功返回打印机的DC。失败返回NULL
    */
    HDC WindowPrinter::GetPrinterDC()
    {
    	DWORD dwNeeded, dwReturned;
    	HDC hdc;
    	::EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwReturned);
    	PRINTER_INFO_4* pinfo4 = (PRINTER_INFO_4*)malloc(dwNeeded);
    	::EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, (BYTE*)pinfo4, dwNeeded, &dwNeeded, &dwReturned);
    	hdc = ::CreateDC(NULL, pinfo4->pPrinterName, NULL, NULL);
    	free(pinfo4);
    	return hdc;
    }
    /*
    功能:打印窗体客户区内容到打印机,自己主动缩放居中打印
    參数: hWnd-被打印窗体的句柄
    */
    void WindowPrinter::PrintWindowClientArea(HWND hWnd)
    {
    	if (hWnd == NULL) return;
    
    	RECT rectClient;
    	::GetClientRect(hWnd, &rectClient);
    	int width = rectClient.right - rectClient.left;
    	int height = rectClient.bottom - rectClient.top;
    
    	// 通过内存DC复制客户区到DDB位图
    	HDC hdcWnd = ::GetDC(hWnd);
    	HBITMAP hbmWnd = ::CreateCompatibleBitmap(hdcWnd, width, height);
    	HDC hdcMem = ::CreateCompatibleDC(hdcWnd);
    	::SelectObject(hdcMem, hbmWnd);
    	::BitBlt(hdcMem, 0, 0, width, height, hdcWnd, 0, 0, SRCCOPY);
    
    	// 把窗体DDB转为DIB
    	BITMAP bmpWnd;
    	::GetObject(hbmWnd, sizeof(BITMAP), &bmpWnd);
    	BITMAPINFOHEADER bi; // 信息头
    	bi.biSize = sizeof(BITMAPINFOHEADER);
    	bi.biWidth = bmpWnd.bmWidth;
    	bi.biHeight = bmpWnd.bmHeight;
    	bi.biPlanes = 1;
    	bi.biBitCount = 32; // 依照每一个像素用32bits表示转换
    	bi.biCompression = BI_RGB;
    	bi.biSizeImage = 0;
    	bi.biXPelsPerMeter = 0;
    	bi.biYPelsPerMeter = 0;
    	bi.biClrUsed = 0;
    	bi.biClrImportant = 0;
    
    	DWORD dwBmpSize = ((bmpWnd.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpWnd.bmHeight; // 每一行像素位32对齐
    	char *lpbitmap = (char*)malloc(dwBmpSize); // 像素位指针
    	::GetDIBits(hdcMem, hbmWnd, 0, (UINT)bmpWnd.bmHeight,
    		lpbitmap,
    		(BITMAPINFO*)&bi,
    		DIB_RGB_COLORS);
    
    	::DeleteDC(hdcMem);
    	::DeleteObject(hbmWnd);
    	::ReleaseDC(hWnd, hdcWnd);
    
    	// 存为文件(可选)
    	BITMAPFILEHEADER bmfHeader; // 文件头
    	DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    	bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
    	bmfHeader.bfSize = dwSizeofDIB;
    	bmfHeader.bfType = 0x4D42;
    
    	FILE* fp = NULL;
    	::_wfopen_s(&fp, L"capture.bmp", L"w");
    	::fwrite(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, fp); // 写入文件头
    	::fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, fp);        // 写入信息头
    	::fwrite(lpbitmap, dwBmpSize, 1, fp);                  // 写入像素位
    	::fclose(fp);
    	fp = NULL;
    
    	// StretchDIBits()缩放打印DIB
    	HDC hdcPrinter = WindowPrinter::GetPrinterDC();
    	if (hdcPrinter == NULL)
    		return;
    
    	int pageWidth = ::GetDeviceCaps(hdcPrinter, HORZRES);
    	int pageHeight = ::GetDeviceCaps(hdcPrinter, VERTRES);
    
    	float scaleX = (float)pageWidth / (float)bmpWnd.bmWidth;
    	float scaleY = (float)pageHeight / (float)bmpWnd.bmHeight;
    	float scale = scaleX < scaleY ?

    scaleX : scaleY; int xDst, yDst, cxDst, cyDst; cxDst = (int)((float)bmpWnd.bmWidth * scale); cyDst = (int)((float)bmpWnd.bmHeight * scale); xDst = (int)((pageWidth - cxDst) / 2); yDst = (int)((pageHeight - cyDst) / 2); static DOCINFO di = { sizeof(DOCINFO), L"PRINTJOBNAME" }; if (::StartDoc(hdcPrinter, &di) > 0) { if (::StartPage(hdcPrinter) > 0) { ::StretchDIBits(hdcPrinter, xDst, yDst, cxDst, cyDst, 0, 0, bmpWnd.bmWidth, bmpWnd.bmHeight, lpbitmap, (BITMAPINFO*)&bi, DIB_RGB_COLORS, SRCCOPY); ::EndPage(hdcPrinter); } ::EndDoc(hdcPrinter); } ::DeleteDC(hdcPrinter); ::free(lpbitmap); }


     

  • 相关阅读:
    HTTPS, SPDY和 HTTP/2性能的简单对比
    mysql去除字段内容的空格和换行回车
    jquery获取选中select的文本,值等
    jquery 选择器
    php获取调用本方法的上个方法,php堆栈,函数入库
    php 过滤js字符串代码
    php 获取根目录
    php生成唯一字符串
    php javascript的ajax
    php 上传文件大小控制配置文件中设置的
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5193905.html
Copyright © 2011-2022 走看看