-
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.
-
Subclass Internet Explorer_Server
-
As I explained, I do not know or understand how to subclass in KOL - is there an example available?
-
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,
$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;
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.
-
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?
-
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;
-
And of course it's better to place checking of type of message on the first place.
P.S. Please, excuse my english.
-
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!
|