pagethird.cpp

来自「Nero刻录工具的插件编程SDK」· C++ 代码 · 共 542 行

CPP
542
字号
/******************************************************************************
|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|* PARTICULAR PURPOSE.
|* 
|* Copyright 1995-2004 Ahead Software AG. All Rights Reserved.
|*-----------------------------------------------------------------------------
|* NeroSDK / NVAPIExample
|*
|* PROGRAM: PageThird.cpp
|*
|* PURPOSE: Implementation of the third page.
******************************************************************************/

#include "stdafx.h"
#include "NVAPIExample.h"
#include "PageThird.h"

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


#define UM_START_PROCESS		(WM_APP + 1)

#define TIMER_INTERVAL			500 /* ms */
#define TIMER_ID				100

CPageThird::CPageThird(CSheet * pParent)
	: CPage(CPageThird::IDD, pParent)
	, m_bActiveState (false)
	, m_bAbort (false)
{
	//{{AFX_DATA_INIT(CPageThird)
	//}}AFX_DATA_INIT
}


void CPageThird::DoDataExchange(CDataExchange* pDX)
{
	CPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPageThird)
	DDX_Control(pDX, IDC_TOTAL_TIME, c_TotalTime);
	DDX_Control(pDX, IDC_PROGRESS_PERCENT, c_Percent);
	DDX_Control(pDX, IDC_PROGRESS, c_Progress);
	DDX_Control(pDX, IDC_MESSAGES, c_Messages);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CPageThird, CPage)
	//{{AFX_MSG_MAP(CPageThird)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	ON_MESSAGE(UM_START_PROCESS, OnStartProcess)
	ON_MESSAGE(UM_NERO_USER_DIALOG, OnNeroUserDialog)
	ON_MESSAGE(UM_NERO_IDLE_CALLBACK, OnNeroIdleCallback)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPageThird message handlers

bool CPageThird::Create (void)
{
	return CDialog::Create (m_lpszTemplateName, m_pParentWnd) != FALSE;
}


bool CPageThird::OnNext (void)
{
	// If we are in an active state, the button is used for abortion. So,
	// abort and eat the button click.
	// 
	if (m_bActiveState)
	{
		m_bAbort = true;
		return true;
	}
	else
	{
		return false;
	}
}

void CPageThird::OnChangeState (bool bActivate, bool bForward)
{
	// If the page is activated in the forward direction...
	// 
	if (bActivate && bForward)
	{
		// Change into active state and remember the initial tick count
		// so we can time this transcoding and burning.
		// 
		m_bActiveState = true;
		m_dwStartTickCount = GetTickCount ();

		// Start the timer that will update the elapsed time.
		// 
		SetTimer (TIMER_ID, TIMER_INTERVAL, NULL);
		
		// Change Next button to Abort and disable the other one.
		// 
		CString sAbort;
		sAbort.LoadString (IDS_BUTTON_ABORT);
		GetParent ()->GetDlgItem (IDOK)->SetWindowText (sAbort);
		GetParent ()->GetDlgItem (IDCANCEL)->EnableWindow (false);

		// Reset the position of the progress bar and remove all items from
		// the message list ctrl.
		// 
		c_Progress.SetPos (0);
		c_Percent.SetWindowText ("");
		c_TotalTime.SetWindowText ("");
		c_Messages.DeleteAllItems ();

		// Reset all relevant variables.
		// 
		m_LastAction = (ProgressAction) -1;
		m_sLastItemname.Empty ();
		m_bAbort = false;

		InsertMessage (IDS_STARTING_TRANSCODING);

		// Post a message to ourseleves so that everything is painted
		// before we begin.
		// 
		PostMessage (UM_START_PROCESS);
	}
}

LRESULT CPageThird::OnStartProcess (WPARAM wParam, LPARAM lParam)
{
	// Now start transcoding. The method won't return until it finishes
	// but we have a progress callback to monitor the process.
	// 
	try
	{
		INeroBurnContextPtr pBurnContext;
		CPageData * pPageData = GetPageData ();

		VARIANT_BOOL bSuccess = pPageData->m_pProject->CreateNeroBurnContext (NeroAPIGlueGetModuleHandle (),
																			this,
																			&pBurnContext);
		if (!bSuccess)
		{
			// Transcoding was unsuccessful...
			// 
			if (m_bAbort)
			{
				// If unsuccessful and aborted, simply display the aborted
				// message.
				// 
				CString sAborted;
				sAborted.LoadString (IDS_ERROR_ABORTED);
				InsertMessage (sAborted);

				AfxMessageBox (IDS_ERROR_ABORTED);
			}
			else
			{
				// If there was an error, insert another message line into the
				// message listctrl and display an error message box!
				// 
				IErrorPtr pError = pPageData->m_pProject->LastError;
				
				USES_CONVERSION;
				CString sError;
				CString sFormat;
				sFormat.LoadString (IDS_TRANSCODING_ERROR_FORMAT);
				sError.Format (sFormat, pError->ErrCode, W2CA (pError->XMLID), W2CA (pError->ErrText));
				InsertMessage (sError);

				AfxMessageBox (IDS_ERROR_TRANSCODING);
			}
		}
		else
		{
			// Ok, now do the burning...
			// 
			InsertMessage (IDS_STARTING_BURNING);

			bool bBurnError = true;

			// Open the device...
			// 
			NERO_DEVICEHANDLE hDevice = NeroOpenDevice (pPageData->m_pDeviceInfo);
			if (hDevice != NULL)
			{
				NERO_PROGRESS * pNeroProgress;

				// Create NERO_PROGRESS structure using API.
				// 
				pNeroProgress = NeroCreateProgress ();
				if (pNeroProgress != NULL)
				{
					// Fill-in the NERO_PROGRESS structure wiht our own
					// callbacks.
					// 
					pNeroProgress->npAbortedCallback = NeroAbortedCallback;
					pNeroProgress->npAddLogLineCallback = NeroAddLogLineCallback;
					pNeroProgress->npProgressCallback = NeroProgressCallback;
					pNeroProgress->npUserData = this;

					// Now, finally start burning using the NERO_CD_FORMAT
					// and NERO_WRITE_CD as returned from NeroVisionAPI.
					// The burn speed and recorder were previously selected
					// by the user.
					// 
					NEROAPI_BURN_ERROR err;
					err = NeroBurn (hDevice,
									(NERO_CD_FORMAT) pBurnContext->NERO_CD_FORMAT,
									pBurnContext->NERO_WRITE_CD,
									NBF_WRITE|NBF_DAO,
									pPageData->m_dwBurnSpeed,
									pNeroProgress);

					bBurnError = err != NEROAPI_BURN_OK;

					NeroFreeMem (pNeroProgress);
				}

				NeroCloseDevice (hDevice);
			}

			// Display an appropriate message depending on the status of
			// the burn operation.
			// 
			AfxMessageBox (bBurnError? IDS_BURN_FAILED: IDS_BURN_OK);
		}
	}
	catch (...)
	{
		AfxMessageBox (IDS_UNEXPECTED_NVAPI_ERROR);
	}

	// When everything is finally done, restore the buttons to original
	// state.
	// 
	RestoreButtons ();
	
	return 0;
}

// This is a helper message to insert a message into the log using a
// message string ID.
// 
void CPageThird::InsertMessage (UINT uMessageID)
{
	CString sMessage;
	sMessage.LoadString (uMessageID);
	InsertMessage (sMessage);
}

// This is a helper message to insert a message into the log using a
// direct string pointer.
// 
void CPageThird::InsertMessage (LPCSTR psMessage)
{
	int iIndex = c_Messages.InsertItem (c_Messages.GetItemCount (), psMessage, 0);
	c_Messages.EnsureVisible (iIndex, false);
	c_Messages.UpdateWindow ();
}

BOOL CPageThird::OnInitDialog() 
{
	CPage::OnInitDialog();
	
	// Insert a single column into the listctrl and make sure that the
	// width is set to maximum minus the size of the vertical scrollbar.
	// 
	CRect rcMessages;
	c_Messages.GetClientRect (&rcMessages);
	
	CString sColumnCaption;
	sColumnCaption.LoadString (IDS_MESSAGES_COLUMN);
	
	c_Messages.InsertColumn (0,
		sColumnCaption,
		LVCFMT_LEFT,
		rcMessages.Width () - ::GetSystemMetrics (SM_CXVSCROLL));
	
	c_Messages.SetExtendedStyle (LVS_EX_FULLROWSELECT);

	c_Progress.SetRange (0, 100);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

STDMETHODIMP CPageThird::raw_OnProgress (
							enum ProgressAction action,
							BSTR itemname,
							double currentRemain,
							double currentTotal,
							float currentFraction,
							double totalRemain,
							double totalTotal,
							float totalFraction)
{
	USES_CONVERSION;
	CString sNewItemname = W2CA (itemname);

	// If either the action or the item name changed, let's insert another
	// message line.
	// 
	if (action != m_LastAction ||
		sNewItemname != m_sLastItemname)
	{
		m_LastAction = action;
		m_sLastItemname = sNewItemname;

		// These phases are supported by NeroVisionAPI. Their stings are
		// in the string table.
		// 
		static UINT uActionIDs[] = {
			IDS_ACTION_ESTIMATING,
			IDS_ACTION_PREPARING,
			IDS_ACTION_TRANSCODING,
			IDS_ACTION_GENERATING,
			IDS_ACTION_ANALYZING,
		};

		// Make sure the action is within known bounds.
		// 
		if (action < Estimating || action > Analyzing)
		{
			action = Estimating;
		}
		
		// Format and insert the message line.
		// 
		CString sAction;
		CString sMessage;
		sAction.LoadString (uActionIDs[action]);
		sMessage.Format ("%s %s", sAction, sNewItemname);
		
		InsertMessage (sMessage);
	}

	// Update the progress bar and pump the messages so that everything
	// remains responsive.
	// 
	SetPercent ((int) (totalFraction*100));

	((CNVAPIExampleApp *)AfxGetApp ())->PumpMessages ();
	
	return S_OK;
}

// This is a helper method to set both the progress bar and a textual
// progress percent.
// 
void CPageThird::SetPercent (int iPercent)
{
	CString sPercent;
	sPercent.Format ("%d%%", iPercent);
	c_Percent.SetWindowText (sPercent);
	c_Progress.SetPos (iPercent);
}

STDMETHODIMP CPageThird::raw_ShouldCancel (
										   VARIANT_BOOL * pbCancel)
{
	// Cancel the transcoding operation as needed and pump the messages.
	// 
	*pbCancel = m_bAbort? VARIANT_TRUE: VARIANT_FALSE;
	
	((CNVAPIExampleApp *)AfxGetApp ())->PumpMessages ();
	
	return S_OK;
}

void CPageThird::RestoreButtons (void)
{
	// If we are in an active state it means that we are either
	// transcoding or burning. Either way, we should abort the process.
	// 
	m_bActiveState = false;
	
	KillTimer (TIMER_ID);

	CString sBack;
	sBack.LoadString (IDS_BUTTON_BACK);
	GetParent ()->GetDlgItem (IDCANCEL)->EnableWindow (true);
	GetParent ()->GetDlgItem (IDCANCEL)->SetWindowText (sBack);
	
	CString sFinish;
	sFinish.LoadString (IDS_BUTTON_FINISH);
	GetParent ()->GetDlgItem (IDOK)->SetWindowText (sFinish);
}

// The aborted callback only returns our aborted flag.
// 
BOOL NERO_CALLBACK_ATTR CPageThird::NeroAbortedCallback (void *pUserData)
{
	CPageThird * pThis = (CPageThird *) pUserData;

	return pThis->m_bAbort;
}

// Add log line callback inserts a new message into the log.
// 
void NERO_CALLBACK_ATTR CPageThird::NeroAddLogLineCallback (void *pUserData, NERO_TEXT_TYPE type, const char *text)
{
	CPageThird * pThis = (CPageThird *) pUserData;

	pThis->InsertMessage (text);
}

// Progress callback advances the progress bar.
// 
BOOL NERO_CALLBACK_ATTR CPageThird::NeroProgressCallback (void *pUserData, DWORD dwProgressInPercent)
{
	CPageThird * pThis = (CPageThird *) pUserData;

	pThis->SetPercent (dwProgressInPercent);

	return pThis->m_bAbort;
}

// This handler is for our user message UM_NERO_USER_DIALOG which is sent
// to us by our parent and in turn by the application which owns the real
// user dialog and idle handlers.
// 
LRESULT CPageThird::OnNeroUserDialog (WPARAM wParam, LPARAM lParam)
{
	return (LRESULT) NeroUserDialog ((NeroUserDlgInOut) wParam, (void *) lParam);
}

NeroUserDlgInOut CPageThird::NeroUserDialog (NeroUserDlgInOut type, void *data)
{
	// We handle here only a few of the user dialog messages.
	// 
	switch (type)
	{
		case DLG_WAITCD:
			{
				// When the cd is requested, display the localized version
				// of the message in the list ctrl log.
				// 
				LPSTR psText = NeroGetLocalizedWaitCDTexts ((NERO_WAITCD_TYPE) (int)data);
				if (psText != NULL)
				{
					InsertMessage (psText);
					NeroFreeMem (psText);
				}
			}

			return DLG_RETURN_EXIT;
			
		case DLG_WAITCD_REMINDER:
			// Just insert the reminder message in the log.
			// 
			InsertMessage (IDS_WAITCD_REMAINDER);
			
			return DLG_RETURN_EXIT;

		case DLG_WAITCD_DONE:
			// When waiting on a cd is done, insert a message.
			// 
			InsertMessage (IDS_WAITCD_DONE);

			return DLG_RETURN_EXIT;
			
		case DLG_FILESEL_IMAGE:
			{
				CString sFilter;
				sFilter.LoadString (IDS_NERO_IMAGE_FILES_FILTER);
				CFileDialog fd (FALSE,
					"txt",
					NULL,
					OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
					sFilter,
					this);
				
				if (IDOK == fd.DoModal ())
				{
					if (fd.GetPathName ().GetLength () < MAX_PATH)
					{
						strcpy ((char *) data, fd.GetPathName ());
						return DLG_RETURN_CONTINUE;
					}
				}
			}
			return DLG_RETURN_EXIT;
			
		case DLG_WAITCD_MEDIA_INFO:
			{
				// Insert the info about the media present and requested.
				// 
				const NERO_DLG_WAITCD_MEDIA_INFO * pMediaInfo = (const NERO_DLG_WAITCD_MEDIA_INFO *) data;
				ATLASSERT (pMediaInfo != NULL);

				CString sFormat;
				CString sMessage;
				sFormat.LoadString (IDS_FORMAT_WAITCD_MEDIA_INFO);
				sMessage.Format (sFormat, pMediaInfo->ndwmiLastDetectedMediaName,
											pMediaInfo->ndwmiRequestedMediaName);
				InsertMessage (sMessage);
				
				// The return value is ignored.
				// 
				return DLG_RETURN_EXIT;
			}
			
		default:
			return DLG_RETURN_NOT_HANDLED;
	}
}

// We know about NeroAPI's idle callback by handling a user message
// UM_NERO_IDLE_CALLBACK. All we are required to do is return our aborted
// flag.
// 
LRESULT CPageThird::OnNeroIdleCallback (WPARAM wParam, LPARAM lParam)
{
	return (LRESULT) m_bAbort;
}

void CPageThird::OnTimer(UINT nIDEvent) 
{
	if (nIDEvent == TIMER_ID)
	{
		// When our timer fires, let's update the elapsed time.
		// 
		DWORD dwDelta = (GetTickCount () - m_dwStartTickCount + 500)/1000;
		DWORD dwHours = dwDelta/3600;
		DWORD dwMinutes = (dwDelta%3600)/60;
		DWORD dwSeconds = dwDelta%60;
		
		CString sTime;
		sTime.Format ("%02d:%02d:%02d", dwHours, dwMinutes, dwSeconds);
		
		c_TotalTime.SetWindowText (sTime);
	}

	CPage::OnTimer(nIDEvent);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?