// MFC_NopePadDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MFC_NopePad.h"
#include "MFC_NopePadDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMFC_NopePadDlg dialog

CMFC_NopePadDlg::CMFC_NopePadDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMFC_NopePadDlg::IDD, pParent),
	m_PageSetupDlg( PSD_RETURNDEFAULT|PSD_INTHOUSANDTHSOFINCHES )
{
	//{{AFX_DATA_INIT(CMFC_NopePadDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	// Invoke dialog to get margin defaults
	m_PageSetupDlg.DoModal();
	// Turn off the GetDefaults flag
	m_PageSetupDlg.m_psd.Flags &= (~PSD_RETURNDEFAULT);

}

void CMFC_NopePadDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMFC_NopePadDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMFC_NopePadDlg, CDialog)
	//{{AFX_MSG_MAP(CMFC_NopePadDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_SIZE()
	ON_COMMAND(IDM_EXIT, OnExit)
	ON_COMMAND(IDM_PAGESETUP, OnPagesetup)
	ON_COMMAND(IDM_PRINT, OnPrint)
	ON_COMMAND(AFX_ID_PREVIEW_CLOSE, OnIdPreviewClose)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMFC_NopePadDlg message handlers

BOOL CMFC_NopePadDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here


	CRect Rect;
	GetClientRect( &Rect );
	CEdit* pEdit = (CEdit*)GetDlgItem( IDC_EDIT );
	pEdit->MoveWindow( 0, 0, Rect.right, Rect.bottom );

	m_CurFile = "Untitled";

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMFC_NopePadDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMFC_NopePadDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMFC_NopePadDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CMFC_NopePadDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	CEdit* pEdit = (CEdit*)GetDlgItem( IDC_EDIT );	
	if( pEdit )
		pEdit->MoveWindow( 0, 0, cx, cy );
}

void CMFC_NopePadDlg::OnExit() 
{
	EndDialog( 0 );	
}

void CMFC_NopePadDlg::OnPagesetup() 
{
	m_PageSetupDlg.DoModal();	
}

