Results 1 to 3 of 3

Thread: [VB6] Always Behind / Always at the Bottom / Bottommost

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Post [VB6] Always Behind / Always at the Bottom / Bottommost

    The following code will put a Form always behind/at the bottom of all top-level windows. This is accomplished by processing the WM_WINDOWPOSCHANGING message.

    Code:
    Option Explicit     'In a standard .BAS module
    
    Private Declare Function DefSubclassProc Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function SetWindowSubclass Lib "comctl32.dll" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
    Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" Alias "#412" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
    Private Declare Sub PutMem4 Lib "msvbvm60.dll" (ByVal Ptr As Long, ByVal Value As Long)
    
    Public Function Subclass(ByRef Frm As VB.Form) As Boolean
        Subclass = SetWindowSubclass(Frm.hWnd, AddressOf SubclassProc, ObjPtr(Frm))
    End Function
    
    Public Function UnSubclass(ByRef Frm As VB.Form) As Boolean
        UnSubclass = RemoveWindowSubclass(Frm.hWnd, AddressOf SubclassProc, ObjPtr(Frm))
    End Function
    
    Private Function SubclassProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
        Const WM_WINDOWPOSCHANGING = &H46&, HWND_BOTTOM = 1&, SIGN_BIT = &H80000000
    
        If uMsg <> WM_WINDOWPOSCHANGING Then
            SubclassProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
        Else
            PutMem4 (lParam Xor SIGN_BIT) + 4& Xor SIGN_BIT, HWND_BOTTOM    'WINDOWPOS.hWndInsertAfter = HWND_BOTTOM
        End If                                                              'Xor: Unsigned pointer arithmetic
    End Function
    Usage example:

    Code:
    Option Explicit     'In Form1
    
    Private Sub Form_Load()
        Subclass Me
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        UnSubclass Me
    End Sub

  2. #2
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    Re: [VB6] Always Behind / Always at the Bottom / Bottommost

    Hi Victor,

    I like it. In fact, I like it enough to put it in my library. I think Bonnie West deserves some credit. She just wasn't quite as careful with the sign bit when offsetting. And she didn't use the newer/safer comctl32 method of subclassing.

    It might also be useful to monitor for WM_DESTROY in the subclass procedure, which would obviate the need for the form to handle this.

    This could definitely have certain uses.

    Take Care,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  3. #3
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    894

    Re: [VB6] Always Behind / Always at the Bottom / Bottommost

    I have implemented this function for years (or the other very similar also published in these forums), these has problems, if you are using "ALWAYS BOTTOM" feature for it being a launcher that launch others apps, or others apps are launched manually this approach alone will fail sometimes (it is a lottery).

    it is a lottery for it working right, very often new just opened apps starts behind this ALWAYS BOTTOM window.

    So to complement it, is a requirement to execute in a timer SetWindowsPos with HWND_BOTTOM (const =1), and NOMOVE, NOSIZE, etc.... just to enforce that the window sticks to the bottom all the times. The method on these threads only ignore the order of "place it first plane" as it gets the focus/active, but just ignoring it and switching on the fly to BOTTOM is not enough. The window must actively enforce to be placed in the bottom zorder all the times within a TIMER to ensure no other app can appear hiden behind this always_bottom window.

    within TIMER in same window

    SetWindowPos Me.hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE + SWP_NOMOVE + SWP_SHOWWINDOW

    It enforces the message procedure to be run and catch the WM_WINDOWPOSCHANGING. It is the difference betwenn not execute the WndProc , and execute it guarantee always!. So if new apps just launched can't be hidden randomly, (overall if this window is bigger, able to cover all the screen, where any just launched app can be completely covered by it).
    Last edited by flyguille; Oct 23rd, 2022 at 12:42 PM.

Tags for this Thread

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