首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 将Frame上的控件转移到form上出现的闪烁问题 [已结帖,结帖人:luincnyou]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • luincnyou
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-08-18 18:05:26 楼主
    我建立了一个Frame,名为frmTool,我的主窗口名为frmMain。我想实现点击lblTool(一个Label控件)后将frmTool动态载入,然后将frmTool上的所有控件转移到主窗口中。
    以下代码可以正常工作。开发、运行环境:Windows Vista+Delphi 2007
    可是却出现了奇怪的问题:
    1:如果frmTool中有TMemo的话,将这个memo转移到主窗口后,用鼠标来回划过memo的边缘,memo的边框比正常时的粗(没有用过Vista的可能不太清楚,在Vista下,用鼠标划过memo/edit的边缘,边缘会有暂时变成蓝色并稍微加粗的效果,此处说的“比正常时的粗”的“正常”就是指此)。
    2.转移后的TListView和TSpeedButton控件用鼠标在上面来回划过的话会出现明显的闪烁。
    3.在frmTool上PageControl控件的第一页中如果有TButton或TBitbtn的话,点击lblTool后整个主窗口会闪烁一下(事实上我的程序中还有其它的Frame,这个问题在其它Frame中并不存在,不知道为什么),如果是TSpeedButton则正常(我猜想这是由于TSpeedButton继承自TControl而不是TWinControl的缘故,但不知道是为什么)。
    我觉得这三个问题都是由一个问题引起的,但不知道是什么原因。问题有点麻烦,希望大牛们能够费心看一下,谢谢!

    代码附下:
    Delphi(Pascal) code
    type TMyFrame = class of TFrame; ... 点击lblTool后: procedure TfrmMain.lblToolClick(Sender: TObject); var i: integer; begin //载入TfrmTool(frmTool是之前建立的Frame) if LoadFrameByClassName(TfrmTool) then begin //循环将frmTool上的所有控件的Parent设成frmMain //注:下面的Ffrm定义在TfrmMain中:Ffrm: TFrame;在LoadFrameByClassName中赋予Ffrm的值; for i := Ffrm.ControlCount - 1 downto 0 do Ffrm.Controls[i].Parent := frmMain; end; end; //LoadFrameByClassName函数:返回True为建立成功 function TfrmMain.LoadFrameByClassName(FrameClassName: TMyFrame): boolean; begin Result := False; if Assigned(Ffrm) then FreeAndNil(Ffrm); Ffrm := FrameClassName.Create(self); //设Ffrm为不可见,因为要的是Ffrm中的控件,Ffrm本身没有用 Ffrm.Visible := False; Result := True; end;
    100  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • chenzhuo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 13:36:351楼 得分:20
    将容器控件的doublebuffer := true;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Harryfin
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 13:40:072楼 得分:80
    doublebuffered估计不行,用这个试试:

    操作前
    SendMessage(Form.Handle, WM_SETREDRAW, 0, 0);

    操作后
    SendMessage(Form.Handle, WM_SETREDRAW, 1, 0);
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • luincnyou
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 14:10:383楼 得分:0
    To:chenzhuo
    谢谢,加上DoubleBuffered:=True;后,第三个问题解决了,但是前两个问题依旧存在。
    To:Harry
    我在lblToolClick事件的begin后加SendMessage(Handle, WM_SETREDRAW, 0, 0); ,end;前加SendMessage(Handle, WM_SETREDRAW, 1, 0); ,点击lblTool后有的控件只显示出了轮廓,需要鼠标在上面掠过才能显示完整,而且闪烁的问题依旧没有改变。

    我自己尝试做了以下步骤:
    1.开发时手动将frmTool放到主窗体上而不是动态载入,而且不再进行控件的转移,闪烁问题依然存在;
    2.新建一个Frame,在上面放一个TMemo,不存在闪烁问题。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Harryfin
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 14:30:124楼 得分:0
    忘记说了,SETREDRAW 1后你还要手动控制下窗体重绘:Form.Invalidate
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Harryfin
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 14:31:545楼 得分:0
    闪烁的原因就是因为窗体多次重绘了,哪个地方闪就让哪个地方禁止重绘,最后再一次过重绘。试试看
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • luincnyou
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 16:40:266楼 得分:0
    To:Harry
    我的代码是这样的:
    Delphi(Pascal) code
    procedure TfrmMain.lblToolClick(Sender: TObject); var i: integer; begin SendMessage(Handle, WM_SETREDRAW, 0, 0); //载入TfrmTool(frmTool是之前建立的Frame) if LoadFrameByClassName(TfrmTool) then begin //循环将frmTool上的所有控件的Parent设成frmMain //注:下面的Ffrm定义在TfrmMain中:Ffrm: TFrame;在LoadFrameByClassName中赋予Ffrm的值; for i := Ffrm.ControlCount - 1 downto 0 do Ffrm.Controls[i].Parent := frmMain; end; SendMessage(Handle, WM_SETREDRAW, 1, 0); Invalidate; end;

    这个代码和不加Invalidate的一样。是不是代码放的位置不对?谢谢

    我把闪烁时的视频录了下来,视频中TMemo闪了4次,pgc控件闪了2次。
    http://www.fileurls.com/utvudo
    (大小:305KB,8月26日前有效)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Harryfin
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-23 17:30:167楼 得分:0
    用invalidate好像真的刷新失败,后来用了RedrawWindow就可以了,应该还有其它重画的方法。前后还是加WM_SETREDRAW
    Delphi(Pascal) code
    RedrawWindow(Handle, nil, 0, RDW_INVALIDATE + RDW_ALLCHILDREN + RDW_NOINTERNALPAINT);
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved