//Demostrate multithread multitasking
/*
The sample application illustrates how to implement the Locking Mechanism of the PDF Converter.
The Lock() function can be used in multi-threading situations to avoid conflicts between multiple applications
or multiple threads requesting simultaneous access the Converter products.

The CDIntf library uses the registry to interact with the printer drivers. When the Lock function is used,
the output file name and options are set using the SetDocFileProps function and not from the SetDefaultFileName
and SetFileNameOptions functions.

What the Lock() function actually does is reserve a private area where the settings for that specific job are set.
SetDocFileProps sets the preferences for the print job and when the job is being printed, the spooler gets the
settings for that job and then deletes that private place.

The Unlock function is used after printing has ended to make sure another printout can start. The call to Unlock
is needed only in the case where an error occurs; the printer will otherwise call Unlock internally as soon as
printing starts to allow another printout to occur in parallel. The Timeout value represents the Timeout in
milliseconds after which the function returns.
*/





//#using <mscorlib.dll>

#include <afxwin.h>
#include <string.h>
#include <stdlib.h>



#include "ids.h"
#include "thread.h"



UINT MyThread(LPVOID WinObjPtr);

int ThreadId = 0;
int maxX, maxY;



/////////////////////////////////////////////////////////////////////////////
// CAmPdfTestView message handlers

#define NoPrompt			0x00000001	// do not prompt for file name
#define UseFileName			0x00000002	// use file name set by SetDefaultFileName else use document name
#define EmbedFonts			0x00000010	// embed fonts used in the input document
#define BroadcastMessages	0x00000020	// broadcast PDF events
#define MultilingualSupport	0x00000080	// activate multi-lingual support
#define EmbedStandardFonts	0x00200000	// embed standard fonts such as Arial, Times, ...
#define EmbedLicensedFonts	0x00400000	// embed fonts requiring a license



typedef long (CALLBACK* PDFDriverInitProc)(LPCSTR Printer);
typedef long (CALLBACK* DriverInitProc)(LPCSTR Printer);
typedef void (CALLBACK* DriverEndProc)(long hPrinter);
typedef long (CALLBACK* SetDefaultConfigProc)(long hPrinter);
typedef long (CALLBACK* SetDefaultPrinterProc)(long hPrinter);
typedef long (CALLBACK* RestoreDefaultPrinterProc)(long hPrinter);
typedef long (CALLBACK* EnablePrinterProc)(long hPrinter, LPCSTR szCompany, LPCSTR szCode);

/********** Print Job Locking Functions **********/
typedef long (CALLBACK* LockProc)(long hPrinter, LPCSTR szLockName);
typedef long (CALLBACK* UnlockProc)(long hPrinter, LPCSTR szLockName, long dwTimeout);
typedef long(CALLBACK* SetDocFilePropsProc)(long hPrinter, LPCSTR szDocTitle, long lOptions, LPCSTR szFileDir, LPCSTR szFileName);


// set the destination window for notification messages
typedef long(CALLBACK* SendMessagesToProc)(long hPrinter, LPCSTR szWndClass);

LockProc Lock = NULL;
UnlockProc Unlock = NULL;
SetDocFilePropsProc	SetDocFileProps = NULL;

SendMessagesToProc SendMessagesTo = NULL;


PDFDriverInitProc PDFDriverInit = NULL;
DriverInitProc DriverInit = NULL;
DriverEndProc PDFDriverEnd = NULL;
SetDefaultPrinterProc SetDefaultPrinter = NULL;
RestoreDefaultPrinterProc RestoreDefaultPrinter = NULL;
EnablePrinterProc EnablePrinter = NULL;

#define STRLICENSETO			"Amyuni PDF Converter Evaluation"
#define STRACTIVATIONCODE		"07EFCDAB0100010025AFF1801CB9441306C5739F7D452154D8833B9CECBA2ADE79E3762A69FFC354528A5F4A5811BE3204A0A439F5BA"
#define AMYUNI_PRINTER_NAME		"Amyuni PDF Converter"

LPCSTR szPrinter = AMYUNI_PRINTER_NAME;
HINSTANCE hLib = NULL;
long pdfPrinter;
int bInit = NULL;







//Construct main window
CMainWIn::CMainWIn()
{
	Create(NULL, "MultiThreadExample", WS_OVERLAPPEDWINDOW, rectDefault, NULL, "THREADMENU");

	//Load accelertator table
	if (!LoadAccelTable("THREADMENU"))
		MessageBox("Cannot Load Accelerators", "Error");

	//Can remove stuff below
	m_x = m_y = 0;

	maxY = GetSystemMetrics(SM_CXSCREEN);
	maxY = GetSystemMetrics(SM_CYSCREEN);

	CClientDC DC(this);

	//create bitmap for virtual window
	m_memDC.CreateCompatibleDC(&DC);
	m_bmp.CreateCompatibleBitmap(&DC, maxX, maxY);

	m_memDC.SelectObject(&m_bmp);

	//use standard background
	m_bkbrush.CreateStockObject(BLACK_BRUSH);
	m_memDC.SelectObject(&m_bkbrush);

	//paint background of virtual window
	m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY);
	//////




}
//Initialize the application
BOOL CApp::InitInstance()
{

	m_pMainWnd = new CMainWIn;
	m_pMainWnd->ShowWindow(m_nCmdShow);
	m_pMainWnd->UpdateWindow();

	bInit = 0;

	// dynamically load the library. 
	//This should be done in InitInstance 
	hLib = LoadLibrary(_T("CDIntf600.dll"));
	if (NULL == hLib)
	{
		return FALSE;
	}

	// get exported functions addresses 
	PDFDriverInit = (PDFDriverInitProc)GetProcAddress(hLib, _T("PDFDriverInit"));
	DriverInit = (DriverInitProc)GetProcAddress(hLib, _T("DriverInit"));
	PDFDriverEnd = (DriverEndProc)GetProcAddress(hLib, _T("DriverEnd"));
	SetDefaultPrinter = (SetDefaultPrinterProc)GetProcAddress(hLib, _T("SetDefaultPrinter"));
	RestoreDefaultPrinter = (RestoreDefaultPrinterProc)GetProcAddress(hLib, _T("RestoreDefaultPrinter"));
	EnablePrinter = (EnablePrinterProc)GetProcAddress(hLib, _T("EnablePrinter"));

	SendMessagesTo = (SendMessagesToProc)GetProcAddress(hLib, _T("SendMessagesTo"));

	/********** Print Job Locking Functions **********/
	Lock = (LockProc)GetProcAddress(hLib, _T("Lock"));
	Unlock = (UnlockProc)GetProcAddress(hLib, _T("Unlock"));
	SetDocFileProps = (SetDocFilePropsProc)GetProcAddress(hLib, _T("SetDocFileProps"));



	if (NULL == DriverInit ||
		NULL == PDFDriverEnd ||
		NULL == DriverInit ||
		NULL == Lock ||
		NULL == Unlock ||
		NULL == SetDocFileProps ||
		NULL == SendMessagesTo)
	{
		return FALSE;
	}

	// init the PDF Printer DWORD Err; 
	if (!bInit)
	{
		if (NULL == (pdfPrinter = (*DriverInit)(szPrinter)))
		{ // system error, exit 
			return FALSE;
		}
		bInit = 1;
	}


	return TRUE;
}

//This is the application's message map
BEGIN_MESSAGE_MAP(CMainWIn, CFrameWnd)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_COMMAND(IDM_THREAD, OnThread)
	ON_COMMAND(IDM_EXIT, OnExit)
	ON_COMMAND(IDM_HELP, OnHelp)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
//Update the screen using contents of the virual window
//currently not used
afx_msg void CMainWIn::OnPaint()
{
	CPaintDC DC(this);
	DC.BitBlt(0, 0, maxX, maxY, &m_memDC, 0, 0, SRCCOPY);
}


