PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Chap18/EmfView/EmfView.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 504 lines | 362 code | 124 blank | 18 comment | 40 complexity | f32b58186fc84ce9db793acbd885b1cb MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module EmfView;
  6. import core.memory;
  7. import core.runtime;
  8. import core.thread;
  9. import std.conv;
  10. import std.math;
  11. import std.range;
  12. import std.string;
  13. import std.utf;
  14. auto toUTF16z(S)(S s)
  15. {
  16. return toUTFz!(const(wchar)*)(s);
  17. }
  18. pragma(lib, "gdi32.lib");
  19. pragma(lib, "comdlg32.lib");
  20. import core.sys.windows.windef;
  21. import core.sys.windows.winuser;
  22. import core.sys.windows.wingdi;
  23. import core.sys.windows.winbase;
  24. import core.sys.windows.commdlg;
  25. import resource;
  26. string appName = "EmfView";
  27. string description = "Enhanced Metafile Viewer";
  28. HINSTANCE hinst;
  29. extern (Windows)
  30. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  31. {
  32. int result;
  33. try
  34. {
  35. Runtime.initialize();
  36. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  37. Runtime.terminate();
  38. }
  39. catch (Throwable o)
  40. {
  41. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  42. result = 0;
  43. }
  44. return result;
  45. }
  46. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  47. {
  48. hinst = hInstance;
  49. HACCEL hAccel;
  50. HWND hwnd;
  51. MSG msg;
  52. WNDCLASS wndclass;
  53. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  54. wndclass.lpfnWndProc = &WndProc;
  55. wndclass.cbClsExtra = 0;
  56. wndclass.cbWndExtra = 0;
  57. wndclass.hInstance = hInstance;
  58. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  59. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  60. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  61. wndclass.lpszMenuName = appName.toUTF16z;
  62. wndclass.lpszClassName = appName.toUTF16z;
  63. if (!RegisterClass(&wndclass))
  64. {
  65. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  66. return 0;
  67. }
  68. hwnd = CreateWindow(appName.toUTF16z, // window class name
  69. description.toUTF16z, // window caption
  70. WS_OVERLAPPEDWINDOW, // window style
  71. CW_USEDEFAULT, // initial x position
  72. CW_USEDEFAULT, // initial y position
  73. CW_USEDEFAULT, // initial x size
  74. CW_USEDEFAULT, // initial y size
  75. NULL, // parent window handle
  76. NULL, // window menu handle
  77. hInstance, // program instance handle
  78. NULL); // creation parameters
  79. ShowWindow(hwnd, iCmdShow);
  80. UpdateWindow(hwnd);
  81. hAccel = LoadAccelerators(hInstance, appName.toUTF16z);
  82. while (GetMessage(&msg, NULL, 0, 0))
  83. {
  84. if (!TranslateAccelerator(hwnd, hAccel, &msg))
  85. {
  86. TranslateMessage(&msg);
  87. DispatchMessage(&msg);
  88. }
  89. }
  90. return msg.wParam;
  91. }
  92. HPALETTE CreatePaletteFromMetaFile(HENHMETAFILE hemf)
  93. {
  94. HPALETTE hPalette;
  95. int iNum;
  96. LOGPALETTE* plp;
  97. if (!hemf)
  98. return NULL;
  99. if (0 == (iNum = GetEnhMetaFilePaletteEntries(hemf, 0, NULL)))
  100. return NULL;
  101. plp = cast(typeof(plp))GC.malloc(LOGPALETTE.sizeof + (iNum - 1) * PALETTEENTRY.sizeof);
  102. plp.palVersion = 0x0300;
  103. plp.palNumEntries = cast(ushort)iNum; // hmm
  104. GetEnhMetaFilePaletteEntries(hemf, iNum, plp.palPalEntry.ptr);
  105. hPalette = CreatePalette(plp);
  106. GC.free(plp);
  107. return hPalette;
  108. }
  109. __gshared wchar[MAX_PATH] szFileName = 0;
  110. __gshared wchar[MAX_PATH] szTitleName = 0;
  111. extern (Windows)
  112. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  113. {
  114. scope (failure) assert(0);
  115. static DOCINFO di = DOCINFO(DOCINFO.sizeof, "EmfView: Printing");
  116. static HENHMETAFILE hemf;
  117. static OPENFILENAME ofn;
  118. static PRINTDLG printdlg = PRINTDLG(PRINTDLG.sizeof);
  119. static string szFilter = "Enhanced Metafiles (*.EMF)\0*.emf\0All Files (*.*)\0*.*\0\0";
  120. BOOL bSuccess;
  121. ENHMETAHEADER header;
  122. HDC hdc, hdcPrn;
  123. HENHMETAFILE hemfCopy;
  124. HMENU hMenu;
  125. HPALETTE hPalette;
  126. int i, iLength, iEnable;
  127. PAINTSTRUCT ps;
  128. RECT rect;
  129. PTSTR pBuffer;
  130. switch (message)
  131. {
  132. case WM_CREATE:
  133. // Initialize OPENFILENAME structure
  134. ofn.hwndOwner = hwnd;
  135. ofn.hInstance = NULL;
  136. ofn.lpstrFilter = szFilter.toUTF16z;
  137. ofn.lpstrCustomFilter = NULL;
  138. ofn.nMaxCustFilter = 0;
  139. ofn.nFilterIndex = 0;
  140. ofn.lpstrFile = szFileName.ptr;
  141. ofn.nMaxFile = MAX_PATH;
  142. ofn.lpstrFileTitle = szTitleName.ptr;
  143. ofn.nMaxFileTitle = MAX_PATH;
  144. ofn.lpstrInitialDir = NULL;
  145. ofn.lpstrTitle = NULL;
  146. ofn.Flags = 0;
  147. ofn.nFileOffset = 0;
  148. ofn.nFileExtension = 0;
  149. ofn.lpstrDefExt = "emf";
  150. ofn.lCustData = 0;
  151. ofn.lpfnHook = NULL;
  152. ofn.lpTemplateName = NULL;
  153. return 0;
  154. case WM_INITMENUPOPUP:
  155. hMenu = GetMenu(hwnd);
  156. iEnable = hemf ? MF_ENABLED : MF_GRAYED;
  157. EnableMenuItem(hMenu, IDM_FILE_SAVE_AS, iEnable);
  158. EnableMenuItem(hMenu, IDM_FILE_PRINT, iEnable);
  159. EnableMenuItem(hMenu, IDM_FILE_PROPERTIES, iEnable);
  160. EnableMenuItem(hMenu, IDM_EDIT_CUT, iEnable);
  161. EnableMenuItem(hMenu, IDM_EDIT_COPY, iEnable);
  162. EnableMenuItem(hMenu, IDM_EDIT_DELETE, iEnable);
  163. EnableMenuItem(hMenu, IDM_EDIT_PASTE,
  164. IsClipboardFormatAvailable(CF_ENHMETAFILE) ?
  165. MF_ENABLED : MF_GRAYED);
  166. return 0;
  167. case WM_COMMAND:
  168. switch (LOWORD(wParam))
  169. {
  170. case IDM_FILE_OPEN:
  171. // Show the File Open dialog box
  172. ofn.Flags = 0;
  173. if (!GetOpenFileName(&ofn))
  174. return 0;
  175. // If there's an existing EMF, get rid of it.
  176. if (hemf)
  177. {
  178. DeleteEnhMetaFile(hemf);
  179. hemf = NULL;
  180. }
  181. // Load the EMF into memory
  182. SetCursor(LoadCursor(NULL, IDC_WAIT));
  183. ShowCursor(TRUE);
  184. hemf = GetEnhMetaFile(szFileName.ptr);
  185. ShowCursor(FALSE);
  186. SetCursor(LoadCursor(NULL, IDC_ARROW));
  187. // Invalidate the client area for later update
  188. InvalidateRect(hwnd, NULL, TRUE);
  189. if (hemf == NULL)
  190. {
  191. MessageBox(hwnd, "Cannot load metafile",
  192. appName.toUTF16z, MB_ICONEXCLAMATION | MB_OK);
  193. }
  194. return 0;
  195. case IDM_FILE_SAVE_AS:
  196. if (!hemf)
  197. return 0;
  198. // Show the File Save dialog box
  199. ofn.Flags = OFN_OVERWRITEPROMPT;
  200. if (!GetSaveFileName(&ofn))
  201. return 0;
  202. // Save the EMF to disk file
  203. SetCursor(LoadCursor(NULL, IDC_WAIT));
  204. ShowCursor(TRUE);
  205. hemfCopy = CopyEnhMetaFile(hemf, szFileName.ptr);
  206. ShowCursor(FALSE);
  207. SetCursor(LoadCursor(NULL, IDC_ARROW));
  208. if (hemfCopy)
  209. {
  210. DeleteEnhMetaFile(hemf);
  211. hemf = hemfCopy;
  212. }
  213. else
  214. MessageBox(hwnd, "Cannot save metafile",
  215. appName.toUTF16z, MB_ICONEXCLAMATION | MB_OK);
  216. return 0;
  217. case IDM_FILE_PRINT:
  218. // Show the Print dialog box and get printer DC
  219. printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION;
  220. if (!PrintDlg(&printdlg))
  221. return 0;
  222. if (NULL == (hdcPrn = printdlg.hDC))
  223. {
  224. MessageBox(hwnd, "Cannot obtain printer DC",
  225. appName.toUTF16z, MB_ICONEXCLAMATION | MB_OK);
  226. return 0;
  227. }
  228. // Get size of printable area of page
  229. rect.left = 0;
  230. rect.right = GetDeviceCaps(hdcPrn, HORZRES);
  231. rect.top = 0;
  232. rect.bottom = GetDeviceCaps(hdcPrn, VERTRES);
  233. bSuccess = FALSE;
  234. // Play the EMF to the printer
  235. SetCursor(LoadCursor(NULL, IDC_WAIT));
  236. ShowCursor(TRUE);
  237. if ((StartDoc(hdcPrn, &di) > 0) && (StartPage(hdcPrn) > 0))
  238. {
  239. PlayEnhMetaFile(hdcPrn, hemf, &rect);
  240. if (EndPage(hdcPrn) > 0)
  241. {
  242. bSuccess = TRUE;
  243. EndDoc(hdcPrn);
  244. }
  245. }
  246. ShowCursor(FALSE);
  247. SetCursor(LoadCursor(NULL, IDC_ARROW));
  248. DeleteDC(hdcPrn);
  249. if (!bSuccess)
  250. MessageBox(hwnd, "Could not print metafile",
  251. appName.toUTF16z, MB_ICONEXCLAMATION | MB_OK);
  252. return 0;
  253. case IDM_FILE_PROPERTIES:
  254. if (!hemf)
  255. return 0;
  256. iLength = GetEnhMetaFileDescription(hemf, 0, NULL);
  257. pBuffer = cast(typeof(pBuffer))GC.malloc((iLength + 256) * TCHAR.sizeof);
  258. GetEnhMetaFileHeader(hemf, ENHMETAHEADER.sizeof, &header);
  259. // Format header file information
  260. i = wsprintf(pBuffer,
  261. "Bounds = (%i, %i) to (%i, %i) pixels\n",
  262. header.rclBounds.left, header.rclBounds.top,
  263. header.rclBounds.right, header.rclBounds.bottom);
  264. i += wsprintf(pBuffer + i,
  265. "Frame = (%i, %i) to (%i, %i) mms\n",
  266. header.rclFrame.left, header.rclFrame.top,
  267. header.rclFrame.right, header.rclFrame.bottom);
  268. i += wsprintf(pBuffer + i,
  269. "Resolution = (%i, %i) pixels = (%i, %i) mms\n",
  270. header.szlDevice.cx, header.szlDevice.cy,
  271. header.szlMillimeters.cx,
  272. header.szlMillimeters.cy);
  273. i += wsprintf(pBuffer + i,
  274. "Size = %i, Records = %i, Handles = %i, Palette entries = %i\n",
  275. header.nBytes, header.nRecords,
  276. header.nHandles, header.nPalEntries);
  277. // Include the metafile description, if present
  278. if (iLength)
  279. {
  280. i += wsprintf(pBuffer + i, "Description = ");
  281. GetEnhMetaFileDescription(hemf, iLength, pBuffer + i);
  282. pBuffer [lstrlen(pBuffer)] = '\t';
  283. }
  284. MessageBox(hwnd, pBuffer, "Metafile Properties", MB_OK);
  285. GC.free(pBuffer);
  286. return 0;
  287. case IDM_EDIT_COPY:
  288. case IDM_EDIT_CUT:
  289. if (!hemf)
  290. return 0;
  291. // Transfer metafile copy to the clipboard
  292. hemfCopy = CopyEnhMetaFile(hemf, NULL);
  293. OpenClipboard(hwnd);
  294. EmptyClipboard();
  295. SetClipboardData(CF_ENHMETAFILE, hemfCopy);
  296. CloseClipboard();
  297. if (LOWORD(wParam) == IDM_EDIT_COPY)
  298. return 0;
  299. goto case;
  300. // fall through if IDM_EDIT_CUT
  301. case IDM_EDIT_DELETE:
  302. if (hemf)
  303. {
  304. DeleteEnhMetaFile(hemf);
  305. hemf = NULL;
  306. InvalidateRect(hwnd, NULL, TRUE);
  307. }
  308. return 0;
  309. case IDM_EDIT_PASTE:
  310. OpenClipboard(hwnd);
  311. hemfCopy = GetClipboardData(CF_ENHMETAFILE);
  312. CloseClipboard();
  313. if (hemfCopy && hemf)
  314. {
  315. DeleteEnhMetaFile(hemf);
  316. hemf = NULL;
  317. }
  318. hemf = CopyEnhMetaFile(hemfCopy, NULL);
  319. InvalidateRect(hwnd, NULL, TRUE);
  320. return 0;
  321. case IDM_APP_ABOUT:
  322. MessageBox(hwnd, "Enhanced Metafile Viewer\n(c) Charles Petzold, 1998",
  323. appName.toUTF16z, MB_OK);
  324. return 0;
  325. case IDM_APP_EXIT:
  326. SendMessage(hwnd, WM_CLOSE, 0, 0L);
  327. return 0;
  328. default:
  329. }
  330. break;
  331. case WM_PAINT:
  332. hdc = BeginPaint(hwnd, &ps);
  333. if (hemf)
  334. {
  335. hPalette = CreatePaletteFromMetaFile(hemf);
  336. if (hPalette !is null)
  337. {
  338. SelectPalette(hdc, hPalette, FALSE);
  339. RealizePalette(hdc);
  340. }
  341. GetClientRect(hwnd, &rect);
  342. PlayEnhMetaFile(hdc, hemf, &rect);
  343. if (hPalette)
  344. DeleteObject(hPalette);
  345. }
  346. EndPaint(hwnd, &ps);
  347. return 0;
  348. case WM_QUERYNEWPALETTE:
  349. hPalette = CreatePaletteFromMetaFile(hemf);
  350. if (!hemf || hPalette is null)
  351. return FALSE;
  352. hdc = GetDC(hwnd);
  353. SelectPalette(hdc, hPalette, FALSE);
  354. RealizePalette(hdc);
  355. InvalidateRect(hwnd, NULL, FALSE);
  356. DeleteObject(hPalette);
  357. ReleaseDC(hwnd, hdc);
  358. return TRUE;
  359. case WM_PALETTECHANGED:
  360. if (cast(HWND)wParam == hwnd)
  361. break;
  362. hPalette = CreatePaletteFromMetaFile(hemf);
  363. if (!hemf || hPalette is null)
  364. break;
  365. hdc = GetDC(hwnd);
  366. SelectPalette(hdc, hPalette, FALSE);
  367. RealizePalette(hdc);
  368. UpdateColors(hdc);
  369. DeleteObject(hPalette);
  370. ReleaseDC(hwnd, hdc);
  371. break;
  372. case WM_DESTROY:
  373. if (hemf)
  374. DeleteEnhMetaFile(hemf);
  375. PostQuitMessage(0);
  376. return 0;
  377. default:
  378. }
  379. return DefWindowProc(hwnd, message, wParam, lParam);
  380. }