Click to See Complete Forum and Search --> : Keeping a form on top


Rupert Bates
March 12th, 1999, 09:20 AM
Does anyone know of a way to keep a form 'on top' in VB even when it is not the active form, so it behaves like a tool palette. An example of the sort of thing I mean is the toolbox in VB (when it is not docked obviously).


Rupert

Chris Eastwood
March 12th, 1999, 09:38 AM
Hi


This is one of the most asked questions about VB programming. I've got a routine (posted below) that does exactly what you want - it's taken from my VBCodeLibrary sample project on the CodeGuru site :


(http://www.codeguru.com/vb/articles/1634.shtml)


- This also includes some other tips & tricks and allows you to keep a database of all this handy code in one place.


Here's the code :


'

' Declarations

'


Public Declare Function SetWindowPos Lib "user32" _

(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _

ByVal x As Long, ByVal y As Long, ByVal cx As Long, _

ByVal cy As Long, ByVal wFlags As Long) As Long


'

' Sets a form Topmost

'


Public Sub SetTopMost(ByVal lHwnd As Long, ByVal bTopMost As Boolean)

'

' Set the hwnd of the window topmost or not topmost

'

Dim lUseVal As Long

Dim lRet As Long



lUseVal = IIf(bTopMost, HWND_TOPMOST, HWND_NOTOPMOST)



lRet = SetWindowPos(lHwnd, lUseVal, 0, 0, 0, 0, SWPFLAGS)



If lRet < 0 Then

'

' Couldn't do operation - handle error here

'

' DisplayWinAPIError lRet

End If


End Sub


So, to get your Form TopMost :


SetTopMost myForm.hwnd, True


or :


SetTopMost myForm.hwnd, False


to undo the operation


Regards


Chris Eastwood


CodeGuru - the website for developers

http://www.codeguru.com/vb

Rupert Bates
March 12th, 1999, 11:20 AM
Chris, thanks for your reply and forgive me if I'm being dense but where do I get the values of HWND_TOPMOST, HWND_NOTOPMOST and SWPFLAGS from?

Rupert

Chris Eastwood
March 13th, 1999, 06:38 AM
Hi


Sorry about that - I forgot to put them into my code library.


You should be able to get them from the API viewer that comes with VB (look at the add-ins menu).


Otherwise :


Public Const SWP_NOMOVE = 2 ' Constants used in Setting Window

Public Const SWP_NOSIZE = 1 ' Position (eg. Topmost)

Public Const SWP_HIDEWINDOW = &H80

Public Const SWP_SHOWWINDOW = &H40


Public Const SWPFLAGS = SWP_NOMOVE Or SWP_NOSIZE '

Public Const HWND_TOPMOST = -1 '

Public Const HWND_NOTOPMOST = -2 '


Regards


Chris Eastwood


CodeGuru - the website for developers

http://www.codeguru.com/vb

Rupert Bates
March 15th, 1999, 08:39 AM
Chris, I can't get this code to work. I have two MDIChild forms and I am trying to make it so that form2 will never appear above form1 (a tool palette) even when form2 is active. I have tried:


ret = SetWindowPos(Form1.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE)


which returns successfully, but does not do the trick, the window's zordering simply follows activation (whichever window is active is also on top).

Am I missing something?

Chris Eastwood
March 15th, 1999, 09:50 AM
Oh


I didn't realize you were using MDI child forms. The SetWindowPos api call will have no effect on MDI child windows.


There is no easy way to make an MDI child form 'on-top' in VB. You need to get into the down & dirty world of subclassing to capture the WM_WINDOWPOSCHANGED message - there's an article about the on the MSDN :


Q108315



- No easy fixes here, but if you know about subclassing, it shouldn't be too difficult.


Regards


Chris Eastwood


CodeGuru - the website for developers

http://www.codeguru.com/vb

Rupert Bates
March 16th, 1999, 08:44 AM
Chris,

Now I have my SetWindowPos call working (I wonder if you can guess what's coming next), how can I set my topmost window to NOTOPMOST if the user alt+tabs out of the application. Currently my window just stays on top of all other application windows.

Rupert

Chris Eastwood
March 16th, 1999, 09:16 AM
Hi Rupert


Now this is a tricky one - Steve at vbaccelerator (http://vbaccelerator.com) has written quite a bit about capturing the lost-focus / deactivate event of an application.


This is pretty heavy stuff unless you know something about subclassing and windows messages - I'm not going to try and repeat it here when Steve has done such an excellent job. There's an example and tutorial at the link below that should help you get on your way :


http://vbaccelerator.com/codelib/ssubtmr/yielddet.htm


Good Luck


Chris Eastwood


CodeGuru - the website for developers

http://www.codeguru.com/vb




Detecting when another application is activated

Rupert Bates
March 24th, 1999, 06:52 AM
As a postscript to this discussion, I have just found out that I can achieve the effect I wanted (keeping a tool palette or wizard window on top of the top level mdi window when not active) by showing the tool window with:


frmToolWindow.show vbModeless, Me


where Me is the mdi form. So simple and yet so difficult to work out from the documentation!

Chris Eastwood
March 24th, 1999, 11:09 AM
Hi Rupert


- That was a good find -


I knew about the '.show vbmodal/vbmodeless, me' option, but it had completely slipped my mind (Karl Peterson mentioned it in VBPJ a few months back).


Do you want to enter this into the OpenFaq on the CodeGuru site ?


Regards


Chris Eastwood


CodeGuru - the website for developers

http://www.codeguru.com/vb

Ravi Kiran
March 25th, 1999, 05:26 AM
Hi,


Infact i had also implimented this!. It was a a case of just 2 forms. (Both SDI) and one had an Image covering almost entire screen ( a 720x720 img), and other some parameter setting form. Some of these params were set by clicking on the image, for which i needed the 'tool bar' like effect you are talking about. I had achieved this using Form2.Show VbModeless Form1!!


I had tried a similar effect on another occasion and FAILED, because one of the forms was shown 'Modal', and we cannot have a 'Modeless child' for a Modal parent.(It was a multi form app, and i was trying it at the wrong place) Hence i didn't know if it would work in MDI case!


Chris, mention this point also, if you do!.


Ravi