Jump to content
Sign in to follow this  
grzesiek

Window always in background

Recommended Posts

grzesiek

Hello! I searched forum but couldn't find any solution. I would like to create GUI which will always stay behind other opened windows. Something opposite to $WS_EX_TOPMOST. Window should always stay in background even when user will click on it and move it. I know that this is possible because I saw some app which window was always in background. So I would like to know if someone know how to this is in AutoiIT. Thanks for any suggestion and I will be very glad to see some examples.

Share this post


Link to post
Share on other sites
martin

Hello! I searched forum but couldn't find any solution. I would like to create GUI which will always stay behind other opened windows. Something opposite to $WS_EX_TOPMOST. Window should always stay in background even when user will click on it and move it. I know that this is possible because I saw some app which window was always in background. So I would like to know if someone know how to this is in AutoiIT. Thanks for any suggestion and I will be very glad to see some examples.

You will need something like this. I haven't quite got it right but it's getting close.

Getting too late now and I won't have time for a couple of days so maybe someone can improve it.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Const $HWND_BOTTOM = 1
Const $SWP_NOOWNERZORDER = 0x200
Const $SWP_NOACTIVATE = 16
Const $WM_EXITSIZEMOVE = 0x232
Const $SWP_NOSIZE = 1
GUIRegisterMsg($WM_ACTIVATE, "On_WM_ACTIVATE")
GUIRegisterMsg($WM_EXITSIZEMOVE, "on_WM_EXITSIZEMOVE")

$hGui = GUICreate("My GUI")
GUISetState(@SW_SHOW)

; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
GUIDelete()


Func on_WM_EXITSIZEMOVE($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
        $wp = WinGetPos($hGui)
        DllCall("user32.dll", "long", "SetWindowPos", "hwnd", $hWnd, "hwnd", $HWND_BOTTOM, "int", $wp[0], "int", $wp[1], _
                "int", 0, "int", 0, "long", BitOR($SWP_NOSIZE, $SWP_NOACTIVATE));BitOR($SWP_NOOWNERZORDER,$SWP_NOACTIVATE))
    EndIf
    
EndFunc  ;==>on_WM_EXITSIZEMOVE

Func On_WM_ACTIVATE($hWnd, $msg, $wParam, $lParam)
    Local $iState = BitAND($wParam, 0x0000FFFF), $iMinimize = BitShift($wParam, 16)
    If $iState And $hWnd = $hGui Then
        $wp = WinGetPos($hGui)
        DllCall("user32.dll", "long", "SetWindowPos", "hwnd", $hWnd, "hwnd", $HWND_BOTTOM, "int", $wp[0], "int", $wp[1], _
                "int", $wp[2], "int", $wp[3], "long", $SWP_NOACTIVATE);BitOR($SWP_NOOWNERZORDER,$SWP_NOACTIVATE))
    EndIf
EndFunc  ;==>On_WM_ACTIVATE

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Malkey

Hello! I searched forum but couldn't find any solution. I would like to create GUI which will always stay behind other opened windows. Something opposite to $WS_EX_TOPMOST. Window should always stay in background even when user will click on it and move it. I know that this is possible because I saw some app which window was always in background. So I would like to know if someone know how to this is in AutoiIT. Thanks for any suggestion and I will be very glad to see some examples.

Have you looked at _WinAPI_SetWindowPos() function.

It is in Help file:

Examples are on the forum

http://www.autoitscript.com/forum/index.php?act=Search

or Google Search enter :-

"_WinAPI_SetWindowPos" site:autoitscript.com

in the Google search box.

And the actual function is in the include directory in the WinAPI.au3 file.

Good luck.

Edited by Malkey

Share this post


Link to post
Share on other sites
martin

Have you looked at _WinAPI_SetWindowPos() function.

It is in Help file:

Examples are on the forum

http://www.autoitscript.com/forum/index.php?act=Search

or Google Search enter :-

"Processor Speed" site:autoitscript.com

in the Google search box.

And the actual function is in the include directory in the WinAPI.au3 file.

