• Re: riched20 - save and load cursor position (Newyana2)

    From Newyana2@21:1/5 to R.Wieser on Tue Jun 13 09:10:17 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote

    | As you have mentioned to have done quite a bit with the RichEdit control,
    | maybe you can help me understand a problem I had a while ago.
    |
    | I loaded an RTF file (containing multiple font sizes) into a RichEd20
    | control, Than Itried to save the cursor position using EM_GETSCROLLPOS and
    | later restore the position using EM_SETSCROLLPOS.
    |
    | The problem ? Even when I executed those two commands directly after the
    | other* the cursor jumped up a number of lines.
    |

    I sandwich operations between LockWindowUpdate
    on the parent window. I also sometimes add EnableWindow
    on the RichEdit itself. The former blocks painting. The
    latter blocks input from mouse and keyboard.

    DoEvents
    LockWindowUpdate ParentWindow.hWnd
    EnableWindow hRE.hWnd, False

    ' [Here I might do something like read out the
    RE content and run the string through a tokenizing
    routine to update formatting, colors, or whatever,
    then put back the new RTF text.]

    EnableWindow hRE.hWnd, True
    LockWindowUpdate 0

    At some point MS decided LockWindowUpdate should not be
    used and recommended a WM_SETREDRAW message instead.
    If I remember correctly, LWU wraps that message along with
    other operations. I never understood the hubbub. Raymond
    Chen goes on about how all hell will break loose if you start
    running LWU on multiple windows because there's no window
    handle for unlocking. But I don't see a problem with that. I'm
    not doing it with multiple windows and I only do it for a fraction
    of a second. It may be possible for another program to make
    the same call during that fraction of a second while someone is
    using my editor, but that's farfetched. At any rate, you can try
    WM_SETREDRAW. Both block painting but keep track of changes
    for painting after unlock. EnableWindow, by contrast, is used to
    block input to the window entirely while a locking operation is
    going on.

    I find that if I can do all operations in less than 1/4 second
    then the window display is smooth and the content just updates
    in appearance. I don't if that covers the problem you're having.
    I Guess I typically record SelStart before any operation and
    then return it to that position. EM_GETSEL and EM_SETSEL.

    I don't get how you're doing any of this with script, but I'll
    leave you to it. :) However, getting, setting SelStart requires
    a long pointer to a CHARRANGE STRUCT. The STRUCT is two
    longs, which specify the starting point and ending point of
    a specified set of characters. You dson't have to care about that
    if you just return the CHARRANGE from GET to the SET operation,
    but you will need to handle a CHARRANGE.


    | P.s.
    | I posted the question here as you frequent this newsgroup. But I've set
    | the follow-up to "comp.os.ms-windows.programmer.win32". If thats not a
    | newsgroup your newsgroup provider carries than please remove the
    | redirection.
    |

    I'll find out, I guess. I'm setting it for both, since
    it's possible someone here would be curious. I used
    to visit maybe 6-7 programming groups, including
    Win32 API. I didn't know there were any still left.
    The only one I still go to is vb.general.discussion,
    which still gets regular traffic.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Tue Jun 13 17:45:00 2023
    XPost: alt.windows7.general

    Newyana2,

    I sandwich operations between LockWindowUpdate on the parent
    window. I also sometimes add EnableWindow on the RichEdit itself.

    I just tried either and both LockWindowUpdate and EnableWindow but alas, I
    got the same jumping result.

    Thanks for the suggestion though.

    I'll find out, I guess. I'm setting it for both, since
    it's possible someone here would be curious.

    That indeed has happened. I was hoping they would move to this (comp.os.ms-windows.programmer.win32) newsgroup too.

    I used to visit maybe 6-7 programming groups

    Most of the programming newsgroups I visit are of little usage to me, as my questions are seldom about the language, but instead about the underlaying controls, DLL functions, etc.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Newyana2@21:1/5 to R.Wieser on Tue Jun 13 15:14:51 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote

    | I just tried either and both LockWindowUpdate and EnableWindow but alas, I
    | got the same jumping result.
    |

    I don't see how that's possible. If you do a LWU, then
    save the cursor pos, then do operations, then reset
    the cursor, then unlock window, it's not possible for
    the window to move while you're doing all that.

    Did you also save and reset the SelStart position?
    If you do as above but end up with SelStart (cursor pos)
    several lines away, then it will jump. You have to put
    everything back as it was before you unlock.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Tue Jun 13 22:27:29 2023
    XPost: alt.windows7.general

    Newyana2,

    I don't see how that's possible.

    I don't either, but it still does.

    I just retried it, and it behaves the same. To double-check I removed the unlocking, and afterwards, as expected, wasn't able to interact with the RichEdit control anymore.

    And something I did not mention before : the jumps seem to get smaller the closer the cursor gets to the top.

    Did you also save and reset the SelStart position?

    No. Why should I ?


    Ehhrrmmm... I said I saved the /cursor/ position, but as you probably have noticed fromk the used EM_xxx messages, I was trying to save and restore the position of the "view". IOW, I'm not even touching the cursor (anymore).

    For reference, here is the code thats under the button :

    ;-- Get the current scrollpos location
    call SendMessageA,[@@hWnd],EM_GETSCROLLPOS, 0, ebx

    ;-- go to that same location
    call SendMessageA,[@@hWnd],EM_SETSCROLLPOS, 0, ebx

    (some debugging-output snipped)

    If you do as above but end up with SelStart (cursor pos)
    several lines away, then it will jump.

    I start with the cursor in the view. When I than click the button the view jumps /away/ from it, in the direction of the start of the file.

    Looking at the vertical scrollbar it jumps to a position halfway between the current position an the top of the text. Scrolling the view using that scrollbar works normally.

    I have absolutily no idea what is happening. :-(

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Newyana2@21:1/5 to R.Wieser on Tue Jun 13 17:31:15 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote
    |
    | > Did you also save and reset the SelStart position?
    |
    | No. Why should I ?
    |
    |
    | Ehhrrmmm... I said I saved the /cursor/ position, but as you probably
    have
    | noticed fromk the used EM_xxx messages, I was trying to save and restore
    the
    | position of the "view". IOW, I'm not even touching the cursor (anymore).
    |
    | For reference, here is the code thats under the button :
    |
    | ;-- Get the current scrollpos location
    | call SendMessageA,[@@hWnd],EM_GETSCROLLPOS, 0, ebx
    |
    | ;-- go to that same location
    | call SendMessageA,[@@hWnd],EM_SETSCROLLPOS, 0, ebx
    |
    | (some debugging-output snipped)
    |
    | > If you do as above but end up with SelStart (cursor pos)
    | > several lines away, then it will jump.

    The button? You click a button to run the test?
    I don't know whether that might affect it, since it takes
    focus from that window. But I'm not really understanding
    what you're doing, or why you need a button.

    GETSCROLLPOS is not the same as cursor position.
    Cursor position is EM_EXGETSEL and EM_EX_SETSEL.
    It's a CHARRANGE that describes the selection offset in
    characters and the selection length. So, for example,
    if you send EX_SETSEL with 100, 100 then you'll put the
    cursor at the 100th character with no selection length.

    SCROLLPOS is the scrolled position of the RichEdit window
    in relation to the upper left corner.

    How about if you just do the operation you want without
    the button? In other words, do what you actually want to
    do with the text. Say, for example, that you're going to
    change the font of some words and the color of others. Then
    you get your cursor point and scrollpoint, you lock the window,
    you do your changes, you reset scroll and cursor, and finally
    you unlock. Not via a button by via code. If you have to
    use the button then you might need to always track cursor
    and scroll positions, so that you know where they were when
    the RE loses focus.

    If you change the actual text then of course you'll need to
    account for that. For example, if the cursor is at char 542 and
    you remove the first 100 characters, then 542 will be a
    different position in the text and a different line will be the line
    where you were before.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Jun 14 08:16:57 2023
    XPost: alt.windows7.general

    Newyana2,

    The button? You click a button to run the test?

    Yes. Exactly because its a test.

    I don't know whether that might affect it, since
    it takes focus from that window.

    I moved it from the WM_INITDIALOG code to in a WM_COMMAND bit of code (for
    the buttons event) - as a control might not be fully initialized in WM_INITDIALOG, skewing the result.

    But I'm not really understanding what you're doing,

    Currently ? Trying to figure out what causes that jump.

    Later on ? Use it to save the current "view" position when I close the program, so that it can be restored next time I open it.

    or why you need a button.

    I needed a way to get those two lines of code executed somehow and I wanted
    to remove as much as non-essential code as possible (the actual saving on
    close and loading on opening the program) so it could not interfere (read: cause the problem).

    GETSCROLLPOS is not the same as cursor position.
    Cursor position is EM_EXGETSEL and EM_EX_SETSEL.

    Yes, that was my mistake in naming the problem. Its about saving/restoring the views position, not the cursor.

    SCROLLPOS is the scrolled position of the RichEdit window
    in relation to the upper left corner.

    I would have thought so too (reading the MSDN documentation), but here I am, with two lines of code which do not do what thay are supposed to do. :-(

    How about if you just do the operation you want without
    the button? In other words, do what you actually want to
    do with the text.

    That is what I started with and where I noticed the problem. From that I
    went into "bug hunting mode", stripping as much irrelevant-to-the-problem
    code as I could while keeping the problem itself. Its how I ended up with
    the two lines I posted.

    If you change the actual text then of course you'll need to
    account for that.

    :-) I'm aware of that, thank you.

    Again, my code is now retrieving the views current location and than telling
    it to move *to that same position*. IOW, the view should not move at all.
    Yet, it does. :-(



    Extra info:
    I mentioned that the view jumps to a position roughly halfway the distance between its current position and the top of the text. Subsequent presses
    of the button repeated that effect, roughly halving the distance every time. IOW, its not an offset problem.

    I also turned the whole thing upside-down by setting the views location to a specified one, and than ask where it thought it was.

    set get
    ----- ----
    500 -> 159
    12000 -> 3811
    21000 -> 6669

    The funny thing is that when I divide the latter by the former the factor is the same every time : 0.31757.

    Holdup, let me try something ....

    I just "compiled" the program again, but removed the (dialog definition)
    line specifying the dialogs default font and size. The "get" result
    changed. Why ? Beats me.

    I than also told the RichEdit control to load plain text (instead of RTF
    text, which uses several font sizes). The "get" result again changed.

    IOW, *something* is messing with the "get" result, and it ain't me. <phew!>


    To be absolutily clear about it, the RichEdit control gets created and
    filled with text /way/ before I press the "test" button. And the code
    behind that button only contains (besides some debugging output) the EM_GETSCROLLPOS and EM_SETSCROLLPOS commands. No "funny stuff" of any
    kind.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Jun 14 11:47:41 2023
    XPost: alt.windows7.general

    Newyana2,

    ... I wanted to remove as much as non-essential code as possible (the
    actual saving on close and loading on opening the program) so it could
    not interfere (read: cause the problem).

    Just now I realized that I applied some extra settings to the RichEdit
    control, and disabled all of it. As a result the "set" and "get" started to match. Victory ! (even though not all of the RTF file gets loaded)

    ... well, not quite : what's causing it ?

    It turns out that when use EM_EXLIMITTEXT (so I can load more than 64K of
    RTF) it starts to happen. When I set it to something like 0x50000 the "set"
    and "get" values start to get different, with the difference becoming larger the higer that the EM_EXLIMITTEXT value is.

    Do I have any idea why that its happening ? Nope. Is it in any way
    mentioned on the MSDN webpage explaining EM_EXLIMITTEXT ? Also nope.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Newyana2@21:1/5 to R.Wieser on Wed Jun 14 08:13:11 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote

    | It turns out that when use EM_EXLIMITTEXT (so I can load more than 64K of
    | RTF) it starts to happen. When I set it to something like 0x50000 the
    "set"
    | and "get" values start to get different, with the difference becoming
    larger
    | the higer that the EM_EXLIMITTEXT value is.
    |
    | Do I have any idea why that its happening ? Nope. Is it in any way
    | mentioned on the MSDN webpage explaining EM_EXLIMITTEXT ? Also nope.
    |

    I use 8000000 (decimal). I don't remember how I came up
    with that number. But I doubt it's doing anything but changing
    the theoretical height of the window. Something else seems
    to be affecting the jumping. As my father used to say when no
    one would admit to breaking something, "I guess a ghost must
    have done it." :)

    If it were me I'd lock the window, load the file, set the
    cursor position, then unlock. The cursor is automatically
    scrolled into view, so you don't need the scroll position.
    And scroll position could change, as you say, with font
    changes. But cursor position won't change because it's
    a character offset rather than a window display setting.

    If you want to keep doing it as you're doing it then maybe
    start eliminating factors more. For instance, you could load
    the file from within code. I'm not clear about the dialogue.
    You're making your own window? If you're calling GetOpenFileName
    then the dialogue window is gone when you get the file path,
    so it shouldn't be a factor. But if you're making your own window
    or sub-frame I suppose it could affect where the focus goes.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Jun 14 14:52:41 2023
    XPost: alt.windows7.general

    Newyana2,

    But I doubt it's doing anything but changing
    the theoretical height of the window

    I used different numbers to EM_EXLIMITTEXT, set a constant position using EM_SETSCROLLPOS and saw the EM_GETSCROLLPOS return different values. If its not /the/ cause than it still influences it - even though, as you remarked,
    it should not have to do anything with it.

    If it were me I'd lock the window, load the file, set the
    cursor position, then unlock.

    Its currently not about restoring the views position (I used another approch which seems to work alright, even if a bit clumsy), but about determining if
    I should remove the EM_GET- and EM_SETSCROLLPOS from the list of usable messages - so I won't run into something similar in the future.

    By the way: I found, while googeling, a few other messages about having the same problem. None of them mentioned a solution to it.


    If you want to keep doing it as you're doing it then maybe
    start eliminating factors more.

    Such as ?

    For instance, you could load the file from within code.

    I'm already doing that. Starting a program after each small edit (trying to locate the problem) and than having to load the same file over-and-over
    again quickly becomes tiresome.

    Besides, bughunting should not be done on something you're (unknowingly, mistakingly) changing the parameters to. IOW, for/during my testing the filename (and (thus) the loaded text) is a constant.

    I'm not clear about the dialogue. You're making your own window?

    You always do. :-) In my case I describe a dialog in a resource file, and
    than load that resource using "call DialogBoxParamA,0, IDC_DIALOG,0,offset DialogCB,0"

    Also, as mentioned, the reason why I found EM_EXLIMITTEXT to be involved is because I effectivily disabled /everytyhing/. And that was enough to make
    the problem disappear - on the cost of only seeing a partially-loaded RTF
    file.


    If you want to see the full sourcecode (or certain parts thereof) you only
    have to ask. I have no problem with posting it (here and/or to an email addres).

    Remark: Its in Assembly (should not be too hard to read, but you never
    know).

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Jun 14 16:54:33 2023
    Paul,

    You're still not using quite the right terminology, if you say the problem right it
    might be easier to solve :-)

    That might have been true when I posted my first message about it (mea
    culpa), but not not this far in the thread. If by now you have no idea
    what I'm talking about you never will. :-)

    If you try to set the scroll position to a place where the carat won't actually be visible
    in the window, my understanding is that it will scroll to a different
    place instead where
    the carat will be visible.

    If you have ever used the a scrollwheel in an edit control (or just the vertical, or even horizontal slider) you know that is false.

    Though when you type something or even use the cursor keys to move the caret around the view will snap to a location which includes the caret.

    So you want to set the carat position in the text before you try adjusting the scroll to
    show the part of the text you desire.

    In the parent to your message I wrote that each press of the button (and executing the EM_GETSCROLLPOS, EM_SETSCROLLPOS combination) the "view" would jump further "up"wards, towards the start of the text. That would not be possible if what you say in the above is true, 'cause the "view" would than stay leashed to the caret, keeping it in view..

    This may be the source of your difficulties.

    So no, it isn't (alas).

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul N@21:1/5 to R.Wieser on Wed Jun 14 07:29:01 2023
    On Wednesday, June 14, 2023 at 7:17:22 AM UTC+1, R.Wieser wrote:
    GETSCROLLPOS is not the same as cursor position.
    Cursor position is EM_EXGETSEL and EM_EX_SETSEL.
    Yes, that was my mistake in naming the problem. Its about saving/restoring the views position, not the cursor.

    You're still not using quite the right terminology, if you say the problem right it might be easier to solve :-)

    The "cursor" is the mouse pointer which moves around when you move the mouse. The "carat" is the flashing line which indicates where new text will go if you type any, and which moves when you press the arrow keys.

    If you try to set the scroll position to a place where the carat won't actually be visible in the window, my understanding is that it will scroll to a different place instead where the carat will be visible. So you want to set the carat position in the
    text before you try adjusting the scroll to show the part of the text you desire. This may be the source of your difficulties.

    Hope this is in some way helpful!
    Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Newyana2@21:1/5 to R.Wieser on Wed Jun 14 12:51:41 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote

    | > I'm not clear about the dialogue. You're making your own window?

    | You always do. :-) In my case I describe a dialog in a resource file, and
    | than load that resource using "call DialogBoxParamA,0, IDC_DIALOG,0,offset
    | DialogCB,0"

    I've never used that. I use GetOpenFileName, to
    give me a system file-open window with all the fixings.

    |
    | If you want to see the full sourcecode (or certain parts thereof) you only
    | have to ask. I have no problem with posting it (here and/or to an email
    | addres).
    |
    That might be good. I'm having trouble following. I thought
    you said the problem was with loading a file, and now you say
    it isn't. So I don't really understand what you're doing. If I
    can make out the code then I might be able to run my own test.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Wed Jun 14 20:06:58 2023
    XPost: alt.windows7.general

    Newyana2,

    | In my case I describe a dialog in a resource file, and than load
    | that resource using "call DialogBoxParamA,0, IDC_DIALOG,0,offset
    | DialogCB,0"

    I've never used that. I use GetOpenFileName, to
    give me a system file-open window with all the fixings.

    Were talking about two very different things here : you're talking about the dialog which allows you to select a file to be opened, I on the other hand
    was describing how I create a programs window with all the controls on it.

    I could use that "GetOpenFileName" dialog to select the file to load into my programs RichEdit control, but I normally pass the filename as a commandline argument. Like when you click a datafile and the associated program gets executed, which than "automatically" opens the datafile.

    That might be good. I'm having trouble following.

    I thought you said the problem was with loading a file,

    I can't remember I did. I did however mention that I loaded an RTF file
    into a RichEdit control - as a base to test against.

    My whole-and-only problem consists manipulating the position of the current "view", using those EM_GETSCROLLPOS and EM_SETSCROLLPOS messages. The rest
    is just fluff to be able to see what happens.

    Here are the two files (.RC and .ASM). I've removed any-and-everything not related to the problem.

    Regards,
    Rudy Wieser


    .RC (resource) file :

    - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    #include "RichEd20.rci"

    ;================================================

    #define IDD_BASEWIN 1000
    #define IDC_EXECUTE 1002
    #define IDC_RICHEDIT 1003

    IDD_BASEWIN DIALOG DISCARDABLE 300, 0, 450, 200

    ;-- Create a sizable window
    STYLE DS_3DLOOK | WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX |
    WS_MINIMIZEBOX ;| DS_CENTER

    CAPTION "RICHED20 20220411"
    FONT 8, "MS Sans Serif"
    BEGIN

    CONTROL "",IDC_RICHEDIT,"RichEdit20A"
    ,WS_TABSTOP | WS_BORDER ; | ES_SAVESEL | ES_NOHIDESEL
    | ES_MULTILINE | WS_VSCROLL ; | ES_WANTRETURN
    ,5,5,445,175

    PUSHBUTTON "&Execute",IDC_EXECUTE,5,185,50,11

    END

    ;================================================

    - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    The .ASM (Assembly) file :
    - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    ;=======================
    .Target equ GUI

    .486
    .model flat,STDCALL
    stackalign
    locals

    ;-----------------------
    .nolist

    INCLUDELIB KERNEL32.LIB
    INCLUDE KERNEL32.INC

    INCLUDELIB USER32.LIB
    INCLUDE USER32.INC

    INCLUDELIB RichEd20.LIB
    INCLUDE RichEd20.INC

    .list
    ;-----------------------

    ;-- Load the control-ID constants (IDD_xxx and IDC_xxx, extracted from the resource file)

    % include @FileName.rhi

    ;=======================









    ;=======================
    .CODE
    ;-----------------------

    Start proc
    ;-- Initialize RichEdit component
    call LoadLibraryA,offset @@TXT_RichEdDLL

    ;-- Create the programs window
    call DialogBoxParamA,0,IDD_BASEWIN,0,offset DialogCB,0

    call ExitProcess,eax

    ;=======================
    .DATA
    ;-----------------------

    @@TXT_RichEdDLL db 'RichEd20.dll',0

    ;-----------------------
    Start endp
    ;=======================









    ;=======================
    .CODE
    ;-----------------------

    DialogCB proc
    arg @@hWnd:DWORD,@@wMsg:DWORD,@@wParam:DWORD,@@lParam:DWORD
    uses ebx,ecx,edx,esi,edi

    movzx eax,word ptr [@@wMsg]

    cmp eax,WM_INITDIALOG
    je @@Init

    cmp eax,WM_CLOSE
    je @@Close

    cmp eax,WM_COMMAND
    je @@Command

    @@DialogCB_Cont:
    xor eax,eax
    @@DialogCB9:
    ret

    ;-----------------------

    @@Init:
    call SendDlgItemMessageA,[@@hWnd],IDC_RICHEDIT,EM_EXLIMITTEXT,0,10000000
    ;10M chars

    call LoadDocument,[@@hWnd],IDC_RICHEDIT,offset [@@TXT_File]

    jmp @@DialogCB_Cont

    ;-----------------------

    @@Close:
    call EndDialog,[@@hWnd],0
    jmp @@DialogCB_Cont

    ;-----------------------

    @@Command:
    movzx eax,word ptr [@@wParam]

    cmp eax,IDC_EXECUTE
    je @@Execute

    jmp @@DialogCB_Cont

    ;---------------

    @@Execute:
    call GetDlgItem,[@@hWnd],IDC_RICHEDIT
    call Fail1Test,eax

    jmp @@DialogCB_Cont

    ;=======================
    .DATA
    ;-----------------------

    ;-- Make sure the 'TestRTF.doc' file is large enough (over 250 KByte
    ; on my machine), otherwise the problem won't show

    @@TXT_File label byte
    db 'TestRTF.doc',0

    ;-----------------------
    DialogCB endp
    ;=======================









    ;=======================
    .CODE
    ;-----------------------
    LoadDocument PROCDESC hWnd:DWORD,lCtlID:DWORD,sFile:DWORD
    ; Load either an RTF or plain text document

    LoadDocument proc
    arg @@hWnd:DWORD,@@lCtlID:DWORD,@@sFile:DWORD
    uses ebx
    local @@rES:EDITSTREAM

    cmp [@@lCtlID],0
    je @@LoadDocument1

    call GetDlgItem,[@@hWnd],[@@lCtlID]
    mov [@@hWnd],eax
    @@LoadDocument1:

    lea ebx,[@@rES]
    call RtlZeroMemory,ebx,size EDITSTREAM
    mov [ebx].ES_pCallBack,offset @@LoadFileCB

    ;-- Needs to be set, as EM_SETTEXTMODE can cause an RTF file to
    ; be rejected, but EM_STREAMIN than *doesn't* set an error ..
    mov [ebx].ES_lError,0FFFFFFF0h ;Needs to be given a real error code

    call CreateFileA,[@@sFile],GENERIC_READ, FILE_SHARE_READ, 0 \
    ,OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0
    mov [ebx].ES_lCookie,eax
    cmp eax,INVALID_HANDLE_VALUE
    je @@LoadDocument_E

    ;-- Try to load the file as RTF. Might fail.
    call SendMessageA,[@@hWnd],EM_STREAMIN,SF_RTF,ebx
    ; and eax,eax ;# of chars read. Zero doesn't need to be an error ...
    ; jz @@LoadDocument_E1

    cmp [ebx].ES_lError,0FFFFFFF0h ; -16 (no idea what this error means...)
    jne @@LoadDocument2

    ;-- Try to load the file as plain text
    call SetFilePointer,[ebx].ES_lCookie,0,0,FILE_BEGIN

    call SendMessageA,[@@hWnd],EM_STREAMIN,SF_TEXT,ebx

    @@LoadDocument2:
    cmp [ebx].ES_lError,0 ;Any error?
    jne @@LoadDocument_E1 ;Yep

    call CloseHandle,[ebx].ES_lCookie

    ;-- OK --
    clc
    @@LoadDocument9:
    ret

    ;---------------

    @@LoadDocument_E1:
    call CloseHandle,[ebx].ES_lCookie
    @@LoadDocument_E:
    ;-- Error --
    stc
    jmp @@LoadDocument9

    ;-----------------------

    @@LoadFileCB proc
    arg @@lCookie:DWORD,@@pBufDat:DWORD,@@lBufSiz:DWORD,@@plReadCnt:DWORD

    call ReadFile,[@@lCookie],[@@pBufDat],[@@lBufSiz],[@@plReadCnt],0

    cmp eax,1
    sbb eax,eax
    ret
    endp

    ;-----------------------
    LoadDocument endp
    ;=======================









    ;=======================
    .CODE
    ;-----------------------
    Fail1Test PROCDESC hWnd:DWORD

    Fail1Test proc
    arg @@hWnd:DWORD
    uses ebx
    local @@rPnt:POINT

    lea ebx,[@@rPnt]

    ;-- Get the current scrollpos location
    call SendMessageA,[@@hWnd],EM_GETSCROLLPOS, 0, ebx

    ;-- go to that same location
    call SendMessageA,[@@hWnd],EM_SETSCROLLPOS, 0, ebx

    ret

    ;-----------------------
    Fail1Test endp
    ;=======================









    ;=======================

    end Start
    ends

    ;-----------------------

    - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Newyana2@21:1/5 to All on Wed Jun 14 16:48:05 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote...

    |code

    That code doesn't really tell me much, but I tried setting up
    a quickie with VB code and a VB RichTextBox, which wraps
    RichEdit. I did find that it acts as you say. I don't know why.
    When I get and set scrollpos it jumps, and each additional
    operation moves the scrollpos up. However, if I get and set
    the caret position it works fine, with no jumping:

    Private Const WM_USER = &H400&
    Private Const EM_GETSCROLLPOS = (WM_USER + 221)
    Private Const EM_SETSCROLLPOS = (WM_USER + 222)
    Private Const EM_EXGETSEL = (WM_USER + 52)
    Private Const EM_EXSETSEL = (WM_USER + 55)

    Private Type POINTAPI
    X As Long
    Y As Long
    End Type

    Private Type CHARRANGE
    cpMin As Long
    cpMax As Long
    End Type


    Private Declare Function SendMessageAnyW Lib "user32" Alias "SendMessageW" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam
    As Long) As Long


    Private Sub Command1_Click() '-- load big file.
    RTB.LoadFile "C:\Windows\Desktop\bible.txt", 1 '--should be over 250 KB. :)
    End Sub

    Private Sub Command2_Click() '-- get and set scroll position.
    Dim LRet As Long, PT2 As POINTAPI

    LRet = SendMessageAnyW(RTB.hWnd, EM_GETSCROLLPOS, 0&, VarPtr(PT2))
    Debug.Print PT2.Y
    LRet = SendMessageAnyW(RTB.hWnd, EM_SETSCROLLPOS, 0&, VarPtr(PT2))
    Debug.Print PT2.Y
    End Sub

    Private Sub Command3_Click() '-- get and set cursor position.
    Dim CR1 As CHARRANGE
    On Error Resume Next
    SendMessageAnyW RTB.hWnd, EM_EXGETSEL, 0, VarPtr(CR1)
    Debug.Print CR1.cpMin
    SendMessageAnyW RTB.hWnd, EM_EXSETSEL, 0, VarPtr(CR1)
    Debug.Print CR1.cpMin
    End Sub

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Thu Jun 15 08:56:48 2023
    XPost: alt.windows7.general

    Newyana2,

    I did find that it acts as you say. I don't know why.
    When I get and set scrollpos it jumps, and each
    additional operation moves the scrollpos up.

    Thank you for confirming it.

    Now all I need to do is figure out how to fix it - if at all possible (have seen it mentioned as a being bug).

    However, if I get and set the caret position it works fine,

    That was never a problem. EM_SETSEL has always worked for me.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Apd@21:1/5 to R.Wieser on Thu Jun 15 10:43:02 2023
    XPost: alt.windows7.general

    "R.Wieser" wrote:
    Newyana2,

    I did find that it acts as you say. I don't know why.
    When I get and set scrollpos it jumps, and each
    additional operation moves the scrollpos up.

    Thank you for confirming it.

    Now all I need to do is figure out how to fix it - if at all possible
    (have seen it mentioned as a being bug).

    I played with the VB code and found it seems to be a function of font
    size and window width. If the font size is not too large and the rich
    text box is wide enough, the jumping doesn't occur. I don't know
    exactly what that relationship is. Very strange!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Thu Jun 15 12:37:36 2023
    XPost: alt.windows7.general

    Apd,

    I played with the VB code and found it seems to be a function of font size and window width. If the font size is not too large and the rich text box
    is wide enough, the jumping doesn't occur. I don't know exactly what that relationship is. Very strange!

    Thanks for looking into it. :-)

    When you made the problem disappear by making the font smaller and the
    control wider, have you also tried to increase the ammount of loaded text (double the document) ?

    The problem might be a function of the total height of the document. Both
    of your changes lessen it.

    My own guess that EM_EXLIMITTEXT is involved does also match the (updated, still guessed) "total height" possible cause : Limit the ammount of text
    that can be loaded and you limit the hight of the document.

    Hmm... I just tried to remove all line-ends within the paragraphs, but still got the/my problem.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Apd@21:1/5 to R.Wieser on Thu Jun 15 12:52:46 2023
    XPost: alt.windows7.general

    "R.Wieser" wrote:
    Apd,

    I played with the VB code and found it seems to be a function of font
    size and window width. If the font size is not too large and the rich
    text box is wide enough, the jumping doesn't occur. I don't know exactly
    what that relationship is. Very strange!

    Thanks for looking into it. :-)

    When you made the problem disappear by making the font smaller and the control wider, have you also tried to increase the ammount of loaded text (double the document) ?

    The larger the byte count, the worse it is. I already had 500K of text.
    With a larger amount, it's not possible to make the window wide enough
    unless you have a very wide screen. With 100K or less, the window can
    be quite narrow before the effect is seen. BTW. I'm using Tahoma 10pt, throughout.

    The problem might be a function of the total height of the document. Both
    of your changes lessen it.

    I also varied the window height but it made no difference.

    My own guess that EM_EXLIMITTEXT is involved does also match the (updated, still guessed) "total height" possible cause : Limit the ammount of text
    that can be loaded and you limit the hight of the document.

    Maybe with a really tall screen it would be seen!

    Hmm... I just tried to remove all line-ends within the paragraphs, but
    still got the/my problem.

    I'm using many copies of the same paragraph, 356 characters long which
    wraps to the window.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Newyana2@21:1/5 to R.Wieser on Thu Jun 15 08:06:14 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote

    |
    | Now all I need to do is figure out how to fix it - if at all possible
    (have
    | seen it mentioned as a being bug).
    |
    It may very well be a bug. I've come across other bugs.
    Especially when things are not well documented. Sometimes
    I think MS assigns people to break things that are not officially
    documented. For example, when I added UTF-8 support for
    richedit I came across listings for the flags needed, but when
    I actually did it, it was all mixed up. Some EM messages work
    with it. Some don't. Special handling was needed for ANSI vs
    unicode strings. It was all trial and error.

    A similar thing once happened in Win98. People were using
    an icon choosing system window and MS changed the functionality
    in ME. It wasn't official, so no one could complain. Then, if I
    remember correctly, they broke it altogether in XP. The dialogue
    window was still there. MS just reworked it in arbitrary ways so
    that it wouldn't work unless you had the secret initiation. Then there's
    also the infamous Bags keys in the Registry to save window
    coordinates for Explorer windows. MS broke the whole system
    with every Windows version and as far as I know they never
    had it working properly. The Registry keys have to be edited
    to make it work. Yet MS went to great lengths to make that difficult.
    It's like a supermarket where they shuffle the products around
    every night, just to be a wiseguy.

    The scrollpos issue never showed up for me because I don't
    use it to save a position. I only use it for line numbers. I have
    a second RE window along the edge of the main RE, which I use
    to provide line numbers. When the main RE moves, the line
    numbers RE must match it. That functionality works fine. When
    I do operations with lockwindowupdate I just return it to the
    original caret position before unlocking. With paste I need
    to calculate the caret position to put it at the end of the paste.
    There are little details like that. But I don't think I've ever needed
    anything but caret position saved before an operation and reset
    at the end.

    With multiple files I save the top line position and then set
    it to that position when switching between loaded files. For
    that I use EM_GETFIRSTVISIBLELINE and EM_LINESCROLL. I
    guess I probably also save the caret position. It's not all fresh in
    my mind, as I haven't worked with this for some time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Fri Jun 16 10:23:29 2023
    XPost: alt.windows7.general

    Apd,

    The larger the byte count, the worse it is.

    I've been doing some more testing, varying the size of the file and the # of characters on a line but could not pinpoint what caused the problem.

    But something raised my suspicion : when I changed the size of the file I noticed that the "no problem" vs "a problem" file always had near to or over 4000 lines.

    So, I disabled RichEd20's wordwrap (so that the number of lines in RichEd20 matched the sourcefile, regardless of how long the lines where), and just
    added and removed empty lines.

    To make sure the size of the loaded file wasn't a problem the first time I reached the "no problem" -> "problem" point again I replaced some long lines with empty ones (the file became smaller, even though it contained the same
    # of lines)

    The end result ? The "no problem" -> "problem" point was when I changed
    the number of lines in the file from 4096 to 4097. Yep, from 0x1000 to
    0x1001. :-)

    I just generated a file in which I only had the line number printed (just
    over 30 KByte) and the problem occurred on the same line.

    IOW, it looks like a magical number is involved, but MS "forgot" to mention
    it.

    Regards,
    Rudy Wieser

    P.s.
    It looks like its influencing the EM_GETSCROLLPOS. With 4095 lines the
    "view"s Y position is 0xFEFE, with twice the ammount of lines its 0xFF8F.
    Not really twice as much height, wouldn't you say ? :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Fri Jun 16 10:12:44 2023
    XPost: alt.windows7.general

    Newyana2,

    It may very well be a bug. I've come across other bugs.

    It very well might be. But it also might be an oversight when creating the documentation (which is also a bug, but of a different kind :- )

    As I just wrote to Apd, I just found out that the problem starts to occur
    when RichEdit shows 4096 or more /displayed/ lines (a word wrap counts as another line).

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Apd@21:1/5 to R.Wieser on Fri Jun 16 13:34:57 2023
    XPost: alt.windows7.general

    "R.Wieser" wrote:
    [...]
    The end result ? The "no problem" -> "problem" point was when I changed
    the number of lines in the file from 4096 to 4097. Yep, from 0x1000 to 0x1001. :-)

    In a test I did, the jumping happened on exactly 4096 lines but only
    when EM_GETSCROLLPOS > 32768. Below 32768, the jumping stopped. This
    used short lines with no wrap in 10pt Courier New.

    IOW, it looks like a magical number is involved, but MS "forgot" to
    mention it.

    Yes, magic numbers. The same problem from 2005:
    "RichTextBox scrolling incorrect" <https://groups.google.com/g/microsoft.public.vb.controls/c/o1NiVb526NE>

    "... problem occurs if fontheight in pixels * line count > 64k"

    I tried more than 4096 lines with a smaller font (8pt Courier New) and
    there was no jumping.

    It looks like its influencing the EM_GETSCROLLPOS. With 4095 lines the "view"s Y position is 0xFEFE, with twice the ammount of lines its 0xFF8F.
    Not really twice as much height, wouldn't you say ? :-)

    See also this:

    <https://learn.microsoft.com/en-us/windows/win32/controls/em-getscrollpos>

    "The values returned in the POINT structure are 16-bit values (even in
    the 32-bit wide fields)".

    What a mess!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Fri Jun 16 15:51:27 2023
    XPost: alt.windows7.general

    Apd,

    In a test I did, the jumping happened on exactly 4096 lines but only when EM_GETSCROLLPOS > 32768. Below 32768, the jumping stopped. This used short lines with no wrap in 10pt Courier New.

    I did the test using a flat textfile. To get a 4096 lines with a height
    less than 32768 the font size needs to be 8 units or less.

    Though in my case I had 4096 lines and (as mentioned) EM_GETSCROLLPOS
    returned a value of just under 0xFF00 when the jumping stopped. Thats quite
    a bit higher as what you found ...

    I think I also found your first link (I did quite bit of googeling trying to find out what caused the problem), but as it was mostly guesses I put it
    aside. Ah yes, april last year.

    "The values returned in the POINT structure are 16-bit values (even in the 32-bit wide fields)".

    Damn! Thats something I missed, even though I suspected something like it.

    Though assuming that is clipped to 16 bits it doesn't explain why doubling
    my file resulted in a larger value (from 0xFEFE to 0xFF8F) : any value below 65536 doubled but modulo 65536 should become less than the doubled value,
    not more. Odd.

    What a mess!

    It certainly is. Even just by the absense of a clear warning.


    By the way, I just realized that the 4096 line limit could well be just a side-effect of that 16-bit clipping and the size of the plain-text font.

    ... testing ...

    I just changed the font to 120 twips (6 points) and used a plain-text file
    with lines showing the numbers 0 ... 4100. The EM_GETSCROLLPOS returned the value 0xDF58 and no jumping occured.

    IOW, its not a "number of lines" related, but, as you suggested earlier,
    just the height of the document. Strange though that it keeps jumping, even when the location of the view becomes lower than 65536.

    And again doubling the number of lines caused the result become larger, not smaller (0xDF58 -> FF6F).

    Another fine mess I/we find myself/ourselves in ! :-( :-)

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Fri Jun 16 19:01:22 2023
    XPost: alt.windows7.general

    Newyana2,

    Not all that bad. It leaves me room for about 60 -70
    window heights worth of text. On the one hand, there
    seems to be no excuse for limiting 32-bit values to
    16-bit.

    I could imagine something like that for earlier versions of the OS (win 3.x, perhaps W95 and W98 too), but not for later ones. /Especially/ not for versions Vista and up.

    On the other hand, who needs 4000 lines of text with
    formatting?

    I dunno, anyone who reads documents or stories ? :-p Like I've got RFC's
    that are have a 4000+ linecount (RFC 883 (domain names) to name one).

    The real tragedy is that you're not finding a way to
    get paid for your uncanny ability to find bugs. :)

    I don't think I'm good at finding bugs. I just come across them while I'm trying to create something. It just might be my urge to know what is going
    on that I do not just forget about the bug when I find a work-around.

    As for getting payed for them ? The last time I tried to tell a company
    that their product had a problem and asked how they fixed it they claimed
    that it wasn't in their database, so nothing they could do for me. IOW, I would gladly take a fixed product as payment, but I'm not even getting that.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Newyana2@21:1/5 to R.Wieser on Fri Jun 16 12:29:00 2023
    XPost: alt.windows7.general

    "R.Wieser" <address@is.invalid> wrote

    | > What a mess!
    |
    | It certainly is. Even just by the absense of a clear warning.
    |

    Not all that bad. It leaves me room for about 60 -70
    window heights worth of text. On the one hand, there
    seems to be no excuse for limiting 32-bit values to 16-bit.
    On the other hand, who needs 4000 lines of text with
    formatting? The real tragedy is that you're not finding
    a way to get paid for your uncanny ability to find bugs. :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Fri Jun 16 19:11:00 2023
    XPost: alt.windows7.general

    I just come across them while I'm trying to create something.

    One thing that could be of influence : I'm writing Assembly (rather low
    level) and as such need to write /all/ the glue myself. So if there is a problem it can't be hidden from me like a compiler could do (either by
    applying a fix in the high(er) level function call, or simply by not giving access to the malfunctioning DLL function).

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Sat Jun 17 08:01:25 2023
    XPost: alt.windows7.general

    And again doubling the number of lines caused the result become larger,
    not smaller (0xDF58 -> FF6F).

    This morning I realized the cause for that : the value is for the *top* of
    the view, not the total height of the displayed content. When I doubled the files contents the view does not go twice the previous distance, but twice /plus the height of the view itself/.

    IOW, the answer was staring me in the eye. Quite Literally.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)