Main.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. unit Main;
  2. interface
  3. uses
  4. Qt, QExtCtrls, QDialogs, QMenus, QTypes, QGraphics, QControls, QForms,
  5. SysUtils, Classes, QStdCtrls, IdGlobal,
  6. libmng;
  7. {****************************************************************************}
  8. {* For conditions of distribution and use, *}
  9. {* see copyright notice in libmng.pas *}
  10. {****************************************************************************}
  11. {* *}
  12. {* project : libmng *}
  13. {* file : main.pas copyright (c) 2000-2002 G.Juyn *}
  14. {* version : 1.0.5 *}
  15. {* *}
  16. {* purpose : Main form for mngview application *}
  17. {* *}
  18. {* author : G.Juyn *}
  19. {* web : http://www.3-t.com *}
  20. {* email : mailto:[email protected] *}
  21. {* *}
  22. {* comment : this is the heart of the mngview applciation *}
  23. {* *}
  24. {* changes : 1.0.5 - 09/21/2002 - G.Juyn *}
  25. {* - modified for Kylix use *}
  26. {* *}
  27. {****************************************************************************}
  28. type
  29. TMainForm = class(TForm)
  30. OFMainMenu: TMainMenu;
  31. OFMenuFile: TMenuItem;
  32. OFMenuFileOpen: TMenuItem;
  33. OFMenuFileN1: TMenuItem;
  34. OFMenuFileExit: TMenuItem;
  35. OFTimer: TTimer;
  36. OFOpenDialog: TOpenDialog;
  37. OFPanel: TPanel;
  38. OFImage: TImage;
  39. procedure FormCreate(Sender: TObject);
  40. procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  41. procedure FormShow(Sender: TObject);
  42. procedure FormResize(Sender: TObject);
  43. procedure FormKeyDown(Sender: TObject; var Key: Word;
  44. Shift: TShiftState);
  45. procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  46. Y: Integer);
  47. procedure OFImageMouseMove(Sender: TObject; Shift: TShiftState; X,
  48. Y: Integer);
  49. procedure OFImageMouseDown(Sender: TObject; Button: TMouseButton;
  50. Shift: TShiftState; X, Y: Integer);
  51. procedure OFImageMouseUp(Sender: TObject; Button: TMouseButton;
  52. Shift: TShiftState; X, Y: Integer);
  53. procedure OFTimerTimer(Sender: TObject);
  54. procedure OFMenuFileOpenClick(Sender: TObject);
  55. procedure OFMenuFileExitClick(Sender: TObject);
  56. private
  57. { Private declarations }
  58. SFFileName : string; { filename of the input stream }
  59. OFFile : TFileStream; { input stream }
  60. IFHandle : mng_handle; { the libray handle }
  61. OFBitmap : TBitmap; { drawing canvas }
  62. BFCancelled : boolean; { <esc> or app-exit }
  63. BFHasMouse : boolean; { mouse is/was over image }
  64. procedure MNGerror (SHMsg : string);
  65. public
  66. { Public declarations }
  67. end;
  68. var
  69. MainForm: TMainForm;
  70. {****************************************************************************}
  71. implementation
  72. {$R *.dfm}
  73. {****************************************************************************}
  74. {$F+}
  75. function Memalloc (iLen : mng_uint32) : mng_ptr; cdecl;
  76. {$F-}
  77. begin
  78. getmem (Result, iLen); { get memory from the heap }
  79. fillchar (Result^, iLen, 0); { and initialize it }
  80. end;
  81. {****************************************************************************}
  82. {$F+}
  83. procedure Memfree (iPtr : mng_ptr;
  84. iLen : mng_size_t); cdecl;
  85. {$F-}
  86. begin
  87. freemem (iPtr, iLen); { free the memory }
  88. end;
  89. {****************************************************************************}
  90. {$F+}
  91. function Openstream (hHandle : mng_handle) : mng_bool; cdecl;
  92. {$F-}
  93. var OHForm : TMainForm;
  94. begin { get a fix on our form }
  95. OHForm := TMainForm (mng_get_userdata (hHandle));
  96. with OHFORM do
  97. begin
  98. if OFFile <> nil then { free previous stream (if any) }
  99. OFFile.Free;
  100. { open a new stream }
  101. OFFile := TFileStream.Create (SFFileName, fmOpenRead or fmShareDenyWrite);
  102. end;
  103. Result := MNG_TRUE;
  104. end;
  105. {****************************************************************************}
  106. {$F+}
  107. function Closestream (hHandle : mng_handle) : mng_bool; cdecl;
  108. {$F-}
  109. var OHForm : TMainForm;
  110. begin { get a fix on our form }
  111. OHForm := TMainForm (mng_get_userdata (hHandle));
  112. with OHFORM do
  113. begin
  114. OFFile.Free; { cleanup the stream }
  115. OFFile := nil; { don't use it again ! }
  116. end;
  117. Result := MNG_TRUE;
  118. end;
  119. {****************************************************************************}
  120. {$F+}
  121. function Readdata ( hHandle : mng_handle;
  122. pBuf : mng_ptr;
  123. iBuflen : mng_uint32;
  124. var pRead : mng_uint32) : mng_bool; cdecl;
  125. {$F-}
  126. var OHForm : TMainForm;
  127. begin
  128. { get a fix on our form }
  129. OHForm := TMainForm (mng_get_userdata (hHandle));
  130. with OHForm do
  131. begin { are we at EOF ? }
  132. if OFFile.Position >= OFFile.Size then
  133. begin
  134. pRead := 0; { indicate so }
  135. end
  136. else
  137. begin
  138. { read the requested data }
  139. pRead := OFFile.Read (pBuf^, iBuflen);
  140. end;
  141. end;
  142. Result := MNG_TRUE;
  143. end;
  144. {****************************************************************************}
  145. {$F+}
  146. function ProcessHeader (hHandle : mng_handle;
  147. iWidth : mng_uint32;
  148. iHeight : mng_uint32) : mng_bool; cdecl;
  149. {$F-}
  150. var OHForm : TMainForm;
  151. begin { get a fix on our form }
  152. OHForm := TMainForm (mng_get_userdata (hHandle));
  153. with OHForm do
  154. begin
  155. OFBitmap.Width := iWidth; { store the new dimensions }
  156. OFBitmap.Height := iHeight;
  157. OFBitmap.PixelFormat := pf32bit;
  158. OFImage.Left := 0; { adjust the visible component }
  159. OFImage.Top := 0;
  160. OFImage.Width := iWidth;
  161. OFImage.Height := iHeight;
  162. FormResize (OHForm); { force re-centering the image}
  163. { clear the canvas & draw an outline }
  164. OFBitmap.Canvas.Brush.Color := clGray;
  165. OFBitmap.Canvas.Brush.Style := bsSolid;
  166. OFBitmap.Canvas.FillRect (OFBitmap.Canvas.ClipRect);
  167. OFImage.Picture.Assign (OFBitmap); { make sure it gets out there }
  168. { tell the library we want funny windows-bgr}
  169. if mng_set_canvasstyle (hHandle, MNG_CANVAS_BGRX8) <> 0 then
  170. MNGerror ('libmng reported an error setting the canvas style');
  171. end;
  172. Result := MNG_TRUE;
  173. end;
  174. {****************************************************************************}
  175. {$F+}
  176. function GetCanvasLine (hHandle : mng_handle;
  177. iLinenr : mng_uint32) : mng_ptr; cdecl;
  178. {$F-}
  179. var OHForm : TMainForm;
  180. begin { get a fix on our form }
  181. OHForm := TMainForm (mng_get_userdata (hHandle));
  182. { easy with these bitmap objects ! }
  183. Result := TBitmap(OHForm.OFImage.Picture.Graphic).ScanLine [iLinenr];
  184. end;
  185. {****************************************************************************}
  186. {$F+}
  187. function ImageRefresh (hHandle : mng_handle;
  188. iX : mng_uint32;
  189. iY : mng_uint32;
  190. iWidth : mng_uint32;
  191. iHeight : mng_uint32) : mng_bool; cdecl;
  192. {$F-}
  193. var OHForm : TMainForm;
  194. begin { get a fix on our form }
  195. OHForm := TMainForm (mng_get_userdata (hHandle));
  196. { force redraw }
  197. OHForm.OFImage.Refresh;
  198. Result := MNG_TRUE;
  199. end;
  200. {****************************************************************************}
  201. {$F+}
  202. function MyGetTickCount (hHandle : mng_handle) : mng_uint32; cdecl;
  203. {$F-}
  204. begin
  205. Result := GetTickCount; { the system knows that }
  206. end;
  207. {****************************************************************************}
  208. {$F+}
  209. function SetTimer (hHandle : mng_handle;
  210. iMsecs : mng_uint32) : mng_bool; cdecl;
  211. {$F-}
  212. var OHForm : TMainForm;
  213. begin { get a fix on our form }
  214. OHForm := TMainForm (mng_get_userdata (hHandle));
  215. OHForm.OFTimer.Interval := iMsecs; { and set the timer }
  216. OHForm.OFTimer.Enabled := true;
  217. Result := MNG_TRUE;
  218. end;
  219. {****************************************************************************}
  220. procedure TMainForm.FormCreate(Sender: TObject);
  221. var IHRed, IHGreen, IHBlue : word;
  222. begin { initialize }
  223. OFBitmap := TBitmap.Create;
  224. BFHasMouse := false;
  225. OFFile := nil;
  226. OFOpenDialog.Initialdir := '';
  227. { now initialize the library }
  228. IFHandle := mng_initialize (mng_ptr(self), Memalloc, Memfree, nil);
  229. if IFHandle = NIL then
  230. begin
  231. MNGerror ('libmng initialization error' + #13#10 +
  232. 'Program aborted');
  233. Application.Terminate;
  234. end;
  235. { no need to store chunk-info ! }
  236. mng_set_storechunks (IFHandle, MNG_FALSE);
  237. { do not use suspension-buffer }
  238. mng_set_suspensionmode (IFHandle, MNG_FALSE);
  239. { set all the callbacks }
  240. if (mng_setcb_openstream (IFHandle, Openstream ) <> MNG_NOERROR) or
  241. (mng_setcb_closestream (IFHandle, Closestream ) <> MNG_NOERROR) or
  242. (mng_setcb_readdata (IFHandle, Readdata ) <> MNG_NOERROR) or
  243. (mng_setcb_processheader (IFHandle, ProcessHeader ) <> MNG_NOERROR) or
  244. (mng_setcb_getcanvasline (IFHandle, GetCanvasLine ) <> MNG_NOERROR) or
  245. (mng_setcb_refresh (IFHandle, ImageRefresh ) <> MNG_NOERROR) or
  246. (mng_setcb_gettickcount (IFHandle, MyGetTickCount ) <> MNG_NOERROR) or
  247. (mng_setcb_settimer (IFHandle, SetTimer ) <> MNG_NOERROR) then
  248. begin
  249. MNGerror ('libmng reported an error setting a callback function!' + #13#10 +
  250. 'Program aborted');
  251. Application.Terminate;
  252. end;
  253. IHRed := (Color ) and $FF; { supply our own bg-color }
  254. IHGreen := (Color shr 8) and $FF;
  255. IHBlue := (Color shr 16) and $FF;
  256. IHRed := (IHRed shl 8) + IHRed;
  257. IHGreen := (IHGreen shl 8) + IHGreen;
  258. IHBlue := (IHBlue shl 8) + IHBlue;
  259. if mng_set_bgcolor (IFHandle, IHRed, IHGreen, IHBlue) <> MNG_NOERROR then
  260. MNGerror ('libmng reported an error setting the background color!');
  261. end;
  262. {****************************************************************************}
  263. procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  264. begin
  265. BFCancelled := true;
  266. if OFTimer.Enabled then { if we're still animating then stop it }
  267. begin
  268. OFTimer.Enabled := false;
  269. Application.ProcessMessages;
  270. if mng_reset (IFHandle) <> MNG_NOERROR then
  271. MNGerror ('libmng reported an error during reset!');
  272. end;
  273. mng_cleanup (IFHandle);
  274. end;
  275. {****************************************************************************}
  276. procedure TMainForm.FormShow(Sender: TObject);
  277. begin
  278. FormResize (self);
  279. end;
  280. {****************************************************************************}
  281. procedure TMainForm.FormResize(Sender: TObject);
  282. begin { center the image in the window }
  283. if ClientWidth < OFImage.Width then
  284. OFImage.Left := 0
  285. else
  286. OFImage.Left := (ClientWidth - OFImage.Width ) div 2;
  287. if ClientHeight < OFImage.Height then
  288. OFImage.Top := 0
  289. else
  290. OFImage.Top := (ClientHeight - OFImage.Height) div 2;
  291. end;
  292. {****************************************************************************}
  293. procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
  294. Shift: TShiftState);
  295. begin
  296. if Key = Key_Escape then { pressing <esc> will freeze an animation }
  297. begin
  298. if OFTimer.Enabled then
  299. if mng_display_freeze (IFHandle) <> MNG_NOERROR then
  300. MNGerror ('libmng reported an error during display_freeze!');
  301. OFTimer.Enabled := false; { don't let that timer go off then ! }
  302. BFCancelled := true;
  303. end;
  304. end;
  305. {****************************************************************************}
  306. procedure TMainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  307. Y: Integer);
  308. begin
  309. if mng_status_dynamic (IFHandle) then
  310. begin
  311. if BFHasMouse then { if we had the mouse, it's left ! }
  312. begin
  313. if mng_trapevent (IFHandle, 3, 0, 0) <> MNG_NOERROR then
  314. MNGerror ('libmng reported an error during trapevent!');
  315. BFHasMouse := false;
  316. end;
  317. end;
  318. end;
  319. {****************************************************************************}
  320. procedure TMainForm.OFImageMouseMove(Sender: TObject; Shift: TShiftState;
  321. X, Y: Integer);
  322. begin
  323. if mng_status_dynamic (IFHandle) then
  324. begin
  325. if BFHasMouse then { did we have the mouse already ? }
  326. begin
  327. if mng_trapevent (IFHandle, 2, X, Y) <> MNG_NOERROR then
  328. MNGerror ('libmng reported an error during trapevent!');
  329. end
  330. else
  331. begin { if not, it has entered ! }
  332. if mng_trapevent (IFHandle, 1, X, Y) <> MNG_NOERROR then
  333. MNGerror ('libmng reported an error during trapevent!');
  334. BFHasMouse := true;
  335. end;
  336. end;
  337. end;
  338. {****************************************************************************}
  339. procedure TMainForm.OFImageMouseDown(Sender: TObject; Button: TMouseButton;
  340. Shift: TShiftState; X, Y: Integer);
  341. begin
  342. if mng_status_dynamic (IFHandle) then
  343. if mng_trapevent (IFHandle, 4, X, Y) <> MNG_NOERROR then
  344. MNGerror ('libmng reported an error during trapevent!');
  345. end;
  346. {****************************************************************************}
  347. procedure TMainForm.OFImageMouseUp(Sender: TObject; Button: TMouseButton;
  348. Shift: TShiftState; X, Y: Integer);
  349. begin
  350. if mng_status_dynamic (IFHandle) then
  351. if mng_trapevent (IFHandle, 5, X, Y) <> MNG_NOERROR then
  352. MNGerror ('libmng reported an error during trapevent!');
  353. end;
  354. {****************************************************************************}
  355. procedure TMainForm.OFTimerTimer(Sender: TObject);
  356. var IHRslt : mng_retcode;
  357. begin
  358. OFTimer.Enabled := false; { only once ! }
  359. if not BFCancelled then
  360. begin { and inform the library }
  361. IHRslt := mng_display_resume (IFHandle);
  362. if (IHRslt <> MNG_NOERROR) and (IHRslt <> MNG_NEEDTIMERWAIT) then
  363. MNGerror ('libmng reported an error during display_resume!');
  364. end;
  365. end;
  366. {****************************************************************************}
  367. procedure TMainForm.OFMenuFileOpenClick(Sender: TObject);
  368. var IHRslt : mng_retcode;
  369. begin
  370. OFOpenDialog.InitialDir := '';
  371. OFOpenDialog.FileName := SFFileName;
  372. if OFOpenDialog.Execute then { get the filename }
  373. begin
  374. if OFTimer.Enabled then { if the lib was active; stop it }
  375. begin
  376. OFTimer.Enabled := false;
  377. Application.ProcessMessages; { process any timer requests (for safety) }
  378. { now freeze the animation }
  379. if mng_reset (IFHandle) <> MNG_NOERROR then
  380. MNGerror ('libmng reported an error during reset!');
  381. end;
  382. { save interesting fields }
  383. SFFileName := OFOpenDialog.FileName;
  384. BFCancelled := false;
  385. OFImage.Picture.Graphic := nil; { clear the output-canvas }
  386. OFImage.Refresh;
  387. { always reset (just in case) }
  388. if mng_reset (IFHandle) <> MNG_NOERROR then
  389. MNGerror ('libmng reported an error during reset!')
  390. else
  391. begin { and let the lib do it's job ! }
  392. IHRslt := mng_readdisplay (IFHandle);
  393. if (IHRslt <> MNG_NOERROR) and (IHRSLT <> MNG_NEEDTIMERWAIT) then
  394. MNGerror ('libmng reported an error reading the input file!');
  395. end;
  396. end;
  397. end;
  398. {****************************************************************************}
  399. procedure TMainForm.OFMenuFileExitClick(Sender: TObject);
  400. begin
  401. if mng_cleanup (IFHandle) <> MNG_NOERROR then
  402. MNGerror ('libmng cleanup error');
  403. Close;
  404. end;
  405. {****************************************************************************}
  406. procedure TMainForm.MNGerror;
  407. var iErrorcode : mng_uint32;
  408. iSeverity : mng_uint8;
  409. iChunkname : mng_chunkid;
  410. iChunkseq : mng_uint32;
  411. iExtra1 : mng_int32;
  412. iExtra2 : mng_int32;
  413. zErrortext : mng_pchar;
  414. begin { get extended info }
  415. iErrorcode := mng_getlasterror (IFHandle, iSeverity, iChunkname, iChunkseq,
  416. iExtra1, iExtra2, zErrortext);
  417. MessageDlg (SHMsg + #13#10#13#10 + strpas (zErrortext) + #13#10#13#10 +
  418. Format ('Error = %d; Severity = %d; Chunknr = %d; Extra1 = %d',
  419. [iErrorcode, iSeverity, iChunkseq, iExtra1]),
  420. mtError, [mbOK], 0);
  421. Application.Terminate;
  422. end;
  423. {****************************************************************************}
  424. end.