Good luck.

_WinAPI_SetWindowPos() is just a wrapper for the dllcalls and doesn't do any more than my example does, but can you suggest what to do to stop the window flickering to the top for a split second after it has been moved? I've tried using $WM_MOVE but no better.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
grzesiek

Thanks for your help. I tried Martin example and this is exactly what I wanted but as you mentioned the window appears in front other window. So this doesn't look professional right now. I doubt I will be able to fix that but I will try :)

Share this post


Link to post
Share on other sites
someone

I've been using this problem as a way to try learning more about dlls, and windows messages, stuff like that. I found a page on msdn where someone specifically points to the problem you are having with the flickering. I'm trying to figure it out on my own, but so far not getting it.

Here is the link

(Post by durstin, says Answer in the title)

Seems like the answer may lie in capturing the activate (so says the link), and disregarding it using NOACTIVATEANDEAT(??) although see other windows messages in the help file, I see nothing for NOACTIVATEANDEAT. I don't know I'm not entirely understanding all this so maybe I'm totally off. If someone is able to figure this out I'd love to see how (or even just how to implement the code in the link)

Have a good weekened everyone

Andrew

EDIT: When I just tried the link it wasn't working for me but fixed and verified its working ok now.

Edited by someone

While ProcessExists('Andrews bad day.exe')
	BlockInput(1)
	SoundPlay('Music.wav')
	SoundSetWaveVolume('Louder')
WEnd

Share this post


Link to post
Share on other sites
covaks

Maybe this could lead to something.. It stops the window from flickering for a sec when you click on it (but it still flickers when activated from the taskbar). The problem is, now you can't move the window, and probably can't click on any controls on it either. Which might not be a problem if you just want to create a display only gui that never moves. I think you could still process clicks for controls however if you get the mouse position when clicked, find out what control is under it (There are functions to get the control under the mouse on the forums), then use ControlClick to actually click it. How you would work out moving the window or resizing though is a different matter, but could probably be done with some work..

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include "MouseSetOnEvent_UDF.au3"

Const $HWND_BOTTOM = 1
Const $SWP_NOOWNERZORDER = 0x200
Const $SWP_NOACTIVATE = 16
Const $WM_EXITSIZEMOVE = 0x232
Const $SWP_NOSIZE = 1
GUIRegisterMsg($WM_ACTIVATE, "On_WM_ACTIVATE")
GUIRegisterMsg($WM_EXITSIZEMOVE, "on_WM_EXITSIZEMOVE")

$hGui = GUICreate("My GUI")
_MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT, "MousePrimaryDown_Event", "", "", $hGui)
    
GUISetState(@SW_SHOW)

; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
GUIDelete()


Func on_WM_EXITSIZEMOVE($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
        $wp = WinGetPos($hGui)
        DllCall("user32.dll", "long", "SetWindowPos", "hwnd", $hWnd, "hwnd", $HWND_BOTTOM, "int", $wp[0], "int", $wp[1], _
                "int", 0, "int", 0, "long", BitOR($SWP_NOSIZE, $SWP_NOACTIVATE));BitOR($SWP_NOOWNERZORDER,$SWP_NOACTIVATE))
    EndIf
    
EndFunc  ;==>on_WM_EXITSIZEMOVE

Func On_WM_ACTIVATE($hWnd, $msg, $wParam, $lParam)
    Local $iState = BitAND($wParam, 0x0000FFFF), $iMinimize = BitShift($wParam, 16)
    If $iState And $hWnd = $hGui Then
        $wp = WinGetPos($hGui)
        DllCall("user32.dll", "long", "SetWindowPos", "hwnd", $hWnd, "hwnd", $HWND_BOTTOM, "int", $wp[0], "int", $wp[1], _
                "int", $wp[2], "int", $wp[3], "long", $SWP_NOACTIVATE);BitOR($SWP_NOOWNERZORDER,$SWP_NOACTIVATE))
    EndIf
EndFunc  ;==>On_WM_ACTIVATE

Func MousePrimaryDown_Event()
    ; $Control = Get Control under mouse function()
    ; $pos = MouseGetPos()
    ; ControlClick($hGui,"",$Control, $pos[0], $pos[1])
    ; Or something like this.. 
EndFunc

One thing though, I had to modify the UDF. Change this line in the IsHoveredWnd() function:

If Not WinActive($hWnd) Or ($aRet[0] <> $hWnd And Not $iRet) Then $iRet = False

To this:

If $aRet[0] <> $hWnd Then $iRet = False

Share this post


Link to post
Share on other sites
grzesiek

I just wanted to add that I found easier and better way to do this.

Here is an example:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$gui = GUICreate("", -1, -1, -1, -1, $WS_CAPTION+$WS_MAXIMIZEBOX+$WS_SYSMENU)
DllCall("user32.dll", "hwnd", "SetParent", "hwnd", $gui, "hwnd", WinGetHandle("Program Manager"))
GUISetState()

While 1
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
WEnd

To prevent gui from appearing infront other windows the gui is set as child window of desktop. One minus is that this will remove gui button from taskbar so the gui can't be minimized. But I think for now it is the best method to do this.

Share this post


Link to post
Share on other sites
someone

Thanks grzesiek for updating us... glad to see you found an acceptable solution, I kept trying to figure out a better way but didn't really get anywhere.

I thought I'd mention a good workaround for the minimize issue if your interested is to create a button(or something else) to minimize it to the tray. The minize to tray code isn't mine it comes from Zedna in this post

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#NoTrayIcon

Opt("TrayOnEventMode",1)
Opt("TrayMenuMode",1)   

TraySetOnEvent($TRAY_EVENT_PRIMARYUP,"SpecialEvent")
$gui = GUICreate("", 350, 350, -1, -1, $WS_CAPTION+$WS_MAXIMIZEBOX+$WS_SYSMENU)
$button = GUICtrlCreateButton("Minimize", 150, 100)
DllCall("user32.dll", "hwnd", "SetParent", "hwnd", $gui, "hwnd", WinGetHandle("Program Manager"))
GUISetState()

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    If $msg = $button Then
        GuiSetState(@SW_HIDE)
        TraySetState(1) ; show
        TraySetToolTip ("My app - click here to restore")
    EndIf
WEnd

Func SpecialEvent()
    TrayShow(0) ; hide
EndFunc

Func TrayShow($show) ; 0/1 hide/show
    If $show Then
        GuiSetState(@SW_HIDE)
        TraySetState(1) ; show
        TraySetToolTip ("My app - click here to restore")
    Else
        GuiSetState(@SW_Show)
        TraySetState(2) ; hide
    EndIf
EndFunc

Out of curiosity, did you check out the link I gave a few posts up? I'm still very interested in trying to understand what the guy is talking about.


While ProcessExists('Andrews bad day.exe')
	BlockInput(1)
	SoundPlay('Music.wav')
	SoundSetWaveVolume('Louder')
WEnd

Share this post


Link to post
Share on other sites
RomanK

hi everyone, I justed wanted to update and tell you,

that the short way with the ProgMan Handle doesn't work on Windows 7.

The GUI just won't appear when trying to do so on Win7. Au3Info tells that the desktop's class name is WorkerW, but this also doesn't work.

But at least martin's code from 2nd post works well, thanks! :)


[font="Courier New"]http://RomanK.hondadesigns.com[/font]

Share this post


Link to post
Share on other sites
wraithdu

The short method works fine for me on Win7 RC1, and the Desktop classname is still SysListView32... :)

Edited by wraithdu

Share this post


Link to post
Share on other sites
RomanK

oh that's strange, for me not... maybe it's because I use the 64 bit version?


[font="Courier New"]http://RomanK.hondadesigns.com[/font]

Share this post


Link to post
Share on other sites
wraithdu

^^^ yep, I'd bet my lunch. x64 :)

Edited by wraithdu

Share this post


Link to post
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
Sign in to follow this  

×