Solved

Last activated application, vb.net

Posted on 2006-11-28
15
3,773 Views
Last Modified: 2012-06-22
Does anyone here know how to get the below code to work with GetActiveWindow versus getting foreground window?


Imports System.Runtime.InteropServices

Public Class Form1
    Inherits System.Windows.Forms.Form




    ' Shell Events Constants
    Public Enum ShellEvents
        HSHELL_WINDOWCREATED = 1
        HSHELL_WINDOWDESTROYED = 2
        HSHELL_ACTIVATESHELLWINDOW = 3
        HSHELL_WINDOWACTIVATED = 4
        HSHELL_GETMINRECT = 5
        HSHELL_REDRAW = 6
        HSHELL_TASKMAN = 7
        HSHELL_LANGUAGE = 8
        HSHELL_ACCESSIBILITYSTATE = 11
    End Enum

    ' API Declares
    Public Declare Function RegisterWindowMessage Lib "user32.dll" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Integer
    Public Declare Function DeregisterShellHookWindow Lib "user32" (ByVal hWnd As IntPtr) As Integer
    Public Declare Function RegisterShellHookWindow Lib "user32" (ByVal hWnd As IntPtr) As Integer
    Public Declare Function GetForegroundWindow Lib "user32" () As IntPtr
    Public Declare Function SetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hWnd As IntPtr) As Integer

    Private uMsgNotify As Integer
    Private lastWindow As IntPtr





    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.TopMost = True

        uMsgNotify = RegisterWindowMessage("SHELLHOOK")
        RegisterShellHookWindow(Me.Handle)

    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = uMsgNotify Then
            Select Case m.WParam.ToInt32
                Case ShellEvents.HSHELL_WINDOWACTIVATED
                    Debug.WriteLine("window activated")
                    Dim curWindow As IntPtr = GetForegroundWindow()
                    If (Not curWindow.Equals(IntPtr.Zero)) AndAlso (Not curWindow.Equals(Me.Handle)) Then
                        lastWindow = curWindow
                    End If
            End Select
        End If
        MyBase.WndProc(m)
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        If Not lastWindow.Equals(IntPtr.Zero) Then
            SetForegroundWindow(lastWindow)
            System.Threading.Thread.Sleep(100)
            SendKeys.Send("Hello World...")

        End If

    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        DeregisterShellHookWindow(Me.Handle)
    End Sub


End Class
************************************************************
0
Comment
Question by:TechMonster
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
15 Comments
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 18031153
You sure you want GetActiveWindow()?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/getactivewindow.asp

    "The GetActiveWindow function retrieves the window handle to the active window attached to the calling thread's message queue. "

"attached to the calling thread's message queue"...so that will only get the active window of the app that contains Form1.  It won't give you any windows from other processes.
0
 

Author Comment

by:TechMonster
ID: 18031345
Idle Mind,
 
Not really sure. I have used the getforegroundwindow and it works for the most part but has recently failed when used with a "web-based" application running on citrix.

The user uses the mouse to designate where the text from my program is going to paste.  They click on the destination application and then go back to my program and press "Go."  

I was hoping there would an alternate way to capture the last activated application since it is failing with vb.net.

Interesting enough I know a different c++ application works fine and is using hooking to remember the last application.  I just don't know the code they are using.  

Can you help?
 
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 18033014
So basically you need a way to let the user pick a "target" window?

Do you only need the "main" window or do you need to get the hWnd of a specific control in the target window?
0
Salesforce Has Never Been Easier

Improve and reinforce salesforce training & adoption using WalkMe's digital adoption platform. Start saving on costly employee training by creating fast intuitive Walk-Thrus for Salesforce. Claim your Free Account Now

 

Author Comment

by:TechMonster
ID: 18035516
"you need a way to let the user pick a "target" window?" <-- Exactly.

Just the main window should do it.  The user picks a text field within the window which places the cursor in it.  When they go back to my program and press go it will (should) remember that same window, set it as the active window, then paste some information from my program into the window where the cursor was.  

For the most part the getforeground window DID work.  Works great with Word and Notepad and some other applications but, if they had an application running with "on top" (the most forefront application) on then it will fail thinking that the forefront application was the last activated window.  
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 18049082
Try this...

Add three Labels, a TextBox, and a small PictureBox to a form.  Make the PictureBox so you can see it by setting the BorderStyle, BackColor or Image properties.

Open up NotePad or Wordpad and then drag the PictureBox onto that window and drop it.

You could use SendKeys.Send() instead of SendMessage().

You could make your app hide or minimize when the user "drags" your PictureBox (making it reappear on MouseUp).



Public Class Form1

    Public Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Integer, ByVal yPoint As Integer) As IntPtr

    Public Declare Function GetAncestor Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal gaFlags As Integer) As IntPtr
    Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As IntPtr, ByVal lpString As String, ByVal cch As Integer) As Integer
    Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As IntPtr) As Integer
    Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Integer) As Integer

    Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As IntPtr, ByVal lpdwProcessId As Integer) As Integer
    Public Declare Function AttachThreadInput Lib "user32" (ByVal idAttach As Integer, ByVal idAttachTo As Integer, ByVal fAttach As Integer) As Integer
    Public Declare Function Putfocus Lib "user32" Alias "SetFocus" (ByVal hWnd As IntPtr) As Integer
    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer

    Public Const GA_ROOT As Integer = 2
    Public Const EM_REPLACESEL As Integer = &HC2

    Private overWindow As IntPtr
    Private mainWindow As IntPtr
    Private windowText As String
    Private className As String
    Private controlText As String

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        If e.Button = Windows.Forms.MouseButtons.Left Then            
            ' for informational purposes...
            overWindow = WindowFromPoint(Windows.Forms.Cursor.Position.X, Windows.Forms.Cursor.Position.Y)

            mainWindow = GetAncestor(overWindow, GA_ROOT)
            windowText = New String(Microsoft.VisualBasic.Chr(0), GetWindowTextLength(mainWindow) + 1)
            GetWindowText(mainWindow, windowText, Len(windowText))
            Label1.Text = "Main Target Window Caption: " & windowText

            className = Space(256)
            Dim retVal As Long
            retVal = GetClassName(overWindow, className, 256)
            className = className.Substring(0, retVal)
            Label2.Text = "Target Window ClassName: " & className

            controlText = New String(Microsoft.VisualBasic.Chr(0), GetWindowTextLength(overWindow) + 1)
            GetWindowText(overWindow, controlText, Len(controlText))
            Label3.Text = "Target Window Caption: " & controlText
        End If
    End Sub

    Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
        If e.Button = Windows.Forms.MouseButtons.Left Then
            ' attempt to paste text into the window we are over
            If Not Me.Handle.Equals(mainWindow) Then
                Dim ThreadID1 As Integer
                Dim ThreadID2 As Integer
                ThreadID1 = GetWindowThreadProcessId(Me.Handle, 0)
                ThreadID2 = GetWindowThreadProcessId(overWindow, 0)

                Call AttachThreadInput(ThreadID1, ThreadID2, True)

                Putfocus(overWindow)
                SendMessage(overWindow, EM_REPLACESEL, &O0, TextBox1.Text)
                Call AttachThreadInput(ThreadID1, ThreadID2, False)
            Else
                Putfocus(overWindow)
                SendMessage(overWindow, EM_REPLACESEL, &O0, TextBox1.Text)
            End If
        End If
    End Sub

End Class
0
 

Author Comment

by:TechMonster
ID: 18054242
I'm taking a look at your solution right now.  Thanks for doing this.

The only concern of mine is the drop method.  I plan on implementing a version of the solution that
Putsfocus over the window when they press on a "Enter" button on my program.  The trick here is that I am not sure how to capture the "overwindow." when the click on the destination application.  You see once they click on the destination application they stil have to go back to my program to select "enter."

 

0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 18054549
That's fine...

The handle to the window is captured in the "overWindow" variable where you can use it later.

I am running code in the MouseUp event but you could do it from anywhere you want.

If you want you could change the cursor as the user drags or drag the outline of the PB for a better visual indicator.

So the user would drag and drop onto the target window to select it.  Then they can go back and press the button whenever they need to.
0
 

Author Comment

by:TechMonster
ID: 18054629
The code does work well and solves my intial problem of not being able to paste into a webbased application  loaded on Citrix.  The program I have will not use drag and drop method however.  

The user clicks on the destination application text field
Then the user clicks on a "enter" button  on my program which triggers some text within my program to be pasted into the destination application.

It is somewhat different then your solution but your solution I think is going to put me on the right direction.  I should have something here shortly.  
 
 
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 18054671
You could make a small floating window that is always on top for the user drag from and designate the target field to make it easier to work with.

Let me know what else I can do...
0
 

Author Comment

by:TechMonster
ID: 18054710
Thanks Idle_Mind.  I appreciate your help GREATLY!  

The only thing I need to do is get the destination application via mouseclick
and then capture that destination application via a "enter Button" on from my applicaiton.

Your solution has gotten me further than I been in in weeks!


0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 18054767
You won't be able to get the target window via mouse click using the method I showed...only drag and drop.

To get the mouse click route to work, we either need to go back to the SetCapture route (which I'm still playing with...didn't anticipate problems converting it to VB.Net!), use a low level mouse hook, or poll the mouse with a timer (not very pretty).

Another option would be to use a low level keyboard hook so you can trap keypresses.  Then the user would click on the target window to give it focus and press a key combination (F2 or something) to designate that field.
0
 

Author Comment

by:TechMonster
ID: 18054803
I would lean more towards the SetCapture route..or low level mouse hook(never heard of it before).  They seem to be more intuitive.  

0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 18055196
0
 

Author Comment

by:TechMonster
ID: 18069836
Idle Mind - Any updates on this?
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
This video Micro Tutorial shows how to password-protect PDF files with free software. Many software products can do this, such as Adobe Acrobat (but not Adobe Reader), Nuance PaperPort, and Nuance Power PDF, but they are not free products. This vide…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question