注:因为懒了,所以只将自己发的帖子的内容Copy出来了,没有整理(http://topic.csdn.net/u/20100816/15/6232364a-ebeb-4bf6-903c-1a3012c447b3.html?seed=441349749&r=67778824#r_67778824)

问题:

(gxj1680): CEdit中,做个Undo和Redo功能(要多步),可以使用EN_CHANGE事件,但是怎么保存上次的内容呢?
如:1输入abc, (abc)
  2再次输入123 (abc123)
  3在c处按键Backspace (ab123)
问:我怎么记忆上次的操作呢,有没有什么方法记录 “位置,操作”这样的消息(WPARAM,LPARAM,message),而不是每次都记忆CEdit中改变前的内容(这样相对耗内存),在什么函数里能拦截这样的操作呢,WinProc? PretranslateMessage?

另:在CEdit上,用输入法输入内容“中国”是一次写到CEdit中的呢,还是每个Keydown(zhongguo)都触发了EN_CHANGE事件呢?

答:

2楼(youngvc05):

EN_CHANGE消息应该是每输入一个字符就有响应的。可以用一个短时间间隔的定时器来定时记录输入的内容。

记录 “位置,操作”这样的消息(WPARAM,LPARAM,message)——我没想到什么办法。

3楼(gxj1680):

1: 一般Undo和Redo操作每次记录的都是CEdit中的全部内容吗?这不浪费内存吗?向word那样的,如果内容很多的话,每次都记录word中的内容会很浪费内存吧...

2: 关于EN_CHANGE响应,在word中用输入法操作后,一次回退时回退的是用输入法输入的内容,怎么判断的呢?
如:abc(直接键盘输入)中国(输入法)谷歌(输入法) //括号及内容为注释
回退时有3步:abc中国谷歌
  abc中国
  abc

4楼(gxj1680):
abc会一次删除

5楼(gxj1680):

像word这样的,回退操作时,如果你用的是输入法(如搜狗),每次回退都会回退一次输入的内容(输入法上的内容)
没人了么。。。

6楼(grf9527):

写个链表,自动增加长度,然后记录所有的输入

7楼(na_he):

队列之类的保证后进的先出,即可

8楼(zhaoxueqian1988):

将每次的输入内容的首地址缓存到链表。
Undo显示前一节点的内容;
Redo显示后一节点的内容。

10楼(gxj1680):

abc中国わたし123中国供钱党咱们老百姓
(每次输入用的不同颜色),其中“中国供钱党”用的是两次输入的,一次是zhongguo,一次是gongqiandang
"咱们老百姓"用的是一次输入zanmenlaobaixing
这样回退的过程是:
abc中国わたし123中国供钱党咱们老百姓
abc中国わたし123中国供钱党
abc中国わたし123中国
abc中国わたし123
abc中国わたし
abc中国
abc

像abc这样的数据(没用输入法),即使输入时间间隔很长时间,一次回退回退的内容也是abc整体而不是先退c,再退b,再退a

我就想知道这里面word里是以什么消息事件触发“abc”为一个单位,“中国”一个单位,“わたし”一个单位,“123”一个单位,“中国”一个单位,“供钱党”一个单位,“咱们老百姓”一个单位
什么事件呢?
不应该是EN_KILLFOCUS,因为用输入法时没有触发EN_KILLFOCUS事件?
而对于EN_CHANGE事件,如果用TRACE跟踪,会显示在输入“zhongguo”时,没有触发,而回车或其他操作将对应的“中国”放到Edit中时,触发了EN_CHANGE,并且出发了两次

中国

///

有哪位仁兄给解下惑啊,难不成自己在EN_CHANGE事件和WM_KEYDOWN之间加标志位?
有没有什么消息或事件呢?
......

11楼(gxj1680):

主要想知道word以什么区分输入法间输入的间隔(回退分段)的?

12楼(WindsonZhL):

晕,如果是派生CEdit子类的话,当然应该重载OnChar了!!

EN_CHANGFE只是控件通知父窗口做处理用的

13楼(gxj1680):

注:中间切换输入法
"abc" 没用输入法
"中国" 中文输入法一次
"わたし" 日文输入法一次

///

测了下,
如果用搜狗(中文)输入法,一次输入”abc“,则回退是将”abc“作为一个回退单位,只回退1次
如 果用搜狗(中文)输入法,每次输入一个字符就回车将其输入到edit中,”a“(回车),”b“(回车),”c“(回车),则 回退时”a“,”b“,”c“分别作为一个回退单位,要回退3次

想知道word怎么分辨的?

14楼(gxj1680):

不能将每次的OnChar作为一个回退单位吧?
word不是这么区分的吧..

/引用 12 楼 windsonzhl 的回复

晕,如果是派生CEdit子类的话,当然应该重载OnChar了!!
EN_CHANGFE只是控件通知父窗口做处理用的

15楼( na2650945 ):
集成自己的CEditView.
然后自己实现是否可能。
用个链表。

16楼( na2650945 ):
文字处理软件或排版软件中的Undo/Redo你就不要想了,那一般是基于存储
开发出来的一整套Undo/Redo机制,因为需要Undo/Redo的可不仅仅是文字:)
Undo/Redo机制中有普通事务处理和超级事务处理,后者就是应对这种连续
性操作的。Undo/Redo机制一般是用临时文件作为缓存载体的。系统的%temp%
目录就是专门放置临时文件的。

