2009-05-13 5 views
1

Mike Lischke의 Virtual Treeview에서 TWebBrowser 컨트롤을 같은 양식에서 사용할 때 버그를 수정하기 위해 workaround 코드 이 추가되었습니다.델파이 : TOleControl은 ActiveControl을 잘못된 상태로 둡니다?

문제는 사용자가 TOleControl (있는 TWebBrowser이 내려)와 상호 작용하려고하면, 최초의 마우스 클릭 먹이었다. 그런 다음 다시 클릭하여 제어 권한을 부여해야합니다. 그러면 그들은 컨트롤과 상호 작용할 수 있습니다. 잠재적으로 초점 문제를

TOleControl에서 파생 된 모든 제어했습니다

그는 설명하는 주석이 있습니다. TOleControl 클래스 테스트 할 것이다 (그 중에서도 변형를 포함한다)를 OleCtrls 부를 포함 피하기 위해

IOleClientSite 인터페이스를 지원하는 테스트에 사용되는 TOleControl와 좋은 지표. 전체 SNIPPIT에서

:

procedure TBaseVirtualTree.WMKillFocus(var Msg: TWMKillFocus); 
var 
    Form: TCustomForm; 
    Control: TWinControl; 
    Pos: TSmallPoint; 
    Unknown: IUnknown; 
begin 
    inherited; 

    [snip] 

    { 
    Workaround for wrapped non-VCL controls (like TWebBrowser), 
    which do not use VCL mechanisms and 
    leave the ActiveControl property in the wrong state, 
    which causes trouble when the control is refocused. 
    } 
    Form := GetParentForm(Self); 
    if Assigned(Form) and (Form.ActiveControl = Self) then 
    begin 
    Cardinal(Pos) := GetMessagePos; 
    Control := FindVCLWindow(SmallPointToPoint(Pos)); 
    { 
     Every control derived from TOleControl has potentially 
     the focus problem. In order to avoid including 
     the OleCtrls unit (which will, among others, include Variants), 
     which would allow to test for the TOleControl 
     class, the IOleClientSite interface is used for the test, 
     which is supported by TOleControl and a good indicator. 
    } 
    if Assigned(Control) and Control.GetInterface(IOleClientSite, Unknown) then 
     Form.ActiveControl := nil; 

    // For other classes the active control should not be modified. Otherwise you need two clicks to select it. 
    end; 
end; 

문제 해결이 더 이상 나를 위해 작동하는지 없다. 그리고 솔직히 말해서 나는 그 문제가 실제로 무엇인지, 그리고 그의 해결책이 그것을 어떻게 고정 시켰는지 전혀 모른다.

그의 의견이 무엇을 말하고 있는지 이해하고 있고, 문제가 무엇인지, 그리고 그가하고있는 일이 어떻게 고쳐야 하는지를 아는 사람이 있습니까? VCL 메커니즘을 사용하고 컨트롤이 재 집중 될 때 문제의 원인이되는 잘못된 상태에서 ActiveControl 속성을 두지 않습니다 (TWebBrowser 같은) 포장 비 VCL 컨트롤에 대한

해결. 모든 컨트롤 TOleControl에서 파생 된 잠재적으로 포커스 문제가 있습니다.

코드는 의도

Form.ActiveControl := nil; 

문에 도달하지만, 그것은 단지 트릭을하고 있지 않습니다.

내가 그것을 고칠 것,하지만 난 그가 그것을 발견, 또는 어떻게 그 TOleControl에 대해 올 수하지 않습니다 "사용 VCL 메커니즘과 잘못된 상태의 ActiveControl 속성을 잎하는 방법을 모른다."


나는 원래 (12개월 이상)이 질문에 on borland.public.delphi.nativeapi.win32 newsgroup in 2008

Question on Soft-Gems forum

범프 20110515을 요청

보너스 독서

범프 20150401 (7 년 후) : 아직도 미상 XE6

+0

Virtual TreeView가 작동하지 않습니다. 14. 화성 09에서 마지막 버전? 아마도 가장 위대한 델파이 구성 요소가 이제까지 IMHO. – Tom

+0

내가 처음 질문을했을 때 그것은 없어졌습니다. Mike가 Mac 및 MySQL 개발로 옮겼을 때, VT에 좋지 않았습니다. 일부 산발적 인 지원이 있지만 공식은 없습니다. –

+0

기존 태그를 사용하기 위해이 질문에 태그를 다시 지정하는 동안 tvirtualtreeview 태그가 이미이 질문에 존재 함을 발견했습니다 : http://stackoverflow.com/questions/687438/. 당신은 어떤 것이 옳은지 알 수 있습니다. 그래서 그들 중 하나를 바꾸시겠습니까? 감사. –

답변

3

에서 sn't 작업은 내가 (표준 TWebBrowser보다 훨씬 낫다) TEmbeddedWB를 사용하여이 문제를 극복하고 나는이 OnShowUI 이벤트 추가했다 :

function THtmlFrame.webBrowserShowUI(const dwID: Cardinal; 
    const pActiveObject: IOleInPlaceActiveObject; 
    const pCommandTarget: IOleCommandTarget; const pFrame: IOleInPlaceFrame; 
    const pDoc: IOleInPlaceUIWindow): HRESULT; 
begin 
    try 
    if WebBrowser.CanFocus then 
     WebBrowser.SetFocus; // tell the VCL that the web-browser is focused 
    except 
    on E: EInvalidOperation do 
     ; // ignore "Cannot focus inactive or invisible control" 
    end; 
    Result := S_FALSE; 
end; 


하지만 만약을 더 많은 코드를 작성해야하는 TWebBrowser를 사용해야합니다.

type 
    IDocHostUIHandler = interface(IUnknown) 
    ['{bd3f23c0-d43e-11cf-893b-00aa00bdce1a}'] 
    function ShowContextMenu(const dwID: DWORD; const ppt: PPOINT; 
     const CommandTarget: IUnknown; const Context: IDispatch): HRESULT; stdcall; 
    function GetHostInfo(var pInfo: TDOCHOSTUIINFO): HRESULT; stdcall; 
    function ShowUI(const dwID: DWORD; const pActiveObject: IOleInPlaceActiveObject; 
     const pCommandTarget: IOleCommandTarget; const pFrame: IOleInPlaceFrame; 
     const pDoc: IOleInPlaceUIWindow): HRESULT; stdcall; 
    function HideUI: HRESULT; stdcall; 
    function UpdateUI: HRESULT; stdcall; 
    function EnableModeless(const fEnable: BOOL): HRESULT; stdcall; 
    function OnDocWindowActivate(const fActivate: BOOL): HRESULT; stdcall; 
    function OnFrameWindowActivate(const fActivate: BOOL): HRESULT; stdcall; 
    function ResizeBorder(const prcBorder: PRECT; const pUIWindow: IOleInPlaceUIWindow; const fRameWindow: BOOL): HRESULT; stdcall; 
    function TranslateAccelerator(const lpMsg: PMSG; const pguidCmdGroup: PGUID; const nCmdID: DWORD): HRESULT; stdcall; 
    function GetOptionKeyPath(out pchKey: POLESTR; const dw: DWORD): HRESULT; stdcall; 
    function GetDropTarget(const pDropTarget: IDropTarget; out ppDropTarget: IDropTarget): HRESULT; stdcall; 
    function GetExternal(out ppDispatch: IDispatch): HRESULT; stdcall; 
    function TranslateUrl(const dwTranslate: DWORD; const pchURLIn: POLESTR; out ppchURLOut: POLESTR): HRESULT; stdcall; 
    function FilterDataObject(const pDO: IDataObject; out ppDORet: IDataObject): HRESULT; stdcall; 
    end; // IDocHostUIHandler 

    ICustomDoc = interface(IUnknown) 
    ['{3050f3f0-98b5-11cf-bb82-00aa00bdce0b}'] 
    function SetUIHandler(const pUIHandler: IDocHostUIHandler): HResult; stdcall; 
    end; 

    TDocHostUIHandler = class(TInterfacedObject, IDocHostUIHandler) 
    private 
    FWebBrowser: TWebBrowser; 
    protected 
    function EnableModeless(const fEnable: BOOL): HResult; stdcall; 
    function FilterDataObject(const pDO: IDataObject; out ppDORet: IDataObject): HResult; stdcall; 
    function GetDropTarget(const pDropTarget: IDropTarget; out ppDropTarget: IDropTarget): HResult; stdcall; 
    function GetExternal(out ppDispatch: IDispatch): HResult; stdcall; 
    function GetHostInfo(var pInfo: TDocHostUIInfo): HResult; stdcall; 
    function GetOptionKeyPath(var pchKey: POLESTR; const dw: DWORD): HResult; stdcall; 
    function HideUI: HResult; stdcall; 
    function OnDocWindowActivate(const fActivate: BOOL): HResult; stdcall; 
    function OnFrameWindowActivate(const fActivate: BOOL): HResult; stdcall; 
    function ResizeBorder(const prcBorder: PRECT; const pUIWindow: IOleInPlaceUIWindow; 
     const fFrameWindow: BOOL): HResult; stdcall; 
    function ShowContextMenu(const dwID: DWORD; const ppt: PPOINT; 
     const pcmdtReserved: IInterface; const pdispReserved: IDispatch): HResult; stdcall; 
    function ShowUI(const dwID: DWORD; const pActiveObject: IOleInPlaceActiveObject; 
     const pCommandTarget: IOleCommandTarget; const pFrame: IOleInPlaceFrame; 
     const pDoc: IOleInPlaceUIWindow): HResult; stdcall; 
    function TranslateAccelerator(const lpMsg: PMSG; const pguidCmdGroup: PGUID; const nCmdID: DWORD): HResult; stdcall; 
    function TranslateUrl(const dwTranslate: DWORD; const pchURLIn: POLESTR; var ppchURLOut: POLESTR): HResult; stdcall; 
    function UpdateUI: HResult; stdcall; 
    public 
    constructor Create(AWebBrowser: TWebBrowser); 
    property WebBrowser: TWebBrowser read FWebBrowser; 
    end; 


