解决不了的图片闪烁问题,请高手赐教!

chocolate_zql 2010-05-09 10:49:59
看了很多帖子,说是用双缓冲技术解决,首先得先捕获WM_ERASEBKGND消息,return True。我在程序里加了以后程序运行后客户区就不能正常显示了,显示的是当前桌面的背景,不知道是什么原因。如果这个程序要用双缓冲技术解决刷新闪烁问题该怎么处理呢?
#include <windows.h>
#include"resource.h"
//声明窗口消息处理函数
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
// 定义WinMain函数
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInst,
LPSTR lpszCmdLine,
int nCmdShow)
{
//--------------------------以下为初始化窗口类---------------------------
HWND hwnd; //定义一个窗口句柄
MSG Msg; //定义一个消息结构
WNDCLASS wndclass; //定义一个窗口类结构
HACCEL hAccel;
char lpszClassName[]="窗口"; //定义窗口类名数组
char lpszTitle[]="My_Windows"; //定义窗口标题名数组
//窗口类的定义
wndclass.style=0; //默认类型
wndclass.lpfnWndProc=WndProc; //窗口函数WndProc()
wndclass.cbClsExtra=0; //窗口类无扩展
wndclass.cbWndExtra=0; //窗口实例无扩展
wndclass.hInstance=hInstance; //当前窗口实例句柄
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); //窗口的最小化图标为默认图标
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); //窗口采用箭头光标
/* HBITMAP hBmp;
hBmp=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP5));
wndclass.hbrBackground=CreatePatternBrush(hBmp); */
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //窗口背景为白色
wndclass.lpszMenuName="IDR_MENU";//MAKEINTRESOURCE(IDR_MENU); //窗口中无菜单
wndclass.lpszClassName=lpszClassName; //窗口类名为"窗口"
//---------------------------以下进行窗口类注册-------------------------
if(!RegisterClass(&wndclass)) //如果注册失败则报警
{
MessageBeep(0);
return FALSE;
}
//创建窗口
hwnd=CreateWindow(lpszClassName,//窗口类名
lpszTitle, //窗口实例的标题名
WS_OVERLAPPEDWINDOW,//窗口的风格
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口左上角坐标为默认值
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口的高和宽为默认值
NULL, //无父窗口
NULL, //无主菜单
hInstance, //创建窗口的应用程序的当前句柄
NULL); //无参数值
ShowWindow(hwnd,nCmdShow); //显示窗口
UpdateWindow(hwnd); //绘制窗口用户区
hAccel=LoadAccelerators(hInstance,"MyAccel");
while(GetMessage(&Msg,NULL,0,0))//消息循环
{
if(!TranslateAccelerator(hwnd,hAccel,&Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
return Msg.wParam; //消息循环结束即程序终止时将信息返回系统
}
//定义窗口消息处理函数
LRESULT CALLBACK WndProc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
static HMENU hMenu;
HMENU hBitmapMenu,hBackgroundMenu,hFileMenu;
static HBRUSH idColor[3];
static int iSelection=IDM_WHITE;
static HDC hDC;
static HINSTANCE hInstance;
static HBITMAP hBitmap;
POINT point;
static bool bStretch=false;
static BITMAP bm;
static HDC hdcmem;
PAINTSTRUCT ps;
static int cx,cy,iStep=1;
static int xSign=1,ySign=1;
switch(message)
{
case WM_CREATE:
hMenu=GetMenu(hwnd);
EnableMenuItem(hMenu,IDM_DEL,MF_GRAYED);
idColor[0]=(HBRUSH)GetStockObject(WHITE_BRUSH);
idColor[1]=(HBRUSH)GetStockObject(BLACK_BRUSH);
idColor[2]=CreateSolidBrush(RGB(255,0,0));
hInstance=((LPCREATESTRUCT)lParam)->hInstance;

hBackgroundMenu=GetSubMenu(hMenu,1);
hBitmap=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP1));
SetMenuItemBitmaps(hBackgroundMenu,IDM_WHITE,MF_BYCOMMAND,hBitmap,hBitmap);
hBitmap=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP3));
SetMenuItemBitmaps(hBackgroundMenu,IDM_BLACK,MF_BYCOMMAND,hBitmap,hBitmap);
hBitmap=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP2));
SetMenuItemBitmaps(hBackgroundMenu,IDM_Red,MF_BYCOMMAND,hBitmap,hBitmap);
hFileMenu=GetSubMenu(hMenu,0);
hBitmap=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP4));
SetMenuItemBitmaps(hFileMenu,IDM_NEW,MF_BYCOMMAND,hBitmap,hBitmap);
hDC=GetDC(hwnd);
hdcmem=CreateCompatibleDC(hDC);
ReleaseDC(hwnd,hDC);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_NEW:
hBitmapMenu=LoadMenu(hInstance,"IDR_MENU1");
hBitmapMenu=GetSubMenu(hBitmapMenu,0);
InsertMenu(hMenu,1,MF_POPUP|MF_BYPOSITION,(UINT_PTR)hBitmapMenu,"&BitMap");
EnableMenuItem(hMenu,IDM_NEW,MF_GRAYED);
EnableMenuItem(hMenu,IDM_DEL,MF_ENABLED);
DrawMenuBar(hwnd);
break;
case IDM_PASTE:
MessageBox(hwnd,"你选择了Paste菜单项","菜单",0);
break;
case IDM_COPY:
MessageBox(hwnd,"你选择了Copy菜单项","菜单",0);
break;
case IDM_DEL:
DeleteMenu(hMenu,1,MF_BYPOSITION);
EnableMenuItem(hMenu,IDM_NEW,MF_ENABLED);
EnableMenuItem(hMenu,IDM_DEL,MF_GRAYED);
DrawMenuBar(hwnd);
break;
case IDM_WHITE:
case IDM_BLACK:
case IDM_Red:
CheckMenuItem(hMenu,iSelection,MF_UNCHECKED);
iSelection=LOWORD(wParam);
CheckMenuItem(hMenu,iSelection,MF_CHECKED);
SetClassLong(hwnd,GCL_HBRBACKGROUND,(long)idColor[iSelection-IDM_WHITE]);
InvalidateRect(hwnd,NULL,TRUE);
break;
case IDM_BITBLT:
hBitmap=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP5));
GetObject(hBitmap,sizeof(BITMAP),(LPVOID)&bm);
bStretch=false;
InvalidateRect(hwnd,NULL,true);
break;
case IDM_STRETCHBLT:
hBitmap=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP5));
GetObject(hBitmap,sizeof(BITMAP),(LPVOID)&bm);
bStretch=true;
InvalidateRect(hwnd,NULL,true);
break;
case IDM_LARGER:
iStep=iStep*10;
InvalidateRect(hwnd,NULL,true);
break;
case IDM_SMALL:
iStep=iStep/10;
InvalidateRect(hwnd,NULL,true);
case IDM_OVERTURNX:
xSign=-1*xSign;
InvalidateRect(hwnd,NULL,true);
break;
case IDM_OVERTURNY:
ySign=-1*ySign;
InvalidateRect(hwnd,NULL,true);
}
break;
case WM_SIZE:
cx=LOWORD(lParam);
cy=HIWORD(lParam);
InvalidateRect(hwnd,NULL,false);
break;
case WM_PAINT:
hDC=BeginPaint(hwnd,&ps);
SelectObject(hdcmem,hBitmap);
if(bStretch==false)
BitBlt(hDC,cx/2-bm.bmWidth/2,cy/2-bm.bmHeight/2,bm.bmWidth+iStep,bm.bmHeight+iStep,hdcmem,0,0,SRCCOPY);
else
StretchBlt(hDC,cx/2-xSign*(bm.bmWidth+iStep)/2,cy/2-ySign*(bm.bmHeight+iStep)/2,xSign*(bm.bmWidth+iStep),ySign*(bm.bmHeight)+iStep,hdcmem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
EndPaint(hwnd,&ps);
break;
case WM_RBUTTONUP:
hMenu = GetSubMenu (hMenu, 0) ;
point.x=LOWORD(lParam);
point.y=HIWORD(lParam);
ClientToScreen(hwnd,&point);
TrackPopupMenu (hMenu, TPM_RIGHTBUTTON, point.x, point.y,0, hwnd, NULL) ;
break;
case WM_ERASEBKGND:
return true;
case WM_DESTROY:
DeleteObject(hBitmap);
PostQuitMessage(0); //调用PostQuitMessage 发出WM_QUIT消息
default: //默认时采用系统消息默认处理函数
return DefWindowProc(hwnd,message,wParam,lParam);
}
return (0);
}
...全文
150 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
chocolate_zql 2010-05-20
  • 打赏
  • 举报
