Jump to content

Convert msgbox from other applications to toast/ballon


Recommended Posts

Hello.

I'm using some software that displays bunch of unnecessary messages as message box with "ok" button.

I'd like to automatically "convert" these messages into toast or balloon, which is relatively easy task.

Before I waste my time code it, I thought I'd ask if maybe someone already done this, I've search the forum, but nothing came up.

Has anyone seen anything that would do that?

 

Thank you.

Link to comment
Share on other sites

You can check in a loop (or a hook but I don't think it's necessary to complicate the script) when certain messageboxes appear on the screen, then grab the message, close the message box and display the message as you like.

Link to comment
Share on other sites

Hello. Modify this code. Check for the window's Process. play with it get the text, hide it, click it etc. 

 

Saludos

Link to comment
Share on other sites

7 minutes ago, Danyfirex said:

Hello. Modify this code. Check for the window's Process. play with it get the text, hide it, click it etc. 

 

Saludos

Thank you. This doesn't seem to be working for message boxes, only for unowned windows, while message boxes usually a child of a main window (?)

Link to comment
Share on other sites

bring it to your needs

;
;~ #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 6 -w 7

#include <WinAPIProc.au3>
#include <WinAPISysWin.au3>
#include <StringConstants.au3>
#include <TrayConstants.au3>

Opt("TrayMenuMode", 3) ; These are options 1 and 2 for TrayMenuMode.
Opt("TrayOnEventMode", 1) ; Enable TrayOnEventMode.

