Forcing a window to the front after running another process


  • kills Dumbledore

    OK, so this is a weird one. I think it's possibly related to different Windows versions changing how they prevent focus stealing

    The situation:
    We have a VB.net Winforms application that consists of a main window, usually left maximised, and additional windows opened for different activities. The flow in this case is as follows:

    • from the main window, open a client
    • from the client, open a policy
    • from the policy, create a document to send to the client.
      • this opens another window from which you choose a template, then the template is populated with client and policy details and fed into Word for the user to make any edits.
      • On closing and saving the document, a final window comes up asking what to do with the document (email or printing for physical delivery). This window is meant to be modal (opened with ShowDialog), but doesn't actually block windows underneath. This is probably a bug but not the one I'm interested in at the moment.

    The problem:
    On Windows 7, this all works pretty much as expected, apart from the minor issue above where the modal window isn't actually modal. It is always on top which is good enough for the purposes.

    On Windows 10, the final window comes up underneath every other window from the application. Investigating it in debug shows that the topmost property is true but this appears to be ignored.

    An additional complication I've just encountered: on Windows 7, if the main window is maximised and you switch to it from the policy window, then switch back and do the document part, the behaviour is like Windows 10: the last window comes up bottom in the Z order instead of on top.

    All I can think of is that this must be to do with Windows changes to prevent annoying focus stealing, and the fact that Word is opened and closed in the middle of the process somehow confuses it into thinking that the final window is trying to steal focus from Word.

    Is there some way to work around this? Ideally without engaging in the arms race between focus stealing applications and Windows trying to stop them annoying users


  • Trolleybus Mechanic

    @Jaloopa said in Forcing a window to the front after running another process:

    • from the policy, create a document to send to the client.
      • this opens another window from which you choose a template, then the template is populated with client and policy details and fed into Word for the user to make any edits.
      • On closing and saving the document, a final window comes up asking what to do with the document (email or printing for physical delivery). This window is meant to be modal (opened with ShowDialog), but doesn't actually block windows underneath. This is probably a bug but not the one I'm interested in at the moment.

    I'm assuming, that the Template chooser is closed when Word is started, so logically the workflow is now back to the policy window.
    What about parenting the dialog window to that? That should make it trivial to have a modal topmost window.



  • @Jaloopa Does Windows have multiple layers on which windows can sit? If so, would it solve the problem if you move the dialog to a layer in front of those of normal windows?


  • kills Dumbledore

    @OloEopia said in Forcing a window to the front after running another process:

    What about parenting the dialog window to that? That should make it trivial to have a modal topmost window

    Trivial if there weren't multiple layers of indirection in creating a new window with the architecture of this application.


  • kills Dumbledore

    @Gurth said in Forcing a window to the front after running another process:

    @Jaloopa Does Windows have multiple layers on which windows can sit? If so, would it solve the problem if you move the dialog to a layer in front of those of normal windows?

    If it does, I'm not familiar with the API


  • kills Dumbledore

    I cargo culted a fix by adding a bunch of calls to various bring to front methods in the Activated event handler. On Monday I'll work out the minimum required set of lines and then try to research what exactly it's all doing



  • @Jaloopa My understanding was that the bringtofront apis only work if the app has focus to begin with. The intent is to prevent random apps from popping up in front. (We have a bug now about this - people want it to pop in front - and of course, it works some machines and not on others... sigh.)


  • Banned

    What's the parent of the dialog anyway? Also, do all windows belong to the same process (except Word, of course)?



  • @Jaloopa said in Forcing a window to the front after running another process:

    If it does, I'm not familiar with the API

    I can’t seem to find anything that indicates the concept is even present in Windows, but I’m not exactly familiar with programming for it, so chances are I missed something.


  • kills Dumbledore

    @Gurth if there was, it would surprise me not to have ever heard about it in things like Raymond Chen's blog.


  • kills Dumbledore

    @dcon said in Forcing a window to the front after running another process:

    @Jaloopa My understanding was that the bringtofront apis only work if the app has focus to begin with. The intent is to prevent random apps from popping up in front. (We have a bug now about this - people want it to pop in front - and of course, it works some machines and not on others... sigh.)

    Yeah,I'm sure it's to do with the fact that the window is created in response to the Word window closing. The weird thing is that it comes up below everything in its own application


  • kills Dumbledore

    @Gąska said in Forcing a window to the front after running another process:

    What's the parent of the dialog anyway? Also, do all windows belong to the same process (except Word, of course)?

    The parent property is null. The internal API does have a way to pass in a parent but the way it's called means it would need changes through quite a big call stack and some of it is more generic so would need much more extensive testing


  • Banned

    @Jaloopa unfortunately, there's no other way to do it sanely (ie. so that it doesn't break with next update). Though if you want to go the hacky way, maybe instead of pushing it to the top, try pushing everything else (in your app) to the bottom?



  • Here's how I did this in Python:

    import ctypes
    import tkinter as tk
    import keyboard # https://github.com/boppreh/keyboard/
    
    root = tk.Tk()
    
    # set up widgets, etc.
    # for why you have to simulate an ALT keypress, see
    # https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-locksetforegroundwindow#remarks
    
    keyboard.send('alt', do_release=False) 
    ctypes.windll.user32.SetForegroundWindow(root.winfo_id())        
    keyboard.send('alt', do_press=False)
    

  • Banned

    @marczellm said in Forcing a window to the front after running another process:

    do_release=False

    do_press=False

    *twitch*


  • Notification Spam Recipient

    @marczellm said in Forcing a window to the front after running another process:

    *Reads*

    0_1540167570909_ba2dbefe-d392-4331-b7ef-e7e6fa047205-image.png

    Wowww....


Log in to reply