I need FindWindowLike for C#

WuLabs
WuLabs used Ask the Experts™
on
I need a FindWindowLike implementation in C#, or at least something that does the same thing.  THe idea is a findwindow with wildcards.  THere is currently an implementation in VB but i was not able to convert it.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
Hi.

You could use Windows API to do this.
For example, this will get handles and window text's of all windows which have text (titles).

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;

namespace WindowsApplication6
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            private System.Windows.Forms.Button button1;
            private System.Windows.Forms.ListBox listBox1;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.button1 = new System.Windows.Forms.Button();
                  this.listBox1 = new System.Windows.Forms.ListBox();
                  this.SuspendLayout();
                  //
                  // button1
                  //
                  this.button1.Location = new System.Drawing.Point(544, 40);
                  this.button1.Name = "button1";
                  this.button1.Size = new System.Drawing.Size(160, 40);
                  this.button1.TabIndex = 0;
                  this.button1.Text = "Find";
                  this.button1.Click += new System.EventHandler(this.button1_Click);
                  //
                  // listBox1
                  //
                  this.listBox1.Location = new System.Drawing.Point(24, 32);
                  this.listBox1.Name = "listBox1";
                  this.listBox1.Size = new System.Drawing.Size(512, 264);
                  this.listBox1.TabIndex = 1;
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(704, 334);
                  this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                                              this.listBox1,
                                                                                                              this.button1});
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.ResumeLayout(false);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [DllImport("user32.dll")]
            public static extern bool EnumWindows(CallBack lpEnumFunc, Int32 lParam);
            [DllImport("user32.dll")]
            public static extern Int32 GetWindowText(Int32 hwnd, StringBuilder lpString, Int32 cch);
            [DllImport("user32.dll")]
            public static extern Int32 GetWindowTextLength (Int32 hwnd);
            
            [STAThread]
            static void Main()
            {
                  Application.Run(new Form1());
            }
            
            public delegate bool CallBack(int hwnd, int lParam);

            private void button1_Click(object sender, System.EventArgs e)
            {
                  listBox1.Items.Clear();
                  CallBack myCallBack = new CallBack(EnumWindowsProc);
                  EnumWindows (myCallBack,0);
            }

            private bool EnumWindowsProc (Int32 hwnd, Int32 lParam)
            {
                  StringBuilder WindowText = new StringBuilder(1024);
                  int WindowTextLength;
                  WindowTextLength = GetWindowTextLength(hwnd) + 1;
                  
                  GetWindowText(hwnd,WindowText,WindowTextLength);
                  if (WindowText.ToString().Trim() != "")
                        listBox1.Items.Add(hwnd.ToString() + " - " + WindowText);
                  return true;
            }
      }
}

Author

Commented:
Maybe i was not clear.  I need findwindow WITH WILDCARDS. Like this: http://support.microsoft.com/kb/147659
Most Valuable Expert 2012
Top Expert 2008

Commented:
Here is an implementation after converting the code from that Micro$oft article:

using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;

namespace My.Computer
{
  public class FindWindowLike
  {
   
    public class Window
    {
      public string Title;
      public string Class;
      public int Handle;
    }

    [DllImport("user32")]
    private static extern int GetWindow(int hwnd, int wCmd);

    [DllImport("user32")]
    private static extern int GetDesktopWindow();

    [DllImport("user32", EntryPoint="GetWindowLongA")]
    private static extern int GetWindowLong(int hwnd, int nIndex);
   
    [DllImport("user32")]
    private static extern int GetParent(int hwnd);

    [DllImport("user32", EntryPoint="GetClassNameA")]
    private static extern int GetClassName(
      int hWnd, [Out] StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32", EntryPoint="GetWindowTextA")]
    private static extern int GetWindowText(
      int hWnd, [Out] StringBuilder lpString, int nMaxCount);
   
    private const int GWL_ID = (-12);
    private const int GW_HWNDNEXT = 2;
    private const int GW_CHILD = 5;

    public static Window[] Find(int hwndStart, string findText, string findClassName)
    {

      ArrayList windows = DoSearch(hwndStart, findText, findClassName);

      return (Window[])windows.ToArray(typeof(Window));

    } //Find


    private static ArrayList DoSearch(int hwndStart, string findText, string findClassName)
    {

      ArrayList list = new ArrayList();
 
      if (hwndStart == 0)
        hwndStart = GetDesktopWindow();

      int hwnd = GetWindow(hwndStart, GW_CHILD);
 
      while (hwnd != 0)
      {
       
        // Recursively search for child windows.
        list.AddRange(DoSearch(hwnd, findText, findClassName));
       
        StringBuilder text = new StringBuilder(255);
        int rtn = GetWindowText(hwnd, text, 255);
        string windowText = text.ToString();
        windowText = windowText.Substring(0, rtn);

        StringBuilder cls = new StringBuilder(255);  
        rtn = GetClassName(hwnd, cls, 255);
        string className = cls.ToString();
        className = className.Substring(0, rtn);
     
        if (GetParent(hwnd) != 0)
          rtn = GetWindowLong(hwnd, GWL_ID);

        if (windowText.Length > 0 && windowText.StartsWith(findText) && 
          (className.Length == 0 || className.StartsWith(findClassName)))
        {
          Window currentWindow = new Window();
     
          currentWindow.Title = windowText;
          currentWindow.Class = className;
          currentWindow.Handle = hwnd;
       
          list.Add(currentWindow);
        }

        hwnd = GetWindow(hwnd, GW_HWNDNEXT);

      }

      return list;

    } //DoSearch

  } //Class

} //Namespace


Test usage:
   My.Computer.FindWindowLike.Window[] list = My.Computer.FindWindowLike.Find(0, "Document1", "");

Bob
Fundamentals of JavaScript

Learn the fundamentals of the popular programming language JavaScript so that you can explore the realm of web development.

Author

Commented:
Hi Bob,

Your code compiles and runs, but does not provide the exact same functionality as http://support.microsoft.com/kb/147659.  For example when I run to find window caption "*", * does not work as a wildcard.  See examples in the link provided.  Such examples do not work with your code.  The code you provided only searches for windows which contain X, where X is the window caption I am looking for.

What you provided works for what I need.  But, I will not award you the full points unless you provide me with the exact function that fullfills the spec.

I will award 500 pts + A to you if you can provide me with an updated full function.

Otherwise I will award 250 points + B to you.

You have a few days.  Thanks!
Most Valuable Expert 2012
Top Expert 2008
Commented:
The VB code uses the keyword Like, which C# does not have, so you can't use wildcards.  The StartsWith gives you a close approximation of using wildcards.

>>You have a few days.  Thanks!
Gee thanks, you are so generous.

Bob

Commented:
Will this code work in a C# Service

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial