Показать сообщение отдельно
  #12  
Старый 02.03.2017, 12:03
Droltromed Droltromed вне форума
Прохожий
 
Регистрация: 22.02.2017
Сообщения: 9
Версия Delphi: Delphi XE10
Репутация: 10
Хорошо

Цитата:
Вот пример HTML редактора для разборки, у меня правда не пошёл, среда не та
У меня тоже не взлетел, к сожалению. Но выглядит отменно, полноценный редактор на вид, кропотливая работа)

В общем, решение завершил.
Реализовал так:

Эту часть запихнул в ApplicationEvents.OnDeactivate
Код:
var
 SelObj: IHTMLSelectionObject;
 SelRange: IHtmlTxtRange;
begin
 SelObj:= (WebBrowser1.Document as IHTMLDocument2).selection;
 SelRange:= SelObj.CreateRange as IHtmlTxtRange;
 SelRange.execCommand('BackColor', false, '#FFCC00'); //даём цвет выделенной части
end;

И эту часть запихнул в ApplicationEvents.OnMessage:

Код:
var
 SelObj: IHTMLSelectionObject;
 SelRange: IHtmlTxtRange;
begin
 if (Msg.message=WM_LBUTTONDOWN) or (Msg.message=WM_RBUTTONDOWN) then
 begin  
  SelObj:= (Form13.WebBrowser1.Document as IHTMLDocument2).selection;
  SelRange:= SelObj.CreateRange as IHtmlTxtRange;
  SelRange.execCommand('BackColor', false, 'false'); //убираем цвет с выделения
 end;
end;

Как оказалось, OnActivate срабатывает уже после обработки события, через которое получен фокус назад (будь это alt+tab, клик мыши или что-то ещё), поэтому в нём бесполезно ловить выделенный текст: он будет уже потерян после клика мышью по окну браузера. А OnMessage срабатывает как раз перед всеми обработчиками, именно там и ловим нажатие мыши.

Повесил проверку именно левой или правой кнопки мыши, потому что выделение из браузера снять больше нечем. Провёл небольшие тесты: ни одно из событий получения фокуса (кнопки, горячие клавиши) не снимут выделение браузера, кроме левой или правой кнопки мыши и кроме одного события:

- если кликнуть на заголовок окна, то оно не засчитается в OnMessage как клик мышью. Это создало небольшую проблему. Поэтому просто берём и запихиваем в OnActivate то же самое, что и в OnDeactivate, но снимающее цвет:
Код:
var
 SelObj: IHTMLSelectionObject;
 SelRange: IHtmlTxtRange;
begin
 SelObj:= (Form13.WebBrowser1.Document as IHTMLDocument2).selection;
 SelRange:= SelObj.CreateRange as IHtmlTxtRange;
 SelRange.execCommand('BackColor', false, 'false'); //убираем цвет с выделения
end;

В итоге получаем: при снятии фокуса с приложения окрашивается цвет выделенного. При получении фокуса кликом цвет снимается через OnMessage. При получении фокуса кликом по заголовку в дело вступает OnActivate и тоже снимает цвет с выделения.

Есть в этом небольшой минус - множество холостых срабатываний если просто кликать по окну, вызывая OnMessage или когда получаем фокус кликом (срабатывает OnMessage, а следом OnActivate, получая двойной сброс цвета).

Благо предложенный код не создаёт тормоза при выполнении и не вызывает исключений, если у браузера ничего не выделено, но вызывает исключения если в браузере ничего не открыто. Поэтому если бывают случаи держать браузер пустым, то обработку можно просто завернуть в Try Except или проверять наполненность браузера.

В остальном, реализация получилась именно такой, как хотелось и задумывалось. Большое спасибо за предложенный код, Alegun .
Ответить с цитированием