WEB开发网
开发学院软件开发C语言 如何避免多控件窗体重新布局时闪烁 阅读

如何避免多控件窗体重新布局时闪烁

 2010-09-30 21:00:08 来源:WEB开发网   
核心提示: 关键一行在 this.SendMessage(11, 0, 0); 虾米意思呢? 它给自身Send了一个code为11的windows消息,11代表虾米?在windows消息定义中可以看到 WM_SETREDRAW = 0x0B (0x0B也就是11),这行代码的意思是告诉windows对Lis

关键一行在 this.SendMessage(11, 0, 0); 虾米意思呢? 它给自身Send了一个code为11的windows消息,11代表虾米?

在windows消息定义中可以看到 WM_SETREDRAW = 0x0B (0x0B也就是11),这行代码的意思是告诉windows对ListView控件停止重绘界面,直到显式要求重新绘制为止. 很牛叉对不对 :Dok,在EndUpdateInternal中又做了虾米?

internal bool EndUpdateInternal(bool invalidate)
{
    if (this.updateCount <= 0)
    {
        return false;
    }
    this.updateCount = (short) (this.updateCount - 1);
    if (this.updateCount == 0)
    {
        this.SendMessage(11, -1, 0);
        if (invalidate)
        {
            this.Invalidate();
        }
    }
    return true;
}

同样有一行代码: this.SendMessage(11, –1, 0); 11还是同一个意思,此时告知windows可以重绘ListView控件了

ok,到这时候应该明白这2个方法含义了吧,也就是说对子控件的操作都是在一个“冻结”的状态中进行的,等到所有准备工作就绪,才对最终状态重新绘制,因此界面就不会出现闪烁状态.

如何依葫芦画瓢?

要知道不是每个控件类都有提供BeginUpdate和EndUpdate方法,所以需要自己亲自打造一个

1. SendMessage如何来? 从windows api interop而来,很简单,有个工具可以提供所有api函数到c#方法的转换: P/Invoke Interop Assistant

2.11这个定义以及类似的东东怎么找? 强大的google或者bing可以帮忙 :D

至于代码怎么写,就不需要偶来操刀啦 :D

后记:

这样处理之后,是不是发现闪烁从此就不再出现了?但是……还有问题

拿一个无边框窗体举例,当它从Normal状态变为Maxmized(顺便设置TopMost为true),你会很高兴看到该窗体包含的子控件真的不闪了,从Maxmized回到Normal时,也不闪了,但是很诡异的问题发生了: 任务栏不见了?取而代之的是当前窗体的背景色??? 难道任务栏没有重绘回来???

发生什么事情了? 不是只让窗体的重绘停止了吗,怎么会影响到任务栏窗口?

ok,解决办法是有的,发个消息给任务栏窗口让它强制重绘,怎么写?

同样,对于.net中的任何控件,都自带Invalidate方法,通过调用该方法,可以强制重绘控件的整体或某矩形部分, 又要画瓢啦

在Invalidate中可以看到这么一行

SafeNativeMethods.RedrawWindow(new HandleRef(this.window, this.Handle), (NativeMethods.COMRECT) null, NativeMethods.NullHandleRef, 0x85);

现在的问题是,如何获取任务栏窗口句柄?  bing一把就会发现,很简单: FindWindow(“Shell_TrayWnd”, “”);

ok, 后面的事情就简单啦

再后记

不难发现,Control对象其实是自带BeginUpdateInternal方法的,但m$很恶毒的把它弄成internal的了… 而且只被少数几个控件享用: ListView,

上一页  1 2 

Tags:如何 避免 控件

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接