/// <summary>
 /// アイテムテキストの取得。
 /// </summary>
 /// <param name="Handle">ウィンドウハンドル。</param>
 /// <param name="hItem">アイテムハンドル。</param>
 /// <returns>アイテムテキスト。</returns>
 internal static string GetItemTextInTarget(IntPtr Handle, IntPtr hItem)
 {
     TVITEMEX item = new TVITEMEX();
     item.hItem = hItem;
     item.mask = TVIF.TEXT;
     GetItemInTarget(Handle, item);
     return item.pszText;
 }
        public void TestEmulateChangeItemEventAsync()
        {
            if (!isUni || !OSUtility.Is7or8())
            {
                //設定によってはこのイベントは発生しない。
                return;
            }

            NativeTree tree = new NativeTree(testDlg.IdentifyFromDialogId(1042));
            TVITEMEX newItem = new TVITEMEX();
            newItem.hItem = tree.Nodes[0];
            newItem.mask = TVIF.STATE;
            newItem.stateMask = TVIS.SELECTED;
            newItem.state = TVIS.SELECTED;

            Async async = new Async();
            tree.EmulateChangeItem(newItem, async);
            Assert.IsTrue(0 < MessageBoxUtility.CloseAll(testDlg, async));
        }
        public void TestSetGetItem()
        {
            NativeTree tree = new NativeTree(testDlg.IdentifyFromDialogId(1041));
            TVITEMEX item = new TVITEMEX();
            foreach (TVIF element in (TVIF[])Enum.GetValues(typeof(TVIF)))
            {
                item.mask |= element;
            }
            foreach (TVIS element in (TVIS[])Enum.GetValues(typeof(TVIS)))
            {
                item.stateMask |= element;
            }

            //アイテムのすべての情報が正常に取得できることを確認。
            item.hItem = tree.Nodes[0];
            tree.GetItem(item);
            Assert.AreEqual("0", item.pszText);
            Assert.AreEqual(0, item.iImage);
            Assert.AreEqual(4, item.iSelectedImage);
            Assert.AreEqual(1, item.cChildren);
            Assert.AreEqual(new IntPtr(100), item.lParam);
            Assert.AreEqual((TVIS)0, (item.state & TVIS.EXPANDED));
            tree.EmulateExpand(item.hItem, true);
            tree.GetItem(item);
            Assert.AreEqual(TVIS.EXPANDED, (item.state & TVIS.EXPANDED));
            item.hItem = tree.FindNode(0, 0); //iImageは上記では0確認であるため、念のため、値の入ったアイテムでもテスト。
            tree.GetItem(item);
            Assert.AreEqual(1, item.iImage);

            //全ての情報情報を設定できることを確認。
            item.hItem = tree.Nodes[0];
            tree.GetItem(item);//もとに戻す用
            TVITEMEX newItem = new TVITEMEX();
            newItem.hItem = item.hItem;
            newItem.mask = item.mask;
            newItem.pszText = "xxx";
            newItem.iImage = 1;
            newItem.iSelectedImage = 2;
            newItem.cChildren = 0;
            newItem.lParam = new IntPtr(200);
            newItem.stateMask = TVIS.SELECTED;
            newItem.state = TVIS.SELECTED;
            tree.EmulateChangeItem(newItem);

            TVITEMEX check = new TVITEMEX();
            check.hItem = item.hItem;
            check.mask = item.mask;
            check.stateMask = item.stateMask;
            tree.GetItem(check);
            Assert.AreEqual("xxx", check.pszText);
            Assert.AreEqual(1, check.iImage);
            Assert.AreEqual(2, check.iSelectedImage);
            Assert.AreEqual(0, check.cChildren);
            Assert.AreEqual(new IntPtr(200), check.lParam);
            Assert.AreEqual(TVIS.SELECTED, check.state & TVIS.SELECTED);
        }
 /// <summary>
 /// 指定のアイテムがチェック状態であるかを取得します。
 /// </summary>
 /// <param name="handle">ウィンドウハンドル。</param>
 /// <param name="hItem">アイテムハンドル。</param>
 /// <returns>チェック状態であるか。</returns>
 internal static bool IsCheckedInTarget(IntPtr handle, IntPtr hItem)
 {
     TVITEMEX item = new TVITEMEX();
     item.mask = TVIF.HANDLE | TVIF.STATE;
     item.hItem = hItem;
     item.stateMask = (TVIS)TVIS_STATEIMAGEMASK;
     GetItemInTarget(handle, item);
     return (((int)item.state >> 12) - 1) != 0;
 }
 /// <summary>
 /// 指定のアイテムが展開状態であるかを取得します。
 /// </summary>
 /// <param name="handle">ウィンドウハンドル。</param>
 /// <param name="hItem">アイテムハンドル。</param>
 /// <returns>指定のアイテムが展開状態であるか。</returns>
 internal static bool IsExpandedInTarget(IntPtr handle, IntPtr hItem)
 {
     TVITEMEX item = new TVITEMEX();
     item.hItem = hItem;
     item.mask = TVIF.STATE;
     item.stateMask = TVIS.EXPANDED;
     item.state = 0;
     GetItemInTarget(handle, item);
     return (item.state & TVIS.EXPANDED) != 0;
 }
 /// <summary>
 /// チェック状態を変更するためのアイテムを作成します。
 /// </summary>
 /// <param name="hItem">アイテムハンドル。</param>
 /// <param name="check">チェック状態。</param>
 /// <returns>アイテム。</returns>
 private static TVITEMEX CreateCheckChangeItem(IntPtr hItem, bool check)
 {
     TVITEMEX item = new TVITEMEX();
     item.mask = TVIF.HANDLE | TVIF.STATE;
     item.hItem = hItem;
     item.stateMask = (TVIS)TVIS_STATEIMAGEMASK;
     item.state = (TVIS)((check ? 2 : 1) << 12);
     return item;
 }
 /// <summary>
 /// 指定のアイテムが展開状態であるかを取得します。
 /// </summary>
 /// <param name="wndHandle">ウィンドウハンドル。</param>
 /// <param name="hItem">アイテムハンドル。</param>
 /// <returns>指定のアイテムが展開状態であるか。</returns>
 private static bool IsExpandedOnce(IntPtr wndHandle, IntPtr hItem)
 {
     TVITEMEX item = new TVITEMEX();
     item.hItem = hItem;
     item.mask = TVIF.STATE;
     item.stateMask = TVIS.EXPANDEDONCE;
     item.state = 0;
     GetItemInTarget(wndHandle, item);
     return (item.state & TVIS.EXPANDEDONCE) != 0;
 }
        /// <summary>
        /// ノードを検索します。
        /// </summary>
        /// <param name="wndHandle">ウィンドウハンドル。</param>
        /// <param name="nodeText">各ノードのテキスト。</param>
        /// <returns>検索されたノードのアイテムハンドル。未発見時はIntPtr.Zeroが返ります。</returns>
        private static IntPtr FindNodeInTarget(IntPtr wndHandle, string[] nodeText)
        {
            //ルートに連なるノードを取得
            IntPtr[] nodes = GetRootNodesInTarget(wndHandle);

            //検索
            IntPtr hit = IntPtr.Zero;
            for (int i = 0; i < nodeText.Length; i++)
            {
                hit = IntPtr.Zero;
                for (int j = 0; j < nodes.Length; j++)
                {
                    TVITEMEX item = new TVITEMEX();
                    item.hItem = nodes[j];
                    item.mask = TVIF.TEXT;
                    GetItemInTarget(wndHandle, item);
                    if (item.pszText == nodeText[i])
                    {
                        hit = nodes[j];
                        nodes = GetChildNodesInTarget(wndHandle, nodes[j]);
                        break;
                    }
                }
                if (hit == IntPtr.Zero)
                {
                    return IntPtr.Zero;
                }
            }
            return hit;
        }
 /// <summary>
 /// アイテム情報を設定します。
 /// 状態にかかわる情報が変化した場合、コントロールの設定によっては、TVN_ITEMCHANGING、TVN_ITEMCHANGEDの通知が発生します。
 /// </summary>
 /// <param name="handle">ウィンドウハンドル。</param>
 /// <param name="item">アイテム情報。</param>
 private static void EmulateChangeItemInTarget(IntPtr handle, TVITEMEX item)
 {
     NativeMethods.SetFocus(handle);
     bool isUni = NativeMethods.IsWindowUnicode(handle);
     int TVM_SETITEM = isUni ? TVM_SETITEMW : TVM_SETITEMA;
     item._core.pszText = isUni ? Marshal.StringToCoTaskMemUni(item.pszText) :
                                     Marshal.StringToCoTaskMemAnsi(item.pszText);
     try
     {
         NativeDataUtility.ToBool(NativeMethods.SendMessage(handle, TVM_SETITEM, IntPtr.Zero, ref item._core));
     }
     finally
     {
         Marshal.FreeCoTaskMem(item._core.pszText);
     }
 }
        /// <summary>
        /// アイテム情報を取得します。
        /// </summary>
        /// <param name="handle">ウィンドウハンドル。</param>
        /// <param name="item">アイテム情報。</param>
        /// <returns>アイテム。</returns>
        internal static bool GetItemInTarget(IntPtr handle, TVITEMEX item)
        {
            bool isUni = NativeMethods.IsWindowUnicode(handle);
            int TVM_GETITEM = isUni ? TVM_GETITEMW : TVM_GETITEMA;

            //文字列取得の場合バッファを確保する。
            if ((item.mask & TVIF.TEXT) == TVIF.TEXT)
            {
                item._core.cchTextMax = 256;
            }

            while (true)
            {
                if (0 < item._core.cchTextMax)
                {
                    item._core.pszText = Marshal.AllocCoTaskMem((item._core.cchTextMax + 1) * 8);
                }
                try
                {
                    if (!NativeDataUtility.ToBool(NativeMethods.SendMessage(handle, TVM_GETITEM, IntPtr.Zero, ref item._core)))
                    {
                        return false;
                    }

                    //文字列取得がなければ終了。
                    if (item._core.pszText == IntPtr.Zero)
                    {
                        return true;
                    }

                    //文字列に変換。
                    item.pszText = isUni ? Marshal.PtrToStringUni(item._core.pszText) :
                            Marshal.PtrToStringAnsi(item._core.pszText);

                    //サイズが足りていれば終了。
                    if (item.pszText.Length < item._core.cchTextMax - 1)
                    {
                        return true;
                    }

                    //リトライ。
                    item._core.cchTextMax *= 2;
                }
                finally
                {
                    if (item._core.pszText != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(item._core.pszText);
                    }
                }
            }
        }
        /// <summary>
        /// Sets the value of an item.
        /// Produces TVN_ITEMCHANGING and TVN_ITEMCHANGED notifications when the information in connection with a state changes, depending on the setup of the control.
        /// Executes asynchronously. 
        /// </summary>
        /// <param name="item">Item information.</param>
        /// <param name="async">Asynchronous execution object.</param>
#else
        /// <summary>
        /// アイテム情報を設定します。
        /// 状態にかかわる情報が変化した場合、コントロールの設定によっては、TVN_ITEMCHANGING、TVN_ITEMCHANGEDの通知が発生します。
        /// 非同期で実行します。
        /// </summary>
        /// <param name="item">アイテム情報。</param>
        /// <param name="async">非同期実行オブジェクト。</param>
#endif
        public void EmulateChangeItem(TVITEMEX item, Async async)
        {
            App[GetType(), "EmulateChangeItemInTarget", async](Handle, item);
        }
        /// <summary>
        /// Sets the value of an item.
        /// Produces TVN_ITEMCHANGING and TVN_ITEMCHANGED notifications when the information in connection with a state changes, depending on the setup of the control.
        /// </summary>
        /// <param name="item">Item information.</param>
#else
        /// <summary>
        /// アイテム情報を設定します。
        /// 状態にかかわる情報が変化した場合、コントロールの設定によっては、TVN_ITEMCHANGING、TVN_ITEMCHANGEDの通知が発生します。
        /// </summary>
        /// <param name="item">アイテム情報。</param>
#endif
        public void EmulateChangeItem(TVITEMEX item)
        {
            App[GetType(), "EmulateChangeItemInTarget"](Handle, item);
        }
        /// <summary>
        /// Obtains item data for an indicated item.
        /// </summary>
        /// <param name="hItem">Item handle.</param>
        /// <returns>Item data.</returns>
