CIEBHO.pas 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. unit CIEBHO;
  2. {$WARN SYMBOL_PLATFORM OFF}
  3. interface
  4. uses
  5. Windows, ActiveX, Classes, ComObj, Shdocvw, Registry;
  6. type
  7. TTIEAdvBHO = class(TComObject, IObjectWithSite, IDispatch, IObjectSafety)
  8. private
  9. FIESite: IUnknown;
  10. FIE: IWebBrowser2;
  11. FCPC: IConnectionPointContainer;
  12. FCP: IConnectionPoint;
  13. FCookie: Integer;
  14. FObjectSafetyFlags: DWORD;
  15. protected
  16. //IObjectWithSite接口方法定义
  17. function SetSite(const pUnkSite: IUnknown): HResult; stdcall;
  18. function GetSite(const riid: TIID; out site: IUnknown): HResult; stdcall;
  19. //IDispatch接口方法定义
  20. function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  21. function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
  22. stdcall;
  23. function GetIDsOfNames(const IID: TGUID; Names: Pointer;
  24. NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  25. function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  26. Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
  27. stdcall;
  28. //事件处理过程
  29. procedure DoNewWindow2(var ppDisp: IDispatch; var Cancel: WordBool);
  30. procedure DoBeforeNavigate2(const pDisp: IDispatch; var URL: OleVariant; var Flags: OleVariant;
  31. var TargetFrameName: OleVariant; var PostData: OleVariant;
  32. var Headers: OleVariant; var Cancel: WordBool);
  33. function GetInterfaceSafetyOptions(const IID: TIID; pdwSupportedOptions,
  34. pdwEnabledOptions: PDWORD): HResult; stdcall;
  35. function SetInterfaceSafetyOptions(const IID: TIID; dwOptionSetMask,
  36. dwEnabledOptions: DWORD): HResult; stdcall;
  37. end;
  38. const
  39. Class_TIEAdvBHO: TGUID = '{49DDFDBB-2D52-4942-AA4A-DE9EB3036DA2}';
  40. AppKey = '\Software\Winsoft\LxTalk';
  41. CompanyKeyValue = '\Winsoft'; //做OEM版时,此处应该改为对应公司的网址或名称
  42. AppTitle = '办公助手';
  43. iAtom: PChar = 'Winsoft';
  44. implementation
  45. uses Variants, ComServ, Sysutils, ComConst, ShellAPI, CallClientInterfaceUnit;
  46. { TTIEAdvBHO }
  47. //------------------------------------------------------------------------------
  48. function TTIEAdvBHO.GetInterfaceSafetyOptions(const IID: TIID;
  49. pdwSupportedOptions, pdwEnabledOptions: PDWORD): HResult;
  50. var
  51. Unk: IUnknown;
  52. begin
  53. if (pdwSupportedOptions = nil) or (pdwEnabledOptions = nil) then
  54. begin
  55. Result := E_POINTER;
  56. Exit;
  57. end;
  58. Result := QueryInterface(IID, Unk);
  59. if Result = S_OK then
  60. begin
  61. pdwSupportedOptions^ := INTERFACESAFE_FOR_UNTRUSTED_CALLER or
  62. INTERFACESAFE_FOR_UNTRUSTED_DATA;
  63. pdwEnabledOptions^ := FObjectSafetyFlags and
  64. (INTERFACESAFE_FOR_UNTRUSTED_CALLER or INTERFACESAFE_FOR_UNTRUSTED_DATA);
  65. end
  66. else begin
  67. pdwSupportedOptions^ := 0;
  68. pdwEnabledOptions^ := 0;
  69. end;
  70. end;
  71. //------------------------------------------------------------------------------
  72. function TTIEAdvBHO.SetInterfaceSafetyOptions(const IID: TIID;
  73. dwOptionSetMask, dwEnabledOptions: DWORD): HResult;
  74. var
  75. Unk: IUnknown;
  76. begin
  77. Result := QueryInterface(IID, Unk);
  78. if Result <> S_OK then Exit;
  79. FObjectSafetyFlags := dwEnabledOptions and dwOptionSetMask;
  80. end;
  81. //------------------------------------------------------------------------------
  82. procedure TTIEAdvBHO.DoBeforeNavigate2(const pDisp: IDispatch; var URL,
  83. Flags, TargetFrameName, PostData, Headers: OleVariant;
  84. var Cancel: WordBool);
  85. var
  86. StrURL,
  87. BaseURLForOpenTalkingForm,
  88. LoginName: String;
  89. Registry: TRegistry;
  90. FVar: OleVariant;
  91. begin
  92. BaseURLForOpenTalkingForm := '';
  93. {从注册表中读取 BaseURL}
  94. Registry := TRegistry.Create;
  95. try
  96. Registry.RootKey := HKEY_LOCAL_MACHINE;
  97. if Registry.OpenKey(AppKey + CompanyKeyValue, True) then
  98. begin
  99. BaseURLForOpenTalkingForm := Registry.ReadString('BaseURLForOpenTalkingForm');
  100. end;
  101. finally
  102. Registry.Free;
  103. end;
  104. StrURL := URL;
  105. if (Length(StrURL) > Length(BaseURLForOpenTalkingForm)) and (BaseURLForOpenTalkingForm <> '') then
  106. begin
  107. if AnsiSameText(Copy(StrURL, 1, Length(BaseURLForOpenTalkingForm)), BaseURLForOpenTalkingForm) then
  108. begin
  109. LoginName := Copy(StrURL, Length(BaseURLForOpenTalkingForm) + 1, Length(StrURL));
  110. try
  111. FVar := CreateOleObject('IEBHO.CallClientInterface');
  112. try
  113. FVar.OpenTalkingForm(LoginName);
  114. finally
  115. FVar := Unassigned;
  116. end;
  117. finally
  118. if not FIE.Visible then
  119. FIE.Quit
  120. else
  121. Cancel := True;
  122. end;
  123. end;
  124. end;
  125. end;
  126. //------------------------------------------------------------------------------
  127. procedure TTIEAdvBHO.DoNewWindow2(var ppDisp: IDispatch;
  128. var Cancel: WordBool);
  129. begin
  130. //判断页面是否显示完全
  131. // Debugger.LogMsg('NewWindow2');
  132. // if FIE.ReadyState<>REFRESH_COMPLETELY then
  133. // begin
  134. // //不完全,禁止
  135. // Cancel:=False;
  136. // ppDisp:=FIE.Application;
  137. // end;
  138. end;
  139. //------------------------------------------------------------------------------
  140. function TTIEAdvBHO.GetIDsOfNames(const IID: TGUID; Names: Pointer;
  141. NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
  142. begin
  143. Result := E_NOTIMPL;
  144. end;
  145. //------------------------------------------------------------------------------
  146. function TTIEAdvBHO.GetSite(const riid: TIID;
  147. out site: IInterface): HResult;
  148. begin
  149. if Supports(FIESite, riid, site) then
  150. Result := S_OK
  151. else
  152. Result := E_NOINTERFACE;
  153. end;
  154. //------------------------------------------------------------------------------
  155. function TTIEAdvBHO.GetTypeInfo(Index, LocaleID: Integer;
  156. out TypeInfo): HResult;
  157. begin
  158. Result := E_NOTIMPL;
  159. pointer(TypeInfo) := nil;
  160. end;
  161. //------------------------------------------------------------------------------
  162. function TTIEAdvBHO.GetTypeInfoCount(out Count: Integer): HResult;
  163. begin
  164. Result := E_NOTIMPL;
  165. Count := 0;
  166. end;
  167. //------------------------------------------------------------------------------
  168. procedure BuildPositionalDispIds(pDispIds: PDispIdList; const dps: TDispParams);
  169. var
  170. i: integer;
  171. begin
  172. Assert(pDispIds <> nil);
  173. for i := 0 to dps.cArgs - 1 do
  174. pDispIds^[i] := dps.cArgs - 1 - i;
  175. if (dps.cNamedArgs <= 0) then
  176. Exit;
  177. for i := 0 to dps.cNamedArgs - 1 do
  178. pDispIds^[dps.rgdispidNamedArgs^[i]] := i;
  179. end;
  180. //------------------------------------------------------------------------------
  181. function TTIEAdvBHO.Invoke(DispID: Integer; const IID: TGUID;
  182. LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
  183. ArgErr: Pointer): HResult;
  184. var
  185. dps: TDispParams absolute Params;
  186. bHasParams: boolean;
  187. pDispIds: PDispIdList;
  188. iDispIdsSize: integer;
  189. begin
  190. pDispIds := nil;
  191. iDispIdsSize := 0;
  192. bHasParams := (dps.cArgs > 0);
  193. if (bHasParams) then
  194. begin
  195. iDispIdsSize := dps.cArgs * SizeOf(TDispId);
  196. GetMem(pDispIds, iDispIdsSize);
  197. end;
  198. try
  199. if (bHasParams) then
  200. BuildPositionalDispIds(pDispIds, dps);
  201. Result := S_OK;
  202. case DispId of
  203. // 251://NEWWINDOW2事件ID
  204. // begin
  205. // DoNewWindow2(IDispatch(dps.rgvarg^[pDispIds^[0]].pdispval^),
  206. // dps.rgvarg^[pDispIds^[1]].pbool^);
  207. // end;
  208. 250://BeforeNaviage2事件id
  209. begin
  210. DoBeforeNavigate2(IDispatch(dps.rgvarg^[pDispIds^[0]].dispval),
  211. POleVariant(dps.rgvarg^[pDispIds^[1]].pvarval)^,
  212. POleVariant(dps.rgvarg^[pDispIds^[2]].pvarval)^,
  213. POleVariant(dps.rgvarg^[pDispIds^[3]].pvarval)^,
  214. POleVariant(dps.rgvarg^[pDispIds^[4]].pvarval)^,
  215. POleVariant(dps.rgvarg^[pDispIds^[5]].pvarval)^,
  216. dps.rgvarg^[pDispIds^[6]].pbool^);
  217. end;
  218. 253://OnQuit事件ID
  219. begin
  220. FCP.Unadvise(FCookie);
  221. end;
  222. else
  223. Result := DISP_E_MEMBERNOTFOUND;
  224. end;
  225. finally
  226. if (bHasParams) then
  227. FreeMem(pDispIds, iDispIdsSize);
  228. end;
  229. end;
  230. //------------------------------------------------------------------------------
  231. function TTIEAdvBHO.SetSite(const pUnkSite: IInterface): HResult;
  232. begin
  233. Result := E_FAIL;
  234. //保存接口
  235. FIESite := pUnkSite;
  236. if not Supports(FIESite, IWebBrowser2, FIE) then
  237. Exit;
  238. if not Supports(FIE, IConnectionPointContainer, FCPC) then
  239. Exit;
  240. //挂接事件
  241. FCPC.FindConnectionPoint(DWebBrowserEvents2, FCP);
  242. FCP.Advise(Self, FCookie);
  243. Result := S_OK;
  244. end;
  245. //------------------------------------------------------------------------------
  246. procedure DeleteRegKeyValue(Root: DWORD; Key: string; ValueName: string = '');
  247. var
  248. KeyHandle: HKEY;
  249. begin
  250. if ValueName = '' then
  251. RegDeleteKey(Root, PChar(Key));
  252. if RegOpenKey(Root, PChar(Key), KeyHandle) = ERROR_SUCCESS then
  253. try
  254. RegDeleteValue(KeyHandle, PChar(ValueName));
  255. finally
  256. RegCloseKey(KeyHandle);
  257. end;
  258. end;
  259. //------------------------------------------------------------------------------
  260. procedure CreateRegKeyValue(Root: DWORD; const Key, ValueName, Value: string);
  261. var
  262. Handle: HKey;
  263. Status, Disposition: Integer;
  264. begin
  265. Status := RegCreateKeyEx(ROOT, PChar(Key), 0, '',
  266. REG_OPTION_NON_VOLATILE, KEY_READ or KEY_WRITE, nil, Handle,
  267. @Disposition);
  268. if Status = 0 then
  269. begin
  270. Status := RegSetValueEx(Handle, PChar(ValueName), 0, REG_SZ,
  271. PChar(Value), Length(Value) + 1);
  272. RegCloseKey(Handle);
  273. end;
  274. if Status <> 0 then
  275. raise EOleRegistrationError.CreateRes(@SCreateRegKeyError);
  276. end;
  277. type
  278. TIEAdvBHOFactory = class(TComObjectFactory)
  279. public
  280. procedure UpdateRegistry(Register: Boolean); override;
  281. end;
  282. { TIEAdvBHOFactory }
  283. //------------------------------------------------------------------------------
  284. procedure TIEAdvBHOFactory.UpdateRegistry(Register: Boolean);
  285. begin
  286. inherited;
  287. if Register then
  288. CreateRegKeyValue(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\explorer\Browser Helper Objects\' + GuidToString(ClassID), '', '')
  289. else
  290. DeleteRegKeyValue(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\explorer\Browser Helper Objects\' + GuidToString(ClassID), '');
  291. end;
  292. initialization
  293. TIEAdvBHOFactory.Create(ComServer, TTIEAdvBHO, Class_TIEAdvBHO,
  294. 'TIEAdvBHO', '', ciMultiInstance, tmApartment);
  295. end.