至于输入法的问题,那个并不困难,不管OnChar执行多少次,OnKeyUp只会
执行一次,所以用一个状态量控制就可以了,OnKeyUp时将状态量重置。

CEdit的多步Undo/Redo,肯定要OnChar具体执行前存一次,之后存一次
(之后不存就不能Redo)。有限次Undo的话,应该不会耗太多内存的。

17楼( gxj1680 ):
这里面的Edit类已经是从CEdit派生的了,(CMyEdit)
关键是回退的内容的分段单位

18楼( na2650945 ):
补充,Undo/Redo机制不是以字符或什么为单位的,是以“过程”为单位的。
一般会在修改对象前先保存对象,会记录Undo的起点和终点(也即Redo的终点和起点),
这样一对数值对应一个过程。同是会有Undo/Redo堆栈。当然Undo/Redo字串也是
需要记录的,一是这是每一个Undo过程的标识,一是U/R菜单项需要。

19楼( gxj1680 ):
OnKeyUp是每输入一个字符都会执行一次啊?输入”zhongguo“要执行8次OnKeyUp操作呢啊?

引用:///
//至于输入法的问题,那个并不困难,不管OnChar执行多少次,OnKeyUp只会
//执行一次,所以用一个状态量控制就可以了,OnKeyUp时将状态量重置。

20楼( na2650945 ):
就是利用OnKeyUp消息和状态量,来识别一个完整的输入过程,然后再控制Undo/Redo粒度。
Undo/Redo机制中每次OnChar是一个过程这是没有办法的,超级事务只是将多步Undo并为
一步执行罢了。

/引用 17 楼 gxj1680 的回复
这里面的Edit类已经是从CEdit派生的了,(CMyEdit)
关键是回退的内容的分段单位

21楼( na2650945 ):
输入法输入词或句的话,OnKeyUp只会执行一次的(也就是按空格或回车那一次)。

/引用 19 楼 gxj1680 的回复
OnKeyUp是每输入一个字符都会执行一次啊?输入”zhongguo“要执行8次OnKeyUp操作呢啊?

引用:///
//至于输入法的问题,那个并不困难,不管OnChar执行多少次,OnKeyUp只会
//执行一次,所以用一个状态量控制就可以了,OnKeyUp时将状态量重置。

22楼( na2650945 ):
What???
你的意思是连英文单词都要……,这个我投降,微软可是有词法分析技术的,要不怎么拼写检查:)

///引用 19 楼 gxj1680 的回复
OnKeyUp是每输入一个字符都会执行一次啊?输入”zhongguo“要执行8次OnKeyUp操作呢啊?

23楼( gxj1680 ):
不对啊,我用搜狗输入法和日文输入法,每次按键弹起都会触发OnKeyUp事件呢?
输入:”watashi“(わたし)
在按键"w","a","t","a","s","h","i"时都会触发OnKeyUp事件,触发了7次(不算切换输入法)

24楼( na2650945 ):
也许不同的输入法的处理过程有所不同?

顺便简单介绍一下输入法的处理过程,输入法实际上是与窗口进程绑定的。
一般在中文输入状态下,输入法会将OnKeyDown/OnKeyUp的nCode(虚拟键码)
置为VK_PROCESSKEY,从而屏蔽主程序处理键盘消息。待输入过程最终完成后,
才向主程序传递WM_CHAR或WM_IME_CHAR消息。

25楼( gxj1680 ):
这个知识还真不知道,不过,用搜狗中文输入法时也是每个输入字符都出发了OnKeyUp,迷糊了...

