Bringing window to foreground

I wrote a simple messaging app that I use to send short text messages between computers on my home network. Typically, the window will sit in the background and I send it to the foreground when a message comes in by

def bring_to_front(self):
    hwnd = win32gui.FindWindow(None, self.title)
    win32gui.ShowWindow(hwnd, win32con.SW_SHOWNORMAL)
    win32gui.SetForegroundWindow(hwnd)

The odd thing is that on two nearly identical laptops, both running Windows 11 Home, on one laptop the Window pops to the foreground when a message is received. On the other, the Window stays in the background but the taskbar icon flashes. Any idea why the difference with the same code?

Try this:

import win32gui
import win32con

def get_window_hwnd(window_titlex):
    thelist = []

    def findit(hwnd, ctx):
        if window_titlex in win32gui.GetWindowText(hwnd).lower():
            thelist.append(hwnd)

    win32gui.EnumWindows(findit, None)
    if thelist:
        return thelist[0]
    else:
        return None


def focus_on_the_window(window_title):
    def windowEnumerationHandler(hwnd, top_windowsx):
        top_windowsx.append((hwnd, win32gui.GetWindowText(hwnd)))

    results = []
    top_windows = []
    win32gui.EnumWindows(windowEnumerationHandler, top_windows)
    the_window_hndw = get_window_hwnd(window_title)
    if the_window_hndw:
        if win32gui.IsIconic(the_window_hndw):
            win32gui.ShowWindow(the_window_hndw, win32con.SW_SHOWNOACTIVATE)
    for i in top_windows:
        if window_title in i[1].lower():
            print(i)
            win32gui.ShowWindow(i[0], 5)
            win32gui.SetForegroundWindow(i[0])
            break

I appreciate the response but I have to say that is some of the most confusing code I have ever seen. It seems to me that the entire block could be reduced to

hwnd = win32gui.FindWindow(None, title)
win32gui.ShowWindow(hwnd, win32con.SW_SHOWNOACTIVATE)

what about just using style wx.STAY_ON_TOP (no win32 etc) :hot_face:

Because I don’t want it to stay on top. I just want to bring it to the top when a message is received. I did manage to get it working by

self.Show()
hwnd = win32gui.FindWindow(None, self.title)
win32gui.ShowWindow(hwnd, win32con.SW_SHOWNORMAL)
win32gui.SetForegroundWindow(hwnd)

and this way the user can switch to another window until another message comes in. As I recall (pre retirement in 2008) Windows NT used to have a “send” option for net.exe as in

net send computername message text

but this is either no longer supported, or just not vailable for Windows Home. Or perhaps it is only available in a WIndows Domain.

By you programmatically calling SetForegroundWindow, aren’t you taking focus away from the taks the user is performing? If they’re typing away on something, doesn’t SetForegroundWindow automatically switch their input to your application, so now they’re typing into your simple messaging app?
What if they just got through entering their username into some dialog, and now your window pops up without their input, and they now type their password into your messaging app?

That is the desired behaviour in this specific case.

the user can minimize it (or hide it) and when a new message comes in show it again ? :face_with_hand_over_mouth:

If I don’t make it top-most then the user has the option of leaving it on-screen and switching to another window, or minimizing. If I make it top-most then the user has one fewer options. A small distinction but I think it’s nice to have the choice.

run this skeleton (the main idea should be clear): every 10 seconds the window will be right at the top and updated, if minimized (available in the task bar) or not and the user can do whatever is on his mind :cowboy_hat_face:

from threading import Thread, Event
import wx

class Listen(Thread):

    def __init__(self, evh, evt_quit):
        super().__init__()
        self.evh = evh
        self.evt_quit = evt_quit
        self.start()

    def run(self):
        count = 1
        while not self.evt_quit.is_set():
            if divmod(count, 10)[1] == 0:
                wx.CallAfter(self.evh.pop_up, count)
            wx.Sleep(1)
            count += 1
            print(str(count))

class Gui(wx.Dialog):

    def __init__(self):
        super().__init__(None, title='My App',
            style=wx.DEFAULT_FRAME_STYLE|wx.STAY_ON_TOP)

        self.evt_quit = Event()
        Listen(self, self.evt_quit)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add(wx.StaticText(self, -1, label='Message no '))
        hbox.Add(5, 0)
        self.msg = wx.TextCtrl(self)
        hbox.Add(self.msg)
        self.SetSizer(hbox)
        self.Layout()
        self.Bind(wx.EVT_CLOSE, self.close)
        self.Bind(wx.EVT_WINDOW_DESTROY,
                                    lambda _: print(f'{self=} detroyed'))

    def pop_up(self, value):
        self.Restore()
        self.msg.ChangeValue(str(value))
        wx.Bell()

    def close(self, _):
        self.evt_quit.set()
        self.Destroy()

    def __del__(self):
        print(f'{self=} __del__')

app = wx.App()
Gui()
app.MainLoop()

I don’t mean to sound ungrateful but the meaning is not obvious. And if the meaning is not obvious then it should be documented. I do not understand the intention of the code, or why you are using threading and callbacks. It seems overly complex for the situation. If you are doing polling then what is the point of threading. I know I did not post my full code but I typically run the app on a 10 second sleep polling loop. When a message is sent or received I go into a 1 second loop, then switch back to 10 seconds if no message is sent or received within 60 seconds.

repeating your own demand

  • the user can minimize it or just carry on working

  • if a message is received it pops up to the top

(for a Gui polling in a thread is the most simple way :wink:)

Pardon my ignorance, but why is polling in a thread simpler than polling without a thread? I’ve only used threading for one app (to scan a folder and hash images in the background) and it was my understanding that because of the GIL (which can be disabled in release 3.13) threading doesn’t buy you much anyway.

Also, I rarely make demands. I developed the app in a particular way but I am always open to better ways as long as the “better” way doesn’t unnecessarily complicate things. It’s like optimization. It’s not worth it for a 1% improvement in speed to mangle the clarity of the code.

the Gui is best to run in the main thread (for catching all the events from the operating system) and a time consuming process (polling or such) must run somewhat ‘parallel’ in order not to disturb the Gui and the wx.CallAfter is a simplified way of feeding the non-GUI results into the GUI thread :innocent:

Ah. I see your point. Putting the polling/sleep in a thread makes the GUI more responsive.

Lesson learned. Thanks.

It works for me.

It took a while to get back to it, but thanks to @da-dada’s suggestions I was able to put the watcher into a thread. It’s working much better now. Thanks for the help.