CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Aug 2011
    Posts
    0

    AppBar - Windows 7

    I'm trying to make a simple appbar on the right side of the screen. I have accomplished this many times before.. but I can't seem to get it working in Windows 7. The placement seems right, and as far as I can tell the messages seem to be in the right order. I have tried both Windows.Forms.FormBorderStyle.None as well as Windows.Forms.FormBorderStyle.FixedToolWindow. What am I doing wrong?
    Code:
    Public Class Form1
    
        Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As IntPtr, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer
        Public Declare Auto Function MoveWindow Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal X As Int32, ByVal Y As Int32, ByVal nWidth As Int32, ByVal nHeight As Int32, ByVal bRepaint As Boolean) As Boolean
        Declare Function SHAppBarMessage Lib "shell32.dll" Alias "SHAppBarMessage" (ByVal dwMessage As Integer, ByRef pData As APPBARDATA) As Integer
        Declare Function SetWindowPos Lib "user32.dll" (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, ByVal X As Integer, ByVal Y As Integer, ByVal cX As Integer, ByVal cY As Integer, ByVal wFlags As Integer) As Integer
    
        Structure APPBARDATA
            Dim cbSize As Integer
            Dim hwnd As Integer
            Dim uCallbackMessage As [Delegate]
            Dim uEdge As Integer
            Dim rc As RECT
            Dim lParam As Integer ' message specific
        End Structure
        Structure RECT
            Dim Left As Integer
            Dim Top As Integer
            Dim Right As Integer
            Dim Bottom As Integer
        End Structure
    
        Const ABE_LEFT As Integer = 0
        Const ABE_TOP As Integer = &H1
        Const ABE_RIGHT As Integer = 2
        Const ABE_BOTTOM As Integer = 3
    
        Const ABM_NEW As Integer = 0
        Const ABM_REMOVE As Integer = 1
        Const ABM_QUERYPOS As Integer = 2
        Const ABM_SETPOS As Integer = &H3
        Const ABM_GETSTATE As Integer = 4
        Const ABM_GETTASKBARPOS As Integer = 5
        Const ABM_ACTIVATE As Integer = 6
        Const ABM_GETAUTOHIDEBAR As Integer = 7
        Const ABM_SETAUTOHIDEBAR As Integer = 8
        Const ABM_WINDOWPOSCHANGED As Integer = 9
    
        Const ABS_AUTOHIDE As Integer = 1
        Const ABS_ALWAYSONTOP As Integer = 2
    
        Const HWND_NOTTOPMOST As Integer = -2
        Const HWND_TOPMOST As Integer = -1
        Const HWND_TOP As Integer = 0
        Const SHOWNORMAL As Integer = 5
    
        Const SWP_NOSIZE As Integer = &H1
        Const SWP_NOMOVE As Short = &H2
        Const SWP_NOZORDER As Integer = 4
        Const SWP_NOACTIVATE As Integer = &H10
        Const SWP_DRAWFRAME As Integer = &H20
        Const SWP_SHOWWINDOW As Integer = &H40
        Dim abd As APPBARDATA
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.TopMost = True
            Me.Size = New Size(150, 350)
            Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedToolWindow
    
            Dim combinedwidth As Integer = Screen.PrimaryScreen.WorkingArea.Width
            Dim height As Integer = Screen.PrimaryScreen.WorkingArea.Height
            Dim top As Integer = 0
    
            SHAppBarMessage(ABM_NEW, abd)
            abd.hwnd = Me.Handle.ToInt32
            abd.cbSize = Len(abd)
            With abd
                .uEdge = ABE_RIGHT
                .rc.Top = top
                .rc.Right = (combinedwidth)
                .rc.Left = .rc.Right - Me.Width
                .rc.Bottom = height
    
                SHAppBarMessage(ABM_QUERYPOS, abd)
                'abd.rc.Left = abd.rc.Right - Me.Width
                SHAppBarMessage(ABM_SETPOS, abd)
                'MoveWindow(abd.hwnd, .rc.Left, .rc.Top, .rc.Right - .rc.Left, .rc.Bottom, True)
                SetWindowPos(abd.hwnd, HWND_TOP, .rc.Left, .rc.Top, .rc.Right - .rc.Left, .rc.Bottom, SWP_SHOWWINDOW Or SWP_NOACTIVATE)
            End With
        End Sub
    End Class

  2. #2
    Join Date
    Jun 2004
    Location
    NH
    Posts
    678

    Re: AppBar - Windows 7

    I think it's a timing issue. This works for me on Windows 7 Ultimate.

    Code:
        Const ABE_LEFT As Int32 = 0
        Const ABE_TOP As Int32 = 1
        Const ABE_RIGHT As Int32 = 2
        Const ABE_BOTTOM As Int32 = 3
        Const ABM_NEW As Int32 = 0
        Const ABM_REMOVE As Int32 = 1
        Const ABM_QUERYPOS As Int32 = 2
        Const ABM_SETPOS As Int32 = 3
        Const ABM_GETSTATE As Int32 = 4
        Const ABM_GETTASKBARPOS As Int32 = 5
        Const ABM_ACTIVATE As Int32 = 6
        Const ABM_GETAUTOHIDEBAR As Int32 = 7
        Const ABM_SETAUTOHIDEBAR As Int32 = 8
        Const ABM_WINDOWPOSCHANGED As Int32 = 9
        Const ABS_AUTOHIDE As Int32 = 1
        Const ABS_ALWAYSONTOP As Int32 = 2
        Const HWND_NOTTOPMOST As Int32 = -2
        Const HWND_TOPMOST As Int32 = -1
        Const HWND_TOP As Int32 = 0
        Const SHOWNORMAL As Int32 = 5
        Private Structure APPBARDATA
            Public cbSize As Int32
            Public hwnd As IntPtr
            Public uCallbackMessage As [Delegate]
            Public uEdge As Int32
            Public rc As RECT
            Public lParam As Int32
        End Structure
        Private Structure RECT
            Public rLeft As Int32
            Public rTop As Int32
            Public rRight As Int32
            Public rBottom As Int32
        End Structure
        Private Enum EDGE As Int32
            Left = ABE_LEFT
            Top = ABE_TOP
            Right = ABE_RIGHT
            Bottom = ABE_BOTTOM
        End Enum
        Private Declare Function apiMoveWindow Lib "user32" Alias "MoveWindow" (ByVal hWnd As IntPtr, ByVal X As Int32, ByVal Y As Int32, ByVal nWidth As Int32, ByVal nHeight As Int32, ByVal bRepaint As Boolean) As Boolean
        Private Declare Function apiSHAppBarMessage Lib "shell32" Alias "SHAppBarMessage" (ByVal dwMessage As Int32, ByRef pData As APPBARDATA) As Int32
        Private abd As New APPBARDATA
    
        Private Sub Form1_MouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDoubleClick
            Me.Close()
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            DockToEdge(EDGE.Right)
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            DockToEdge(EDGE.Left)
        End Sub
        Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
            DockToEdge(EDGE.Top)
        End Sub
        Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
            DockToEdge(EDGE.Bottom)
        End Sub
    
        Private Sub DockToEdge(ByVal edge As Int32)
            On Error Resume Next
            apiSHAppBarMessage(ABM_REMOVE, abd)
            abd = New APPBARDATA
            abd.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(abd)
            abd.hwnd = Me.Handle
            abd.uEdge = edge
            If edge = ABE_LEFT OrElse edge = ABE_RIGHT Then
                Me.Height = Screen.PrimaryScreen.WorkingArea.Height
                Me.Width = 75
                abd.rc.rTop = Screen.PrimaryScreen.WorkingArea.Top : abd.rc.rBottom = Screen.PrimaryScreen.WorkingArea.Bottom
                If edge = ABE_LEFT Then
                    abd.rc.rLeft = Screen.PrimaryScreen.WorkingArea.Left
                    abd.rc.rRight = abd.rc.rLeft + 75
                Else
                    abd.rc.rRight = Screen.PrimaryScreen.WorkingArea.Right
                    abd.rc.rLeft = abd.rc.rRight - 75
                End If
            ElseIf edge = ABE_TOP OrElse edge = ABE_BOTTOM Then
                Me.Width = Screen.PrimaryScreen.WorkingArea.Width
                Me.Height = 25
                abd.rc.rLeft = Screen.PrimaryScreen.WorkingArea.Left
                abd.rc.rRight = Screen.PrimaryScreen.WorkingArea.Right
                If edge = ABE_TOP Then
                    abd.rc.rTop = Screen.PrimaryScreen.WorkingArea.Top
                    abd.rc.rBottom = abd.rc.rTop + 25
                Else
                    abd.rc.rBottom = Screen.PrimaryScreen.WorkingArea.Bottom
                    abd.rc.rTop = abd.rc.rBottom - 25
                End If
            End If
            apiSHAppBarMessage(ABM_NEW, abd)
            apiSHAppBarMessage(ABM_SETPOS, abd)
            Application.DoEvents() 'This seemed to work, although a thread also works
            apiMoveWindow(abd.hwnd, abd.rc.rLeft, abd.rc.rTop, abd.rc.rRight - abd.rc.rLeft, abd.rc.rBottom - abd.rc.rTop, True)
        End Sub
    
        Private Sub MoveFormOnThread()
            Threading.Thread.Sleep(25)
            apiMoveWindow(abd.hwnd, abd.rc.rLeft, abd.rc.rTop, abd.rc.rRight - abd.rc.rLeft, abd.rc.rBottom - abd.rc.rTop, True)
        End Sub
    Last edited by TT(n); August 26th, 2011 at 03:03 AM.

  3. #3
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: AppBar - Windows 7

    Shouldn't be in Form_Load
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  4. #4
    Join Date
    Jun 2004
    Location
    NH
    Posts
    678

    Re: AppBar - Windows 7

    It worked in Form_Load too, but this was just my sample with buttons to be simple. The problem was in the MoveWindow return value. I believe calling this function to early overlaps with the previous call to ABM_SETPOS, and so the work area is not ready yet. Calling ABM_WINDOWPOSCHANGED did not seem to flush anything although DoEvents does, unless you prefer a thread to move it.

    Here is a sample with gradient look to it, more like the real taskbar.
    Attached Files Attached Files
    Last edited by TT(n); August 26th, 2011 at 02:41 PM. Reason: Add example file

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured