How to catch that external window became active?

Is there a way to have C# application run in background and catch the event, when any open window gets focus?
kutiJackAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Mike TomlinsonMiddle School Assistant TeacherCommented:
You could try something like this....
Imports System.Runtime.InteropServices
Public Class Form1
 
    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
 
    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 GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As IntPtr, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
    Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As IntPtr) As Integer
 
    Private uMsgNotify As Integer
 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        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
                    Dim curWindow As IntPtr = GetForegroundWindow()
                    Dim windowText As New System.Text.StringBuilder()
                    windowText.Length = GetWindowTextLength(curWindow) + 1
                    GetWindowText(curWindow, windowText, windowText.Length)
                    Debug.Print("Current Window: " & curWindow.ToString("X") & ": " & windowText.ToString)
            End Select
        End If
        MyBase.WndProc(m)
    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

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
kutiJackAuthor Commented:
Your VB code works well, but please, could you explain me, why  some windows throw on WINDOWACTIVATED event value of 4 and some value of 32772?
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
What kind of windows?...are they by chance system windows like the desktop, start menu etc?...
0
Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

kutiJackAuthor Commented:
Hello, sorry for my late response. Now things have changed, all windows show value of 32772 on WINDOWACTIVATED event. All other events give propre values according to enumeration you provided. This is little strange to me.
0
kutiJackAuthor Commented:
I have Windows XP Professional
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
I'm running Visual Studio 2008 Standard on a 64-bit Vista Home Premium system.

Can you post your converted code?

0
kutiJackAuthor Commented:
Here is the converted code, but your original VB code produces the same value 32772 on window activation



using System.Diagnostics;
using System;
using System.Xml.Linq;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using Microsoft.VisualBasic;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
 
namespace WindowsApplication1
{
	public partial class Form1
	{
		public Form1()
		{
			InitializeComponent();
			
			//Added to support default instance behavour in C#
			if (defaultInstance == null)
				defaultInstance = this;
		}
		
		#region Default Instance
		
		private static Form1 defaultInstance;
		
		/// <summary>
		/// Added by the VB.Net to C# Converter to support default instance behavour in C#
		/// </summary>
		public static Form1 Default
		{
			get
			{
				if (defaultInstance == null)
				{
					defaultInstance = new Form1();
					defaultInstance.FormClosed += new FormClosedEventHandler(defaultInstance_FormClosed);
				}
				
				return defaultInstance;
			}
		}
		
		static void defaultInstance_FormClosed(object sender, FormClosedEventArgs e)
		{
			defaultInstance = null;
		}
		
		#endregion
		
		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
		}
		
		[DllImport("user32.dll",EntryPoint="RegisterWindowMessageA", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]
		public static extern int RegisterWindowMessage(string lpString);
		[DllImport("user32", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]
		public static extern int DeregisterShellHookWindow(IntPtr hWnd);
		[DllImport("user32", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]
		public static extern int RegisterShellHookWindow(IntPtr hWnd);
		[DllImport("user32", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]
		public static extern IntPtr GetForegroundWindow();
		
		[DllImport("user32",EntryPoint="GetWindowTextA", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]
		public static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder lpString, int cch);
		[DllImport("user32",EntryPoint="GetWindowTextLengthA", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]
		public static extern int GetWindowTextLength(IntPtr hWnd);
		
		private int uMsgNotify;
		
		public void Form1_Load(object sender, System.EventArgs e)
		{
			uMsgNotify = RegisterWindowMessage("SHELLHOOK");
			RegisterShellHookWindow(this.Handle);
		}
		
		protected override void WndProc(ref System.Windows.Forms.Message m)
		{
			if (m.Msg == uMsgNotify)
            {
               
				switch (m.WParam.ToInt32())
				{
					case  (int) (ShellEvents.HSHELL_WINDOWACTIVATED):
						IntPtr curWindow = GetForegroundWindow();
						System.Text.StringBuilder windowText = new System.Text.StringBuilder();
						windowText.Length = GetWindowTextLength(curWindow) + 1;
						GetWindowText(curWindow, windowText, windowText.Length);
						Debug.Print("Current Window: " + curWindow.ToString("X") + ": " + windowText.ToString());
						break;
				}
			}
			base.WndProc(ref m);
		}
		
		public void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			DeregisterShellHookWindow(this.Handle);
		}
		
	}
}

Open in new window

0
kutiJackAuthor Commented:
Thank you for your code. I tried events on virtual machine with clean XP and all values are now "4", so the confusion lies somewhere in my OS.
0
kutiJackAuthor Commented:
I tried to run application on virtual machine with clean XP and everything went all right, all activation events threw value of 4. So, the cause is probably in my OS. Maby I will find it soon. Thank you.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.