VB.NET将程序嵌入任务栏


* 本文章只是对KyleMong写的《HOW TO :将程序嵌入任务栏中》做一个总结和延伸。请先看完《HOW TO :将程序嵌入任务栏中》后再浏览本文。

首先,我们先来具体了解下XP任务栏的结构

1.整个任务栏的类名为Shell_TrayWnd
2.其下分为了三个区:开始按钮,中间任务栏和右下角任务栏:
1)开始按钮: 类名为BUTTON,标题为"开始",控件ID为0x130
2)中间任务栏:类名为ReBarWindow32,控件ID为0xA005,其下又有三个子窗口:
i.快速启动栏: 类名:ToolbarWindow32,Title:Quick Launch
ii.正在运行程序栏:类名:MSTaskSwWClass,Title:运行应用程序;再其下又有一个类名:ToolbarWindow32,Title:运行应用程序
iii.文字输入语言栏:类名:CiceroUIWndFrame,Title:TF_FloatingLangBar_WndTitle
3.右下角任务栏:类名:TrayNotifyWnd,其下有也有三个子窗口:
1)时间显示栏:类名:TrayClockWClass,Title:当前时间如19:00
2)主要显示栏:类名:SysPager,其下有个子窗口,就是我们最常见的最小化到右下角任务栏的地方:类名:ToolbarWindow32,Title:通知区域
3)一个button,类名:Button,控件ID为0x5DE

好了,有了类名我们就可以通过FindWindow和findwindowex来找到它们的句柄,接着就可以进行操作了。

接下来我们介绍几个API在VB中的运用

'第一个是FindWindow

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String,ByVal lpWindowName As String) As Long 

lpClassName '类名

  指向一个以null结尾的、用来指定类名的字符串或一个可以确定类名字符串的原子。如果这个参数是一个原子,那么它必须是一个调用函数前已经通过GlobalAddAtom函数创建好的全局原子。这个原子(一个16bit的值),必须被放置在lpClassName的低位字节中,lpClassName的高位字节置零。

  如果该参数为null时,将会寻找任何与lpWindowName参数匹配的窗口。

lpWindowName '窗体名

  指向一个以null结尾的、用来指定窗口名(即窗口标题)的字符串。如果此参数为NULL,则匹配所有窗口名。

'第二个是findwindowex

Public Declare Function findwindowex Lib "user32" Alias "findwindowexA" (ByVal hWnd1 As Long,ByVal hWnd2 As Long,ByVal lpsz1 As String,ByVal lpsz2 As String) As Long

函数功能:该函数获得一个窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配。这个函数查找子窗口,从排在给定的子窗口后面的下一个子窗口开始。在查找时不区分大小写。

hwndParent

要查找子窗口的父窗口句柄。

  如果hwndParent为NULL,则函数桌面窗口为父窗口,查找桌面窗口的所有子窗口。

  Windows NT5.0 and later:如果hwndParent是HWND_MESSAGE,函数仅查找所有消息窗口。

hwndChildAfter

子窗口句柄。查找从在Z序中的下一个子窗口开始。子窗口必须为hwndParent窗口的直接子窗口而非后代窗口。如果HwndChildAfter为NULL,查找从hwndParent的第一个子窗口开始。如果hwndParent 和 hwndChildAfter同时为NULL,则函数查找所有的顶层窗口及消息窗口。

lpszClass

指向一个指定了类名的空结束字符串,或一个标识类名字符串的成员的指针。如果该参数为一个成员,则它必须为前次调用theGlobaIAddAtom函数产生的全局成员。该成员为16位,必须位于lpClassName的低16位,高位必须为0。

lpszWindow

指向一个指定了窗口名(窗口标题)的空结束字符串。如果该参数为 NULL,则为所有窗口全匹配。返回值:如果函数成功,返回值为具有指定类名和窗口名的窗口句柄。如果函数失败,返回值为NULL。


'第三个是GetwindowRect

Public Declare Function GetwindowRect Lib "user32" Alias "GetwindowRect" (ByVal hwnd As Long,lpRect As RECT) As Long

