打印对话框


我思路
1.拷贝当前窗口,对话框以图片形式保存起来。
(1)拷贝当前对话框
HBITMAP CYouDlg::CopyScreenToBitmap(LPRECT lpRect)
{
HDC hScrDC, hMemDC;     
// 屏幕和内存设备描述表
HBITMAP hBitmap,hOldBitmap;  
// 位图句柄
int       nX, nY, nX2, nY2;     
// 选定区域坐标
int       nWidth, nHeight;     
// 位图宽度和高度
int       xScrn, yScrn;        
// 屏幕分辨率
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
// 获得屏幕分辨率
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//确保选定区域是可见的
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScrn)
nX2 = xScrn;
if (nY2 > yScrn)
nY2 = yScrn;
nWidth = nX2 - nX;
nHeight = nY2 - nY;

// 创建一个与屏幕设备描述表兼容的位图
hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,0,0, nWidth,nHeight,hScrDC, nX, nY, SRCCOPY);
//得到屏幕位图的句柄
hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
return hBitmap;
}
(2)保存窗口
int CYouDlg::SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName)
{
HDC     hDC;        
    //设备描述表
int     iBits;     
//当前显示分辨率下每个像素所占字节数
WORD    wBitCount;  
    //位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数
DWORD           dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
BITMAP          Bitmap;       
//位图属性结构
BITMAPFILEHEADER   bmfHdr;       
//位图文件头结构
BITMAPINFOHEADER   bi;           
//位图信息头结构
LPBITMAPINFOHEADER lpbi;         
//指向位图信息头结构
    HANDLE          fh, hDib, hPal;
HPALETTE     hOldPal=NULL;
//定义文件,分配内存句柄,调色板句柄

//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) *
GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else if (iBits <= 24)
wBitCount = 24;
else
wBitCount = 32;
//计算调色板大小
if (wBitCount <= 8)
dwPaletteSize=(1<<wBitCount)*sizeof(RGBQUAD);

//设置位图信息头结构
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize            = sizeof(BITMAPINFOHEADER);
bi.biWidth           = Bitmap.bmWidth;
bi.biHeight          = Bitmap.bmHeight;
bi.biPlanes          = 1;
bi.biBitCount         = wBitCount;
bi.biCompression      = BI_RGB;
bi.biSizeImage        = 0;
bi.biXPelsPerMeter     = 0;
bi.biYPelsPerMeter     = 0;
bi.biClrUsed         = 0;
bi.biClrImportant      = 0;

dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
//为位图内容分配内存

/*xxxxxxxx计算位图大小分解一下(解释一下上面的语句)xxxxxxxxxxxxxxxxxxxx
//每个扫描行所占的字节数应该为4的整数倍,具体算法为:
int biWidth = (Bitmap.bmWidth*wBitCount) / 32;
if((Bitmap.bmWidth*wBitCount) % 32)
biWidth++; //不是整数倍的加1
biWidth *= 4;//到这里,计算得到的为每个扫描行的字节数。
dwBmBitsSize = biWidth * Bitmap.bmHeight;//得到大小
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板  
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS);
//恢复调色板  
if (hOldPal)
{
SelectPalette(hDC, hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//创建位图文件   
fh=CreateFile(lpFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh==INVALID_HANDLE_VALUE)
return FALSE;
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize , &dwWritten, NULL);
//清除  
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
如果只保存当前彩色图片。那么可以添加一个CButton按钮。ID:IDC_SAVEBMP Caption :保存当前图片 为其添加消息映射
void CYouDlg::OnSavebmp()
{
CRect rect;
GetWindowRect(&rect);
HBITMAP hMap = CopyScreenToBitmap(rect);
SaveBitmapToFile(hMap,"C://mydlg.bmp");
}

2.把当前窗口的图片转换为黑白的。

void CYouDlg::OnChangebmp()
{

CFile   BmpFile,GrayBmp;  
BITMAPFILEHEADER bf,Dstbf;  
BITMAPINFOHEADER bi,Dstbi;  
DWORD dwLineBytes;  
BYTE *pData;  
BYTE *pGrayData;  
LPSTR                               lpPtr;  
LPSTR                               lpTempPtr;  
int                                 x,y;  
float                               Y;//YUV中存Y的值,就是灰度值  
DWORD                               i;//临时变量  
BYTE Red,Green,Blue,Gray;  
DWORD SrcBuf,DstBuf;  
   
BmpFile.Open("C://mydlg.bmp",CFile::modeRead|CFile::typeBinary);  
BmpFile.Read(&bf,sizeof(BITMAPFILEHEADER));  
BmpFile.Read(&bi,sizeof(BITMAPINFOHEADER));  
dwLineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);  
SrcBuf=dwLineBytes*bi.biHeight;  
pData=(BYTE   *)new   BYTE[SrcBuf];  
BmpFile.Read(pData,SrcBuf);  
BmpFile.Close();  
memcpy((char   *)&Dstbf,(char   *)&bf,sizeof(BITMAPFILEHEADER)); //做必要的改变  
Dstbf.bfSize=(DWORD)(sizeof(BITMAPFILEHEADER)  
+sizeof(BITMAPINFOHEADER)  
+256*sizeof(RGBQUAD)  
+WIDTHBYTES(bi.biWidth*8)*bi.biHeight);//文件大小  
Dstbf.bfOffBits=(DWORD)(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD));//文件头到存放图像数据的偏移量  
   
memcpy((char   *)&Dstbi,(char   *)&bi,sizeof(BITMAPINFOHEADER));  
Dstbi.biClrUsed=0;  
          Dstbi.biBitCount=8;//256级灰度图是8位的  
Dstbi.biSizeImage=(DWORD)WIDTHBYTES(Dstbi.biWidth*8)*Dstbi.biHeight;  
   
pGrayData=(BYTE   *)new   BYTE[Dstbi.biSizeImage+256*sizeof(RGBQUAD)];  
     
lpPtr=(char   *)pData;  
lpTempPtr=(char   *)pGrayData;  
   
for   (i   =   0;   i   <   256;   i++)    
   {   //灰度从(0,0,0)到(255,255,255),灰度调色板  
       *(lpTempPtr++)=(unsigned   char)i;  
       *(lpTempPtr++)=(unsigned   char)i;  
       *(lpTempPtr++)=(unsigned   char)i;  
       *(lpTempPtr++)=0;  
   }

for(y=0;y<bi.biHeight;y++)  
{  
lpPtr=(char   *)pData+SrcBuf-dwLineBytes-y*dwLineBytes;  
                  lpTempPtr=(char*)pGrayData+Dstbi.biSizeImage+256*sizeof(RGBQUAD)-WIDTHBYTES(bi.biWidth*8)-y*WIDTHBYTES(bi.biWidth*8);  
                    for(x=0;x<bi.biWidth;x++)  
       {  
                              Blue=(BYTE)(*lpPtr++);  
                              Green=(BYTE)(*lpPtr++);  
                              Red=(BYTE)(*lpPtr++);  
                              //   Y=(float)(Red*0.299+Green*0.587+Blue*0.114);  
      //Y=(float)(Red*0.28965+Green*0.60581+Blue*0.10454);    //灰白
   Y=(float)(Red+Green+Blue)/3;                           
      //Y=max(Blue,max(Green,Red));
   if(Y<128)
   {
    Y=0;   //RGB(0,0,0)
   }
   else
    Y=765; //RGB(255,255,255)
                              //从位图数据计算得到Y值,写入新图中  
                              Gray=(BYTE)Y;    
                              *(lpTempPtr++)=(unsigned   char)Gray;  
        }  
     }  
GrayBmp.Open("C://mydlg1.bmp",CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);  
GrayBmp.Write(&Dstbf,sizeof(BITMAPFILEHEADER));  
GrayBmp.Write(&Dstbi,sizeof(BITMAPINFOHEADER));  
GrayBmp.Write(pGrayData,256*sizeof(RGBQUAD)+Dstbi.biSizeImage);  
GrayBmp.Close();  
delete[] pData;  
delete[] pGrayData;  
   

}

3.打印转换后的黑白对话框。
void CYouDlg::PrintBmp()
{
CDC   memDC;  
CClientDC   dc(this);  
   
int   bmpWidth   =   1600;  
int   bmpHeight   =   500;  
memDC.CreateCompatibleDC(   &dc   );  
CBitmap   *   bitmap   =   new   CBitmap();  
   
HBITMAP   hBitmap   =   NULL;    
hBitmap   =   (HBITMAP)LoadImage(NULL,   "C://mydlg1.bmp",   IMAGE_BITMAP,   0,   0,    
LR_LOADFROMFILE   |   LR_CREATEDIBSECTION   |   LR_DEFAULTSIZE);    
bitmap->Attach(hBitmap);    
   
CBitmap   *   pOldBitmap   =   (CBitmap   *)   memDC.SelectObject(   bitmap   );  
if   (pOldBitmap   ==   NULL)   //   if   bitmap   is   very   big,   better   check   this   !  
{  
memDC.DeleteDC();  
delete   bitmap;  
return;  
}  
   
CDC   prtDC;  
CPrintInfo   printInfo;  
CSize   size;  
DOCINFO   di;  
CString   szPortName,   szAppName,   szPrintError;  
szAppName.LoadString(AFX_IDS_APP_TITLE);  
szPrintError   =   "";  
   
CSize   paper_size;     //printer   paper   size   in   mm  
int   xLogPPI   =   0;  
int   yLogPPI   =   0;  
   
if(   AfxGetApp()->GetPrinterDeviceDefaults(&printInfo.m_pPD->m_pd)   )  
{  
HDC   hDC   =   printInfo.m_pPD->m_pd.hDC;  
if   (hDC   ==   NULL)  
hDC   =   printInfo.m_pPD->CreatePrinterDC();  
if(hDC   !=NULL)  
{  
prtDC.Attach(hDC);  
paper_size.cx   =   prtDC.GetDeviceCaps(HORZSIZE);  
paper_size.cy   =   prtDC.GetDeviceCaps(VERTSIZE);  
xLogPPI   =   prtDC.GetDeviceCaps(LOGPIXELSX);  
yLogPPI   =   prtDC.GetDeviceCaps(LOGPIXELSY);  
}  
else    
{  
AfxMessageBox("Can   not   find   printer.   Please   check   installed/default   printers.");  
return;  
}  
}  
int   scr_xLogPPI   =   dc.GetDeviceCaps(LOGPIXELSX);  
int   scr_yLogPPI   =   dc.GetDeviceCaps(LOGPIXELSY);  
int   paper_width   =   (int)   ((double)   paper_size.cx   *   (double)   xLogPPI   /   25.4);       //width   of   a   printed   page   in   pixels  
int   paper_height   =   (int)   ((double)   paper_size.cy   *   (double)   yLogPPI   /   25.4);  
double   ratio_x   =   (double)   xLogPPI   /   (double)   scr_xLogPPI;  
double   ratio_y   =   (double)   yLogPPI   /   (double)   scr_yLogPPI;  
   
CString   strPageNumber   =   "";  
   
int   page_info_left   =   (int)   (   (double)   paper_width   *   0.9   );  
int   page_info_right   =   paper_width;  
int   page_info_top   =   (int)   (   (double)   paper_height   *   0.99);  
int   page_info_bottom   =   paper_height;  
CRect   page_info_rect   =   CRect(page_info_left,   page_info_top,    
                                                              page_info_right,page_info_bottom   );  
int   printed_pages   =   0;  
int   total_print_pages   =   0;  
BOOL   bAbort_print   =   FALSE;  
   
//   calculate   pages  
          int   total_pages   =   (bmpWidth   *   ratio_x   +   paper_width   -   1   )   /   paper_width;  
//pop   up   printer   dialog  
CPrintDialog   prtDlg(FALSE,   PD_PAGENUMS);  
   
prtDlg.m_pd.nMinPage   =   1;
//total_pages=1;
prtDlg.m_pd.nMaxPage   =   total_pages;   //等于3
prtDlg.m_pd.nFromPage   =   1;
//total_pages=1;
prtDlg.m_pd.nToPage   =   total_pages;   //等于3
   
if(prtDlg.DoModal()   ==   IDOK   )  
{  
memset(&di,   0,   sizeof(DOCINFO));  
di.cbSize   =   sizeof(DOCINFO);  
di.lpszDocName   =   szAppName;  
szPortName   =   prtDlg.GetPortName();  
di.lpszOutput   =   szPortName;  
prtDC.m_bPrinting   =   TRUE;  
}  
else  
return;     //Cancel   button   pressed,   don't   forget   this!  
   
if(prtDC.StartDoc(&di)   ==   -1)  
{  
AfxMessageBox("Printing   error   occured.   Unable   to   find   printer.");  
prtDC.Detach();  
prtDC.DeleteDC();  
return;  
}  
   
prtDC.SetMapMode(MM_TEXT);  
   
int   i   =   0;  
for(i   =   0;   i   <   1;   i++)  
{  
prtDC.StartPage();  
strPageNumber.Format("Page:%d   of   %d",   ++printed_pages,   total_print_pages   );  
   
if   (   i   ==   (total_pages   -   1)   &&   total_pages   >   1   )   //last   page  
{  
int   last_bmpWidth   =   bmpWidth   -   paper_width   /   ratio_x   *   i;  
prtDC.StretchBlt(0,   0,   last_bmpWidth   *   ratio_x,   bmpHeight*   ratio_y,   &memDC,  
          paper_width   *   i   /   ratio_x,   0,   last_bmpWidth,   bmpHeight,   SRCCOPY);  
}  
else  
prtDC.StretchBlt(0,   0,   paper_width,   bmpHeight*   ratio_y,   &memDC,  



paper_width   *   i   /   ratio_x,   0,   paper_width   /   ratio_x   ,   bmpHeight,   SRCCOPY);  
prtDC.TextOut(page_info_rect.left,   page_info_rect.top,   strPageNumber   );  
   
prtDC.EndPage();  
}  
memDC.SelectObject(pOldBitmap);  
delete   bitmap;  
memDC.DeleteDC();  
   
prtDC.EndDoc();  
prtDC.Detach();  
prtDC.DeleteDC();  
return;  
}

如果打印成黑白,那么可以添加一个CButton按钮。ID:IDC_PRINTBMP Caption :打印   为其添加消息映射
void CYouDlg::OnPrint()
{
CRect rect;
GetWindowRect(&rect);
HBITMAP hMap = CopyScreenToBitmap(rect);
SaveBitmapToFile(hMap,"C://mydlg.bmp");
OnChangebmp();
PrintBmp();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值