{*******************************************************************} { } { ExpressWeb Framework by Developer Express } { Designer Module } { } { Copyright (c) 2000-2008 Developer Express Inc. } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE } { SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS } { LICENSED TO DISTRIBUTE THE EXPRESSWEB FRAMEWORK AND ALL } { ACCOMPANYING VCL CLASSES AS PART OF AN EXECUTABLE WEB } { APPLICATION ONLY. } { } { THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED } { FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE } { COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE } { AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT } { AND PERMISSION FROM DEVELOPER EXPRESS INC. } { } { CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {*******************************************************************} unit cxWebHTMLBehaviors; interface uses Classes, Windows, Contnrs, Graphics, MSHTML_TLB, cxWebHTMLEdIntf, cxWebHTMLEvents; type TcxCustomHTMLBehavior = class; TcxHTMLBehaviorClass = class of TcxCustomHTMLBehavior; TcxHTMLNamespace = class(TInterfacedObject, IcxHTMLNamespace, IElementNamespaceFactory, IElementNamespaceFactoryCallback, IElementBehaviorFactory) private FName: string; FTags: TStringList; FElementInfo: IcxHTMLElementInfo; FEditorInfo: IcxHTMLEditorInfo; FBehaviors: IInterfaceList; protected { IcxHTMLNamespace } procedure AddTags(ATags: array of string); function GetBehaviors: IInterfaceList; function GetEditorInfo: IcxHTMLEditorInfo; function GetElementBehavior(AElement: IHTMLElement): IcxHTMLBehavior; function GetElementInfo: IcxHTMLElementInfo; function GetName: string; { IElementNamespaceFactory } function create(const pNamespace: IElementNamespace): HResult; stdcall; { IElementNamespaceFactoryCallback } function Resolve(const bstrNamespace: WideString; const bstrTagName: WideString; const bstrAttrs: WideString; const pNamespace: IElementNamespace): HResult; stdcall; { IElementBehaviorFactory } function FindBehavior(const bstrBehavior: WideString; const bstrBehaviorUrl: WideString; const pSite: IElementBehaviorSite; out ppBehavior: IElementBehavior): HResult; stdcall; public constructor CreateObj(const AName: string; const AEditor: IUnknown); destructor Destroy; override; end; TcxCustomHTMLBehavior = class(TInterfacedObject, IElementBehavior, IHTMLPainter, IHTMLPainterEventInfo, IcxHTMLBehavior) private FNamespace: TcxHTMLNamespace; FBehaviorSite: IElementBehaviorSite; FBehaviorSiteOM: IElementBehaviorSiteOM; FPaintSite: IHTMLPaintSite; FCanSetCursor: Boolean; FCanSetTarget: Boolean; FCookie: Integer; FElement: IHTMLElement; FEventSink: TcxCustomHTMLEventSink; FEventSinkIntf: IcxEventSink; protected function CreateEventSink: TcxCustomHTMLEventSink; class function EventSinkClass: TcxHTMLEventSinkClass; virtual; function GetEventSink: TcxCustomHTMLEventSink; overload; virtual; function HasEventSink: Boolean; virtual; { IElementBehavior } function Init(const pBehaviorSite: IElementBehaviorSite): HResult; stdcall; function Notify(lEvent: Integer; var pVar: OleVariant): HResult; stdcall; function Detach: HResult; stdcall; { IHTMLPainter } function Draw(rcBounds: tagRECT; rcUpdate: tagRECT; lDrawFlags: Integer; hdc: HDC; var pvDrawObject: Pointer): HResult; stdcall; function onresize(size: tagSIZE): HResult; stdcall; function GetPainterInfo(out pInfo: _HTML_PAINTER_INFO): HResult; stdcall; function HitTestPoint(pt: tagPOINT; out pbHit: Integer; out plPartID: Integer): HResult; stdcall; { IHTMLPainterEventInfo } function GetEventInfoFlags(out plEventInfoFlags: Integer): HResult; stdcall; function GetEventTarget(var ppElement: IHTMLElement): HResult; stdcall; function SetCursor(lPartID: Integer): HResult; stdcall; function StringFromPartID(lPartID: Integer; out pbstrPart: WideString): HResult; stdcall; { IcxHTMLBehavior } function GetPaintSite: IHTMLPaintSite; function GetElement: IHTMLElement; function GetNamespace: IcxHTMLNamespace; // Element Behavior procedure InitializeBehavior; virtual; procedure FinalizeBehavior; virtual; // Painter function HitTestAt(X, Y: Integer; out APartID: Integer): Boolean; virtual; procedure DrawElement(ADC: HDC; ABounds: TRect); virtual; procedure OnResizeElement(ANewSize: TPoint); virtual; function TransparentDraw: Boolean; virtual; function GetZOrder: Integer; virtual; function GetExpandRect: TRect; virtual; // Painter Event Info function GetCursor(const APartID: Integer): HCURSOR; virtual; function GetTarget: IHTMLElement; virtual; function GetStringFromPartID(const APartID: Integer): string; virtual; public constructor Create(ANamespace: TcxHTMLNamespace); virtual; property Element: IHTMLElement read GetElement; property EventSink: TcxCustomHTMLEventSink read GetEventSink; property EventSinkIntf: IcxEventSink read FEventSinkIntf; property PaintSite: IHTMLPaintSite read FPaintSite; property CanSetCursor: Boolean read FCanSetCursor write FCanSetCursor; property CanSetTarget: Boolean read FCanSetTarget write FCanSetTarget; property Cookie: Integer read FCookie write FCookie; property Namespace: TcxHTMLNamespace read FNamespace; end; TcxHTMLDrawGrid = class(TcxCustomHTMLBehavior) private FGridBmp: TBitmap; function ShowGrid: Boolean; function GridXSize: Integer; function GridYSize: Integer; protected function GetEventSink: TcxCustomHTMLEventSink; override; procedure DrawElement(ADC: HDC; ABounds: TRect); override; function GetZOrder: Integer; override; public destructor Destroy; override; end; TcxHTMLSelectRegion = class(TcxCustomHTMLBehavior, IcxHTMLSelectionBehavior) protected class function EventSinkClass: TcxHTMLEventSinkClass; override; function GetEventSink: TcxHTMLSelectRegionSink; reintroduce; overload; procedure DrawElement(ADC: HDC; ABounds: TRect); override; function GetZOrder: Integer; override; function HitTestAt(X, Y: Integer; out APartID: Integer): Boolean; override; function GetCursor(const APartID: Integer): HCURSOR; override; { IcxHTMLSelectionBehavior } procedure SetOnRegionSelected(AHandler: TcxHTMLRegionSelectEvent); public constructor Create(ANamespace: TcxHTMLNamespace); override; property EventSink: TcxHTMLSelectRegionSink read GetEventSink; end; TcxHTMLEWFCtrlBehavior = class(TcxCustomHTMLBehavior, IcxHTMLBehaviorViewLink) private FViewLinkEventSinkIntf: IcxEventSink; FViewLinkEventSink: TcxHTMLDocEventSink; FViewLinkInitialized: Boolean; function GetElementDef: IHTMLElementDefaults; protected class function EventSinkClass: TcxHTMLEventSinkClass; override; procedure DrawElement(ADC: HDC; ABounds: TRect); override; function GetCursor(const APartID: Integer): HCURSOR; override; function GetZOrder: Integer; override; function HitTestAt(X, Y: Integer; out APartID: Integer): Boolean; override; function GetExpandRect: TRect; override; procedure InitializeBehavior; override; procedure FinalizeBehavior; override; procedure OnResizeElement(ANewSize: TPoint); override; procedure ViewLinkStateChange(const AEventObject: IHTMLEventObj); procedure SetViewLinkContent(const AContent, ACSSContent: string); { IcxHTMLBehaviorViewLink } function GetViewLinkDoc: IHTMLDocument2; procedure UpdateContent; property ElementDef: IHTMLElementDefaults read GetElementDef; public constructor Create(ANamespace: TcxHTMLNamespace); override; end; TcxHTMLEWFCntnrBehavior = class(TcxCustomHTMLBehavior) protected function GetEventSink: TcxCustomHTMLEventSink; override; procedure DrawElement(ADC: HDC; ABounds: TRect); override; function GetZOrder: Integer; override; function GetExpandRect: TRect; override; procedure InitializeBehavior; override; end; implementation uses ActiveX, ComObj, SysUtils, Variants, URLMon; var EWFMarkIcon: HICON; BackgroundBrush: HBrush; BorderBrush: HBrush; const EWFMarkIconSize: TSize = (cx: 26; cy:11); // TODO: get icon size instead const { TcxHTMLNamespace } constructor TcxHTMLNamespace.CreateObj(const AName: string; const AEditor: IUnknown); begin FName := AName; Supports(AEditor, IcxHTMLElementInfo, FElementInfo); Supports(AEditor, IcxHTMLEditorInfo, FEditorInfo); FBehaviors := TInterfaceList.Create; FTags := TStringList.Create; FTags.Sorted := True; FTags.Duplicates := dupIgnore; end; destructor TcxHTMLNamespace.Destroy; begin FTags.Free; FBehaviors.Clear; inherited; end; procedure TcxHTMLNamespace.AddTags(ATags: array of string); var I: Integer; begin for I := Low(ATags) to High(ATags) do FTags.Add(ATags[I]); end; function TcxHTMLNamespace.GetEditorInfo: IcxHTMLEditorInfo; begin Result := FEditorInfo; end; function TcxHTMLNamespace.GetElementBehavior(AElement: IHTMLElement): IcxHTMLBehavior; var I: Integer; begin if AElement <> nil then for I := 0 to FBehaviors.Count - 1 do begin Result := FBehaviors[I] as IcxHTMLBehavior; if (Result.Element <> nil) and (Result.Element.sourceIndex = AElement.sourceIndex) then Exit; end; Result := nil; end; function TcxHTMLNamespace.GetElementInfo: IcxHTMLElementInfo; begin Result := FElementInfo; end; function TcxHTMLNamespace.GetBehaviors: IInterfaceList; begin Result := FBehaviors; end; function TcxHTMLNamespace.GetName: string; begin Result := FName; end; function TcxHTMLNamespace.create( const pNamespace: IElementNamespace): HResult; var I: Integer; begin for I := 0 to FTags.Count - 1 do pNamespace.AddTag(FTags[I], 0); {Creates a normal element behavior} Result := S_OK; end; function TcxHTMLNamespace.Resolve(const bstrNamespace: WideString; const bstrTagName: WideString; const bstrAttrs: WideString; const pNamespace: IElementNamespace): HResult; begin { write code here to resolve unknown tags while HTML is parsed} Result := S_OK; end; function TcxHTMLNamespace.FindBehavior(const bstrBehavior, bstrBehaviorUrl: WideString; const pSite: IElementBehaviorSite; out ppBehavior: IElementBehavior): HResult; var Element: IHTMLElement; begin pSite.GetElement(Element); if Supports(Element, IHTMLBodyElement) then //TODO: move to separate namespace begin if SameText(bstrBehaviorUrl, 'grid') then ppBehavior := TcxHTMLDrawGrid.Create(Self); if SameText(bstrBehaviorUrl, 'select') then ppBehavior := TcxHTMLSelectRegion.Create(Self); end else if GetElementInfo.CanHaveBehavior(Element) then if GetElementInfo.IsElementContainer(Element) then ppBehavior := TcxHTMLEWFCntnrBehavior.Create(Self) else ppBehavior := TcxHTMLEWFCtrlBehavior.Create(Self); Result := S_OK; end; { TcxCustomHTMLBehavior } constructor TcxCustomHTMLBehavior.Create(ANamespace: TcxHTMLNamespace); begin FNamespace := ANamespace; FCanSetCursor := False; FCanSetTarget := False; FEventSink := nil; FEventSinkIntf := nil; end; function TcxCustomHTMLBehavior.Init( const pBehaviorSite: IElementBehaviorSite): HResult; var hr: HRESULT; begin if pBehaviorSite <> nil then begin FBehaviorSite := pBehaviorSite; hr := FBehaviorSite.QueryInterface(IElementBehaviorSiteOM, FBehaviorSiteOM); OleCheck(hr); hr := FBehaviorSite.QueryInterface(IHTMLPaintSite, FPaintSite); OleCheck(hr); if FNamespace <> nil then FNamespace.GetBehaviors.Add(Self); Result := S_OK; end else Result := E_POINTER; end; function TcxCustomHTMLBehavior.Notify(lEvent: Integer; var pVar: OleVariant): HResult; var hr: HRESULT; Node: IHTMLDOMNode; W: WideString; begin case lEvent of BEHAVIOREVENT_CONTENTREADY: begin hr := FBehaviorSite.GetElement(FElement); OleCheck(hr); FElement.QueryInterface(IHTMLDOMNode, Node); W := Node.nodeName; if HasEventSink then EventSinkIntf.Connect(FElement); InitializeBehavior; end; end; Result := S_OK; end; function TcxCustomHTMLBehavior.Detach: HResult; begin FinalizeBehavior; FPaintSite := nil; FBehaviorSiteOM := nil; FBehaviorSite := nil; FElement := nil; if EventSinkIntf <> nil then EventSinkIntf.Disconnect; FEventSinkIntf := nil; FEventSink := nil; if FNamespace <> nil then FNamespace.GetBehaviors.Remove(Self); Result := S_OK; end; function TcxCustomHTMLBehavior.Draw(rcBounds, rcUpdate: tagRECT; lDrawFlags: Integer; hdc: HDC; var pvDrawObject: Pointer): HResult; var Bounds: TRect; begin Bounds.Left := rcBounds.left; Bounds.Top := rcBounds.top; Bounds.Right := rcBounds.right; Bounds.Bottom := rcBounds.bottom; DrawElement(hdc, Bounds); Result := S_OK; end; function TcxCustomHTMLBehavior.onresize(size: tagSIZE): HResult; var NewSize: TPoint; begin NewSize.X := size.cx; NewSize.Y := size.cy; OnResizeElement(NewSize); Result := S_OK; end; function TcxCustomHTMLBehavior.GetPainterInfo( out pInfo: _HTML_PAINTER_INFO): HResult; var ExRect: TRect; begin if @pInfo <> nil then begin if TransparentDraw then pInfo.lFlags := HTMLPAINTER_TRANSPARENT else pInfo.lFlags := HTMLPAINTER_OPAQUE; pInfo.lFlags := pInfo.lFlags or HTMLPAINTER_HITTEST; pInfo.lZOrder := GetZOrder; FillMemory(@pInfo.iidDrawObject, SizeOf(TGUID), 0); ExRect := GetExpandRect; pInfo.rcExpand.left := ExRect.Left; pInfo.rcExpand.top := ExRect.Top; pInfo.rcExpand.right := ExRect.Right; pInfo.rcExpand.bottom := ExRect.Bottom; Result := S_OK; end else Result := E_POINTER; end; function TcxCustomHTMLBehavior.HitTestPoint(pt: tagPOINT; out pbHit, plPartID: Integer): HResult; var PartID: Integer; Hit: Boolean; begin Hit := HitTestAt(pt.x, pt.y, PartID); if @pbHit <> nil then pbHit := Integer(Hit); if @plPartID <> nil then plPartID := PartID; Result := S_OK; end; procedure TcxCustomHTMLBehavior.InitializeBehavior; begin end; procedure TcxCustomHTMLBehavior.FinalizeBehavior; begin end; procedure TcxCustomHTMLBehavior.DrawElement(ADC: HDC; ABounds: TRect); begin end; procedure TcxCustomHTMLBehavior.OnResizeElement(ANewSize: TPoint); begin end; function TcxCustomHTMLBehavior.TransparentDraw: Boolean; begin Result := True; end; function TcxCustomHTMLBehavior.GetZOrder: Integer; begin Result := HTMLPAINT_ZORDER_NONE; end; function TcxCustomHTMLBehavior.GetExpandRect: TRect; begin FillMemory(@Result, SizeOf(TRect), 0); end; function TcxCustomHTMLBehavior.GetEventInfoFlags( out plEventInfoFlags: Integer): HResult; begin Result := S_OK; if @plEventInfoFlags = nil then Exit; plEventInfoFlags := 0; if CanSetCursor then plEventInfoFlags := plEventInfoFlags or HTMLPAINT_EVENT_SETCURSOR; if CanSetTarget then plEventInfoFlags := plEventInfoFlags or HTMLPAINT_EVENT_TARGET; end; function TcxCustomHTMLBehavior.GetEventTarget( var ppElement: IHTMLElement): HResult; begin if @ppElement <> nil then ppElement := GetTarget; Result := S_OK; end; function TcxCustomHTMLBehavior.SetCursor(lPartID: Integer): HResult; begin Windows.SetCursor(GetCursor(lPartID)); Result := S_OK; end; function TcxCustomHTMLBehavior.StringFromPartID(lPartID: Integer; out pbstrPart: WideString): HResult; var Part: WideString; begin Part := GetStringFromPartID(lPartID); if @pbstrPart <> nil then pbstrPart := Part; Result := S_OK; end; function TcxCustomHTMLBehavior.HitTestAt(X, Y: Integer; out APartID: Integer): Boolean; begin APartID := -1; Result := False; end; function TcxCustomHTMLBehavior.GetStringFromPartID( const APartID: Integer): string; begin Result := ''; end; function TcxCustomHTMLBehavior.GetCursor(const APartID: Integer): HCURSOR; begin Result := 0; end; function TcxCustomHTMLBehavior.GetTarget: IHTMLElement; begin Result := nil; end; function TcxCustomHTMLBehavior.CreateEventSink: TcxCustomHTMLEventSink; begin Result := EventSinkClass.Create(Self); FEventSinkIntf := Result; end; function TcxCustomHTMLBehavior.HasEventSink: Boolean; begin Result := EventSink <> nil; end; class function TcxCustomHTMLBehavior.EventSinkClass: TcxHTMLEventSinkClass; begin Result := TcxCustomHTMLEventSink; end; function TcxCustomHTMLBehavior.GetEventSink: TcxCustomHTMLEventSink; begin if FEventSink = nil then FEventSink := CreateEventSink; Result := FEventSink; end; function TcxCustomHTMLBehavior.GetPaintSite: IHTMLPaintSite; begin Result := FPaintSite; end; function TcxCustomHTMLBehavior.GetElement: IHTMLElement; begin Result := FElement; end; function TcxCustomHTMLBehavior.GetNamespace: IcxHTMLNamespace; begin Result := FNamespace as IcxHTMLNamespace; end; { TcxHTMLDrawGrid } procedure TcxHTMLDrawGrid.DrawElement(ADC: HDC; ABounds: TRect); var X, Y: Integer; AGridYSize, AGridXSize: Integer; Color: Cardinal; ClientRect: TRect; begin inherited; if Element = nil then Exit; AGridYSize := GridYSize; AGridXSize := GridXSize; if ShowGrid then begin ClientRect := ABounds; Y := ClientRect.Top + AGridYSize; while Y < ClientRect.Bottom do begin X := ClientRect.Left + AGridXSize; while X < ClientRect.Right do begin Color := 0; //TODO: invert background SetPixel(ADC, X, Y, Color); Inc(X, AGridXSize); end; Inc(Y, AGridYSize); end; end; end; function TcxHTMLDrawGrid.GetZOrder: Integer; begin Result := HTMLPAINT_ZORDER_BELOW_FLOW; // Result := HTMLPAINT_ZORDER_BELOW_CONTENT; end; function TcxHTMLDrawGrid.GridXSize: Integer; begin if (Namespace <> nil) and (Namespace.GetEditorInfo <> nil) then Result := Namespace.GetEditorInfo.GridXSize else Result := 0; end; function TcxHTMLDrawGrid.GridYSize: Integer; begin if (Namespace <> nil) and (Namespace.GetEditorInfo <> nil) then Result := Namespace.GetEditorInfo.GridYSize else Result := 0; end; function TcxHTMLDrawGrid.ShowGrid: Boolean; begin if (Namespace <> nil) and (Namespace.GetEditorInfo <> nil) then Result := Namespace.GetEditorInfo.ShowGrid and (Namespace.GetElementInfo.ContainerLayout(Element) = hclGrid) else Result := False; end; function TcxHTMLDrawGrid.GetEventSink: TcxCustomHTMLEventSink; begin Result := nil; end; destructor TcxHTMLDrawGrid.Destroy; begin if (FGridBmp <> nil) then begin FGridBmp.Free; FGridBmp := nil; end; inherited Destroy; end; { TcxHTMLSelectRegion } constructor TcxHTMLSelectRegion.Create(ANamespace: TcxHTMLNamespace); begin inherited Create(ANamespace); CanSetCursor := True; end; class function TcxHTMLSelectRegion.EventSinkClass: TcxHTMLEventSinkClass; begin Result := TcxHTMLSelectRegionSink; end; procedure TcxHTMLSelectRegion.DrawElement(ADC: HDC; ABounds: TRect); var SelectRect: TRect; TmpRgn, SelectRgn: HRGN; begin inherited; if HasEventSink and (EventSink.State = hssSelecting) then begin SelectRect := EventSink.NormalSelectRect; OffsetRect(SelectRect, ABounds.Left, ABounds.Top); SelectRgn := CreateRectRgnIndirect(SelectRect); InflateRect(SelectRect, -1, -1); if Namespace.GetEditorInfo.IsToolSelected then InflateRect(SelectRect, -1, -1); TmpRgn := CreateRectRgnIndirect(SelectRect); CombineRgn(SelectRgn, SelectRgn, TmpRgn, RGN_XOR); InvertRgn(ADC, SelectRgn); DeleteObject(TmpRgn); DeleteObject(SelectRgn); end; end; function TcxHTMLSelectRegion.GetCursor(const APartID: Integer): HCURSOR; begin Result := LoadCursor(0, IDC_ARROW); end; function TcxHTMLSelectRegion.GetEventSink: TcxHTMLSelectRegionSink; begin Result := inherited GetEventSink as TcxHTMLSelectRegionSink; end; function TcxHTMLSelectRegion.GetZOrder: Integer; begin if HasEventSink and (EventSink.State <> hssNone) then Result := HTMLPAINT_ZORDER_WINDOW_TOP else Result := HTMLPAINT_ZORDER_BELOW_FLOW; // Result := HTMLPAINT_ZORDER_BELOW_CONTENT; end; function TcxHTMLSelectRegion.HitTestAt(X, Y: Integer; out APartID: Integer): Boolean; begin Result := True; end; procedure TcxHTMLSelectRegion.SetOnRegionSelected(AHandler: TcxHTMLRegionSelectEvent); begin if EventSink <> nil then EventSink.OnRectSelect := AHandler; end; { TcxHTMLEWFCtrlBehavior } constructor TcxHTMLEWFCtrlBehavior.Create(ANamespace: TcxHTMLNamespace); begin inherited Create(ANamespace); CanSetCursor := True; FViewLinkInitialized := False; end; class function TcxHTMLEWFCtrlBehavior.EventSinkClass: TcxHTMLEventSinkClass; begin Result := TcxHTMLEWFCtrlEventSink; end; procedure TcxHTMLEWFCtrlBehavior.DrawElement(ADC: HDC; ABounds: TRect); begin inherited; DrawIconEx(ADC, ABounds.Left, ABounds.Top, EWFMarkIcon, 0, 0, 0, 0, DI_NORMAL); if (EventSink as TcxHTMLEWFCtrlEventSink).IsResizing then begin Inc(ABounds.Top, EWFMarkIconSize.cy); FrameRect(ADC, ABounds, BorderBrush); end; end; function TcxHTMLEWFCtrlBehavior.GetCursor( const APartID: Integer): HCURSOR; begin Result := LoadCursor(0, IDC_SIZEALL); end; function TcxHTMLEWFCtrlBehavior.GetExpandRect: TRect; begin Result := inherited GetExpandRect; Result.Top := EWFMarkIconSize.cy; end; function TcxHTMLEWFCtrlBehavior.GetZOrder: Integer; begin Result := HTMLPAINT_ZORDER_ABOVE_CONTENT; end; function TcxHTMLEWFCtrlBehavior.HitTestAt(X, Y: Integer; out APartID: Integer): Boolean; begin Result := False; end; procedure TcxHTMLEWFCtrlBehavior.InitializeBehavior; var Doc4: IHTMLDocument4; ViewLink: IHTMLDocument2; begin inherited; Element.document.QueryInterface(IHTMLDocument4, Doc4); ViewLink := Doc4.createDocumentFromUrl('about:Blank', 'null'); // Do not localize if ViewLink <> nil then begin FViewLinkEventSink := TcxHTMLDocEventSink.Create(nil); FViewLinkEventSinkIntf := FViewLinkEventSink; FViewLinkEventSinkIntf.Connect(ViewLink); FViewLinkEventSink.OnReadyStateChange := ViewLinkStateChange; if ElementDef <> nil then begin ElementDef.canHaveHTML := False; ElementDef.viewInheritStyle := False; ElementDef.contentEditable := 'false'; // Do not localize ElementDef._Set_viewLink(ViewLink as IHTMLDocument); end; FViewLinkInitialized := True; end; end; procedure TcxHTMLEWFCtrlBehavior.ViewLinkStateChange(const AEventObject: IHTMLEventObj); begin UpdateContent; { Element.style.pixelLeft := Left; Element.style.pixelTop := Top; Element.style.pixelWidth := Right - Left; Element.style.pixelHeight := Bottom - Top; } end; procedure TcxHTMLEWFCtrlBehavior.SetViewLinkContent(const AContent, ACSSContent: string); const EWFStyleID = 'ewfdesignstyleid'; EWFElementID = 'ewfdesignelementid'; var ViewLink: IHTMLDocument2; Element: IHTMLElement; StyleElement: IHTMLStyleElement; begin ViewLink := GetViewLinkDoc; Element := (ViewLink as IHTMLDocument3).getElementById(EWFStyleID); if ACSSContent <> '' then begin if Element = nil then begin Element := ViewLink.createElement(Format('', [EWFStyleID])); (ViewLink.body as IHTMLDOMNode).appendChild(Element as IHTMLDOMNode); end; if Supports(Element, IHTMLStyleElement, StyleElement) and (StyleElement.styleSheet <> nil) then StyleElement.styleSheet.cssText := ACSSContent; end else if Element <> nil then (Element as IHTMLDOMNode).removeNode(True); Element := (ViewLink as IHTMLDocument3).getElementById(EWFElementID); if Element = nil then begin Element := ViewLink.createElement(Format('', [EWFElementID])); (ViewLink.body as IHTMLDOMNode).appendChild(Element as IHTMLDOMNode); end; if Element <> nil then Element.innerHTML := AContent; end; function TcxHTMLEWFCtrlBehavior.GetViewLinkDoc: IHTMLDocument2; begin Supports(ElementDef.viewLink, IHTMLDocument2, Result); end; procedure TcxHTMLEWFCtrlBehavior.UpdateContent; var ViewLink: IHTMLDocument2; Content, InlineStyle, CSSContent: string; begin if not FViewLinkInitialized then Exit; ViewLink := GetViewLinkDoc; if (ViewLink <> nil) and IsDocumentReady(ViewLink) then begin (GetViewLinkDoc.body as IHTMLBodyElement).scroll := 'no'; // Do not localize Namespace.GetElementInfo.GetViewLinkContent(Element, Content, CSSContent, InlineStyle); if ElementDef <> nil then ElementDef.style.cssText := InlineStyle; SetViewLinkContent(Content, CSSContent); Namespace.GetEditorInfo.CompleteUndoBlock; end; end; procedure TcxHTMLEWFCtrlBehavior.FinalizeBehavior; begin if FViewLinkEventSinkIntf <> nil then FViewLinkEventSinkIntf.Disconnect; FViewLinkEventSinkIntf := nil; FViewLinkEventSink := nil; inherited; end; procedure TcxHTMLEWFCtrlBehavior.OnResizeElement(ANewSize: TPoint); begin end; function TcxHTMLEWFCtrlBehavior.GetElementDef: IHTMLElementDefaults; var SiteOM2: IElementBehaviorSiteOM2; begin if Supports(FBehaviorSite, IElementBehaviorSiteOM2, SiteOM2) then SiteOM2.GetDefaults(Result) else Result := nil; end; { TcxHTMLEWFCntnrBehavior } function TcxHTMLEWFCntnrBehavior.GetEventSink: TcxCustomHTMLEventSink; begin Result := nil; end; procedure TcxHTMLEWFCntnrBehavior.DrawElement(ADC: HDC; ABounds: TRect); begin inherited; DrawIconEx(ADC, ABounds.Left, ABounds.Top, EWFMarkIcon, 0, 0, 0, 0, DI_NORMAL); end; function TcxHTMLEWFCntnrBehavior.GetExpandRect: TRect; begin Result := inherited GetExpandRect; Result.Top := EWFMarkIconSize.cy; end; function TcxHTMLEWFCntnrBehavior.GetZOrder: Integer; begin Result := HTMLPAINT_ZORDER_BELOW_CONTENT; end; procedure TcxHTMLEWFCntnrBehavior.InitializeBehavior; var SiteOM2: IElementBehaviorSiteOM2; ElementDef: IHTMLElementDefaults; begin inherited; if Supports(FBehaviorSite, IElementBehaviorSiteOM2, SiteOM2) then begin SiteOM2.GetDefaults(ElementDef); if ElementDef <> nil then begin ElementDef.canHaveHTML := True; ElementDef.viewInheritStyle := True; ElementDef.contentEditable := 'inherit'; // Do not localize end; end; end; function CreateBrush(AStyle, AColor: Cardinal; AHatch: Integer): HBrush; var LogBrush: TLogBrush; begin LogBrush.lbStyle := AStyle; LogBrush.lbColor := AColor; LogBrush.lbHatch := AHatch; Result := CreateBrushIndirect(LogBrush); end; initialization EWFMarkIcon := LoadImage(HInstance, 'EWFCONTROLSMARK', IMAGE_ICON, 0, 0, 0); // Do not localize BackgroundBrush := CreateBrush(BS_SOLID, ColorToRGB(clWindow), 0); BorderBrush := CreateBrush(BS_SOLID, $C0C0C0, 0); finalization DeleteObject(EWFMarkIcon); DeleteObject(BackgroundBrush); DeleteObject(BorderBrush); end.