PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Extra/BackBuffer/BackBuffer.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 188 lines | 127 code | 33 blank | 28 comment | 3 complexity | bff32192eb75efba0d13be2faf89defc MD5 | raw file
  1. /+
  2. + Copyright Andrej Mitrovic 2011.
  3. + Distributed under the Boost Software License, Version 1.0.
  4. + (See accompanying file LICENSE_1_0.txt or copy at
  5. + http://www.boost.org/LICENSE_1_0.txt)
  6. +
  7. + Demonstrates a simple double-buffer drawing mechanism.
  8. + Basically you do all the drawing in a backbuffer and
  9. + then blit that to the screen when you're done.
  10. +
  11. + Some good info about avoiding flicker can be found here:
  12. + http://www.catch22.net/tuts/flicker
  13. +
  14. + Also see various codeproject.com C/C++ helper libraries
  15. + and articles that have anti-flicker code.
  16. +
  17. + Note that scrollbars and titlebars still flicker,
  18. + but this could also be fixed. Search online to figure
  19. + this stuff out.
  20. +/
  21. module BackBuffer;
  22. import core.memory;
  23. import core.runtime;
  24. import core.thread;
  25. import std.conv;
  26. import std.math;
  27. import std.range;
  28. import std.string;
  29. import std.utf;
  30. auto toUTF16z(S)(S s)
  31. {
  32. return toUTFz!(const(wchar)*)(s);
  33. }
  34. pragma(lib, "gdi32.lib");
  35. import core.sys.windows.windef;
  36. import core.sys.windows.winuser;
  37. import core.sys.windows.wingdi;
  38. import core.sys.windows.winbase;
  39. string appName = "BackBuffer";
  40. string description = "BackBuffer Demo";
  41. HINSTANCE hinst;
  42. extern (Windows)
  43. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  44. {
  45. int result;
  46. try
  47. {
  48. Runtime.initialize();
  49. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  50. Runtime.terminate();
  51. }
  52. catch (Throwable o)
  53. {
  54. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  55. result = 0;
  56. }
  57. return result;
  58. }
  59. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  60. {
  61. hinst = hInstance;
  62. HACCEL hAccel;
  63. HWND hwnd;
  64. MSG msg;
  65. WNDCLASS wndclass;
  66. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  67. wndclass.lpfnWndProc = &WndProc;
  68. wndclass.cbClsExtra = 0;
  69. wndclass.cbWndExtra = 0;
  70. wndclass.hInstance = hInstance;
  71. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  72. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  73. //~ wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  74. wndclass.hbrBackground = null; // don't send WM_ERASEBKND messages
  75. wndclass.lpszMenuName = appName.toUTF16z;
  76. wndclass.lpszClassName = appName.toUTF16z;
  77. if (!RegisterClass(&wndclass))
  78. {
  79. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  80. return 0;
  81. }
  82. hwnd = CreateWindow(appName.toUTF16z, // window class name
  83. description.toUTF16z, // window caption
  84. WS_OVERLAPPEDWINDOW, // window style
  85. CW_USEDEFAULT, // initial x position
  86. CW_USEDEFAULT, // initial y position
  87. CW_USEDEFAULT, // initial x size
  88. CW_USEDEFAULT, // initial y size
  89. NULL, // parent window handle
  90. NULL, // window menu handle
  91. hInstance, // program instance handle
  92. NULL); // creation parameters
  93. ShowWindow(hwnd, iCmdShow);
  94. UpdateWindow(hwnd);
  95. while (GetMessage(&msg, NULL, 0, 0))
  96. {
  97. TranslateMessage(&msg);
  98. DispatchMessage(&msg);
  99. }
  100. return msg.wParam;
  101. }
  102. extern (Windows)
  103. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  104. {
  105. scope (failure) assert(0);
  106. static int cxClient, cyClient, cxSource, cySource;
  107. int x, y;
  108. HDC hdc;
  109. PAINTSTRUCT ps;
  110. static HDC hdcMem;
  111. static HBITMAP hbmMem;
  112. static HANDLE hOld;
  113. RECT rect;
  114. switch (message)
  115. {
  116. case WM_SIZE:
  117. cxClient = LOWORD(lParam);
  118. cyClient = HIWORD(lParam);
  119. return 0;
  120. // When you set 'hbrBackground = null' it prevents
  121. // the WM_ERASEBKND message to be sent.
  122. case WM_ERASEBKGND:
  123. return 1;
  124. case WM_PAINT:
  125. {
  126. // Get DC for window
  127. hdc = BeginPaint(hwnd, &ps);
  128. // Create an off-screen DC for double-buffering
  129. hdcMem = CreateCompatibleDC(hdc);
  130. hbmMem = CreateCompatibleBitmap(hdc, cxClient, cyClient);
  131. hOld = SelectObject(hdcMem, hbmMem);
  132. // Draw into hdcMem
  133. GetClientRect(hwnd, &rect);
  134. FillRect(hdcMem, &rect, GetStockObject(BLACK_BRUSH));
  135. rect.left += 10;
  136. rect.top += 10;
  137. rect.right -= 10;
  138. rect.bottom -= 10;
  139. FillRect(hdcMem, &rect, GetStockObject(WHITE_BRUSH));
  140. // Transfer the off-screen DC to the screen
  141. BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);
  142. // Free-up the off-screen DC
  143. SelectObject(hdcMem, hOld);
  144. DeleteObject(hbmMem);
  145. DeleteDC (hdcMem);
  146. EndPaint(hwnd, &ps);
  147. return 0;
  148. }
  149. case WM_DESTROY:
  150. PostQuitMessage(0);
  151. return 0;
  152. default:
  153. }
  154. return DefWindowProc(hwnd, message, wParam, lParam);
  155. }