首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

在API中如何解决鼠标拉动图片时的闪烁白条(纯API代码)

2012-02-21 
在API中怎么解决鼠标拉动图片时的闪烁白条(纯API代码)在API中怎么解决鼠标拉动图片时的闪烁白条(纯API代码

在API中怎么解决鼠标拉动图片时的闪烁白条(纯API代码)
在API中怎么解决鼠标拉动图片时的闪烁白条(纯API代码)

网上有很多关于这个的问题   但是都是MFC的代码  

都是说的双重缓存技术,但是我不知道在纯API怎么实现

我现在正在学API   还没有接触MFC   所以看不懂MFC代码

//以下是我的代码   麻烦大家帮我   这代码应该怎么改才不会闪烁


---------------------------------
#include   <windows.h>
#include   <stdio.h>
#include   "resource.h "
HDC   hdc,hdcBit;//定义图形句柄
HBITMAP   hBm;
BITMAPbm;
LRESULT   CALLBACK   WndProc(HWND   hWnd,   UINT   message,WPARAM   wParam,   LPARAM   lParam);//申明窗口处理函数

//-------初始化窗口类---------------------------------
int   APIENTRY   WinMain(
  HINSTANCE   hInstance,             //应用程序当前实例句柄
  HINSTANCE   hPrevInstance,     //应用程序其他实例句柄
  LPTSTR   lpCmdLine,                   //指向程序命令行参数的指针
  int   nCmdShow                             //应用程序开始执行时窗口显示方式的整数值标识
  )
{
HWND   hwnd;                   //定义窗口句柄
MSG   Msg;                       //定义消息的类
WNDCLASS   wndclass;   //定义窗口的类
char   lpszClassName[]= "窗口 ";   //定义窗口类名
char   lpszTitle[]= "我的窗口 ";   //定义窗口标题
wndclass.style=0;     //设置窗口样式
wndclass.lpfnWndProc=WndProc;//定义窗口处理函数
wndclass.cbClsExtra=0;//窗口类无扩展
wndclass.cbWndExtra=0;//窗口实例无扩展
wndclass.hInstance=hInstance;//当前实例句柄
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);//窗口最小化图标为缺省
wndclass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDB_BITMAP));//窗口采用箭头光标
wndclass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);//窗口背景色为白色
wndclass.lpszMenuName= "Menu ";//窗口中无菜单
wndclass.lpszClassName=lpszClassName;//定义窗口类名
//-------初始化窗口类---------------------------------


//-------注册窗口---------------------------------
if(!RegisterClass(&wndclass))   //注册窗口
{
MessageBeep(0);   //如果注册失败,则发出警告
return   FALSE;   //返回为假
}
//-------注册窗口---------------------------------


//-------创建窗口---------------------------------
hwnd=CreateWindow(  
lpszClassName,   //窗口类名
lpszTitle,           //窗口标题名
WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,   //创建窗口的样式,WS_VSCROLL垂直滚动条,WS_HSCROLL水平滚动条
100,100,               //窗口左上角坐标
800,600,               //窗口宽度和度高
NULL,                     //该窗口的父窗口句柄
NULL,                     //窗口主菜单句柄
hInstance,           //创建窗口的应用程序当前句柄
NULL                       //指向一个传递给窗口的参数值的指针  
);  
//-------创建窗口---------------------------------

hBm=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP));
GetObject(hBm,sizeof(BITMAP),(LPVOID)&bm);
ShowWindow(hwnd,nCmdShow);     //显示窗口函数
UpdateWindow(hwnd);                   //刷新窗口函数

//-------消息循环---------------------------------
while   (GetMessage(&Msg,NULL,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);


}
return   (int)   Msg.wParam;
}
//-------消息循环---------------------------------

