Click here to Skip to main content
15,883,623 members
Articles / Desktop Programming / WTL

Undo Manager

Rate me:
Please Sign up or sign in to vote.
4.92/5 (10 votes)
12 Sep 20019 min read 118.9K   3.4K   72  
An article about managing undo and redo actions
// undomgr_wtlView.h : interface of the CUndomgr_wtlView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_UNDOMGR_WTLVIEW_H__7982DF86_1CC2_4DAD_9092_0B5422A44681__INCLUDED_)
#define AFX_UNDOMGR_WTLVIEW_H__7982DF86_1CC2_4DAD_9092_0B5422A44681__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

// included atlgdi and my sample gdi graphic objects
#include <atlgdi.h>
#include "gdigraph.h"

class CUndomgr_wtlView : public CWindowImpl<CUndomgr_wtlView>
{
public:
	CUndomgr_wtlView()
	{
		// Reset counter
		m_id = 0;

		// Intialize graphic context class, used for undo - redo operations
		GUIContext::Initialize(&m_displayMap, &m_deletedMap);
	}

	DECLARE_WND_CLASS(NULL)

	// Added IOleUndoManager as a member
	CComPtr<IOleUndoManager> m_spUndoMgr;

	// Added an object map for display objects and one for deleted objects
	GUIObjectMap	m_displayMap;
	GUIObjectMap	m_deletedMap;

	// Counter for unique identifiers
	long			m_id;

	BOOL PreTranslateMessage(MSG* pMsg)
	{
		pMsg;
		return FALSE;
	}

	BEGIN_MSG_MAP(CUndomgr_wtlView)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUP)
	END_MSG_MAP()

	LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		CPaintDC dc(m_hWnd);

		// Draw each graphic object in the display map
		std::for_each(m_displayMap.begin(), m_displayMap.end(), DrawFunctor(dc));

		return 0;
	}

	LRESULT OnLButtonUP(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		// Create different graphical objets with mouse clicks

		POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };

		switch (m_id % 4)
		{
			case 3:
			{
				// Creates a group of 2 boxes a round rect and an ellipse
				CreateGuiGroup(pt);
				break;
			}
			case 2:
			{
				// Creates an ellipse
				CreateGuiObject(2,pt);
				break;
			}
			case 1:
			{
				// Creates a round rect
				CreateGuiObject(1,pt);
				break;
			}
			default:
			{
				// Creates a box
				CreateGuiObject(0,pt);
				break;
			}
		}

		Invalidate();
		return 0;
	}


	void CreateGuiGroup(POINT pt)
	{
		//
		// Create parent undo unit to group units into one action
		//
		CComPtr<IOleParentUndoUnit> spPUU;
		HRESULT hr = CreateGroupUnit(&spPUU);
		if (SUCCEEDED(hr))
		{
			// Open the parent unit, following units added through the
			// manager will be added to this unit.
			hr = m_spUndoMgr->Open(spPUU);
			if (SUCCEEDED(hr))
			{
				POINT pt0, pt1, pt2, pt3;
				pt0.x = pt.x - 20; pt0.y = pt.y - 20;
				pt1.x = pt.x - 20; pt1.y = pt.y + 20;
				pt2.x = pt.x + 20; pt2.y = pt.y - 20;
				pt3.x = pt.x + 20; pt3.y = pt.y + 20;
				CreateGuiObject(0,pt0); // box
				CreateGuiObject(1,pt1); // round rect
				CreateGuiObject(2,pt2); // ellipse
				CreateGuiObject(0,pt3); // box

				// Commit to undo stack
				m_spUndoMgr->Close(spPUU, TRUE);
			}
		}

		// Increment counter, otherwise we will create only groups from now
		m_id++;
	}

	void CreateGuiObject(LONG type, POINT pt)
	{
		CGUIObject* p = NULL;

		switch (type)
		{
			case 0: 
				p = new CGUIBox(pt);
				break;
			case 1: 
				p = new CGUIRoundRect(pt);
				break;
			case 2: 
				p = new CGUIEllipse(pt);
				break;
		}

		if (p)
		{
			// Increment counter
			m_id++;

			// Insert the object in the display map by id
			m_displayMap.insert(GUIObjectMap::value_type(m_id, p));

			//
			// Add object to the undo stack
			//
			CComPtr<IOleUndoUnit> spUU;
			HRESULT hr = CreateUndoUnit(m_id, &spUU);
			if (SUCCEEDED(hr))
			{
				hr = m_spUndoMgr->Add(spUU);
			}
		}
	}

};


/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_UNDOMGR_WTLVIEW_H__7982DF86_1CC2_4DAD_9092_0B5422A44681__INCLUDED_)

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions