Конференция "KOL" » Subclassing ActiveX Conrol
 
  • Jon © (04.08.10 12:56) [0]
    Can anyone provide an example of subclassing a ActiveX control with KOL please?

    I need to subclass the WebBrowser control in order for it to handle certain keypresses correctly (such as Tab, etc).

    With the VCL, I was recommended to use IsKeyMsg in the Forms.pas unit, but this does not apply to KOL's structure.

    My problem is that when it comes to subclassing, I am lost. Any advice is welcome.

    You can see the problem by looking at the example that I posted in another thread (reply [5] in http://pda.delphimaster.net/?id=1280668558&n=10) - go to google.com and enter a search but the dropdown query suggestions do not appear, but the suggestions work with IE.
  • Дмитрий К © (05.08.10 12:30) [1]
    Subclass
    Internet Explorer_Server

  • Jon © (05.08.10 13:17) [2]
    As I explained, I do not know or understand how to subclass in KOL - is there an example available?
  • Дмитрий К © (05.08.10 13:30) [3]
    program Project1;

    uses
     windows,
     messages,
     kol,
     kolwebbrowser, activex;
    type
     PForm1 = ^TForm1;
     TForm1 = object(TObj)
     private
       form, pnl, btn1: pcontrol;
       html: PKOLWebBrowser;
       FOleInPlaceActiveObject: IOleInPlaceActiveObject;
       procedure btn1Click(Sender: PObj);
     end;

    procedure NewForm1(var Result: PForm1; APArent: PControl);
    begin
     New(Result, Create);
     with Result^ do
     begin
       form := NewForm(APArent, 'WebBrowser');
       Applet := form;
       form.Add2AutoFree(Result);
       form.SimpleStatusText := '';
       pnl := NewPanel(Form, esNone).SetAlign(caBottom);
       html := NewKOLWebBrowser(form);
       PControl(html).SetAlign(caClient);
       html.Navigate('http://google.com');
       btn1 := NewButton(pnl, 'btn1').ResizeParentBottom;
       btn1.OnClick := btn1Click;
     end;
    end;

    var Form1: PForm1; p: Pointer; wbwnd: HWND;

    function WndProc(wnd: HWND; msg: Cardinal; wParam, lParam: Integer): Integer; stdcall;
    const
      DialogKeys: set of Byte = [VK_LEFT, VK_RIGHT, VK_BACK, {VK_UP, VK_DOWN,}
        $30..$39, $41..42, $44..$55, $57, $59..$5A];
    var
      msg1: windows.TMsg;
      iOIPAO: IOleInPlaceActiveObject;
      Dispatch: IDispatch;
    begin
     msg1.hwnd := wbwnd;
     msg1.message := msg;
     msg1.wParam := wParam;
     msg1.lParam := lParam;

     if not form1.html.Busy then
     begin
       if form1.FOleInPlaceActiveObject = nil then
       begin
        Dispatch := form1.html.Application;
        if Dispatch <> nil then
        begin
          Dispatch.QueryInterface(IOleInPlaceActiveObject, iOIPAO);
          if iOIPAO <> nil then
            form1.FOleInPlaceActiveObject := iOIPAO;
        end;
      end;

      if form1.FOleInPlaceActiveObject <> nil then
        if ((Msg1.message = WM_KEYDOWN) or (Msg1.message = WM_KEYUP)) and
          not (Msg1.wParam in DialogKeys) then
          form1.FOleInPlaceActiveObject.TranslateAccelerator(Msg1);

     end;
     result := CallWindowProcW(p, wnd, msg, wParam, lParam);
    end;

    { TForm1 }

    procedure TForm1.btn1Click(Sender: PObj);

    begin
     wbwnd := FindWindowEx(html.Handle,0,'Shell DocObject View',nil);
     wbwnd := FindWindowEx(wbwnd,0,'Internet Explorer_Server',nil);

     p := Pointer(GetWindowLongW(wbwnd, GWL_WNDPROC));
     SetWindowLongW(wbwnd, GWL_WNDPROC, integer(@wndproc));

    end;

    begin
     NewForm1(Form1, nil);
     Run(Applet);
    end.

  • Jon © (05.08.10 14:54) [4]
    Thank you Dmitry for the comprehensive example.

    I complied it and I see that the TAB key works in the control.
    But on google.com the query suggestions still do not work.

    There is a trick way to show the suggestions:
    - start typing a word in the search box, like: goo
    - press TAB
    - press SHIFT+TAB
    Now the suggestions list shows, but it does not update.

    Is there an easy fix for this?
  • Дмитрий К © (05.08.10 16:04) [5]
    You're welcome.
    btw, I must admit, I understand slightly how that code works, and why DialogKeys should be ignored. Here, I tried to modify WndProc, and I believe it works now.
    function WndProc(wnd: HWND; msg: Cardinal; wParam, lParam: Integer): Integer; stdcall;
    var
      msg1: windows.TMsg;
      iOIPAO: IOleInPlaceActiveObject;
      Dispatch: IDispatch;
    begin
     if not form1.html.Busy then
     begin
       if form1.FOleInPlaceActiveObject = nil then
       begin
         Dispatch := form1.html.Application;
         if Dispatch <> nil then
         begin
           Dispatch.QueryInterface(IOleInPlaceActiveObject, iOIPAO);
           if iOIPAO <> nil then
             form1.FOleInPlaceActiveObject := iOIPAO;
         end;
       end;
       if form1.FOleInPlaceActiveObject <> nil then
       begin
         msg1.hwnd := wbwnd;
         msg1.message := msg;
         msg1.wParam := wParam;
         msg1.lParam := lParam;
         if ((Msg1.message = WM_KEYDOWN) or (Msg1.message = WM_KEYUP)) then
         begin
           if form1.FOleInPlaceActiveObject.TranslateAccelerator(Msg1) = 0 then
           begin
             Result := 0;
             Exit;
           end;
         end;
       end;
     end;
     result := CallWindowProcW(p, wnd, msg, wParam, lParam);
    end;

  • Дмитрий К © (05.08.10 16:15) [6]
    And of course it's better to place checking of type of message on the first place.

    P.S. Please, excuse my english.
  • Jon © (06.08.10 03:47) [7]
    You, my friend, are a genius! Thank you very much again. I shall learn from your example.

    PS: Please excuse my English - your English is infinitely better than my Russian!
 
Конференция "KOL" » Subclassing ActiveX Conrol
Есть новые Нет новых   [134430   +2][b:0.003][p:0.005]