読者です 読者をやめる 読者になる 読者になる

もなかアイスの試食品

「とりあえずやってみたい」そんな気持ちが先走りすぎて挫折が多い私のメモ書きみたいなものです.

【VB.NET】Windowsのタスクバーを非表示にした

はじめに

とあるアプリの仕様上、Windowsのタスクバーを非表示にしたくなった。

調べてみると、意外とコーディング方法がなく(XP時代のコードがでてきた)、また参考にしたコードもちょっと問題があった。

一応やりたいことが出来たのでメモ書き

環境

実装

以下のサイトを参考にした。

Windowsのタスクバーの表示・非表示をAPIで制御する方法。(自動的に隠す隠さないもあるよ)

参考にしたサイトのものをそのまま使用すると、Windowsのスタートボタン(?)が残っていた

「WinLister」というツールを使用したところ、スタートボタンのウィンドウクラス名が「Button」っぽい

なので、「Shell_TrayWnd」と「Button」を非表示にするようにしたところ、タスクバーがちゃんと消えるようになった

以下、タスクバーを非表示にするクラス

Imports System.Runtime.InteropServices


Class TaskbarControl


    ''' <summary>ウィンドウクラス名を格納しておく</summary>
    Private windowClasses As String() = New String() {"Shell_TrayWnd", "Button"}

    ''' <summary>タスクバー非表示前の状態保存用変数</summary>
    Private lastStatus As Dictionary(Of IntPtr, ABMsg) = New Dictionary(Of IntPtr, ABMsg)


    ''' <summary>タスクバーを表示します。</summary>
    Public Sub Show()
        SetVisible(True)
    End Sub


    ''' <summary>タスクバーを非表示にします。</summary>
    Public Sub Hidden()
        SetVisible(False)
    End Sub


    ''' <summary>タスクバーの表示・非表示切り替え</summary>
    '''
    ''' <param name="visible">trueのとき表示する</param>
    Private Sub SetVisible(visible As Boolean)
        For Each className As String In windowClasses
            Dim hWnd As IntPtr = FindWindow(className, Nothing)

            If hWnd = 0 Then
                Continue For
            End If

            ' 非表示にする際は、「表示」している状態のAutoHideのOn・Offを同じ設定にするため、
            ' メンバ変数に現在の状態を保存する。非表示から表示状態にするときは、保存していた
            ' 前回値を設定する。
            Dim appbarMessage As ABMsg
            If visible Then
                If Me.lastStatus.ContainsKey(hWnd) Then
                    appbarMessage = Me.lastStatus(hWnd)
                Else
                    appbarMessage = ABMsg.ABM_NEW
                End If
            Else
                Dim status As ABMsg = Me.GetAppBarStatus(hWnd)
                Me.lastStatus.Add(hWnd, status)
                appbarMessage = ABMsg.ABM_REMOVE
            End If

            Me.SetAppBarStatus(hWnd, ABMsg.ABM_ACTIVATE)

            Dim command As Integer = If(visible, WindowCmd.Show, WindowCmd.Hide)
            ShowWindow(hWnd, command)
        Next

        If visible Then
            Me.lastStatus.Clear()
        End If

    End Sub


    ''' <summary>タスクバーの状態を取得</summary>
    '''
    ''' <param name="hWnd">ウィンドウハンドル</param>
    ''' <returns>タスクバーの表示状態</returns>
    Private Function GetAppBarStatus(hWnd As IntPtr) As ABMsg
        Dim pData As New APPBARDATA()
        pData.cbSize = Marshal.SizeOf(pData)
        pData.hWnd = hWnd

        SHAppBarMessage(ABMsg.ABM_GETSTATE, pData)

        Return pData.lParam
    End Function


    ''' <summary>タスクバーの状態を設定</summary>
    '''
    ''' <param name="hWnd">ウィンドウハンドル</param>
    ''' <param name="status">AppBarメッセージ</param>
    Private Sub SetAppBarStatus(hWnd As IntPtr, status As ABMsg)
        Dim pData As New APPBARDATA()
        pData.cbSize = Marshal.SizeOf(pData)
        pData.hWnd = hWnd

        pData.lParam = status
        SHAppBarMessage(ABMsg.ABM_SETSTATE, pData)
    End Sub


    ''' <summary>Sends an appbar message to the system.</summary>
    Private Enum ABMsg As Integer
        ''' <summary>Registers a new appbar and specifies the message identifier that the system should use to send notification messages to the appbar.</summary>
        ABM_NEW = 0

        ''' <summary>Unregisters an appbar, removing the bar from the system's internal list.</summary>
        ABM_REMOVE = 1

        ''' <summary>Requests a size and screen position for an appbar.</summary>
        ABM_QUERYPOS = 2

        ''' <summary>Sets the size and screen position of an appbar.</summary>
        ABM_SETPOS = 3

        ''' <summary>Retrieves the autohide and always-on-top states of the Windows taskbar.</summary>
        ABM_GETSTATE = 4

        ''' <summary>Retrieves the bounding rectangle of the Windows taskbar. </summary>
        '''
        ''' <remarks>
        ''' Note that this applies only to the system taskbar.
        ''' Other objects, particularly toolbars supplied with third-party software, also can be present.
        ''' As a result, some of the screen area not covered by the Windows taskbar might not be visible to the user.
        ''' To retrieve the area of the screen not covered by both the taskbar
        ''' and other app bars—the working area available to your application—,
        ''' use the GetMonitorInfo function.
        ''' </remarks>
        ABM_GETTASKBARPOS = 5

        ''' <summary>Notifies the system to activate or deactivate an appbar.</summary>
        '''
        ''' <remarks>
        ''' The lParam member of the APPBARDATA pointed to by pData is set to TRUE to activate or FALSE to deactivate.
        ''' </remarks>
        ABM_ACTIVATE = 6

        ''' <summary>Retrieves the handle to the autohide appbar associated with a particular edge of the screen.</summary>
        ABM_GETAUTOHIDEBAR = 7

        ''' <summary>Registers or unregisters an autohide appbar for an edge of the screen.</summary>
        ABM_SETAUTOHIDEBAR = 8

        ''' <summary>Notifies the system when an appbar's position has changed.</summary>
        ABM_WINDOWPOSCHANGED = 9

        ''' <summary>Sets the state of the appbar's autohide and always-on-top attributes.</summary>
        '''
        ''' <remarks>
        ''' Windows XP and later
        ''' </remarks>
        ABM_SETSTATE = 10

        ''' <summary>Retrieves the handle to the autohide appbar associated with a particular edge of a particular monitor.</summary>
        '''
        ''' <remarks>
        ''' Windows XP and later
        ''' </remarks>
        ABM_GETAUTOHIDEBAREX = 11

        ''' <summary>Registers or unregisters an autohide appbar for an edge of a particular monitor.</summary>
        '''
        ''' <remarks>
        ''' Windows XP and later
        ''' </remarks>
        ABM_SETAUTOHIDEBAREX = 12
    End Enum


    ''' <summary>Contains information about a system appbar message.</summary>
    '''
    ''' <remarks>
    ''' http://www.geocities.jp/katayama_hirofumi_mz/imehackerz/ja/APPBARDATA.html
    ''' </remarks>
    <StructLayout(LayoutKind.Sequential)>
    Private Structure APPBARDATA
        ''' <summary>The size of the structure, in bytes.</summary>
        Public cbSize As Integer

        ''' <summary>The handle to the appbar window.</summary>
        '''
        ''' <remarks>
        ''' Not all messages use this member. See the individual message page to see if you need to provide an hWind value.
        ''' </remarks>
        Public hWnd As IntPtr

        ''' <summary>An application-defined message identifier.</summary>
        '''
        ''' <remarks>
        ''' The application uses the specified identifier for notification messages
        ''' that it sends to the appbar identified by the hWnd member.
        ''' This member is used when sending the ABM_NEW message.
        ''' </remarks>
        Public uCallbackMessage As UInteger

        ''' <summary>A value that specifies an edge of the screen.</summary>
        '''
        ''' <remarks>
        ''' This member is used when sending one of these messages:<br/>
        ''' <list type="bullet">
        '''   <item>ABM_GETAUTOHIDEBAR</item>
        '''   <item>ABM_SETAUTOHIDEBAR</item>
        '''   <item>ABM_GETAUTOHIDEBAREX</item>
        '''   <item>ABM_SETAUTOHIDEBAREX</item>
        '''   <item>ABM_QUERYPOS</item>
        '''   <item>ABM_SETPOS</item>
        ''' </list>
        ''' </remarks>
        Public uEdge As ABEdge

        ''' <summary>A RECT structure</summary>
        '''
        ''' <remarks>
        ''' A RECT structure whose use varies depending on the message:<br/>
        ''' ABM_GETTASKBARPOS、ABM_QUERYPOS、ABM_SETPOS:
        '''     The bounding rectangle, in screen coordinates, of an appbar or the Windows taskbar.
        ''' ABM_GETAUTOHIDEBAREX、ABM_SETAUTOHIDEBAREX
        '''     The monitor on which the operation is being performed. This information can be retrieved through the GetMonitorInfo function.
        ''' </remarks>
        Public rc As RECT

        ''' <summary>A message-dependent value.</summary>
        '''
        ''' <remarks>
        ''' This member is used with these messages:<br/>
        ''' <list type="bullet">
        '''   <item>ABM_SETAUTOHIDEBAR</item>
        '''   <item>ABM_SETAUTOHIDEBAREX</item>
        '''   <item>ABM_SETSTATE</item>
        ''' </list>
        ''' See the individual message pages for details.
        ''' </remarks>
        Public lParam As Integer
    End Structure


    ''' <summary>A value that specifies an edge of the screen.</summary>
    Private Enum ABEdge As Integer
        ''' <summary>Left edge.</summary>
        ABE_LEFT = 0

        ''' <summary>Top edge.</summary>
        ABE_TOP = 1

        ''' <summary>Right edge.</summary>
        ABE_RIGHT = 2

        ''' <summary>Bottom edge.</summary>
        ABE_BOTTOM = 3
    End Enum


    ''' <summary>the coordinates of the upper-left and lower-right corners of a rectangle.</summary>
    <StructLayout(LayoutKind.Sequential)>
    Private Structure RECT
        ''' <summary>The x-coordinate of the upper-left corner of the rectangle.</summary>
        Public left As Integer

        ''' <summary>The y-coordinate of the upper-left corner of the rectangle.</summary>
        Public top As Integer

        ''' <summary>The x-coordinate of the lower-right corner of the rectangle.</summary>
        Public right As Integer

        ''' <summary>The y-coordinate of the lower-right corner of the rectangle.</summary>
        Public bottom As Integer
    End Structure


    ''' <summary>ウィンドウの表示方法</summary>
    '''
    ''' <remarks>
    ''' https://msdn.microsoft.com/ja-jp/library/cc411211.aspx
    ''' </remarks>
    Private Enum WindowCmd As Integer
        ''' <summary>表示</summary>
        Hide = 0
        ''' <summary>非表示</summary>
        Show = 5
    End Enum


    ''' <summary>システムにAppBarメッセージを送信する。</summary>
    '''
    ''' <remarks>
    ''' https://msdn.microsoft.com/ja-jp/library/bb762108(v=vs.85).aspx
    ''' </remarks>
    '''
    ''' <param name="dwMessage">AppBarメッセージ値</param>
    ''' <param name="pData">送信パラメータ</param>
    '''
    ''' <returns>メッセージに依存した値</returns>
    <DllImport("shell32.dll", CallingConvention:=CallingConvention.StdCall)>
    Private Shared Function SHAppBarMessage(dwMessage As ABMsg, ByRef pData As APPBARDATA) As Integer
    End Function


    ''' <summary>指定されたウィンドウの表示状態を設定します。</summary>
    '''
    ''' <remarks>
    ''' https://msdn.microsoft.com/ja-jp/library/cc411211.aspx
    ''' </remarks>
    '''
    ''' <param name="hWnd">ウィンドウハンドル</param>
    ''' <param name="nCmdShow">表示状態</param>
    '''
    ''' <returns>ウィンドウが以前から表示されていた場合は、0 以外の値</returns>
    <DllImport("user32.dll", EntryPoint:="ShowWindow")>
    Private Shared Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Integer
    End Function


    ''' <summary>指定された文字列と一致するクラス名とウィンドウ名を持つ親を持たないウィンドウのハンドルを返します</summary>
    '''
    ''' <remarks>
    ''' https://msdn.microsoft.com/ja-jp/library/cc364634.aspx
    ''' </remarks>
    '''
    ''' <param name="lpClassName">クラス名</param>
    ''' <param name="lpWindowName">ウィンドウ名</param>
    '''
    ''' <returns>関数が成功すると、指定したクラス名とウィンドウ名を持つウィンドウのハンドルが返ります</returns>
    <DllImport("user32.dll", EntryPoint:="FindWindow")>
    Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As Integer
    End Function


End Class

使用例

使用方法はこんな感じ

Class MainWindow

    Private taskbarController As TaskbarControl = New TaskbarControl()

    ''' <summary>画面表示時に実行</summary>
    Private Sub Grid_Loaded(sender As Object, e As RoutedEventArgs)
        Me.Left = 0
        Me.Top = 0
        Me.Width = SystemParameters.PrimaryScreenWidth
        Me.Height = SystemParameters.PrimaryScreenHeight
        Me.Topmost = True
        taskbarController.Hidden()
    End Sub

    ''' <summary>アプリ終了時に実行</summary>
    Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)
        taskbarController.Show()
    End Sub

End Class

動作確認はWindows7(64bit)、Windows10(うろ覚え・・・)

C#版も作ったけど、タスクバーの復帰がうまくいかなかった・・・

具体的には、タスクバーを「自動的に隠す」にした後に、非表示→表示と動作させると「自動的に隠す」の設定が消えてる・・・VBだと問題なかったんだけど

C#版で作ったことはなかったことにしよう