反色出耐颤现-反色消失 交替多了速度快了,就成闪烁一样了!
屏蔽反色就可以了昌薯败,和EDIT BOX里刷屏手猜时屏蔽反色一样的道理!
相信很多人在做图形界面开发时,常常会遇到屏幕闪烁的情况,当然我也不例外。前段时间用vc++做了一个小游戏——五子棋,前期阶段主要做的是逻辑层面的编码,没有太注意屏幕闪烁的情况,到了后来实现悔棋功能时需要擦除已下过的棋子进行重绘,屏幕闪烁厉害,急需解决——有哪个玩家愿意玩屏幕老闪烁的游戏? 通常来说程序根据需要调用Invalidate(FALSE)使窗口客户区无效引起重绘,然后在窗口OnPaint函数(基于文档视图的程序则是OnDraw)中进行稳定绘图就行了。但是,我们在OnPaint中进行多重绘制(画背景、棋盘、棋子等),前后绘制的反差造成了闪烁现象。以前知道Java中解决屏幕闪烁问题是用双缓冲的方法,现在发现在vc++中也是可以这么做的。简单来锋蚂册说,双缓冲就是先把需要绘银宏制的东西全部一口气画在内存中,最后把内存中的数据搬到屏幕上显示。下面是双缓冲的代码实现例子:
点击(此处)折叠或打开
void C****Dlg::OnPaint()
{
if (IsIconic())
{
//......
}
else
{
//CDialog::OnPaint()//不要调用这个
CPaintDC dc(this)//对话框的dc//通常CPaintDC用来响应WM_PAINT消息。
//CPaintDC是从CDC派生出来的:在构造时自动调用CWnd::BeginPaint,析构时调用CWnd::EndPaint。
RECT rect// 客户区矩形
GetClientRect(&rect)
// 使用双缓冲避免屏幕刷新时闪烁
CDC dcMem// 内存dc
CBitmap bmpMem// 位图
dcMem.CreateCompatibleDC(NULL)// 创建兼容dc
bmpMem.CreateCompatibleBitmap(&dc, rect.right-rect.left, rect.bottom-rect.top)//创建跟客户区域大小一样的(空)位图
// 把位图选到设备上下文环境中
CBitmap *pOld = dcMem.SelectObject(&bmpMem)
//dcMem.FillSolidRect(&rect, RGB(255,255,255))
// 在此处将绘制内容全画到dcMem内存中,(即把之前使用CPaintDC绘制的dc换成dcMem即可)
DrawTable(dcMem)//画棋盘
DrawChesses(dcMem)// 画棋子
//......
// 至此,内存中绘图完毕
// 从内存拷贝到设备dc
dc.BitBlt(0, 0, rect.right - rect.left, rect.bottom - rect.top, &dcMem, 0, 0, SRCCOPY)
dc.SelectObject(pOld)
// 释放资源
bmpMem.DeleteObject()
dcMem.DeleteDC()
}
}
PS:屏幕闪烁问题虽然得到解决了,但是窗口上的按钮却还会闪(可能是因为使用图片按钮的缘故才那么明显),当然这个我也是无法容忍的。
默认情况窗口风格没有设置了WS_CLIPCHILDREN属性,所以父窗口刷新时子窗口也跟着刷新,于是产生按钮闪烁现象,于是我在游戏开始时给窗口加上WS_CLIPCHILDREN属性:
ModifyStyle(0, WS_CLIPCHILDREN)
这样Invalidate 时按钮就不会闪烁了。
如果窗口加上了WS_CLIPCHILDREN属性,当需要切换背景图片时,按钮因为没有刷新所以会被盖住,直到(鼠标移到按钮上)重绘时才会显示出来。
解决方法:
1)添加BOOL类型的成员变量bgroundChanged,初始化为FALSE;
2)在切换背景图片前调用ModifyStyle(WS_CLIPCHILDREN, 0)去掉物友WS_CLIPCHILDREN属性,并把bgroundChanged设置为TRUE;
3)在OnPaint中最后增加
if (TRUE == bgroundChanged)
{
bgroundChg = FALSE
ModifyStyle(0, WS_CLIPCHILDREN)
}
隐藏,显示其他程序的托盘图标(此为Delphi代码)Delphi
USES Commctrl,ShellAPI
procedure TForm1.Button1Click(Sender: TObject)
var TBHWND:HWND
i,count:integer
PID,PRC: THandle
Buff: PChar
Info: _TBBUTTON
R: Cardinal
S: array[0..1024] of char
begin
TBHWND := FindWindow('Shell_TrayWnd', nil) // Shell_TrayWnd: 任务栏窗口
TBHWND := FindWindowEx(TBHWND, 0, 'TrayNotifyWnd', nil)// TrayNotifyWnd:任慧卜差务栏类
TBHWND := FindWindowEx(TBHWND, 0, 'ToolbarWindow32', nil) // ToolbarWindow32:托弊裤盘类,是一个toolbar// wd:=FindWindowEx(wd,0,'SysPager',NIL)
if TBHWND=0 then exit
GetWindowThreadProcessId(TBHWND, @PID)
PRC := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False, PID)
Buff := VirtualAllocEx(PRC, nil, 4096, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE)
count:=SendMessage(TBHWND,TB_BUTTONCOUNT,0 , 0) //托盘中button的个数,不一定是图前皮标的个数,有些button是隐藏的。
for i:=0 to count-1 do
begin
FillChar(Info, SizeOf(Info), 0)
WriteProcessMemory(PRC, Buff, @Info, SizeOf(Info), R) //消息使用的内存空间必须在Shell之内,所以利用ReadProcessMemoery和WriteProcessMemory。
SendMessage(TBHWND, TB_GETBUTTON, i, integer(Buff))
ReadProcessMemory(PRC, Buff, @Info, SizeOf(Info), R)
SendMessage(TBHWND, TB_GETBUTTONTEXT, Info.idCommand, integer(integer(@Buff[0]) + SizeOf(Info)))
ReadProcessMemory(PRC, Pointer(integer(@Buff[0]) + SizeOf(Info)), @S[0], SizeOf(S), R)
if pos('QQ',StrPas(S))>0 then//如果button的TEXT中包含'QQ'
SendMessage(TBHWND, TB_DELETEBUTTON, i, 0) //删除
Form1.Memo1.Lines.Add(StrPas(S)) //在MEMO1中记录所有button的TEXT
end
VirtualFreeEx(PRC, Buff, 0, MEM_RELEASE)
CloseHandle(PRC)
end
相关的消息:
TCM_ADJUSTRECT TB_ADDBITMAP
TCM_DELETEALLITEMTB_ADDBUTTONS TB_GETMAXSIZE TB_SAVERESTORE
TCM_DELETEITEM TB_ADDSTRINGTB_GETOBJECTTB_SETANCHORHIGHLIGHT
TCM_DESELECTALL TB_AUTOSIZE TB_GETPADDING TB_SETBITMAPSIZE
TCM_GETCURFOCUS TB_BUTTONCOUNT TB_GETRECT TB_SETBUTTONINFO
TCM_GETCURSELTB_BUTTONSTRUCTSIZE TB_GETROWS TB_SETBUTTONSIZE
TCM_GETEXTENDEDSTYLE TB_CHANGEBITMAP TB_GETSTATE TB_SETBUTTONWIDTH
TCM_GETIMAGELIST TB_CHECKBUTTON TB_GETSTYLE TB_SETCMDID
TCM_GETITEM TB_COMMANDTOINDEX TB_GETTEXTROWS TB_SETDISABLEDIMAGELIST
TCM_GETITEMCOUNT TB_CUSTOMIZETB_GETTOOLTIPS TB_SETEXTENDEDSTYLE
TCM_GETITEMRECT TB_DELETEBUTTON TB_HIDEBUTTON TB_SETHOTIMAGELIST
TCM_GETROWCOUNT TB_ENABLEBUTTON TB_HITTEST TB_SETHOTITEM
TCM_GETTOOLTIPS TB_GETANCHORHIGHLIGHT TB_INDETERMINATETB_SETIMAGELIST
TCM_HIGHLISHTITEMTB_GETBITMAPTB_INSERTBUTTON TB_SETINDENT
TCM_HITTEST TB_GETBITMAPFLAGS TB_INSERTMARKHITTESTTB_SETINSERTMARK
TCM_INSERTITEM TB_GETBUTTONTB_ISBUTTONCHECKED TB_SETINSERTMARKCOLOR
TCM_REMOVEIMAGE TB_GETBUTTONINFOTB_ISBUTTONENABLED TB_SETMAXTEXTROWS
TCM_SETCURFOCUS TB_GETBUTTONSIZETB_ISBUTTONHIDDEN TB_SETPADDING
TCM_SETCURSELTB_GETBUTTONTEXTTB_ISBUTTONHIGHLIGHTED TB_SETPARENT
TCM_SETEXTENDEDSTYLE TB_GETDISABLEDIMAGELIST TB_ISBUTTONINDETERMINATETB_SETROWS
TCM_SETIMAGELIST TB_GETEXTENDEDSTYLE TB_ISBUTTONPRESSED TB_SETSTATE
TCM_SETITEM TB_GETHOTIMAGELIST TB_LOADIMAGES TB_SETSTYLE
TCM_SETITEMEXTRA TB_GETHOTITEM TB_MAPACCELERATOR TB_SETTOOLTIPS
TCM_SETITEMSIZE TB_GETIMAGELIST TB_MARKBUTTON
TCM_SETMINTABWIDTH TB_GETINSERTMARKTB_MOVEBUTTON
TCM_SETPADDING TB_GETINSERTMARKCOLOR TB_PRESSBUTTON
TCM_SETTOOLTIPS TB_GETITEMRECT TB_REPLACEBITMAP
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)