win32.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999 by Florian Klaempfl
  5. This file implements the win32 gui support for the graph unit
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {
  13. Remarks:
  14. Colors in 16 color mode:
  15. ------------------------
  16. - the behavior of xor/or/and put isn't 100%:
  17. it is done using the RGB color getting from windows
  18. instead of the palette index!
  19. - palette operations aren't supported
  20. To solve these drawbacks, setpalette must be implemented
  21. by exchanging the colors in the DCs, further GetPaletteEntry
  22. must be used when doing xor/or/and operations
  23. }
  24. const
  25. InternalDriverName = 'WIN32GUI';
  26. var
  27. savedscreen : hbitmap;
  28. graphrunning : boolean;
  29. graphdrawing : tcriticalsection;
  30. bitmapdc : hdc;
  31. oldbitmap : hgdiobj;
  32. mainwindow : HWnd;
  33. pal : ^rgbrec;
  34. SavePtr : pointer; { we don't use that pointer }
  35. MessageThreadHandle : Handle;
  36. MessageThreadID : DWord;
  37. windc : hdc;
  38. function GetPaletteEntry(r,g,b : word) : word;
  39. var
  40. dist,i,index,currentdist : longint;
  41. begin
  42. dist:=$7fffffff;
  43. index:=0;
  44. for i:=0 to maxcolors-1 do
  45. begin
  46. currentdist:=abs(r-pal[i].red)+abs(g-pal[i].green)+
  47. abs(b-pal[i].blue);
  48. if currentdist<dist then
  49. begin
  50. index:=i;
  51. dist:=currentdist;
  52. end;
  53. end;
  54. GetPaletteEntry:=index;
  55. end;
  56. procedure PutPixel16Win32GUI(x,y : integer;pixel : word);
  57. var
  58. c : colorref;
  59. begin
  60. x:=x+startxviewport;
  61. y:=y+startyviewport;
  62. { convert to absolute coordinates and then verify clipping...}
  63. if clippixels then
  64. begin
  65. if (x<startxviewport) or (x>(startxviewport+viewwidth)) or
  66. (y<StartyViewPort) or (y>(startyviewport+viewheight)) then
  67. exit;
  68. end;
  69. if graphrunning then
  70. begin
  71. EnterCriticalSection(graphdrawing);
  72. c:=RGB(pal[pixel].red,pal[pixel].green,pal[pixel].blue);
  73. SetPixel(bitmapdc,x,y,c);
  74. SetPixel(windc,x,y,c);
  75. LeaveCriticalSection(graphdrawing);
  76. end;
  77. end;
  78. function GetPixel16Win32GUI(x,y : integer) : word;
  79. var
  80. c : COLORREF;
  81. begin
  82. x:=x+startxviewport;
  83. y:=y+startyviewport;
  84. { convert to absolute coordinates and then verify clipping...}
  85. if clippixels then
  86. begin
  87. if (x<startxviewport) or (x>(startxviewport+viewwidth)) or
  88. (y<StartyViewPort) or (y>(startyviewport+viewheight)) then
  89. exit;
  90. end;
  91. if graphrunning then
  92. begin
  93. EnterCriticalSection(graphdrawing);
  94. c:=Windows.GetPixel(bitmapdc,x,y);
  95. GetPixel16Win32GUI:=GetPaletteEntry(GetRValue(c),GetGValue(c),GetBValue(c));
  96. LeaveCriticalSection(graphdrawing);
  97. end
  98. else
  99. begin
  100. _graphresult:=grerror;
  101. exit;
  102. end;
  103. end;
  104. procedure DirectPutPixel16Win32GUI(x,y : integer);
  105. var
  106. col : longint;
  107. c,c2 : COLORREF;
  108. begin
  109. if graphrunning then
  110. begin
  111. EnterCriticalSection(graphdrawing);
  112. case currentwritemode of
  113. XorPut:
  114. Begin
  115. c2:=Windows.GetPixel(bitmapdc,x,y);
  116. c:=RGB(pal[col].red,pal[col].green,pal[col].blue) xor c2;
  117. SetPixel(bitmapdc,x,y,c);
  118. SetPixel(windc,x,y,c);
  119. End;
  120. AndPut:
  121. Begin
  122. c2:=Windows.GetPixel(bitmapdc,x,y);
  123. c:=RGB(pal[col].red,pal[col].green,pal[col].blue) and c2;
  124. SetPixel(bitmapdc,x,y,c);
  125. SetPixel(windc,x,y,c);
  126. End;
  127. OrPut:
  128. Begin
  129. c2:=Windows.GetPixel(bitmapdc,x,y);
  130. c:=RGB(pal[col].red,pal[col].green,pal[col].blue) or c2;
  131. SetPixel(bitmapdc,x,y,c);
  132. SetPixel(windc,x,y,c);
  133. End
  134. else
  135. Begin
  136. If CurrentWriteMode<>NotPut Then
  137. col:=CurrentColor
  138. Else col := Not(CurrentColor);
  139. c:=RGB(pal[col].red,pal[col].green,pal[col].blue);
  140. SetPixel(bitmapdc,x,y,c);
  141. SetPixel(windc,x,y,c);
  142. End
  143. end;
  144. LeaveCriticalSection(graphdrawing);
  145. end;
  146. end;
  147. procedure HLine16Win32GUI(x,x2,y: integer);
  148. var
  149. c,c2 : COLORREF;
  150. col,i : longint;
  151. oldpen,pen : HPEN;
  152. Begin
  153. if graphrunning then
  154. begin
  155. { must we swap the values? }
  156. if x>x2 then
  157. Begin
  158. x:=x xor x2;
  159. x2:=x xor x2;
  160. x:=x xor x2;
  161. end;
  162. { First convert to global coordinates }
  163. X:=X+StartXViewPort;
  164. X2:=X2+StartXViewPort;
  165. Y:=Y+StartYViewPort;
  166. if ClipPixels then
  167. Begin
  168. if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  169. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  170. exit;
  171. end;
  172. Case CurrentWriteMode of
  173. AndPut:
  174. Begin
  175. EnterCriticalSection(graphdrawing);
  176. for i:=x to x2 do
  177. begin
  178. c2:=Windows.GetPixel(bitmapdc,i,y);
  179. c:=RGB(pal[col].red,pal[col].green,pal[col].blue) and c2;
  180. SetPixel(bitmapdc,i,y,c);
  181. SetPixel(windc,i,y,c);
  182. end;
  183. LeaveCriticalSection(graphdrawing);
  184. End;
  185. XorPut:
  186. Begin
  187. EnterCriticalSection(graphdrawing);
  188. for i:=x to x2 do
  189. begin
  190. c2:=Windows.GetPixel(bitmapdc,i,y);
  191. c:=RGB(pal[col].red,pal[col].green,pal[col].blue) xor c2;
  192. SetPixel(bitmapdc,i,y,c);
  193. SetPixel(windc,i,y,c);
  194. end;
  195. LeaveCriticalSection(graphdrawing);
  196. End;
  197. OrPut:
  198. Begin
  199. EnterCriticalSection(graphdrawing);
  200. for i:=x to x2 do
  201. begin
  202. c2:=Windows.GetPixel(bitmapdc,i,y);
  203. c:=RGB(pal[col].red,pal[col].green,pal[col].blue) or c2;
  204. SetPixel(bitmapdc,i,y,c);
  205. SetPixel(windc,i,y,c);
  206. end;
  207. LeaveCriticalSection(graphdrawing);
  208. End
  209. Else
  210. Begin
  211. If CurrentWriteMode<>NotPut Then
  212. col:=CurrentColor
  213. Else col:=Not(CurrentColor);
  214. EnterCriticalSection(graphdrawing);
  215. c:=RGB(pal[col].red,pal[col].green,pal[col].blue);
  216. pen:=CreatePen(PS_SOLID,1,c);
  217. oldpen:=SelectObject(bitmapdc,pen);
  218. Windows.MoveToEx(bitmapdc,x,y,nil);
  219. Windows.LineTo(bitmapdc,x2,y);
  220. SelectObject(bitmapdc,oldpen);
  221. oldpen:=SelectObject(windc,pen);
  222. Windows.MoveToEx(windc,x,y,nil);
  223. Windows.LineTo(windc,x2,y);
  224. SelectObject(windc,oldpen);
  225. DeleteObject(pen);
  226. LeaveCriticalSection(graphdrawing);
  227. End;
  228. End;
  229. end;
  230. end;
  231. procedure SetRGBPaletteWin32GUI(colorNum,redValue,greenvalue,
  232. bluevalue : integer);
  233. begin
  234. if directcolor or (colornum<0) or (colornum>=maxcolor) then
  235. begin
  236. _graphresult:=grerror;
  237. exit;
  238. end;
  239. pal[colorNum].red:=redValue;
  240. pal[colorNum].green:=greenValue;
  241. pal[colorNum].blue:=blueValue;
  242. end;
  243. procedure GetRGBPaletteWin32GUI(colorNum : integer;
  244. var redValue,greenvalue,bluevalue : integer);
  245. begin
  246. if directcolor or (colornum<0) or (colornum>=maxcolor) then
  247. begin
  248. _graphresult:=grerror;
  249. exit;
  250. end;
  251. redValue:=pal[colorNum].red;
  252. greenValue:=pal[colorNum].green;
  253. blueValue:=pal[colorNum].blue;
  254. end;
  255. procedure savestate;
  256. begin
  257. end;
  258. procedure restorestate;
  259. begin
  260. end;
  261. function WindowProc(Window: HWnd; AMessage, WParam,
  262. LParam: Longint): Longint; stdcall; export;
  263. var
  264. dc : hdc;
  265. ps : paintstruct;
  266. r : rect;
  267. begin
  268. WindowProc := 0;
  269. case AMessage of
  270. wm_keydown,
  271. wm_keyup,
  272. wm_char:
  273. if assigned(charmessagehandler) then
  274. WindowProc:=charmessagehandler(window,amessage,wparam,lparam);
  275. wm_paint:
  276. begin
  277. EnterCriticalSection(graphdrawing);
  278. graphrunning:=true;
  279. dc:=BeginPaint(Window,@ps);
  280. GetClientRect(Window,@r);
  281. if graphrunning then
  282. BitBlt(dc,0,0,maxx+1,maxy+1,bitmapdc,0,0,SRCCOPY);
  283. EndPaint(Window,ps);
  284. LeaveCriticalSection(graphdrawing);
  285. Exit;
  286. end;
  287. wm_create:
  288. begin
  289. EnterCriticalSection(graphdrawing);
  290. dc:=GetDC(window);
  291. bitmapdc:=CreateCompatibleDC(dc);
  292. savedscreen:=CreateCompatibleBitmap(dc,maxx+1,maxy+1);
  293. ReleaseDC(window,dc);
  294. oldbitmap:=SelectObject(bitmapdc,savedscreen);
  295. windc:=GetDC(window);
  296. LeaveCriticalSection(graphdrawing);
  297. end;
  298. wm_Destroy:
  299. begin
  300. EnterCriticalSection(graphdrawing);
  301. graphrunning:=false;
  302. ReleaseDC(mainwindow,windc);
  303. SelectObject(bitmapdc,oldbitmap);
  304. DeleteObject(savedscreen);
  305. DeleteDC(bitmapdc);
  306. LeaveCriticalSection(graphdrawing);
  307. PostQuitMessage(0);
  308. Exit;
  309. end
  310. else
  311. WindowProc := DefWindowProc(Window, AMessage, WParam, LParam);
  312. end;
  313. end;
  314. function WinRegister: Boolean;
  315. var
  316. WindowClass: WndClass;
  317. begin
  318. WindowClass.Style := cs_hRedraw or cs_vRedraw;
  319. WindowClass.lpfnWndProc := WndProc(@WindowProc);
  320. WindowClass.cbClsExtra := 0;
  321. WindowClass.cbWndExtra := 0;
  322. WindowClass.hInstance := system.MainInstance;
  323. WindowClass.hIcon := LoadIcon(0, idi_Application);
  324. WindowClass.hCursor := LoadCursor(0, idc_Arrow);
  325. WindowClass.hbrBackground := GetStockObject(BLACK_BRUSH);
  326. WindowClass.lpszMenuName := nil;
  327. WindowClass.lpszClassName := 'MyWindow';
  328. winregister:=RegisterClass(WindowClass) <> 0;
  329. end;
  330. { Create the Window Class }
  331. function WinCreate: HWnd;
  332. var
  333. hWindow: HWnd;
  334. begin
  335. hWindow := CreateWindow('MyWindow', 'Graph window application',
  336. ws_OverlappedWindow, 100, 100,
  337. maxx+20, maxy+40, 0, 0, system.MainInstance, nil);
  338. if hWindow <> 0 then begin
  339. ShowWindow(hWindow, SW_SHOW);
  340. UpdateWindow(hWindow);
  341. end;
  342. wincreate:=hWindow;
  343. end;
  344. function MessageHandleThread(p : pointer) : DWord;StdCall;
  345. var
  346. AMessage: Msg;
  347. begin
  348. if not WinRegister then begin
  349. MessageBox(0, 'Register failed', nil, mb_Ok);
  350. Exit;
  351. end;
  352. MainWindow := WinCreate;
  353. if longint(mainwindow) = 0 then begin
  354. MessageBox(0, 'WinCreate failed', nil, mb_Ok);
  355. Exit;
  356. end;
  357. while GetMessage(@AMessage, 0, 0, 0) do
  358. begin
  359. TranslateMessage(AMessage);
  360. DispatchMessage(AMessage);
  361. end;
  362. MessageHandleThread:=0;
  363. end;
  364. procedure InitWin32GUI640x480x16;
  365. begin
  366. getmem(pal,sizeof(RGBrec)*maxcolor);
  367. move(DefaultColors,pal^,sizeof(RGBrec)*maxcolor);
  368. { start graph subsystem }
  369. InitializeCriticalSection(graphdrawing);
  370. graphrunning:=false;
  371. MessageThreadHandle:=CreateThread(nil,0,@MessageHandleThread,
  372. nil,0,MessageThreadID);
  373. repeat until graphrunning;
  374. end;
  375. procedure CloseGraph;
  376. begin
  377. If not isgraphmode then
  378. begin
  379. _graphresult := grnoinitgraph;
  380. exit
  381. end;
  382. WaitForSingleObject(MessageThreadHandle,Infinite);
  383. CloseHandle(MessageThreadHandle);
  384. DeleteCriticalSection(graphdrawing);
  385. freemem(pal,sizeof(RGBrec)*maxcolor);
  386. end;
  387. {
  388. procedure line(x1,y1,x2,y2 : longint);
  389. var
  390. pen,oldpen : hpen;
  391. windc : hdc;
  392. begin
  393. if graphrunning then
  394. begin
  395. EnterCriticalSection(graphdrawing);
  396. pen:=CreatePen(PS_SOLID,4,RGB($ff,0,0));
  397. oldpen:=SelectObject(bitmapdc,pen);
  398. MoveToEx(bitmapdc,x1,y1,nil);
  399. LineTo(bitmapdc,x2,y2);
  400. SelectObject(bitmapdc,oldpen);
  401. windc:=GetDC(mainwindow);
  402. oldpen:=SelectObject(windc,pen);
  403. MoveToEx(windc,x1,y1,nil);
  404. LineTo(windc,x2,y2);
  405. SelectObject(windc,oldpen);
  406. ReleaseDC(mainwindow,windc);
  407. DeleteObject(pen);
  408. LeaveCriticalSection(graphdrawing);
  409. end;
  410. end;
  411. }
  412. { multipage support could be done by using more than one background bitmap }
  413. procedure SetVisualWin32GUI(page: word);
  414. begin
  415. end;
  416. procedure SetActiveWin32GUI(page: word);
  417. begin
  418. end;
  419. function queryadapterinfo : pmodeinfo;
  420. var
  421. mode: TModeInfo;
  422. begin
  423. SaveVideoState:=savestate;
  424. RestoreVideoState:=restorestate;
  425. QueryAdapterInfo := ModeList;
  426. { If the mode listing already exists... }
  427. { simply return it, without changing }
  428. { anything... }
  429. if assigned(ModeList) then
  430. exit;
  431. InitMode(mode);
  432. { now add all standard VGA modes... }
  433. mode.DriverNumber:= VGA;
  434. mode.HardwarePages:= 0;
  435. mode.ModeNumber:=0;
  436. mode.ModeName:='640 x 480 Win32GUI';
  437. mode.MaxColor := 16;
  438. mode.PaletteSize := mode.MaxColor;
  439. mode.DirectColor := FALSE;
  440. mode.MaxX := 639;
  441. mode.MaxY := 479;
  442. mode.DirectPutPixel:={$ifdef fpc}@{$endif}DirectPutPixel16Win32GUI;
  443. mode.PutPixel:={$ifdef fpc}@{$endif}PutPixel16Win32GUI;
  444. mode.GetPixel:={$ifdef fpc}@{$endif}GetPixel16Win32GUI;
  445. mode.HLine := {$ifdef fpc}@{$endif}HLine16Win32GUI;
  446. mode.SetRGBPalette := {$ifdef fpc}@{$endif}SetRGBPaletteWin32GUI;
  447. mode.GetRGBPalette := {$ifdef fpc}@{$endif}GetRGBPaletteWin32GUI;
  448. mode.SetVisualPage := {$ifdef fpc}@{$endif}SetVisualWin32GUI;
  449. mode.SetActivePage := {$ifdef fpc}@{$endif}SetActiveWin32GUI;
  450. mode.InitMode := {$ifdef fpc}@{$endif}InitWin32GUI640x480x16;
  451. mode.XAspect := 10000;
  452. mode.YAspect := 10000;
  453. AddMode(mode);
  454. end;
  455. {
  456. $Log$
  457. Revision 1.1 1999-11-03 20:23:02 florian
  458. + first release of win32 gui support
  459. }