用双缓冲时遇到的一个问题,向高手请教。
时间:2011-12-05
来源:互联网
我是把整个屏幕写入后备缓冲里,用GetDIBits获取每个像素点的RGB,再用SetPixel对后备缓冲的每个像素点赋值。其实每个像素点的颜色都还是没改变。
但程序运行时,如果屏幕有变化,比如窗口的最大最小化,就会显示出错。原因是屏幕画面改变了,但后备缓冲的画面还没有改变。
不知道有没有办法解决这个问题。
源程序:
#include <windows.h>
#include<time.h>
const int ScrnWidth=GetSystemMetrics(SM_CXSCREEN); //屏幕宽度
const int ScrnHight=GetSystemMetrics(SM_CYSCREEN); //屏幕高度
const int ID_TIMER=1;
const char g_szClassName[] = "myWindowClass";
//用于创建双缓冲
static HDC hdcBackBuffer;
static HBITMAP hBitmap;
static HBITMAP hOldBitmap;
static HDC hDC1; //存储桌面窗口设备句柄
static int timecont;
// 定义位图信息
BITMAPINFO bi;
//创建缓冲
BYTE (*pBits)[4]=new BYTE[(ScrnWidth+1)*(ScrnHight+1)][4];
unsigned long GetColor(long x,long y)
{
if(x>0&&x<=ScrnWidth&&y>0&&y<=ScrnHight)
return RGB(pBits[y*ScrnWidth+x][2],pBits[y*ScrnWidth+x][1],pBits[y*ScrnWidth+x][0]);
else
return CLR_INVALID;
}
//主回调函数
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_TIMER: //时钟
BitBlt(hdcBackBuffer, 0, 0, ScrnWidth, ScrnHight, hDC1, 0, 0, SRCCOPY);
::GetDIBits(hdcBackBuffer, hBitmap, 0, ScrnHight, pBits, &bi, DIB_RGB_COLORS);
for(int i=1;i<ScrnHight+1;i++)
for(int j=1;j<ScrnWidth+1;j++)
{
SetPixel(hdcBackBuffer,j,i,GetColor(j,i));
}
BitBlt(hDC1, 0, 0, ScrnWidth, ScrnHight,hdcBackBuffer, 0, 0, SRCCOPY);
return 0;
case WM_CREATE:
int j;
srand(time(0));
SetTimer(hwnd,ID_TIMER,20,NULL); //创建一个定时器
hDC1=GetDC(0); //获取桌面窗口设备场景句柄
timecont=0;
//创建一个内存设备描述表
hdcBackBuffer = CreateCompatibleDC(NULL);
//创建相容的位图
hBitmap=CreateCompatibleBitmap(hDC1,ScrnWidth,ScrnHight);
//将bitmap装入内存
hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);
//把后备缓冲初始化成白色
BitBlt(hdcBackBuffer,0,0,ScrnWidth,ScrnHight,NULL,NULL,NULL,WHITENESS);
// 定义位图信息
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = ScrnWidth;
bi.bmiHeader.biHeight = -ScrnHight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage =ScrnWidth* 4 *ScrnHight; // 32 bit
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
return 0;
case WM_CLOSE:
ReleaseDC(0,hDC1); //释放桌面窗口设备句柄
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
//删除内存DC和位图
SelectObject(hdcBackBuffer, hOldBitmap);
DeleteDC(hdcBackBuffer);
DeleteObject(hBitmap);
//删除缓冲
delete[] pBits;
pBits = NULL;
KillTimer(hwnd, ID_TIMER); //销毁定时器
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize=sizeof(WNDCLASSEX);
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc=WndProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL;
wc.lpszClassName=g_szClassName;
wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "窗体注册失败!", "错误!",MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd=CreateWindowEx( WS_EX_CLIENTEDGE,
g_szClassName,
"程序",
WS_OVERLAPPEDWINDOW|WS_MINIMIZE,
CW_USEDEFAULT,
CW_USEDEFAULT,
240,
120,
NULL,
NULL,
hInstance,
NULL);
if(hwnd==NULL)
{
MessageBox(NULL, "窗体创建失败!", "错误!",MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg,NULL,0,0)>0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
但程序运行时,如果屏幕有变化,比如窗口的最大最小化,就会显示出错。原因是屏幕画面改变了,但后备缓冲的画面还没有改变。
不知道有没有办法解决这个问题。
源程序:
#include <windows.h>
#include<time.h>
const int ScrnWidth=GetSystemMetrics(SM_CXSCREEN); //屏幕宽度
const int ScrnHight=GetSystemMetrics(SM_CYSCREEN); //屏幕高度
const int ID_TIMER=1;
const char g_szClassName[] = "myWindowClass";
//用于创建双缓冲
static HDC hdcBackBuffer;
static HBITMAP hBitmap;
static HBITMAP hOldBitmap;
static HDC hDC1; //存储桌面窗口设备句柄
static int timecont;
// 定义位图信息
BITMAPINFO bi;
//创建缓冲
BYTE (*pBits)[4]=new BYTE[(ScrnWidth+1)*(ScrnHight+1)][4];
unsigned long GetColor(long x,long y)
{
if(x>0&&x<=ScrnWidth&&y>0&&y<=ScrnHight)
return RGB(pBits[y*ScrnWidth+x][2],pBits[y*ScrnWidth+x][1],pBits[y*ScrnWidth+x][0]);
else
return CLR_INVALID;
}
//主回调函数
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_TIMER: //时钟
BitBlt(hdcBackBuffer, 0, 0, ScrnWidth, ScrnHight, hDC1, 0, 0, SRCCOPY);
::GetDIBits(hdcBackBuffer, hBitmap, 0, ScrnHight, pBits, &bi, DIB_RGB_COLORS);
for(int i=1;i<ScrnHight+1;i++)
for(int j=1;j<ScrnWidth+1;j++)
{
SetPixel(hdcBackBuffer,j,i,GetColor(j,i));
}
BitBlt(hDC1, 0, 0, ScrnWidth, ScrnHight,hdcBackBuffer, 0, 0, SRCCOPY);
return 0;
case WM_CREATE:
int j;
srand(time(0));
SetTimer(hwnd,ID_TIMER,20,NULL); //创建一个定时器
hDC1=GetDC(0); //获取桌面窗口设备场景句柄
timecont=0;
//创建一个内存设备描述表
hdcBackBuffer = CreateCompatibleDC(NULL);
//创建相容的位图
hBitmap=CreateCompatibleBitmap(hDC1,ScrnWidth,ScrnHight);
//将bitmap装入内存
hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);
//把后备缓冲初始化成白色
BitBlt(hdcBackBuffer,0,0,ScrnWidth,ScrnHight,NULL,NULL,NULL,WHITENESS);
// 定义位图信息
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = ScrnWidth;
bi.bmiHeader.biHeight = -ScrnHight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage =ScrnWidth* 4 *ScrnHight; // 32 bit
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
return 0;
case WM_CLOSE:
ReleaseDC(0,hDC1); //释放桌面窗口设备句柄
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
//删除内存DC和位图
SelectObject(hdcBackBuffer, hOldBitmap);
DeleteDC(hdcBackBuffer);
DeleteObject(hBitmap);
//删除缓冲
delete[] pBits;
pBits = NULL;
KillTimer(hwnd, ID_TIMER); //销毁定时器
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize=sizeof(WNDCLASSEX);
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc=WndProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL;
wc.lpszClassName=g_szClassName;
wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "窗体注册失败!", "错误!",MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd=CreateWindowEx( WS_EX_CLIENTEDGE,
g_szClassName,
"程序",
WS_OVERLAPPEDWINDOW|WS_MINIMIZE,
CW_USEDEFAULT,
CW_USEDEFAULT,
240,
120,
NULL,
NULL,
hInstance,
NULL);
if(hwnd==NULL)
{
MessageBox(NULL, "窗体创建失败!", "错误!",MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg,NULL,0,0)>0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
作者: zhangyanzlk 发布时间: 2011-12-05
我在VC6下试了一下没报错
作者: heksn 发布时间: 2011-12-05
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28