回复
我将同样的方法用在绘图上就可以,但是用在显示位图上就还是不行,算了,先结了,自己在研究一下。
zyhserry 2010-05-17
  • 打赏
  • 举报
回复
上面的代码不知道你具体是画什么,但是结构是这样的
zyhserry 2010-05-17
  • 打赏
  • 举报
回复

//双缓冲的意思是一个屏幕DC,一个内存DC
//先把所有要画的内容画到内存DC上绘图,然后再把内存的DC上绘好的图画一次性画到屏幕DC上
PAINTSTRUCT ps;
HDC hdcmem; //内存DC
HBITMAP hOldBitmap,hMemBitmap;
HBRUSH hOldBrush,hBrush;;
RECT rect;
GetClientRect(hwnd,&rect);

hDC=BeginPaint(hwnd,&ps);
hdcmem=CreateCompatibleDC(hDC);
hMemBitmap=CreateCompatibleBitmap(hDC,rect.right-rect.left,rect.bottom-rect.top);
hOldBitmap=(HBITMAP)SelectObject(hdcmem,hMemBitmap);
hBrush = CreateSolidBrush(RGB(0,0,0));
hOldBrush = (HBRUSH)SelectObject(hdcmem,hBrush);

//在内存DC上画图
Rectangle(hdcmem,rect.left,rect.top,rect.right,rect.bottom);
if(bStretch==false)
{
//在内存DC上画图
BitBlt(hdcmem,0,0,bm.bmWidth+iStep,bm.bmHeight+iStep,hdcmem,0,0,SRCCOPY);
//把内存DC上的内容画到屏幕DC上
BitBlt(hDC,cx/2-bm.bmWidth/2,cy/2- bm.bmHeight/2,bm.bmWidth+iStep,bm.bmHeight+iStep,hdcmem,0,0,SRCCOPY);
}
else
{
//把内存DC上的内容画到屏幕DC上
StretchBlt(hDC,cx/2-xSign*(bm.bmWidth+iStep)/2,cy/2-ySign*(bm.bmHeight+iStep)/2,xSign*(bm.bmWidth+iStep),ySign*(bm.bmHeight)+iStep,hdcmem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
}
EndPaint(hwnd,&ps);

SelectObject(hdcmem,hOldBitmap);
SelectObject(hdcmem,hOldBrush);
chocolate_zql 2010-05-16
  • 打赏
  • 举报
回复
麻烦各位帮我解决下吧,谢谢了
chocolate_zql 2010-05-12
  • 打赏
  • 举报
回复
麻烦诸位帮我看看我上面用的双缓冲技术哪里用的不对,解决后马上给分
xiuxianshen 2010-05-10
  • 打赏
  • 举报
回复
自己找点双缓冲的例子看看吧
双缓冲例子
chocolate_zql 2010-05-10
  • 打赏
  • 举报
回复
这是我根据3搂给的例子新改的WM_PAINT消息里的语句,帮我看看哪里有问题,改变窗口大小时还是会闪烁。
PAINTSTRUCT ps;
HDC hdcmem,hOldMemdc;
HBITMAP hOldBitmap,hMemBitmap;
RECT rect;
hDC=BeginPaint(hwnd,&ps);
hdcmem=CreateCompatibleDC(hDC);
hOldMemdc=CreateCompatibleDC(hDC);
GetClientRect(hwnd,&rect);
hMemBitmap=CreateCompatibleBitmap(hDC,rect.right-rect.left,rect.bottom-rect.top);
hOldBitmap=(HBITMAP)SelectObject(hOldMemdc,hMemBitmap);
SelectObject(hOldMemdc,CreateSolidBrush(RGB(0,0,0)));
Rectangle(hOldMemdc,rect.left,rect.top,rect.right,rect.bottom);
hOldBitmap=(HBITMAP)SelectObject(hdcmem,hBitmap);
if(bStretch==false)
{
BitBlt(hOldMemdc,0,0,bm.bmWidth+iStep,bm.bmHeight+iStep,hdcmem,0,0,SRCCOPY);
SelectObject(hdcmem,hOldBitmap);
BitBlt(hDC,cx/2-bm.bmWidth/2,cy/2-bm.bmHeight/2,bm.bmWidth+iStep,bm.bmHeight+iStep,hOldMemdc,0,0,SRCCOPY);
}
else
StretchBlt(hDC,cx/2-xSign*(bm.bmWidth+iStep)/2,cy/2-ySign*(bm.bmHeight+iStep)/2,xSign*(bm.bmWidth+iStep),ySign*(bm.bmHeight)+iStep,hdcmem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
EndPaint(hwnd,&ps);
DeleteDC(hdcmem);
DeleteDC(hOldMemdc);
DeleteObject(hMemBitmap);
BloodFighter 2010-05-09
  • 打赏
  • 举报
回复
有一个CMemDC类,网络上流传很多,你可以自己搜搜,用法非常简单,就是浪费了点效率
Eleven 2010-05-09
  • 打赏
  • 举报
回复
WM_PAINT消息里使用双缓冲。。。但是你并没有使用。。。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