Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 522
  • Last Modified:

API Undo Call Doesn't Work in XP

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
houston
Asked:
houston
  • 22
  • 10
  • 8
  • +2
1 Solution
 
DrDelphiCommented:
I just tested this in VB5 on a windows 2k box and it works perfectly.
0
 
Richie_SimonettiIT OperationsCommented:
Const WM_USER = &H400
Const EM_CANUNDO = WM_USER + 22
Const EM_EMPTYUNDOBUFFER = WM_USER + 29
Const EM_UNDO = WM_USER + 23
0
 
Richie_SimonettiIT OperationsCommented:
Also, why don't you use Private Const WM_UNDO = &H304 instead?
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
DrDelphiCommented:
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
 
Richie_SimonettiIT OperationsCommented:
DrDelphi: that's not a bad idea!
0
 
DrDelphiCommented:
I have my occasional moments...<g>

0
 
houstonAuthor Commented:
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
 
Richie_SimonettiIT OperationsCommented:
I did a try with win2k/vb6 sp5 and rich ocx version 6.0.88.4 and works ok.
0
 
houstonAuthor Commented:
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
 
Richie_SimonettiIT OperationsCommented:
Could you paste the full code that you use with problematic OCX?
We could do a try in our machines....
0
 
DrDelphiCommented:
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
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
Richie_SimonettiIT OperationsCommented:
Zipping and mailing is an option?
0
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
Richie_SimonettiIT OperationsCommented:
I did try your little last code and you are right, even in 98 API doesn't works!
0
 
houstonAuthor Commented:
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
 
Richie_SimonettiIT OperationsCommented:
I tried in 2000 and doesn't works also. It appears like you are touching a sensitive property with len stuff.
0
 
DrDelphiCommented:
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
 
houstonAuthor Commented:
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
 
DrDelphiCommented:
Hmmm. Oh well, it was just a thought....

0
 
houstonAuthor Commented:
And, not to forget,  the len(. . .   in the change event works with a standard text box.
0
 
houstonAuthor Commented:
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
 
DrDelphiCommented:
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
 
houstonAuthor Commented:
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
 
DrDelphiCommented:
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
 
houstonAuthor Commented:
Thanks, I'll try it later today.
0
 
DrDelphiCommented:
Good luck..
0
 
houstonAuthor Commented:
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
 
DrDelphiCommented:
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
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
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
 
houstonAuthor Commented:
I should mention the EM_REDO does not work,  period.  Whether the Len(RTB) is included or not.
0
 
Computer101Commented:
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
 
DanRollinsCommented:
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
 
Computer101Commented:
Points refunded and placed in PAQ

Computer101
E-E Admin
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 22
  • 10
  • 8
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now