title: How do I implement double buffering in the winapi?
body: <p>I can't stop the flickering. I got the advice to add dubbel-buffering. How do I do that?</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;windows.h&gt;
  #include &lt;string&gt;
  #include &lt;fstream&gt;
  #include &lt;vector&gt;
  
  using namespace std;
  
  namespace {
      const int ID_NEW = 1;
      const int ID_QUIT = 2;
      const int ID_ABOUT = 3;
      const int NORTH_BUTTON_ID = 4;
      const int SOUTH_BUTTON_ID = 5;
      const int WEST_BUTTON_ID = 6;
      const int EAST_BUTTON_ID = 7;
      const int ID_FINISHED_GAME = 8;
      int x = 0;
      int y = 0;
      int xStart = 0;
      int yStart = 0;
      int windowHeight = 400;
      int windowWidth = 500;
      char level1[20][21];
      int noOfMoves = 0;
  }
  
  void readLevel(string fileName, char level[20][21]) {
      char character{};
      ifstream file(fileName);
      int i = 0;
      int j = 0;
      if (file.is_open()) {
          while (file &gt;&gt; character) {
              level[j][i] = character;
              if (level[j][i] == 's') {
                  y = yStart = j;
                  x = xStart = i;
              }
              if (++i % 20 == 0) {
                  i = 0;
                  j++;
              }
          }
          file.close();
      }
  }
  
  void restart(){
      x = xStart;
      y = yStart;
      noOfMoves = 0;
  }
  
  LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
      HDC hdc{ 0 };
      PAINTSTRUCT ps{ 0 };
      switch (msg) {
      case WM_CLOSE:
          PostQuitMessage(0);
          return 0;
      case WM_COMMAND:
          switch (LOWORD(wParam)){
          case ID_ABOUT:
              MessageBox(hwnd, L"About this program!", L"About", MB_OK);
              return 0;
          case ID_NEW:
              restart();
              return 0;
          case ID_QUIT:
              if (MessageBox(0, L"Do you really want to quit?", L"Are you sure?", MB_YESNO) == IDYES) {
                  PostQuitMessage(0);
                  return 0;
              }
          case NORTH_BUTTON_ID:
              if (level1[y - 1][x] != '1') {
                  y -= 1;
                  noOfMoves++;
              }
              break;
          case SOUTH_BUTTON_ID:
              if (level1[y + 1][x] != '1'){
                  y += 1;
                  noOfMoves++;
              }
              break;
          case WEST_BUTTON_ID:
              if (level1[y][x - 1] != '1'){
                  x -= 1;
                  noOfMoves++;
              }
              break;
          case EAST_BUTTON_ID:
              if (level1[y][x + 1] != '1') {
                  x += 1;
                  noOfMoves++;
              }
              break;
          }
          if (level1[y][x] == 'e') {
              wstring moves = L"Congratulations, you finished the game with " + to_wstring(noOfMoves);
              MessageBox(hwnd, moves.c_str(), L"Finished game", MB_OK);
          }
      case WM_PAINT: {
                         char wall[2] = { "W" };
                         char floor[2] = { 'W' };
                         char current[2] = { "X" };
                         char goal[2] = { "G" };
                         wstring position = L"Position = [" + to_wstring(x) + L", " + to_wstring(y) + L"]";
                         wstring moves = L"Move = " + to_wstring(noOfMoves);
                         hdc = BeginPaint(hwnd, &amp;ps);
                         TextOut(hdc, 20, 200, position.c_str(), position.size());
                         TextOut(hdc, 20, 220, moves.c_str(), moves.size());
                         for (int i = 0; i &lt; 20; i++) {
                             for (int j = 0; j &lt; 20; j++) {
                                 if (level1[j][i] == '1') {
                                     SetTextColor(hdc, RGB(0, 0, 0));
                                     SetBkColor(hdc, RGB(0, 0, 0));
                                     TextOut(hdc, 14 * i + 190, 14 * j + 20, LPCTSTR(wall), strlen(wall));
                                 }
                                 SetBkColor(hdc, RGB(255, 255, 255));
                                 if (level1[j][i] == '0') {
                                     SetTextColor(hdc, RGB(255, 255, 255));
                                     TextOut(hdc, 14 * i + 190, 14 * j + 20, LPCTSTR(floor), strlen(floor));
                                 }
                                 SetTextColor(hdc, RGB(0, 0, 0));
                                 if (i == x &amp;&amp; j == y)
                                     TextOut(hdc, 14 * i + 190, 14 * j + 20, LPCTSTR(current), strlen(current));
                                 if (level1[j][i] == 'e')
                                     TextOut(hdc, 14 * i + 190, 14 * j + 20, LPCTSTR(goal), strlen(goal));
                             }
                         }
                         EndPaint(hwnd, &amp;ps);
                         break;
  
      }
      case WM_ERASEBKGND:
          return true;
      }
      return DefWindowProc(hwnd, msg, wParam, lParam);
  }
  
  HMENU CreateMainMenu() {
      HMENU main = CreateMenu();
      HMENU file = CreateMenu();
      AppendMenu(file, MF_STRING, ID_NEW, L"&amp;New");
      AppendMenu(file, MF_SEPARATOR, 0, 0);
      AppendMenu(file, MF_STRING, ID_QUIT, L"&amp;Quit");
      AppendMenu(main, MF_POPUP, (UINT_PTR)file, L"&amp;File");
      HMENU help = CreateMenu();
      AppendMenu(help, MF_STRING, ID_ABOUT, L"&amp;About");
      AppendMenu(main, MF_POPUP, (UINT_PTR)help, L"&amp;Help");
      return main;
  }
  
  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
      LPSTR lpCmdLine, int nCmdShow) {
      readLevel("level1.txt", level1);
      WNDCLASS wc = { 0 };
      wc.hbrBackground = NULL;
      wc.lpfnWndProc = WinProc;
      wc.hInstance = hInstance;
      wc.lpszClassName = L"MyWindowClass";
      RegisterClass(&amp;wc);
      HWND hwnd = CreateWindow(L"MyWindowClass", L"The Maze",
          WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
          windowWidth, windowHeight, 0, CreateMainMenu(), hInstance, 0);
      HWND buttonNorth = CreateWindow(L"BUTTON", L"NORTH", WS_CHILD | WS_VISIBLE,
          10, 20, 150, 40, hwnd, (HMENU)NORTH_BUTTON_ID, hInstance, 0);
      HWND buttonSouth = CreateWindow(L"BUTTON", L"SOUTH", WS_CHILD | WS_VISIBLE,
          10, 60, 150, 40, hwnd, (HMENU)SOUTH_BUTTON_ID, hInstance, 0);
      HWND buttonEast = CreateWindow(L"BUTTON", L"EAST", WS_CHILD | WS_VISIBLE,
          10, 140, 150, 40, hwnd, (HMENU)EAST_BUTTON_ID, hInstance, 0);
      HWND buttonWest = CreateWindow(L"BUTTON", L"WEST", WS_CHILD | WS_VISIBLE,
          10, 100, 150, 40, hwnd, (HMENU)WEST_BUTTON_ID, hInstance, 0);
      UpdateWindow(hwnd);
      ShowWindow(hwnd, nCmdShow);
      MSG msg = { 0 };
      BOOL isRunning = true;
      while (isRunning) {
          while (PeekMessage(&amp;msg, 0, 0, 0, PM_REMOVE)) {
              if (msg.message == WM_QUIT)
                  isRunning = false;
              TranslateMessage(&amp;msg);
              DispatchMessage(&amp;msg);
          }
          wc.hbrBackground = NULL;
          InvalidateRect(hwnd, NULL, FALSE);
          Sleep(10);
      }
      return 0;
  }
  </code></pre>