开发环境:
Visaul Studio 2008 - C#.Net问题描述:
MDI窗体,样子像Windows的Explorer资源管理器,侧边栏里的条目用于切换各个MDI子窗体,因显示时出现花屏现象(不能一次全部完整显示),曾采取如下方案进行优化:1、 把切换时动态创建、释放的窗体资源修改成全局的,用Form.Show()、Form.Hide()取代。
效果不明显。2、 使用Windows API 中的LockWindowUpdate与SendMessage函数:frmChild1.Hide( );  // 隐藏当前显示的子窗体LockWindowUpdate(this.Handle);  // 锁定父窗体
frmChild2.Show( );               // 显示窗体等其他需要再显示前做的事
LockWindowUpdate (IntPtr.Zero);   // 解锁父窗体
RedrawWindow (this.Handle, IntPtr.Zero, IntPtr.Zero, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);  // 立即强制重绘父窗体及其所有子窗体效果好转,但人眼还能看到一些花屏现象,仍不能一次全部完整显示。3、 使用Windows API中的SendMessage函数: frmChild1.Hide( );SendMessage(this.Handle, WM_SETDRAW, false, null);  // 禁止窗体中的绘制操作 ----- 1
frmChild2.Show( );               // 显示窗体等其他需要再显示前做的事
SendMessage(this.Handle, WM_SETDRAW, true, null);  // 解除禁止绘制操作     ----- 2
RedrawWindow (this.Handle, IntPtr.Zero, IntPtr.Zero, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);   // 立即强制重绘父窗体及其所有子窗体4、 几乎可以全部显示完整,达到了显示要求。但是,鼠标点击切换子窗体时,如果在窗体切换没有完成 (frmChild2未显示出来frmChild1未消失时) 时再次点击窗体任意区域,就会激活隐藏在父窗体后的其他应用程序的窗体,然后屏幕就花了,如果后面是记事本,鼠标形状就变成了输入的形状,父窗体的、其他应用程序的,都显示不完整,鼠标移过的地方,其他应用程序的窗体才显示。
确定问题就在1与2之间,SendMessage函数使用的问题。想要的效果是:鼠标在父窗体任意区域点击都只对当前窗体有效,不会激活后面的窗体,也不会变成后面窗体中鼠标的形状。
弄了好久了,。。希望能得到解决 谢~

解决方案 »

  1.   

    在设计时中窗体櫣放个treeview,右边放个panel,
    treeview中每项对应一个单独的单例窗体,
    点击时清空panel,再将对应的窗体加进来并设为panel的子项
    不要再放其它多的东西和过多的逻辑判断,
    如果有且有必要,用异步在后台操作
      

  2.   

    是一个上位机,MDI界面,界面中有部分自定义控件(主要是设置时看着直观),在用SendMessage解决大量控件的问题中,测试效果不明显,但是偶然发现用在这个程序中有效(可以减少花屏现象),只是:

    鼠标点击切换子窗体时,如果在窗体切换没有完成 (frmChild2未显示出来frmChild1未消失时) 时再次点击窗体任意区域,就会激活隐藏在父窗体后的其他应用程序的窗体,然后屏幕就花了,如果后面是记事本,鼠标形状就变成了输入的形状,父窗体的、其他应用程序的,都显示不完整,鼠标移过的地方,其他应用程序的窗体才显示。
      

  3.   

    这,没弄明白,怎么MDI窗体切换你点击能透过当前的窗体激活后面的其他程序?
      

  4.   


    这个和我问题一样的,
    http://topic.csdn.net/u/20091127/11/9b067481-7578-46ba-868d-d8d616d0ae41.html?seed=155608517&r=78439253#r_78439253
      

  5.   

    Jeffery在Windows 核心编程都说了,Windows资源管理器系统对他进行了优待和特殊处理:在开发应用程序的用户界面时,很可能出现对线程的另一种误用。几乎在所有的应用程序中,所有用户界面的组件(窗口)应该共享同一个线程。单个线程应该创建窗口的所有子窗口。有时在不同的线程上创建不同的窗口是有用的,不过这种情况确实非常少见。通常情况下,一个应用程序拥有一个用户界面线程,用于创建所有窗口,并且有一个G e t M e s s a g e循环。进程中的所有其他线程都是工作线程,它们与计算机或I / O相关联,但是这些线程从不创建窗口。另外,一个用户界面线程通常拥有比工作线程更高的优先级,因此用户界面负责向用户作出响应。虽然单个进程拥有多个用户界面线程的情况并不多见,但是这种情况有着某种有效的用途。Windows资源管理器为每个文件夹窗口创建了一个独立的线程。它使你能够将文件从一个文件夹拷贝到另一个文件夹,并且仍然可以查看你的系统上的其他文件夹。另外,如果Windows资源管理器中存在一个错误,那么负责处理文件夹的线程可能崩溃,但是仍然能够对其他文件夹进行操作,至少在执行的操作导致其他文件夹也崩溃之前,仍然可以对它们进行操作。
      

  6.   


    那我该怎么办呢?SendMessage(false)后怎么才能避免
    鼠标点击时不会激活后面的窗口呢?
      

  7.   

    为了阻止窗体中的绘制操作,我这样做的:
    SendMessage函数中,送消息 WM_SETREDRAW,设置SETREDRAW为FALSE,导致窗口不进行绘制。
    此时,看到的窗体是假的,鼠标形状是后面应用程序的形状;
    鼠标划过,后面的应用程序就显示出来了。
    人眼看到的就是“花屏”。
    除非激活其他窗体把屏幕覆盖,才把“花”的地方清除,
    或者直到 SETREDRAW设置为TRUE,然后RedrawWindow,LockWindowUpdate的效果不理想,SETREDRAW会出现“花屏”,
    如何解决使用SETREDRAW带来的的花屏?????????
      

  8.   

    为了阻止窗体中的绘制操作,我这样做的:
    SendMessage函数中,送消息 WM_SETREDRAW,设置SETREDRAW为FALSE,导致窗口不进行绘制。
    此时,看到的窗体是假的,现象:
    鼠标形状是后面应用程序的形状
    鼠标划过,后面的应用程序就显示出来了
    人眼看到的就是“花屏”。
    除非激活其他窗体把屏幕覆盖,才把“花”的地方清除
    或者直到 SETREDRAW设置为TRUE然后RedrawWindow,[color=#0000FF]LockWindowUpdate的效果不理想,SETREDRAW会出现“花屏”,
    如何解决使用SETREDRAW带来的的花屏?????????[/color]