Preventing all thread's windows becoming foreground when one of them is activated
|
|
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
|
|
|