26楼( gxj1680 ):
终于找到消息了,在WinProc中,拦截消息WM_IME_CHAR即可, (谢谢 风之子:WindsonZhL)
中文的搜狗输入法和日文输入法,在输入过程中不触发WM_IME_CHAR消息,在将输入法中的内容写回Edit时,会自动触发WM_IME_CHAR消息

LRESULT CEditEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_IME_CHAR)
{
//添加想要的操作
//..
}

return CEdit::WindowProc(message, wParam, lParam);
}

//注:只是不用输入法时,输入abc怎么放到一块还要研究研究啊

27楼( gxj1680 ):
不过WM_IME_CHAR还有个问题
假设你输入”中国“,虽然会在将输入法中的内容写回Edit时,自动触发WM_IME_CHAR,但根据你输入单词的个数n,会接连触发n次。。。
很愁人啊,问题又回去了

28楼( xiansheng00 ):
设计模式里面有个模式Command模式,看懂了你就可以解决这个问题。

29楼( gxj1680 ):
跟踪DEBUG用TRACE输出发现
1. 切换输入法时,可以在WinProc中拦截WM_INPUTLANGCHANGEREQUEST和WM_INPUTLANGCHANGE实现

2. 在输入法用日文输入法时,切换日文和英文输入状态(按键Alt+~)时,可以用下面方法判断IME是否关闭或打开
  HIMC hImc = ::ImmGetContext(this->GetSafeHwnd());
BOOL bImmStatus = ::ImmGetOpenStatus(hImc);
if (bImmStatus && bImmStatus != m_bImmStatus)
TRACE(_T("Imm is open\n"));
else if (!bImmStatus && bImmStatus != m_bImmStatus)
TRACE(_T("Imm is closed\n"));
m_bImmStatusLast = bImmStatus;
注: 如果为日文输入状态(即IME是打开状态),如果按键Alt+~切换到了英文直接输入状态,即为IME关闭状态

3. 但是如果输入法为中文的搜狗输入法时,上面2的判断IME是否off就不好用了
  因为在判断时拦截到的message号为WM_GETDLGCODE,WM_KEYFIRST和WM_CHAR(注意不是WM_IME_CHAR),所 以,还是可以判断出来的,通过WM_CHAR,如果切换为中文输入状态了,就可以通过WM_IME_STARTCOMPOSITION和 WM_IME_ENDCOMPOSITION判断出一次整个的用输入法的输入块

4. 用输入法(中文如搜狗,日文)输入时,可以通过WM_IME_STARTCOMPOSITION和WM_IME_ENDCOMPOSITION为一组message判断你用输入法输入的整个输入内容(一次完整输入:有输入法到Edit中的一个过程)

好了,问题应该能解决了,结贴

30楼( WindsonZhL ):
呵呵,你自己找到IME的API和消息了(MSDN?),不错不错,赞一个:)

其实对于非系统提供的输入法(第三方输入法),可以不用关注太多,软件之间的冲突多了去了。
不过我曾经被微软拼音害得很惨,从此怕了输入法这块儿了。

31楼( gxj1680 ):
在WinProc中直接用TRACE输出所有消息message号,然后自己屏蔽重复没用的,跟踪查看的,可以在winUser中将对应的message号直接用消息名输出,这样看起来方便,当然自己得研究重复消息

32楼( gxj1680 ):
再补充个其他的东西吧
在没有自己设定SetEventMask前,CRichEditCtrl中,拦截不到EN_CHANGE/ENM_CHANGE
加上下面的代码就可以拦截到EN_CHANGE了

long lMast = GetEventMask();
lMast |= ENM_CHANGE;
lMast &= ~ENM_PROTECTED;
SetEventMask(lMast);

33楼( gxj1680 ):
确实,模式是个好东西啊,不过自己还不太懂,还有很多东西要学啊
Command模式能完全满足Undo和Redo操作,不过这块自己目前还不会,看看再说这个

引用 28 楼 xiansheng00 的回复:

设计模式里面有个模式Command模式,看懂了你就可以解决这个问题。
帖子链接: http://topic.csdn.net/u/20100816/15/6232364a-ebeb-4bf6-903c-1a3012c447b3.html?seed=441349749&r=67778824#r_67778824

