Solved

API Undo Call Doesn't Work in XP

Posted on 2002-04-25
43
506 Views
Last Modified: 2007-12-19
I have a program with more than a thousand users which uses the Windows Undo API.  The call works in 9x, but does not work in 2000 or XP.  Anybody know why?

Here's the declaration:

    Public Const EM_CANUNDO = &HC6
    Public Const EM_EMPTYUNDOBUFFER = &HCD
    Public Const EM_UNDO = &HC7
    Public Declare Function SendMessage Lib "USER32" Alias "SendMessageA" (ByVal hWnd _
    As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
     

Here's how I call it:

        Result = SendMessage(form1.RichTextBox1.hWnd, EM_UNDO, 0, 0)

houston
VB5
0
Comment
Question by:houston
  • 22
  • 10
  • 8
  • +2
43 Comments
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
I just tested this in VB5 on a windows 2k box and it works perfectly.
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
Const WM_USER = &H400
Const EM_CANUNDO = WM_USER + 22
Const EM_EMPTYUNDOBUFFER = WM_USER + 29
Const EM_UNDO = WM_USER + 23
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
Also, why don't you use Private Const WM_UNDO = &H304 instead?
0
 

Author Comment

by:houston
Comment Utility
To:  Richie_Simonetti

I tried the constant set you posted:

                     Const WM_USER = &H400
                     Const EM_CANUNDO = WM_USER + 22
                     Const EM_EMPTYUNDOBUFFER = WM_USER + 29
                     Const EM_UNDO = WM_USER + 23

They didn't work in Win98, where my set were working.

I haven't tried them in XP.  Are they supposed to work in XP but not in Win9x?

houston
0
 

Author Comment

by:houston
Comment Utility
To:  DrDelphi

>  I just tested this in VB5 on a windows 2k box and it works perfectly.

It doesn't work in my full application.  Do you have any ideas what thay might mean or suggestions where I go from here?

houston
0
 

Author Comment

by:houston
Comment Utility
To:  DrDelphi

>  I just tested this in VB5 on a windows 2k box and it works perfectly.

It doesn't work in my full application.  Do you have any ideas what thay might mean or suggestions where I go from here?

houston
0
 

Author Comment

by:houston
Comment Utility
To:  DrDelphi

>  I just tested this in VB5 on a windows 2k box and it works perfectly.

It doesn't work in my full application.  Do you have any ideas what thay might mean or suggestions where I go from here?

houston
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
I have a thought.... can you compile a test application doing the same thing but using it on a standard textbox as opposed to a RichEdit? I am wondering if the problem lies with the RichEdit on the target systems (which may have been updated on my system with a service pack). My basis for this thought can be found on M$'s site at:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/CommCtls/winui/richedit_9d2r.asp

Let me know...


0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
DrDelphi: that's not a bad idea!
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
I have my occasional moments...<g>

0
 

Author Comment

by:houston
Comment Utility
I don't know what this adds, but I created a very simple program that contained only a richtextbox and the API call.  This simple program works with XP.

DrDelphi -- I just read your suggestion and have not had a chance to try it, but there is so much code around the RTB I don't think it will be practical to change it to a simple textbox.

houston
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
I did a try with win2k/vb6 sp5 and rich ocx version 6.0.88.4 and works ok.
0
 

Author Comment

by:houston
Comment Utility
To: Richie

Yes, it worked for me with a very simple program, but doesn't with a more elaborate one.  

Even though I'm using VB5 I'm using version 6.00.8804 of the ocx.

I tried DrDelphi's suggestion.  I found an early, much simpler version of the application where it was practical to change the richbox to a standard textbox.  The standard textbox version works in XP.   I had to eliminate a fair amount of code to get the standard textbox version to compile so I'm not sure whether it was the textbox or the eliminated code that made it work.  I intend to remove the same code and keep the RichBox to isolate this.

houston
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
Could you paste the full code that you use with problematic OCX?
We could do a try in our machines....
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
houston,
  I never intended to suggest that you should remove the RichEdit from your project. I was only suggesting that to debug where the problem was, in your code or in the RichEdit itself. As it turns, we were able to determine that the problem is in fact somewhere in your code, since you are able to make it work in a simpler application. I would never intentionally have someone change something that should work, just because they are unable to get it. My suggestion was meant to help you find out WHY it wasn't working.


Good luck!!
0
 

Author Comment

by:houston
Comment Utility
DrDelph -- I understood you were suggesting a test (debug).  Sorry if I said something that led you to think otherwise.  

There's too much code around the current version of the program to change it to a standard textbox (for the test), but I found a very old version that was simple enough to change by commenting out the conflicting code.  That's the one I was able to compile with the standard textbox and see that it works in XP.  But, because I had to remove so much stuff to get it to compile I'm not sure whether it was removing the code or substituting the textbox that made it work.

houston
0
 

Author Comment

by:houston
Comment Utility
Richie -- Thanks for the offer, but there's far too much code layered around the RTB to post.  The RTB is the central feature of the application with about 30 forms and 20 modules. The main form is  about 200K.   References to the RTB are made throughout the program.

houston
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
Zipping and mailing is an option?
0
 

Author Comment

by:houston
Comment Utility
OK, I've tracked down the cause but I still don't understand the problem.

Create a RichTextBox1 and set up the Undo function as described in the problem definition - I use a Menu item, but I assume it works the same set up in a command button.

Then in the Change event put this line of code:

Private Sub RichTextBox1_Change()
     DocLength = Len(RichTextBox1.Text)
End Sub

When I do this the Undo API quits working in XP.

Houston

P.S.  If this extension of the original statement of the question violates some kind of Exchange rules tell me how I should do it.
0
 

Author Comment

by:houston
Comment Utility
Hello DrDelph & Richie

Have you seen my latest comments?  

I don't know how this systemt works for Experts (question answerers).  Are you notified by email when I add a comment or do you have to voluntarily come look to see if there is anything new?

houston
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
I did try your little last code and you are right, even in 98 API doesn't works!
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:houston
Comment Utility
Hmmm . . .   That's interesting.  It works in 98 and 95 for me.  I only fails in XP (I don't run 2000 but my first report of Undo failure was from a 2000 user).
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
Comment Utility
I tried in 2000 and doesn't works also. It appears like you are touching a sensitive property with len stuff.
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
Weird! I wonder if it is a timing issue? Since you're reading LEN in the change event and I'm pretty sure that VB is doing an "invisible" selection to get that value... I am thinking that it may be hosing UNDO. Can you try moving the DocLength=Len(Richedit.text) to another event handler (such as button click) and then try UNDO? (for debugging purposes).