#else
        /// <summary>
        /// アイテムデータを取得します。
        /// </summary>
        /// <param name="hItem">アイテムハンドル。</param>
        /// <returns>アイテムデータ。</returns>
#endif
        public IntPtr GetItemData(IntPtr hItem)
        {
            TVITEMEX item = new TVITEMEX();
            item.hItem = hItem;
            item.mask = TVIF.PARAM;
            GetItem(item);
            return item.lParam;
        }
        /// <summary>
        /// Obtains item information.
        /// </summary>
        /// <param name="item">Item information.</param>
        /// <returns>Success or failure.</returns>
#else
        /// <summary>
        /// アイテム情報を取得します。
        /// </summary>
        /// <param name="item">アイテム情報。</param>
        /// <returns>成否。</returns>
#endif
        public bool GetItem(TVITEMEX item)
        {
            AppVar inTarget = App.Dim(item);
            bool ret = (bool)App[GetType(), "GetItemInTarget"](Handle, inTarget).Core;
            TVITEMEX getData = (TVITEMEX)inTarget.Core;
            item._core = getData._core;
            item.pszText = getData.pszText;
            return ret;
        }
        public void TestEmulateChangeItemEvent()
        {
            if (!isUni || !OSUtility.Is7or8())
            {
                //設定によってはこのイベントは発生しない。
                return;
            }

            NativeTree tree = new NativeTree(testDlg.IdentifyFromDialogId(1041));

            TVITEMEX itemOri = new TVITEMEX();
            itemOri.hItem = tree.Nodes[0];
            tree.GetItem(itemOri);
            TVITEMEX newItem = new TVITEMEX();
            newItem.hItem = itemOri.hItem;
            newItem.mask = itemOri.mask = TVIF.STATE;
            newItem.stateMask = TVIS.SELECTED;
            newItem.state = (TVIS)0;

            //一度明示的に選択をOFFにする
            tree.EmulateChangeItem(newItem);

            //変更
            newItem.state = TVIS.SELECTED;
            Assert.IsTrue(EventChecker.IsSameTestEvent(testDlg,
            delegate { tree.EmulateChangeItem(newItem); },
                new CodeInfo(1041, NativeMethods.WM_NOTIFY, TVN_ITEMCHANGING),
                new CodeInfo(1041, NativeMethods.WM_NOTIFY, TVN_ITEMCHANGED)
            ));
        }