Global $bPaused = False
TraySetIcon(StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", $STR_NOCASESENSEBASIC, -1) - 1) & "\Icons\MyAutoIt3_Blue.ico")

#Region === Tray_Menu ===
TraySetOnEvent($TRAY_EVENT_PRIMARYDOUBLE, "TogglePause")

Global $idPaused = TrayCreateItem("Pause", -1, -1, $TRAY_ITEM_RADIO)
TrayItemSetOnEvent(-1, "TogglePause")
TrayItemSetState(-1, $TRAY_UNCHECKED)

TrayCreateItem("") ; Create a separator line.
Global $idExit = TrayCreateItem("Exit")
TrayItemSetOnEvent(-1, "GoToExit")

#EndRegion === Tray_Menu ===


_Main()


;----------------------------------------------------------------------------------------
Func _Main()

    Local $hMBox, $iPID
    Local $sText, $sTitle, $sProcess
    Local $BlackList = "C:\Program Files (x86)\AutoIt3\SciTE\SciTE.exe" ; *** <---------

    ;**********************************
    While 1
        _GetTrayStatus()

        If WinActive("[CLASS:#32770]") Then
            $hMBox = WinGetHandle("[CLASS:#32770]")

            ; Retrieve the identifier of the thread and pass a variable to the $iPID parameter to store the PID.
            $iPID = 0
            $sProcess = ""
            _WinAPI_GetWindowThreadProcessId($hMBox, $iPID)
            $sProcess = _WinAPI_GetProcessFileName($iPID)

            If $sProcess = $BlackList Then
                $sText = ""
                $sTitle = ""
                $sText = ControlGetText ($hMBox, "", "Static2") ; WinGetText($hMBox) ; *** <---------
                $sTitle = WinGetTitle($hMBox)
                WinClose($hMBox)
                Tip($sText, $sTitle, 7, 2060)
            EndIf
        EndIf
        Sleep(10)
    WEnd
    ;**********************************

EndFunc   ;==>_Main

;----------------------------------------------------------------------------------------
Func GoToExit()    ; exit
    Exit
EndFunc   ;==>GoToExit
;----------------------------------------------------------------------------------------
Func _GetTrayStatus()
    While 1
        If $bPaused = False Then
            ExitLoop
        Else  ; calm down and stay
            Sleep(500)
        EndIf
    WEnd
EndFunc   ;==>_GetTrayStatus
;----------------------------------------------------------------------------------------
Func TogglePause()

    If $bPaused = False Then
        $bPaused = True
        TrayItemSetState($idPaused, $TRAY_CHECKED)    ; $TRAY_UNCHECKED, $TRAY_CHECKED
        TraySetIcon(StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", $STR_NOCASESENSEBASIC, -1) - 1) & "\Icons\MyAutoIt3_Red.ico")
    Else
        $bPaused = False
        TrayItemSetState($idPaused, $TRAY_UNCHECKED)    ; $TRAY_UNCHECKED, $TRAY_CHECKED
        TraySetIcon(StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", $STR_NOCASESENSEBASIC, -1) - 1) & "\Icons\MyAutoIt3_Blue.ico")
    EndIf

EndFunc   ;==>TogglePause
;----------------------------------------------------------------------------------------
; https://www.autoitscript.com/forum/topic/209408-traytipgui-to-send-a-message-to-the-tray
;----------------------------------------------------------------------------------------
Func Tip($Msg, $Title = "info", $Timeout = 3, $Icon = 2060)
    Local $FilePath = @ScriptDir & "\TrayTipGUI.au3"
    Local $Param = '"' & $Title & '" "' & $Msg & '" "' & $Timeout & '" "' & $Icon & '"'
    Run(FileGetShortName(@AutoItExe) & " " & FileGetShortName($FilePath) & " " & $Param)
EndFunc   ;==>Tip
;----------------------------------------------------------------------------------------

 

I know that I know nothing

Link to comment
Share on other sites

Posted (edited)

The detection of a popup is not an issue, however it turned out detection of the text inside become an issue...

image.png.94691e95a26555d00130c7472d9aac0e.png

image.png.19cef3e48bbf33d6b0db3a3cc63bddb7.png

None of the #31 methods seem to be able detect any text but "OK" from the button.

UWPOCR to the rescue:

 

Works great, but it's slow because of _ScreenCapture_CaptureWnd()

Is there a faster alternative?

Edited by VAN0
Link to comment
Share on other sites

Another approach would be to move the window to the usual toast location and close it after 2-3 secs.

Edit : made an example for the fun of it...

Run("Notepad")
Local $hWnd = WinWaitActive("[CLASS:Notepad]")
ControlSend($hWnd, "", "Edit1", "Test")
ControlSend($hWnd, "", "", "!{F4}")   ; simulate a msg box

While Sleep(10)
  $hWnd = WinGetHandle("[CLASS:#32770]")  ; or title "Bloc-notes" for french Notepad
  If $hWnd Then ExitLoop
WEnd

Local $aPos = WinGetPos($hWnd)
WinMove($hWnd, "", @DesktopWidth - $aPos[2] - 10, @DesktopHeight + 1)
ControlHide($hWnd, "", "Button1")
ControlHide($hWnd, "", "Button2")
ControlHide($hWnd, "", "Button3")

For $i = 15 To $aPos[3] + 50 Step 3
  WinMove($hWnd, "", @DesktopWidth - $aPos[2] - 10, @DesktopHeight - $i)
  Sleep(10)
Next
SoundPlay("C:\Windows\Media\Windows Notify Messaging.wav")
Sleep(2000)
WinKill($hWnd)

ps. changed a bit the code to make it more of toast

Edited by Nine
Link to comment
Share on other sites

check when the message box is active and press ctrl+c to see what text it receives  ..if


e.g. in Notepad receives:

[Window Title]
Notepad

[Main Instruction]
Do you want to save changes to Untitled?

[Save] [Don't Save] [Cancel]

e.g. in SciTE receives:

---------------------------
SciTE
---------------------------
Save changes to (Untitled)?
---------------------------
Yes   No   Cancel   
---------------------------

 

I know that I know nothing

Link to comment
Share on other sites

1 hour ago, Nine said:

Another approach would be to move the window to the usual toast location and close it after 2-3 secs.

I like that! didn't occur to me I can manipulate sizes, style and hide controls!
Just one issue with this, it won't allow clicking in parent application until popup closed, unless there is a way make it non-modal?

 

1 hour ago, ioa747 said:

check when the message box is active and press ctrl+c to see what text it receives  ..if

Unfortunately, it just makes "error" sound, and nothing being copied to clipboard. I guess it's not standard message box, although it's uses the same class

Link to comment
Share on other sites

4 minutes ago, VAN0 said:

unless there is a way make it non-modal?

Unfortunately, it is not possible, AFAIK.  Another way would be to move/hide the window like I did, make modifications to the window, use PrintWindow, kill the window, create a toast (guicreate) with a pic inside.  BTW, Printwindow is really fast...I don't think user would notice.

Link to comment
Share on other sites

Posted (edited)
15 hours ago, Nine said:

 BTW, Printwindow is really fast...I don't think user would notice.

I'm getting very promising results with this. But there are 2 issues:

1) sometimes it doesn't capture the window, because it runs too soon before popup fully painted. Is there a way detect if window has been fully painted? (I really don't want to add sleep()) [edit] this was due to me trying change style of the window: removing title bar, borders, buttons. Once I left everything intact, and just capture inside the window - it resolved this issue

 

2) using example from the help file:

#include <GUIConstantsEx.au3>
#include <SendMessage.au3>
#include <StaticConstants.au3>
#include <WinAPIGdi.au3>
#include <WinAPIGdiDC.au3>
#include <WinAPIHObj.au3>
#include <WindowsConstants.au3>

Run(@SystemDir & '\calc.exe')
Local $hWnd = WinWaitActive("[CLASS:ApplicationFrameWindow]", '', 3)
If Not $hWnd Then
        Exit
EndIf

; Create GUI
Local $iSize = WinGetPos($hWnd)
Local $hForm = GUICreate('Test ' & StringReplace(@ScriptName, '.au3', '()'), $iSize[2] + 80, $iSize[3] + 80)
Local $idPic = GUICtrlCreatePic('', 40, 40, $iSize[2], $iSize[3])
Local $hPic = GUICtrlGetHandle($idPic)

; Create bitmap
Local $hDC = _WinAPI_GetDC($hPic)
Local $hDestDC = _WinAPI_CreateCompatibleDC($hDC)
Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iSize[2], $iSize[3])
Local $hDestSv = _WinAPI_SelectObject($hDestDC, $hBitmap)
Local $hSrcDC = _WinAPI_CreateCompatibleDC($hDC)
Local $hBmp = _WinAPI_CreateCompatibleBitmap($hDC, $iSize[2], $iSize[3])
Local $hSrcSv = _WinAPI_SelectObject($hSrcDC, $hBmp)
_WinAPI_PrintWindow($hWnd, $hSrcDC)
_WinAPI_BitBlt($hDestDC, 0, 0, $iSize[2], $iSize[3], $hSrcDC, 0, 0, $MERGECOPY)

_WinAPI_ReleaseDC($hPic, $hDC)
_WinAPI_SelectObject($hDestDC, $hDestSv)
_WinAPI_SelectObject($hSrcDC, $hSrcSv)
_WinAPI_DeleteDC($hDestDC)
_WinAPI_DeleteDC($hSrcDC)
_WinAPI_DeleteObject($hBmp)

; Set bitmap to control
_SendMessage($hPic, $STM_SETIMAGE, 0, $hBitmap)
Local $hObj = _SendMessage($hPic, $STM_GETIMAGE)
If $hObj <> $hBitmap Then
        _WinAPI_DeleteObject($hBitmap)
EndIf

GUISetState(@SW_SHOW)

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

WinClose("[CLASS:ApplicationFrameWindow]", "")

I re-use the $hForm window and $idPic and just change their size for each popup. However when popup is the same size as previous popup but with different content, the image shows blended both popups (merged). If I reset $idPic to 0,0 size and then to correct size, it works fine, but I'm not sure if it's the most efficient way.

 

[EDIT]

Printwindow is really fast, and unlike _ScreenCapture_CaptureWnd it allows capture window while it's outside of view!

Edited by VAN0
Link to comment
Share on other sites

There is no reason to reuse the GUI (toast).  Once the original window is hidden, user won't see a thing.

Here my take :

#include <WinAPIGdiDC.au3>
#include <GUIConstants.au3>
#include <SendMessage.au3>
#include <Constants.au3>
#include <WinAPISysWin.au3>
#include <APISysConstants.au3>

Run("Notepad")
Local $hWnd = WinWaitActive("[CLASS:Notepad]")
ControlSend($hWnd, "", "Edit1", "Test")
ControlSend($hWnd, "", "", "!{F4}")   ; simulate a msg box

While Sleep(10)
  $hWnd = WinGetHandle("[CLASS:#32770]")  ; or title "Bloc-notes" for french Notepad
  If $hWnd Then ExitLoop
WEnd

; hide window and modify
Local $aPos = WinGetPos($hWnd)
WinMove($hWnd, "", @DesktopWidth, @DesktopHeight)
ControlHide($hWnd, "", "Button1")
ControlHide($hWnd, "", "Button2")
ControlHide($hWnd, "", "Button3")

; create toast
Local $hGUI = GUICreate("", $aPos[2], $aPos[3], @DesktopWidth - $aPos[2] - 10, @DesktopHeight - $aPos[3] - 50, $WS_POPUP)
Local $idPic = GUICtrlCreatePic("", 0, 0, $aPos[2], $aPos[3])
Local $hPic = GUICtrlGetHandle($idPic)

; Create bitmap
Local $hDC = _WinAPI_GetDC($hPic)
Local $hDestDC = _WinAPI_CreateCompatibleDC($hDC)
Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $aPos[2], $aPos[3])
Local $hDestSv = _WinAPI_SelectObject($hDestDC, $hBitmap)
Local $hSrcDC = _WinAPI_CreateCompatibleDC($hDC)
Local $hBmp = _WinAPI_CreateCompatibleBitmap($hDC, $aPos[2], $aPos[3])
Local $hSrcSv = _WinAPI_SelectObject($hSrcDC, $hBmp)
_WinAPI_PrintWindow($hWnd, $hSrcDC)
_WinAPI_BitBlt($hDestDC, 0, 0, $aPos[2], $aPos[3], $hSrcDC, 0, 0, $MERGECOPY)
_WinAPI_ReleaseDC($hPic, $hDC)
_WinAPI_SelectObject($hDestDC, $hDestSv)
_WinAPI_SelectObject($hSrcDC, $hSrcSv)
_WinAPI_DeleteDC($hDestDC)
_WinAPI_DeleteDC($hSrcDC)
_WinAPI_DeleteObject($hBmp)

WinKill($hWnd)  ; close source window

; show toast
_SendMessage($hPic, $STM_SETIMAGE, 0, $hBitmap) ; set GUI picture
_WinAPI_AnimateWindow($hGUI,  $AW_VER_NEGATIVE, 1000)
SoundPlay("C:\Windows\Media\Windows Notify Messaging.wav")
Sleep(2000)
_WinAPI_DeleteObject($hBitmap)
GUIDelete()

 

Edited by Nine
Added window animation
Link to comment
Share on other sites

3 minutes ago, Nine said:

There is no reason to reuse the GUI (toast).  Once the original window is hidden, user won't see a thing

Well, there is, if you are planning on leaving script running and show a toast every time message box appears, at least for performance reason, it's much faster update existing GUI than destroy and recreate new one each time...is it not?

Link to comment
Share on other sites

3 minutes ago, VAN0 said:

is it not?

FWIW, Not For Me... The time (and coding effort) you spend modifying the GUI each time is not worth it.  Do your own tests...Simplicity == Elegancy.

Link to comment
Share on other sites

Posted (edited)
54 minutes ago, Nine said:

FWIW, Not For Me... The time (and coding effort) you spend modifying the GUI each time is not worth it.  Do your own tests...Simplicity == Elegancy.

Sorry, I disagree with this, in fact I believe this is the reason why all new software requires more and more powerful machines without adding any more functionalities, because people care about simplicity vs optimizations...

My current code that updates existing GUI and shows/hides it takes about 40ms to move the popup outside view area, create an image of it, save it to disk for text recognition with UWPOCR, recognize the text, copy bitmap into GUI image and show GUI.

Same process but with new GUI created for each image takes about 60ms, that's 50% increase and it doesn't really make it less complex either.

Strangely it takes 250ms to close the popup with WinClose...what?

Edited by VAN0
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...