Good luck!!

BTW: I'm in the office, no VB here so I am not able to try it out myself.... sorry.


0
 

Author Comment

by:houston
Comment Utility
I tried putting it in keyup with the same result.

Remember this has been working in 9x for many users for years.  I said over a thousand, but in fact it is many thousands.

houston
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
Hmmm. Oh well, it was just a thought....

0
 

Author Comment

by:houston
Comment Utility
And, not to forget,  the len(. . .   in the change event works with a standard text box.
0
 

Author Comment

by:houston
Comment Utility
Do you suppose this qualifies as a VB or XP bug?  If so who reports them to whom?  

More importantly, does Microsoft do anything about them after they are reported?
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
I am not convinced that it is either, but rather a RichEdit problem, based on the fact that you said the standard textbox worked. I'd be VERY interested in seeing not only the version of the RichEdit you're using, but also the dependencies for that library. There may be an issue with one of them. I am completely unable to replicate your problem in either Windows2k OR 98 (VB4 and VB5 on both). I am REALLY starting to suspect the RichEdit itself. Have you tried any of the newer API's for RichEdit to see if they work? (EM_REDO, etc?).


Standing by...
0
 

Author Comment

by:houston
Comment Utility
Seems to me it kinda has to be a bug of some sort.  Maybe a failure to make the newer RichEdit downward compatible.

RICHED.DLL is 4.00.834.839.
riched20.dll is 5.30.23.1200
RichEd32.dll is 5.0.1461.82
I don't have a dep file for them.

No I haven't tried EM_REDO.  How is REDO different from UNDO?

Do you know where I can find an example?  I'm a "monkey see, monkey do" user of APIs.

houston
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
From the M$ knowledgebase:

Platform SDK: Windows User Interface

EM_REDO
Send an EM_REDO message to a rich edit control to redo the next action in the control's redo queue.

To send this message, call the SendMessage function with the following parameters.

SendMessage(
  (HWND) hWnd,              // handle to destination window
  EM_REDO,                  // message to send
  (WPARAM) wParam,          // not used; must be zero
  (LPARAM) lParam           // not used; must be zero
);
Parameters
This message has no parameters; wParam and lParam must be zero.

Return Values
If the Redo operation succeeds, the return value is a nonzero value.

If the Redo operation fails, the return value is zero.

Remarks
To determine whether there are any actions in the control's redo queue, send the EM_CANREDO message.

Requirements
  Windows NT/2000/XP: Included in Windows NT 4.0 and later.
  Windows 95/98/Me: Included in Windows 98 and later.
  Redistributable: Requires Rich Edit 2.0 or later on Windows 95.
  Header: Declared in Richedit.h.



and EM_UNDO (which mentions EM_REDO for RichEdit)

EM_UNDO
The EM_UNDO message undoes the last edit control operation in the control's undo queue. You can send this message to either an edit control or a rich edit control.

To send this message, call the SendMessage function with the following parameters.

SendMessage(
  (HWND) hWnd,         // handle to destination window
  EM_UNDO,             // message to send
  (WPARAM) wParam,     // not used; must be zero
  (LPARAM) lParam      // not used; must be zero
);
Parameters
This message has no parameters.

Return Values
For a single-line edit control, the return value is always TRUE.

For a multiline edit control, the return value is TRUE if the undo operation is successful, or FALSE if the undo operation fails.

Remarks
Edit controls and Rich Edit 1.0: An undo operation can also be undone. For example, you can restore deleted text with the first EM_UNDO message, and remove the text again with a second EM_UNDO message as long as there is no intervening edit operation.

Rich Edit 2.0 and later: The undo feature is multilevel—so sending two EM_UNDO messages will undo the last two operations in the undo queue. To redo an operation, send the EM_REDO message.

Rich Edit: Supported in Rich Edit 1.0 and later. For information about the compatibility of rich edit versions with the various system versions, see About Rich Edit Controls.

Requirements
  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winuser.h; include Windows.h.



and the CONSTANTS for REDO actions, etc:

Public Const WM_COPY = &H301
Public Const WM_CUT = &H300
Public Const WM_PASTE = &H302

Public Const WM_USER = &H400
Public Const EM_SETTEXTMODE = (WM_USER + 89)
Public Const EM_UNDO = &HC7
Public Const EM_REDO = (WM_USER + 84)
Public Const EM_CANPASTE = (WM_USER + 50)
Public Const EM_CANUNDO = &HC6&
Public Const EM_CANREDO = (WM_USER + 85)
Public Const EM_GETUNDONAME = (WM_USER + 86)
Public Const EM_GETREDONAME = (WM_USER + 87)





Good luck!!



0
 

Author Comment

by:houston
Comment Utility
Thanks, I'll try it later today.
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
Good luck..
0
 

Author Comment

by:houston
Comment Utility
OK, I tried it -- same result.

I think I got it coded right because it works in 98 and fails in XP.

houston

By the way, if I haven't said how grateful I am for your helping me try to solve this, I'm saying it now -- THANK YOU!!
0
 
LVL 6

Expert Comment

by:DrDelphi
Comment Utility
You're welcome... I just wish I knew what the problem is. All the documentation that I have read both on RichEdit and XP says this should work. I don't any XP boxes here myself, but I do have everything else, including numerous versions of Delphi,VB,BCB,VC++, RichEdit, etc. Everything that I have tried has worked. Initially you said that it wasn't working on either Windows 2K OR XP.... have you gotten it to run on W2k at least? If so, I would have to finally admit that it would seem to be an XP issue... if not, then I am back to questioning RichEdit, since I HAVE been able to get it to work consistently in Windows 2K.

>I think I got it coded right because it works in 98 and fails in XP.<



-DrD
0
 

Author Comment

by:houston
Comment Utility
I have no easy way to test on 2000.  I have 98 98SE and XP on my machines.  That's why I never mention testing on 2000.   However, the problem was first reported on 2000, and other 2000 users have confirmed.  Also, Richie says it fails on 2000.  Problem is he says it also fails for him on 98, and I know it has worked for years on thousands of 95/98 boxes.

houston
0
 

Author Comment

by:houston
Comment Utility
I just realized I forgot to mention something.  When I said I got the EM_REDO to work in 98 I'm not sure how it's suppose to behave.  I have to run the function twice for it to Undo.

Enter some characters in the RTB.
 Run EM_REDO  once -- nothing.  Run it a second time -- it Undoes (takes the characters away).  Run it again -- nothing.  Run it a fourth time it Redoes (puts back what it took away before).

Because the name was "Redo" instead of "Undo" I though the was just the way it worked??

houston
0
 

Author Comment

by:houston
Comment Utility
Wait, stop!  I have the EM_REDO results wrong. <blush>  I don't have it working at all.

When I looked at the "works second time" again I remembered that every other time I hit the Undo it calls a Redo which is uses the original EM_REDO call.  So the reason it appeared to be working in 98 on the second call was because I was doing this:

(note I included constants I don't need to avoid leaving out the wrong thing for the test)
EM_UNDO   doesn't work
EM_REDO   always has worked in 98
EM_UNDO   doesn't work
EM_REDO   always has worked in 98

So now I'm not sure I got the EM_REDO API call right here it is.

Public Const WM_COPY = &H301
Public Const WM_CUT = &H300
Public Const WM_PASTE = &H302

Public Const WM_USER = &H400
Public Const EM_SETTEXTMODE = (WM_USER + 89)
Public Const EM_UNDO = &HC7
Public Const EM_REDO = (WM_USER + 84)
Public Const EM_CANPASTE = (WM_USER + 50)
Public Const EM_CANUNDO = &HC6&
Public Const EM_CANREDO = (WM_USER + 85)
Public Const EM_GETUNDONAME = (WM_USER + 86)
Public Const EM_GETREDONAME = (WM_USER + 87)
   
Public Const EM_EMPTYUNDOBUFFER = &HCD
    Public Declare Function SendMessage Lib "USER32" Alias "SendMessageA" (ByVal hWnd _
    As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
     

Result = SendMessage(form1.RichTextBox1.hWnd, EM_REDO, 0, 0)



In the Requirements section it said:
Header: Declared in Winuser.h; include Windows.h.

I don't know what that means.

Also, it says "For a multiline edit control, the return value is TRUE if the undo operation is successful, or FALSE if the undo operation fails."  

It returns 0 (zero).  As I understand it -1 (minus one) is false and any positive number is true.
0
 

Author Comment

by:houston
Comment Utility
geez get in a hurry and I make all kinds of mistakes:

That should read:

EM_REDO   doesn't work
EM_UNDO  always has worked in 98
EM_REDO   doesn't work
EM_UNDO  always has worked in 98

So now I'm not sure I got the EM_REDO API call right here it is.

(note I included constants I don't need to avoid leaving out the wrong thing for the test)
0
 

Author Comment

by:houston
Comment Utility
I should mention the EM_REDO does not work,  period.  Whether the Len(RTB) is included or not.
0
 
LVL 1

Expert Comment

by:Computer101
Comment Utility
A request for deletion has been made.  If no response or you feel this is in error, comment.  If no objection, I will delete in three days.

Computer101
E-E Admin
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
houston, an EE Moderator will handle this for you.
Moderator, my recommended disposition is:

    Refund points and save as a 0-pt PAQ.

DanRollins -- EE database cleanup volunteer
0
 
LVL 1

Accepted Solution

by:
Computer101 earned 0 total points
Comment Utility
Points refunded and placed in PAQ

Computer101
E-E Admin
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now