Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / MFC

XTrueColorToolBar - True-color toolbar with support for Office-style color button

Rate me:
Please Sign up or sign in to vote.
4.69/5 (20 votes)
10 Jan 2008CPOL5 min read 72.7K   4.2K   63  
XTrueColorToolBar is an MFC class based on CToolBar that provides support for true-color bitmaps, with optional support for an Office-style color picker button.
// wordpdoc.cpp : implementation of the CWordPadDoc class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "wordpad.h"
#include "wordpdoc.h"
#include "wordpvw.h"
#include "cntritem.h"
#include "srvritem.h"
#include "formatba.h"
#include "mainfrm.h"
#include "ipframe.h"
#include "buttondi.h"
#include "helpids.h"
#include "strings.h"
#include "unitspag.h"
#include "docopt.h"
#include "optionsh.h"
#include "multconv.h"

#pragma warning(disable : 4996)	// disable bogus deprecation warning

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

extern BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn);
extern UINT AFXAPI AfxGetFileTitle(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax);

#ifndef OFN_EXPLORER
#define OFN_EXPLORER 0x00080000L
#endif
/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc
IMPLEMENT_DYNCREATE(CWordPadDoc, CRichEditDoc)

BEGIN_MESSAGE_MAP(CWordPadDoc, CRichEditDoc)
	//{{AFX_MSG_MAP(CWordPadDoc)
	ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)
	ON_UPDATE_COMMAND_UI(ID_OLE_VERB_POPUP, OnUpdateOleVerbPopup)
	ON_COMMAND(ID_FILE_SEND_MAIL, OnFileSendMail)
	ON_UPDATE_COMMAND_UI(ID_FILE_NEW, OnUpdateIfEmbedded)
	ON_UPDATE_COMMAND_UI(ID_FILE_OPEN, OnUpdateIfEmbedded)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateIfEmbedded)
	ON_UPDATE_COMMAND_UI(ID_FILE_PRINT, OnUpdateIfEmbedded)
	ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_DIRECT, OnUpdateIfEmbedded)
	ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_PREVIEW, OnUpdateIfEmbedded)
	//}}AFX_MSG_MAP
	ON_UPDATE_COMMAND_UI(ID_FILE_SEND_MAIL, OnUpdateFileSendMail)
	ON_COMMAND(ID_OLE_EDIT_LINKS, CRichEditDoc::OnEditLinks)
	ON_UPDATE_COMMAND_UI(ID_OLE_VERB_FIRST, CRichEditDoc::OnUpdateObjectVerbMenu)
	ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_CONVERT, CRichEditDoc::OnUpdateObjectVerbMenu)
	ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, CRichEditDoc::OnUpdateEditLinksMenu)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc construction/destruction

CWordPadDoc::CWordPadDoc()
{
	m_nDocType = -1;
	m_nNewDocType = -1;
}

BOOL CWordPadDoc::OnNewDocument()
{
	if (!CRichEditDoc::OnNewDocument())
		return FALSE;

	//correct type already set in theApp.m_nNewDocType;
	int nDocType = (IsEmbedded()) ? RD_EMBEDDED : theApp.m_nNewDocType;

	GetView()->SetDefaultFont(IsTextType(nDocType));
	SetDocType(nDocType);

	return TRUE;
}