如何做CEdit中的Undo,Redo(和word类似的输入法输入一次为一个回退块)相关推荐

  1. iOS: 为画板App增加 Undo/Redo(撤销/重做)操作

    这个随笔的内容以上一个随笔为基础,(在iOS中实现一个简单的画板),上一个随笔实现了一个简单的画板: 今天我们要为这个画板增加Undo/Redo操作,当画错了一笔,可以撤销它,或者撤销之后后悔了,还可 ...

  2. [转]MySQL日志——Undo | Redo

    本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多 ...

  3. WPF/Silverlight Undo/Redo框架

    应用中Undo/Redo是比较常用的功能,如果每个应用做一个比较麻烦,可以参考如下的框架: 大名鼎鼎的 infragistics 提供的框架: http://blogs.infragistics.co ...

  4. mysql数据库undo日志恢复_MySQL的undo/redo日志和binlog日志,以及2PC

    发现自己的知识点有点散,今天就把它们连接起来,好好总结一下. 一.undo log.redo log.binlog的定义和对比 定义和作用 所在架构层级 日志形式 所在文件和默认名称,组织结构 是否缓 ...

  5. (swing读书笔记)Undo/Redo(下)

    (swing读书笔记)Undo/Redo(下) By cszhao1980 四.更好的集成--StateEdit 现在,实现Undo功能已经比较简单了: (1)         建立一个"普 ...

  6. 【DB笔试面试682】在Oracle中,Undo段中区3种状态分别是什么(Undo表空间系列)?...

    ♣ 题目 部分 在Oracle中,Undo段中区3种状态分别是什么? ♣ 答案部分 Undo信息存储在Undo段中,Undo段又存储在Undo表空间中.Undo表空间仅用于Undo段(在Undo表空间 ...

  7. 改变CEdit中字体大小与颜色

    注:本文是我在CSDN看到了一篇很精彩的技术讨论帖,所以转过来,鞭策自己. 以下是原文(我自己整理了一下) 问题的提出: 楼主olion 怎样修改CEdit中的文本的字体大小及颜色? 1 楼andyg ...

  8. 达梦DM8之使用dmmdf恢复误删除的undo/redo文件

    误删除 undo/redo 日志怎么办? 分以下两种情况: 1.如果有备份文件 如果有备份文件,可以重新初始化一个新的数据库(初始化参数要和原库一样,比如页大小.大小写敏感.字符集等,这些可以在 DM ...

  9. (swing读书笔记)Undo/Redo(上)

    (swing读书笔记)Undo/Redo(上) By cszhao1980 一.UndoableEdit系列 Undo.Redo是十分有用的功能,Swing提供了一组类来协助用户完成Undo.Redo ...

最新文章

  1. Eclipse:xml文件中添加.xsd约束文件
  2. NR 5G 移动性和状态变化
  3. 商业逻辑12讲之管理沟通的逻辑
  4. 架构师之路:从码农到架构师你差了哪些
  5. ubuntu php mysql apache_Ubuntu+Apache+PHP+Mysql环境搭建(完整版)(转)
  6. 3月19日发布!vivo X27配置揭晓:搭载骁龙710处理器
  7. debian dhcp服务启动不了_网刻批量装系统pxe启动教程全自动分区装系统
  8. 转《JAVA和C#得相同点和不同点》
  9. python记录输入次数_如何计算用户输入错误的次数
  10. 网络工程计算机等级,网络工程师题库_计算机等级考试题库_考试资料网
  11. QT 代码添加QScrollArea
  12. 使用ASP.NET MVC Web SignalR 构建单身聊天室(一)
  13. 2021高考成绩查询怎么查小分,2021微信哪个小程序可以查成绩 高考成绩怎么查
  14. 苹果手机还原网络设置会怎样_苹果手机信号不好,那是因为你没这样设置,这样设置信号顶呱呱...
  15. M1芯片完美运行安卓模拟器,简单无坑
  16. 组合学:使用10个数字与52个字母生成1477万个不重复的4位串码
  17. 使用自定义的Layer和Cell实现手写汉字生成(Tensorflow2)
  18. redis:redis-cli使用
  19. 【Niagara 02】Tridium N4使用——照明控制案例
  20. 海康AI开放平台初体验

热门文章

  1. 支付宝扫码支付示例源码
  2. php每30分钟计算一次收益,PHP 计算用户的累计收益
  3. 2021年危险化学品经营单位安全管理人员考试内容及危险化学品经营单位安全管理人员考试资料
  4. C++ 直接计算多项式的值
  5. excel 域 邮件合并_如何获得免费的电子邮件域(5种快速简便的方法)
  6. 玩转华为数据中心交换机系列 | 配置动态路由接入M-LAG
  7. qiankun微前端应用间通信实现
  8. 深入理解Activity的生命周期
  9. 深度学习目标检测方法汇总
  10. GBase 8a 高可用集群同城双活灾备方案