Jump to content
Tuts 4 You
Sign in to follow this  
LCF-AT

How to bring a window active to front?

Recommended Posts

Teddy Rogers

Probably better to answer my questions in this post and then come up with a better solution. Stealing focus, annoying users or simply making your program to do things it should not really be doing to circumvent the rules of Windows is not where you should be wasting your time.

If your program needs to be front my suggestion would be to have an option so the user can choose when the window goes from front to back, user does it manually after activating it or you time out and send it back for them...

Ted.

Share this post


Link to post
Teddy Rogers

This seems to solve your problem. Give it a try, hopefully all good for you...

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 lpPoint.POINT, tagINPUT.INPUT
  Static cOnr, cWnd, Timer

  #WM_CLIPBOARDUPDATE = $031D

  Select uMsg
    Case #WM_CLIPBOARDUPDATE
      If IsClipboardFormatAvailable_(#CF_TEXT)
        
        ; Find the last clipboard owner then bring our window to the foreground.
        
        cOnr = GetClipboardOwner_()
        cWnd = GetParent_(cOnr)
        
        SetWindowPos_(cWnd, hWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
        
        ; Save the current mouse pointer coordinates.
        
        GetCursorPos_(@lpPoint.POINT)
        
        ; Find our window position then activate our window.

        GetWindowRect_(hWnd, @lpRect.RECT)
        SetCursorPos_(lpRect\left + 10, lpRect\top + 10)

        ; Simulate mouse down.
        
        tagINPUT\type        = #INPUT_MOUSE
        tagINPUT\mi\dwFlags  = #MOUSEEVENTF_LEFTDOWN
        SendInput_(1, @tagINPUT, SizeOf(INPUT))
        
        ; Simulate mouse up.
        
        tagINPUT\mi\dwFlags  = #MOUSEEVENTF_LEFTUP
        SendInput_(1, @tagINPUT, SizeOf(INPUT))
        
        ; Return mouse pointer to original position.
        
        SetCursorPos_(lpPoint\x, lpPoint\y)
        
      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.

WindowToFocus.exe

WindowToFocus x32.exe

Edited by Teddy Rogers
Attached x32 version as I always forget LCF uses x32... (see edit history)
  • Like 2

Share this post


Link to post
Teddy Rogers

Another variation by detecting user input then sending the window back from the foreground...

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

Prototype.i AddClipboardFormatListener_(hWnd)
Global AddClipboardFormatListener_.AddClipboardFormatListener_

AddClipboardFormatListener_ = GetFunction(User32, "AddClipboardFormatListener")

Procedure LastInput(cWnd)
  Protected plii.LASTINPUTINFO
  Protected lastTime

  plii\cbSize = SizeOf(LASTINPUTINFO)
  
  If GetLastInputInfo_(@plii)
    
    lastTime = plii\dwTime
    
    Repeat
      GetLastInputInfo_(@plii)
      Delay(10)
    Until plii\dwTime > lastTime
    
    SetWindowPos_(WindowID(0), cWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
    
  EndIf

EndProcedure

Procedure WindowToFocus(hWnd, uMsg, wParam, lParam)
  Static cOnr, cWnd

  #WM_CLIPBOARDUPDATE = $031D

  Select uMsg
    Case #WM_CLIPBOARDUPDATE
      If IsClipboardFormatAvailable_(#CF_TEXT)
        
        ; Find the last clipboard owner then bring our window to the foreground.
        
        cOnr = GetClipboardOwner_()
        cWnd = GetParent_(cOnr)
        
        SetWindowPos_(cWnd, hWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
        
        ; Save the current mouse pointer coordinates.
        
        CreateThread(@LastInput(), cWnd)
        
      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.

LastInput.exe

  • Like 2

Share this post


Link to post
Teddy Rogers

Waiting on mouse movement this time...

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

Prototype.i AddClipboardFormatListener_(hWnd)
Global AddClipboardFormatListener_.AddClipboardFormatListener_

AddClipboardFormatListener_ = GetFunction(User32, "AddClipboardFormatListener")

Procedure LastInput(cWnd)
  Protected lpPoint.POINT
  Protected oldx, oldy
  
  GetCursorPos_(@lpPoint.POINT)
  
  oldx = lpPoint\x
  oldy = lpPoint\y
  
  Repeat
    GetCursorPos_(@lpPoint.POINT)
    Delay(10)
  Until oldx <> lpPoint\x Or oldy <> lpPoint\y
  
  SetWindowPos_(WindowID(0), cWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
  
EndProcedure

Procedure WindowToFocus(hWnd, uMsg, wParam, lParam)
  Static cOnr, cWnd

  #WM_CLIPBOARDUPDATE = $031D

  Select uMsg
    Case #WM_CLIPBOARDUPDATE
      If IsClipboardFormatAvailable_(#CF_TEXT)
        
        ; Find the last clipboard owner then bring our window to the foreground.
        
        cOnr = GetClipboardOwner_()
        cWnd = GetParent_(cOnr)
        
        SetWindowPos_(cWnd, hWnd, #Null, #Null, #Null, #Null, #SWP_NOSIZE | #SWP_NOMOVE | #SWP_ASYNCWINDOWPOS)
        
        ; Save the current mouse pointer coordinates.
        
        CreateThread(@LastInput(), cWnd)
        
      EndIf
      
  EndSelect

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Ted.

  • Like 1

Share this post


Link to post
LCF-AT

Hi again,

ok I tried your example files Ted.The WindowToFocus x32 file is not working for all apps like Olly if I copy something from there or pressing strg+c.In this case Olly keeps in front.For other apps like notepad it does work but your file always opens the menu of the icon.Your LastInput file isnt what I want.

@NOP

I have UAC disabled.Moving files via drag / drop in Olly is always working but no more after testing your files.Also drag / drop in Firefox wasnt working anymore = nothing happens.I had to restart my PC yesterday and then drag / drop was working again (without testing your app examples again).

I just dont understand why its so tricky to bring a window in front like you can do with mouse.

greetz

Share this post


Link to post
LCF-AT

Hi again,

I changed the code a little...

                    invoke GetClipboardOwner
                    mov cOnr,eax
                    invoke GetParent,cOnr
                    mov cWnd,eax
                    invoke SetWindowPos,cWnd,hWin,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE or SWP_ASYNCWINDOWPOS
                    invoke GetCursorPos,addr lp
                    invoke GetWindowRect,hWin,addr rc
                    mov eax, rc.left
                    add eax, 30
                    mov ecx, rc.top
                    add ecx, 10
                    invoke SetCursorPos,eax,ecx
                    
                    invoke SetWindowPos,hWin,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE or SWP_ASYNCWINDOWPOS
                    invoke SetWindowPos,hWin,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE or SWP_ASYNCWINDOWPOS
                    
                    
                    mov INP.INPUT._type,INPUT_MOUSE
                    mov INP.INPUT.mi.dwFlags, MOUSEEVENTF_LEFTDOWN
                    invoke SendInput,1,addr INP,sizeof INP
                    
                    mov INP.INPUT.mi.dwFlags, MOUSEEVENTF_LEFTUP
                    invoke SendInput,1,addr INP,sizeof INP
                    
                    invoke SetCursorPos,lp.x,lp.y

...adding SetWindowPos x2.Now it works better.Also moved mouse more to left to prevent to open  that menu.But also in this case its not working all over.When I do copy something from browser or other sources then WM_CLIPBOARDUPDATE seems to fail.Before I used WM_DRAWCLIPBOARD with SetClipboardViewer functon etc and there it was working.Strange is that its now no more working.Maybe using AddClipboardFormatListener function and RemoveClipboardFormatListener isnt a good choice or doing change something on my system = WM_DRAWCLIPBOARD fails.Now I need to reboot PC to check this out.Hhmm!!!So thats pretty bad,dont wanna each time do a reboot just to get my old stuff working again.Otherwise I will just using SetWindowPos x2 alone without getting the avtive window status if the other code examples doing some strange problems later.

greetz

EDIT: My fault about WM_DRAWCLIPBOARD so its still working.Just forgot that I added a check yesterday.So I think now its seems to work better using example from Ted WindowToFocus x32 just with adding SetWindowPos x2 and moving mousepointer some more to right side where it does click on.I think with this method I can live now so far. :) I can use it with WM_DRAWCLIPBOARD (SetClipboardViewer etc) or also with WM_CLIPBOARDUPDATE with AddClipboardFormatListener function.This seems to be easier just need to call this function once + RemoveClipboardFormatListener at the end.

Thank again guys.

Edited by LCF-AT (see edit history)
  • Like 1

Share this post


Link to post
Teddy Rogers
12 hours ago, LCF-AT said:

So I think now its seems to work better using example from Ted WindowToFocus x32

I am glad you have a workaround for this in the end.

You may find suspending operation for around ~10 milliseconds after setting the cursor position and before simulating the mouse down input, using the Sleep function, adds a little bit more reliability and may not require you to add a second call to SetWindowPos.

If you are concerned about accidentally activating a menu when simulating the mouse down you can calculate the centre of the windows titlebar or populate NONCLIENTMETRICS structure. Just be mindful there may be occasions where this may still occur particularly with owner drawn windows and Windows 10 apps.

I still recommend the timer option... 😎

Ted.

  • Like 2

Share this post


Link to post
LCF-AT

Hi,

thanks Ted.I'am glad too now so far to got a working method now for that tiny thing.I also found some more tiny issues using your method (getting problems when using this method in more than one application = mouse cursor problems) but so long I am just using it for one app it should be ok.

About the calc where to press the mouse on window.I tried calcing the half of width to press the mouse there but should get problems when I can move the app window to smallest window = press on minimize button etc.I think when I just do add 1 for left rect and 1 for top rect = better and  clicking on first window pixel+1 without to hit the icon etc.I think I can use this so without to calc.

I made a new file for testing.Should work so far to copy text from somewhere into edit and active window also if minimized etc.

Font_Clipboard_Test.rar

greetz

Share this post


Link to post

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