Jump to content
Tuts 4 You

How to bring a window active to front?


LCF-AT

Recommended Posts

Hi guys,

I have a small question.I would like to bring my app into front by itself when something was found in browser I am looking at.I tried using SetForegroundWindow but dosent work also AllowSetForegroundWindow either.Only way I am able to do is just using SetWindowPos function with HWND_TOPMOST paramter & again with HWND_NOTOPMOST paramter.So I wanna just bring my app window in front only without to have / keep HWND_TOPMOST flag.

invoke SetWindowPos,hWin,HWND_TOPMOST,0,0,0,0,   SWP_ASYNCWINDOWPOS or SWP_NOMOVE or SWP_NOSIZE
invoke SetWindowPos,hWin,HWND_NOTOPMOST,0,0,0,0, SWP_ASYNCWINDOWPOS or SWP_NOMOVE or SWP_NOSIZE

Using that 2 functions is working so far but there is one issue.When my app window was bring to the front and I move the mouse in a other xy app window like notepad then my own app is still in front so long till I press the mouse button on any app window top title bar.How can I prevent this?Somehow I need to set my app window into activate mode but also SetActiveWindow function dosent work.Has anyone a idea?

greetz

Link to comment

In terms of API that can be used / are used to do this:

  • BringWindowToTop
  • SetActiveWindow
  • SetForegroundWindow
  • SetFocus
  • SetWindowPos
  • ShowWindow
  • SwitchToThisWindow

In some cases, you may need to make use of 'AttachThreadInput' as well.

  • Like 1
Link to comment

Hi again,

SetFocus dosent work etc.My app window keeps inactive (it pop ups in front) and I need to press somewhere in my app to make it active.The other functions I tried already too without success to make my window active (like I would do with mouse).

greetz

Link to comment

SetWindowPos(windowHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);

think you can convert that to asm yourself :)

 

  • Like 1
Link to comment

Hi,

it dosent work too elvncrn8. :( My app window pop ups in front = Ok but dosent gets the focus or active status like it gets when I do press anywhere with mouse in my app you know what I mean?

Maybe you guys dont understand what I mean so I try to explain it again.My goal is it to bring my app in front (same like I would do it manually with mouse just selecting any open app etc).So to bring my app in front does work so far but the problem is this (now listen)....

Example: I have open a notepad file and my app.My app is behind the notepad app = notepad does visually overlap my app.Clear so far right.Now in  my notepad app I do just copy some text via mouse or strg+c and the text get copied to clipboard.My app does notice the clipboard change and now it should come into front what also works using SetWindowPos with HWND_TOPMOST & right after with HWND_NOTOPMOST (dont want to keep topmost).Ok so far right?My app is now in front but isnt active = the notepad app has still active window status.When I now press with mouse in the notepad field to select anything etc then my app is still in front instead the notepad app which SHOULD get back in front if I select anything in notepad but this isnt working.I can only press once on notepad title bar to get notepad back in front or otherwise it keeps in back and when I move the notepad window then it will moved behind my app.No idea how to explain this better.Normaly I just want to simulate the normal mouse handling way.

So I just want to bring my app in front (like to press with mouse on my app window anywhere) but when I do press anywhere in a other open app THEN this other app should come in front (not only pressing on title bar to get it work).

Maybe this....just open 2 apps like 2 notepad files and now put them visible window by window next to next.Now just overlap on app window a little over the other app window.If you now press with mouse on the left notepad text field etc then this app comes in front.If you press on notepad on right side then this comes in front.Thats it.This I wanna have with my app.So when I do use SetWindowPos function in my app then it dosent get this active window status like it would get when I would press with mouse on it.How to make this work?I tried already all functions above.Is there any extra things I need to execute or whatever?

PS: Just look at the X button on any app like notepad where you can exit the app (Windows 7).When the window is active then this X button has the red color and when its not active then its transparent......in my case after calling SetWindowPos function then my app comes in front but the X button is still transparent just when I do select with mouse anywhere in my app then the X button gets red color = active window.You know?How to use function XY SetWindowPos or others to bring my app in front with active (red colored X button) instead tranparent X button = not active?

active.png.91cfb8a6146c6ff00369f33c8eef69ba.png

greetz

Link to comment

Hi,

dosent wok too.I made a small test app you guys can try out.

1.) run my exe and run any notepad file with any text into

2.) select text in notepad and press copy and now my app should pop up in front (without red marked / active X button right above)

