如何实现与SciTE那样的无限次撤销
本帖最后由 tryhi 于 2011-1-9 23:14 编辑我的思路的用windos消息,每次文本框数据变化都压入一个数组里,但那样只能实现每次撤销只撤销一个字符,所以在压入数组前要先判断,这是不是一次连续的输入,如果是,用最新替换最后面那个,不是则压入,如何判断这是不是一次连续输入呢?
比如十次变化
a
ab
abc
ab
abd
abde
abdef
abgdef
abghdef
iabghdef
把保存为abc
ab
abdef
abghdef
iabghdef非常感谢6楼3mile给出的例子,其实这个例子我也看过,当时测试的结果好像不能无限撤销(郁闷)……如今重新看了下,发现确实可以,另外8楼白隼将代码简化成比较容易理解,最佳答案就采纳他的吧希望3mile前辈不介意
{:face (396):} #include <GuiRichEdit.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiMenu.au3>
$hGui = GUICreate("Exampl", 320, 350, -1, -1)
$hRichEdit = _GUICtrlRichEdit_Create($hGui, "This is a test.", 10, 10, 300, 220, BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL))
$Button1 = GUICtrlCreateButton("撤销", 8, 224, 57, 25)
$Button2 = GUICtrlCreateButton("重做", 80, 224, 57, 25)
GUISetState(@SW_SHOW)
While True
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
GUIDelete()
Exit
Case $Button1
_GUICtrlRichEdit_Undo($hRichEdit)
Case $Button2
_GUICtrlRichEdit_Redo($hRichEdit)
EndSwitch
WEnd代码由3mile给出的自带例子简化 本帖最后由 binghc 于 2011-1-9 11:11 编辑
呵~终于有人提出这种问题啦!
不过貌似SciTE也不是根据是不是连续变化来决定撤销到哪一步的。
好像是根据:空号键,回车键等来决定撤销到哪个位置,也就是说当你按下了{space}或者{enter}的时候它才记录一个状态
(而且普通的空格键还不算,当你输入半个单词,然后用空格填充成完整单词后才算) 一般你要实现这个撤销功能大部分是对文本控件,所以给楼主提点意见:
如果是英文,可以每个单词记录一次。但是大多时候不会是存英文,所以建议时候没输入几个字符就记录一次
。或者这样:如果输入的英文,就每个单词记录一次(单词边界不一定是空格,只要是连续的英文就算一个单词,它的后面也可以是一个汉字、换行等)。其他可以每个或几个字符记录一次 本帖最后由 popyoung 于 2011-1-9 11:39 编辑
粗想一下,对于一行代码,好像其实就是删除字符串时保存,改变光标位置插入字符串时保存
a
ab
abc
ab 删除,保存abc
abd
abde
abdef
abgdef 改变光标位置到3,插入,保存abdef
abghdef 没改变光标位置,插入,不保存
iabghdef 改变光标位置到1,插入,保存abghdef
本帖最后由 popyoung 于 2011-1-9 11:44 编辑
默认情况是每次输入时光标都是后一格,当光标不按照此规律时,保存。
也就是说只要核对光标位置就可以了。
LZ还漏了一种情况,在直接修改一个或多个字母时。abc
abd 光标位置没往后移,保存abc RichEdi本向应该就有无限UnDo,ReDo。
#AutoIt3Wrapper_Au3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiRichEdit.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiMenu.au3>
Global $hRichEdit, $mnu, $mnuUndo, $mnuRedo, $mnuCut, $mnuCopy
Global $mnuPaste, $mnuPasteSpl, $mnuPasteSplRTF, $mnuPasteSplwObjs
Main()
Func Main()
Local $hGui
$hGui = GUICreate("Example (" & StringTrimRight(@ScriptName,4) &")", 320, 350, -1, -1)
$hRichEdit = _GUICtrlRichEdit_Create($hGui, "This is a test.", 10, 10, 300, 220, _
BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL))
GUISetState(@SW_SHOW)
_GUICtrlRichEdit_AppendText($hRichEdit, ReadBmpToRtf(FindFirstBMP()) & @CR)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
$mnu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
$mnuUndo = GUICtrlCreateMenuItem("Undo", $mnu)
$mnuRedo = GUICtrlCreateMenuItem("Redo", $mnu)
GUICtrlCreateMenuItem("", $mnu)
$mnuCut = GUICtrlCreateMenuItem("Cut", $mnu)
$mnuCopy = GUICtrlCreateMenuItem("Copy", $mnu)
$mnuPaste = GUICtrlCreateMenuItem("Paste", $mnu)
$mnuPasteSpl = GUICtrlCreateMenu("Paste Special", $mnu)
$mnuPasteSplRTF = GUICtrlCreateMenuItem("RTF only", $mnuPasteSpl)
$mnuPasteSplwObjs = GUICtrlCreateMenuItem("With objects", $mnuPasteSpl)
_GuiCtrlRichEdit_SetEventMask($hRichEdit, $ENM_MOUSEEVENTS)
While True
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
GUIDelete()
Exit
Case $mnuUndo
_GuiCtrlRichEdit_Undo($hRichEdit)
Case $mnuRedo
_GuiCtrlRichEdit_Redo($hRichEdit)
Case $mnuCut
_GuiCtrlRichEdit_Cut($hRichEdit)
Case $mnuCopy
_GuiCtrlRichEdit_Copy($hRichEdit)
Case $mnuPaste
_GuiCtrlRichEdit_Paste($hRichEdit)
Case $mnuPasteSplRTF
_GuiCtrlRichEdit_PasteSpecial($hRichEdit, False)
Case $mnuPasteSplwObjs
_GuiCtrlRichEdit_PasteSpecial($hRichEdit, True)
EndSwitch
WEnd
EndFunc ;==>Main
Func WM_NOTIFY($hWnd, $iMsg, $iWparam, $iLparam)
#forceref $iMsg, $iWparam
Local $hWndFrom, $iCode, $tNMHDR, $tMsgFilter, $hMenu
$tNMHDR = DllStructCreate($tagNMHDR, $iLparam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $hWndFrom
Case $hRichEdit
Select
Case $iCode = $EN_MSGFILTER
$tMsgFilter = DllStructCreate($tagEN_MSGFILTER, $iLparam)
If DllStructGetData($tMsgFilter, "msg") = $WM_RBUTTONUP Then
$hMenu = GUICtrlGetHandle($mnu)
SetMenuTexts($hWndFrom, $hMenu)
_GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd)
EndIf
EndSelect
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY
Func SetMenuTexts($hWnd, $hMenu)
Local $fState
If _GUICtrlRichEdit_CanUndo($hWnd) Then
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuUndo, True, False)
_GUICtrlMenu_SetItemText($hMenu, $mnuUndo, "Undo: " & _GUICtrlRichEdit_GetNextUndo($hWnd), False)
Else
_GUICtrlMenu_SetItemText($hMenu, $mnuUndo, "Undo", False)
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuUndo, False, False)
EndIf
If _GUICtrlRichEdit_CanRedo($hWnd) Then
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuRedo, True, False)
_GUICtrlMenu_SetItemText($hMenu, $mnuRedo, "Redo: " & _GUICtrlRichEdit_GetNextRedo($hWnd), False)
Else
_GUICtrlMenu_SetItemText($hMenu, $mnuRedo, "Redo", False)
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuRedo, False, False)
EndIf
$fState = _GuiCtrlRichEdit_IsTextSelected($hWnd)
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuCut, $fState, False)
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuCopy, $fState, False)
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuPaste, _GUICtrlRichEdit_CanPaste($hWnd))
_GUICtrlMenu_SetItemEnabled($hMenu, $mnuPasteSpl, _GUICtrlRichEdit_CanPasteSpecial($hWnd), False)
EndFunc ;==>SetMenuTexts
Func ReadBmpToRtf($sBmpFilspc)
Local $hFile, $sRtf
$hFile = FileOpen($sBmpFilspc, 16)
If FileRead($hFile, 2) <> "0x424D" Then Return SetError(1, 0, "")
FileRead($hFile, 12)
$sRtf = '{\rtf1{\pict\dibitmap ' & Hex(FileRead($hFile)) & '}}'
FileClose($hFile)
Return $sRtf
EndFunc ;==>ReadBmpToRtf
Func FindFirstBMP($sPath = @WindowsDir)
Local $hFind, $sBmpFilspc
$hFind = FileFindFirstFile($sPath & "\*.bmp")
$sBmpFilspc = FileFindNextFile($hFind)
FileClose($hFind)
Return $sPath & "\" & $sBmpFilspc
EndFunc ;==>FindFirstBMP
学vim的无限undo,直接写在一个文件中 {:face (356):}
页:
[1]