多线程后台打印程序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haimianjie2012/article/details/86497228

**.cpp

//
// Asks user which printer to use, then creates
// background printing thread.
//
void PrintText(HWND hwndParent, char *pszText)

PrintText

// BackPrint_win32.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "BackPrint_win32.h"
#include "MtVerify.h"
#include <windowsx.h>
#include <commdlg.h>
//
// Macro definitions
//
#define WM_SHOWBITMAP   WM_APP
#define MAX_LOADSTRING 100
//
// Structures
//
typedef struct
{   // Information passed to background thread for printing
	HWND hDlg;
	HWND hWndParent;
	HDC hDc;
	BOOL bPrint;    // TRUE if printing;
	char szText[256];
} ThreadPrintInfo;
// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name
HBITMAP gbmpDisplay;
RECT gDisplayRect;

int gNumPrinting;
// Handle to each created thread
HANDLE gPrintJobs[64];
// Height of bitmap returned by DrawText
int iHeight;

// HWND of the dialog so other threads can find it.
HWND hDlgMain;

// Forward declarations of functions included in this code module:
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK MainWndProc(HWND hWnd, unsigned msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK PrintDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL PrintDlg_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam);
void PrintDlg_OnCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
void PrintDlg_OnPaint(HWND hwnd);
void PrintText(HWND hwndParent, char *pszText);
void PrintToDisplay(HWND hwndParent, char *pszText);
DWORD WINAPI BackgroundPrintThread(LPVOID pVoid);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	MSG     msg;
	HWND    hWnd;
	WNDCLASS wc;
	int index;

	hInst = hInstance;
	if (!hPrevInstance)
	{
		memset(&wc, 0, sizeof(wc));
		wc.lpfnWndProc  = MainWndProc;
		wc.hInstance    = hInstance;
		wc.hIcon        = LoadIcon (hInstance, "GenIco");
		wc.hCursor      = LoadCursor(NULL,IDC_ARROW);
		wc.hbrBackground= GetSysColorBrush(COLOR_BACKGROUND);
		wc.lpszMenuName = "PRINTING_MENU";
		wc.lpszClassName= "PrintDlgClass";
		if (!RegisterClass(&wc))
			return FALSE;
	}


	hWnd = CreateWindow(
		"PrintDlgClass",
		"Background Printing",
		WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU,
		CW_USEDEFAULT, // At this point we do not want to
		0,             //  show the window until we know
		0,             //  how big the Dialog Box is so
		0,             //  that we can fit the main window
		NULL,          //  around it.
		NULL,
		hInstance,
		NULL);

	hDlgMain = CreateDialog(hInst,
		MAKEINTRESOURCE(IDD_PRINT),
		hWnd, (DLGPROC)PrintDlgProc);

	ShowWindow(hWnd, nCmdShow);
	ShowWindow(hDlgMain, SW_SHOW);

	while (GetMessage(&msg, NULL, 0, 0))
	{	// Get Next message in queue
		if(hDlgMain == NULL || !IsDialogMessage(hDlgMain,&msg))
		{
			TranslateMessage(&msg); /* Translate virtual key codes */
			DispatchMessage(&msg);	/* Dispatches message to window */
		}
	} // end while

	// Wait for all threads to terminate. The Window will
	// have already disappeared by this point.
	for (index = 0; index < gNumPrinting; index++)
	{
		DWORD status;
		do 
		{	// Wait for thread to terminate
			GetExitCodeThread(gPrintJobs[index], &status);
			Sleep(10);
		} while (status == STILL_ACTIVE);

	} // end for


	return (int) msg.wParam;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}
LRESULT CALLBACK MainWndProc(HWND hWnd, unsigned msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_CREATE:
		break;

	case WM_COMMAND:

		switch (wParam)
		{
		case IDM_ABOUT:
			DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
			break;
		case IDM_EXIT:
			PostQuitMessage(0);
			break;
		default:
			return (DefWindowProc(hWnd, msg, wParam, lParam));
		}

	case WM_SETFOCUS:
		// ensure that the Dialog Box has the focus
		SetFocus(hDlgMain);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, msg, wParam, lParam);

	}
	return 0;
}