函数功能:该函数返回指定窗口的边框矩形的尺寸。该尺寸以相对于屏幕坐标左上角的屏幕坐标给出。

hWnd

窗口句柄。

lpRect

指向一个RECT结构的指针,该结构接收窗口的左上角和右下角的屏幕坐标。

定义:首先添加:Imports System.Runtime.InteropServices(在vb2010中,写入下面代码后会有一个红色的感叹号,点击它并选择第一个。或者把它复制到代码最上端)

    <StructLayout(LayoutKind.Sequential,CharSet:=CharSet.Auto)> _
    Private Structure RECT
        Public Left As Integer    'X,即左上角的横坐标
        Public Top As Integer     'Y,即左上角的纵坐标
        Public Right As Integer   'Width,宽
        Public Bottom As Integer  'Height,高
    End Structure

返回值:如果函数成功,返回值为非零:如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数

'第四个是SetParent

Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long,ByVal hWndNewParent As Long) As Long 


函数功能:该函数改变某个子窗口的父窗口。

参数:

  hWndChild:子窗口句柄。

  hWndNewParent:新的父窗口句柄。如果该参数是NULL,则桌面窗口就成为新的父窗口。在WindowsNT5.0中,如果参数为HWND_MESSAGE,则子窗口成为消息窗口。

  返回值:如果函数成功,返回值为子窗口的原父窗口句柄;如果函数失败,返回值为NULL。若想获得多错误信息,请调用GetLastError函数

'第五个是MoveWindow

Public Declare Function MoveWindow Lib "user32" Alias "MoveWindow" (ByVal hwnd As Long,ByVal x As Long,ByVal y As Long,ByVal nWidth As Long,ByVal nHeight As Long,ByVal bRepaint As Long) As Long


函数功能:改变指定窗口的位置和大小.对顶窗口来说,位置和大小取决于屏幕的左上角;对子窗口来说,位置和大小取决于父窗口客户区的左上角.对于Owned窗口,位置和大小取决于屏幕左上角.

参数

  hWnd指定了窗口的句柄

  x指定了CWnd的左边的新位置。

  y指定了CWnd的顶部的新位置。

  nWidth指定了CWnd的新宽度。

  nHeight指定了CWnd的新高度。

  bRepaint指定了是否要重画CWnd。如果为TRUE,则CWnd象通常那样在OnPaint消息处理函数中接收到一条WM_PAINT消息。如果这个参数为FALSE,则不会发生任何类型的重画操作。这应用于客户区、非客户区(包括标题条和滚动条)和由于CWnd移动而露出的父窗口的任何部分。当这个参数为FALSE的时候,应用程序必须明确地使CWnd和父窗口中必须重画的部分无效或重画。

'第六个是ShowWindow

Public Declare Function ShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long,ByVal nCmdshow As Long) As Long


函数功能:该函数设置指定窗口的显示状态。

参数:(一些常量具体的值请查询API浏览器)

hWnd:指窗口句柄。
  SW_HIDE:隐藏窗口并激活其他窗口。
  SW_MAXIMIZE:最大化指定的窗口。
  SW_MINIMIZE:最小化指定的窗口并且激活在Z序中的下一个顶层窗口。
  SW_RESTORE:激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指定这个标志。
  SW_SHOW:在窗口原来的位置以原来的尺寸激活和显示窗口。
  SW_SHOWDEFAULT:依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的。
  SW_SHOWMAXIMIZED:激活窗口并将其最大化。
  SW_SHOWMINIMIZED:激活窗口并将其最小化。
  SW_SHOWMINNOACTIVATE:窗口最小化,激活窗口仍然维持激活状态。
  SW_SHOWNA:以窗口原来的状态显示窗口。激活窗口仍然维持激活状态。
  SW_SHOWNOACTIVATE:以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态。

  SW_SHOWnorMAL:激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志。

好了,一些API就介绍到这,现在就是编写代码了,请新建一个模块,然后复制入以下代码

Imports System.Runtime.InteropServices