void CMFC_NopePadDlg::OnPrint() 
{
	// TODO: Add your command handler code here

	// Create the CPrinterDialog object with the flags for retrieving 
	//the current printer DC.
	CPrintDialog Printer(FALSE);
	// Invoke the GetDefaults function, which will only retrieve the printer DC, and
	Printer.GetDefaults();

	if( !Printer.m_pd.hDC )
		MessageBox( "Unable to open printer" );
	else
	{
		// Get CEdit* for the Edit control in the window
		CEdit* pEdit = (CEdit*)GetDlgItem( IDC_EDIT );

		// For convenience, create a CDC object, and attach the printer HDC
		// to it.  The destructor for the CDC will automatically destroy the
		// HDC when we leave these french braces.
		CDC PrinterDC;
		PrinterDC.Attach( Printer.m_pd.hDC );

		// Start Printing
		PrinterDC.SetMapMode( MM_HIENGLISH );
		// CurFonts Height is based on screen DC.  Make one for the printer DC
		CFont ReportFont;
		PNCreatePrinterFont( pEdit, ReportFont );
		PrinterDC.SelectObject( ReportFont );

		// Determine the margins, in HIENGLISH units: 1/1000ths inches
		int Left, Right, Top, Bottom, CurY;
		PNEzMargins( m_PageSetupDlg, Left, Top, Right, Bottom );

		// Setup the DOCINFO structure so that Windows Spooler shows an
		// intelligent name for our print job
		DOCINFO DocInfo;
		memset(&DocInfo, 0, sizeof(DocInfo));
		DocInfo.cbSize = sizeof(DocInfo);
		DocInfo.lpszDocName = (LPCSTR)m_CurFile;

		// Start printing the document
		PrinterDC.StartDoc( &DocInfo );

		// String to hold our text
		CString Text;

		// Determine the line height for our font, and the 
		// width of the report body
		int LineSize, FontHeight;
		CSize TextSize = PrinterDC.GetTextExtent( "Hy" );
		FontHeight = TextSize.cy;
		int BodyWidth = Right - Left;
		int PageNum=1;
		CString Header;

		// A flag to indicate that the header should be printed
		bool PageStart=true;

		// Iterate through the lines of the Edit control
		for( int i = 0; i < pEdit->GetLineCount(); i++ )
		{
			if( PageStart )
			{
				// If we already printed something, then we have to remember to end the 
				// previous page
				if( i > 0 )
					PrinterDC.EndPage();
				
				// Tell Spooler to start a new page
				PrinterDC.StartPage();
				
				// Print page header
				PrinterDC.MoveTo( Left, Top + 100 );
				PrinterDC.LineTo( Right, Top + 100 );
				Header.Format( "%s - Page %d", (LPCSTR)m_CurFile, PageNum++);
				PrinterDC.TextOut( Left, Top + 100 + FontHeight, Header );
				
				// Set the PageStart flag to false until needed again, and
				// set the CurY position back to the top margin
				PageStart = false;
				CurY = Top;
			}

			// Get the line of text for the report from our multi-line edit box
			LineSize = pEdit->GetLine(i, Text.GetBuffer(1024), 1024 );
			Text.ReleaseBuffer(LineSize);

			// Determine if the line fits in our printable areas
			do {
				TextSize = PrinterDC.GetTextExtent( Text, LineSize );
				if( TextSize.cx  > BodyWidth )
					LineSize--;
			} while( TextSize.cx > BodyWidth );

			// Print the line (or only the portion that fits on the page)
			PrinterDC.TextOut( Left, CurY, Text, LineSize );

			// Decrement the current Y position to move down by 1 line
			CurY -= TextSize.cy;
		}
		// End the last page
		PrinterDC.EndPage();

		// Stop printing the document
		PrinterDC.EndDoc();

		
	}

}

void CMFC_NopePadDlg::PNEzMargins(CPageSetupDialog &pPageSetup, int &Left, int &Top, int &Right, int &Bottom)
{
	Left = pPageSetup.m_psd.rtMargin.left - pPageSetup.m_psd.rtMinMargin.left;
	Top = -(pPageSetup.m_psd.rtMargin.top - pPageSetup.m_psd.rtMinMargin.top);
	Right = pPageSetup.m_psd.ptPaperSize.x - pPageSetup.m_psd.rtMargin.right - pPageSetup.m_psd.rtMinMargin.left;
	Bottom = -(pPageSetup.m_psd.ptPaperSize.y - pPageSetup.m_psd.rtMargin.bottom - pPageSetup.m_psd.rtMinMargin.top);

}

BOOL CMFC_NopePadDlg::PNCreatePrinterFont(CWnd *pWin, CFont &Font)
{
	LOGFONT LogFont;

	CFont* pCurFont = pWin->GetFont();
	pCurFont->GetLogFont( &LogFont );
	
	CDC *pTmpDC = pWin->GetDC();

	// Get current height divided by LOGPIXELSY, gives us logical height in inches.  Mul that by 1000
	// Becuase printer DC mode is MM_HIENGLISH where each unist it 1/1000 an inch
	LogFont.lfHeight = int( (LogFont.lfHeight / (float)pTmpDC->GetDeviceCaps(LOGPIXELSY))*1000 );
	BOOL Ret = Font.CreateFontIndirect( &LogFont );
	pWin->ReleaseDC( pTmpDC );

	return( Ret );

}

void CMFC_NopePadDlg::OnIdPreviewClose() 
{
	// TODO: Add your command handler code here

	// This function does nothing.  It's called by the ESC key accelerator,
	// so that the Escape key doesn't close the window
}

BOOL CMFC_NopePadDlg::PreTranslateMessage(MSG* pMsg) 
{
	
	
	return CDialog::PreTranslateMessage(pMsg);
}
