Strange behaviour of ScintillaNET and WeifenLuo.WinFormsUI.Docking #85
Comments
In some rare cases I believe it is possible for Windows Forms to destroy a control's handle and recreate it. My guess is that's what is happening. I'm pretty sure we did a fix for this issue in ScintillaNET v2... I just need to go back through the code to find it. If you would like to confirm that this is the issue, try hooking the |
I can handle both HandleDestroyed and HandleCreated and re-set the text after it is re-created. Is that the fix? Or you are going to do in a better way properly remove the root cause of it? |
I just noticed, not only the Text will be deleted, but also, all the margins and other properties (Lexer) are gone as well. Hope that helps. |
Just an update, the workaround is what I described, to listen on those events (HandleDestroyed , HandleCreated) and reinitialise the entire component again. Hope this will be fixed in future. |
There is a another workaround on that. I had the same error when I reconstructed the window on startup from the XML file. To circumvent the error, you can put all windows involving scintilla controls in a kind of queue when you would normally load them in the reconstruction-call-back-function. Afterwards, catch the Shown event of the main form and process the queue, i.e. open the windows. Not beautiful, but it works (only at start-up, not when moving windows). |
So I've been studying this issue quite a bit and here is a brain dump of what I've found. As I suspected, there are times when Windows Forms will force a handle change. See:
This is an issue for ScintillaNET (currently) because everything is associated with that handle. If the handle changes -- no more Scintilla. This issue was also identified and fixed in previous version of ScintillaNET and detailed here: The approach used in this fix is to swallow the WM_DESTROY Window message and instead change the control parent so that the handle doesn't actually change. To actually destroy the handle, some additional code has been added to the Another approach would be to do something similar to what @Aghlara has done and to save the state of the control when the handle is destroyed and then restore the state again when the handle is created. We could do this internally and seamlessly to ScintillaNET users. The drawback of this approach is that it is a bit more expensive. It requires copying out the document text and then restoring it again but that's probably not a significant hit. Finally, we could leave this as an issue for ScintillaNET users... which I know would be an unpopular choice... but this issue is very specific to using ScintillaNET in an MDI configuration. When the visibility of an MDI window changes (or when moving an MDI window using the WeifenLuo library) the handle gets destroyed and created again. To prevent this from affecting the Scintilla control it should be as easy as removing the control from the MDI window and then adding it back again after the move/visible change. If anyone has any opinions about this, please feel free to speak up. I'm going to let this churn a bit in my head and then make a decision. |
I think the first option would be the best to do, even if it isn't performed in the greatest of ways. The option of reconfiguring the entire control sounds a little to expensive, and if it were to be the method used, should at least be done internally. That is just my opinion however. |
Is it possible to make it configurable? I see it as new public property |
I think re-initializing the control is safer although it feels expensive. The reason is safer is because of the fact that control handle is being destroyed by underlaying components, so swallowing the WM_DESTROY message and ignoring it may have some unknown side effects in the future. I think this should be just handled by the ScintillaNet users. |
I tried following these instructions which fix it in v2.x: However what is the equivalent of Scintilla.WndProc in v3.x? Also based on this, and from what I'm reading, the Dispose() method would have to be modified, but am not sure what to change. Would I have to reset the container controls handle? (https://scintillanet.codeplex.com/workitem/11811) Thanks. |
The details of the actual fix done in v2 are in these changesets: https://scintillanet.codeplex.com/SourceControl/changeset/34532 |
The fix from v2 works, thanks. Do you think this is something we could implement? |
I like the suggestion that the fix be something developers can opt into. I'm working on it but it will take some time with my other priorities. |
This getting fixed anytime soon ? :/ |
Sorry, I haven't forgotten. Been busy with my day job; but I confess that there is a part of me that is just ignoring it because I don't want to deal with it. :) I'm just not please with any of the options. In the meantime you are using one of the workaround, no? |
Please fix it :) |
I ran into the same problem and ended up doing what Aghlara recommended. However, for some reason my HandleCreated is not getting called after I dock the MDI window. As a result, I check if my HandleDestroyed is getting called as a result of FormClose or Dock and then recreate my Scintilla control if necessary. A question for Jacob, will this logic (HandleDestroyed/HandleCreated) have to be undone when you fix this code? |
Yes, i've fixed it. |
@Krischkros I am at a loss - I don't see an "AutoHide" property in Scinitalla. I see a AutoCAutoHide but I am sure that is different. I am using version 3.5.1 Are you saying you have modified the code on your end? |
Thank you everyone for being patient on this. I just wanted to make sure I got this right, or if I didn't get it right, that I did it in a way which wouldn't impact users who don't have this issue. Commit d632e6e adds a new method called To enable the workaround, simply call
Internally I'm using the same fix that we did for ScintillaNET v2, but I've also addressed a memory leak that was present in the v2 fix. Please report any issues you find. |
I have been waiting for this for a long time, thank you. No more modifying the source every time an update is released 👍 |
Can you give me steps to reproduce? I didn't experience any AccessViolationExceptions in my testing. |
Create a dockpanel instance (from http://dockpanelsuite.com/), create a scintillaNET instance and load files into the editor.
etc.. so, open 10-30 files and close them quickly. i hope i can help |
I see what's going on... you have a race condition in your application. If you want to load files on a background thread using the background loader you need to be mindful of when that operation completes. What I think is happening is that you are disposing of the Scintilla control before the load operation completes and sets the document. Said another way, your file doesn't finish loading until after the control is already disposed. Once the Scintilla control is disposed, trying to set the document will attempt to read/write a memory location which is no longer valid and the result is an AccessViolationException. I would recommend using background threads (async/await) only if you are acutely aware of the challenges in synchronizing threads. Oh, and be sure you are calling the new |
I'm going to close this issue for now because the fix was included in the 3.5.4 release. If we need to open it back up again I can. |
Works as charm. Thank you. |
Hi,
Has anyone integrated Scintilla with WeifenLuo dock control? When I drag a form and change its location to left/right from being a document the Sceintilla either:
Gets Access Violation Exception:
at ScintillaNET.Scintilla.DirectMessage(IntPtr sciPtr, Int32 msg, IntPtr wParam, IntPtr lParam)
at ScintillaNET.Scintilla.DirectMessage(Int32 msg, IntPtr wParam, IntPtr lParam)
at ScintillaNET.Scintilla.DirectMessage(Int32 msg, IntPtr wParam)
at ScintillaNET.Scintilla.OnHandleCreated(EventArgs e)
at System.Windows.Forms.Control.WmCreate(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at ScintillaNET.Scintilla.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
TextChanged is raise and text is deleted with no proper call stack!
I even disabled all the logic for folding and numbering... I thought might be related to that, but still the same issue.
Can anyone help me here?
Before moving:
After moving is done:
As you can see the right side is the form that in previous picture had contents.
Regards.
The text was updated successfully, but these errors were encountered: