Здравствуйте Снорк, Вы писали:
С>Буду премного благодарен за любой пример.
С>Я концептуально в фишку въехать не могу.
С>Вот 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
Удачи ;)