/// <summary>
        /// ウィンドウハンドルからオブジェクトを取得。
        /// </summary>
        /// <param name="windowHandle">ウィンドウハンドル。</param>
        /// <param name="analyzer">別システムウィンドウ解析。</param>
        /// <returns>オブジェクト。</returns>
        public static object FromHandle(IntPtr windowHandle, IOtherSystemWindowAnalyzer[] analyzer)
		{
			for(int i = 0; i < analyzer.Length; i++)
			{
                object obj = analyzer[i].FromHandle(windowHandle);
				if (obj != null)
				{
					return obj;
				}
			}
			return Control.FromHandle(windowHandle);
		}
        /// <summary>
        /// オブジェクトからウィンドウハンドル取得。
        /// </summary>
        /// <param name="obj">オブジェクト。</param>
        /// <param name="analyzer">別システムウィンドウ解析。</param>
        /// <returns>ウィンドウハンドル。</returns>
        public static IntPtr GetHandle(object obj, IOtherSystemWindowAnalyzer[] analyzer)
		{
            for (int i = 0; i < analyzer.Length; i++)
            {
                IntPtr handle = analyzer[i].GetHandle(obj);
				if (handle != IntPtr.Zero)
				{
					return handle;
				}
			}
			Control control = obj as Control;
			if (control != null)
			{
				return control.Handle;
			}
			return IntPtr.Zero;
		}
        /// <summary>
        /// 解析。
        /// </summary>
        /// <param name="handle">ハンドル。</param>
        /// <param name="analyzer">別システムウィンドウ解析。</param>
        /// <returns>解析結果。</returns>
        public static WindowInfo Analyze(IntPtr handle, IOtherSystemWindowAnalyzer[] analyzer)
        {
            //子ウィンドウを全て取得する
            List<IntPtr> children = new List<IntPtr>();
            NativeMethods.EnumWindowsDelegate callback = delegate(IntPtr hWnd, IntPtr lParam)
            {
                children.Add(hWnd);
                return 1;
            };
            NativeMethods.EnumChildWindows(handle, callback, IntPtr.Zero);
            GC.KeepAlive(callback);

            //ウィンドウ情報を取得する
            WindowInfo info = new WindowInfo();
            info.Handle = handle;
            NativeMethods.RECT rc = new NativeMethods.RECT();
            NativeMethods.GetWindowRect(handle, ref rc);
            List<int> zIndex = new List<int>();
            GetWindowInfo(new Point(rc.left, rc.top), info, children, zIndex, analyzer);
            return info;
        }
		/// <summary>
        /// ウィンドウ情報取得。
		/// </summary>
        /// <param name="pos">ルートウィンドウの左上座標。</param>
        /// <param name="info">ウィンドウ情報格納バッファ。</param>
        /// <param name="children">子ウィンドウハンドル。</param>
        /// <param name="analyzer">別システムウィンドウ解析。</param>
        /// <param name="zIndex">Zインデックス。</param>
        private static void GetWindowInfo(Point pos, WindowInfo info, List<IntPtr> children, List<int> zIndex, IOtherSystemWindowAnalyzer[] analyzer)
		{
			NativeMethods.RECT rc = new NativeMethods.RECT();
			NativeMethods.GetWindowRect(info.Handle, ref rc);
			info.Bounds = new Rectangle(rc.left - pos.X, rc.top - pos.Y, rc.right - rc.left, rc.bottom - rc.top);

			//ウィンドウテキスト取得
            int len = NativeMethods.GetWindowTextLength(info.Handle);
            StringBuilder builder = new StringBuilder((len + 1) * 8);
			NativeMethods.GetWindowText(info.Handle, builder, len * 8);
			info.Text = builder.ToString();
			
			//z順設定
			info.ZIndex = zIndex.ToArray();

			//ダイアログID取得
			info.DialogId = NativeMethods.GetDlgCtrlID(info.Handle);

			//ウィンドウクラス名称取得
			StringBuilder className = new StringBuilder((WindowClassNameMax + 1) * 8);
			NativeMethods.GetClassName(info.Handle, className, WindowClassNameMax * 8);
			info.ClassName = className.ToString();

            //他のウィンドウシステムのウィンドウの場合は解析処理を委譲
            List<WindowInfo> otherSystemChildren = new List<WindowInfo>();
            for (int i = 0; i < analyzer.Length; i++)
            {
                WindowInfo obj = analyzer[i].Analyze(info.Handle);
                if (obj != null)
                {
                    info.TypeFullName = obj.TypeFullName;
                    info.TargetObject = obj.TargetObject;
                    otherSystemChildren.AddRange(obj.Children);
                    break;
                }
            }
            if (info.TargetObject == null)
            {
                //.Netのコントロールの場合、型を取得する
                Control net = Control.FromHandle(info.Handle);
                if (net != null)
                {
                    info.TypeFullName = net.GetType().FullName;
                    info.TargetObject = net;
                }
            }

			//自分の子ウィンドウを集める
			List<IntPtr> myChildren = new List<IntPtr>();
			for (int i = children.Count - 1; 0 <= i; i--)
			{
				if (NativeMethods.GetParent(children[i]) == info.Handle)
				{
					myChildren.Add(children[i]);
					children.RemoveAt(i);
				}
			}

			//Z順でソートする
			IntPtr[] myChildrenSort = WindowPositionUtility.SortByZIndex(myChildren.ToArray());

			//子のウィンドウ情報を設定する
			zIndex.Add(0);
            List<WindowInfo> allChildren = new List<WindowInfo>();
            for (int i = 0; i < myChildrenSort.Length; i++)
			{
				zIndex[zIndex.Count - 1] = i;
				WindowInfo c = new WindowInfo();
				c.Handle = myChildrenSort[i];
                allChildren.Add(c);
				GetWindowInfo(pos, c, children, zIndex, analyzer);
			}
			zIndex.RemoveAt(zIndex.Count - 1);
            
            //別システムに属するウィンドウはZIndexの整合性が取れなくなるので最後に追加
            allChildren.AddRange(otherSystemChildren);
            info.Children = allChildren.ToArray();
		}