2012-04-28 182 views
0

我有一個相當大的應用程序,我試圖在Visual-C++中進行,現在我正試圖添加撤消/重做功能。Visual C++撤消和重做操作

如果事件數量相當多(按鈕點擊,標籤文本改變等),我想找到一種方法來撤銷/重做,而不必爲每個函數添加代碼。 對於實例,我想要一個可以讀取每個事件並自動存儲的類。然後在我的撤銷/重做事件中,我可以獲取最新的操作。

如果這是不可能的,我不會介意其他方式。

任何幫助?

+2

撤銷重做與錯誤處理一樣,是更容易的事情之一從一開始就建立起來,然後再進行改造。祝你好運! – Cameron 2012-04-28 21:20:09

回答

2

聲明一個代表兩個操作的類 - 撤銷和重做。 也創建該類的兩個向量。

對於要應用撤消/重做的每個操作,將該類的實例推送到撤消向量中。應該有儘可能多的派生類,因爲您想要撤消的操作。

例如,如果點擊按鈕將背景渲染爲綠色,您將創建一個類實例,其撤消metdho將背景渲染爲前一種顏色,其重做方法將背景渲染爲綠色,並將其填充到撤消向量中。 當你撤消 - 你彈出最後一個類的實例並調用它的撤消方法,這會將背景繪製爲以前的顏色。然後你把它推到重做向量。

當您重做時,您會彈出頂級類實例的重做向量並調用其重做方法,然後將它們回填到撤消向量中。

還有一些其他的情況(邊界),你會遇到的時候解決這些問題.. :-)

+0

謝謝你的幫助。我真的希望有一種方法可以自動調用發生的事件,就像您可以自動獲得鼠標單擊事件一樣,但我猜測這是不可能的。 +1接受。 – SuperPrograman 2012-05-03 17:45:12

1

做你的活動通過某種類型的隊列?默認情況下,在C++中沒有這樣的隊列(有一個windows os級別的事件隊列,但是可能已經管理好了並且在C++ -cli中不可用),並且你沒有指出這是否緊密映射到你的問題上)其他構造我不知道。

如果你有一些中央隊列,那麼它只是一個事件捕捉事件,因爲他們通過並知道如何撤消每個動作。如果沒有中央隊列,那麼除了更改每個可撤消的函數以創建某種類型的撤銷對象並將其存儲在某個類型的撤銷對象中以及撤銷該類型的撤銷對象之外,我看不到任何其他方法。

在一個沒有大的中央工作隊列的純淨的.net或C++環境中,我將創建一個類和撤消條目,實現一個方法/成員函數來撤消,另一個重做/執行工作。但只是撤消功能,這可能只是一個.net委託或一個c樣式函數指針和一個參數列表。如果你做了一個撤銷/重做類的動作,它可能是一個模板或泛型,它存儲指向do和undo函數的指針/委託,以及最初調用時的參數列表。

這些可以運行以撤銷已完成的操作。它們將被插入到某種類型的隊列容器中,這種容器看起來並不重要,因爲它保留了命令的長度,應該爲應用程序選擇最好的std,.net或其他容器。當你不再需要它們時,你可以丟棄舊的。執行時,必須刪除最後插入隊列的條目以保持一致性。

如果你還需要重做功能,那麼你所做的動作隊列必須是可迭代的,並且最簡單的方法是使用那個類,而動作有一個方法/成員函數可以撤消/重做所需的動作。你會有和某種類型的迭代器,指針,索引或標記指示你已經撤消了多久。每次請求撤消時,都必須向後移動標記(按時間順序),然​​後在隊列中的該位置執行撤消命令。如果請求重做,則當前指示的項目執行其重做指令,然後迭代器按時間順序前進(按時間順序)通過隊列,或者如果您處於隊列中最前面的項目,則忽略(我假設)。

如果你想遠離你想要達到的目標,你可以將你的應用程序置於行動隊列周圍。你可能不需要改變你實現這種方法的功能。你的用戶界面(我認爲,可以很容易成爲你的API)的功能,插入行動(支持做和撤消)到隊列中,然後命令隊列來做。如果副作用已知且可逆,則不必更改現有功能。但是,您需要更改所有呼叫者以進行操作而不是直接呼叫,並且您需要編寫進行撤消操作的對應方。

1

我試圖在一個小實驗庫中實現類似的功能:https://github.com/d-led/undoredo-cpp。它包含一個TransactionStore的實現,類似於CodeChords提供的人。您可能需要真正爲每個可撤銷對象添加功能,並且還要處理對象的生命週期,以防您的操作涉及對象構建或破壞

+0

謝謝!我會檢查一下。十分有趣。 – SuperPrograman 2012-09-03 14:29:46