How to change position of caret in MSHTML during mouse click? - c#

I have a MSHTML-based control embedded in an application and the ContentEditable mode is used to edit documents inside it. The body of the HTML document initially contains the following lines:
<div></div>
<div id="signature"></div>
The caret is placed at the beginning of the document, that is inside the first DIV element. Now when user clicks with mouse inside the control in a place below the last line, the caret is moved into the second DIV element, as it's the closest one to the point where the user clicked.
I want to move the pointer to the end of the first DIV on the mouse click. Now I have the code to calculate the intended position of the caret as IMarkupPointer and IDisplayPointer. What I need to know is where to intercept the MSHTML event pipeline to do the actual caret move.
I've written code that implements IHTMLEditDesigner and moves the caret using IHTMLCaret.MoveCaretToPointer to the intended position. The problem is that no matter where I intercept the event (PreHandleEvent, PostHandleEvent or PostEditorEventNotify) the caret position is eventually reverted to the default one on single click (but it is not reverted if I hold the left mouse button pressed for a while or if I click with right mouse button).

Use jscript inside of the HTML that you load into the IE control. If you do not know HTML and jscript very well you will find this task very painful.
See these questions for my experience when I tried do so something like this.
Risk of using contentEditable in
IE
Why is ContentEditable
removing “ID” from div
I also had lots of other problem, including have to write resize logic in jscript to get the HTML editor to size along with the WinForm form and having to pass the default form/coontrol colours into the HTML editor so that it looked write then users changed colour schemes on Windows.
Even better just find a HTML editor and load it into the IE control, you will still have to code with standard window colours etc yourself.
There are also 3rd party winforms HTML editors you can use. If possible I think you should buy in a solution as ContentEditable is a lot harder in real life then it look.
A quick google found.
Writer by Lutz Roeder (of Reflector fame)
NetRix by netrixcomponent
Html Editor by Carl Nolan
HTML viewing and editing component for WinForms apps

Have you tried using a winforms timer with a timeout of 0?
When you get the mouse down event start the timer.
Then the MSHTML control will process the event
You will then go back to the windows message loop
All other messages in the message queue will then be process before the timer
Hopefully by now MSHTML has set the default caret position on single click
You can then move the caret position yourself when the timer fires
Have a look with Spy++ to see what events are being sent between the diffent windows in the MSHTML control to get other ideals. The MSHTML control is like no other winforms control and you have to go back to all the trick you used in the days of C and Win32 programming.

Maybe there are separate events for mouseDown mouseUp and mouseClick.
You intercept mouseClick but default behavior gets executed on mouseUp.

Have you tied setting the "focus" to the first div by finding the dom item for it, and calling the setFocus (or whatever it is called) dom method? The caret should move to where the fosus is.
(There are interfaces that MSHTML expose to find dom items and call methods on them. Sorry I don't recall the details of how to do this)

I believe you need to change the SelectStart property and leave the SelectionLength = 0. That will move the caret to a new position.

Related

Change Cursor when hovering over url RichTextBox

Currently when hovering over a url/link in a RichTextBox (WinForms) the cursor changes to a really low quality cursor without anti aliasing. I would like to use the default windows one, which looks way better, but I couldn't find any solutions... I only found a way to change the general hover cursor, but not when hovering over urls.
Thanks for all replies :)
This seems like a bug between RichTextBox and HiDPI support. The control properly renders text in HiDPI when HiDPI mode is enabled in the WinForms application, but it doesn't have the updated cursor.
Depending on the use case, you might consider using the WebBrowser control or something similar. It appears to support the higher resolution pointer cursor. It would work pretty well for viewing content, but for editing content, it might get a bit rough.
As a gross, hacky workaround, you might be able to add MouseMove event handlers to detect if the mouse is over a hyperlink or not and change the cursor for the whole control manually. This would involve the GetCharIndexFromPosition(Point) method passing in the Point from the MouseMove event args, then looking at the RTF Codes in the string from the Rtf property. If the CharIndex is the non-RTF string, you'd need to use the Text property, then determine if there's a URL there using some sort of Regex.