LRESULT CALLBACK PrintDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CLOSE:
		DestroyWindow(hDlg);
		hDlgMain = NULL;
		break;

	case WM_DESTROY:
		return TRUE;
		break;

	case WM_SHOWBITMAP:
		if (gbmpDisplay)
			DeleteObject(gbmpDisplay);

		gDisplayRect = *(RECT*)wParam;
		gbmpDisplay = (HBITMAP) lParam;
		InvalidateRect(hDlgMain, NULL, TRUE);
		break;

		HANDLE_MSG(hDlg, WM_INITDIALOG, PrintDlg_OnInitDialog);
		HANDLE_MSG(hDlg, WM_COMMAND, PrintDlg_OnCommand);
		HANDLE_MSG(hDlg, WM_PAINT, PrintDlg_OnPaint);

	default:
		return (FALSE);
	}

	return 0;
}

BOOL PrintDlg_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam)
{
	RECT rect;

	// Size parent to fit this dialog
	GetWindowRect(hwndDlg, &rect); 
	SetWindowPos(GetParent(hwndDlg),NULL,
		0,0,
		rect.right-rect.left,
		rect.bottom-rect.top+GetSystemMetrics(SM_CYMENU)
		+GetSystemMetrics(SM_CYCAPTION),
		SWP_NOMOVE | SWP_NOZORDER);

	return TRUE;
}

void PrintDlg_OnCommand(HWND hDlg, int id,HWND hwndCtl, UINT codeNotify)
{
	char szText[256];

	switch (id)
	{
	case IDC_PRINT:
		GetDlgItemText(hDlg, IDC_EDIT_TEXT, szText, 256);
		PrintText(hDlg, szText);
		break;

	case IDC_DISPLAY:
		GetDlgItemText(hDlg, IDC_EDIT_TEXT, szText, 256);
		PrintToDisplay(hDlg, szText);
		break;

	case IDCANCEL:
	case IDM_EXIT:
		PostMessage(GetParent(hDlg),WM_DESTROY,
			(WPARAM)0, (LPARAM)0);
		DestroyWindow(hDlgMain);
		hDlgMain = NULL;
		break;

	default:
		break;
	}
}

void PrintDlg_OnPaint( HWND hwnd )
{
	PAINTSTRUCT paint;
	HWND hwndCtrl;
	HDC hdc;
	HDC hDcMem;
	HBITMAP bmpOld;
	RECT rect;
	POINT point;

	if (!gbmpDisplay)
		return;

	hwndCtrl = GetDlgItem(hwnd, IDC_OUTPUT);

	hdc = BeginPaint(hwnd, &paint);

	GetWindowRect(hwndCtrl, &rect);
	point = *((POINT *)&rect);
	ScreenToClient(hwnd, &point);

	hDcMem = CreateCompatibleDC(NULL);
	bmpOld = (HBITMAP)SelectObject(hDcMem, gbmpDisplay);

	// Copy bitmap to screen
	MTVERIFY( BitBlt(hdc, point.x+10, point.y+40,
		gDisplayRect.right-gDisplayRect.left, gDisplayRect.bottom-gDisplayRect.top,
		hDcMem, iHeight, 0, SRCCOPY) );

	SelectObject(hDcMem, bmpOld);
	DeleteDC(hDcMem);

	EndPaint(hwnd, &paint);
}

//
// Asks user which printer to use, then creates
// background printing thread.
//
void PrintText(HWND hwndParent, char *pszText)
{
	ThreadPrintInfo *pInfo;
	HANDLE hThread;
	DWORD dwThreadId;
	int result;
	DOCINFO docInfo;

	PRINTDLG dlgPrint;

	// Put up Common Dialog for Printing and get hDC.
	memset(&dlgPrint, 0, sizeof(PRINTDLG));
	dlgPrint.lStructSize = sizeof(PRINTDLG);
	dlgPrint.hwndOwner = hwndParent;
	dlgPrint.Flags = PD_ALLPAGES | PD_USEDEVMODECOPIES
		| PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
	dlgPrint.hInstance = hInst;
	if (!PrintDlg(&dlgPrint))
		return;

	// Initialize Printer device
	docInfo.cbSize = sizeof(DOCINFO);
	docInfo.lpszDocName = "Background Printing Example";
	docInfo.lpszOutput = NULL;
	docInfo.lpszDatatype = NULL;
	docInfo.fwType = 0;
	result = StartDoc(dlgPrint.hDC, &docInfo);
	result = StartPage(dlgPrint.hDC);

	pInfo = (ThreadPrintInfo *)HeapAlloc(GetProcessHeap(),
		HEAP_ZERO_MEMORY,
		sizeof(ThreadPrintInfo));
	pInfo->hDlg = hwndParent;
	pInfo->hWndParent = hwndParent;
	pInfo->hDc = dlgPrint.hDC;
	pInfo->bPrint = TRUE;
	strcpy(pInfo->szText, pszText);

	MTVERIFY( hThread = CreateThread(NULL, 0,
		BackgroundPrintThread, (LPVOID)pInfo,
		0, &dwThreadId ));

	// keep track of all background printing threads
	gPrintJobs[gNumPrinting++] = hThread;
}


