none
如何实现让子窗口显示在任务栏上的? RRS feed

  • 问题

  • 在Excel在打开多个文件的时候,每一个子窗口都会有一个对应的任务栏按钮。刚开始我以为是SDI形式的程序,但是Excel上都有重新排列的选项,这样就可以让多个子窗口在同一个MainFrame中显示出来了。但是当我用MFC建立一个MDI的程序时,新建和打开一个文档都不会让子窗口显示在任务栏上。根据MSDN的说明一个子窗口是不可能在任务栏上显示一个按钮的,但是偏偏Excel做到了。

    这个问题很困扰我,而且我也搜索过多次,在搜索的过程中我也想到了几种方案: 
    方案1:网上有一个例子MSDI,但是它的效果仅仅类似于MTI的效果,并不能把多个子窗口显示在同一个MainFrame中。 
    方案2:利用ITaskbarList, 这个组件很是怪异,因为在一个程序或者说一个进程中我只能用AddTab增加一个任务按钮,然后无论再怎么调用AddTab都不能多增加一个了。而且,我的试验机器的操作系统是Vista的,在Vista上面的表现就更怪异了。调用AddTab是完全没有任何反应的,只能调用ActivateTab才能将一个任务按钮显示出来。 
    方案3:利用Shell Hook,想法就是通过截获HSHELL_XXX来获取窗口建立、激活和销毁的消息,这主要是为了能防止一个窗口在任务栏上显示按钮的。但问题是,即使我拦截了这些消息MainFrame的任务按钮还是显示出来的。而ShellProc中完全获取不到子窗口创建和销毁的消息。 
    方案4:利用SendMessage想任务栏发送消息或者直接获取到任务栏(ToolBarWindow32)的句柄把它转换成CToolBarCtrl指针直接增加一个按钮,但是前者会报告内存不能读的错误然后Explorer进程挂掉,而后者更甚直接把Explorer弄挂掉然后把我任务栏上的图标大小都改变了完全无法恢复。 
    方案5:利用SetParent或SetWindowLong方法设置子窗口的父窗口指针为空,这样子窗口就不算是一个子窗口了,然后也能在任务栏上显示出任务按钮来了。但是问题是,如果一个子窗口的父亲指针被设为空,整个程序基本都无法运行了,尤其是在MDI程序中一启动就挂掉了。
    而且我也用Spy++检查过,Excel中的子窗口是有父亲指针的,不是一个独立的窗口。 
    经过反复的实验这几种方案都不能达到Excel的效果,当然关于Hook方面的东西我不大熟悉,也不敢下断言Hook这种方法一定不行。 
    所以今天想问问各位高人,Excel到底是通过什么方法做到这点的?
    2009年12月4日 2:06

答案

全部回复

  • 这个没什么难的,把你的子窗口风格加上WS_EX_APPWINDOW  
    WS_EX_APPWINDOW  Forces a top-level window onto the taskbar when the window is visible.


    0xBAADF00D
    2009年12月4日 9:29
    版主
  • 这个没什么难的,把你的子窗口风格加上WS_EX_APPWINDOW  
    WS_EX_APPWINDOW  Forces a top-level window onto the taskbar when the window is visible.


    0xBAADF00D

         我试过这个方法了,但是没有任何效果。因为子窗口并不是top-level类型的,它是有父窗口的,所以即使设置了这个风格,也不会让子窗口显示在任务栏上。
         不好意思,试过的方法太多,并没有把这个列出来。
    2009年12月4日 10:11
  • 那你把它设成WS_POPUP的也行,有父窗口也能显示


    0xBAADF00D
    2009年12月4日 16:50
    版主
  • 那你把它设成WS_POPUP的也行,有父窗口也能显示


    0xBAADF00D

         这个方法我的确没试过,但是在MDI的中对ChildFrame的窗口风格增加WS_POPUP的时候就会有“空文档建立失败”的消息弹出,而且ChildFrame窗口也不会显示。
    2009年12月7日 1:18