Re[6]: DHTML edit control for IE 5.5
От: kig Россия  
Дата: 02.07.02 08:19
Оценка: 17 (2)
Здравствуйте Снорк, Вы писали:

С>Буду премного благодарен за любой пример.

С>Я концептуально в фишку въехать не могу.
С>Вот DHTMLED.OCX — обычный OLE Control, я написал тулбар у нему ЖКЧ, и управляю через DECMD_*, спасибо retalik'у за дефайны.
С>Через Get/SetDocHTML управляю, проблему с кириллицей решил так: вместо SetHTML я вызываю LoadDoc, так он ее всасывает без проблем.
С>Если б он ещё не подвисал, зараза...

С>А MSHTML — идея в чём? Тоже OLE Control, но другой? Мне в проекте надо визуализировать/редактировать HTML, а не размещать его на страничках в Вебе.


Да это те же самые яйца, только с боку :) Вот только не "падают". Пока :))

На самом деле, кажется с ишака 5.0 (хотя в MSDN указан ie4.0)


HRESULT IHTMLDocument2::get_designMode(BSTR *p);
HRESULT IHTMLDocument2::put_designMode(BSTR v);


где

On — Document can be edited.
Off | Inherit — Default. Document cannot be edited.

Посредством этого WebBrowser-control (тоже OCX) переводится в режим редактирования. А далее все очень похоже на DHTMLEd. (Может тебе в процессе еще и это пригодится
Подключение к событиям объектной модели DHTML при использовании WebBrowser-control
Автор(ы): Тимофей Чадов
). Для подключения к любым событиям в WebBrowser-control тебе так же может понадобится имплементация IHTMLEditDesigner. Там всего четыре метода. Вот пример (правда на Д), мне надо было изменить поведение при tab и shift-tab, что бы фокус перемещался на другие контролы в Дельфи, а не скакал внутри WebBrowser-control:


function TCSMMSHTMLEdit.TranslateAccelerator(inEvtDispId: Integer; const pIEventObj: IHTMLEventObj): HResult;
begin
  Result := S_FALSE;
  if (inEvtDispId = csmIDEvent_onkeydown) and (pIEventObj.keyCode = 9) and (not pIEventObj.altKey) and (not pIEventObj.ctrlKey) then
  begin
    pIEventObj.cancelBubble := True;
    TCSMCustomWinControl(GetParentForm(Self)).NextFocused(Self, not pIEventObj.shiftKey);
    Result := S_OK;
  end
  else if Assigned(FOnTranslateAccelerator) then
    Result := FOnTranslateAccelerator(inEvtDispId, pIEventObj);
end;


Методом тыка подключать имплементацию этого интерфейса мне пришлось два раза (версия ie6.0.2600.0000). Почему так, не знаю. Отключать симметрично, тоже два раза. Сделано было так:


procedure TCSMMSHTMLEdit.SetDesignMode(Value: Boolean);
var
  ihd: IHTMLDocument2;
  ihes: IHTMLEditServices;
begin
  if (Value or Completed) and (not (csDestroying in ComponentState))then
  begin
    if not Assigned(Document) then AssignDocument;
    ihd := Document as IHTMLDocument2;
    if (Value <> (ihd.designMode = 'On')) then
    begin
      Succeeded((ihd as IServiceProvider).QueryService(SID_SHTMLEDITSERVICES, IID_IHTMLEditServices, ihes));
      if Value then
      begin
        ihd.designMode := 'On';
        Succeeded(ihes.AddDesigner(FEditDesigner));
        ihd := Document as IHTMLDocument2;
        Succeeded((ihd as IServiceProvider).QueryService(SID_SHTMLEDITSERVICES, IID_IHTMLEditServices, ihes));
        ihd.designMode := 'On';
        Succeeded(ihes.AddDesigner(FEditDesigner));
        if (FCSMMSHTMLEditorContainer <> nil) then
          FCSMMSHTMLEditorContainer.Turn(True);
      end
      else
      begin
        ihd.designMode := 'Off';
        Succeeded(ihes.RemoveDesigner(FEditDesigner));
        ihd.designMode := 'Off';
        Succeeded(ihes.RemoveDesigner(FEditDesigner));
        if (FCSMMSHTMLEditorContainer <> nil) then
          FCSMMSHTMLEditorContainer.Turn(False);
      end;
    end;
  end;
