以前竟然没有做过打印的程序(为了省事,曾经使用word automation打印过)。突然要打印文字和图片,而且不能再使用word了,就花了一点时间理解map mode和打印,或许这些内容对您也有点用,原理很简单,能省一些您打字的功夫也不错:-)
//Author: Onega
#include <windows.h>
#include <stdio.h>
LPCTSTR bmp_filename = "C:\\test\\PrintDemo\\res\\Toolbar.bmp";
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) ;
HWND hwMain;
HANDLE hbmp = NULL;
const int ID_FILE_PRINT = __LINE__;
int get_line_height(HDC hdc)
{ //return text line height
//return value < 0 if map mode is not MM_TEXT, so that you can always use
//y+= line_height when drawing to device.
int map_mode = GetMapMode(hdc);
TEXTMETRIC tm;
GetTextMetrics(hdc,&tm);
int h = tm.tmHeight + tm.tmExternalLeading;
if(MM_TEXT != map_mode)
h = 0 - h;
return h;
}
double get_screen_pixel_width(int map_mode)
{ //purpose: a pixel displayed in MM_TEXT mode should be about the same size
//when displayed in other map mode.
HDC hdc = GetDC(NULL);
double hroz_size = GetDeviceCaps(hdc,HORZSIZE);//Width, in millimeters, of the physical screen.
double horz_res = GetDeviceCaps(hdc, HORZRES);//Width, in pixels, of the screen.
double pixel_width = hroz_size / horz_res; // Width, in millimeters
// 1 inch = 25.4 mm
const double INCH_TO_MM = 25.4;
const double INCH_TO_TWIP = 1440;
switch(map_mode)
{
case MM_LOMETRIC:
pixel_width *= 10;
break;
case MM_HIMETRIC:
pixel_width *= 100;
break;
case MM_TEXT:
break;
case MM_LOENGLISH: //Each logical unit is mapped to 0.01 inch
pixel_width = pixel_width / INCH_TO_MM * 100;
break;
case MM_HIENGLISH: //Each logical unit is mapped to 0.001 inch
pixel_width = pixel_width / INCH_TO_MM * 1000;
break;
case MM_TWIPS: //Each logical unit is mapped to one twentieth of a printer's point (1/1440 inch, also called a twip).
pixel_width = pixel_width / INCH_TO_MM * INCH_TO_TWIP;
break;
default:
break;
}
return pixel_width;//Width, in logical units according to the map_mode
}
void draw(HDC hdc)
{
if(hbmp == NULL)
{
hbmp = (HANDLE)LoadImage( NULL,bmp_filename ,
IMAGE_BITMAP, 0,0,LR_LOADFROMFILE);
}
int map_mode = MM_TWIPS;
LPCTSTR map_name = "MM_TWIPS";
SetMapMode(hdc,map_mode); //Each logical unit is mapped to 0.1 millimeter.
int x = 0;
int y = 0;
int line_h = get_line_height(hdc);
SelectObject(hdc,GetStockObject(BLACK_PEN));
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc,x, y,map_name,strlen(map_name));
y += line_h;
if( NULL != hbmp)
{
BITMAP bm;
GetObject( hbmp, sizeof(BITMAP), &bm );
long width=bm.bmWidth;
long height=bm.bmHeight;
HDC memdc = CreateCompatibleDC(hdc);
HGDIOBJ oldbmp = SelectObject(memdc,hbmp);
double pixel_size = get_screen_pixel_width(map_mode);
int bmp_draw_width = (int)(width * pixel_size) ;
int bmp_draw_height = (int)(height * pixel_size) ;
StretchBlt(hdc,x,y, bmp_draw_width ,-bmp_draw_height, memdc, 0,0,width,height,SRCCOPY);
SelectObject(memdc,oldbmp);
DeleteDC(memdc);
}
else
{
LPCTSTR error_msg = "failed to load bitmap from file";
TextOut(hdc,x,y,error_msg,strlen(error_msg));
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
WNDCLASSEX wndclass ;
HMENU hMenu,hMenuA;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "PrintDemo";
wndclass.hIconSm = NULL;
RegisterClassEx (&wndclass);
hwMain=CreateWindow (wndclass.lpszClassName,NULL,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,500,568,NULL,NULL,hInstance,NULL);
hMenu=CreateMenu();
hMenuA=CreateMenu();
AppendMenu(hMenuA,MF_STRING,ID_FILE_PRINT,"Print");
AppendMenu(hMenu,MF_POPUP,(UINT)hMenuA,"File");
SetMenu(hwMain,hMenu);
ShowWindow (hwMain,iCmdShow);
UpdateWindow (hwMain);
while (GetMessage (&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam ;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static PRINTDLG pd;
static DOCINFO dci;
static LPTSTR lpszDocName="Print Test";
switch (iMsg)
{
case WM_CREATE:
pd.lStructSize=sizeof(pd);
pd.hwndOwner=hwnd;
pd.hDevMode=NULL;
pd.hDevNames=NULL;
pd.Flags=PD_RETURNDC|PD_HIDEPRINTTOFILE |PD_RETURNDEFAULT;
pd.nFromPage=1;
pd.nToPage=1;
pd.nMinPage=1;
pd.nMaxPage=1;
pd.nCopies=1;
dci.cbSize=sizeof(dci);
dci.lpszDocName=lpszDocName;
dci.lpszOutput=NULL;
dci.lpszDatatype=NULL;
dci.fwType=0;
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_FILE_PRINT:
if (!PrintDlg(&pd))
return 0;
hdc=pd.hDC;
StartDoc(hdc,&dci);
StartPage(hdc);
draw(hdc);
EndPage(hdc);
EndDoc(hdc);
break;
}
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
draw(hdc);
EndPaint(hwnd,&ps);
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}