芙萝拉10:HOW TO:将程序窗口嵌入到任务栏中

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 01:32:12

HOW TO:将程序窗口嵌入到任务栏中

分类: VB.NET 2011-08-02 08:01 158人阅读 评论(3) 收藏 举报

      今天我们来看看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):

[vb] view plaincopyprint?
  1. '寻找窗口列表中第一个符合指定条件的顶级窗口  
  2.  Private Declare Function FindWindow Lib "user32" _  
  3.                  Alias "FindWindowA" (ByVal lpClassName As String, _  
  4.                                       ByVal lpWindowName As String) As Integer  
  5.   
  6.  '在窗口列表中寻找与指定条件相符的第一个子窗口  
  7.  Private Declare Function FindWindowEx Lib "user32" _  
  8.                  Alias "FindWindowExA" (ByVal hWnd1 As Integer, _  
  9.                                         ByVal hWnd2 As Integer, _  
  10.                                         ByVal lpsz1 As String, _  
  11.                                         ByVal lpsz2 As String) As Integer  
  12.   
  13.  '指定一个窗口的新父  
  14.  Private Declare Function SetParent Lib "user32" _  
  15.                  Alias "SetParent" (ByVal hWndChild As Integer, _  
  16.                                     ByVal hWndNewParent As Integer) As Integer  
  17.   
  18.  '改变指定窗口的位置和大小。顶级窗口可能受最大或最小尺寸的限制,那些尺寸优先于这里设置的参数  
  19.  Private Declare Function MoveWindow Lib "user32" _  
  20.                  Alias "MoveWindow" (ByVal hWnd As IntPtr, _  
  21.                                      ByVal x As Integer, _  
  22.                                      ByVal y As Integer, _  
  23.                                      ByVal nWidth As Integer, _  
  24.                                      ByVal nHeight As Integer, _  
  25.                                      ByVal bRepaint As Integer) As Integer  
  26.   
  27.  '获得整个窗口的范围矩形,窗口的边框、标题栏、滚动条及菜单等都在这个矩形内  
  28.  Private Declare Function GetWindowRect Lib "user32" _  
  29.                  Alias "GetWindowRect" (ByVal hWnd As IntPtr, _  
  30.                                         ByRef lpRect As RECT) As Integer  
  31.   
  32.   _  
  33.  Private Structure RECT  
  34.      Public Left As Integer  
  35.      Public Top As Integer  
  36.      Public Right As Integer  
  37.      Public Bottom As Integer  
  38.  End Structure  

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

[vb] view plaincopyprint?

  1. Private Sub cmdTextBox_KeyPress(ByVal sender As Object, ByVal e As _  
  2.                                 System.Windows.Forms.KeyPressEventArgs) _  
  3.                                 Handles cmdTextBox.KeyPress  
  4.     If e.KeyChar = Chr(13) Then  
  5.         If UCase(cmdTextBox.Text) = "END" Then  
  6.             Me.Close()  
  7.         End If  
  8.     End If  
  9. End Su  

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

      既然要改变最小化窗口的width,那么我们就先来找最小化窗口的Handle,先声明一个全局变量,来储存我们找到的最小化窗口的Handle:
[vb] view plaincopyprint?
  1. Dim hMin As Long  

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

[vb] view plaincopyprint?
  1. Dim hTaskbar, hBar As Long  
  2. hTaskbar = FindWindow("Shell_TrayWnd", vbNullString)            '寻找类名是Shell_TrayWnd的窗口Handle  
  3. hBar = FindWindowEx(hTaskbar, 0, "ReBarWindow32", vbNullString) '寻来找二级容器的Handle  
  4. hMin = FindWindowEx(hBar, 0, "MSTaskSwWClass", vbNullString)    '寻找最小化窗口的Handle  

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

[vb] view plaincopyprint?

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

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

[vb] view plaincopyprint?

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

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

[vb] view plaincopyprint?

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

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

[vb] view plaincopyprint?

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


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

[vb] view plaincopyprint?
  1. MoveWindow(hMin, 0, 0, rcMin.Right - rcMin.Left, rcMin.Bottom - rcMin.Top, True)  
      终于完成了,现在可以运行看一下效果了,和文章一开始的效果一样吧?

  

By Alexis·M(小孟)