Module SetMinForm
    '寻找窗口列表中第一个符合指定条件的顶级窗口
    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

    '设置指定窗口的显示状态
    Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As IntPtr,_
        ByVal nCmdshow As Integer) As Integer
    Const SW_SHOW = 5
    Const SW_HIDE = 0




    <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

    '声明全集变量,并暂存相关数据
    Dim hTaskbar,hBar,HLang As Long
    Dim rcBar As RECT
    Dim rcTaskbar As RECT
    Dim rcLang As RECT
    Public BarOldRight As Integer
    Public HBarOldWidth,HBarNewWidth As Integer

    Function SetMinFormStyle(ByVal Con As Form) As Boolean
        On Error GoTo cw
        hTaskbar = FindWindow("Shell_TrayWnd",vbNullString)            '寻找类名是Shell_TrayWnd的窗口Handle
        hBar = findwindowex(hTaskbar,"ReBarWindow32",vbNullString) '寻找中间任务栏的Handle
        HLang = findwindowex(hTaskbar,"TrayNotifyWnd",vbNullString) '寻找右下角任务栏的Handle
        GetwindowRect(HLang,rcLang)                                    '获得右下角任务栏的RECT
        GetwindowRect(hBar,rcBar)                                      '获得中间任务栏的RECT
        GetwindowRect(hTaskbar,rcTaskbar)                              '获得任务栏的RECT
        HBarOldWidth = rcBar.Right - rcBar.Left
        BarOldRight = rcBar.Right
        HBarNewWidth = HBarOldWidth - Con.Width
        MoveWindow(hBar,rcBar.Left,HBarNewWidth,rcBar.Bottom,True) '调整中间任务栏的宽度,为程序腾出位置
        SetParent(Con.Handle,hTaskbar)                                                           '把程序窗口设置成任务栏的子窗口
        MoveWindow(Con.Handle,HBarOldWidth - Con.Width,Con.Width,Con.Height,True)           '调整程序的位置
        ShowWindow(Con.Handle,SW_SHOW)                                                           '显示窗体,可要可不要
        Return True
        Exit Function
cw:
        Return False
    End Function
    Function UnSetMinFormStyle() As Boolean
        On Error GoTo cw
        MoveWindow(hBar,rcBar.Right - rcBar.Left,True)             '恢复中间任务栏的宽度
        Return True
        Exit Function
cw:
        Return False
    End Function

    Sub UpDataConBarRect(ByVal Con As Form)  '调整程序与任务栏各窗口的位置
        Dim HTaskBara,HBara,HLangA As Long
        Dim RCHBara As RECT
        Dim RCHLangA As RECT
        HTaskBara = FindWindow("Shell_TrayWnd",vbNullString)            '寻找类名是Shell_TrayWnd的窗口Handle
        HBara = findwindowex(HTaskBara,vbNullString) '寻找中间任务栏的Handle
        HLangA = findwindowex(HTaskBara,vbNullString) '寻找右下角任务栏的Handle
        GetwindowRect(HLangA,RCHLangA)        '获得右下角任务栏的RECT
        GetwindowRect(HBara,RCHBara)        '获得中间任务栏的RECT
        If RCHLangA.Left <> Con.Left + Con.Width Then MoveWindow(Con.Handle,RCHLangA.Left - Con.Width,True)
        HBarNewWidth = Con.Left - rcBar.Left
        If RCHBara.Right - RCHBara.Left <> HBarNewWidth Then MoveWindow(hBar,True)
        ShowWindow(Con.Handle,SW_SHOW)
    End Sub
End Module



然后在你的程序中写入下面代码并设置Formborderstyle为none,然后运行程序,嘿嘿,程序是不是嵌入了呢?注意程序的Width和Height不要太大哦!

Public Class Form1
   
    Private Sub Form1_Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.Click
        Me.Close()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object,ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        UnSetMinFormStyle()
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles MyBase.Load
        SetMinFormStyle(Me)
    End Sub


    Private Sub Timer1_Tick(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles Timer1.Tick
        UpDataConBarRect(Me)
    End Sub


End Class

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
  Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
  PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
  沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")