GLS.FullScreenViewer.pas 17 KB

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