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.

603 lines
17 KiB

  1. //---------------------------------------------------------------------
  2. // Main.cpp - tests various ways of drawing a nine grid hBitmap
  3. //---------------------------------------------------------------------
  4. #include "stdafx.h"
  5. #include "resource.h"
  6. #include "tmutils.h"
  7. #include "ninegrid.h"
  8. #include <atlbase.h>
  9. #include "stdio.h"
  10. //---------------------------------------------------------------------
  11. enum TESTNUM
  12. {
  13. TN_ORIG,
  14. TN_CACHE,
  15. TN_DIRECT,
  16. TN_TRUE,
  17. TN_SOLID,
  18. };
  19. //---------------------------------------------------------------------
  20. TESTNUM g_eTestNum = TN_CACHE;
  21. SIZINGTYPE g_eSizingType = ST_TILE;
  22. int iTestCount = 100;
  23. //---------------------------------------------------------------------
  24. #define MAX_LOADSTRING 100
  25. //---------------------------------------------------------------------
  26. HINSTANCE hInst;
  27. TCHAR szTitle[MAX_LOADSTRING];
  28. TCHAR szWindowClass[MAX_LOADSTRING];
  29. //---------------------------------------------------------------------
  30. ATOM MyRegisterClass(HINSTANCE hInstance);
  31. BOOL InitInstance(HINSTANCE, int);
  32. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  33. LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
  34. __int64 liFreq;
  35. __int64 liStart;
  36. __int64 liEnd;
  37. HWND hwnd;
  38. RECT rcButton = {50, 50, 150, 150};
  39. RECT rcCompare = {200, 50, 300, 150};
  40. RECT rcWindow = {50, 200, 450, 500};
  41. BITMAPINFO *g_pBitmapHdr = NULL;
  42. BYTE *g_pBits = NULL;
  43. int g_iImageHeight = 0;
  44. HBRUSH g_Brushes[5] = {0};
  45. HBITMAP g_hBitmap;
  46. HBITMAP g_hBitmap2;
  47. //---------------------------------------------------------------------
  48. __int64 TestButtonDrawing(HDC hdc, RECT *prc, int iCount)
  49. {
  50. QueryPerformanceCounter((LARGE_INTEGER*)&liStart);
  51. for (int i = 0; i < iCount; i++)
  52. {
  53. DrawFrameControl(hdc, prc, DFC_BUTTON, DFCS_BUTTONPUSH);
  54. }
  55. QueryPerformanceCounter((LARGE_INTEGER*)&liEnd);
  56. return (liEnd - liStart);
  57. }
  58. //---------------------------------------------------------------------
  59. __int64 TestWindowDrawing(HDC hdc, RECT *prc, int iCount)
  60. {
  61. int iCaptionHeight = GetSystemMetrics(SM_CYSIZE);
  62. int iBorderSize = 2; // GetSystemMetrics(SM_CXBORDER);
  63. COLORREF crBorder = GetSysColor(COLOR_ACTIVEBORDER);
  64. QueryPerformanceCounter((LARGE_INTEGER*)&liStart);
  65. for (int i = 0; i < iCount; i++)
  66. {
  67. RECT rcCaption = {prc->left, prc->top, prc->right, prc->top + iCaptionHeight};
  68. DrawCaption(hwnd, hdc, &rcCaption, DC_TEXT | DC_ICON | DC_ACTIVE | DC_GRADIENT);
  69. //---- draw rest of frame ----
  70. COLORREF crOld = SetBkColor(hdc, crBorder);
  71. //---- left border ----
  72. RECT rc = {prc->left, prc->top + iCaptionHeight, prc->left+iBorderSize, prc->bottom};
  73. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  74. //---- bottom border ----
  75. RECT rc2 = {prc->left, prc->bottom-iBorderSize, prc->right, prc->bottom};
  76. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc2, NULL, 0, NULL);
  77. //---- right border ----
  78. RECT rc3 = {prc->right-iBorderSize, prc->top + iCaptionHeight, prc->right, prc->bottom};
  79. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc3 , NULL, 0, NULL);
  80. //---- restore the color ----
  81. SetBkColor(hdc, crOld);
  82. }
  83. QueryPerformanceCounter((LARGE_INTEGER*)&liEnd);
  84. return (liEnd - liStart);
  85. }
  86. //---------------------------------------------------------------------
  87. HRESULT CreateBitmapFromBits(HDC hdc, BITMAPINFOHEADER *pBitmapHdr, BYTE *pDibBits,
  88. HBITMAP *phBitmap)
  89. {
  90. int iSetVal;
  91. HBITMAP hBitmap = NULL;
  92. HRESULT hr = S_OK;
  93. //---- create the actual bitmap ----
  94. hBitmap = CreateCompatibleBitmap(hdc, pBitmapHdr->biWidth, pBitmapHdr->biHeight);
  95. if (! hBitmap)
  96. {
  97. hr = GetLastError();
  98. goto exit;
  99. }
  100. iSetVal = SetDIBits(hdc, hBitmap, 0, pBitmapHdr->biHeight, pDibBits, (BITMAPINFO *)pBitmapHdr,
  101. DIB_RGB_COLORS);
  102. if (! iSetVal)
  103. {
  104. hr = GetLastError();
  105. goto exit;
  106. }
  107. *phBitmap = hBitmap;
  108. exit:
  109. if (FAILED(hr))
  110. {
  111. if (hBitmap)
  112. DeleteObject(hBitmap);
  113. }
  114. return hr;
  115. }
  116. //---------------------------------------------------------------------------
  117. __int64 TestOriginal(HDC hdc, RECT *prc, int iCount)
  118. {
  119. if (! g_pBitmapHdr)
  120. return 0;
  121. //---- create bitmap from dib ---
  122. int iImageWidth = g_pBitmapHdr->bmiHeader.biWidth;
  123. int iImageHeight = g_pBitmapHdr->bmiHeader.biHeight / 5;
  124. //---- fill out the NineGrid struct ----
  125. NGINFO nginfo = {sizeof(NGINFO)};
  126. nginfo.hdcDest = hdc;
  127. nginfo.rcClip = *prc;
  128. nginfo.hBitmap = g_hBitmap;
  129. nginfo.dwOptions = 0;
  130. SetRect(&nginfo.rcSrc, 0, iImageHeight, iImageWidth, 2*iImageHeight);
  131. nginfo.rcDest = *prc;
  132. nginfo.iSrcMargins[0] = 4;
  133. nginfo.iSrcMargins[1] = 4;
  134. nginfo.iSrcMargins[2] = 9;
  135. nginfo.iSrcMargins[3] = 9;
  136. nginfo.iDestMargins[0] = 4;
  137. nginfo.iDestMargins[1] = 4;
  138. nginfo.iDestMargins[2] = 9;
  139. nginfo.iDestMargins[3] = 9;
  140. nginfo.eImageSizing = g_eSizingType;
  141. QueryPerformanceCounter((LARGE_INTEGER*)&liStart);
  142. for (int i = 0; i < iCount; i++)
  143. {
  144. DrawNineGrid(&nginfo);
  145. }
  146. QueryPerformanceCounter((LARGE_INTEGER*)&liEnd);
  147. return (liEnd - liStart);
  148. }
  149. //---------------------------------------------------------------------------
  150. __int64 TestTrue(HDC hdc, RECT *prc, int iCount)
  151. {
  152. if (! g_pBitmapHdr)
  153. return 0;
  154. //---- create bitmap from dib ---
  155. int iImageWidth = g_pBitmapHdr->bmiHeader.biWidth;
  156. int iImageHeight = g_pBitmapHdr->bmiHeader.biHeight / 5;
  157. //---- fill out the NineGrid struct ----
  158. NGINFO nginfo = {sizeof(NGINFO)};
  159. nginfo.hdcDest = hdc;
  160. nginfo.rcClip = *prc;
  161. nginfo.hBitmap = g_hBitmap;
  162. nginfo.dwOptions = 0;
  163. SetRect(&nginfo.rcSrc, 0, iImageHeight, iImageWidth, 2*iImageHeight);
  164. nginfo.rcDest = *prc;
  165. nginfo.iDestMargins[0] = 0;
  166. nginfo.iDestMargins[1] = 0;
  167. nginfo.iDestMargins[2] = 0;
  168. nginfo.iDestMargins[3] = 0;
  169. nginfo.iSrcMargins[0] = 0;
  170. nginfo.iSrcMargins[1] = 0;
  171. nginfo.iSrcMargins[2] = 0;
  172. nginfo.iSrcMargins[3] = 0;
  173. nginfo.eImageSizing = ST_TRUESIZE;
  174. QueryPerformanceCounter((LARGE_INTEGER*)&liStart);
  175. for (int i = 0; i < iCount; i++)
  176. {
  177. DrawNineGrid(&nginfo);
  178. }
  179. QueryPerformanceCounter((LARGE_INTEGER*)&liEnd);
  180. return (liEnd - liStart);
  181. }
  182. //---------------------------------------------------------------------------
  183. __int64 TestSolid(HDC hdc, RECT *prc, int iCount)
  184. {
  185. if (! g_pBitmapHdr)
  186. return 0;
  187. //---- create bitmap from dib ---
  188. int iImageWidth = g_pBitmapHdr->bmiHeader.biWidth;
  189. int iImageHeight = g_pBitmapHdr->bmiHeader.biHeight / 5;
  190. //---- fill out the NineGrid struct ----
  191. NGINFO nginfo = {sizeof(NGINFO)};
  192. nginfo.hdcDest = hdc;
  193. nginfo.rcClip = *prc;
  194. nginfo.hBitmap = g_hBitmap;
  195. nginfo.dwOptions = NGO_SOLIDBORDER | NGO_SOLIDCONTENT;
  196. SetRect(&nginfo.rcSrc, 0, iImageHeight, iImageWidth, 2*iImageHeight);
  197. nginfo.rcDest = *prc;
  198. nginfo.iDestMargins[0] = 2;
  199. nginfo.iDestMargins[1] = 2;
  200. nginfo.iDestMargins[2] = 2;
  201. nginfo.iDestMargins[3] = 2;
  202. nginfo.iSrcMargins[0] = 2;
  203. nginfo.iSrcMargins[1] = 2;
  204. nginfo.iSrcMargins[2] = 2;
  205. nginfo.iSrcMargins[3] = 2;
  206. nginfo.eImageSizing = g_eSizingType;
  207. QueryPerformanceCounter((LARGE_INTEGER*)&liStart);
  208. for (int i = 0; i < iCount; i++)
  209. {
  210. DrawNineGrid(&nginfo);
  211. }
  212. QueryPerformanceCounter((LARGE_INTEGER*)&liEnd);
  213. return (liEnd - liStart);
  214. }
  215. //---------------------------------------------------------------------------
  216. __int64 TestCache(HDC hdc, RECT *prc, int iCount)
  217. {
  218. if (! g_pBitmapHdr)
  219. return 0;
  220. int iImageWidth = g_pBitmapHdr->bmiHeader.biWidth;
  221. int iImageHeight = g_pBitmapHdr->bmiHeader.biHeight / 5;
  222. //---- fill out the NineGrid struct ----
  223. NGINFO nginfo = {sizeof(NGINFO)};
  224. nginfo.hdcDest = hdc;
  225. nginfo.rcClip = *prc;
  226. nginfo.hBitmap = g_hBitmap;
  227. nginfo.dwOptions = NGO_CACHEBRUSHES;
  228. SetRect(&nginfo.rcSrc, 0, iImageHeight, iImageWidth, 2*iImageHeight);
  229. nginfo.rcDest = *prc;
  230. nginfo.iDestMargins[0] = 4;
  231. nginfo.iDestMargins[1] = 4;
  232. nginfo.iDestMargins[2] = 9;
  233. nginfo.iDestMargins[3] = 9;
  234. nginfo.iSrcMargins[0] = 4;
  235. nginfo.iSrcMargins[1] = 4;
  236. nginfo.iSrcMargins[2] = 9;
  237. nginfo.iSrcMargins[3] = 9;
  238. nginfo.pCachedBrushes = g_Brushes;
  239. nginfo.eImageSizing = g_eSizingType;
  240. QueryPerformanceCounter((LARGE_INTEGER*)&liStart);
  241. for (int i = 0; i < iCount; i++)
  242. {
  243. DrawNineGrid(&nginfo);
  244. }
  245. QueryPerformanceCounter((LARGE_INTEGER*)&liEnd);
  246. return (liEnd - liStart);
  247. }
  248. //---------------------------------------------------------------------------
  249. __int64 TestDirect(HDC hdc, RECT *prc, int iCount)
  250. {
  251. if (! g_pBitmapHdr)
  252. return 0;
  253. //---- create bitmap from dib ---
  254. int iImageWidth = g_pBitmapHdr->bmiHeader.biWidth;
  255. int iImageHeight = g_pBitmapHdr->bmiHeader.biHeight / 5;
  256. //---- fill out the NineGrid struct ----
  257. NGINFO nginfo = {sizeof(NGINFO)};
  258. nginfo.hdcDest = hdc;
  259. nginfo.rcClip = *prc;
  260. nginfo.hBitmap = g_hBitmap;
  261. nginfo.pBits = g_pBits;
  262. nginfo.pbmHdr = (BITMAPINFOHEADER *)g_pBitmapHdr;
  263. nginfo.dwOptions = NGO_DIRECTBITS;
  264. SetRect(&nginfo.rcSrc, 0, iImageHeight, iImageWidth, 2*iImageHeight);
  265. nginfo.rcDest = *prc;
  266. nginfo.iSrcMargins[0] = 4;
  267. nginfo.iSrcMargins[1] = 4;
  268. nginfo.iSrcMargins[2] = 9;
  269. nginfo.iSrcMargins[3] = 9;
  270. nginfo.iDestMargins[0] = 4;
  271. nginfo.iDestMargins[1] = 4;
  272. nginfo.iDestMargins[2] = 9;
  273. nginfo.iDestMargins[3] = 9;
  274. nginfo.eImageSizing = g_eSizingType;
  275. QueryPerformanceCounter((LARGE_INTEGER*)&liStart);
  276. for (int i = 0; i < iCount; i++)
  277. {
  278. DrawNineGrid(&nginfo);
  279. }
  280. QueryPerformanceCounter((LARGE_INTEGER*)&liEnd);
  281. return (liEnd - liStart);
  282. }
  283. //---------------------------------------------------------------------------
  284. void CompareTimes(LPCWSTR pszMsg, __int64 liBase, __int64 liCompare)
  285. {
  286. char buff[100];
  287. USES_CONVERSION;
  288. double flSecs = double(liCompare)/double(liFreq);
  289. double flRatio = double(liCompare)/double(liBase);
  290. sprintf(buff, "%.4f secs (%.2f x)", flSecs, flRatio);
  291. MessageBox(NULL, A2W(buff), pszMsg, MB_OK);
  292. }
  293. //---------------------------------------------------------------------
  294. HRESULT TestDrawing()
  295. {
  296. RECT rc = {0,0,100,100};
  297. __int64 liButton, liWindow, liCompare;
  298. //---- initialize timing stuff ----
  299. QueryPerformanceFrequency((LARGE_INTEGER*)&liFreq);
  300. //---- create a memory hBitmap to write to ----
  301. HDC hdc = CreateCompatibleDC(NULL);
  302. HBITMAP hbmp = CreateBitmap(100, 100, 1, 24, NULL);
  303. SelectObject(hdc, hbmp);
  304. //---- also, get our window's dc so we can verify drawing visually ----
  305. HDC hdcWindow = GetWindowDC(hwnd);
  306. //---- first, time the reference "button" ----
  307. liButton = TestButtonDrawing(hdc, &rc, iTestCount);
  308. CompareTimes(L"Reference Button", liButton, liButton);
  309. //---- then, time the reference "window" ----
  310. liWindow = TestWindowDrawing(hdc, &rc, iTestCount);
  311. CompareTimes(L"Reference Window", liWindow, liWindow);
  312. HRESULT hr = E_FAIL;
  313. CBitmapPixels pixels;
  314. int iWidth, iHeight, iBytesPerPixel, iBytesPerRow;
  315. //---- load hBitmap ----
  316. g_hBitmap = (HBITMAP)LoadImage(hInst, L"ButtonBlue.bmp", IMAGE_BITMAP, 0, 0,
  317. LR_LOADFROMFILE);
  318. if (! g_hBitmap)
  319. goto exit;
  320. //---- convert to DIBDATA ----
  321. hr = pixels.OpenBitmap(NULL, g_hBitmap, FALSE, (DWORD **)&g_pBits, &iWidth, &iHeight,
  322. &iBytesPerPixel, &iBytesPerRow);
  323. if (FAILED(hr))
  324. goto exit;
  325. g_pBitmapHdr = (BITMAPINFO *)pixels._hdrBitmap;
  326. pixels._hdrBitmap = NULL; // don't deallocate on exit
  327. CreateBitmapFromBits(hdc, (BITMAPINFOHEADER*) g_pBitmapHdr, g_pBits, &g_hBitmap2);
  328. switch (g_eTestNum)
  329. {
  330. case TN_ORIG:
  331. //---- time the original ninegrid ----
  332. liCompare = TestOriginal(hdc, &rc, iTestCount);
  333. CompareTimes(L"Original 9-grid", liButton, liCompare);
  334. break;
  335. case TN_CACHE:
  336. //---- time the cache ninegrid ----
  337. liCompare = TestCache(hdc, &rc, iTestCount);
  338. CompareTimes(L"Cache 9-grid", liButton, liCompare);
  339. break;
  340. case TN_TRUE:
  341. //---- time the TrueSize ninegrid ----
  342. liCompare = TestTrue(hdc, &rc, iTestCount);
  343. CompareTimes(L"TrueSize 9-grid", liButton, liCompare);
  344. break;
  345. case TN_DIRECT:
  346. //---- time the direct ninegrid ----
  347. liCompare = TestDirect(hdc, &rc, iTestCount);
  348. CompareTimes(L"Direct 9-grid", liButton, liCompare);
  349. break;
  350. case TN_SOLID:
  351. //---- time the solid border ninegrid ----
  352. liCompare = TestSolid(hdc, &rc, iTestCount);
  353. CompareTimes(L"Solid Border 9-grid", liButton, liCompare);
  354. break;
  355. }
  356. exit:
  357. return hr;
  358. }
  359. //---------------------------------------------------------------------
  360. int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  361. LPSTR lpCmdLine, int nCmdShow)
  362. {
  363. MSG msg;
  364. HACCEL hAccelTable;
  365. // Initialize global strings
  366. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  367. LoadString(hInstance, IDC_NINEGRID, szWindowClass, MAX_LOADSTRING);
  368. MyRegisterClass(hInstance);
  369. // Perform application initialization:
  370. if (!InitInstance (hInstance, nCmdShow))
  371. {
  372. return FALSE;
  373. }
  374. hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_NINEGRID);
  375. // Main message loop:
  376. while (GetMessage(&msg, NULL, 0, 0))
  377. {
  378. if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  379. {
  380. TranslateMessage(&msg);
  381. DispatchMessage(&msg);
  382. }
  383. }
  384. return msg.wParam;
  385. }
  386. //---------------------------------------------------------------------
  387. ATOM MyRegisterClass(HINSTANCE hInstance)
  388. {
  389. WNDCLASSEX wcex;
  390. wcex.cbSize = sizeof(WNDCLASSEX);
  391. wcex.style = CS_HREDRAW | CS_VREDRAW;
  392. wcex.lpfnWndProc = (WNDPROC)WndProc;
  393. wcex.cbClsExtra = 0;
  394. wcex.cbWndExtra = 0;
  395. wcex.hInstance = hInstance;
  396. wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_NINEGRID);
  397. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  398. wcex.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(150, 230, 230));
  399. wcex.lpszMenuName = (LPCWSTR)IDC_NINEGRID;
  400. wcex.lpszClassName = szWindowClass;
  401. wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
  402. return RegisterClassEx(&wcex);
  403. }
  404. //---------------------------------------------------------------------
  405. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  406. {
  407. hInst = hInstance; // Store instance handle in our global variable
  408. hwnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  409. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  410. if (!hwnd)
  411. {
  412. return FALSE;
  413. }
  414. TestDrawing();
  415. ShowWindow(hwnd, nCmdShow);
  416. UpdateWindow(hwnd);
  417. return TRUE;
  418. }
  419. //---------------------------------------------------------------------
  420. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  421. {
  422. int wmId, wmEvent;
  423. PAINTSTRUCT ps;
  424. HDC hdc;
  425. TCHAR szHello[MAX_LOADSTRING];
  426. LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
  427. switch (message)
  428. {
  429. case WM_COMMAND:
  430. wmId = LOWORD(wParam);
  431. wmEvent = HIWORD(wParam);
  432. // Parse the menu selections:
  433. switch (wmId)
  434. {
  435. case IDM_ABOUT:
  436. DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
  437. break;
  438. case IDM_EXIT:
  439. DestroyWindow(hWnd);
  440. break;
  441. default:
  442. return DefWindowProc(hWnd, message, wParam, lParam);
  443. }
  444. break;
  445. case WM_PAINT:
  446. hdc = BeginPaint(hWnd, &ps);
  447. // TODO: Add any drawing code here...
  448. RECT rt;
  449. GetClientRect(hWnd, &rt);
  450. //---- paint test results ----
  451. TestButtonDrawing(ps.hdc, &rcButton, 1);
  452. TestWindowDrawing(ps.hdc, &rcWindow, 1);
  453. switch (g_eTestNum)
  454. {
  455. case TN_ORIG:
  456. TestOriginal(ps.hdc, &rcCompare, 1);
  457. break;
  458. case TN_CACHE:
  459. TestCache(ps.hdc, &rcCompare, 1);
  460. break;
  461. case TN_DIRECT:
  462. TestDirect(ps.hdc, &rcCompare, 1);
  463. break;
  464. case TN_TRUE:
  465. TestTrue(ps.hdc, &rcCompare, 1);
  466. break;
  467. case TN_SOLID:
  468. TestSolid(ps.hdc, &rcCompare, 1);
  469. break;
  470. }
  471. EndPaint(hWnd, &ps);
  472. break;
  473. case WM_DESTROY:
  474. PostQuitMessage(0);
  475. break;
  476. default:
  477. return DefWindowProc(hWnd, message, wParam, lParam);
  478. }
  479. return 0;
  480. }
  481. //---------------------------------------------------------------------
  482. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  483. {
  484. switch (message)
  485. {
  486. case WM_INITDIALOG:
  487. return TRUE;
  488. case WM_COMMAND:
  489. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
  490. {
  491. EndDialog(hDlg, LOWORD(wParam));
  492. return TRUE;
  493. }
  494. break;
  495. }
  496. return FALSE;
  497. }
  498. //---------------------------------------------------------------------