{ TDocHostUIHandler } 

function TDocHostUIHandler.EnableModeless(const fEnable: BOOL): HResult; 
begin 
    Result := S_OK; 
end; 

function TDocHostUIHandler.FilterDataObject(const pDO: IDataObject; out ppDORet: IDataObject): HResult; 
begin 
    ppDORet := nil; 
    Result := S_FALSE; 
end; 

function TDocHostUIHandler.GetDropTarget(const pDropTarget: IDropTarget; out ppDropTarget: IDropTarget): HResult; 
begin 
    ppDropTarget := nil; 
    Result := E_FAIL; 
end; 

function TDocHostUIHandler.GetExternal(out ppDispatch: IDispatch): HResult; 
begin 
    ppDispatch := nil; 
    Result := E_FAIL; 
end; 

function TDocHostUIHandler.GetHostInfo(var pInfo: TDocHostUIInfo): HResult; 
begin 
    Result := S_OK; 
end; 

function TDocHostUIHandler.GetOptionKeyPath(var pchKey: POLESTR; const dw: DWORD): HResult; 
begin 
    Result := E_FAIL; 
end; 

function TDocHostUIHandler.HideUI: HResult; 
begin 
    Result := S_OK; 
end; 

function TDocHostUIHandler.OnDocWindowActivate(const fActivate: BOOL): HResult; 
begin 
    Result := S_OK; 
end; 

function TDocHostUIHandler.OnFrameWindowActivate(const fActivate: BOOL): HResult; 
begin 
    Result := S_OK; 
end; 

function TDocHostUIHandler.ResizeBorder(const prcBorder: PRECT; const pUIWindow: IOleInPlaceUIWindow; const fFrameWindow: BOOL): HResult; 
begin 
    Result := S_FALSE; 
end; 

function TDocHostUIHandler.ShowContextMenu(const dwID: DWORD; const ppt: PPOINT; const pcmdtReserved: IInterface; const pdispReserved: IDispatch): HResult; 
begin 
    Result := S_FALSE 
end; 

function TDocHostUIHandler.TranslateAccelerator(const lpMsg: PMSG; const pguidCmdGroup: PGUID; const nCmdID: DWORD): HResult; 
begin 
    Result := S_FALSE; 
end; 

function TDocHostUIHandler.TranslateUrl(const dwTranslate: DWORD; const pchURLIn: POLESTR; var ppchURLOut: POLESTR): HResult; 
begin 
    Result := E_FAIL; 
end; 

function TDocHostUIHandler.UpdateUI: HResult; 
begin 
    Result := S_OK; 
end; 

function TDocHostUIHandler.ShowUI(const dwID: DWORD; const pActiveObject: IOleInPlaceActiveObject; const pCommandTarget: IOleCommandTarget; 
    const pFrame: IOleInPlaceFrame; const pDoc: IOleInPlaceUIWindow): HResult; 
begin 
    try 
    if WebBrowser.CanFocus then 
     WebBrowser.SetFocus; // tell the VCL that the web-browser is focused 
    except 
    on E: EInvalidOperation do 
     ; // ignore "Cannot focus inactive or invisible control" 
    end; 
    Result := S_OK; 
end; 



// install the DocHostUIHandler into the WebBrowser 
var 
    CustomDoc: ICustomDoc; 
begin 
    if WebBrowser1.Document.QueryInterface(ICustomDoc, CustomDoc) = S_OK then 
    CustomDoc.SetUIHandler(TDocHostUIHandler.Create(WebBrowser1)); 
end; 
+0

나는 TEmbeddedWB를 사용하고 있지만이 문제는 TWebBrowser에서도 발생합니다. 그리고 나는 사람들이 TEmbeddedWB를 비난하면서 탄원하는 것을 원하지 않을 것입니다. CanFocus/SetFocus를 OnShowUI 이벤트에 추가하려고했습니다. 작동하지 않습니다. 주로 웹 브라우저 컨트롤을 클릭하기 전까지는 OnShowUI 이벤트가 실제로 실행되지 않기 때문입니다. –