PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Chap13/DevCaps2/DevCaps2.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 467 lines | 385 code | 73 blank | 9 comment | 23 complexity | 18d93994f1a3ca293f83e8c281d06fcb MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module DevCaps2;
  6. /+
  7. + Note: I still haven't been able to get the device name out of a menu handle,
  8. + it throws on access. If you know of a workaround please submit a fix. Thanks.
  9. +/
  10. import core.memory;
  11. import core.runtime;
  12. import core.thread;
  13. import std.conv;
  14. import std.math;
  15. import std.range;
  16. import std.string;
  17. import std.stdio;
  18. import std.utf : count, toUTFz;
  19. auto toUTF16z(S)(S s)
  20. {
  21. return toUTFz!(const(wchar)*)(s);
  22. }
  23. pragma(lib, "gdi32.lib");
  24. pragma(lib, "winspool.lib");
  25. import core.sys.windows.windef;
  26. import core.sys.windows.winuser;
  27. import core.sys.windows.wingdi;
  28. import core.sys.windows.winbase;
  29. import core.sys.windows.winspool;
  30. import resource;
  31. string appName = "DevCaps2";
  32. string description = "Device Capabilities 2";
  33. enum ID_TIMER = 1;
  34. HINSTANCE hinst;
  35. struct BITS
  36. {
  37. int iMask;
  38. string description;
  39. }
  40. enum IDM_DEVMODE = 1000;
  41. extern (Windows)
  42. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  43. {
  44. int result;
  45. try
  46. {
  47. Runtime.initialize();
  48. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  49. Runtime.terminate();
  50. }
  51. catch (Throwable o)
  52. {
  53. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  54. result = 0;
  55. }
  56. return result;
  57. }
  58. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  59. {
  60. hinst = hInstance;
  61. HWND hwnd;
  62. MSG msg;
  63. WNDCLASS wndclass;
  64. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  65. wndclass.lpfnWndProc = &WndProc;
  66. wndclass.cbClsExtra = 0;
  67. wndclass.cbWndExtra = 0;
  68. wndclass.hInstance = hInstance;
  69. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  70. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  71. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  72. wndclass.lpszMenuName = appName.toUTF16z;
  73. wndclass.lpszClassName = appName.toUTF16z;
  74. if (!RegisterClass(&wndclass))
  75. {
  76. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  77. return 0;
  78. }
  79. hwnd = CreateWindow(appName.toUTF16z, // window class name
  80. description.toUTF16z, // window caption
  81. WS_OVERLAPPEDWINDOW, // window style
  82. CW_USEDEFAULT, // initial x position
  83. CW_USEDEFAULT, // initial y position
  84. CW_USEDEFAULT, // initial x size
  85. CW_USEDEFAULT, // initial y size
  86. NULL, // parent window handle
  87. NULL, // window menu handle
  88. hInstance, // program instance handle
  89. NULL); // creation parameters
  90. ShowWindow(hwnd, iCmdShow);
  91. UpdateWindow(hwnd);
  92. while (GetMessage(&msg, NULL, 0, 0))
  93. {
  94. TranslateMessage(&msg);
  95. DispatchMessage(&msg);
  96. }
  97. return msg.wParam;
  98. }
  99. extern (Windows)
  100. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  101. {
  102. scope (failure) assert(0);
  103. wchar[32] szDevice;
  104. string szWindowText;
  105. static int cxChar, cyChar, nCurrentDevice = IDM_SCREEN, nCurrentInfo = IDM_BASIC;
  106. static DWORD dwNeeded, dwReturned;
  107. static PRINTER_INFO_4* pinfo4;
  108. static PRINTER_INFO_5* pinfo5;
  109. DWORD i;
  110. HDC hdc, hdcInfo;
  111. HMENU hMenu;
  112. HANDLE hPrint;
  113. PAINTSTRUCT ps;
  114. TEXTMETRIC tm;
  115. switch (message)
  116. {
  117. case WM_CREATE:
  118. hdc = GetDC(hwnd);
  119. SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  120. GetTextMetrics(hdc, &tm);
  121. cxChar = tm.tmAveCharWidth;
  122. cyChar = tm.tmHeight + tm.tmExternalLeading;
  123. ReleaseDC(hwnd, hdc);
  124. goto case WM_SETTINGCHANGE;
  125. case WM_SETTINGCHANGE:
  126. hMenu = GetSubMenu(GetMenu(hwnd), 0);
  127. while (GetMenuItemCount(hMenu) > 1)
  128. DeleteMenu(hMenu, 1, MF_BYPOSITION);
  129. if (GetVersion() & 0x80000000) // Windows 98
  130. {
  131. EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &dwNeeded, &dwReturned);
  132. pinfo5 = cast(typeof(pinfo5))GC.malloc(dwNeeded);
  133. EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, cast(PBYTE)pinfo5, dwNeeded, &dwNeeded, &dwReturned);
  134. for (i = 0; i < dwReturned; i++)
  135. {
  136. AppendMenu(hMenu, (i + 1) % 16 ? 0 : MF_MENUBARBREAK, i + 1, pinfo5[i].pPrinterName);
  137. }
  138. GC.free(pinfo5);
  139. }
  140. else // Windows NT
  141. {
  142. EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwReturned);
  143. pinfo4 = cast(typeof(pinfo4))GC.malloc(dwNeeded);
  144. EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, cast(PBYTE)pinfo4, dwNeeded, &dwNeeded, &dwReturned);
  145. for (i = 0; i < dwReturned; i++)
  146. {
  147. AppendMenu(hMenu, (i + 1) % 16 ? 0 : MF_MENUBARBREAK, i + 1, pinfo4[i].pPrinterName);
  148. }
  149. GC.free(pinfo4);
  150. }
  151. AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
  152. AppendMenu(hMenu, 0, IDM_DEVMODE, "Properties");
  153. wParam = IDM_SCREEN;
  154. goto case WM_COMMAND;
  155. case WM_COMMAND:
  156. hMenu = GetMenu(hwnd);
  157. if (LOWORD(wParam) == IDM_SCREEN || // IDM_SCREEN & Printers
  158. LOWORD(wParam) < IDM_DEVMODE)
  159. {
  160. CheckMenuItem(hMenu, nCurrentDevice, MF_UNCHECKED);
  161. nCurrentDevice = LOWORD(wParam);
  162. CheckMenuItem(hMenu, nCurrentDevice, MF_CHECKED);
  163. }
  164. else if (LOWORD(wParam) == IDM_DEVMODE) // Properties selection
  165. {
  166. GetMenuString(hMenu, nCurrentDevice, szDevice.ptr, szDevice.length, MF_BYCOMMAND);
  167. if (OpenPrinter(szDevice.ptr, &hPrint, NULL))
  168. {
  169. PrinterProperties(hwnd, hPrint);
  170. ClosePrinter(hPrint);
  171. }
  172. }
  173. else // info menu items
  174. {
  175. CheckMenuItem(hMenu, nCurrentInfo, MF_UNCHECKED);
  176. nCurrentInfo = LOWORD(wParam);
  177. CheckMenuItem(hMenu, nCurrentInfo, MF_CHECKED);
  178. }
  179. InvalidateRect(hwnd, NULL, TRUE);
  180. return 0;
  181. case WM_INITMENUPOPUP:
  182. if (lParam == 0)
  183. EnableMenuItem(GetMenu(hwnd), IDM_DEVMODE, (nCurrentDevice == IDM_SCREEN) ? MF_GRAYED : MF_ENABLED);
  184. return 0;
  185. case WM_PAINT:
  186. szWindowText = "Device Capabilities: ";
  187. if (nCurrentDevice == IDM_SCREEN)
  188. {
  189. hdcInfo = CreateIC("DISPLAY", NULL, NULL, NULL);
  190. }
  191. else
  192. {
  193. hMenu = GetMenu(hwnd);
  194. GetMenuString(hMenu, nCurrentDevice, szDevice.ptr, szDevice.length/2, MF_BYCOMMAND);
  195. hdcInfo = CreateIC(NULL, szDevice.ptr, NULL, NULL);
  196. }
  197. //~ szDevice; // I can't even touch this thing without throwing.. oh well.
  198. hdc = BeginPaint(hwnd, &ps);
  199. SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  200. if (hdcInfo)
  201. {
  202. switch (nCurrentInfo)
  203. {
  204. case IDM_BASIC:
  205. DoBasicInfo(hdc, hdcInfo, cxChar, cyChar);
  206. break;
  207. case IDM_OTHER:
  208. DoOtherInfo(hdc, hdcInfo, cxChar, cyChar);
  209. break;
  210. case IDM_CURVE:
  211. case IDM_LINE:
  212. case IDM_POLY:
  213. case IDM_TEXT:
  214. DoBitCodedCaps(hdc, hdcInfo, cxChar, cyChar, nCurrentInfo - IDM_CURVE);
  215. break;
  216. default:
  217. }
  218. DeleteDC(hdcInfo);
  219. }
  220. EndPaint(hwnd, &ps);
  221. return 0;
  222. case WM_DESTROY:
  223. PostQuitMessage(0);
  224. return 0;
  225. default:
  226. }
  227. return DefWindowProc(hwnd, message, wParam, lParam);
  228. }
  229. void DoBasicInfo(HDC hdc, HDC hdcInfo, int cxChar, int cyChar)
  230. {
  231. struct Info
  232. {
  233. int nIndex;
  234. string description;
  235. }
  236. enum infos =
  237. [
  238. Info(HORZSIZE, "HORZSIZE Width in millimeters:"),
  239. Info(VERTSIZE, "VERTSIZE Height in millimeters:"),
  240. Info(HORZRES, "HORZRES Width in pixels:"),
  241. Info(VERTRES, "VERTRES Height in raster lines:"),
  242. Info(BITSPIXEL, "BITSPIXEL Color bits per pixel:"),
  243. Info(PLANES, "PLANES Number of color planes:"),
  244. Info(NUMBRUSHES, "NUMBRUSHES Number of device brushes:"),
  245. Info(NUMPENS, "NUMPENS Number of device pens:"),
  246. Info(NUMMARKERS, "NUMMARKERS Number of device markers:"),
  247. Info(NUMFONTS, "NUMFONTS Number of device fonts:"),
  248. Info(NUMCOLORS, "NUMCOLORS Number of device colors:"),
  249. Info(PDEVICESIZE, "PDEVICESIZE Size of device structure:"),
  250. Info(ASPECTX, "ASPECTX Relative width of pixel:"),
  251. Info(ASPECTY, "ASPECTY Relative height of pixel:"),
  252. Info(ASPECTXY, "ASPECTXY Relative diagonal of pixel:"),
  253. Info(LOGPIXELSX, "LOGPIXELSX Horizontal dots per inch:"),
  254. Info(LOGPIXELSY, "LOGPIXELSY Vertical dots per inch:"),
  255. Info(SIZEPALETTE, "SIZEPALETTE Number of palette entries:"),
  256. Info(NUMRESERVED, "NUMRESERVED Reserved palette entries:"),
  257. Info(COLORRES, "COLORRES Actual color resolution:"),
  258. Info(PHYSICALWIDTH, "PHYSICALWIDTH Printer page pixel width:"),
  259. Info(PHYSICALHEIGHT, "PHYSICALHEIGHT Printer page pixel height:"),
  260. Info(PHYSICALOFFSETX, "PHYSICALOFFSETX Printer page x offset:"),
  261. Info(PHYSICALOFFSETY, "PHYSICALOFFSETY Printer page y offset:")
  262. ];
  263. string buffer;
  264. foreach (index, info; infos)
  265. {
  266. buffer = format("%-45s%8s", info.description, GetDeviceCaps(hdcInfo, info.nIndex));
  267. TextOut(hdc, cxChar, (index + 1) * cyChar, buffer.toUTF16z, buffer.count);
  268. }
  269. }
  270. void DoOtherInfo(HDC hdc, HDC hdcInfo, int cxChar, int cyChar)
  271. {
  272. enum clips =
  273. [
  274. BITS(CP_RECTANGLE, "CP_RECTANGLE Can Clip To Rectangle:"),
  275. ];
  276. enum rasters =
  277. [
  278. BITS(RC_BITBLT, "RC_BITBLT Capable of simple BitBlt:"),
  279. BITS(RC_BANDING, "RC_BANDING Requires banding support:"),
  280. BITS(RC_SCALING, "RC_SCALING Requires scaling support:"),
  281. BITS(RC_BITMAP64, "RC_BITMAP64 Supports bitmaps >64K:"),
  282. BITS(RC_GDI20_OUTPUT, "RC_GDI20_OUTPUT Has 2.0 output calls:"),
  283. BITS(RC_DI_BITMAP, "RC_DI_BITMAP Supports DIB to memory:"),
  284. BITS(RC_PALETTE, "RC_PALETTE Supports a palette:"),
  285. BITS(RC_DIBTODEV, "RC_DIBTODEV Supports bitmap conversion:"),
  286. BITS(RC_BIGFONT, "RC_BIGFONT Supports fonts >64K:"),
  287. BITS(RC_STRETCHBLT, "RC_STRETCHBLT Supports StretchBlt:"),
  288. BITS(RC_FLOODFILL, "RC_FLOODFILL Supports FloodFill:"),
  289. BITS(RC_STRETCHDIB, "RC_STRETCHDIB Supports StretchDIBits:")
  290. ];
  291. enum szTechs =
  292. [
  293. "DT_PLOTTER (Vector plotter)",
  294. "DT_RASDISPLAY (Raster display)",
  295. "DT_RASPRINTER (Raster printer)",
  296. "DT_RASCAMERA (Raster camera)",
  297. "DT_CHARSTREAM (Character stream)",
  298. "DT_METAFILE (Metafile)",
  299. "DT_DISPFILE (Display file)"
  300. ];
  301. string buffer;
  302. buffer = format("%-24s%04s", "DRIVERVERSION:", GetDeviceCaps(hdcInfo, DRIVERVERSION));
  303. TextOut(hdc, cxChar, cyChar, buffer.toUTF16z, buffer.count);
  304. buffer = format("%-24s%40s", "TECHNOLOGY:", szTechs[GetDeviceCaps(hdcInfo, TECHNOLOGY)]);
  305. TextOut(hdc, cxChar, 2 * cyChar, buffer.toUTF16z, buffer.count);
  306. buffer = "CLIPCAPS (Clipping capabilities)";
  307. TextOut(hdc, cxChar, 4 * cyChar, buffer.toUTF16z, buffer.count);
  308. foreach (index, clip; clips)
  309. {
  310. buffer = format("%-45s %3s", clip.description, (GetDeviceCaps(hdcInfo, CLIPCAPS) & clip.iMask) ? "Yes" : "No");
  311. TextOut(hdc, 9 * cxChar, (index + 6) * cyChar, buffer.toUTF16z, buffer.count);
  312. }
  313. buffer = "RASTERCAPS (Raster capabilities)";
  314. TextOut(hdc, cxChar, 8 * cyChar, buffer.toUTF16z, buffer.count);
  315. foreach (index, raster; rasters)
  316. {
  317. buffer = format("%-45s %3s", raster.description, (GetDeviceCaps(hdcInfo, RASTERCAPS) & raster.iMask) ? "Yes" : "No");
  318. TextOut(hdc, 9 * cxChar, (index + 10) * cyChar, buffer.toUTF16z, buffer.count);
  319. }
  320. }
  321. void DoBitCodedCaps(HDC hdc, HDC hdcInfo, int cxChar, int cyChar, int iType)
  322. {
  323. enum curves =
  324. [
  325. BITS(CC_CIRCLES, "CC_CIRCLES Can do circles:"),
  326. BITS(CC_PIE, "CC_PIE Can do pie wedges:"),
  327. BITS(CC_CHORD, "CC_CHORD Can do chord arcs:"),
  328. BITS(CC_ELLIPSES, "CC_ELLIPSES Can do ellipses:"),
  329. BITS(CC_WIDE, "CC_WIDE Can do wide borders:"),
  330. BITS(CC_STYLED, "CC_STYLED Can do styled borders:"),
  331. BITS(CC_WIDESTYLED, "CC_WIDESTYLED Can do wide and styled borders:"),
  332. BITS(CC_INTERIORS, "CC_INTERIORS Can do interiors:")
  333. ];
  334. enum lines =
  335. [
  336. BITS(LC_POLYLINE, "LC_POLYLINE Can do polyline:"),
  337. BITS(LC_MARKER, "LC_MARKER Can do markers:"),
  338. BITS(LC_POLYMARKER, "LC_POLYMARKER Can do polymarkers"),
  339. BITS(LC_WIDE, "LC_WIDE Can do wide lines:"),
  340. BITS(LC_STYLED, "LC_STYLED Can do styled lines:"),
  341. BITS(LC_WIDESTYLED, "LC_WIDESTYLED Can do wide and styled lines:"),
  342. BITS(LC_INTERIORS, "LC_INTERIORS Can do interiors:")
  343. ];
  344. enum polys =
  345. [
  346. BITS(PC_POLYGON, "PC_POLYGON Can do alternate fill polygon:"),
  347. BITS(PC_RECTANGLE, "PC_RECTANGLE Can do rectangle:"),
  348. BITS(PC_WINDPOLYGON, "PC_WINDPOLYGON Can do winding number fill polygon:"),
  349. BITS(PC_SCANLINE, "PC_SCANLINE Can do scanlines:"),
  350. BITS(PC_WIDE, "PC_WIDE Can do wide borders:"),
  351. BITS(PC_STYLED, "PC_STYLED Can do styled borders:"),
  352. BITS(PC_WIDESTYLED, "PC_WIDESTYLED Can do wide and styled borders:"),
  353. BITS(PC_INTERIORS, "PC_INTERIORS Can do interiors:")
  354. ];
  355. enum texts =
  356. [
  357. BITS(TC_OP_CHARACTER, "TC_OP_CHARACTER Can do character output precision:"),
  358. BITS(TC_OP_STROKE, "TC_OP_STROKE Can do stroke output precision:"),
  359. BITS(TC_CP_STROKE, "TC_CP_STROKE Can do stroke clip precision:"),
  360. BITS(TC_CR_90, "TC_CP_90 Can do 90 degree character rotation:"),
  361. BITS(TC_CR_ANY, "TC_CR_ANY Can do any character rotation:"),
  362. BITS(TC_SF_X_YINDEP, "TC_SF_X_YINDEP Can do scaling independent of X and Y:"),
  363. BITS(TC_SA_DOUBLE, "TC_SA_DOUBLE Can do doubled character for scaling:"),
  364. BITS(TC_SA_INTEGER, "TC_SA_INTEGER Can do integer multiples for scaling:"),
  365. BITS(TC_SA_CONTIN, "TC_SA_CONTIN Can do any multiples for exact scaling:"),
  366. BITS(TC_EA_DOUBLE, "TC_EA_DOUBLE Can do double weight characters:"),
  367. BITS(TC_IA_ABLE, "TC_IA_ABLE Can do italicizing:"),
  368. BITS(TC_UA_ABLE, "TC_UA_ABLE Can do underlining:"),
  369. BITS(TC_SO_ABLE, "TC_SO_ABLE Can do strikeouts:"),
  370. BITS(TC_RA_ABLE, "TC_RA_ABLE Can do raster fonts:"),
  371. BITS(TC_VA_ABLE, "TC_VA_ABLE Can do vector fonts:")
  372. ];
  373. struct BitInfo
  374. {
  375. int iIndex;
  376. string title;
  377. BITS[] bitarray;
  378. }
  379. enum bitinfos =
  380. [
  381. BitInfo(CURVECAPS, "CURVCAPS (Curve Capabilities)", curves),
  382. BitInfo(LINECAPS, "LINECAPS (Line Capabilities)", lines),
  383. BitInfo(POLYGONALCAPS, "POLYGONALCAPS (Polygonal Capabilities)", polys),
  384. BitInfo(TEXTCAPS, "TEXTCAPS (Text Capabilities)", texts)
  385. ];
  386. static string buffer;
  387. auto iDevCaps = GetDeviceCaps(hdcInfo, bitinfos[iType].iIndex);
  388. TextOut(hdc, cxChar, cyChar, bitinfos[iType].title.toUTF16z, bitinfos[iType].title.count);
  389. foreach (index, bit; bitinfos[iType].bitarray)
  390. {
  391. buffer = format("%-55s %3s", bit.description, (iDevCaps & bit.iMask) ? "Yes" : "No");
  392. TextOut(hdc, cxChar, (index + 3) * cyChar, buffer.toUTF16z, buffer.count);
  393. }
  394. }