/////////////////////////////////////////////////////////////////////////////
//Reposition text when left mouse button is pressed
// currently not used
afx_msg void CMainWIn::OnLButtonDown(UINT Flags, CPoint Loc)
{
	m_x = Loc.x;
	m_y = Loc.y;
}


/////////////////////////////////////////////////////////////////////////////
//Process IDM_EXIT
afx_msg void CMainWIn::OnExit()
{
	int response;
	response = MessageBox("Quit the Program?", "Exit", MB_YESNO);

	if (response == IDYES)
		SendMessage(WM_CLOSE); //Terminate app 
}



/////////////////////////////////////////////////////////////////////////////
//Process IDM_HELP
afx_msg void CMainWIn::OnHelp()
{
	MessageBox("MultiThreading", "Help");
}


/////////////////////////////////////////////////////////////////////////////
//Process IDM_Thread
afx_msg void CMainWIn::OnThread()
{
	//TCHAR className[64];
	//GetClassName( m_hWnd, className, sizeof(className) );
	//(*SendMessagesTo)( pdfPrinter,  className );
	AfxBeginThread(MyThread, this);
}






/////////////////////////////////////////////////////////////////////////////
//Create worker threads and print to the PDF Converter 
UINT MyThread(LPVOID WinObjPtr)
{

	char str[255];
	int len;
	ThreadId++;

	CMainWIn *ptr = (CMainWIn *)WinObjPtr;


	//Create unique doc and filename
	CTime theTime = CTime::GetCurrentTime();
	CString strTempTime;
	CString strFileName;

	strTempTime.Format(_T("%02d%02d%02d"),
		theTime.GetHour(),
		theTime.GetMinute(),
		theTime.GetSecond());
	strFileName = "c:\\temp\\lock\\" + strTempTime + ".pdf";

	(*SetDefaultPrinter)(pdfPrinter);

	/*Create a unique document name
	---------------------------------
	The Lock() function requires the developer to pass the function the document
	title that is going to be printed. This is same document title that will appear
	in the print spooler. When implementing the Locking mechanism one way to quickly
	check how your printing application is generating document titles is to first pause
	the PDF Converter and then print to it. In the print spooler you will see the
	document name to use.
	*/
	(*Lock)(pdfPrinter, strTempTime);
	(*SetDocFileProps) (pdfPrinter, strTempTime, 3, _T(""), strFileName);

	(*EnablePrinter)(pdfPrinter, STRLICENSETO, STRACTIVATIONCODE);


	/////////////////////////////////////////////////////////////
	// Print DC
	// get printer DC 
	HDC hDC = CreateDC(_T("WINSPOOL"), szPrinter, NULL, NULL);
	if (NULL == hDC) { return FALSE; }

	// print something 
	DOCINFO di; di.cbSize = sizeof(DOCINFO);
	di.lpszDocName = strTempTime;
	//di.lpszOutput = _T("c:\\temp\\from_multi_thread.PDF"); 
	di.lpszOutput = NULL;

	StartDoc(hDC, &di);

	//This prints a 10 page document
	for (int i = 0; i < 10; i++)
	{
		len = wsprintf(str, "ThreadId# %d and Page# %d", ThreadId, i);
		StartPage(hDC);
		TextOut(hDC, 200, 200, str, len);
		EndPage(hDC);
	}
	EndDoc(hDC);

	//Unlock if problem occurs
	(*Unlock)(pdfPrinter, strTempTime, 1000);

	DeleteDC(hDC);



	/**********************************************************************
	exit PDF. This should be done in ExitInstance
	this line removes the printer that was created
	********************************************************************* */
	//(*PDFDriverEnd)(pdfPrinter);


	//(*SetFileNameOptions)(pdfPrinter, 0);
	//Add this to ExitInstance
	//FreeLibrary( hLib );


	ThreadId--;
	return 0;
}


CApp App;