Link to home
Start Free TrialLog in
Avatar of WuLabs
WuLabs

asked on

I need FindWindowLike for C#

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.
Avatar of dbrckovi
dbrckovi
Flag of Croatia image

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;
            }
      }
}
Avatar of WuLabs
WuLabs

ASKER

Maybe i was not clear.  I need findwindow WITH WILDCARDS. Like this: http://support.microsoft.com/kb/147659
Avatar of Bob Learned
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
Avatar of WuLabs

ASKER

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!
ASKER CERTIFIED SOLUTION
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Will this code work in a C# Service