读书人

在API中如何解决鼠标拉动图片时的闪烁

发布时间: 2012-02-21 16:26:23 作者: rapoo

在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


读书人网 >VC/MFC

热点推荐