//-------窗口处理函相数------------------------------
LRESULT   CALLBACK   WndProc(HWND   hwnd,   UINT   message,WPARAM   wParam,   LPARAM   lParam)
{
static   HINSTANCE           hInst   ;
PAINTSTRUCT   ps;//定义指向包含绘图信息的结构变量
static   POINT   nPos,oPos,aPos;
static   BOOL   ndw=FALSE;
char   str[20];
switch(message)
{
case   WM_CREATE:
hdc=GetDC(hwnd);
hdcBit=CreateCompatibleDC(hdc);
hBm=CreateCompatibleBitmap(hdc,bm.bmWidth,bm.bmHeight);//双重缓存
hInst   =   ((LPCREATESTRUCT)lParam)-> hInstance;//   获取程序实例句柄
SetClassLong(hwnd,   GCL_HICON,   (LONG)LoadIcon(hInst,   MAKEINTRESOURCE(IDB_BITMAP)));
SetCursor(LoadCursor(hInst,   MAKEINTRESOURCE(IDB_BITMAP)));
ReleaseDC(hwnd,hdc);
break;
case   WM_LBUTTONDOWN:
if(LOWORD(lParam)> =aPos.x&&LOWORD(lParam) <=aPos.x+bm.bmWidth&&HIWORD(lParam)> =aPos.y&&HIWORD(lParam) <=aPos.y+bm.bmHeight)
{
SetCursor(LoadCursor(hInst,MAKEINTRESOURCE(IDC_CURSOR)));
nPos.x=LOWORD(lParam);
nPos.y=HIWORD(lParam);
ndw=TRUE;
}
break;
case   WM_RBUTTONDOWN:
InvalidateRect(hwnd,NULL,TRUE);
break;
case   WM_LBUTTONUP:
if(ndw==TRUE)
{
aPos.x=aPos.x+oPos.x;
aPos.y=aPos.y+oPos.y;
ndw=FALSE;
SetCursor(LoadCursor(NULL,IDC_ARROW));
InvalidateRect(hwnd,NULL,TRUE);
}
break;
case   WM_MOUSEMOVE:
if(ndw==TRUE)
{
oPos.x=LOWORD(lParam)-nPos.x;
oPos.y=HIWORD(lParam)-nPos.y;

InvalidateRect(hwnd,NULL,TRUE);
ReleaseDC(hwnd,hdc);
}
else
SetCursor(LoadCursor(NULL,IDC_ARROW));
if(LOWORD(lParam)> =aPos.x&&LOWORD(lParam) <=aPos.x+bm.bmWidth&&HIWORD(lParam)> =aPos.y&&HIWORD(lParam) <=aPos.y+bm.bmHeight)
SetCursor(LoadCursor(hInst,MAKEINTRESOURCE(IDC_CURSOR)));
break;
case   WM_PAINT:
hdc   =   BeginPaint(hwnd,   &ps);   //开始绘图
SelectObject(hdcBit,hBm);
if(ndw==FALSE)
StretchBlt(hdc,aPos.x,aPos.y,bm.bmWidth,bm.bmHeight,hdcBit,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
else
StretchBlt(hdc,aPos.x+oPos.x,aPos.y+oPos.y,bm.bmWidth,bm.bmHeight,hdcBit,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
sprintf(str, "%d,%d ",aPos.x,aPos.y);
TextOut(hdc,0,0,str,strlen(str));
EndPaint(hwnd,&ps);//结束绘图
return   0;

case   WM_DESTROY://退出消息
DeleteObject(hdcBit);
PostQuitMessage(0);//退出处理函数
return   0;
default:   //缺省消息处理函数
return   DefWindowProc(hwnd,message,wParam,lParam);
}
return(0);
}
//-------窗口处理函相数------------------------------


[解决办法]
InvalidateRect是为了简化刷新的处理, 通常应在背景反差不大的情况下使用. 在很多入门级的代码示例中用的较多。

如果简单的使用InvalidateRect, 即使使用双缓冲,实际应用中也免不了会闪烁。
比较实用的解决方法是在原使用InvalidateRect的地方直接绘制(别怕麻烦)。可以定义一个函数OnDraw(HDC hdc);在WM_PAINT、WM_MOUSEMOVE等地方直接调用OnDraw


热点排行