2
0

GLS.FullScreenViewer.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.FullScreenViewer;
  5. (* A Platform specific full-screen viewer *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. Winapi.Windows,
  10. Winapi.Messages,
  11. System.Classes,
  12. System.SysUtils,
  13. VCL.Forms,
  14. VCL.Controls,
  15. VCL.Menus,
  16. GLS.OpenGLTokens,
  17. GLS.Utils,
  18. GLS.Context,
  19. GLS.Scene,
  20. GLS.SceneViewer;
  21. type
  22. TGLScreenDepth = (sd8bits, sd16bits, sd24bits, sd32bits);
  23. (* A FullScreen viewer.
  24. This non visual viewer will, when activated, use the full screen as rendering
  25. surface. It will also switch/restore videomode depending on the required
  26. width/height.
  27. This is performed by creating an underlying TForm and using its surface
  28. for rendering OpenGL, "decent" ICDs will automatically use PageFlipping
  29. instead of BlockTransfer (slower buffer flipping mode used for windowed OpenGL).
  30. Note: if you terminate the application either via a kill or in the IDE,
  31. the original resolution isn't restored. *)
  32. TGLFullScreenViewer = class(TGLNonVisualViewer)
  33. private
  34. FFormIsOwned: Boolean;
  35. FForm: TForm;
  36. FOwnDC: HWND;
  37. FScreenDepth: TGLScreenDepth;
  38. FActive: Boolean;
  39. FSwitchedResolution: Boolean;
  40. FManualRendering: Boolean;
  41. FUpdateCount: Integer;
  42. FOnMouseDown: TMouseEvent;
  43. FOnMouseUp: TMouseEvent;
  44. FOnMouseMove: TMouseMoveEvent;
  45. FOnMouseWheel: TMouseWheelEvent;
  46. FOnMouseWheelDown: TMouseWheelUpDownEvent;
  47. FOnMouseWheelUp: TMouseWheelUpDownEvent;
  48. FOnClick, FOnDblClick: TNotifyEvent;
  49. FOnKeyDown: TKeyEvent;
  50. FOnKeyUp: TKeyEvent;
  51. FOnKeyPress: TKeyPressEvent;
  52. FOnClose: TCloseEvent;
  53. FOnCloseQuery: TCloseQueryEvent;
  54. FStayOnTop: Boolean;
  55. FVSync: TGLVSyncMode;
  56. FRefreshRate: Integer;
  57. FCursor: TCursor;
  58. FPopupMenu: TPopupMenu;
  59. procedure SetScreenDepth(const val: TGLScreenDepth);
  60. procedure SetActive(const val: Boolean);
  61. procedure SetOnMouseDown(const val: TMouseEvent);
  62. procedure SetOnMouseUp(const val: TMouseEvent);
  63. procedure SetOnMouseMove(const val: TMouseMoveEvent);
  64. procedure SetOnMouseWheel(const val: TMouseWheelEvent);
  65. procedure SetOnMouseWheelDown(const val: TMouseWheelUpDownEvent);
  66. procedure SetOnMouseWheelUp(const val: TMouseWheelUpDownEvent);
  67. procedure SetOnClick(const val: TNotifyEvent);
  68. procedure SetOnDblClick(const val: TNotifyEvent);
  69. procedure SetOnCloseQuery(const val: TCloseQueryEvent);
  70. procedure SetOnClose(const val: TCloseEvent);
  71. procedure SetOnKeyUp(const val: TKeyEvent);
  72. procedure SetOnKeyDown(const val: TKeyEvent);
  73. procedure SetOnKeyPress(const val: TKeyPressEvent);
  74. procedure SetStayOnTop(const val: Boolean);
  75. procedure SetCursor(const val: TCursor);
  76. procedure SetPopupMenu(const val: TPopupMenu);
  77. procedure SetForm(aVal: TForm);
  78. procedure SetManualRendering(const val: Boolean);
  79. protected
  80. function GetHandle: HWND;
  81. procedure DoBeforeRender(Sender: TObject);
  82. procedure DoBufferChange(Sender: TObject); override;
  83. procedure DoBufferStructuralChange(Sender: TObject); override;
  84. procedure Startup;
  85. procedure Shutdown;
  86. procedure BindFormEvents;
  87. procedure DoCloseQuery(Sender: TObject; var CanClose: Boolean);
  88. procedure DoPaint(Sender: TObject);
  89. procedure DoActivate(Sender: TObject);
  90. procedure DoDeactivate(Sender: TObject);
  91. procedure DoFormDestroy(Sender: TObject);
  92. public
  93. constructor Create(AOwner: TComponent); override;
  94. destructor Destroy; override;
  95. procedure Render(baseObject: TGLBaseSceneObject = nil); override;
  96. (* Adjusts property so that current resolution will be used.
  97. Call this method if you want to make sure video mode isn't switched. *)
  98. procedure UseCurrentResolution;
  99. procedure BeginUpdate;
  100. procedure EndUpdate;
  101. // Activates/deactivates full screen mode.
  102. property Active: Boolean read FActive write SetActive;
  103. procedure ReActivate;
  104. (* Read access to the underlying form handle.
  105. Returns 0 (zero) if the viewer is not active or has not yet
  106. instantiated its form. *)
  107. property Handle: HWND read GetHandle;
  108. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  109. function LastFrameTime: Single;
  110. function FramesPerSecond: Single;
  111. function FramesPerSecondText(decimals: Integer = 1): String;
  112. procedure ResetPerformanceMonitor;
  113. property RenderDC: HWND read FOwnDC;
  114. published
  115. property Form: TForm read FForm write SetForm;
  116. property ManualRendering: Boolean read FManualRendering write SetManualRendering;
  117. // It is not used in UNIX. Requested ScreenDepth.
  118. property ScreenDepth: TGLScreenDepth read FScreenDepth write SetScreenDepth default sd32bits;
  119. (* Specifies if the underlying form is "fsStayOnTop".
  120. The benefit of StayOnTop is that it hides the windows bar and
  121. other background windows. The "fsStayOnTop" is automatically
  122. switched off/on when the underlying form loses/gains focus.
  123. It is recommended not to use StayOnTop while running in the IDE
  124. or during the debugging phase. *)
  125. property StayOnTop: Boolean read FStayOnTop write SetStayOnTop default False;
  126. (* Specifies if the refresh should be synchronized with the VSync signal.
  127. If the underlying OpenGL ICD does not support the WGL_EXT_swap_control
  128. extension, this property is ignored. *)
  129. property VSync: TGLVSyncMode read FVSync write FVSync default vsmSync;
  130. (* Screen refresh rate.
  131. Use zero for system default. This property allows you to work around
  132. the winxp bug that limits uses a refresh rate of 60hz when changeing
  133. resolution. it is however suggested to give the user the opportunity
  134. to adjust it instead of having a fixed value (expecially beyond
  135. 75hz or for resolutions beyond 1024x768).
  136. the value will be automatically clamped to the highest value
  137. *reported* compatible with the monitor. *)
  138. property RefreshRate: Integer read FRefreshRate write FRefreshRate;
  139. property Cursor: TCursor read FCursor write SetCursor default crDefault;
  140. property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
  141. property OnClose: TCloseEvent read FOnClose write SetOnClose;
  142. property OnKeyUp: TKeyEvent read FOnKeyUp write SetOnKeyUp;
  143. property OnKeyDown: TKeyEvent read FOnKeyDown write SetOnKeyDown;
  144. property OnKeyPress: TKeyPressEvent read FOnKeyPress write SetOnKeyPress;
  145. property OnCloseQuery: TCloseQueryEvent read FOnCloseQuery write SetOnCloseQuery;
  146. property OnClick: TNotifyEvent read FOnClick write SetOnClick;
  147. property OnDblClick: TNotifyEvent read FOnDblClick write SetOnDblClick;
  148. property OnMouseDown: TMouseEvent read FOnMouseDown write SetOnMouseDown;
  149. property OnMouseUp: TMouseEvent read FOnMouseUp write SetOnMouseUp;
  150. property OnMouseMove: TMouseMoveEvent read FOnMouseMove write SetOnMouseMove;
  151. property OnMouseWheel: TMouseWheelEvent read FOnMouseWheel write SetOnMouseWheel;
  152. property OnMouseWheelDown: TMouseWheelUpDownEvent read FOnMouseWheelDown
  153. write SetOnMouseWheelDown;
  154. property OnMouseWheelUp: TMouseWheelUpDownEvent read FOnMouseWheelUp
  155. write SetOnMouseWheelUp;
  156. end;
  157. procedure Register;
  158. // ------------------------------------------------------------------
  159. implementation
  160. // ------------------------------------------------------------------
  161. uses
  162. GLS.Screen,
  163. GLS.WindowsContext;
  164. const
  165. cScreenDepthToBPP: array [sd8bits .. sd32bits] of Integer = (8, 16, 24, 32);
  166. procedure Register;
  167. begin
  168. RegisterComponents('GLScene', [TGLFullScreenViewer]);
  169. end;
  170. // ------------------
  171. // ------------------ TGLFullScreenViewer ------------------
  172. // ------------------
  173. constructor TGLFullScreenViewer.Create(AOwner: TComponent);
  174. begin
  175. inherited Create(AOwner);
  176. Width := 800;
  177. Height := 600;
  178. FScreenDepth := sd32bits;
  179. FVSync := vsmSync;
  180. FCursor := crDefault;
  181. Buffer.ViewerBeforeRender := DoBeforeRender;
  182. end;
  183. destructor TGLFullScreenViewer.Destroy;
  184. begin
  185. Active := False;
  186. inherited Destroy;
  187. end;
  188. procedure TGLFullScreenViewer.DoBeforeRender(Sender: TObject);
  189. begin
  190. SetupVSync(VSync);
  191. end;
  192. procedure TGLFullScreenViewer.DoBufferChange(Sender: TObject);
  193. begin
  194. if Assigned(FForm) and (not Buffer.Rendering) then
  195. begin
  196. Buffer.Render;
  197. end;
  198. end;
  199. procedure TGLFullScreenViewer.DoBufferStructuralChange(Sender: TObject);
  200. begin
  201. if Active and (FUpdateCount = 0) then
  202. ReActivate
  203. end;
  204. procedure TGLFullScreenViewer.Render(baseObject: TGLBaseSceneObject = nil);
  205. begin
  206. Buffer.Render(baseObject);
  207. end;
  208. procedure TGLFullScreenViewer.BeginUpdate;
  209. begin
  210. Inc(FUpdateCount);
  211. end;
  212. procedure TGLFullScreenViewer.EndUpdate;
  213. begin
  214. Dec(FUpdateCount);
  215. if FUpdateCount = 0 then
  216. begin
  217. if Active then
  218. DoBufferStructuralChange(Self)
  219. end
  220. else if FUpdateCount < 0 then
  221. begin
  222. FUpdateCount := 0;
  223. Assert(False, 'Unbalanced Begin/EndUpdate');
  224. end;
  225. end;
  226. procedure TGLFullScreenViewer.ReActivate;
  227. begin
  228. Shutdown;
  229. Startup;
  230. end;
  231. procedure TGLFullScreenViewer.Notification(AComponent: TComponent;
  232. Operation: TOperation);
  233. begin
  234. if (Operation = opRemove) and (Buffer <> nil) then
  235. begin
  236. if (AComponent = Buffer.Camera) then
  237. Buffer.Camera := nil;
  238. Active := False;
  239. if (AComponent = FForm) then
  240. begin
  241. Active := False;
  242. Form := nil;
  243. end;
  244. end;
  245. inherited Notification(AComponent, Operation);
  246. end;
  247. function TGLFullScreenViewer.LastFrameTime: Single;
  248. begin
  249. Result := Buffer.LastFrameTime;
  250. end;
  251. function TGLFullScreenViewer.FramesPerSecond: Single;
  252. begin
  253. Result := Buffer.FramesPerSecond;
  254. end;
  255. function TGLFullScreenViewer.FramesPerSecondText(decimals: Integer): String;
  256. begin
  257. Result := Format('%.*f FPS', [decimals, Buffer.FramesPerSecond]);
  258. end;
  259. procedure TGLFullScreenViewer.ResetPerformanceMonitor;
  260. begin
  261. Buffer.ResetPerformanceMonitor;
  262. end;
  263. procedure TGLFullScreenViewer.UseCurrentResolution;
  264. begin
  265. BeginUpdate;
  266. try
  267. Width := Screen.Width;
  268. Height := Screen.Height;
  269. case GetCurrentColorDepth of
  270. 24: ScreenDepth := sd24bits;
  271. 16: ScreenDepth := sd16bits;
  272. 8: ScreenDepth := sd8bits;
  273. else
  274. // highest depth possible otherwise
  275. ScreenDepth := sd32bits;
  276. end;
  277. finally
  278. EndUpdate;
  279. end;
  280. end;
  281. procedure TGLFullScreenViewer.SetActive(const val: Boolean);
  282. begin
  283. if val <> FActive then
  284. begin
  285. // Alt+Tab delayed until better times
  286. // {$IFDEF MSWindows}
  287. // Application.OnDeactivate:=DoDeActivate;
  288. // Application.OnActivate:=DoActivate;
  289. // {$ENDIF}
  290. if val then
  291. Startup
  292. else
  293. Shutdown;
  294. end;
  295. end;
  296. procedure TGLFullScreenViewer.Startup;
  297. var
  298. res: TResolution;
  299. begin
  300. if FActive then
  301. Exit;
  302. if FForm = nil then
  303. begin
  304. FFormIsOwned := True;
  305. FForm := TForm.Create(nil);
  306. FForm.Show();
  307. end
  308. else
  309. FFormIsOwned := False;
  310. with FForm do
  311. begin
  312. If BorderStyle <> bsNone then
  313. BorderStyle := bsNone;
  314. Cursor := Self.Cursor;
  315. PopupMenu := Self.PopupMenu;
  316. Left := 0;
  317. Top := 0;
  318. ClientWidth := Self.Width;
  319. ClientHeight := Self.Height;
  320. BindFormEvents;
  321. res := GetIndexFromResolution(Width, Height,
  322. cScreenDepthToBPP[ScreenDepth]);
  323. if res = 0 then
  324. raise Exception.Create('Unsupported video mode');
  325. if StayOnTop then
  326. FormStyle := fsStayOnTop
  327. else
  328. FormStyle := fsNormal;
  329. {$IFDEF MSWINDOWS}
  330. SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE) and
  331. not WS_CAPTION);
  332. {$ENDIF}
  333. // WindowState:=wsMaximized;
  334. // Switch video mode
  335. if (Screen.Width <> Width) or (Screen.Height <> Height) or
  336. (GetCurrentColorDepth <> cScreenDepthToBPP[ScreenDepth]) then
  337. begin
  338. SetFullscreenMode(res, FRefreshRate);
  339. FSwitchedResolution := True;
  340. end;
  341. {$IFDEF MSWINDOWS}
  342. // Hides Taskbar + Windows 7 Button
  343. ShowWindow(FindWindow('Shell_TrayWnd', nil), SW_HIDE);
  344. ShowWindow(FindWindow('BUTTON', nil), SW_HIDE);
  345. {$ENDIF}
  346. // Show;
  347. end;
  348. Buffer.Resize(0, 0, Width, Height);
  349. FOwnDC := GetDC(FForm.Handle);
  350. Buffer.CreateRC(FOwnDC, False);
  351. // Linux Unicode
  352. {$IFDEF Linux}
  353. GrabMouseToForm(FForm);
  354. {$ENDIF}
  355. // todo
  356. FActive := True;
  357. end;
  358. procedure TGLFullScreenViewer.Shutdown;
  359. begin
  360. if not FActive then
  361. Exit;
  362. Assert(FForm <> nil);
  363. Buffer.DestroyRC;
  364. with FForm do
  365. begin
  366. Cursor := crDefault;
  367. PopupMenu := nil;
  368. end;
  369. {$IFDEF Linux}
  370. ReleaseMouseFromForm(FForm);
  371. {$ENDIF}
  372. {$IFDEF MSWINDOWS}
  373. // Restore Taskbar + Windows 7 Button
  374. ShowWindow(FindWindow('Shell_TrayWnd', nil), SW_SHOWNA);
  375. ShowWindow(FindWindow('BUTTON', nil), SW_SHOWNA);
  376. {$ENDIF}
  377. // attempt that, at the very least...
  378. if FSwitchedResolution then
  379. RestoreDefaultMode;
  380. FActive := False;
  381. if FFormIsOwned then
  382. FreeAndNil(FForm);
  383. end;
  384. procedure TGLFullScreenViewer.BindFormEvents;
  385. begin
  386. if Assigned(FForm) then
  387. with FForm do
  388. begin
  389. OnMouseDown := FOnMouseDown;
  390. OnMouseUp := FOnMouseUp;
  391. OnMouseMove := FOnMouseMove;
  392. OnMouseWheel := FOnMouseWheel;
  393. OnMouseWheelDown := FOnMouseWheelDown;
  394. OnMouseWheelUp := FOnMouseWheelUp;
  395. OnClick := FOnClick;
  396. OnDblClick := FOnDblClick;
  397. OnCloseQuery := DoCloseQuery;
  398. OnClose := FOnClose;
  399. OnKeyUp := FOnKeyUp;
  400. OnKeyDown := FOnKeyDown;
  401. OnKeyPress := FOnKeyPress;
  402. OnPaint := DoPaint;
  403. OnDestroy := DoFormDestroy;
  404. end;
  405. end;
  406. procedure TGLFullScreenViewer.DoCloseQuery(Sender: TObject;
  407. var CanClose: Boolean);
  408. begin
  409. if Assigned(FOnCloseQuery) then
  410. FOnCloseQuery(Sender, CanClose);
  411. CanClose := True;
  412. // if CanClose then Shutdown;
  413. end;
  414. procedure TGLFullScreenViewer.DoPaint(Sender: TObject);
  415. begin
  416. If not ManualRendering then
  417. if Form <> nil then
  418. Render;
  419. end;
  420. procedure TGLFullScreenViewer.DoActivate(Sender: TObject);
  421. begin
  422. (* If not Active and (Form <> nil) then begin
  423. Startup;
  424. end; *)
  425. end;
  426. procedure TGLFullScreenViewer.DoDeactivate(Sender: TObject);
  427. begin
  428. (* If Active and (Form <> nil) then begin
  429. Shutdown;
  430. Form.Height:=0;
  431. Form.Width:=0;
  432. end; *)
  433. end;
  434. procedure TGLFullScreenViewer.DoFormDestroy(Sender: TObject);
  435. begin
  436. Active := False;
  437. end;
  438. procedure TGLFullScreenViewer.SetScreenDepth(const val: TGLScreenDepth);
  439. begin
  440. if FScreenDepth <> val then
  441. begin
  442. FScreenDepth := val;
  443. DoBufferStructuralChange(Self);
  444. end;
  445. end;
  446. procedure TGLFullScreenViewer.SetStayOnTop(const val: Boolean);
  447. begin
  448. if val <> FStayOnTop then
  449. begin
  450. FStayOnTop := val;
  451. DoBufferStructuralChange(Self);
  452. end;
  453. end;
  454. procedure TGLFullScreenViewer.SetOnCloseQuery(const val: TCloseQueryEvent);
  455. begin
  456. FOnCloseQuery := val; // this one uses a special binding
  457. end;
  458. procedure TGLFullScreenViewer.SetOnClose(const val: TCloseEvent);
  459. begin
  460. If Form <> nil then
  461. Form.OnClose := val;
  462. FOnClose := val;
  463. end;
  464. procedure TGLFullScreenViewer.SetOnKeyPress(const val: TKeyPressEvent);
  465. begin
  466. If Form <> nil then
  467. Form.OnKeyPress := val;
  468. FOnKeyPress := val;
  469. end;
  470. procedure TGLFullScreenViewer.SetOnKeyUp(const val: TKeyEvent);
  471. begin
  472. If Form <> nil then
  473. Form.OnKeyUp := val;
  474. FOnKeyUp := val;
  475. end;
  476. procedure TGLFullScreenViewer.SetOnKeyDown(const val: TKeyEvent);
  477. begin
  478. If Form <> nil then
  479. Form.OnKeyDown := val;
  480. FOnKeyDown := val;
  481. end;
  482. procedure TGLFullScreenViewer.SetOnMouseWheel(const val: TMouseWheelEvent);
  483. begin
  484. If Form <> nil then
  485. Form.OnMouseWheel := val;
  486. FOnMouseWheel := val;
  487. end;
  488. procedure TGLFullScreenViewer.SetOnMouseWheelDown
  489. (const val: TMouseWheelUpDownEvent);
  490. begin
  491. If Form <> nil then
  492. Form.OnMouseWheelDown := val;
  493. FOnMouseWheelDown := val;
  494. end;
  495. procedure TGLFullScreenViewer.SetOnMouseWheelUp
  496. (const val: TMouseWheelUpDownEvent);
  497. begin
  498. If Form <> nil then
  499. Form.OnMouseWheelUp := val;
  500. FOnMouseWheelUp := val;
  501. end;
  502. procedure TGLFullScreenViewer.SetOnClick(const val: TNotifyEvent);
  503. begin
  504. If Form <> nil then
  505. Form.OnClick := val;
  506. FOnClick := val;
  507. end;
  508. procedure TGLFullScreenViewer.SetOnDblClick(const val: TNotifyEvent);
  509. begin
  510. If Form <> nil then
  511. Form.OnDblClick := val;
  512. FOnDblClick := val;
  513. end;
  514. procedure TGLFullScreenViewer.SetOnMouseMove(const val: TMouseMoveEvent);
  515. begin
  516. If Form <> nil then
  517. Form.OnMouseMove := val;
  518. FOnMouseMove := val;
  519. end;
  520. procedure TGLFullScreenViewer.SetOnMouseDown(const val: TMouseEvent);
  521. begin
  522. If Form <> nil then
  523. Form.OnMouseDown := val;
  524. FOnMouseDown := val;
  525. end;
  526. procedure TGLFullScreenViewer.SetOnMouseUp(const val: TMouseEvent);
  527. begin
  528. If Form <> nil then
  529. Form.OnMouseUp := val;
  530. FOnMouseUp := val;
  531. end;
  532. procedure TGLFullScreenViewer.SetCursor(const val: TCursor);
  533. begin
  534. if val <> FCursor then
  535. begin
  536. FCursor := val;
  537. if Form <> nil then
  538. FForm.Cursor := val;
  539. end;
  540. end;
  541. procedure TGLFullScreenViewer.SetPopupMenu(const val: TPopupMenu);
  542. begin
  543. if val <> FPopupMenu then
  544. begin
  545. FPopupMenu := val;
  546. if Assigned(FForm) then
  547. FForm.PopupMenu := val;
  548. end;
  549. end;
  550. procedure TGLFullScreenViewer.SetForm(aVal: TForm);
  551. begin
  552. FForm := aVal;
  553. end;
  554. procedure TGLFullScreenViewer.SetManualRendering(const val: Boolean);
  555. begin
  556. if FManualRendering <> val then
  557. FManualRendering := val;
  558. end;
  559. function TGLFullScreenViewer.GetHandle: HWND;
  560. begin
  561. if Form <> nil then
  562. Result := FForm.Handle
  563. else
  564. Result := 0;
  565. end;
  566. // ------------------------------------------------------------------
  567. initialization
  568. // ------------------------------------------------------------------
  569. RegisterClasses([TGLFullScreenViewer]);
  570. finalization
  571. {$IFDEF MSWINDOWS}
  572. // Restore Taskbar + Windows 7 Button
  573. ShowWindow(FindWindow('Shell_TrayWnd', nil), SW_SHOWNA);
  574. ShowWindow(FindWindow('BUTTON', nil), SW_SHOWNA);
  575. {$ENDIF}
  576. end.