cefclient.dpr 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. {$IFDEF FPC}
  2. {$MODE DELPHI}{$H+}
  3. {$APPTYPE GUI}
  4. {$ENDIF}
  5. {$I cef.inc}
  6. program cefclient;
  7. uses
  8. Classes,
  9. Windows,
  10. Messages,
  11. SysUtils,
  12. ceflib,
  13. ceffilescheme in '..\filescheme\ceffilescheme.pas';
  14. type
  15. TCustomClient = class(TCefClientOwn)
  16. private
  17. FLifeSpan: ICefLifeSpanHandler;
  18. FLoad: ICefLoadHandler;
  19. FDisplay: ICefDisplayHandler;
  20. protected
  21. function GetLifeSpanHandler: ICefLifeSpanHandler; override;
  22. function GetLoadHandler: ICefLoadHandler; override;
  23. function GetDisplayHandler: ICefDisplayHandler; override;
  24. public
  25. constructor Create; override;
  26. end;
  27. TCustomLifeSpan = class(TCefLifeSpanHandlerOwn)
  28. protected
  29. procedure OnAfterCreated(const browser: ICefBrowser); override;
  30. function OnBeforePopup(const browser: ICefBrowser; const frame: ICefFrame;
  31. const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition;
  32. userGesture: Boolean; var popupFeatures: TCefPopupFeatures;
  33. var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings;
  34. var noJavascriptAccess: Boolean): Boolean; override;
  35. procedure OnBeforeClose(const browser: ICefBrowser); override;
  36. function DoClose(const browser: ICefBrowser): Boolean; override;
  37. end;
  38. TCustomLoad = class(TCefLoadHandlerOwn)
  39. protected
  40. procedure OnLoadStart(const browser: ICefBrowser; const frame: ICefFrame); override;
  41. procedure OnLoadEnd(const browser: ICefBrowser; const frame: ICefFrame;
  42. httpStatusCode: Integer); override;
  43. end;
  44. TCustomDisplay = class(TCefDisplayHandlerOwn)
  45. protected
  46. procedure OnAddressChange(const browser: ICefBrowser;
  47. const frame: ICefFrame; const url: ustring); override;
  48. procedure OnTitleChange(const browser: ICefBrowser; const title: ustring); override;
  49. end;
  50. type
  51. {$IFDEF FPC}
  52. TWindowProc = LongInt;
  53. {$ELSE}
  54. TWindowProc = Pointer;
  55. WNDPROC = Pointer;
  56. {$ENDIF}
  57. var
  58. Window : HWND;
  59. handl: ICefClient = nil;
  60. brows: ICefBrowser = nil;
  61. browserId: Integer = 0;
  62. navigateto: ustring = 'http://www.google.com';
  63. backWnd, forwardWnd, reloadWnd, stopWnd, editWnd: HWND;
  64. editWndOldProc: TWindowProc;
  65. isLoading, canGoBack, canGoForward: Boolean;
  66. const
  67. MAX_LOADSTRING = 100;
  68. MAX_URL_LENGTH = 255;
  69. BUTTON_WIDTH = 72;
  70. URLBAR_HEIGHT = 24;
  71. IDC_NAV_BACK = 200;
  72. IDC_NAV_FORWARD = 201;
  73. IDC_NAV_RELOAD = 202;
  74. IDC_NAV_STOP = 203;
  75. var
  76. setting: TCefBrowserSettings;
  77. function CefWndProc(Wnd: HWND; message: UINT; wParam: Integer; lParam: Integer): Integer; stdcall;
  78. var
  79. ps: PAINTSTRUCT;
  80. info: TCefWindowInfo;
  81. rect: TRect;
  82. hdwp: THandle;
  83. x: Integer;
  84. strPtr: array[0..MAX_URL_LENGTH-1] of WideChar;
  85. strLen, urloffset: Integer;
  86. begin
  87. if Wnd = editWnd then
  88. case message of
  89. WM_CHAR:
  90. if (wParam = VK_RETURN) then
  91. begin
  92. // When the user hits the enter key load the URL
  93. FillChar(strPtr, SizeOf(strPtr), 0);
  94. PDWORD(@strPtr)^ := MAX_URL_LENGTH;
  95. strLen := SendMessageW(Wnd, EM_GETLINE, 0, Integer(@strPtr));
  96. if (strLen > 0) then
  97. begin
  98. strPtr[strLen] := #0;
  99. brows.MainFrame.LoadUrl(strPtr);
  100. end;
  101. Result := 0;
  102. end else
  103. Result := CallWindowProc(WNDPROC(editWndOldProc), Wnd, message, wParam, lParam);
  104. else
  105. Result := CallWindowProc(WNDPROC(editWndOldProc), Wnd, message, wParam, lParam);
  106. end else
  107. case message of
  108. WM_PAINT:
  109. begin
  110. BeginPaint(Wnd, ps);
  111. EndPaint(Wnd, ps);
  112. result := 0;
  113. end;
  114. WM_CREATE:
  115. begin
  116. handl := TCustomClient.Create;
  117. x := 0;
  118. GetClientRect(Wnd, rect);
  119. backWnd := CreateWindowW('BUTTON', 'Back',
  120. WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON
  121. or WS_DISABLED, x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
  122. Wnd, IDC_NAV_BACK, HInstance, nil);
  123. Inc(x, BUTTON_WIDTH);
  124. forwardWnd := CreateWindowW('BUTTON', 'Forward',
  125. WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON
  126. or WS_DISABLED, x, 0, BUTTON_WIDTH,
  127. URLBAR_HEIGHT, Wnd, IDC_NAV_FORWARD,
  128. HInstance, nil);
  129. Inc(x, BUTTON_WIDTH);
  130. reloadWnd := CreateWindowW('BUTTON', 'Reload',
  131. WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON
  132. or WS_DISABLED, x, 0, BUTTON_WIDTH,
  133. URLBAR_HEIGHT, Wnd, IDC_NAV_RELOAD,
  134. HInstance, nil);
  135. Inc(x, BUTTON_WIDTH);
  136. stopWnd := CreateWindowW('BUTTON', 'Stop',
  137. WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON
  138. or WS_DISABLED, x, 0, BUTTON_WIDTH, URLBAR_HEIGHT,
  139. Wnd, IDC_NAV_STOP, HInstance, nil);
  140. Inc(x, BUTTON_WIDTH);
  141. editWnd := CreateWindowW('EDIT', nil,
  142. WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or
  143. ES_AUTOVSCROLL or ES_AUTOHSCROLL or WS_DISABLED,
  144. x, 0, rect.right - BUTTON_WIDTH * 4,
  145. URLBAR_HEIGHT, Wnd, 0, HInstance, nil);
  146. // Assign the edit window's WNDPROC to this function so that we can
  147. // capture the enter key
  148. editWndOldProc := TWindowProc(GetWindowLong(editWnd, GWL_WNDPROC));
  149. SetWindowLong(editWnd, GWL_WNDPROC, LongInt(@CefWndProc));
  150. FillChar(info, SizeOf(info), 0);
  151. Inc(rect.top, URLBAR_HEIGHT);
  152. info.Style := WS_CHILD or WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or WS_TABSTOP;
  153. info.parent_window := Wnd;
  154. info.x := rect.left;
  155. info.y := rect.top;
  156. info.Width := rect.right - rect.left;
  157. info.Height := rect.bottom - rect.top;
  158. FillChar(setting, sizeof(setting), 0);
  159. setting.size := SizeOf(setting);
  160. CefBrowserHostCreate(@info, handl, navigateto, @setting, nil);
  161. isLoading := False;
  162. canGoBack := False;
  163. canGoForward := False;
  164. SetTimer(Wnd, 1, 100, nil);
  165. result := 0;
  166. end;
  167. WM_TIMER:
  168. begin
  169. // Update the status of child windows
  170. EnableWindow(editWnd, True);
  171. EnableWindow(backWnd, canGoBack);
  172. EnableWindow(forwardWnd, canGoForward);
  173. EnableWindow(reloadWnd, not isLoading);
  174. EnableWindow(stopWnd, isLoading);
  175. Result := 0;
  176. end;
  177. WM_COMMAND:
  178. case LOWORD(wParam) of
  179. IDC_NAV_BACK:
  180. begin
  181. brows.GoBack;
  182. Result := 0;
  183. end;
  184. IDC_NAV_FORWARD:
  185. begin
  186. brows.GoForward;
  187. Result := 0;
  188. end;
  189. IDC_NAV_RELOAD:
  190. begin
  191. brows.Reload;
  192. Result := 0;
  193. end;
  194. IDC_NAV_STOP:
  195. begin
  196. brows.StopLoad;
  197. Result := 0;
  198. end;
  199. else
  200. result := DefWindowProc(Wnd, message, wParam, lParam);
  201. end;
  202. WM_DESTROY:
  203. begin
  204. brows := nil;
  205. PostQuitMessage(0);
  206. result := DefWindowProc(Wnd, message, wParam, lParam);
  207. end;
  208. WM_SETFOCUS:
  209. begin
  210. if brows <> nil then
  211. PostMessage(brows.Host.WindowHandle, WM_SETFOCUS, wParam, 0);
  212. Result := 0;
  213. end;
  214. WM_SIZE:
  215. begin
  216. if(brows <> nil) then
  217. begin
  218. // Resize the browser window and address bar to match the new frame
  219. // window size
  220. GetClientRect(Wnd, rect);
  221. Inc(rect.top, URLBAR_HEIGHT);
  222. urloffset := rect.left + BUTTON_WIDTH * 4;
  223. hdwp := BeginDeferWindowPos(1);
  224. hdwp := DeferWindowPos(hdwp, editWnd, 0, urloffset, 0, rect.right - urloffset, URLBAR_HEIGHT, SWP_NOZORDER);
  225. hdwp := DeferWindowPos(hdwp, brows.Host.WindowHandle, 0, rect.left, rect.top,
  226. rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
  227. EndDeferWindowPos(hdwp);
  228. end;
  229. result := DefWindowProc(Wnd, message, wParam, lParam);
  230. end;
  231. WM_CLOSE:
  232. result := DefWindowProc(Wnd, message, wParam, lParam);
  233. else
  234. result := DefWindowProc(Wnd, message, wParam, lParam);
  235. end;
  236. end;
  237. { TCustomClient }
  238. constructor TCustomClient.Create;
  239. begin
  240. inherited;
  241. FLifeSpan := TCustomLifeSpan.Create;
  242. FLoad := TCustomLoad.Create;
  243. FDisplay := TCustomDisplay.Create;
  244. end;
  245. function TCustomClient.GetDisplayHandler: ICefDisplayHandler;
  246. begin
  247. Result := FDisplay;
  248. end;
  249. function TCustomClient.GetLifeSpanHandler: ICefLifeSpanHandler;
  250. begin
  251. Result := FLifeSpan;
  252. end;
  253. function TCustomClient.GetLoadHandler: ICefLoadHandler;
  254. begin
  255. Result := FLoad;
  256. end;
  257. { TCustomLifeSpan }
  258. function TCustomLifeSpan.DoClose(const browser: ICefBrowser): Boolean;
  259. begin
  260. if browser.Identifier = browserId then
  261. begin
  262. PostMessage(Window, WM_CLOSE, 0, 0);
  263. Result := True;
  264. end else
  265. Result := False;
  266. end;
  267. procedure TCustomLifeSpan.OnAfterCreated(const browser: ICefBrowser);
  268. begin
  269. if not browser.IsPopup then
  270. begin
  271. // get the first browser
  272. brows := browser;
  273. browserId := brows.Identifier;
  274. end;
  275. end;
  276. procedure TCustomLifeSpan.OnBeforeClose(const browser: ICefBrowser);
  277. begin
  278. if browser.Identifier = browserId then
  279. brows := nil;
  280. end;
  281. function TCustomLifeSpan.OnBeforePopup(const browser: ICefBrowser; const frame: ICefFrame;
  282. const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition;
  283. userGesture: Boolean; var popupFeatures: TCefPopupFeatures;
  284. var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings;
  285. var noJavascriptAccess: Boolean): Boolean;
  286. begin
  287. if targetUrl = 'about:blank' then
  288. result := False else
  289. begin
  290. Result := True;
  291. brows.MainFrame.LoadUrl(targetUrl);
  292. end;
  293. end;
  294. { TCustomLoad }
  295. procedure TCustomLoad.OnLoadEnd(const browser: ICefBrowser;
  296. const frame: ICefFrame; httpStatusCode: Integer);
  297. begin
  298. if browser.Identifier = browserId then
  299. isLoading := False;
  300. end;
  301. procedure TCustomLoad.OnLoadStart(const browser: ICefBrowser;
  302. const frame: ICefFrame);
  303. begin
  304. if browser.Identifier = browserId then
  305. begin
  306. isLoading := True;
  307. canGoBack := browser.CanGoBack;
  308. canGoForward := browser.CanGoForward;
  309. end;
  310. end;
  311. { TCustomDisplay }
  312. procedure TCustomDisplay.OnAddressChange(const browser: ICefBrowser;
  313. const frame: ICefFrame; const url: ustring);
  314. begin
  315. if (browser.Identifier = browserId) and frame.IsMain then
  316. SetWindowTextW(editWnd, PWideChar(url));
  317. end;
  318. procedure TCustomDisplay.OnTitleChange(const browser: ICefBrowser;
  319. const title: ustring);
  320. begin
  321. if browser.Identifier = browserId then
  322. SetWindowTextW(Window, PWideChar(title));
  323. end;
  324. procedure RegisterSchemes(const registrar: ICefSchemeRegistrar);
  325. begin
  326. registrar.AddCustomScheme('local', True, True, False);
  327. end;
  328. var
  329. {$IFDEF CEF_MULTI_THREADED_MESSAGE_LOOP}
  330. Msg : TMsg;
  331. {$ENDIF}
  332. wndClass : TWndClass;
  333. begin
  334. //CefCache := 'Cache';
  335. //navigateto := 'client://test/';
  336. //navigateto := 'local://c:\';
  337. CefLogSeverity := LOGSEVERITY_WARNING;
  338. CefOnRegisterCustomSchemes := RegisterSchemes;
  339. // multi process
  340. CefSingleProcess := False;
  341. if not CefLoadLibDefault then Exit;
  342. CefRegisterSchemeHandlerFactory('local', '', TFileScheme);
  343. try
  344. wndClass.style := CS_HREDRAW or CS_VREDRAW;
  345. wndClass.lpfnWndProc := @CefWndProc;
  346. wndClass.cbClsExtra := 0;
  347. wndClass.cbWndExtra := 0;
  348. wndClass.hInstance := hInstance;
  349. wndClass.hIcon := LoadIcon(0, IDI_APPLICATION);
  350. wndClass.hCursor := LoadCursor(0, IDC_ARROW);
  351. wndClass.hbrBackground := 0;
  352. wndClass.lpszMenuName := nil;
  353. wndClass.lpszClassName := 'chromium';
  354. RegisterClass(wndClass);
  355. Window := CreateWindow(
  356. 'chromium', // window class name
  357. 'Chromium browser', // window caption
  358. WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN, // window style
  359. Integer(CW_USEDEFAULT), // initial x position
  360. Integer(CW_USEDEFAULT), // initial y position
  361. Integer(CW_USEDEFAULT), // initial x size
  362. Integer(CW_USEDEFAULT), // initial y size
  363. 0, // parent window handle
  364. 0, // window menu handle
  365. hInstance, // program instance handle
  366. nil); // creation parameters
  367. ShowWindow(Window, SW_SHOW);
  368. UpdateWindow(Window);
  369. {$IFNDEF CEF_MULTI_THREADED_MESSAGE_LOOP}
  370. CefRunMessageLoop;
  371. {$ELSE}
  372. while(GetMessageW(msg, 0, 0, 0)) do
  373. begin
  374. TranslateMessage(msg);
  375. DispatchMessageW(msg);
  376. end;
  377. {$ENDIF}
  378. finally
  379. handl := nil;
  380. end;
  381. end.