简体   繁体   English

让 Win32 MessageBox 出现在其他程序之上

[英]Have Win32 MessageBox appear over other programs

I've recently started learning Python and wrote a little script that informs me when a certain website changes content.我最近开始学习 Python 并编写了一个小脚本,当某个网站更改内容时会通知我。 I then added it as a scheduled task to Windows so it can run every 10 minutes.然后我将它作为计划任务添加到 Windows,以便它可以每 10 分钟运行一次。 I'd like to be informed of the website changing right away so I added a win32ui MessageBox that pops up if the script detects that the website has changed.我想立即收到有关网站更改的通知,因此我添加了一个 win32ui MessageBox,如果脚本检测到网站已更改,则会弹出该消息框。 Here's the little code snippet I'm using for the MessageBox (imaginative text, I know):这是我用于 MessageBox 的小代码片段(我知道是富有想象力的文本):

win32ui.MessageBox("The website has changed.", "Website Change", 0)

My issue is this, I spend most of my time using remote desktop so when the MessageBox does pop up it sits behind the remote desktop session, is there any way to force the MessageBox to appear on top of it?我的问题是,我大部分时间都在使用远程桌面,所以当 MessageBox 弹出时,它位于远程桌面会话的后面,有没有办法强制 MessageBox 出现在它上面?

On a similar note when the script runs the command line opens up very briefly over the remote desktop session which I don't want, is there any way of stopping this behaviour?在类似的说明中,当脚本运行时,命令行在我不想要的远程桌面会话上非常短暂地打开,有没有办法阻止这种行为?

I'm happy with Windows specific solutions as I'm aware it might mean dealing with the windowing manager or possibly an alternative way to inform me rather than using a MessageBox.我对 Windows 特定的解决方案很满意,因为我知道这可能意味着处理窗口管理器或可能是一种通知我而不是使用 MessageBox 的替代方法。

When you start anything from Task Scheduler, Windows blocks any " easy " ways to bring your windows or dialogs to top.当您从 Task Scheduler 启动任何内容时,Windows 会阻止任何“简单”的方式将您的窗口或对话框置于顶部。

  1. First way - use MB_SYSTEMMODAL (4096 value) flag.第一种方式 - 使用MB_SYSTEMMODAL (4096 值)标志。 In my experience, it makes Msg dialog "Always on top".根据我的经验,它使 Msg 对话框“始终在最前面”。

     win32ui.MessageBox("The website has changed.", "Website Change", MB_SYSTEMMODAL)
  2. Second way - try to bring your console/window/dialog to the front with Following calls.第二种方式 - 尝试使用以下调用将您的控制台/窗口/对话框置于最前面。 Of course, if you use MessageBox you must do that (for your own created window) before calling MessageBox .当然,如果您使用MessageBox ,则必须在调用MessageBox之前执行此操作(对于您自己创建的窗口)。

     SetForegroundWindow(Wnd); BringWindowToTop(Wnd); SetForegroundWindow(Wnd);

As for flickering of the console window, you may try to start Python in a hidden state.对于控制台窗口的闪烁,您可以尝试在隐藏状态下启动Python。 For example, use ConEmu , 'HidCon' or cmdow .例如,使用ConEmu 、 'HidCon' 或cmdow Refer to their parameters, something like:参考他们的参数,比如:

ConEmu -basic -MinTSA -cmd C:\Python27\python.exe C:\pythonScript.py
    or
CMDOW /RUN /MIN C:\Python27\python.exe C:\pythonScript.py

Avoiding the command window flash is done by naming the script with a pyw extension instead of simply py .避免命令窗口闪光灯被用命名脚本完成pyw扩展,而不是简单py You might also use pythonw.exe instead of python.exe , it really depends on your requirements.您也可以使用pythonw.exe而不是python.exe ,这实际上取决于您的要求。

See http://onlamp.com/pub/a/python/excerpts/chpt20/index.html?page=2http://onlamp.com/pub/a/python/excerpts/chpt20/index.html?page=2

Use ctypes it displays an windows error message box very easy to use,使用 ctypes 它显示一个非常容易使用的 windows 错误消息框,

import ctypes
if condition:
    ctypes.windll.user32.MessageBoxW(0, u"Error", u"Error", 0)

This works for me:这对我有用:

from ctypes import *
def MessageBox(title, text, style):
    sty = int(style) + 4096
    return windll.user32.MessageBoxW(0, text, title, sty) #MB_SYSTEMMODAL==4096
    ## Button Styles:
    ###  0:OK  --  1:OK|Cancel -- 2:Abort|Retry|Ignore -- 3:Yes|No|Cancel -- 4:Yes|No -- 5:Retry|No -- 6:Cancel|Try Again|Continue
    ## To also change icon, add these values to previous number
    ### 16 Stop-sign  ### 32 Question-mark  ### 48 Exclamation-point  ### 64 Information-sign ('i' in a circle)

Usage:用法:

MessageBox('Here is my Title', 'Message to be displayed', 64)

Making the message box system modal will cause it to pop up over every application, but none can be interacted with until it is dismissed.使消息框系统模态将导致它在每个应用程序上弹出,但在它被关闭之前不能与之交互。 Consider either creating a custom dialog box window that you can bring to the front or using a notification bubble instead.考虑创建一个可以放在最前面的自定义对话框窗口,或者改用通知气泡。

Windows tries to make it hard to pop a window over the active application. Windows 试图使在活动应用程序上弹出窗口变得困难。 Users find it annoying, especially since the interrupting window generally steals keyboard focus.用户觉得这很烦人,尤其是因为中断窗口通常会窃取键盘焦点。

The Windows way to give a notification like this is with a balloon in the notification area rather than a message box. Windows 发出这样的通知的方式是在通知区域中使用气球而不是消息框。 Notification balloons don't steal focus and are (supposedly) less distracting.通知气球不会窃取焦点并且(据说)不那么分散注意力。

I'm not sure if the python Windows UI library offers wrappers for notification balloons .我不确定 python Windows UI 库是否提供了通知气球的包装器。

Very easy modal async message box with help of Python and MSG command (working on Win10):在 Python 和 MSG 命令的帮助下非常简单的模态异步消息框(在 Win10 上工作):

# In CMD (you may use Username logged on target machine instead of * to send message to particular user):
msg /server:IP_or_ComputerName * /v /time:appearance_in_secs Message_up_to_255_chars 
# I.e. send "Hello everybody!" to all users on 192.168.0.110 disappearing after 5 mins 
msg /server:192.168.0.110 * /v /time:300 "Hello everybody!"

In Python I've been using subprocess to send CMD commands, allows me to read and process output, find error etc.在 Python 中,我一直使用subprocess发送 CMD 命令,允许我读取和处理输出,查找错误等。

import subprocess as sp

name = 'Lucas'
message = f'Express yourself {name} in 255 characters ;)'
command = f'msg /server:192.168.0.110 * /v /time:360 "{message}"'
output = str(sp.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT))

if 'returncode=0' in output:
    pint('Message sent')
else:
    print('Error occurred. Details:\n')
    print(output[output.index('stdout=b'):])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM