现在的位置: 首页 > 综合 > 正文

【转】将程序窗口嵌入到任务栏中

2012年10月12日 ⁄ 综合 ⁄ 共 3545字 ⁄ 字号 评论关闭

  今天我们来看看VB.NET怎样将程序窗口嵌入到任务栏(Taskbar)中,下图是我们实现的效果。

     
开始之前,小孟先简单介绍一下任务栏的组成,在这里小孟只介绍与我们的程序有关的部分。整个任务栏是有一个大的窗口容器(该容器类名是
Shell_TrayWnd)和一些窗口共同组成的,在这个类名是Shell_TrayWnd的容器中,有一个类名是ReBarWindow32的二级容
器。这个二级容器中包含的窗口在Win7和WinXP中是不同的(小孟使用的Win7,不过在这个程序中Win7和WinXP的效果都是一样的)。在
WinXP中,包含一个类名是MSTaskSwWClass的窗口外,这个窗口就是来显示任务栏按钮的(就是显示你打开了哪些窗口的那个区域,在这里小孟
叫他最小化窗口),还包含快速启动栏(在左侧以小图标显示,单击后会启动相应程序的那个区域);在Win7中只有一个类名是MSTaskSwWClass
的窗口,因为Win7中没有快速启动栏,虽然左侧也有一个类似快速启动的区域,但那个并不是快速启动,而是属于最小化窗口的一部分。以上就是与我们程序有
关的任务栏组成了,小孟这表达能力很有限,大家可能看不懂,so
小孟在下面贴了一张图。

=====================================================================================

Win7:

    红色区域:类名是Shell_TrayWnd的容器                       黄色区域:类名是ReBarWindow32的二级容器

   绿色区域:类名是MSTaskSwWClass的窗口

WinXP:

    红色区域:红色区域——类名是Shell_TrayWnd的容器          黄色区域:类名是ReBarWindow32的二级容器

    绿色区域:快速启动区域                                        
        
紫色窗口:类名是MSTaskSwWClass的窗口

=====================================================================================

      任务栏组成我们介绍完了,下面我们说说大体的思路。首先,我们要最小化窗口的width缩短,来给我们的程序腾出地方;然后,将我们的程序设置成任务栏的子窗口,以便于嵌入任务栏;最后,调整程序的大小和在任务栏中的位置。

准备工作做了这么多,下面正式开工。

新建一个【Windows窗体应用程序】。将窗体BorderStyle属性改成None来把窗体的边框去掉。然后在窗体上添加一个文本框,如下图所示:


下面开始写代码。

我们先把程序需要用到的API和structure来声明一下(先在类外面加上ImportsSystem.Runtime.InteropServices):

   '寻找窗口列表中第一个符合指定条件的顶级窗口
    Private Declare Function FindWindow Lib "user32" _
                    Alias "FindWindowA" (ByVal lpClassName As String, _
                                         ByVal lpWindowName As String) As Integer

    '在窗口列表中寻找与指定条件相符的第一个子窗口
    Private Declare Function FindWindowEx Lib "user32" _
                    Alias "FindWindowExA" (ByVal hWnd1 As Integer, _
                                           ByVal hWnd2 As Integer, _
                                           ByVal lpsz1 As String, _
                                           ByVal lpsz2 As String) As Integer

    '指定一个窗口的新父
    Private Declare Function SetParent Lib "user32" _
                    Alias "SetParent" (ByVal hWndChild As Integer, _
                                       ByVal hWndNewParent As Integer) As Integer

    '改变指定窗口的位置和大小。顶级窗口可能受最大或最小尺寸的限制,那些尺寸优先于这里设置的参数
    Private Declare Function MoveWindow Lib "user32" _
                    Alias "MoveWindow" (ByVal hWnd As IntPtr, _
                                        ByVal x As Integer, _
                                        ByVal y As Integer, _
                                        ByVal nWidth As Integer, _
                                        ByVal nHeight As Integer, _
                                        ByVal bRepaint As Integer) As Integer

    '获得整个窗口的范围矩形,窗口的边框、标题栏、滚动条及菜单等都在这个矩形内
    Private Declare Function GetWindowRect Lib "user32" _
                    Alias "GetWindowRect" (ByVal hWnd As IntPtr, _
                                           ByRef lpRect As RECT) As Integer

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
    Private Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure

      为了方便调试,我们先添加程序退出的代码:

    Private Sub cmdTextBox_KeyPress(ByVal sender As Object, ByVal e As _  
                                    System.Windows.Forms.KeyPressEventArgs) _  
                                    Handles cmdTextBox.KeyPress  
        If e.KeyChar = Chr(13) Then  
            If UCase(cmdTextBox.Text) = "END" Then  
                Me.Close()  
            End If  
        End If  
    End Su  

      这样,我们就可以通过在文本框里输入“end”,然后按回车来退出程序了。

      既然要改变最小化窗口的width,那么我们就先来找最小化窗口的Handle,先声明一个全局变量,来储存我们找到的最小化窗口的Handle:

    Dim hMin As Long  

      接下来,我们查找最小化窗口的句柄(下面的代码都在窗体的Load事件里):

Dim hTaskbar, hBar As Long  
hTaskbar = FindWindow("Shell_TrayWnd", vbNullString)            '寻找类名是Shell_TrayWnd的窗口Handle  
hBar = FindWindowEx(hTaskbar, 0, "ReBarWindow32", vbNullString) '寻来找二级容器的Handle  
hMin = FindWindowEx(hBar, 0, "MSTaskSwWClass", vbNullString)    '寻找最小化窗口的Handle

      找到句柄后,我们来获得二级容器的坐标和最小化窗口的坐标:

    Dim rcBar As RECT  
    GetWindowRect(hMin, rcMin)  '获得最小化窗口的Handle  
    GetWindowRect(hBar, rcBar)  '获得二级容器的Handle  

     下面我们通过用MoveWindow函数来改变窗口的width:

    MoveWindow(hMin, 0, 0, rcMin.Right - rcMin.Left - Me.Width, _  
               rcMin.Bottom - rcMin.Top, True)  

      已经为任务栏腾出地方了,是时候把程序嵌入到任务栏里了:

    SetParent(Me.Handle, hBar)  '把程序窗口设置成任务栏的子窗口  

      调整程序窗口的大小和位置:

    Me.Height = cmdTextBox.Height  
    Me.Width = cmdTextBox.Width  
    MoveWindow(Me.Handle, rcMin.Right - rcMin.Left - Me.Width + 2, _  
              (rcBar.Bottom - rcBar.Top - Me.Height) / 2, _  
               Me.Width, Me.Height, True)  

      把程序窗口嵌入到任务栏里的任务已经完成了,但我们还需要处理一下窗体的Closing事件,使程序关闭的时候,把最小化窗口的width恢复回去(下面这一行代码放在窗体的Closing事件里):

MoveWindow(hMin, 0, 0, rcMin.Right - rcMin.Left, rcMin.Bottom - rcMin.Top, True) 

      终于完成了,现在可以运行看一下效果了,和文章一开始的效果一样吧?

抱歉!评论已关闭.