3.) Now press in notepad field and you see it dosent get the active status back what it should to get back.Now you can also move the notepad window but my app is still in front but notepad should be back in front.

So anyhow I always have first to press A) by own app somewhere to get active status or B,) I have to click on the notepad title bar on time to get this back in front.Somehow I need to set my app window in active state (red color X button) right after it was set in front but how is the question.Just check out my exe file or source so maybe you see something wrong or you know what to add to manage this.

Front.rar

greetz

Link to comment

@LCF-AT: I believe this example and explanation should work: https://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo

My ugly test code (PLEASE don't use it in real life project!):

            ;invoke SetWindowPos,hWin,HWND_TOPMOST,0,0,0,0, SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE or SWP_NOMOVE
            ;invoke SetWindowPos,hWin,HWND_NOTOPMOST,0,0,0,0, SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE or SWP_NOMOVE
            pushad
            invoke GetForegroundWindow
            mov esi, eax
            invoke GetCurrentThreadId
            mov ebx, eax
            invoke GetWindowThreadProcessId, esi, 0
            mov edi, eax
            invoke AttachThreadInput, ebx, edi, 1
            invoke AllowSetForegroundWindow, -1
            invoke SetForegroundWindow,hWin
            invoke AttachThreadInput, ebx, edi, 0
            popad

Please note that I did only very limited testing with only notepad, your sample app and 3 copy to clipboard attempts. There might be issues, especially in your "very specific" configurations with Sandboxie and what not..

Does that solve your problem?
kao.

  • Thanks 1
Link to comment

Hey kao,

it works! :) I just testet your code in the example source I have attached before and its working.Great kao.I thought already it wouldnt be possible to do this anyhow or something but now you came up with a working solution hehe. :) 

Yes,I will try to write this code similar in my app where I wanna have it and make some test running it into Sandboxie etc.I will send some feedback later whether all is working fine or whether I get any new problem.

greetz

EDIT: I see your code / example you found is working so far but not for all.If I have Olly open and do copy something then its just working by random anyhow.Sometimes it works and sometimes not and my app icon in taskbar below does just flash.Not sure about that.In Notepad or browser it seems to work for 100 % til now.I did rewrote your code example to this now....

            invoke GetForegroundWindow
            mov esi, eax
            invoke GetCurrentThreadId
            mov ebx, eax
            invoke GetWindowThreadProcessId,esi,FALSE
            mov edi, eax
            push ebx
            .if ebx != edi
                invoke AttachThreadInput,ebx,edi, TRUE
                invoke SystemParametersInfo,SPI_GETFOREGROUNDLOCKTIMEOUT,FALSE,addr lockTimeOut,0
                invoke SystemParametersInfo,SPI_SETFOREGROUNDLOCKTIMEOUT,FALSE,0,SPIF_SENDWININICHANGE or SPIF_UPDATEINIFILE
                invoke AllowSetForegroundWindow,ASFW_ANY
            .endif
            invoke SetForegroundWindow,hWin
            pop ebx
            .if ebx != edi
                invoke SystemParametersInfo,SPI_SETFOREGROUNDLOCKTIMEOUT,FALSE,addr lockTimeOut,SPIF_SENDWININICHANGE or SPIF_UPDATEINIFILE
                invoke AttachThreadInput,ebx,edi, FALSE
            .endif

...should be right if I have read this C source code correctly.

Edited by LCF-AT
Link to comment

I am a simple man and not sure what you are trying to achieve. I think you may be over complicating things. Is this in the correct order of what you are trying to do?

  1. Wait for WM_DRAWCLIPBOARD message,
  2. On CF_TEXT bring window to front,
  3. When user clicks on window set window to the back.

If it is, an alternate option;

  1. Wait for WM_DRAWCLIPBOARD message,
  2. On CF_TEXT call GetClipboardOwner to obtain hWnd of current clipboard owner,
  3. In your windows event handler wait for WM_KILLFOCUS,
  4. Call SetWindowPos with hWndInsertAfter to position your window after the last clipboard owner.

You'll obviously have to add some code to manage when you want to act on WM_KILLFOCUS events or you will have your window bouncing around behind every clipboard owner.

There are a few other ways you could do this. If you step out nice and simple what you are trying to do so I understand I'll be able to help better...

Ted.

  • Like 1
Link to comment

Hi again,

yes Ted its always the same with me hmm. :) As I said I just wanna bring my app window in front when in clipboard was copied some text.Only problem is that inactive status my app window has when I am just using SetWindowPos functions.

