您的位置:程序门 -> vc/mfc -> 图形处理/算法



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


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


在api中怎么解决鼠标拉动图片时的闪烁白条(纯api代码)[已结贴,结贴人:ivanzone]
发表于:2007-04-06 23:14:18 楼主
在api中怎么解决鼠标拉动图片时的闪烁白条(纯api代码)

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

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

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

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


---------------------------------
#include   <windows.h>
#include   <stdio.h>
#include   "resource.h "
hdc   hdc,hdcbit;//定义图形句柄
hbitmap   hbm;
bitmap bm;
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);
}
//-------窗口处理函相数------------------------------
发表于:2007-04-07 13:39:561楼 得分:0
画面闪烁主要旭背景要重画,请将代码中所有的invalidaterect(hwnd,null,true);第三个参数改为false再试试
发表于:2007-04-07 14:02:462楼 得分:20
invalidaterect是为了简化刷新的处理,   通常应在背景反差不大的情况下使用.   在很多入门级的代码示例中用的较多。

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


发表于:2007-04-08 17:30:453楼 得分:0
双缓冲处理,先在内存绘制,然后再显示。
发表于:2007-04-08 22:04:094楼 得分:0
chehw(chehw)   说的很有道理
我那样做了   是不闪烁了   但是鼠标动图片经过的所有位置会留下以前的痕迹
意思就是图片以外的所有区域没有被刷新
我想   如果是不用刷新根本解决不了这个问题
只有解决了刷新的时候产生的闪烁才能根本解决
希望会的帮帮小弟!
发表于:2007-04-08 22:09:275楼 得分:0
chehw(chehw)     说的很有道理    
我那样做了     是不闪烁了     但是鼠标动图片经过的所有位置会留下以前的痕迹    
意思就是图片以外的所有区域没有被刷新  
你说的方法也相当于是把invalidaterect的最后个值设置为false的效果
我想     如果是不用刷新根本解决不了这个问题    
invalidaterect(hwnd,&rect,false)也不能解决问题
只有解决了刷新的时候产生的闪烁才能根本解决  
希望会的帮帮小弟!
发表于:2007-04-09 00:14:486楼 得分:0
记录每次移动的位置,   根据记录的位置(rtprev),   先用fillrect或patblt或bitblt等方法恢复原背景,   然后再用ondraw在移动后的位置上bitblt图片.   并记录新位置至rtprev
发表于:2007-04-11 15:48:447楼 得分:0
invalidaterect决不是入门级才使用的函数。相反它的用法是很有技巧的,像上面的例子,用invalidaterect来恢复背景,要比用fillrect或patblt或bitblt等方法好的多。前提是设置失效的区域,你不要直接重绘。
好好体会一下invalidaterect函数吧。会给你得绘图带来高效率的。
发表于:2007-04-11 17:48:038楼 得分:0
invalidaterect(hwnd,   null,);
第二个参数设为null后,标记的是整个客户区无效,均需重绘.   写代码时会比较简单,但它是利用系统的消息机制,   通知系统准备重绘.   这种方法即使后面紧跟updatewindow,   也必须要等到系统处理完相关消息后才能生效,   如果背景反差大且绘制过程复杂,闪烁很难避免.

在wm_size/wm_vscroll/wm_hscroll等消息的处理中,先getdc然后直接绘制,   虽然增加了额外的代码量,   但这是高效的方法(不必等系统发消息后再处理,   且在多数情况下不必重绘整个客户区)
发表于:2007-04-11 17:51:339楼 得分:0
invalidaterect的高效通常指的是开发过程的高效(比较省事),   决不是程序运行的高效.
发表于:2007-04-12 17:44:0810楼 得分:0
先在内存中建立一张与当前底图一样的图片,然后根据相关的位置把要绘的图片绘在那个底图上,再显示出来,这样就可以解决你这样的问题了。
发表于:2007-04-12 18:59:0711楼 得分:0
我有一个图象处理方面的问题,请教
简单的说:比如有十张扑克牌,先拍一张照片,取走一张,在拍一张照片,通过程序判断取走了那张
有没有那位做过类似的东西。给我提供些资料或者方向什么的  
有偿提供实现功能的源代码也可以    
联系地址:上海闵行区辛庄地铁站
联系人:王先生
联系电话:13636579369
qq:82268578
msn:wangganling@hotmail.com
e_mail:wanggangling_1@hotmail.com


快速检索

最新资讯
热门点击