PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Samples/Chap15/SeqDisp/SeqDisp.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 366 lines | 281 code | 69 blank | 16 comment | 38 complexity | 7eaf373653e32af0630eca93d226f865 MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module SeqDisp;
  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 = "SeqDisp";
  27. string description = "DIB Sequential Display";
  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. while (GetMessage(&msg, NULL, 0, 0))
  82. {
  83. TranslateMessage(&msg);
  84. DispatchMessage(&msg);
  85. }
  86. return msg.wParam;
  87. }
  88. __gshared wchar[MAX_PATH] szFileName = 0;
  89. __gshared wchar[MAX_PATH] szTitleName = 0;
  90. extern (Windows)
  91. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  92. {
  93. scope (failure) assert(0);
  94. static BITMAPINFO* pbmi;
  95. static BYTE* pBits;
  96. static int cxDib, cyDib, cBits;
  97. static OPENFILENAME ofn;
  98. static string szFilter = "Bitmap Files (*.BMP)\0*.bmp\0All Files (*.*)\0*.*\0\0";
  99. BITMAPFILEHEADER bmfh;
  100. BOOL bSuccess, bTopDown;
  101. DWORD dwBytesRead;
  102. HANDLE hFile;
  103. HDC hdc;
  104. HMENU hMenu;
  105. int iInfoSize, iBitsSize, iRowLength, y;
  106. PAINTSTRUCT ps;
  107. switch (message)
  108. {
  109. case WM_CREATE:
  110. ofn.hwndOwner = hwnd;
  111. ofn.hInstance = NULL;
  112. ofn.lpstrFilter = szFilter.toUTF16z;
  113. ofn.lpstrCustomFilter = NULL;
  114. ofn.nMaxCustFilter = 0;
  115. ofn.nFilterIndex = 0;
  116. ofn.lpstrFile = szFileName.ptr;
  117. ofn.nMaxFile = MAX_PATH;
  118. ofn.lpstrFileTitle = szTitleName.ptr;
  119. ofn.nMaxFileTitle = MAX_PATH;
  120. ofn.lpstrInitialDir = NULL;
  121. ofn.lpstrTitle = NULL;
  122. ofn.Flags = 0;
  123. ofn.nFileOffset = 0;
  124. ofn.nFileExtension = 0;
  125. ofn.lpstrDefExt = "bmp";
  126. ofn.lCustData = 0;
  127. ofn.lpfnHook = NULL;
  128. ofn.lpTemplateName = NULL;
  129. return 0;
  130. case WM_COMMAND:
  131. hMenu = GetMenu(hwnd);
  132. switch (LOWORD(wParam))
  133. {
  134. case IDM_FILE_OPEN:
  135. // Display File Open dialog
  136. if (!GetOpenFileName(&ofn))
  137. return 0;
  138. // Get rid of old DIB
  139. if (pbmi)
  140. {
  141. GC.free(pbmi);
  142. pbmi = NULL;
  143. }
  144. if (pBits)
  145. {
  146. GC.free(pBits);
  147. pBits = NULL;
  148. }
  149. // Generate WM_PAINT message to erase background
  150. InvalidateRect(hwnd, NULL, TRUE);
  151. UpdateWindow(hwnd);
  152. // Open the file
  153. hFile = CreateFile(szFileName.ptr, GENERIC_READ,
  154. FILE_SHARE_READ, NULL, OPEN_EXISTING,
  155. FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  156. if (hFile == INVALID_HANDLE_VALUE)
  157. {
  158. MessageBox(hwnd, "Cannot open file.",
  159. appName.toUTF16z, MB_ICONWARNING | MB_OK);
  160. return 0;
  161. }
  162. // Read in the BITMAPFILEHEADER
  163. bSuccess = ReadFile(hFile, &bmfh, BITMAPFILEHEADER.sizeof,
  164. &dwBytesRead, NULL);
  165. if (!bSuccess || dwBytesRead != BITMAPFILEHEADER.sizeof)
  166. {
  167. MessageBox(hwnd, "Cannot read file.",
  168. appName.toUTF16z, MB_ICONWARNING | MB_OK);
  169. CloseHandle(hFile);
  170. return 0;
  171. }
  172. // Check that it's a bitmap
  173. if (bmfh.bfType != *cast(WORD*) "BM")
  174. {
  175. MessageBox(hwnd, "File is not a bitmap.",
  176. appName.toUTF16z, MB_ICONWARNING | MB_OK);
  177. CloseHandle(hFile);
  178. return 0;
  179. }
  180. // Allocate memory for header and bits
  181. iInfoSize = bmfh.bfOffBits - BITMAPFILEHEADER.sizeof;
  182. iBitsSize = bmfh.bfSize - bmfh.bfOffBits;
  183. pbmi = cast(typeof(pbmi))GC.malloc(iInfoSize);
  184. pBits = cast(typeof(pBits))GC.malloc(iBitsSize);
  185. if (pbmi == NULL || pBits == NULL)
  186. {
  187. MessageBox(hwnd, "Cannot allocate memory.",
  188. appName.toUTF16z, MB_ICONWARNING | MB_OK);
  189. if (pbmi)
  190. GC.free(pbmi);
  191. if (pBits)
  192. GC.free(pBits);
  193. CloseHandle(hFile);
  194. return 0;
  195. }
  196. // Read in the Information Header
  197. bSuccess = ReadFile(hFile, pbmi, iInfoSize,
  198. &dwBytesRead, NULL);
  199. if (!bSuccess || cast(int)dwBytesRead != iInfoSize)
  200. {
  201. MessageBox(hwnd, "Cannot read file.",
  202. appName.toUTF16z, MB_ICONWARNING | MB_OK);
  203. if (pbmi)
  204. GC.free(pbmi);
  205. if (pBits)
  206. GC.free(pBits);
  207. CloseHandle(hFile);
  208. return 0;
  209. }
  210. // Get the DIB width and height
  211. bTopDown = FALSE;
  212. if (pbmi.bmiHeader.biSize == BITMAPCOREHEADER.sizeof)
  213. {
  214. cxDib = (cast(BITMAPCOREHEADER*)pbmi).bcWidth;
  215. cyDib = (cast(BITMAPCOREHEADER*)pbmi).bcHeight;
  216. cBits = (cast(BITMAPCOREHEADER*)pbmi).bcBitCount;
  217. }
  218. else
  219. {
  220. if (pbmi.bmiHeader.biHeight < 0)
  221. bTopDown = TRUE;
  222. cxDib = pbmi.bmiHeader.biWidth;
  223. cyDib = abs(pbmi.bmiHeader.biHeight);
  224. cBits = pbmi.bmiHeader.biBitCount;
  225. if (pbmi.bmiHeader.biCompression != BI_RGB &&
  226. pbmi.bmiHeader.biCompression != BI_BITFIELDS)
  227. {
  228. MessageBox(hwnd, "File is compressed.",
  229. appName.toUTF16z, MB_ICONWARNING | MB_OK);
  230. if (pbmi)
  231. GC.free(pbmi);
  232. if (pBits)
  233. GC.free(pBits);
  234. CloseHandle(hFile);
  235. return 0;
  236. }
  237. }
  238. // Get the row length
  239. iRowLength = ((cxDib * cBits + 31) & ~31) >> 3;
  240. // Read and display
  241. SetCursor(LoadCursor(NULL, IDC_WAIT));
  242. ShowCursor(TRUE);
  243. hdc = GetDC(hwnd);
  244. for (y = 0; y < cyDib; y++)
  245. {
  246. ReadFile(hFile, pBits + y * iRowLength, iRowLength,
  247. &dwBytesRead, NULL);
  248. SetDIBitsToDevice(hdc,
  249. 0, // xDst
  250. 0, // yDst
  251. cxDib, // cxSrc
  252. cyDib, // cySrc
  253. 0, // xSrc
  254. 0, // ySrc
  255. bTopDown ? cyDib - y - 1 : y,
  256. // first scan line
  257. 1, // number of scan lines
  258. pBits + y * iRowLength,
  259. pbmi,
  260. DIB_RGB_COLORS);
  261. }
  262. ReleaseDC(hwnd, hdc);
  263. CloseHandle(hFile);
  264. ShowCursor(FALSE);
  265. SetCursor(LoadCursor(NULL, IDC_ARROW));
  266. return 0;
  267. default:
  268. }
  269. break;
  270. case WM_PAINT:
  271. hdc = BeginPaint(hwnd, &ps);
  272. if (pbmi && pBits)
  273. SetDIBitsToDevice(hdc,
  274. 0, // xDst
  275. 0, // yDst
  276. cxDib, // cxSrc
  277. cyDib, // cySrc
  278. 0, // xSrc
  279. 0, // ySrc
  280. 0, // first scan line
  281. cyDib, // number of scan lines
  282. pBits,
  283. pbmi,
  284. DIB_RGB_COLORS);
  285. EndPaint(hwnd, &ps);
  286. return 0;
  287. case WM_DESTROY:
  288. if (pbmi)
  289. GC.free(pbmi);
  290. if (pBits)
  291. GC.free(pBits);
  292. PostQuitMessage(0);
  293. return 0;
  294. default:
  295. }
  296. return DefWindowProc(hwnd, message, wParam, lParam);
  297. }