VC中关于屏幕闪烁的解决办法

VC中关于屏幕闪烁的解决办法,第1张

不是闪烁,是焦点选择的现象,区域被全选时自动反色,选择失效反色消失,或者反复重绘区域时反色,重绘完成反色消失!

反色出耐颤现-反色消失 交替多了速度快了,就成闪烁一样了!

屏蔽反色就可以了昌薯败,和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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12521008.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存