end;



Для исполнения команд можно пользовать


HRESULT execCommand(
    BSTR cmdID,
    VARIANT_BOOL showUI,
    VARIANT value,
    VARIANT_BOOL *pfRet
);


примерно таким образом (смена фонта):


procedure TCSMMSHTMLEditorContainer.cmbxFontNamesChange(Sender: TObject);
var
  ihd: IHTMLDocument2;
begin
  ihd := TCSMMSHTMLEdit(Self.Owner).Document as IHTMLDocument2;
  if ihd <> nil then
    ihd.execCommand('FontName', False, TComboBox(Sender).Text);
  Windows.SetFocus(TCSMMSHTMLEdit(Self.Owner).Handle);
end;


Где найти в MSDN cписок всех команд я давал в предыдущей ветке (где retalik говорил). Там же описание MSHTML Editing.

И последнее. Для изменения состояния тулбара (там кнопки вдавить, задисейблить или заенейблить) — надо имплементить IDocHostUIHandler и ловить


HRESULT UpdateUI(VOID);


Вот приметно как было реализовано:


function TCSMMSHTMLEdit.UpdateUI: HRESULT;
var
  i: Integer;
  a: TAction;
  ihd: IHTMLDocument2;
  command: WideString;
begin
  if Assigned(Document) and DesignMode and (FCSMMSHTMLEditorContainer <> nil) then begin
    ihd := Document as IHTMLDocument2;
    if (Modified) then
      FCSMMSHTMLEditorContainer.StatusBar.Panels[0].Text := 'Modified'
    else FCSMMSHTMLEditorContainer.StatusBar.Panels[0].Text := '';
    if (ihd.queryCommandValue('OverWrite')) then
      FCSMMSHTMLEditorContainer.StatusBar.Panels[1].Text := 'Overwrite'
    else FCSMMSHTMLEditorContainer.StatusBar.Panels[1].Text := 'Insert';
    for i := 0 to FCSMMSHTMLEditorContainer.actlsMenu.ActionCount - 1 do begin
      a := TAction(FCSMMSHTMLEditorContainer.actlsMenu.Actions[i]);
      if a.Tag > 0 then begin
        command := TCSMMSHTMLEdit.GetCommandName(a);
        a.Enabled := ihd.queryCommandEnabled(command);
        if (a.Tag = 2) then begin
          if (not ihd.queryCommandIndeterm(command)) then
            a.Checked := ihd.queryCommandState(command);
        end;
      end;
    end;
    if (ihd.queryCommandValue('FontName') <> null) then begin
      FCSMMSHTMLEditorContainer.cmbxFontNames.ItemIndex := FCSMMSHTMLEditorContainer.cmbxFontNames.Items.IndexOf(ihd.queryCommandValue('FontName'));
      FCSMMSHTMLEditorContainer.cmbxFontNames.Enabled := ihd.queryCommandEnabled('FontName');
    end
    else FCSMMSHTMLEditorContainer.cmbxFontNames.ItemIndex := -1;
    if (ihd.queryCommandValue('FontSize') <> null) then begin
      FCSMMSHTMLEditorContainer.cmbxFontSizes.ItemIndex := StrToInt(ihd.queryCommandValue('FontSize')) - 1;
      FCSMMSHTMLEditorContainer.cmbxFontSizes.Enabled := ihd.queryCommandEnabled('FontSize');
    end
    else FCSMMSHTMLEditorContainer.cmbxFontSizes.ItemIndex := -1;
    Result := S_OK;
  end
  else Result := inherited UpdateUI;
end;



Все описано В MSDN (старый, не нетовский):
Platform SDK/Web development/Internet development SDK/MSHTML Editing

Удачи ;)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.