Could you explain your alternative method some more Ted?1 = ok,2 = ok.What shall I do at WM_KILLFOCUS?Calling SetWindowPos?

So at WM_DRAWCLIPBOARD I do check for CF_TEXT and then I do call GetClipboardOwner.When the handle is from my own app = aboard (dont need to check my own app when I did copy something from there / only outside of my app).Now when the handle is not from my app then I handle something on WM_KILLFOCUS etc?Thats could be also a problem each time checking you know.

So as I told already before Ted,I just wanna bring my app in front with active status = the exit button right above in my app should be get the red color = same if I do press manually with mouse in my app.With SetWindowPos it dosent work and X button keeps transparent = not active.In this case when my app window dosent have active status but its shown in front then my app window keeps in front visible also when  I do move a other app window like notepad (I did copy something from) behind my own app = This I dont wanna have you know what I mean?The only working method which seems to work better is using the functions kao told before so in this case (when it works) my app window comes in front AND the X Exit button right above gets the red color = active window status and now when I do move the notepad app then notepad gets in front = right.

Sorry,maybe I do speak some chinese language in this case and some people just understand railway station or something.So I made a small video where you can see what I mean what the problem is just using SetWindowPos x2 / HWND_TOPMOST and HWND_NOTOPMOST at WM_DRAWCLIPBOARD.My app keeps in front also when I do select after something in notepad (what should not be).Just watch the video so I think it makes it clear to understand the issue I dont wanna have.

Front Problem.rar

greetz

Link to comment

You cannot take (steal) focus away from another window you do not control whilst the user is currently active inside it. You will not be notified of the other windows' events to make a judgement call when to send your window to back.

As @kao mentioned above the only way to do this would be to attach to the thread input queue of that window. You can then change its z-order position whilst focused.

There are a few caveats. If the process is elevated you will not be able to attach to the input queue. If there is a problem with the process you are attached to you run the risk of inheriting those problems.

Some more questions;

  1. Why do you need to bring your window to the front?
  2. What is the purpose of your window whilst it is in front, what will it do when it is front?
  3. If you need to bring the window to the front how long do you need it to be there?
  4. Why do you need to send it to the back?

If you only need your window to be front for a short period set a timer event to send it back when its work is done.

There are some other methods whilst another window has focus though they are hit-and-miss. Waiting for WM_NCACTIVATE is one, though this event may never occur and shouldn't be relied upon.

Global User32 = OpenLibrary(#PB_Any, "user32.dll")

Prototype.i AddClipboardFormatListener_(hWnd)
Global AddClipboardFormatListener_.AddClipboardFormatListener_

AddClipboardFormatListener_ = GetFunction(User32, "AddClipboardFormatListener")

Procedure WindowToFocus(hWnd, uMsg, wParam, lParam)
  Static cOnr, cWnd, Timer
  
  #WM_CLIPBOARDUPDATE = $031D

  Select uMsg
    Case #WM_CLIPBOARDUPDATE
      If IsClipboardFormatAvailable_(#CF_TEXT)
        
        cOnr = GetClipboardOwner_()
        cWnd = GetParent_(cOnr)
        
        SetWindowPos_(cWnd, hWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
        
        SetTimer_(hWnd, Timer, 500, #Null)
      EndIf
      
    Case #WM_TIMER
      Select wParam
        Case Timer
          SetWindowPos_(hWnd, cWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
      EndSelect
      
  EndSelect

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


If OpenWindow(0, 0, 0, 300, 200, "WindowToFocus", #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)

  AddClipboardFormatListener_(WindowID(0))
  
  SetWindowCallback(@WindowToFocus())
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Ted.

  • Like 1
Link to comment

I use a free app which I think does what your asking, it is a downloader which monitors the clipboard for new links to sites it supports such as youtube, clicknupload etc. and when a new link is copied to clipboard it pops up a window asking if you want to download it

if that's what you want your app to do then maybe you could see how they do it there

http://wordrider.net/freerapid/

 

  • Like 1
Link to comment

Hi again,

I think did understand me wrong Ted.The notepad app in this case was just a example so it could be any xy app.My goal is just to set the active state in my app when it pop up in front = red color X button.So as you can see in my video,when my app comes in front then I do select some text in notepad file BUT you see when I do select it then the notepad app dosent come in front and thats the problem issue.Normaly when you do this with the mouse itself then the app XY is set in front anyway where I do click in the app and this is what I also wanna have.I dont want to keep my own app in front when I do press anywhere outside of my app as you can see in my video when I do move the notepad window which keeps behind my app.

Example: When you have open some apps on Windows then you can press the alt+arrow left/right key (dont  remember the key name now) and you get small windows of all apps too see and you can select any of those running apps and right after this the choosen app comes in front and gets active when you leave the alt key but before it just comes in front without red color X button.

About my app and why I wanna bring my app in front.When I browse on internet I want to copy some text etc into clipboard and right after this my app does check the content of clipboard and if something was found like any link or whatever then my app comes in front with selected area in my app.Now I can decide what to do.....A) I do something now in my app or B.) I do nothing in my app BUT in the case of B I cant browse normaly go on because my app is still in front and need first to press somewere in my app and then I can press again somewhere in browser to get the browser in front.You know?Its like I would do this manually with the mouse itself.With mouse I briing any window in front with active state and this I wanna simulate to bring my app in front.

Something like this....calling SetWindowPos & some API SimulateLeftMouseClick with my app handle.

greetz

Link to comment

Hi,

I tried a little around and checked to send some messages and found this out...

invoke SendMessage,hWin,WM_ACTIVATE,MAKEWPARAM(WA_CLICKACTIVE,0),hWin

...so when I do send this message above then it does the right thing.It brings my app window in front and its also active (red color on X button).The only problem is that its just working once.When I try to copy again something from text etc then it dosent work anymore.Not sure yet how to make it work always.

greetz

Link to comment

SetWindowPos can change the z order but it doesn't activate the window

You can use SetActiveWindow after you have brought to front, if its not in front it will not set as active

Have you tried SetForegroundWindow ?

Quote


Brings the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user. The system assigns a slightly higher priority to the thread that created the foreground window than it does to other threads.

 

 

  • Like 1
Link to comment

You are undoubtedly coming across one of Windows SetForegroundWindow limitations...
 

Quote

 

The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:


• The process is the foreground process.
• The process was started by the foreground process.
• The process received the last input event.
• There is no foreground process.
• The foreground process is being debugged.
• The foreground is not locked (see LockSetForegroundWindow).
• The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
• No menus are active.

An application cannot force a window to the foreground while the user is working with another window. Instead, Foreground and Background Windows will activate the window (see SetActiveWindow) and call the function to notify the user.

A process that can set the foreground window can enable another process to set the foreground window by calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the ability to set the foreground window the next time the user generates input, unless the input is directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that process is specified.

The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow function.


The system automatically enables calls to SetForegroundWindow if the user presses the ALT key or takes some action that causes the system itself to change the foreground window (for example, clicking a background window).

 

 

The last sentence is interesting, it seems if you simulate an alt press then SetForefroundWindow will work...
 

private const int ALT = 0xA4;

private const int EXTENDEDKEY = 0x1;

private const int KEYUP = 0x2;



keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);

keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);

SetForegroundWindow(Handle);

 

Link to comment
19 hours ago, LCF-AT said:

I think did understand me wrong Ted.The notepad app in this case was just a example so it could be any xy app.My goal is just to set the active state in my app when it pop up in front = red color X button.

I think I already answered it 😋

When a user is working/interacting in an active window you can't steal focus away from it to another application. The user passes on focused privileges by activating the window.

If you are really, really, really intent on stealing focus you can do something immensely annoying by simulating a mouse click on screen in a window. Something like this...

Global User32 = OpenLibrary(#PB_Any, "user32.dll")

Prototype.i AddClipboardFormatListener_(hWnd)
Global AddClipboardFormatListener_.AddClipboardFormatListener_

AddClipboardFormatListener_ = GetFunction(User32, "AddClipboardFormatListener")

Procedure WindowToFocus(hWnd, uMsg, wParam, lParam)
  Static cOnr, cWnd, Timer
  
  #WM_CLIPBOARDUPDATE = $031D

  Select uMsg
    Case #WM_CLIPBOARDUPDATE
      If IsClipboardFormatAvailable_(#CF_TEXT)
        
        cOnr = GetClipboardOwner_()
        cWnd = GetParent_(cOnr)
        
        SetWindowPos_(cWnd, hWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
        
        ;GetWindowRect_(cWnd, @lpRect.rect)
        GetWindowRect_(hWnd, @lpRect.rect)
        
        SetCursorPos_(lpRect\left + 10, lpRect\top + 10)
        
        tagINPUT.INPUT
        
        ; Mouse down...
        
        tagINPUT\type        = #INPUT_MOUSE
        tagINPUT\mi\dwFlags  = #MOUSEEVENTF_LEFTDOWN
        SendInput_(1, @tagINPUT, SizeOf(INPUT))
        
        ; Mouse up...
        
        tagINPUT\mi\dwFlags  = #MOUSEEVENTF_LEFTUP
        SendInput_(1, @tagINPUT, SizeOf(INPUT))
        
      EndIf
     
  EndSelect

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


If OpenWindow(0, 0, 0, 300, 200, "WindowToFocus", #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)

  AddClipboardFormatListener_(WindowID(0))
  
  SetWindowCallback(@WindowToFocus())
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Ted.

  • Like 1
Link to comment

I have made 2 small files for you to test as a workaround for your problem...

SetForegroundWindow Keypress Test.exe (Simulates ALT Press & Release)

keybd_event(VK_MENU,0, 0 , 0); //Alt Press
keybd_event(VK_MENU,0,KEYEVENTF_KEYUP,0); // Alt Release

 

SetForegroundWindow Mousebutton Test.exe (Simulates Left Mouse Button Press & Release)

mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); // Left Button Press
mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); // Left Button Up

 

SetForegroundWindowTest.rar

Both worked for me in all programs I tried including Olly

A workaround like this is the only way you can reliably steal focus due to the restrictions, simulating a mouse press or a keypress tricks it into taking away the focus from the window you are working with, ALT apparently allows SetForegroundWindow due to the ALT+TAB feature of windows which will always be on top

  • Like 1
Link to comment

Hi again,

thanks for another answers and examples.I tried now your 2 example files / codes NOP.On the first view it seems to work good but I also see some issues.When I use mousebutton functions then I get some problems with my listview and it does show my popup menu when I do press the left mouse button!?Only shown on right mouse button press.When I do use your VK_MENU functions then I dont get this popup menu problem.After some tests with your files and putting the functions in my source I got a problem with OllyDBG and the drag / drop in Olly dosent work anymore to move any app inside = nothing gets loaded now.Also still now when I dont use any of your example apps or my changed apps.Seems I need to restart my PC now.Seems that some kind of codes arent pretty good to use them and do trigger any problems on other fields like this drag / drop functions which dont work anymore all over the place.Hhmmm.

greetz

Link to comment

I might point out that perhaps what is missing is the task at hand.  If I copy a magnet:// link, my torrent app will automatically come to the front and offer to download if it is open.  In Windows 10, clicking on a link which has magnet:// now brings up a would you like such and such app to open this warning.  The only Windows-sanctioned solution is to use the correct mechanisms like registering your app to handle all of these events.

Clipboard Viewer Chain: https://docs.microsoft.com/en-us/windows/win32/dataxchg/using-the-clipboard#adding-a-window-to-the-clipboard-viewer-chain

Protocol Handlers: https://docs.microsoft.com/en-us/windows/win32/search/-search-3x-wds-ph-install-registration

There are probably tricks you can do.  I don't know how the torrent programs monitor and bring to front, but I imagine you could monitor the clipboard for a change, modify the clipboard to contain a protocol that you are registered for e.g. myapp:// and then the system will bring your app to the forefront.

I imagine this works in Win7 as well.  But its a cleaner and better route in modern windows than hijacking the foreground window which due to annoying apps that have overused that ability has become increasingly complicated, difficult and with all sorts of nuances and details to check for.

For example accessibility features, custom keyboard mappings, system style of windows that might make keyboard/mouse simulation complex, privileged windows, UAC elevation prompts, 2 apps that both are trying to capture and bring to front could end up getting in deadlock fight for it, etc.  A professional solution probably is not worth it unless its absolutely necessary with no alternatives and could require reversing Windows a bit to get some peculiar details.  I've browsed the Win2k source more than few times :).  IMO, Microsoft should open source the UI drawing parts of the basic windows controls so its easy to derive clean professional owner-draw solutions and the like which deals with every possible circumstance.  That seems long overdue and who knows at the current rate maybe they will some day.

Edited by Progman
  • Like 1
Link to comment
57 minutes ago, LCF-AT said:

I got a problem with OllyDBG and the drag / drop in Olly dosent work anymore to move any app inside = nothing gets loaded now

Did you load Olly Elevated? with "Run as administrator"

Link to comment

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
×
×
  • Create New...