-
Mar 22nd, 2001, 02:33 AM
#1
Thread Starter
Fanatic Member
I am writing a windows shell and i am looking for a way to keep a window behind all open windows (even when it is active)
Currently, i am subclassing the wm_activateapp message and using setwindowpos to move the window to the bottom, but this is not as smooth as i want it to be.
I'm just wondering how windows explorer does it so i can finish my shell.
I've looked through the MSDN Win32 SDK looking for a window style that does this. I've looked for flags for setwindowpos. I've also looked for a windows message. No luck what-so-ever.
The subclass method is the only thing i can think of, but it still remains in front of explorer, so i know that the subclassing method is not the same method that explorer uses.
-
Mar 22nd, 2001, 04:07 AM
#2
Fanatic Member
try this:
Code:
Const HWND_BOTTOM = 1
Const SWP_NOSIZE = &H1
Const SWP_NOMOVE = &H2
i = SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE)
Crispin
VB6 ENT SP5
VB.NET
W2K ADV SVR SP3
WWW.BLOCKSOFT.CO.UK
[Microsoft Basic: 1976-2001, RIP]
-
Mar 23rd, 2001, 12:56 AM
#3
Thread Starter
Fanatic Member
that will work until the window is activated. I need the window to stay at the bottom even when it's activated
-
Mar 23rd, 2001, 03:41 AM
#4
Fanatic Member
Got it!
I found a solution, but it has two small problems:
- You can only use it on a borderless form
- The desktop refreshes if it's activated
But if you're making a shell, those shouldn't be a problem, since there's no such thing as a desktop 
The solution was simple, I subclassed the WM_ACTIVATE as you already did, and noticed that when you use a border, it can still come to the top if you hold the button on the titlebar, so I set BorderStyle to None and it worked. The only problem was that it showed the form being on top of the others for a few milliseconds and then went back.
The subclassing was done using the vbAccelerator subclassing component, so I don't know exactly how it's done otherwise. But basically, I consumed the WM_ACTIVATE message (ISubclass_MsgResponse = emrConsume, if you use the vbAccelerator component) and used the following code in the WindowProc event:
Code:
Call LockWindowUpdate(Me.hwnd)
Call SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE)
Call LockWindowUpdate(0)
This worked great, even the controls on the form can still be used normally. The only real problem was that the desktop refreshed because of the LockWindowUpdate...
Good luck!
Teaudirenopossum.Musasapientumfixaestinaure.
(I can't hear you. There's a banana in my ear)
-
Feb 23rd, 2009, 03:55 PM
#5
Thread Starter
Fanatic Member
Re: Window always on bottom
Wow, it only took me 10 year to solve this one proper...
Subclass the WM_WINDOWPOSCHANGING message. The lParam is a WINDOWPOS. In vb6, you need to use RtlMoveMemory api function to copy the lParam to an empty WINDOWPOS variable.
Set the hWndInsertAfter field to HWND_BOTTOM and copy the structure back to the lParam.
In .Net (where I solved this problem), override the wndproc method. Look for the WINDOWPOSCHANGING message.
vb Code:
Dim memloc As IntPtr = m.LParam
Dim pos As WINDOWPOS = m.GetLParam(GetType(WINDOWPOS))
pos.hWndInsertAfter = HWND_BOTTOM
Marshal.StructureToPtr(pos, memloc, True)
-
Dec 23rd, 2012, 06:07 AM
#6
Re: Window always on bottom
 Originally Posted by agent
Wow, it only took me 10 year to solve this one proper...
Subclass the WM_WINDOWPOSCHANGING message. The lParam is a WINDOWPOS. In vb6, you need to use RtlMoveMemory api function to copy the lParam to an empty WINDOWPOS variable.
Set the hWndInsertAfter field to HWND_BOTTOM and copy the structure back to the lParam.
In .Net (where I solved this problem), override the wndproc method. Look for the WINDOWPOSCHANGING message.
vb Code:
Dim memloc As IntPtr = m.LParam Dim pos As WINDOWPOS = m.GetLParam(GetType(WINDOWPOS)) pos.hWndInsertAfter = HWND_BOTTOM Marshal.StructureToPtr(pos, memloc, True)
Could you (or any Good Samaritan) attach a small (but working) VB6 example project ?
Thanks,
Rob
PS I wouldn't know a windows shell if I found it on the beach. All I am looking for is a normal VB6 program running in a normal Windows (XP) that will allow my project's Form (or whatever display) always be on the bottom. It would show in front of the normal Windows desktop, but would never be in front of other running applications.
Last edited by Bobbles; Dec 23rd, 2012 at 06:16 AM.
Reason: clarification
-
Dec 23rd, 2012, 07:45 AM
#7
Re: Window always on bottom
Code:
'In a BAS module
Option Explicit
Private Const GWL_WNDPROC As Long = (-4&) 'Sets a new address for the window procedure.
Private Const HWND_BOTTOM As Long = 1 'Places the window at the bottom of the Z order.
Private Const WM_DESTROY As Long = &H2 'Sent when a window is being destroyed.
Private Const WM_WINDOWPOSCHANGING As Long = &H46 'Sent to a window whose size, position, or place in the Z order is about to change as a result of a call to the SetWindowPos function or another window-management function.
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcW" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongW" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Sub PutMem4 Lib "msvbvm60.dll" (ByVal Ptr As Long, ByVal Value As Long)
Private m_PrevWndFunc As Long
'In Form_Load(), call it like: Subclass hWnd
Public Function Subclass(ByVal hWnd As Long) As Boolean
m_PrevWndFunc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
Subclass = m_PrevWndFunc <> 0&
End Function
Private Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
Case WM_WINDOWPOSCHANGING
PutMem4 lParam + 4&, HWND_BOTTOM 'hWndInsertAfter
Exit Function 'Return zero
Case WM_DESTROY
uMsg = SetWindowLong(hWnd, GWL_WNDPROC, m_PrevWndFunc): Debug.Assert uMsg
uMsg = WM_DESTROY
End Select
WindowProc = CallWindowProc(m_PrevWndFunc, hWnd, uMsg, wParam, lParam)
End Function
The Windows Shell:
The Windows UI provides users with access to a wide variety of objects necessary for running applications and managing the operating system. The most numerous and familiar of these objects are the folders and files that reside on computer disk drives. There are also a number of virtual objects that allow the user to perform tasks such as sending files to remote printers or accessing the Recycle Bin. The Shell organizes these objects into a hierarchical namespace and provides users and applications with a consistent and efficient way to access and manage objects.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|