DCSIMG
Add Your Control On Top Another Application – Part 1 (Win32) - Shai Raiten's Blog

Shai Raiten's Blog

It's all about code...

Add Your Control On Top Another Application – Part 1 (Win32)

Add Your Control On Top Another Application – Part 1 (Win32)image

Couple of days ago I got an email asked me to help with creating a buttons on top all open applications, this has reminded me the CodedUI Recorder.
As you can see from the picture when using CodedUI Testing you will see the “Currently Recording” notification on every active application you are recording.

How?

The design is to make the title bar window of the target application as the parent\owner window of the Control your want to add.
But this is not enough, we need to listen to many events like size change, style etc.. but I’ll get there later.
Here is what we need to do:

  1. Find window handle with FindWindow
  2. Get window position and title bar info using GetTitleBarInfo
  3. Set window as owner\parent using SetWindowLong
  4. SetWinEventHook for couple of events of the target application.

Download Demo Project

 imageSo let’s get started…

Step 1: Create Project

Create a WinForm or WPF project and add the following classes:

  • We will use this class to combine native methods so we can write our code mote efficiently.
    public static class Helpers
  • Native methods collection.
    static class NativeMethods

Step 2: Get Running Processes

Create new class called “PItem” and copy this code:

public class PItem

{

    public string ProcessName { get; set; }

    public string Title { get; set; }

 

    public PItem(string processname, string title)

    {

        this.ProcessName = processname;

        this.Title = title;

    }

 

    public override string ToString()

    {

        if (!string.IsNullOrEmpty(Title))

            return string.Format("{0} ({1})", this.ProcessName, this.Title);

        else

            return string.Format("{0}", this.ProcessName);

    }

}

 

Now, getting all active processes:

Process[] pro_list = e.Result as Process[];

foreach (Process pro in pro_list)

{

    try

    {

        //When using 64bit OS pro.MainModule.ModuleName will throw exception

        // for each 32bit, so Instead of ModuleName I've used ProcessName

        ProcessList.Items.Add(new PItem(pro.ProcessName, pro.MainWindowTitle));

    }

    catch (Exception)

    {

        //Security\ Permissions Issue

    }

}

Step 3: Add Find Native Methods

FindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.
Add below methods to NativeMethods.

using System.Runtime.InteropServices;


// Get a handle to an application window.

[DllImport("user32.dll", SetLastError = true)]

internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

 

// Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter.

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]

internal static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

 

Add below code to Helpers
I’ve created a Find method to handle both FindWindow and FindWindowByCaption (much more easy to search that way :-D)

public static IntPtr Find(string ModuleName, string MainWindowTitle)

{

    //Search the window using Module and Title

    IntPtr WndToFind = NativeMethods.FindWindow(ModuleName, MainWindowTitle);

    if (WndToFind.Equals(IntPtr.Zero))

    {

        if (!string.IsNullOrEmpty(MainWindowTitle))

        {

            //Search window using TItle only.

            WndToFind = NativeMethods.FindWindowByCaption(WndToFind, MainWindowTitle);

            if (WndToFind.Equals(IntPtr.Zero))

                return new IntPtr(0);

        }

    }

    return WndToFind;

}

Step 4: Find Window Handle From Process

Using PItem we can use the ModuleName\Process Name and if the window is exists we can also use window title.
Calling our Helpers class and using Find method with ProcessName and WindowTitle.

PItem pro = ProcessList.SelectedItem as PItem;

 

string ModuleName = pro.ProcessName;

string MainWindowTitle = pro.Title; ;

 

TargetWnd = Helpers.Find(ModuleName, MainWindowTitle);

 

if (!TargetWnd.Equals(IntPtr.Zero))

    Log(ModuleName + " Window: " + TargetWnd.ToString()); // We Found The Window

else

    Log(ModuleName + " Not found"); // No Window Found

 

Download Demo Project

Comments

Twitter Trackbacks for Add Your Control On Top Another Application ??? Part 1 (Win32) - Shai Raiten [microsoft.co.il] on Topsy.com said:

Pingback from  Twitter Trackbacks for                 Add Your Control On Top Another Application ??? Part 1 (Win32) - Shai Raiten         [microsoft.co.il]        on Topsy.com

# May 6, 2010 2:41 PM

Shai Raiten said:

Add Your Control On Top Another Application – Part 2 (Win32) In my previous post Add Your Control On

# May 9, 2010 8:59 PM

Shai Raiten said:

Add Your Control On Top Another Application – Part 3 (Win32) This is part 3 and we are almost done! The

# May 10, 2010 6:15 PM

Shai Raiten said:

Window Hooks – Summary A week ago I received a question through my blog " How can I create buttons

# May 17, 2010 9:07 AM

JJ said:

How can I find a special control in a group of control on a main window?

ex: find a listview within a group of checkbox!!

# October 15, 2010 6:04 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: