如何在winapi中实现双缓冲?

如何在winapi中实现双缓冲?,winapi,double-buffering,Winapi,Double Buffering,我无法停止闪烁。我得到的建议是添加配音缓冲。我该怎么做 #include <iostream> #include <windows.h> #include <string> #include <fstream> #include <vector> using namespace std; namespace { const int ID_NEW = 1; const int ID_QUIT = 2; cons

我无法停止闪烁。我得到的建议是添加配音缓冲。我该怎么做

#include <iostream>
#include <windows.h>
#include <string>
#include <fstream>
#include <vector>

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 >> 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, &ps);
                       TextOut(hdc, 20, 200, position.c_str(), position.size());
                       TextOut(hdc, 20, 220, moves.c_str(), moves.size());
                       for (int i = 0; i < 20; i++) {
                           for (int j = 0; j < 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 && 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, &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"&New");
    AppendMenu(file, MF_SEPARATOR, 0, 0);
    AppendMenu(file, MF_STRING, ID_QUIT, L"&Quit");
    AppendMenu(main, MF_POPUP, (UINT_PTR)file, L"&File");
    HMENU help = CreateMenu();
    AppendMenu(help, MF_STRING, ID_ABOUT, L"&About");
    AppendMenu(main, MF_POPUP, (UINT_PTR)help, L"&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(&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(&msg, 0, 0, 0, PM_REMOVE)) {
            if (msg.message == WM_QUIT)
                isRunning = false;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        wc.hbrBackground = NULL;
        InvalidateRect(hwnd, NULL, FALSE);
        Sleep(10);
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
名称空间{
const int ID_NEW=1;
const int ID_QUIT=2;
const int ID_ABOUT=3;
常量int北按钮ID=4;
const int南按钮ID=5;
康斯特西区按钮ID=6;
常数int东按钮ID=7;
const int ID_FINISHED_GAME=8;
int x=0;
int y=0;
int xStart=0;
int-yStart=0;
内窗高度=400;
int窗宽=500;
字符级别1[20][21];
int noOfMoves=0;
}
void readLevel(字符串文件名,字符级别[20][21]){
字符{};
ifstream文件(文件名);
int i=0;
int j=0;
if(file.is_open()){
while(文件>>字符){
[j][i]级=字符;
如果(级别[j][i]=='s'){
y=yStart=j;
x=xStart=i;
}
如果(++i%20==0){
i=0;
j++;
}
}
file.close();
}
}
void restart(){
x=xStart;
y=yStart;
noOfMoves=0;
}
LRESULT回调WinProc(HWND HWND,UINT msg,WPARAM WPARAM,LPARAM LPARAM){
HDC HDC{0};
PAINTSTRUCT ps{0};
开关(msg){
案例WM_结束:
PostQuitMessage(0);
返回0;
case WM_命令:
开关(LOWORD(wParam)){
案例ID_关于:
MessageBox(hwnd,L“关于这个程序!”,L“关于”,MB_OK);
返回0;
案件编号(新):
重启();
返回0;
案例ID\u退出:
如果(MessageBox(0,L“你真的想退出吗?”,L“你确定吗?”,MB_YESNO)=idies){
PostQuitMessage(0);
返回0;
}
案例北按钮标识:
如果(级别1[y-1][x]!='1'){
y-=1;
noOfMoves++;
}
打破
案例南部按钮标识:
如果(级别1[y+1][x]!='1'){
y+=1;
noOfMoves++;
}
打破
箱子西侧按钮标识:
如果(level1[y][x-1]!='1'){
x-=1;
noOfMoves++;
}
打破
案例东按钮标识:
如果(级别1[y][x+1]!='1'){
x+=1;
noOfMoves++;
}
打破
}
如果(1级[y][x]='e'){
wstring moves=L“恭喜你,你以“+to_wstring(noOfMoves)”结束了游戏;
MessageBox(hwnd,moves.c_str(),L“已完成游戏”,MB_OK);
}
案例WM_油漆:{
char-wall[2]={“W”};
字符层[2]={W'};
字符电流[2]={“X”};
char目标[2]={“G”};
环位置=L“位置=[“+到环(x)+L”,“+到环(y)+L”];
wstring moves=L“Move=“+to_wstring(noOfMoves));
hdc=开始喷漆(hwnd和ps);
TextOut(hdc,20200,position.c_str(),position.size());
TextOut(hdc,20220,moves.c_str(),moves.size());
对于(int i=0;i<20;i++){
对于(int j=0;j<20;j++){
如果(1级[j][i]=“1”){
SetTextColor(hdc,RGB(0,0,0));
SetBkColor(hdc,RGB(0,0,0));
文本输出(hdc、14*i+190、14*j+20、LPCTSTR(墙)、strlen(墙));
}
SetBkColor(hdc、RGB(255、255、255));
如果(1级[j][i]=“0”){
SetTextColor(hdc、RGB(255、255、255));
文本输出(hdc、14*i+190、14*j+20、LPCTSTR(楼层)、strlen(楼层));
}
SetTextColor(hdc,RGB(0,0,0));
如果(i==x&&j==y)
文本输出(hdc、14*i+190、14*j+20、LPCTSTR(当前)、STREN(当前));
如果(1级[j][i]=“e”)
文本输出(hdc、14*i+190、14*j+20、LPCTSTR(目标)、strlen(目标));
}
}
端漆(hwnd和ps);
打破
}
案例WM_擦除BKGND:
返回true;
}
返回DefWindowProc(hwnd、msg、wParam、lParam);
}
HMENU CreateMainMenu(){
HMENU main=CreateMenu();
shmenu file=CreateMenu();
附录菜单(文件、MF_字符串、ID_新建、L“&NEW”);
附录菜单(文件,MF_分隔符,0,0);
附录菜单(文件、MF_字符串、ID_退出、L“&QUIT”);
附录菜单(主菜单,MF_弹出菜单,(UINT_PTR)文件,L“&文件”);
humenu help=CreateMenu();
附录菜单(帮助、MF_字符串、ID_ABOUT、L“&ABOUT”);
附录菜单(主菜单、MF_弹出菜单、(UINT_PTR)帮助、L“&帮助”);
回水总管;
}
int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、,
LPSTR lpCmdLine,int nCmdShow){
readLevel(“level1.txt”,level1);
WNDCLASS wc={0};
wc.hbrBackground=NULL;
wc.lpfnWndProc=WinProc;
wc.hInstance=hInstance;
wc.lpszClassName=L“MyWindowClass”;
注册类(&wc);
HWND HWND=CreateWindow(L“MyWindowClass”,L“迷宫”,
WS_OVERLAPPEDWINDOW、CW_USEDEFAULT、CW_USEDEFAULT、,
windowWidth,windowHeight,0,CreateMainMenu(),hInstance,0);
HWND Buttonnoth=创建窗口(L“按钮”,L“北”,WS|U子对象,WS|U可见,
10,20,150,40,hwnd,(汉努)北按钮ID,hInstance,0);
HWND buttonSouth=创建窗口(L“按钮”,L“南”,WS|U子对象,WS|U可见,
10,60,150,40,hwnd,(汉努)南部按钮ID,hInstance,0);
半对接
case WM_PAINT: 
    {
        // skipped the initialization part to preserve space
        // just copy those, they are irrelevant for your problem

        hdc = BeginPaint(hwnd, &ps);

        // create memory DC and memory bitmap where we shall do our drawing

        HDC memDC = CreateCompatibleDC( hdc );

        // get window's client rectangle. We need this for bitmap creation.
        RECT rcClientRectangle;
        GetClientRect( hwnd, &rcClientRect );

        // now we can create bitmap where we shall do our drawing
        HBITMAP bmp = CreateCompatibleBitmap( hdc, 
            rcClientRect.right - rcClientRect.left, 
            rcClientRect.bottom - rcClientRect.top );

        // we need to save original bitmap, and select it back when we are done,
        // in order to avoid GDI leaks!
        HBITMAP oldBmp = (HBITMAP)SelectObject( memDC, bmp );

        // now you draw your stuff in memory dc; 
        // just substitute hdc with memDC in your drawing code, 
        // like I did below:

        TextOut( memDC, //...
        TextOut( memDC, //...
        for (int i = 0; i < 20; i++) 
        {
            for (int j = 0; j < 20; j++) 
            {
                if (level1[j][i] == '1') 
                {
                    SetTextColor( memDC, //...
                    SetBkColor( memDC, //...
                    TextOut( memDC, //...
                }
                SetBkColor( memDC, //...
                if (level1[j][i] == '0') 
                {
                    SetTextColor( memDC, //...
                    TextOut( memDC, //...
                }
                SetTextColor( memDC, //...
                if (i == x && j == y)
                    TextOut( memDC, //...
                if (level1[j][i] == 'e')
                    TextOut( memDC, //...
            }
        }

        // OK, everything is drawn into memory DC, 
        // now is the time to draw that final result into our target DC

        BitBlt( hdc, 0, 0, rcClientRect.right - rcClientRect.left, 
            rcClientRect.bottom - rcClientRect.top, memDC, 0, 0, SRCCOPY );

        // all done, now we need to cleanup
        SelectObject( memDC, oldBmp ); // select back original bitmap
        DeleteObject( bmp ); // delete bitmap since it is no longer required
        DeleteDC( memDC );   // delete memory DC since it is no longer required

        EndPaint(hwnd, &ps);
        break;
    }