none
ソリューション・エクスプローラのツリービューへの振り分けを、ファイルの拡張子ではなくファイル名を条件にしたい RRS feed

  • 質問

  • Visual C++ のソリューション・エクスプローラのツリービュー振り分けは vcxproj.filters ファイルによって行われますが

    これに、拡張子 (Extensonタグ)以外の要素を条件として含めることはできないでしょうか?

    やりたいことは、拡張子による振り分けでも、なおビューの表示が長くなり見づらい場合、

    せめてファイル名の頭文字あるいはパス別ででも自動振り分けを行い、少しでもツリービューを見やすくすることです。

    ご教示お願い申し上げます。

    2016年2月22日 7:54

回答

  • フィルタの下層にさらにフィルタを作れるので、その頭文字毎のフィルタを作って振り分けで代用してもいいなら。

    頭文字による自動振り分けを拡張機能で書いてみた

    using System;
    using System.Runtime.InteropServices;
    using System.ComponentModel.Design;
    using Microsoft.VisualStudio.Shell;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.VCProjectEngine;
    namespace Company.CPPFilterTest
    {
        [PackageRegistration(UseManagedResourcesOnly = true)]
        [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
        [ProvideMenuResource("Menus.ctmenu", 1)]
        [Guid(GuidList.guidCPPFilterTestPkgString)]
        [ProvideAutoLoad(Microsoft.VisualStudio.Shell.Interop.UIContextGuids80.SolutionExists)]
        public sealed class CPPFilterTestPackage : Package
        {
            private EnvDTE.DTE _DTE;
            private EnvDTE.SolutionEvents _SolutionEvents;
            private VCProjectEngineEvents _VCProjectEvents;
            protected override void Initialize()
            {
                base.Initialize();
                OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
                if (null != mcs)
                {
                    CommandID menuCommandID = new CommandID(GuidList.guidCPPFilterTestCmdSet, (int)PkgCmdIDList.CppFilterTest);
                    MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
                    mcs.AddCommand(menuItem);
                }
    
                _DTE = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));
                _SolutionEvents = _DTE.Events.SolutionEvents;
                _SolutionEvents.Opened += _SolutionEvents_Opened;
            }
    
            void _SolutionEvents_Opened()
            {
                if (_VCProjectEvents == null)
                {
                    foreach (dynamic o in _DTE.Solution.Projects)
                    {
                        if (o.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
                        {
                            VCProject proj = o.Object as VCProject;
                            VCProjectEngine engine = proj.VCProjectEngine as VCProjectEngine;
                            _VCProjectEvents = engine.Events as VCProjectEngineEvents;
                            _VCProjectEvents.ItemAdded += _VCProjectEvents_ItemAdded;
                            _VCProjectEvents.ItemRenamed += _VCProjectEvents_ItemRenamed;
                            break;
                        }
                    }
                }
            }
            /// <summary>新しくファイルを追加した</summary>
            void _VCProjectEvents_ItemAdded(object Item, object ItemParent)
            {
                VCFilter parentFilter = ItemParent as VCFilter;
                VCFile file = Item as VCFile;
                Move(file, parentFilter);
            }
            /// <summary>ファイル名を変更した</summary>
            void _VCProjectEvents_ItemRenamed(object Item, object ItemParent, string OldName)
            {
                VCFilter parentFilter = ItemParent as VCFilter;
                VCFile file = Item as VCFile;
                Move(file, parentFilter);
            }
            /// <summary>ファイル名に合わせて名前別のフィルタへ移動</summary>
            private void Move(VCFile file, VCFilter parentFilter)
            {
                if (file != null && parentFilter != null)
                {
                    var nameParts = parentFilter.CanonicalName.Split('\\');
                    var proj = file.project as VCProject;
                    foreach (VCFilter rootFilter in ((dynamic)proj.Filters))
                    {
                        if (rootFilter.Name == nameParts[0])
                        {
                            string filterName = file.Name[0].ToString().ToUpper();
                            foreach (VCFilter childFilter in ((dynamic)rootFilter.Filters))
                            {
                                if (childFilter.Name == filterName)
                                {
                                    if (file.CanMove(childFilter))
                                    {
                                        file.Move(childFilter);
    
                                    }
                                    return;
                                }
                            }
                            {
                                VCFilter childFilter = (VCFilter)rootFilter.AddFilter(filterName);
                                if (file.CanMove(childFilter))
                                {
                                    file.Move(childFilter);
                                }
                            }
                        }
                    }
                }
            }
    
            /// <summary>既存のファイルを新しいフィルタ(仮想フォルダの代用)に振り分ける</summary>
            private void MenuItemCallback(object sender, EventArgs e)
            {
                foreach (dynamic d in _DTE.Solution.Projects)
                {
                    dynamic proj = d.Object;
                    foreach (VCFilter parentFilter in proj.Filters)
                    {
                        if (parentFilter.CanonicalName.Contains('\\'))
                        {
                            continue;
                        }
    
                        Dictionary<char, VCFilter> dic = new Dictionary<char, VCFilter>();
                        foreach (VCFilter childFilter in ((dynamic)parentFilter.Filters))
                        {
                            if (childFilter.Name.Length == 1)
                            {
                                dic.Add(childFilter.Name[0], childFilter);
                            }
                        }
                        for (int i = (int)'A'; i <= (int)'Z'; i++)
                        {
                            char c = (char)i;
                            VCFilter childFilter;
    
                            if (dic.ContainsKey(c))
                            {
                                childFilter = dic[c];
                            }
                            else
                            {
                                childFilter = (VCFilter)parentFilter.AddFilter(c.ToString());
                                dic.Add(c, childFilter);
                            }
    
                            var items = ((IEnumerable)parentFilter.Items)
                                        .Cast<dynamic>()
                                        .Where(_ => _.Name.ToString().ToUpper().StartsWith(c.ToString()))
                                        .ToArray();
                            foreach (VCFile file in items)
                            {
                                var name = file.Name.ToString();
                                if (file.CanMove(childFilter))
                                {
                                    file.Move(childFilter);
                                }
                            }
    
                            if (((dynamic)childFilter.Items).Count == 0)
                            {
                                childFilter.Remove();
                            }
                        }
                    }
                }
            }
        }
    }

    *.filtersはXMLファイルなので、即時反映でなくてもいいならXMLファイル編集で振り分けでも可能ですね


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク 星 睦美 2016年4月20日 6:42
    2016年2月22日 15:12