用双缓冲时遇到的一个有关问题,向高手请问
用双缓冲时遇到的一个问题,向高手请教。
我是把整个屏幕写入后备缓冲里,用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);
我是把整个屏幕写入后备缓冲里,用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);