Make Multiple Controls Use Same Tool Tip Message (c# Client App.)

I would like the same tool tip message (the one entered in the "ToolTip on myControlId" field) to be displayed when the mouse is hovered over an area which contains multiple controls. I tried putting the controls inside a Panel and GroupBox, but it only works when the mouse is in the "white space" area of the Panel/GroupBox, and, of course, does not work when the mouse is on a control within the Panel/GroupBox.
I'm from the web dev world so I'm open to suggestions for a new approach if I'm going about this the wrong way.
In standart windows developmern (WindowsForms) tootltip or tooltip control is associated to a single control. But you can use ToolTip control (see example how: ToolTip: Windows Forms .NET) and assign to all controls that recieve mouseover event.
If you're in WPF, the story becomes easier as you have message routing so usually it's enought to have subscription in one place.
Hope this helps.

Why can't I reliably focus a control in Winforms?

I have a form that consists of various controls on the left and the main body is a browser window that displays a HTML file created by the other controls. After generating a file I am attempting to set the focus onto the browser window so the scroll wheel works.
On every ODD attempt this works, on the EVEN attempts it does not.
There are two code paths (both starting from a button click) that generate output, both come down to:
Browser.Focus();
Browser.DocumentText = RenderAsHTML();
The first button updates a listbox on the left also, the second does not. The odd/even pattern is independent of which button was pressed.
What in the world is going on here?
In trying the response below and then throwing things at it I found something very interesting:
The system believes the window IS focused. Browser.Focused returns true even when it's not accepting scroll wheel messages.
To make it even stranger one test I did involved throwing a messagebox in there showing some variables--and when that box was cleared going back to the screen the scroll wheel worked 100% of the time. Removing ONLY the MessageBox.Show line returned it to the old behavior.
on Winforms c# - Set focus to first child control of TabPage will find a similar question, there the best answer says that you have to put
ActiveControl = yourControlThatReceiveFocus;

How to move to a location in a web browser component?

I have a .NET windows form page and a WebBrowser component inside. I load a page inside the web browser using the Navigate method as in:
webBrowser1.Navigate("http://www.stackoverflow.com");
The pages length is longer than the browsers height, so the vertical scroll bar appears. Now I want to move the scrollbar down to a specific position.
More specifically I want to search for a specific peace of text inside the page, and scroll to that position.
This behavior is implemented in the built-in "Find" function of the browser, but I can't figure out how to call the Find function from within my code, without the Find window appearing.
Although I don't want the Find window to appear, if the text matches are highlighted it is welcome.
You could do it using anchors.
webBrowser1.Navigate("http://www.stackoverflow.com#myAnchor");
and in your html define this:
<a id="myAnchor" />
This is in itself not very flexible, but if you consistently add anchor tags to key structural parts of the html, you can always jump to the section, block, or div that you want.

Putting ModalPopupExtender in a constant location

I've got a series of ModalPopupExtenders that I'm using to implement popup dialogs on an ASP.NET 2.0 page.
When they popup it's fairly easy to specify the location where they appear using the constructor using X and Y coordinates but I'm unsure how to deal with changes of window size which alters where they should be in cartesian space. I need them to appear relative to some other elements on the page.
I've tried hooking into the onresize javascript function in IE but this is broken and fires whenever a div changes size (problematic really given that i have lots of CollapsiblePanelExtenders in the UI.
Anybody ever done this and have any suggestions how i can get this working?
Edit : This code helps no end in capturing the resize event...
http://blog.stchur.com/2006/09/06/the-ie-resize-bug-revisited/
I've figured out how to do this.
I use onClickClick to display the modal popup after figuring out where to put them by getting the x + y coordinates from a known control from the DOM. Upon resize (from http://blog.stchur.com/2006/09/06/the-ie-resize-bug-revisited/) i've decided to just hide the popups
ModalPopupExtender has a property called RepositionMode for exactly this purpose

Categories