Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
11 KiB

  1. /*~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
  2. **
  3. ** FILE: POV.CPP
  4. ** DATE: 3/31/97
  5. ** PROJ: ATLAS
  6. ** PROG: JKH
  7. ** COMMENTS:
  8. **
  9. ** DESCRIPTION: Window class for a 360 degree Point Of View control
  10. **
  11. **
  12. **
  13. ** NOTE: There are some issues with using extern "C" in this file.
  14. ** If you don't understand why they are there, you're not
  15. ** alone. For now, and probably for a while they will be
  16. ** here though, because I can't get this file and others
  17. ** that use these services to compile without them.
  18. ** Unfortunately the dynamics of this project don't really
  19. ** afford me the time at present to figure this out.
  20. ** TODO: figure this out
  21. **
  22. ** HISTORY:
  23. ** DATE WHO WHAT
  24. ** ---- --- ----
  25. ** 3/31/97 a-kirkh Wrote it.
  26. **
  27. **
  28. **
  29. **
  30. ** Copyright (C) Microsoft 1997. All Rights Reserved.
  31. **
  32. **~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=*/
  33. #pragma pack (8)
  34. #include "POV.H" //This module's stuff.
  35. #include "resource.h"
  36. extern HWND hPOVWnd = NULL;
  37. static HINSTANCE ghResInst;
  38. static LPRECT prctOldRegionBox;
  39. static LPRECT prctNewRegionBox;
  40. double degrees = -1;
  41. void SetDegrees(int dDegrees)
  42. {
  43. degrees = (double)dDegrees;
  44. PostMessage(hPOVWnd, PM_MYJOYPOSCHANGED, 0, 0);
  45. }
  46. extern "C"{
  47. void SetResourceInstance(HINSTANCE hInstance)
  48. {
  49. ghResInst = hInstance;
  50. }
  51. HINSTANCE GetResourceInstance()
  52. {
  53. return(ghResInst);
  54. }
  55. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  56. //
  57. // FUNCTION : POVWndProc
  58. // REMARKS : The callback function for the POVHat Window.
  59. //
  60. // PARAMS : The usual callback funcs for message handling
  61. //
  62. // RETURNS : LRESULT - Depends on the message
  63. // CALLS :
  64. // NOTES :
  65. // WM_PAINT - Just calls DrawControl
  66. //
  67. // PM_MYJOYPOSCHANGED - This is a private (WM_USER) message that is
  68. // called whenever a change in the POV hat occurs.
  69. //
  70. RECT rClient;
  71. HDC hDC;
  72. PAINTSTRUCT ps;
  73. LONG cxClient, cyClient;
  74. HRGN hRegion;
  75. HBITMAP hPOVHubBitmap = NULL;
  76. LRESULT CALLBACK POVWndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  77. {
  78. switch( iMsg ) {
  79. case WM_CREATE:
  80. hPOVWnd = hWnd;
  81. return(0);
  82. case WM_PAINT:
  83. {
  84. hDC = BeginPaint(hWnd, &ps);
  85. DrawControl(hWnd, hDC);
  86. EndPaint(hWnd, &ps);
  87. }
  88. return(0);
  89. case PM_MYJOYPOSCHANGED:
  90. {
  91. degrees /= 100; // if angle == 180, degrees comes in as 18000
  92. GetCurrentArrowRegion(&hRegion);
  93. if( hRegion ) {
  94. GetRgnBox(hRegion, prctNewRegionBox);
  95. InvalidateRect(hWnd, prctOldRegionBox, TRUE);
  96. InvalidateRect(hWnd, prctNewRegionBox, TRUE);
  97. DeleteObject(hRegion);
  98. }
  99. }
  100. default:
  101. return(DefWindowProc(hWnd, iMsg,wParam, lParam));
  102. }
  103. }
  104. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  105. //
  106. // FUNCTION : DrawControl
  107. // REMARKS : Function called by WM_PAINT that draws the POV hat control
  108. // PARAMS : HWND - Control's window handle
  109. // HDC - Control's dc created with BeginPaint
  110. // RETURNS : void
  111. // CALLS : GetCurrentArrowRegion
  112. // NOTES :
  113. // 1) So that stuff can be centered.
  114. // 2) Bitblt that hub thingy in the middle.
  115. // 3) Disallow any problems with aspect ratio.
  116. // 4) Draw the circle, should be round because of 3.
  117. // 5) a.Get the coordinates of the rotated arrow.
  118. // b.Paint the region.
  119. // c.Get the bounding rectangle of the region so we
  120. // can invalidate it next time around.
  121. void DrawControl(HWND hWnd, HDC hDC)
  122. {
  123. assert(hWnd);
  124. assert(hDC);
  125. // 1) Get client size information
  126. SetMapMode(hDC, MM_TEXT);
  127. GetClientRect(hWnd, &rClient);
  128. cxClient = rClient.right - rClient.left;
  129. cyClient = -(rClient.bottom - rClient.top);
  130. // 2) Load the hub bitmap and display it
  131. hPOVHubBitmap = LoadBitmap((HMODULE)ghResInst, MAKEINTRESOURCE(IDB_POVHUB));
  132. assert(hPOVHubBitmap);
  133. DrawBitmap(hDC, hPOVHubBitmap, cxClient/2 - 8, -cyClient/2 - 8);
  134. DeleteObject(hPOVHubBitmap);
  135. // 3) Setup the window to use symmetrical units on a 1000 X 1000 cartesian grid
  136. SetMapMode(hDC, MM_ISOTROPIC);
  137. SetWindowExtEx(hDC, 1000, 1000, NULL);
  138. SetViewportExtEx(hDC, cxClient / 2, cyClient / 2, NULL);
  139. SetViewportOrgEx(hDC, cxClient / 2, -cyClient / 2, NULL);
  140. // 4) Draw the circle upon which the arrow seems to rotate
  141. SelectObject(hDC, (HBRUSH)GetStockObject(NULL_BRUSH));
  142. HPEN hPen = CreatePen( PS_SOLID, 1, CIRCLECOLOR);
  143. //PREFIX: dereferencing NULL pointer 'hPen'
  144. //Millen Bug#129156, manbug 29347
  145. if( hPen != NULL ) {
  146. HPEN hPenOld = (HPEN)SelectObject(hDC, hPen);
  147. Ellipse(hDC, -CIRCLERADIUS, CIRCLERADIUS, CIRCLERADIUS, -CIRCLERADIUS);
  148. SelectObject(hDC, hPenOld);
  149. DeleteObject(hPen);
  150. }
  151. // 5) Paint the Arrow at the correct angle if POV active
  152. if( degrees >= 0 ) {
  153. HBRUSH hBrush = CreateSolidBrush( CIRCLECOLOR );
  154. if( !hBrush ) {
  155. return;
  156. }
  157. HBRUSH hBrushOld = (HBRUSH)SelectObject(hDC, hBrush);
  158. assert(hBrushOld);
  159. GetCurrentArrowRegion(&hRegion);
  160. if( !hRegion ) {
  161. return;
  162. }
  163. PaintRgn(hDC, hRegion);
  164. // GetRgnBox returns zero if it fails...
  165. GetRgnBox(hRegion, prctOldRegionBox);
  166. SelectObject(hDC, hBrushOld);
  167. DeleteObject(hBrush);
  168. DeleteObject(hRegion);
  169. }
  170. }
  171. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  172. //
  173. // FUNCTION : RegisterPOVClass
  174. // REMARKS : Registers the POV Hat window.
  175. //
  176. // PARAMS : hInstance - Used for the call to RegisterClassEx
  177. //
  178. // RETURNS : TRUE - if successfully registered
  179. // FALSE - failed to register
  180. // CALLS : RegisterClassEx
  181. // NOTES :
  182. //
  183. extern BOOL RegisterPOVClass(HINSTANCE hInstance)
  184. {
  185. WNDCLASSEX POVWndClass;
  186. POVWndClass.cbSize = sizeof(POVWndClass);
  187. POVWndClass.style = CS_HREDRAW | CS_VREDRAW;
  188. POVWndClass.lpfnWndProc = POVWndProc;
  189. POVWndClass.cbClsExtra = 0;
  190. POVWndClass.cbWndExtra = 0;
  191. POVWndClass.hInstance = hInstance;
  192. POVWndClass.hIcon = NULL;
  193. POVWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  194. POVWndClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
  195. POVWndClass.lpszMenuName = NULL;
  196. POVWndClass.lpszClassName = "POVHAT";
  197. POVWndClass.hIconSm = NULL;
  198. if( RegisterClassEx( &POVWndClass ) == 0 )
  199. return(FALSE);
  200. return(TRUE);
  201. }
  202. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  203. //
  204. // FUNCTION : DrawBitmap
  205. // REMARKS : Copied verbatim from Petzold (WIN95 pg 190)
  206. // PARAMS : HDC - dc for drawing
  207. // HBITMAP - bitmap to draw
  208. // int xstart, ystart - where to place the bitmap
  209. //
  210. // RETURNS : void
  211. // CALLS :
  212. // NOTES :
  213. //
  214. void DrawBitmap(HDC hDC, HBITMAP hBitmap, int xStart, int yStart)
  215. {
  216. BITMAP bm;
  217. HDC hdcMem;
  218. POINT ptSize, ptOrg;
  219. hdcMem = CreateCompatibleDC(hDC);
  220. // Found by prefix: Millen Bug129155. manbugs 29339
  221. // If CreateCompatibleDC fails, we should'nt proceed.
  222. if( hdcMem == NULL ) return;
  223. SelectObject(hdcMem, hBitmap);
  224. SetMapMode(hdcMem,GetMapMode(hDC));
  225. GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bm);
  226. ptSize.x = bm.bmWidth;
  227. ptSize.y = bm.bmHeight;
  228. DPtoLP(hDC, &ptSize, 1);
  229. ptOrg.x = 0;
  230. ptOrg.y = 0;
  231. DPtoLP(hdcMem, &ptOrg, 1);
  232. BitBlt(hDC, xStart, yStart, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y, SRCAND);
  233. DeleteDC(hdcMem);
  234. }
  235. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  236. //
  237. // FUNCTION : GetCurrentArrowRegion
  238. // REMARKS : Rotates and translate a set of vertices that represents
  239. // the POV hat arrow
  240. //
  241. // PARAMS : HRGN - The region to be rotated
  242. //
  243. // RETURNS : BOOL
  244. // CALLS : GETXCOORD, GETYCOORD (POV.H)
  245. // NOTES :
  246. //
  247. void GetCurrentArrowRegion(HRGN* hRegion)
  248. {
  249. POINT aptPoints[8];
  250. VERTICEINFO aptVInfo[8] = { XARROWPOINT ,YARROWPOINT ,
  251. XARROWRIGHTOUT ,YARROWRIGHTOUT ,
  252. XARROWRIGHTIN ,YARROWRIGHTIN ,
  253. XARROWRIGHTBOTTOM,YARROWRIGHTBOTTOM,
  254. XARROWLEFTBOTTOM ,YARROWLEFTBOTTOM ,
  255. XARROWLEFTIN ,YARROWLEFTIN ,
  256. XARROWLEFTOUT ,YARROWLEFTOUT ,
  257. XARROWPOINT ,YARROWPOINT};
  258. aptPoints[0].x = GETXCOORD(aptVInfo[0].y, aptVInfo[0].x, degrees);
  259. aptPoints[0].y = GETYCOORD(aptVInfo[0].y, aptVInfo[0].x, degrees);
  260. aptPoints[1].x = GETXCOORD(aptVInfo[1].y, aptVInfo[1].x, degrees);
  261. aptPoints[1].y = GETYCOORD(aptVInfo[1].y, aptVInfo[1].x, degrees);
  262. aptPoints[2].x = GETXCOORD(aptVInfo[2].y, aptVInfo[2].x, degrees);
  263. aptPoints[2].y = GETYCOORD(aptVInfo[2].y, aptVInfo[2].x, degrees);
  264. aptPoints[3].x = GETXCOORD(aptVInfo[3].y, aptVInfo[3].x, degrees);
  265. aptPoints[3].y = GETYCOORD(aptVInfo[3].y, aptVInfo[3].x, degrees);
  266. aptPoints[4].x = GETXCOORD(aptVInfo[4].y, aptVInfo[4].x, degrees);
  267. aptPoints[4].y = GETYCOORD(aptVInfo[4].y, aptVInfo[4].x, degrees);
  268. aptPoints[5].x = GETXCOORD(aptVInfo[5].y, aptVInfo[5].x, degrees);
  269. aptPoints[5].y = GETYCOORD(aptVInfo[5].y, aptVInfo[5].x, degrees);
  270. aptPoints[6].x = GETXCOORD(aptVInfo[6].y, aptVInfo[6].x, degrees);
  271. aptPoints[6].y = GETYCOORD(aptVInfo[6].y, aptVInfo[6].x, degrees);
  272. aptPoints[7].x = GETXCOORD(aptVInfo[7].y, aptVInfo[7].x, degrees);
  273. aptPoints[7].y = GETYCOORD(aptVInfo[7].y, aptVInfo[7].x, degrees);
  274. *hRegion = CreatePolygonRgn(aptPoints, 8, WINDING);
  275. }
  276. }