//
// Shows output on the dialog box.
//
void PrintToDisplay(HWND hwndParent, char *pszText)
{
	ThreadPrintInfo *pInfo;
	DWORD dwThreadId;
	HANDLE hThread;

	pInfo = (ThreadPrintInfo *)HeapAlloc(GetProcessHeap(),
		HEAP_ZERO_MEMORY,
		sizeof(ThreadPrintInfo));
	pInfo->hDlg = hwndParent;
	pInfo->hWndParent = GetDlgItem(hwndParent, IDC_OUTPUT);
	pInfo->hDc = GetDC(pInfo->hWndParent);
	pInfo->bPrint = FALSE;
	strcpy(pInfo->szText, pszText);

	MTVERIFY( hThread = CreateThread(NULL, 0,
		BackgroundPrintThread,
		(LPVOID)pInfo,
		0, &dwThreadId ));

	// keep track of all background printing threads
	gPrintJobs[gNumPrinting++] = hThread;
}

//---------------------------------------------------------
// Background Printing Code
//---------------------------------------------------------

DWORD WINAPI BackgroundPrintThread(LPVOID pVoid)
{
	ThreadPrintInfo *pInfo = (ThreadPrintInfo*) pVoid; 
	RECT rect;
	RECT rectMem;
	HDC hDcMem;
	HBITMAP bmpMem;
	HBITMAP bmpOld;
	int x, y;
	int counter = 0;
	int nHeight;
	HFONT hFont;
	HFONT hFontOld;

	// Get dimensions of paper into rect
	rect.left = 0;
	rect.top = 0;
	rect.right =  GetDeviceCaps(pInfo->hDc, HORZRES);
	rect.bottom = GetDeviceCaps(pInfo->hDc, VERTRES);

	nHeight = -MulDiv(36, GetDeviceCaps(pInfo->hDc, LOGPIXELSY), 72);

	// Create Font
	hFont = CreateFont(nHeight, 0, 
		0, 0, FW_DONTCARE, 
		FALSE, FALSE, FALSE, 
		ANSI_CHARSET, 
		OUT_TT_PRECIS, 
		CLIP_DEFAULT_PRECIS,
		PROOF_QUALITY, 
		VARIABLE_PITCH,
		NULL);
	MTASSERT( hFont != 0);

	// Draw into memory device context
	hDcMem = CreateCompatibleDC(pInfo->hDc);
	hFontOld = (HFONT)SelectObject(hDcMem, hFont);
	iHeight = DrawText(hDcMem, pInfo->szText, -1,  &rect, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
	rectMem = rect;
	rectMem.left = rect.left + iHeight;
	rectMem.right = rect.right + (iHeight*2);
	bmpMem = CreateCompatibleBitmap(hDcMem,
		rectMem.right, rect.bottom);
	bmpOld = (HBITMAP)SelectObject(hDcMem, bmpMem);
	OffsetRect(&rect, iHeight, 0); 
	DrawText(hDcMem, pInfo->szText, -1,  &rect,
		DT_LEFT | DT_NOPREFIX | DT_WORDBREAK);

	// Italicize bitmap. We use GetPixel and
	// SetPixel because they are horribly inefficient,
	// thereby causing the thread to run for awhile.
	for (y = 0; y < iHeight; y++)
	{   // Italicize line y
		for (x = rectMem.right; x > iHeight; x--)
		{   // Move specified pixel to the right.
			COLORREF color;
			int offset;
			offset = y - iHeight;
			color = GetPixel(hDcMem, x + offset, y);
			if (color != 0)
				counter++;
			SetPixel(hDcMem, x, y, color);
		} // end for x
	} // end for y
	MTASSERT( counter > 0);

	// Copy bitmap of italicized text from memory to device
	if (pInfo->bPrint)
	{
		BitBlt(pInfo->hDc, 50, 50, rectMem.right-rect.left, rectMem.bottom-rect.top,
			hDcMem, iHeight, 0, SRCCOPY);
	}

	SelectObject(hDcMem, hFontOld);
	SelectObject(hDcMem, bmpOld);
	DeleteDC(hDcMem);

	if (!pInfo->bPrint)
	{
		// We can't just write to the global variable where the
		// bitmap is kept or we might overwrite the work of
		// another thread, thereby "losing" a bitmap

		// Also, if we used PostMessage instead of SendMessage, then
		// the rectangle could have been deleted (it's on the stack)
		// by the time the main message loop is reached.
		SendMessage(pInfo->hDlg, WM_SHOWBITMAP, (WPARAM)&rectMem, (LPARAM) bmpMem);
	}

	if (pInfo->bPrint)
	{   // Finish printing
		int result;

		result = EndPage(pInfo->hDc);
		MTASSERT (result != SP_ERROR);
		result = EndDoc(pInfo->hDc);
		MTASSERT (result != SP_ERROR);
		DeleteDC(pInfo->hDc);
		// If we are printing, we are done with the bitmap.
		DeleteObject(bmpMem);
	} 
	else
	{
		ReleaseDC(pInfo->hWndParent, pInfo->hDc);
	}

	// free data structure passed in.
	HeapFree(GetProcessHeap(), 0, pInfo);

	return 0;
}

resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by BackPrint_win32.rc
//

#define IDS_APP_TITLE			103

#define IDR_MAINFRAME			128
#define IDD_BACKPRINT_WIN32_DIALOG	102
#define IDD_ABOUTBOX			103
#define IDM_ABOUT				104
#define IDM_EXIT				105
#define IDI_BACKPRINT_WIN32			107
#define IDI_SMALL				108
#define IDC_BACKPRINT_WIN32			109
#define IDC_EDIT_TEXT                   1000
#define IDC_OUTPUT                      1001
#define IDD_PRINT                       1002
#define IDC_PRINT                       1003
#define IDC_DISPLAY                     1004
#define IDC_BITMAP                      1005

#define IDC_MYICON				2
#ifndef IDC_STATIC
#define IDC_STATIC				-1
#endif
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NO_MFC					130
#define _APS_NEXT_RESOURCE_VALUE	129
#define _APS_NEXT_COMMAND_VALUE		32771
#define _APS_NEXT_CONTROL_VALUE		1000
#define _APS_NEXT_SYMED_VALUE		110
#endif
#endif

资源文件:

**.rc

//Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1

/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.

IDI_BACKPRINT_WIN32       ICON         "BackPrint_win32.ico"
IDI_SMALL               ICON         "small.ico"

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDC_BACKPRINT_WIN32 MENU
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "E&xit",                IDM_EXIT
    END
    POPUP "&Help"
    BEGIN
        MENUITEM "&About ...",           IDM_ABOUT
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//

IDC_BACKPRINT_WIN32 ACCELERATORS
BEGIN
    "?",            IDM_ABOUT,              ASCII,  ALT
    "/",            IDM_ABOUT,              ASCII,  ALT
END


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About BackPrint_win32"
FONT 8, "MS Shell Dlg"
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
    LTEXT           "BackPrint_win32, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2019",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "OK",IDOK,113,41,50,14,WS_GROUP
END

IDD_PRINT DIALOGEX 0, 0, 236, 137
STYLE WS_CHILD
EXSTYLE WS_EX_CLIENTEDGE
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
    LTEXT           "&Enter Text to Print:",IDC_STATIC,7,7,54,8
    EDITTEXT        IDC_EDIT_TEXT,7,17,222,14,ES_AUTOHSCROLL
    PUSHBUTTON      "&Display",IDC_DISPLAY,7,37,50,14
    PUSHBUTTON      "&Print",IDC_PRINT,65,37,50,14
    GROUPBOX        "Output",IDC_OUTPUT,7,58,222,72
    CONTROL         "",IDC_BITMAP,"Static",SS_BITMAP | SS_REALSIZEIMAGE,15,
                    74,18,20
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 163
        TOPMARGIN, 7
        BOTTOMMARGIN, 55
    END
	 
	IDD_PRINT, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 229
        TOPMARGIN, 7
        BOTTOMMARGIN, 130
    END
END
#endif    // APSTUDIO_INVOKED

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE
BEGIN
    "#ifndef APSTUDIO_INVOKED\r\n"
    "#include ""targetver.h""\r\n"
    "#endif\r\n"
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""windows.h""\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "\0"
END

3 TEXTINCLUDE
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE
BEGIN
   IDC_BACKPRINT_WIN32   "BACKPRINT_WIN32"
   IDS_APP_TITLE       "BackPrint_win32"
END

#endif
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//

/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

猜你喜欢

转载自blog.csdn.net/haimianjie2012/article/details/86497228