如何在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;
}