#pragma once
class CUndoStack
{
public:
CUndoStack(UINT nUndoMessage);
~CUndoStack(void);
void AddItem(CWnd* pWndBtn, int digit);
void RemoveItem();
bool HasItems();
void Reset();
private:
UINT m_nUndoMessage;
struct strUndo
{
int m_iDigit;
CWnd* m_pWndBtn;
};
CList<strUndo*, strUndo*> m_lstUndo;
bool m_bInRemove;
};
#include "StdAfx.h"
#include "UndoStack.h"
CUndoStack::CUndoStack(UINT nUndoMessage)
: m_nUndoMessage(nUndoMessage), m_bInRemove(false)
{
}
CUndoStack::~CUndoStack(void)
{
//Clean up the internal list - prevent memory leaks
Reset();
}
void CUndoStack::AddItem(CWnd* pWndBtn, int digit)
{
//The removal sends a message to the window - this is to prevent the item being added to the list again
if(m_bInRemove)
return;
strUndo* pUndo = new strUndo;
pUndo->m_pWndBtn = pWndBtn;
pUndo->m_iDigit = digit;
m_lstUndo.AddTail(pUndo);
}
void CUndoStack::RemoveItem()
{
if(HasItems()) //No items - then nothing to do
{
strUndo* pUndo = m_lstUndo.RemoveTail(); //unlink from the internal list
//Set the internal flag to prevent re-addition to the list of undo items
m_bInRemove = true;
pUndo->m_pWndBtn->SendMessage(m_nUndoMessage, (WPARAM)(pUndo->m_iDigit), (LPARAM)0);
m_bInRemove = false;
delete pUndo; //release memory
}
}
bool CUndoStack::HasItems()
{
return (m_lstUndo.GetHeadPosition() != NULL);
}
void CUndoStack::Reset()
{
POSITION pos = m_lstUndo.GetHeadPosition();
while(pos != NULL)
{
delete m_lstUndo.GetNext(pos); //release memory
}
m_lstUndo.RemoveAll(); //Remove from the list - memory no longer valid
}
#define SUD_PRESETVALUE (WM_USER+103)
#define SUD_UNDO (WM_USER+104)
afx_msg LRESULT OnUndo(WPARAM wParam, LPARAM lParam);
BEGIN_MESSAGE_MAP(CGridButton, CButton)
ON_MESSAGE(SUD_UNDO, &CGridButton::OnUndo)
END_MESSAGE_MAP()
and
LRESULT CGridButton::OnUndo(WPARAM wParam, LPARAM lParam)
{
SetValue((int)wParam);
return 0;
}
if(iKey >= 0)
{
SetValue(iKey);
return TRUE;
}
if(iKey >= 0)
{
GetParent()->SendMessage(SUD_PRESETVALUE, (WPARAM)this, (LPARAM)GetValue());
SetValue(iKey);
GetParent()->SendMessage(SUD_SETVALUE, (WPARAM)this, (LPARAM)iKey);
return TRUE;
}
CUndoStack m_stackUndo;
afx_msg LRESULT OnPreSetValue(WPARAM wParam, LPARAM lParam);
afx_msg void OnEditUndo();
afx_msg void OnUpdateEditUndo(CCmdUI *pCmdUI);
ON_MESSAGE(SUD_PRESETVALUE, &CSudokuView::OnPreSetValue)
ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, &CSudokuView::OnUpdateEditUndo)
ON_COMMAND(ID_EDIT_UNDO, &CSudokuView::OnEditUndo)
CSudokuView::CSudokuView()
: CFormView(CSudokuView::IDD)
, m_bInitialised(false)
, m_stackUndo(SUD_UNDO)
{
LRESULT CSudokuView::OnPreSetValue(WPARAM wParam, LPARAM lParam)
{
m_stackUndo.AddItem((CWnd*)wParam, (int)lParam);
return 0;
}
void CSudokuView::OnEditUndo()
{
m_stackUndo.RemoveItem();
}
void CSudokuView::OnUpdateEditUndo(CCmdUI *pCmdUI)
{
pCmdUI->Enable(m_stackUndo.HasItems());
}
case CSudokuDoc::eLoadGame:
….
//reset the undo stack
m_stackUndo.Reset();
Invalidate();
break;
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (0)