void CWordPadDoc::ReportSaveLoadException(LPCTSTR lpszPathName,
	CException* e, BOOL bSaving, UINT nIDP)
{
	if (!m_bDeferErrors && e != NULL)
	{
		ASSERT_VALID(e);
		if (e->IsKindOf(RUNTIME_CLASS(CFileException)))
		{
			switch (((CFileException*)e)->m_cause)
			{
			case CFileException::fileNotFound:
			case CFileException::badPath:
				nIDP = AFX_IDP_FAILED_INVALID_PATH;
				break;
			case CFileException::diskFull:
				nIDP = AFX_IDP_FAILED_DISK_FULL;
				break;
			case CFileException::accessDenied:
				nIDP = bSaving ? AFX_IDP_FAILED_ACCESS_WRITE :
						AFX_IDP_FAILED_ACCESS_READ;
				if (((CFileException*)e)->m_lOsError == ERROR_WRITE_PROTECT)
					nIDP = IDS_WRITEPROTECT;
				break;
			case CFileException::tooManyOpenFiles:
				nIDP = IDS_TOOMANYFILES;
				break;
			case CFileException::directoryFull:
				nIDP = IDS_DIRFULL;
				break;
			case CFileException::sharingViolation:
				nIDP = IDS_SHAREVIOLATION;
				break;
			case CFileException::lockViolation:
			case CFileException::badSeek:
			case CFileException::generic:
			case CFileException::invalidFile:
			case CFileException::hardIO:
				nIDP = bSaving ? AFX_IDP_FAILED_IO_ERROR_WRITE :
						AFX_IDP_FAILED_IO_ERROR_READ;
				break;
			default:
				break;
			}
			CString prompt;
			AfxFormatString1(prompt, nIDP, lpszPathName);
			AfxMessageBox(prompt, MB_ICONEXCLAMATION, nIDP);
			return;
		}
	}
	CRichEditDoc::ReportSaveLoadException(lpszPathName, e, bSaving, nIDP);
	return;
}

BOOL CWordPadDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
	if (m_lpRootStg != NULL) // we are embedded
	{
		// we really want to use the converter on this storage
		m_nNewDocType = RD_EMBEDDED;
	}
	else
	{
		if (theApp.cmdInfo.m_bForceTextMode)
			m_nNewDocType = RD_TEXT;
		else
		{
			CFileException fe;
			m_nNewDocType = GetDocTypeFromName(lpszPathName, fe);
			if (m_nNewDocType == -1)
			{
				ReportSaveLoadException(lpszPathName, &fe, FALSE,
					AFX_IDP_FAILED_TO_OPEN_DOC);
				return FALSE;
			}
			if (m_nNewDocType == RD_TEXT && theApp.m_bForceOEM)
				m_nNewDocType = RD_OEMTEXT;
		}
		ScanForConverters();
		if (!doctypes[m_nNewDocType].bRead)
		{
			CString str;
			CString strName = doctypes[m_nNewDocType].GetString(DOCTYPE_DOCTYPE);
			AfxFormatString1(str, IDS_CANT_LOAD, strName);
			AfxMessageBox(str, MB_OK|MB_ICONINFORMATION);
			return FALSE;
		}
	}

//  SetDocType(nNewDocType);
	if (!CRichEditDoc::OnOpenDocument(lpszPathName))
		return FALSE;
	return TRUE;
}

void CWordPadDoc::Serialize(CArchive& ar)
{
	COleMessageFilter* pFilter = AfxOleGetMessageFilter();
	ASSERT(pFilter != NULL);
	pFilter->EnableBusyDialog(FALSE);
	if (ar.IsLoading())
		SetDocType(m_nNewDocType);
	CRichEditDoc::Serialize(ar);
	pFilter->EnableBusyDialog(TRUE);
}

BOOL CWordPadDoc::DoSave(LPCTSTR pszPathName, BOOL bReplace /*=TRUE*/)
	// Save the document data to a file
	// pszPathName = path name where to save document file
	// if pszPathName is NULL then the user will be prompted (SaveAs)
	// note: pszPathName can be different than 'm_strPathName'
	// if 'bReplace' is TRUE will change file name if successful (SaveAs)
	// if 'bReplace' is FALSE will not change path name (SaveCopyAs)
{
	CString newName = pszPathName;
	int nOrigDocType = m_nDocType;  //saved in case of SaveCopyAs or failure

	//  newName     bWrite  type    result
	//  empty       TRUE    -       SaveAs dialog
	//  empty       FALSE   -       SaveAs dialog
	//  notempty    TRUE    -       nothing
	//  notempty    FALSE   W6      warn (change to wordpad, save as, cancel)
	//  notempty    FALSE   other   warn (save as, cancel)

	BOOL bModified = IsModified();

	ScanForConverters();

	BOOL bSaveAs = FALSE;
	if (newName.IsEmpty())
		bSaveAs = TRUE;
	else if (!doctypes[m_nDocType].bWrite)
	{
		if (m_nDocType == RD_WINWORD6)
		{
			//      DWORD nHelpIDs[] =
			//      {
			//          0, 0
			//      };
			int nRes = CButtonDialog::DisplayMessageBox(
				MAKEINTRESOURCE(IDS_WORD6_WARNING), AfxGetAppName(),
				MAKEINTRESOURCE(IDS_WORD6_WARNING_BUTTONS),
				MB_ICONQUESTION, 1, 2);
			if (nRes == 0) // Save
				SetDocType(RD_WORDPAD, TRUE);
			else if (nRes == 2) // Cancel
				return FALSE;
			else
				bSaveAs = TRUE;
			// else save as
		}
		else //
		{
			if (AfxMessageBox(IDS_SAVE_UNSUPPORTED,
				MB_YESNO | MB_ICONQUESTION) != IDYES)
			{
				return FALSE;
			}
			else
				bSaveAs = TRUE;
		}
	}

	if (m_lpRootStg == NULL && IsTextType(m_nDocType) &&
		!GetView()->IsFormatText())
	{
		// formatting changed in plain old text file
		DWORD nHelpIDs[] =
		{
			0, IDH_WORDPAD_WORD6FILE,
			0, IDH_WORDPAD_FORMATTED,
			0, IDH_WORDPAD_TEXTFILE,
			0, 0
		};
		CString str;
		AfxFormatString1(str, IDS_SAVE_FORMAT_TEXT, GetTitle());
		int nRes = CButtonDialog::DisplayMessageBox(str,
			MAKEINTRESOURCE(AFX_IDS_APP_TITLE),
			MAKEINTRESOURCE(IDS_TF_BUTTONS), MB_ICONQUESTION, 0, 3, nHelpIDs);
		if (nRes == 3)
			return FALSE;
		int nDocType = (nRes == 0) ? RD_DEFAULT:    //Word 6
					(nRes == 1) ? RD_RICHTEXT : //RTF
					RD_TEXT;                    //text
		if (IsTextType(m_nDocType) && nDocType != RD_TEXT)
			SetDocType(nDocType, TRUE);
		if (nDocType != RD_TEXT)
			bSaveAs = TRUE;
	}

	GetView()->GetParentFrame()->RecalcLayout();
	if (bSaveAs)
	{
		newName = m_strPathName;
		if (bReplace && newName.IsEmpty())
		{
			newName = m_strTitle;
			int iBad = newName.FindOneOf(_T(" #%;/\\"));    // dubious filename
			if (iBad != -1)
				newName.ReleaseBuffer(iBad);

			// append the default suffix if there is one
			newName += GetExtFromType(m_nDocType);
		}

		int nDocType = m_nDocType;
		if (!theApp.PromptForFileName(newName,
			bReplace ? AFX_IDS_SAVEFILE : AFX_IDS_SAVEFILECOPY,
			OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, FALSE, &nDocType))
		{
			SetDocType(nOrigDocType, TRUE);
			return FALSE;       // don't even try to save
		}
		SetDocType(nDocType, TRUE);
	}

	BeginWaitCursor();
	if (!OnSaveDocument(newName))
	{
		if (pszPathName == NULL)
		{
			// be sure to delete the file
			TRY
			{
				CFile::Remove(newName);
			}
			CATCH_ALL(e)
			{
				TRACE0("Warning: failed to delete file after failed SaveAs\n");
			}
			END_CATCH_ALL
		}
		// restore orginal document type
		SetDocType(nOrigDocType, TRUE);
		EndWaitCursor();
		return FALSE;
	}

	EndWaitCursor();
	if (bReplace)
	{
		int nType = m_nDocType;
		SetDocType(nOrigDocType, TRUE);
		SetDocType(nType);
		// Reset the title and change the document name
		SetPathName(newName, TRUE);
		ASSERT(m_strPathName == newName);       // must be set
	}
	else // SaveCopyAs
	{
		SetDocType(nOrigDocType, TRUE);
		SetModifiedFlag(bModified);
	}
	return TRUE;        // success
}

class COIPF : public COleIPFrameWnd
{
public:
	CFrameWnd* GetMainFrame() { return m_pMainFrame;}
	CFrameWnd* GetDocFrame() { return m_pDocFrame;}
};

void CWordPadDoc::OnDeactivateUI(BOOL bUndoable)
{
	if (GetView()->m_bDelayUpdateItems)
		UpdateAllItems(NULL);
	SaveState(m_nDocType);
	CRichEditDoc::OnDeactivateUI(bUndoable);
	COIPF* pFrame = (COIPF*)m_pInPlaceFrame;
	if (pFrame != NULL)
	{
		if (pFrame->GetMainFrame() != NULL)
			ForceDelayed(pFrame->GetMainFrame());
		if (pFrame->GetDocFrame() != NULL)
			ForceDelayed(pFrame->GetDocFrame());
	}
}

void CWordPadDoc::ForceDelayed(CFrameWnd* pFrameWnd)
{
	ASSERT_VALID(this);
	ASSERT_VALID(pFrameWnd);

	POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
	while (pos != NULL)
	{
		// show/hide the next control bar
		CControlBar* pBar =
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);

		BOOL bVis = pBar->GetStyle() & WS_VISIBLE;
		UINT swpFlags = 0;
		if ((pBar->m_nStateFlags & CControlBar::delayHide) && bVis)
			swpFlags = SWP_HIDEWINDOW;
		else if ((pBar->m_nStateFlags & CControlBar::delayShow) && !bVis)
			swpFlags = SWP_SHOWWINDOW;
		pBar->m_nStateFlags &= ~(CControlBar::delayShow|CControlBar::delayHide);
		if (swpFlags != 0)
		{
			pBar->SetWindowPos(NULL, 0, 0, 0, 0, swpFlags|
				SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc Attributes
CLSID CWordPadDoc::GetClassID()
{
	return (m_pFactory == NULL) ? CLSID_NULL : m_pFactory->GetClassID();
}

void CWordPadDoc::SetDocType(int nNewDocType, BOOL bNoOptionChange)
{
	ASSERT(nNewDocType != -1);
	if (nNewDocType == m_nDocType)
		return;

	m_bRTF = !IsTextType(nNewDocType);
	if (bNoOptionChange)
		m_nDocType = nNewDocType;
	else
	{
		SaveState(m_nDocType);
		m_nDocType = nNewDocType;
		RestoreState(m_nDocType);
	}
}

CWordPadView* CWordPadDoc::GetView()
{
	POSITION pos = GetFirstViewPosition();
	return (CWordPadView* )GetNextView( pos );
}

/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc Operations

CFile* CWordPadDoc::GetFile(LPCTSTR pszPathName, UINT nOpenFlags, CFileException* pException)
{
	CTrackFile* pFile = NULL;
	CFrameWnd* pWnd = GetView()->GetParentFrame();
#ifdef CONVERTERS
	ScanForConverters();

	// if writing use current doc type otherwise use new doc type
	int nType = (nOpenFlags & CFile::modeReadWrite) ? m_nDocType : m_nNewDocType;
	// m_nNewDocType will be same as m_nDocType except when opening a new file
	if (doctypes[nType].pszConverterName != NULL)
		pFile = new CConverter(doctypes[nType].pszConverterName, pWnd);
	else
#endif
	if (nType == RD_OEMTEXT)
		pFile = new COEMFile(pWnd);
	else
		pFile = new CTrackFile(pWnd);
	if (!pFile->Open(pszPathName, nOpenFlags, pException))
	{
		delete pFile;
		return NULL;
	}
	if (nOpenFlags & (CFile::modeWrite | CFile::modeReadWrite))
		pFile->m_dwLength = 0; // can't estimate this
	else
		pFile->m_dwLength = (DWORD)pFile->GetLength();
	return pFile;
}

CRichEditCntrItem* CWordPadDoc::CreateClientItem(REOBJECT* preo) const
{
	// cast away constness of this
	return new CWordPadCntrItem(preo, (CWordPadDoc*)this);
}

/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc server implementation

COleServerItem* CWordPadDoc::OnGetEmbeddedItem()
{
	// OnGetEmbeddedItem is called by the framework to get the COleServerItem
	//  that is associated with the document.  It is only called when necessary.

	CEmbeddedItem* pItem = new CEmbeddedItem(this);
	ASSERT_VALID(pItem);
	return pItem;
}

/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc serialization

/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc diagnostics

#ifdef _DEBUG
void CWordPadDoc::AssertValid() const
{
	CRichEditDoc::AssertValid();
}

void CWordPadDoc::Dump(CDumpContext& dc) const
{
	CRichEditDoc::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CWordPadDoc commands

int CWordPadDoc::MapType(int nType)
{
	if (nType == RD_OEMTEXT)
		nType = RD_TEXT;
	else if (!IsInPlaceActive() && nType == RD_EMBEDDED)
		nType = RD_RICHTEXT;
	return nType;
}

void CWordPadDoc::OnViewOptions()
{
	int nType = MapType(m_nDocType);
	int nFirstPage = 3;
	if (nType == RD_TEXT)
		nFirstPage = 1;
	else if (nType == RD_RICHTEXT)
		nFirstPage = 2;
	else if (nType == RD_WRITE)
		nFirstPage = 4;
	else if (nType == RD_EMBEDDED)
		nFirstPage = 5;

	SaveState(nType);

	COptionSheet sheet(IDS_OPTIONS, NULL, nFirstPage);

	if (sheet.DoModal() == IDOK)
	{
		CWordPadView* pView = GetView();
		if (theApp.m_bWordSel)
			pView->GetRichEditCtrl().SetOptions(ECOOP_OR, ECO_AUTOWORDSELECTION);
		else
		{
			pView->GetRichEditCtrl().SetOptions(ECOOP_AND,
				~(DWORD)ECO_AUTOWORDSELECTION);
		}
		RestoreState(nType);
	}
}

void CWordPadDoc::OnUpdateOleVerbPopup(CCmdUI* pCmdUI)
{
	pCmdUI->m_pParentMenu = pCmdUI->m_pMenu;
	CRichEditDoc::OnUpdateObjectVerbMenu(pCmdUI);
}

BOOL CWordPadDoc::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
	if (nCode == CN_COMMAND && nID == ID_OLE_VERB_POPUP)
		nID = ID_OLE_VERB_FIRST;
	return CRichEditDoc::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

void CWordPadDoc::SaveState(int nType)
{
	if (nType == -1)
		return;
	nType = MapType(nType);
	CWordPadView* pView = GetView();
	if (pView != NULL)
	{
		CFrameWnd* pFrame = pView->GetParentFrame();
		ASSERT(pFrame != NULL);
		// save current state
		pFrame->SendMessage(WPM_BARSTATE, 0, nType);
		theApp.GetDocOptions(nType).m_nWordWrap = pView->m_nWordWrap;
	}
}

void CWordPadDoc::RestoreState(int nType)
{
	if (nType == -1)
		return;
	nType = MapType(nType);
	CWordPadView* pView = GetView();
	if (pView != NULL)
	{
		CFrameWnd* pFrame = pView->GetParentFrame();
		ASSERT(pFrame != NULL);
		// set new state
		pFrame->SendMessage(WPM_BARSTATE, 1, nType);
		int nWrapNew = theApp.GetDocOptions(nType).m_nWordWrap;
		if (pView->m_nWordWrap != nWrapNew)
		{
			pView->m_nWordWrap = nWrapNew;
			pView->WrapChanged();
		}
	}
}

void CWordPadDoc::OnCloseDocument()
{
	SaveState(m_nDocType);
	CRichEditDoc::OnCloseDocument();
}

void CWordPadDoc::PreCloseFrame(CFrameWnd* pFrameArg)
{
	CRichEditDoc::PreCloseFrame(pFrameArg);
	SaveState(m_nDocType);
}

void CWordPadDoc::OnFileSendMail()
{
	if (m_strTitle.Find('.') == -1)
	{
		// add the extension because the default extension will be wrong
		CString strOldTitle = m_strTitle;
		m_strTitle += GetExtFromType(m_nDocType);
		CRichEditDoc::OnFileSendMail();
		m_strTitle = strOldTitle;
	}
	else
		CRichEditDoc::OnFileSendMail();
}

void CWordPadDoc::OnUpdateIfEmbedded(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(!IsEmbedded());
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions