Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / Win API / February 2008



Tip: Looking for answers? Try searching our database.

Preventing all thread's windows becoming foreground when one of them is activated

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Johannes Franke - 18 Feb 2008 14:38 GMT
Hi all,

seems like I am trying to fight a "feature" here. Well, maybe there is some
help.
I am developing a multi-window Office add-on. It's not MDI, and the windows
are not all the same. As I don't want to handicap users working with Office
by modal dialogs, I have decided to make most of the dialogs modeless. Thus,
it is possible to open about 10 different windows simultaneously without
blocking the Office program.
The issue is that on activating any of the dialogs (by clicking the mouse in
it or activating the appropriate window button in the task bar), all of the
other open windows of my app are also put to the foreground even if the user
wanted to gain access only of the one form he/she clicked.
I suspect that this is an intended behaviour of VB6, but for me it's rather
inconvenient and I'd like to know about ways to get around it. I cannot put
each window in a different thread (it's VB6), and even if it were possible
that way, it still demands too much time to develop and may have some
negative impact on the application's overall stability.

Steps for reproduction:

- create a new standard VB6 EXE project
- add a new module to the project so now you have an unnamed form and an
unnamed module
- in the project properties, set startup mode to "Sub Main()"
- create a sub Main() in the module, with the following source code:

Sub Main()

   Dim oFrm As Form1
   Dim n As Long

   For n = 1 To 10
       Set oFrm = New Form1
       Call oFrm.Show
       Set oFrm = Nothing
   Next

End Sub

Running the project will result in a cascade of 10 windows in the top-left
corner of the screen. Drag any of them to a random screen position, then put
some different window in the foreground in the top-left corner (e.g. an
Explorer) so it hides the other nine windows at least partially.
Clicking on the one you dragged away will show not only the one on which you
clicked, but also the nine other windows from behind the Explorer will
reappear in front of it unintendedly. You can repeat this with any of the 10
windows. Activating any of them will always make all of the windows topmost.
Is there some way to make sure that the nine hidden windows stay in the
background in this situation? I'd like to do this the cleanest way possible
to make sure it runs in any environment, does not produce flicker or other
inconveniences.

Thank you a lot for your help!

Regards,
Joe
Vinchenzo vinç - 18 Feb 2008 15:50 GMT
> Hi all,
>
[quoted text clipped - 4 lines]
> wanted to gain access only of the one form he/she clicked.
> I suspect that this is an intended behaviour of VB6,

   Hi, this is the default realationship of all Forms created by your app, there is a 0x0 pixels window called 'Thunder[RTversion]Main", it is their *owner*, if you minimize the owner, all owned are minimized, if you destroy de owner, all owned are destroyed, ...and so on.
   For your task, you can remove (set to Null) the owner of any Form that you want to "detach/unlink/free", changing the GWL_HWNDPARENT bit with the SetWindowLong function.

   For example, following your sample code:

'****************
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
   ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Const GWL_HWNDPARENT As Long = -8

Sub Main()

  Dim oFrm As Form1
  Dim n As Long

  For n = 1 To 10
      Set oFrm = New Form1
      Call oFrm.Show
       SetWindowLong oFrm.hWnd, GWL_HWNDPARENT, 0& '<<<<
      Set oFrm = Nothing
  Next

End Sub
'****************

Signature

   Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
   http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
   http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Johannes Franke - 18 Feb 2008 16:07 GMT
Dear Vinchenzo,

great, that did it! Thank you very much for your explanations.

Greetings from Germany
Johannes

"Johannes Franke" <johannes_franke@hotmail.com> escribió en el mensaje
news:OKF1gvjcIHA.1164@TK2MSFTNGP02.phx.gbl...
> Hi all,
>
[quoted text clipped - 7 lines]
> wanted to gain access only of the one form he/she clicked.
> I suspect that this is an intended behaviour of VB6,

   Hi, this is the default realationship of all Forms created by your app,
there is a 0x0 pixels window called 'Thunder[RTversion]Main", it is their
*owner*, if you minimize the owner, all owned are minimized, if you destroy
de owner, all owned are destroyed, ...and so on.
   For your task, you can remove (set to Null) the owner of any Form that
you want to "detach/unlink/free", changing the GWL_HWNDPARENT bit with the
SetWindowLong function.

   For example, following your sample code:

'****************
Private Declare Function SetWindowLong Lib "user32.dll" Alias
"SetWindowLongA" ( _
   ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As
Long
Private Const GWL_HWNDPARENT As Long = -8

Sub Main()

  Dim oFrm As Form1
  Dim n As Long

  For n = 1 To 10
      Set oFrm = New Form1
      Call oFrm.Show
       SetWindowLong oFrm.hWnd, GWL_HWNDPARENT, 0& '<<<<
      Set oFrm = Nothing
  Next

End Sub
'****************

Signature

   Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
   http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
   http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Ed - 19 Feb 2008 20:56 GMT
>'****************
>Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
[quoted text clipped - 15 lines]
>End Sub
>'****************

Hi,

Nice solution, but one problem, my form is set to ShowInTaskbar=False
and now when a form gets focus it shows up in the Taskbar.

Anyway to keep the forms from showing up in the Taskbar?

Thanks,
Ed
Karl E. Peterson - 19 Feb 2008 21:06 GMT
>>'****************
>>Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
[quoted text clipped - 22 lines]
>
> Anyway to keep the forms from showing up in the Taskbar?

Take a look at http://vb.mvps.org/samples/FormBdr for one method to toggle the
ShowInTaskbar property at runtime.
Signature

.NET: It's About Trust!
http://vfred.mvps.org

Ed - 20 Feb 2008 19:11 GMT
>Take a look at http://vb.mvps.org/samples/FormBdr for one method to toggle the
>ShowInTaskbar property at runtime.

Doesn't seem to work with SetWindowLong oFrm.hWnd, GWL_HWNDPARENT, 0&
Karl E. Peterson - 20 Feb 2008 19:39 GMT
>>Take a look at http://vb.mvps.org/samples/FormBdr for one method to toggle the
>>ShowInTaskbar property at runtime.
>
> Doesn't seem to work with SetWindowLong oFrm.hWnd, GWL_HWNDPARENT, 0&

Hmmmm, yeah, confirmed.

Is there another common application that exhibits the behavior you're attempting to
implement?  If so, we might be able to glean a few hints from that.  If not, well,
perhaps there's a reason.
Signature

.NET: It's About Trust!
http://vfred.mvps.org

Vinchenzo vinç - 20 Feb 2008 23:15 GMT
> Hi,
>
> Nice solution, but one problem, my form is set to ShowInTaskbar=False
> and now when a form gets focus it shows up in the Taskbar.
>
> Anyway to keep the forms from showing up in the Taskbar?

   Hi Ed, of course there is a way, ...mimicking more or less the VB's way.

   Use the CreateWindowEx function to create a new 0x0 pixels "Thunder[RTversion]Main", window with the styles WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_OVERLAPPED, and the extended styles WS_EX_LEFT|WS_EX_LTREADING|WS_EX_RIGHTSCROLLBAR|WS_EX_TOOLWINDOW.
   Set a new owner to all Forms that you want independent to each other, and those with ShowInTaskbar=False will not show its icon in the taskbar:

'****************
···

Set oFrm = New Form1
Call oFrm.Show
SetWindowLong oFrm.hwnd, _
             GWL_HWNDPARENT, _
             CreateWindowEx( _
                            &H80, "ThunderMain", _
                            vbNullString, &H94000000, _
                            0&, 0&, 0&, 0&, 0&, 0&, _
                            GetWindowLong(oFrm.hwnd, GWL_HINSTANCE), _
                            0&)

···
'****************

   Set the appropiate window classname, "ThunderMain" if you test it in the IDE, or compiled for instance in VB6 "ThunderRT6Main".


Signature

   Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
   http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
   http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Ed - 21 Feb 2008 20:30 GMT
>    Hi Ed, of course there is a way, ...mimicking more or less the VB's way.
>
[quoted text clipped - 19 lines]
>
>    Set the appropiate window classname, "ThunderMain" if you test it in the IDE, or compiled for instance in VB6 "ThunderRT6Main".

Added to my project and it's working very nice! :)

Thanks a million,
Ed
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.