About the "jump to top", yes i think too it's earlier than CNNotify, within the message loop.
CNNotify itself will behave correct. It will receive a twofold LVN_ITEMCHANGED, the first, on the currently selected item, with iItem -1 (for deselection), and a second with iItem 0, and it is not clear, why 0 (might it be orphaned from an earlier initialization of the data structure?).
Even if one tries, purely experimental, to intercept the latter (and for the first call that's not possible), the selection will jump to top. On the one hand, the question appears to be, why this doubled LVN_ITEMCHANGED is sent here (for the regular listview it is not). On the other hand: CNNotify doesn’t play a role here, it may be exited directly at the beginning and nothing changes (jumps to top). It happens earlier, right.
Back to the modification of the patch. I tried it out a couple of times, and my experience is:
the side-effect (= unintended closure of edit box when doing fast and repeatedly a Click / F2 / edit on the same item) in rare cases still did occur, but significantly less often.
And: the very irritating effect, that with F2 the editor does open within another control (tree node), as the listview passed the focus to another control. never did happen again since having applied the patch modification.
So far I was satisfied, but not fully, and asked myself, if it’s possible to intercept the remaining few deviants too. With this little addition they appear to be removed:
// end editing
if (IsEditing And OwnerData) then
if (nm^.iItem = -1) And (FSelectedIdx<>-1) then // Specifically when item outside the editor clicked
if Not ((FFocused <> nil) And FFocused.Selected) then // but prevent known side effect (defocusing at repeated /click/edit with Click on the same item)
if FSelectedIdx <> FFocused.Index then // Eliminate remaining deviations
HideEditor;
The syntax can be more compacted of course, but I kept it as it is for better readability.