Ich arbeite an einem kleinen WYSIWYG HTML Editor. Ich nutze ActiveX und TEvsWebBrowser in Lazarus 1.1/FPC 2.6.1.
und die Möglichkeit den Browser in den Editmodus zu setzen.
EInfach Formatierungen (Fett, Kursiv, Text ausrichten) funktionieren bereits.
Ich wollte vorgegebene Überschriften (Blockformatierung) implementieren. Da die unterschiedlichen Browserversionen,
aber unterschiedliche Namen für die Überschriften verwenden, ist es möglich diese vorher auszulesen.
Die Idee war diese auszulesen und in einer Combobox auswählbar zu machen.
Wie das grundsätzlice funktioniert kann man in der Dokumentation zu mshtml nachlesen (c-style). Es kursieren dazu
eine Menge nachfragen und mögliche Lösungen im Netz für Delphi. Eine von diesen möglichen Lösungen wollte ich
für fpc und lazarus umsetzen und sehen was sie bewirken, bzw. ob sie funktioniert.
Ein erstes grundsätzliches Problem erlaubt mir nicht meine Anwendung zu debuggen. Wenn ich die Testanwendung in
der IDE starte und ich während der Laufzeit auf den Editor klicke, um Eingaben zu machen, dann erhalte ich eine Fehlermeldung
und das Programm bricht ab. Wenn ich allerdings die erstellte Anwendung ausserhalb der IDE starte, dann funktioniert soweit alles.
Ich vermute hier erstmal ein Problem mit der ActiveX oder TEvsWebbroser Implementation, da Lazarus 1.1 ja noch nicht released ist.
Soweit als Vorabbemerkung.
Jetzt zum eigentlichen Problem. Ich kann also meine Anwendung nur ausserhalb der IDE starten und nicht debuggen.
Der Quellcode zum Auslesen der Überschriften lautet:
Code: Alles auswählen
procedure THTMLEditorView.FillStylesCombo;
const
IDM_GETBLOCKFMTS = 2233;
GUID_TriEditCommandGroup: TGUID = '{2582F1C0-084E-11d1-9A0E-006097C9B344}';
CMDSETID_Forms3: TGUID = '{DE4BA900-59CA-11CF-9592-444553540000}';
var
CommandTarget: IOleCommandTarget;
MyHResult: HRESULT;
MyVariant, varRange, oNULL: OleVariant;
Ps: PSafeArray;
Warr: array of WideString;
sCommands: string;
StrCount, I: integer;
Pw: PWideChar;
begin
ONull := Null;
// making the variant a VariantArray
TVariantArg(MyVariant).vt := VT_ARRAY;
//if that doesn't works try @CMDSETID_Forms3 in stead of @GUID_TriEditCommandGroup.
{
TVariantArg(vo).vt := vt_bstr;
TVariantArg(vo).bStrVal := nil;
Hr := CommandTarget.Exec(@CMDSETID_Forms3, IDM_BLOCKFMT,
OLECMDEXECOPT_DONTPROMPTUSER, NullVariant, Va);
}
MyHResult := CommandTarget.Exec(
CMDSETID_Forms3,
IDM_GETBLOCKFMTS,
OLECMDEXECOPT_DONTPROMPTUSER,
ONull,
MyVariant);
(*
if (MyHResult = S_OK) then
begin
//get a pointer to the SafeArray
Ps := TVariantArg(VarRange).pArray;
//Get number of strings in the SafeArray
StrCount := TSAFEARRAYBOUND(Ps^.rgsabound).cElements;
//make room fore all the strings in our WideString array
SetLength(Warr, StrCount);
try
//lock the SafeArray = no risk of memory reallocation during
Inc(Ps^.cLocks);
//copy the SafeArray-Strings to the WideString array
//Ps.pvData points to start of the SafeArrays Data-segment
//Ps.cbElements = size of each record = a PWideChar
CopyMemory(@Warr[0], Ps^.pvData, I * 4 {Ps.cbElements});
finally
Dec(Ps^.cLocks); //unlock the SafeArray
end;
sCommands := '';
//get each string from the WideString array
for I := 0 to StrCount do sCommands := sCommands + Warr[I] + #13#10;
end
else
sCommands := 'GetBlockFmts error';
showInfo(sCommands);
*)
(*
//then the API-call way
if (MyHResult = S_OK) then
begin
//get a pointer to the SafeArray
Ps := TVariantArg(VarRange).pArray;
sCommands := '';
for I := VarArrayLowBound(VarRange, 1) to VarArrayHighBound(VarRange, 1) do
begin
//get each string from the SafeArray
SafeArrayGetElement(Ps, PLongInt(I), Pw);
sCommands := sCommands + Pw + #13#10;
end;
end
else
sCommands := 'GetBlockFmts error';
showInfo(sCommands);
//----------------------------------------------------------
*)
end;
Problematischer Code, der zur Fehlermeldung führt:
Code: Alles auswählen
MyHResult := CommandTarget.Exec(
CMDSETID_Forms3,
IDM_GETBLOCKFMTS,
OLECMDEXECOPT_DONTPROMPTUSER,
ONull,
MyVariant);
Das Ergebnis ist eine "Access violation".
Evt. liest jemand ja bereits aus dem Quellcode meinen Fehler, bzw.
hat bereits mal jemand mit CommandTarget gearbeitet oder
könnte mit einen Fehler in der eigentlichen Implementation bestätigten.
Vielen Dank
Antonio