Интерактивные ссылки в элементе управления WebBrowser в режиме редактирования

Я использую элемент управления Windows.Forms WebBrowser в режиме редактирования, чтобы разрешить редактирование HTML в нашем приложении (формы Windows .net 3.5 C #). Проблема в том, что в режиме редактирования ссылки в html не доступны для кликов (т.е. при наведении курсора на них не отображается курсор мыши, а щелчок по ним просто вставляет курсор в это место, а не перемещается по этой ссылке).

Я понимаю, что это сделано намеренно, но можно ли включить режим редактирования, сохранив при этом ссылки в рабочем состоянии? Мы хотим, чтобы пользователь перемещался по набору локальных HTML-страниц, в то же время имея возможность редактировать контент.

Я устанавливаю такой режим редактирования, если он что-то меняет:

webBrowser.Document.ExecCommand("EditMode", false, null);

person Gareth    schedule 11.08.2009    source источник
comment
Что произойдет, если вы нажмете Ctrl + щелчок?   -  person hannson    schedule 14.08.2009


Ответы (2)


Вот небольшое приложение WinForm, которое, кажется, работает. При установке режима редактирования он записывает все позиции ссылок всех тегов A, а затем проверяет положение курсора мыши. Я не уверен, что OffsetRectangle дает правильные значения, если есть фреймы или вложение тегов, но образец html в приложении работает.

При необходимости его можно изменить для захвата onclick и т. Д. Из других тегов.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private readonly Dictionary<Rectangle, Uri> _links = new Dictionary<Rectangle, Uri>();
        private readonly Regex _reLink = new Regex("href=['\"](?<link>.*?)['\"]");

        private const string _html =
            "<html><body><br><div style='top:20px;left:50px;border:solid 1px red'><a href='http://www.cnn.com'>CNN</a></div><br><font size='14'>xx</font><a href='http://stackoverflow.com'>stackoverflow</a></body></html>";

        private bool _isEditMode;

        public Form1()
        {
            InitializeComponent();
            webBrowser1.DocumentText = _html;
            webBrowser1.Document.Click += Document_Click;
            webBrowser1.Document.MouseMove += Document_MouseMove;
        }

        private void Document_MouseMove(object sender, HtmlElementEventArgs e)
        {
            if (!_isEditMode) return;
            ChangeCursorIfOverLink(e);
        }

        private void ChangeCursorIfOverLink(HtmlElementEventArgs e)
        {
            foreach (KeyValuePair<Rectangle, Uri> link in _links)
            {
                if (CursorWithinControl(e, link.Key))
                {
                    if (Cursor.Current != Cursors.Hand)
                        Cursor.Current = Cursors.Hand;
                    return;
                }
            }
            Cursor.Current = Cursors.Default;
        }

        private void Document_Click(object sender, HtmlElementEventArgs e)
        {
            NavigateLinkInEditMode(e);
        }

        private void NavigateLinkInEditMode(HtmlElementEventArgs e)
        {
            if (_isEditMode)
            {
                foreach (KeyValuePair<Rectangle, Uri> link in _links)
                {
                    if (CursorWithinControl(e, link.Key))
                    {
                        webBrowser1.Navigate(link.Value);
                        return;
                    }
                }
            }
        }

        private bool CursorWithinControl(HtmlElementEventArgs e, Rectangle rectangle)
        {
            return e.MousePosition.X >= rectangle.Left
                   && e.MousePosition.X <= rectangle.Left + rectangle.Width
                   && e.MousePosition.Y >= rectangle.Top
                   && e.MousePosition.Y <= rectangle.Top + rectangle.Height;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            RecordLinkPositions();
            webBrowser1.Document.ExecCommand("EditMode", false, null);
            webBrowser1.DocumentText = _html;
            _isEditMode = true;
        }

        private void RecordLinkPositions()
        {
            foreach (HtmlElement element in webBrowser1.Document.All)
            {
                if (element.TagName == "A")
                {
                    string url = _reLink.Match(element.OuterHtml).Groups["link"].Value;
                    _links.Add(element.OffsetRectangle, new Uri(url));
                }
            }
        }
    }
}
person Mikael Svenson    schedule 16.08.2009
comment
Потрясающий! Спасибо, это работает. Я также обнаружил, что в документе есть метод под названием GetElementFromPoint, который позволяет мне избавиться от необходимости хранить позиции элементов. Основная идея здесь заключается в том, что вы устанавливаете Cursor.Current, а не свойство Cursor элемента управления веб-браузера, которое у меня вызывало сбой. - person Gareth; 17.08.2009
comment
Во сне я подумал о проблеме, о которой нужно подумать. Когда пользователь действительно редактирует, OffsetRectangles перемещается. Это можно исправить, используя два веб-элемента управления, один из которых скрыт. Каждый раз, когда нажатие клавиши вводится в EditMode, вы копируете содержимое в скрытый и воссоздаете список смещения. Дайте мне знать, если вам понадобится образец этого. - person Mikael Svenson; 17.08.2009

Я бы проверял, когда пользователь наводит курсор на ссылку, и, при необходимости, показывал что-то в строке состояния. Разрешите пользователю CTRL + щелкнуть ссылку, чтобы открыть ее.

РЕДАКТИРОВАТЬ: Это может пригодиться: http://www.codeproject.com/KB/mobile/browsermouseevents.aspx?msg=2732899.

person AndrewVos    schedule 14.08.2009
comment
Спасибо, Эндрю, да, я уже поигрался с этим, и он заработал, найдя элемент под курсором мыши. Проблема в том, что пользователям нужен курсор в виде руки, а установка свойства курсора в веб-браузере не работает. Установка курсора родительского элемента управления (панели) приводит к тому, что что-то идет не так, и все приложение падает. В идеале я бы хотел что-то, что поддерживается в элементе управления браузером, но если это лучший способ, это то, что должно произойти :) - person Gareth; 14.08.2009