첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
다운로드

▶ DragHelper.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 드래그 헬퍼
    /// </summary>
    public class DragHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 공통 컨트롤들 초기화 하기 - InitCommonControls()

        /// <summary>
        /// 공통 컨트롤들 초기화 하기
        /// </summary>
        /// <returns></returns>
        [DllImport("comctl32.dll")]
        public static extern bool InitCommonControls();

        #endregion
        #region 이미지 리스트 드래그 시작하기 - ImageList_BeginDrag(imageListHandle, imageIndex, hotSpotX, hotSpotY)

        /// <summary>
        /// 이미지 리스트 드래그 시작하기
        /// </summary>
        /// <param name="imageListHandle">이미지 리스트 핸들</param>
        /// <param name="imageIndex">이미지 인덱스</param>
        /// <param name="hotSpotX">핫 스팟 X 좌표</param>
        /// <param name="hotSpotY">핫 스팟 Y 좌표</param>
        /// <returns>처리 결과</returns>
        [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
        public static extern bool ImageList_BeginDrag(IntPtr imageListHandle, int imageIndex, int hotSpotX, int hotSpotY);

        #endregion
        #region 이미지 리스트 드래그 진입시 처리하기 - ImageList_DragEnter(lockWindowHandle, x, y)

        /// <summary>
        /// 이미지 리스트 드래그 진입시 처리하기
        /// </summary>
        /// <param name="lockWindowHandle">잠금 윈도우 핸들</param>
        /// <param name="x">X 좌표</param>
        /// <param name="y">Y 좌표</param>
        /// <returns>처리 결과</returns>
        [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
        public static extern bool ImageList_DragEnter(IntPtr lockWindowHandle, int x, int y);

        #endregion
        #region 이미지 리스트 드래그 이동시 처리하기 - ImageList_DragMove(x, y)

        /// <summary>
        /// 이미지 리스트 드래그 이동시 처리하기
        /// </summary>
        /// <param name="x">X 좌표</param>
        /// <param name="y">Y 좌표</param>
        /// <returns>처리 결과</returns>
        [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
        public static extern bool ImageList_DragMove(int x, int y);

        #endregion
        #region 이미지 리스트 드래그 이탈시 처리하기 - ImageList_DragLeave(lockWindowHandle)

        /// <summary>
        /// 이미지 리스트 드래그 이탈시 처리하기
        /// </summary>
        /// <param name="lockWindowHandle">잠금 윈도우 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
        public static extern bool ImageList_DragLeave(IntPtr lockWindowHandle);

        #endregion
        #region 이미지 리스트 드래그 종료하기 - ImageList_EndDrag()

        /// <summary>
        /// 이미지 리스트 드래그 종료하기
        /// </summary>
        [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
        public static extern void ImageList_EndDrag();

        #endregion
        #region 이미지 리스트 드래그 이미지 표시하기 - ImageList_DragShowNolock(imageVisbile)

        /// <summary>
        /// 이미지 리스트 드래그 이미지 표시하기
        /// </summary>
        /// <param name="imageVisbile">이미지 표시 여부</param>
        /// <returns>처리 결과</returns>
        [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
        public static extern bool ImageList_DragShowNolock(bool imageVisbile);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Static

        #region 생성자 - DragHelper()

        /// <summary>
        /// 생성자
        /// </summary>
        static DragHelper()
        {
            InitCommonControls();
        }

        #endregion
    }
}

 

728x90

 

▶ MainForm.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Class
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 메시지 헬퍼 - MessageHelper

        /// <summary>
        /// 메시지 헬퍼
        /// </summary>
        private class MessageHelper
        {
            public const string 사용중인메뉴는추가할수없습니다                                     = "사용중인 메뉴는 추가할 수 없습니다.";
            public const string 드래그메뉴가그룹메뉴가아니기때문에추가할수없습니다                 = "드래그 메뉴가 그룹 메뉴가 아니기 때문에 추가할 수 없습니다.";
            public const string 타겟노드가그룹메뉴가아니기때문에추가할수없습니다                   = "타겟 노드가 그룹 메뉴가 아니기 때문에 추가할 수 없습니다.";
            public const string 드래그노드와타겟노드가동일한노드이기때문에이동할수없습니다         = "드래그 노드와 타겟 노드가 동일한 노드이기 때문에 이동할 수 없습니다.";
            public const string 드래그노드가타겟노드의조상노드이기때문에이동할수없습니다           = "드래그 노드가 타겟 노드의 조상 노드이기 때문에 이동할 수 없습니다.";
            public const string 드래그노드의자식노드들이모두그룹메뉴가아니기때문에이동할수없습니다 = "드래그 노드의 자식 노드들이 모두 그룹 메뉴가 아니기 때문에 이동할 수 없습니다.";
            public const string 드래그노드가그룹메뉴가아니기때문에이동할수없습니다                 = "드래그 노드가 그룹 메뉴가 아니기 때문에 이동할 수 없습니다.";
            public const string 드래그데이터타입이해당되지않습니다                                 = "드래그 데이터 타입이 해당되지 않습니다.";
            public const string 타겟노드가그룹메뉴가아니기때문에이동할수없습니다                   = "타겟 노드가 그룹 메뉴가 아니기 때문에 이동할 수 없습니다.";
            public const string 그룹메뉴는추가할수없습니다                                         = "그룹 메뉴는 추가할 수 없습니다.";
            public const string 하위메뉴를추가할수없습니다                                         = "하위 메뉴를 추가할 수 없습니다.";
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 메시지 보내기 - SendMessage(windowHandle, message, wordParameter, longParameter)

        /// <summary>
        /// 메시지 보내기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="message">메시지</param>
        /// <param name="wordParameter">매개 변수 1</param>
        /// <param name="longParameter">매개 변수 2</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr windowHandle, uint message, IntPtr wordParameter, IntPtr longParameter);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 메뉴 정보 딕셔너리
        /// </summary>
        private Dictionary<string, MenuInfo> menuInfoDictionary = new Dictionary<string, MenuInfo>();

        /// <summary>
        /// 그리드 히트 정보
        /// </summary>
        private GridHitInfo gridHitInfo = null;

        /// <summary>
        /// 메뉴 모드
        /// </summary>
        private MenuMode menuMode = MenuMode.MainMenu;

        /// <summary>
        /// 트리 이미지 리스트
        /// </summary>
        private ImageList treeImageList;

        /// <summary>
        /// 드래그 이미지 리스트
        /// </summary>
        private ImageList dragImageList;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();


            #region 트리 이미지 리스트를 설정한다.

            this.treeImageList = new ImageList();

            this.treeImageList.ColorDepth       = ColorDepth.Depth8Bit;
            this.treeImageList.ImageSize        = new Size(16, 16);
            this.treeImageList.TransparentColor = Color.Transparent;

            this.treeImageList.Images.Add(Image.FromFile("Images\\menuGroup.png"  ));
            this.treeImageList.Images.Add(Image.FromFile("Images\\menuControl.png"));
            this.treeImageList.Images.Add(Image.FromFile("Images\\menuProcess.png"));
            this.treeImageList.Images.Add(Image.FromFile("Images\\menuAction.png" ));

            #endregion
            #region 드래그 이미지 리스트를 설정한다.

            this.dragImageList = new ImageList();

            this.dragImageList.ColorDepth       = ColorDepth.Depth32Bit;
            this.dragImageList.ImageSize        = new Size(16, 16);
            this.dragImageList.TransparentColor = Color.Transparent;

            #endregion

            #region 메뉴 모드 콤보 박스를 설정한다.

            this.menuModeComboBox.DropDownStyle = ComboBoxStyle.DropDownList;

            this.menuModeComboBox.Items.Add(MenuMode.MainMenu);
            this.menuModeComboBox.Items.Add(MenuMode.Toolbox);

            this.menuModeComboBox.SelectedIndex = 0;

            this.menuModeComboBox.SelectedIndexChanged += menuModeComboBox_SelectedIndexChanged;

            #endregion
            #region 트리 뷰를 설정한다.

            this.treeView.AllowDrop     = true;
            this.treeView.ItemHeight    = 20;
            this.treeView.ImageList     = this.treeImageList;
            this.treeView.HideSelection = false;

            this.treeView.ItemDrag     += treeView_ItemDrag;
            this.treeView.GiveFeedback += treeView_GiveFeedback;
            this.treeView.DragEnter    += treeView_DragEnter;
            this.treeView.DragOver     += treeView_DragOver;
            this.treeView.DragDrop     += treeView_DragDrop;
            this.treeView.DragLeave    += treeView_DragLeave;
            this.treeView.AfterSelect  += treeView_AfterSelect;

            #endregion
            #region 그리드 컨트롤을 설정한다.

            this.gridControl.DataSource = CreateCollection();

            #endregion
            #region 그리드 뷰를 설정한다.

            this.gridView.Appearance.Row.Font                        = new Font("나눔고딕코딩", 12f);
            this.gridView.OptionsBehavior.Editable                   = false;
            this.gridView.OptionsCustomization.AllowGroup            = false;
            this.gridView.OptionsCustomization.AllowColumnMoving     = false;
            this.gridView.OptionsCustomization.AllowFilter           = false;
            this.gridView.OptionsCustomization.AllowGroup            = false;
            this.gridView.OptionsCustomization.AllowQuickHideColumns = false;
            this.gridView.OptionsSelection.MultiSelectMode           = GridMultiSelectMode.RowSelect;
            this.gridView.OptionsSelection.MultiSelect               = false;
            this.gridView.OptionsView.ColumnAutoWidth                = false;
            this.gridView.OptionsView.ShowGroupPanel                 = false;

            this.gridView.BestFitColumns();

            for(int i = 0; i < this.gridView.Columns.Count; i++)
            {
                this.gridView.Columns[i].AppearanceHeader.Font = new Font("나눔고딕코딩", 12f);
            }

            this.gridView.MouseDown += gridView_MouseDown;
            this.gridView.MouseMove += gridView_MouseMove;

            #endregion
            #region 노드 삭제 버튼을 설정한다.

            this.deleteNodeButton.Click += deleteNodeButton_Click;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 메뉴 모드 콤보 박스 선택 인덱스 변경시 처리하기 - menuModeComboBox_SelectedIndexChanged(sender, e)

        /// <summary>
        /// 메뉴 모드 콤보 박스 선택 인덱스 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void menuModeComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            ClearData(this.treeView);

            switch(menuModeComboBox.SelectedIndex)
            {
                case 0 : this.menuMode = MenuMode.MainMenu; break;
                case 1 : this.menuMode = MenuMode.Toolbox;  break;
            }
        }

        #endregion

        #region 그리드 뷰 마우스 DOWN 처리하기 - gridView_MouseDown(sender, e)

        /// <summary>
        /// 그리드 뷰 마우스 DOWN 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void gridView_MouseDown(object sender, MouseEventArgs e)
        {
            this.gridHitInfo = this.gridView.CalcHitInfo(e.Location);

            if(this.gridHitInfo.RowHandle < 0)
            {
                this.gridHitInfo = null;
            }
        }

        #endregion
        #region 그리드 뷰 마우스 이동시 처리하기 - gridView_MouseMove(sender, e)

        /// <summary>
        /// 그리드 뷰 마우스 이동시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void gridView_MouseMove(object sender, MouseEventArgs e)
        {
            if(this.gridHitInfo == null)
            {
                return;
            }

            if(e.Button != MouseButtons.Left)
            {
                return;
            }

            Rectangle dragRectangle = new Rectangle
            (
                new Point
                (
                    this.gridHitInfo.HitPoint.X - SystemInformation.DragSize.Width  / 2,
                    this.gridHitInfo.HitPoint.Y - SystemInformation.DragSize.Height / 2
                ),
                SystemInformation.DragSize
            );

            if(!dragRectangle.Contains(new Point(e.X, e.Y)))
            {
                if(this.gridHitInfo.InRow)
                {
                    int[] selectedRowHandleArray = this.gridView.GetSelectedRows();

                    this.gridControl.DoDragDrop(selectedRowHandleArray, DragDropEffects.Copy);
                }
            }
        }

        #endregion

        #region 트리 뷰 항목 드래그시 처리하기 - treeView_ItemDrag(sender, e)

        /// <summary>
        /// 트리 뷰 항목 드래그시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void treeView_ItemDrag(object sender, ItemDragEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                TreeView treeView = sender as TreeView;
                TreeNode dragNode = e.Item as TreeNode;

                treeView.SelectedNode = dragNode;

                this.dragImageList.Images.Clear();

                this.dragImageList.ImageSize = new Size(dragNode.Bounds.Width + treeView.Indent, dragNode.Bounds.Height);

                Bitmap bitmap = new Bitmap(dragNode.Bounds.Width + treeView.Indent, dragNode.Bounds.Height);

                Graphics graphics = Graphics.FromImage(bitmap);

                graphics.DrawImage(this.treeImageList.Images[GetImageIndex(dragNode.Tag as MenuInfo)], 0, 0);

                graphics.DrawString(dragNode.Text, treeView.Font, new SolidBrush(treeView.ForeColor), (float)treeView.Indent, 1.0f);

                this.dragImageList.Images.Add(bitmap);

                Point mousePoint = treeView.PointToClient(Control.MousePosition);

                int hotSpotX = mousePoint.X + treeView.Indent - dragNode.Bounds.Left;
                int hotSpotY = mousePoint.Y - dragNode.Bounds.Top;

                if(DragHelper.ImageList_BeginDrag(this.dragImageList.Handle, 0, hotSpotX, hotSpotY))
                {
                    treeView.DoDragDrop(e.Item, DragDropEffects.Move);

                    DragHelper.ImageList_EndDrag();
                }
            }
        }

        #endregion
        #region 트리 뷰 피드백 주는 경우 처리하기 - treeView_GiveFeedback(sender, e)

        /// <summary>
        /// 트리 뷰 피드백 주는 경우 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void treeView_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            TreeView treeView = sender as TreeView;

            if(e.Effect == DragDropEffects.Copy)
            {
                e.UseDefaultCursors = false;

                treeView.Cursor = Cursors.Default;
            }
            else if(e.Effect == DragDropEffects.Move)
            {
                e.UseDefaultCursors = true;
            }
        }

        #endregion
        #region 트리 뷰 드래그 진입시 처리하기 - treeView_DragEnter(sender, e)

        /// <summary>
        /// 트리 뷰 드래그 진입시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void treeView_DragEnter(object sender, DragEventArgs e)
        {
            TreeView treeView = sender as TreeView;

            DragHelper.ImageList_DragEnter(treeView.Handle, e.X - treeView.Left, e.Y - treeView.Top);
        }

        #endregion
        #region 트리 뷰 드래그 OVER 처리하기 - treeView_DragOver(sender, e)

        /// <summary>
        /// 트리 뷰 드래그 OVER 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void treeView_DragOver(object sender, DragEventArgs e)
        {
            TreeView treeView = sender as TreeView;

            ScrollControl(treeView);

            if(this.menuMode == MenuMode.MainMenu) // 메뉴 모드가 메인 메뉴인 경우 처리한다.
            {
                if(e.Data.GetDataPresent(typeof(int[])))
                {
                    #region 그리드 뷰에서 드래그한 경우 처리한다.

                    int[]    dragRowHandleArray = (int[])(e.Data.GetData(typeof(int[])));
                    MenuInfo dragMenuInfo       = this.gridView.GetRow(dragRowHandleArray[0]) as MenuInfo;

                    if(this.menuInfoDictionary.ContainsKey(dragMenuInfo.ID)) // 메뉴 정보 딕셔너리에 드래그 메뉴 정보가 있는 경우 처리한다.
                    {
                        e.Effect = System.Windows.Forms.DragDropEffects.None;

                        ShowMessage(MessageHelper.사용중인메뉴는추가할수없습니다);
                    }
                    else // 메뉴 정보 딕셔너리에 드래그 메뉴 정보가 없는 경우 처리한다.
                    {
                        Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                        TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                        TreeNode            targetNode          = treeViewHitTestInfo.Node;
                        MenuInfo            targetMenuInfo      = targetNode?.Tag as MenuInfo;
                        bool                pressCTRLKey        = (e.KeyState & 8) == 8;

                        if(pressCTRLKey) // CTRL 키를 누른 경우 처리한다.
                        {
                            if(targetNode == null)
                            {
                                #region 타겟 노드가 없는 경우 처리한다.

                                if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.Copy;

                                    ShowMessage(string.Empty);
                                }
                                else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.None;

                                    ShowMessage(MessageHelper.드래그메뉴가그룹메뉴가아니기때문에추가할수없습니다);
                                }

                                #endregion
                            }
                            else if(targetNode.Level == 0 || targetNode.Level == 1)
                            {
                                #region 타겟 노드 레벨이 1, 2계층인 경우 처리한다.

                                if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.Copy;

                                    ShowMessage(string.Empty);
                                }
                                else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.None;

                                    ShowMessage(MessageHelper.드래그메뉴가그룹메뉴가아니기때문에추가할수없습니다);
                                }

                                #endregion
                            }
                            else
                            {
                                #region 타겟 노드 레벨이 3계층 이상인 경우 처리한다.

                                e.Effect = DragDropEffects.Copy;

                                ShowMessage(string.Empty);

                                #endregion
                            }
                        }
                        else // CTRL 키를 누르지 않은 경우 처리한다.
                        {
                            if(targetNode == null || targetNode.Level == 0)
                            {
                                #region 타겟 노드가 없거나 타겟 노드 레벨이 1계층인 경우 처리한다.

                                if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.Copy;

                                    ShowMessage(string.Empty);
                                }
                                else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.None;

                                    ShowMessage(MessageHelper.드래그메뉴가그룹메뉴가아니기때문에추가할수없습니다);
                                }

                                #endregion
                            }
                            else
                            {
                                #region 타겟 노드 레벨이 2계층 이상인 경우 처리한다.

                                if(targetMenuInfo.MenuType == "G") // 타겟 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.Copy;

                                    ShowMessage(string.Empty);
                                }
                                else // 타겟 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.None;

                                    ShowMessage(MessageHelper.타겟노드가그룹메뉴가아니기때문에추가할수없습니다);
                                }

                                #endregion
                            }
                        }
                    }

                    #endregion
                }
                else if(e.Data.GetDataPresent(typeof(TreeNode)))
                {
                    Point formPoint = PointToClient(new Point(e.X, e.Y));

                    DragHelper.ImageList_DragMove(formPoint.X - treeView.Left, formPoint.Y - treeView.Top);

                    #region 트리 뷰 내부에서 드래그한 경우 처리한다.

                    Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                    TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                    TreeNode            targetNode          = treeViewHitTestInfo.Node;
                    MenuInfo            targetMenuInfo      = targetNode?.Tag as MenuInfo;
                    TreeNode            dragNode            = e.Data.GetData(typeof(TreeNode)) as TreeNode;
                    MenuInfo            dragMenuInfo        = dragNode.Tag as MenuInfo;
                    bool                pressCTRLKey        = (e.KeyState & 8) == 8;

                    if(dragNode == targetNode) // 드래그 노드와 타겟 노드가 동일한 경우 처리한다.
                    {
                        e.Effect = DragDropEffects.None;

                        ShowMessage(MessageHelper.드래그노드와타겟노드가동일한노드이기때문에이동할수없습니다);
                    }
                    else // 드래그 노드와 타겟 노드가 동일하지 않은 경우 처리한다.
                    {
                        if(IsAncestorNode(dragNode, targetNode)) // 드래그 노드가 타겟 노드의 조상 노드인 경우 처리한다.
                        {
                            e.Effect = DragDropEffects.None;

                            ShowMessage(MessageHelper.드래그노드가타겟노드의조상노드이기때문에이동할수없습니다);
                        }
                        else // 드래그 노드가 타겟 노드의 조상 노드가 아닌 경우 처리한다.
                        {
                            if(pressCTRLKey) // CTRL 키를 누른 경우 처리한다.
                            {
                                if(targetNode == null)
                                {
                                    #region 타겟 노드가 없는 경우 처리한다.

                                    if(dragNode.Level == 0) // 드래그 노드 레벨이 1계층인 경우 처리한다.
                                    {
                                        e.Effect = DragDropEffects.Move;

                                        ShowMessage(string.Empty);
                                    }
                                    else if(dragNode.Level == 1) // 드래그 노드 레벨이 2계층인 경우 처리한다.
                                    {
                                        if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.Move;

                                            ShowMessage(string.Empty);
                                        }
                                        else // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들이 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드의자식노드들이모두그룹메뉴가아니기때문에이동할수없습니다);
                                        }
                                    }
                                    else // 드래그 노드 레벨이 3계층 이상인 경우 처리한다.
                                    {
                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                            {
                                                e.Effect = DragDropEffects.Move;

                                                ShowMessage(string.Empty);
                                            }
                                            else // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들이 아닌 경우 처리한다.
                                            {
                                                e.Effect = DragDropEffects.None;

                                                ShowMessage(MessageHelper.드래그노드의자식노드들이모두그룹메뉴가아니기때문에이동할수없습니다);
                                            }
                                        }
                                        else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드가그룹메뉴가아니기때문에이동할수없습니다);
                                        }
                                    }

                                    #endregion
                                }
                                else if(targetNode.Level == 0)
                                {
                                    #region 타겟 노드 레벨이 1계층인 경우 처리한다.

                                    if(dragNode.Level == 0) // 드래그 노드 레벨이 1계층인 경우 처리한다.
                                    {
                                        e.Effect = DragDropEffects.Move;

                                        ShowMessage(string.Empty);
                                    }
                                    else if(dragNode.Level == 1) // 드래그 노드 레벨이 2계층인 경우 처리한다.
                                    {
                                        if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.Move;

                                            ShowMessage(string.Empty);
                                        }
                                        else // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들이 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드의자식노드들이모두그룹메뉴가아니기때문에이동할수없습니다);
                                        }
                                    }
                                    else // 드래그 노드 레벨이 3계층 이상인 경우 처리한다.
                                    {
                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                            {
                                                e.Effect = DragDropEffects.Move;

                                                ShowMessage(string.Empty);
                                            }
                                            else // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들이 아닌 경우 처리한다.
                                            {
                                                e.Effect = DragDropEffects.None;

                                                ShowMessage(MessageHelper.드래그노드의자식노드들이모두그룹메뉴가아니기때문에이동할수없습니다);
                                            }
                                        }
                                        else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드가그룹메뉴가아니기때문에이동할수없습니다);
                                        }
                                    }

                                    #endregion
                                }
                                else if(targetNode.Level == 1)
                                {
                                    #region 타겟 노드 레벨이 2계층인 경우 처리한다.

                                    if(dragNode.Level == 0 || dragNode.Level == 1)
                                    {
                                        #region 드래그 노드 레벨이 1, 2계층인 경우 처리한다.

                                        e.Effect = DragDropEffects.Move;

                                        ShowMessage(string.Empty);

                                        #endregion
                                    }
                                    else
                                    {
                                        #region 드래그 노드 레벨이 3계층 이상인 경우 처리한다.

                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.Move;

                                            ShowMessage(string.Empty);
                                        }
                                        else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드가그룹메뉴가아니기때문에이동할수없습니다);
                                        }

                                        #endregion
                                    }

                                    #endregion
                                }
                                else
                                {
                                    #region 타겟 노드 레벨이 3계층 이상인 경우 처리한다.

                                    e.Effect = DragDropEffects.Move;

                                    ShowMessage(string.Empty);

                                    #endregion
                                }
                            }
                            else // CTRL 키를 누르지 않은 경우 처리한다.
                            {
                                if(targetNode == null)
                                {
                                    #region 타겟 노드가 없는 경우 처리한다.

                                    if(dragNode.Level == 0)
                                    {
                                        #region 드래그 노드 레벨이 1계층인 경우 처리한다.

                                        e.Effect = DragDropEffects.Move;

                                        ShowMessage(string.Empty);

                                        #endregion
                                    }
                                    else if(dragNode.Level == 1)
                                    {
                                        #region 드래그 노드 레벨이 2계층인 경우 처리한다.

                                        if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.Move;

                                            ShowMessage(string.Empty);
                                        }
                                        else // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들이 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드의자식노드들이모두그룹메뉴가아니기때문에이동할수없습니다);
                                        }

                                        #endregion
                                    }
                                    else
                                    {
                                        #region 드래그 노드 레벨이 3계층 이상인 경우 처리한다.

                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                            {
                                                e.Effect = DragDropEffects.Move;

                                                ShowMessage(string.Empty);
                                            }
                                            else // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들이 아닌 경우 처리한다.
                                            {
                                                e.Effect = DragDropEffects.None;

                                                ShowMessage(MessageHelper.드래그노드의자식노드들이모두그룹메뉴가아니기때문에이동할수없습니다);
                                            }
                                        }
                                        else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드가그룹메뉴가아니기때문에이동할수없습니다);
                                        }

                                        #endregion
                                    }

                                    #endregion
                                }
                                else if(targetNode.Level == 0)
                                {
                                    #region 타겟 노드 레벨이 1계층인 경우 처리한다.

                                    if(dragNode.Level == 0 || dragNode.Level == 1)
                                    {
                                        #region 드래그 노드 레벨이 1, 2계층인 경우 처리한다.

                                        e.Effect = DragDropEffects.Move;

                                        ShowMessage(string.Empty);

                                        #endregion
                                    }
                                    else
                                    {
                                        #region 드래그 노드 레벨이 3계층 이상인 경우 처리한다.

                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.Move;

                                            ShowMessage(string.Empty);
                                        }
                                        else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                        {
                                            e.Effect = DragDropEffects.None;

                                            ShowMessage(MessageHelper.드래그노드가그룹메뉴가아니기때문에이동할수없습니다);
                                        }

                                        #endregion
                                    }

                                    #endregion
                                }
                                else if(targetNode.Level == 1)
                                {
                                    #region 타겟 노드 레벨이 2계층인 경우 처리한다.

                                    e.Effect = DragDropEffects.Move;

                                    ShowMessage(string.Empty);

                                    #endregion
                                }
                                else
                                {
                                    #region 타겟 노드 레벨이 3계층 이상인 경우 처리한다.

                                    if(targetMenuInfo.MenuType == "G") // 타겟 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                    {
                                        e.Effect = DragDropEffects.Move;

                                        ShowMessage(string.Empty);
                                    }
                                    else // 타겟 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                    {
                                        e.Effect = DragDropEffects.None;

                                        ShowMessage(MessageHelper.타겟노드가그룹메뉴가아니기때문에이동할수없습니다);
                                    }

                                    #endregion
                                }
                            }
                        }
                    }

                    #endregion
                }
                else
                {
                    e.Effect = DragDropEffects.None;

                    ShowMessage(MessageHelper.드래그데이터타입이해당되지않습니다);
                }
            }
            else if(this.menuMode == MenuMode.Toolbox) // 메뉴 모드가 툴 박스인 경우 처리한다.
            {
                if(e.Data.GetDataPresent(typeof(int[])))
                {
                    #region 그리드 뷰에서 드래그한 경우 처리한다.

                    int[]    dragRowHandleArray = (int[])(e.Data.GetData(typeof(int[])));
                    MenuInfo dragMenuInfo       = this.gridView.GetRow(dragRowHandleArray[0]) as MenuInfo;

                    if(this.menuInfoDictionary.ContainsKey(dragMenuInfo.ID)) // 메뉴 정보 딕셔너리에 드래그 메뉴 정보가 있는 경우 처리한다.
                    {
                        e.Effect = DragDropEffects.None;

                        ShowMessage(MessageHelper.사용중인메뉴는추가할수없습니다);
                    }
                    else
                    {
                        Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                        TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                        TreeNode            targetNode          = treeViewHitTestInfo.Node;
                        bool                pressCTRLKey        = (e.KeyState & 8) == 8;

                        if(pressCTRLKey) // CTRL 키를 누른 경우 처리한다.
                        {
                            if(targetNode == null)
                            {
                                #region 타겟 노드가 없는 경우 처리한다.

                                if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.None;

                                    ShowMessage(MessageHelper.그룹메뉴는추가할수없습니다);
                                }
                                else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.Copy;

                                    ShowMessage(string.Empty);
                                }

                                #endregion
                            }
                            else
                            {
                                #region 타겟 노드가 있는 경우 처리한다.

                                if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.None;

                                    ShowMessage(MessageHelper.그룹메뉴는추가할수없습니다);
                                }
                                else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.Copy;

                                    ShowMessage(string.Empty);
                                }

                                #endregion
                            }
                        }
                        else // CTRL 키를 누르지 않은 경우 처리한다.
                        {
                            if(targetNode == null)
                            {
                                #region 타겟 노드가 없는 경우 처리한다.

                                if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                {
                                    e.Effect  = DragDropEffects.None;

                                    ShowMessage(MessageHelper.그룹메뉴는추가할수없습니다);
                                }
                                else // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                                {
                                    e.Effect = DragDropEffects.Copy;

                                    ShowMessage(string.Empty);
                                }

                                #endregion
                            }
                            else
                            {
                                #region 타겟 노드가 있는 경우 처리한다.

                                e.Effect = DragDropEffects.None;

                                ShowMessage(MessageHelper.하위메뉴를추가할수없습니다);

                                #endregion
                            }
                        }
                    }

                    #endregion
                }
                else if(e.Data.GetDataPresent(typeof(TreeNode)))
                {
                    Point formPoint = PointToClient(new Point(e.X, e.Y));

                    DragHelper.ImageList_DragMove(formPoint.X - treeView.Left, formPoint.Y - treeView.Top);
                    #region 트리 뷰 내부에서 드래그한 경우 처리한다.

                    Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                    TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                    TreeNode            targetNode          = treeViewHitTestInfo.Node;
                    MenuInfo            targetMenuInfo      = targetNode?.Tag as MenuInfo;
                    TreeNode            dragNode            = e.Data.GetData(typeof(TreeNode)) as TreeNode;
                    MenuInfo            dragMenuInfo        = dragNode.Tag as MenuInfo;
                    bool                pressCTRLKey        = (e.KeyState & 8) == 8;

                    if(dragNode == targetNode) // 드래그 노드와 타겟 노드가 동일한 경우 처리한다.
                    {
                        e.Effect = DragDropEffects.None;

                        ShowMessage(MessageHelper.드래그노드와타겟노드가동일한노드이기때문에이동할수없습니다);
                    }
                    else // 드래그 노드와 타겟 노드가 동일하지 않은 경우 처리한다.
                    {
                        if(pressCTRLKey) // CTRL 키를 누른 경우 처리한다.
                        {
                            e.Effect = DragDropEffects.Move;

                            ShowMessage(string.Empty);
                        }
                        else // CTRL 키를 누르지 않은 경우 처리한다.
                        {
                            if(targetNode == null)
                            {
                                #region 타겟 노드가 없는 경우 처리한다.

                                e.Effect = DragDropEffects.Move;

                                ShowMessage(string.Empty);

                                #endregion
                            }
                            else
                            {
                                #region 타겟 노드가 있는 경우 처리한다.

                                e.Effect = DragDropEffects.None;

                                ShowMessage(MessageHelper.하위메뉴를추가할수없습니다);

                                #endregion
                            }
                        }
                    }

                    #endregion
                }
                else
                {
                    e.Effect = DragDropEffects.None;

                    ShowMessage(MessageHelper.드래그데이터타입이해당되지않습니다);
                }
            }
        }
        
        #endregion
        #region 트리 뷰 드래그 DROP 처리하기 - treeView_DragDrop(sender, e)

        /// <summary>
        /// 트리 뷰 드래그 DROP 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void treeView_DragDrop(object sender, DragEventArgs e)
        {
            TreeView treeView = sender as TreeView;

            DragHelper.ImageList_DragLeave(treeView.Handle);

            if(this.menuMode == MenuMode.MainMenu) // 메뉴 모드가 메인 메뉴인 경우 처리한다.
            {
                if(e.Data.GetDataPresent(typeof(int[])))
                {
                    #region 그리드 뷰에서 드래그한 경우 처리한다.

                    bool                pressCTRLKey        = (e.KeyState & 8) == 8;
                    int[]               dragRowHandleArray  = (int[])(e.Data.GetData(typeof(int[])));
                    MenuInfo            dragMenuInfo        = this.gridView.GetRow(dragRowHandleArray[0]) as MenuInfo;
                    Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                    TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                    TreeNode            targetNode          = treeViewHitTestInfo.Node;
                    MenuInfo            targetMenuInfo      = targetNode?.Tag as MenuInfo;

                    if(pressCTRLKey)
                    {
                        #region CTRL 키를 누른 경우 처리한다.

                        if(targetNode == null) // 타겟 노드가 없는 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                            {
                                InsertTreeNode(treeView.Nodes, 0, dragMenuInfo);
                            }
                        }
                        else if(targetNode.Level == 0) // 타겟 노드 레벨이 1계층인 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                            {
                                InsertTreeNode(treeView.Nodes, targetNode.Index, dragMenuInfo);
                            }
                        }
                        else if(targetNode.Level == 1) // 타겟 노드 레벨이 2계층인 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                            {
                                InsertTreeNode(targetNode.Parent.Nodes, targetNode.Index, dragMenuInfo);
                            }
                        }
                        else // 타겟 노드 레벨이 3계층 이상인 경우 처리한다.
                        {
                            InsertTreeNode(targetNode.Parent.Nodes, targetNode.Index, dragMenuInfo);
                        }

                        #endregion
                    }
                    else
                    {
                        #region CTRL 키를 누르지 않은 경우 처리한다.

                        if(targetNode == null) // 타겟 노드가 없는 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                            {
                                AddTreeNode(treeView.Nodes, dragMenuInfo);
                            }
                        }
                        else if(targetNode.Level == 0) // 타겟 노드 레벨이 1계층인 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                            {
                                AddTreeNode(targetNode.Nodes, dragMenuInfo);
                            }
                        }
                        else // 타겟 노드 레벨이 2계층 이상인 경우 처리한다.
                        {
                            if(targetMenuInfo.MenuType == "G")
                            {
                                AddTreeNode(targetNode.Nodes, dragMenuInfo);
                            }
                        }

                        #endregion
                    }

                    #endregion
                }
                else if(e.Data.GetDataPresent(typeof(TreeNode)))
                {
                    #region 트리 뷰 내에서 드래그한 경우 처리한다.

                    bool                pressCTRLKey        = (e.KeyState & 8) == 8;
                    TreeNode            dragNode            = e.Data.GetData(typeof(TreeNode)) as TreeNode;
                    MenuInfo            dragMenuInfo        = dragNode.Tag as MenuInfo;
                    Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                    TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                    TreeNode            targetNode          = treeViewHitTestInfo.Node;
                    MenuInfo            targetMenuInfo      = targetNode?.Tag as MenuInfo;

                    if(dragNode != targetNode) // 드래그 노드와 타겟 노드가 동일하지 않은 경우 처리한다.
                    {
                        if(!IsAncestorNode(dragNode, targetNode)) // 드래그 노드가 타겟 노드의 조상 노드인 경우 처리한다.
                        {
                            if(pressCTRLKey)
                            {
                                #region CTRL 키를 누른 경우 처리한다.

                                if(targetNode == null) // 타겟 노드가 없는 경우 처리한다.
                                {
                                    if(dragNode.Level == 0) // 드래그 노드 레벨이 1계층인 경우 처리한다.
                                    {
                                        MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                    }
                                    else if(dragNode.Level == 1) // 드래그 노드 레벨이 2계층인 경우 처리한다.
                                    {
                                        if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                        {
                                            MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                        }
                                    }
                                    else // 드래그 노드 레벨이 3계층 이상인 경우 처리한다.
                                    {
                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                            {
                                                MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                            }
                                        }
                                    }
                                }
                                else if(targetNode.Level == 0) // 타겟 노드 레벨이 1계층인 경우 처리한다.
                                {
                                    if(dragNode.Level == 0) // 드래그 노드 레벨이 1계층인 경우 처리한다.
                                    {
                                        MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                    }
                                    else if(dragNode.Level == 1) // 드래그 노드 레벨이 2계층인 경우 처리한다.
                                    {
                                        if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모든 그룹 메뉴들인 경우 처리한다.
                                        {
                                            MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                        }
                                    }
                                    else // 드래그 노드 레벨이 3계층 이상인 경우 처리한다.
                                    {
                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모든 그룹 메뉴들인 경우 처리한다.
                                            {
                                                MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                            }
                                        }
                                    }
                                }
                                else // 타겟 노드 레벨이 2계층 이상인 경우 처리한다.
                                {
                                    MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                }

                                #endregion
                            }
                            else
                            {
                                #region CTRL 키를 누르지 않은 경우 처리한다.

                                if(targetNode == null) // 타겟 노드가 없는 경우 처리한다.
                                {
                                    if(dragNode.Level == 0) // 드래그 노드 레벨이 1계층인 경우 처리한다.
                                    {
                                        MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                    }
                                    else if(dragNode.Level == 1) // 드래그 노드 레벨이 2계층인 경우 처리한다.
                                    {
                                        if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                        {
                                            MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                        }
                                    }
                                    else // 드래그 노드 레벨이 3계층 이상인 경우 처리한다.
                                    {
                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            if(HasChildNodesOnlyGroupMenus(dragNode)) // 드래그 노드의 자식 노드들이 모두 그룹 메뉴들인 경우 처리한다.
                                            {
                                                MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                            }
                                        }
                                    }
                                }
                                else if(targetNode.Level == 0) // 타겟 노드 레벨이 1계층인 경우 처리한다.
                                {
                                    if(dragNode.Level == 0 || dragNode.Level == 1) // 드래그 노드 레벨이 1, 2계층인 경우 처리한다.
                                    {
                                        MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                    }
                                    else // 드래그 노드 레벨이 3계층 이상인 경우 처리한다.
                                    {
                                        if(dragMenuInfo.MenuType == "G") // 드래그 메뉴 정보가 그룹 메뉴인 경우 처리한다.
                                        {
                                            MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                        }
                                    }
                                }
                                else if(targetNode.Level == 1) // 타겟 노드 레벨이 2계층인 경우 처리한다.
                                {
                                    MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                }
                                else // 타겟 노드 레벨이 3계층 이상인 경우 처리한다.
                                {
                                    if(targetMenuInfo.MenuType == "G")
                                    {
                                        MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                                    }
                                }

                                #endregion
                            }
                        }
                    }

                    #endregion
                }
            }
            else if(this.menuMode == MenuMode.Toolbox) // 메뉴 모드가 툴 박스인 경우 처리한다.
            {
                if(e.Data.GetDataPresent(typeof(int[])))
                {
                    #region 그리드 뷰에서 드래그한 경우 처리한다.

                    bool                pressCTRLKey        = (e.KeyState & 8) == 8;
                    int[]               dragRowHandleArray  = (int[])(e.Data.GetData(typeof(int[])));
                    MenuInfo            dragMenuInfo        = this.gridView.GetRow(dragRowHandleArray[0]) as MenuInfo;
                    Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                    TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                    TreeNode            targetNode          = treeViewHitTestInfo.Node;

                    if(pressCTRLKey)
                    {
                        #region CTRL 키를 누른 경우 처리한다.

                        if(targetNode == null) // 타겟 노드가 없는 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType != "G") // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                            {
                                InsertTreeNode(treeView.Nodes, 0, dragMenuInfo);
                            }
                        }
                        else // 타겟 노드가 있는 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType != "G") // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                            {
                                InsertTreeNode(treeView.Nodes, targetNode.Index, dragMenuInfo);
                            }
                        }

                        #endregion
                    }
                    else
                    {
                        #region CTRL 키를 누르지 않은 경우 처리한다.

                        if(targetNode == null) // 타겟 노드가 없는 경우 처리한다.
                        {
                            if(dragMenuInfo.MenuType != "G") // 드래그 메뉴 정보가 그룹 메뉴가 아닌 경우 처리한다.
                            {
                                AddTreeNode(treeView.Nodes, dragMenuInfo);
                            }
                        }

                        #endregion
                    }

                    #endregion
                }
                else if(e.Data.GetDataPresent(typeof(TreeNode)))
                {
                    #region 트리 뷰 내에서 드래그한 경우 처리한다.

                    bool                pressCTRLKey        = (e.KeyState & 8) == 8;
                    TreeNode            dragNode            = e.Data.GetData(typeof(TreeNode)) as TreeNode;
                    MenuInfo            dragMenuInfo        = dragNode.Tag as MenuInfo;
                    Point               mousePoint          = treeView.PointToClient(new Point(e.X, e.Y));
                    TreeViewHitTestInfo treeViewHitTestInfo = treeView.HitTest(mousePoint);
                    TreeNode            targetNode          = treeViewHitTestInfo.Node;

                    if(dragNode != targetNode) // 드래그 노드가 타겟 노드와 동일하지 않은 경우 처리한다.
                    {
                        if(pressCTRLKey)
                        {
                            #region CTRL 키를 누른 경우 처리한다.

                            MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);

                            #endregion
                        }
                        else
                        {
                            #region CTRL 키를 누르지 않은 경우 처리한다.

                            if(targetNode == null) // CTRL 키를 누르지 않은 경우 처리한다.
                            {
                                MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey);
                            }

                            #endregion
                        }
                    }

                    #endregion
                }
            }
        }

        #endregion
        #region 트리 뷰 드래그 이탈시 처리하기 - treeView_DragLeave(sender, e)

        /// <summary>
        /// 트리 뷰 드래그 이탈시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void treeView_DragLeave(object sender, EventArgs e)
        {
            ShowMessage(string.Empty);

            DragHelper.ImageList_DragLeave(this.treeView.Handle);
        }

        #endregion
        #region 트리 뷰 선택 후 처리하기 - treeView_AfterSelect(sender, e)

        /// <summary>
        /// 트리 뷰 선택 후 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeView treeView = sender as TreeView;

            if(treeView.SelectedNode != null)
            {
                MenuInfo menuInfo = treeView.SelectedNode.Tag as MenuInfo;

                ObservableCollection<MenuInfo> menuInfoCollection = this.gridControl.DataSource as ObservableCollection<MenuInfo>;

                int dataSourceIndex = menuInfoCollection.IndexOf(menuInfo);

                int rowHandle = this.gridView.GetRowHandle(dataSourceIndex);

                if(rowHandle > 0)
                {
                    this.gridView.FocusedRowHandle = rowHandle;
                }
            }
        }

        #endregion

        #region 노드 삭제 버튼 클릭시 처리하기 - deleteNodeButton_Click(sender, e)

        /// <summary>
        /// 노드 삭제 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void deleteNodeButton_Click(object sender, EventArgs e)
        {
            TreeNode treeNode = this.treeView.SelectedNode;

            if(treeNode == null)
            {
                MessageBox.Show("선택된 노드가 없습니다.");

                return;
            }

            if(MessageBox.Show(this, "선택한 노드를 삭제하시겠습니까?", "확인", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
            {
                return;
            }

            DeleteNode(this.treeView, treeNode);
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 메시지 표시하기 - ShowMessage(message)

        /// <summary>
        /// 메시지 표시하기
        /// </summary>
        /// <param name="message">메시지</param>
        private void ShowMessage(string message)
        {
            this.messageLabel.Text = message;
        }

        #endregion
        #region 트리 노드 생성하기 - CreateTreeNode(menuInfo)

        /// <summary>
        /// 트리 노드 생성하기
        /// </summary>
        /// <param name="menuInfo">메뉴 정보</param>
        /// <returns>트리 노드</returns>
        private TreeNode CreateTreeNode(MenuInfo menuInfo)
        {
            TreeNode treeNode = new TreeNode();

            treeNode.Name               = menuInfo.ID;
            treeNode.Text               = menuInfo.Name;
            treeNode.Tag                = menuInfo;
            treeNode.ImageIndex         = GetImageIndex(menuInfo);
            treeNode.SelectedImageIndex = treeNode.ImageIndex;

            return treeNode;
        }

        #endregion
        #region 트리 노드 추가하기 - AddTreeNode(treeNodeCollection, menuInfo, ensureVisbile)

        /// <summary>
        /// 트리 노드 추가하기
        /// </summary>
        /// <param name="treeNodeCollection">트리 노드 컬렉션</param>
        /// <param name="menuInfo">메뉴 정보</param>
        /// <param name="ensureVisbile">표시 보장 여부</param>
        private void AddTreeNode(TreeNodeCollection treeNodeCollection, MenuInfo menuInfo, bool ensureVisbile = true)
        {
            TreeNode treeNode = CreateTreeNode(menuInfo);

            treeNodeCollection.Add(treeNode);

            this.menuInfoDictionary.Add(menuInfo.ID, menuInfo);

            this.treeView.SelectedNode = treeNode;

            if(ensureVisbile)
            {
                treeNode.EnsureVisible();
            }
        }

        #endregion
        #region 트리 노드 삽입하기 - InsertTreeNode(treeNodeCollection, index, menuInfo, ensureVisbile)

        /// <summary>
        /// 트리 노드 삽입하기
        /// </summary>
        /// <param name="treeNodeCollection">트리 노드 컬렉션</param>
        /// <param name="index">인덱스</param>
        /// <param name="menuInfo">메뉴 정보</param>
        /// <param name="ensureVisbile">표시 보장 여부</param>
        private void InsertTreeNode(TreeNodeCollection treeNodeCollection, int index, MenuInfo menuInfo, bool ensureVisbile = true)
        {
            TreeNode treeNode = CreateTreeNode(menuInfo);

            treeNodeCollection.Insert(index, treeNode);

            this.menuInfoDictionary.Add(menuInfo.ID, menuInfo);

            this.treeView.SelectedNode = treeNode;

            if(ensureVisbile)
            {
                treeNode.EnsureVisible();
            }
        }

        #endregion
        #region 조상 노드 여부 구하기 - IsAncestorNode(dragNode, targetNode)

        /// <summary>
        /// 조상 노드 여부 구하기
        /// </summary>
        /// <param name="dragNode">드래그 노드</param>
        /// <param name="targetNode">타겟 노드</param>
        /// <returns>조상 노드 여부</returns>
        /// <remarks>드래그 노드가 타겟 노드의 조상 노드인지 조사한다.</remarks>
        private bool IsAncestorNode(TreeNode dragNode, TreeNode targetNode)
        {
            TreeNode currentNode = targetNode;

            while(currentNode != null)
            {
                if(currentNode.Parent == dragNode)
                {
                    return true;
                }

                currentNode = currentNode.Parent;
            }

            return false;
        }

        #endregion
        #region 자식 노드들이 모두 그룹 메뉴들인지 여부 구하기 - HasChildNodesOnlyGroupMenus(parentNode)

        /// <summary>
        /// 자식 노드들이 모두 그룹 메뉴들인지 여부 구하기
        /// </summary>
        /// <param name="parentNode">부모 노드</param>
        /// <returns>자식 노드들이 모두 그룹 메뉴들인지 여부</returns>
        private bool HasChildNodesOnlyGroupMenus(TreeNode parentNode)
        {
            foreach(TreeNode childNode in parentNode.Nodes)
            {
                MenuInfo childMenuInfo = childNode.Tag as MenuInfo;

                if(childMenuInfo.MenuType != "G")
                {
                    return false;
                }
            }

            return true;
        }

        #endregion
        #region 이미지 인덱스 구하기 - GetImageIndex(menuInfo)

        /// <summary>
        /// 이미지 인덱스 구하기
        /// </summary>
        /// <param name="menuInfo">메뉴 정보</param>
        /// <returns>이미지 인덱스</returns>
        private int GetImageIndex(MenuInfo menuInfo)
        {
            switch(menuInfo.MenuType)
            {
                case "G" : return 0;
                case "C" : return 1;
                case "P" : return 2;
                case "A" : return 3;
                default  : return -1;
            }
        }

        #endregion
        #region 데이터 지우기 - ClearData(treeView)

        /// <summary>
        /// 데이터 지우기
        /// </summary>
        /// <param name="treeView">트리 뷰</param>
        private void ClearData(TreeView treeView)
        {
            treeView.BeginUpdate();

            ClearData(treeView.Nodes);

            treeView.Nodes.Clear();

            this.menuInfoDictionary.Clear();

            treeView.EndUpdate();
        }

        #endregion
        #region 데이터 지우기 - ClearData(treeNodeCollection)

        /// <summary>
        /// 데이터 지우기
        /// </summary>
        /// <param name="treeNodeCollection">트리 노드 컬렉션</param>
        private void ClearData(TreeNodeCollection treeNodeCollection)
        {
            foreach(TreeNode noed in treeNodeCollection)
            {
                ClearData(noed.Nodes);

                noed.Tag = null;

                noed.Nodes.Clear();
            }
        }

        #endregion
        #region 드래그 노드 이동하기 - MoveDragNode(treeView, targetNode, dragNode, pressCTRLKey)

        /// <summary>
        /// 드래그 노드 이동하기
        /// </summary>
        /// <param name="treeView">트리 뷰</param>
        /// <param name="targetNode">타겟 노드</param>
        /// <param name="dragNode">드래그 노드</param>
        /// <param name="pressCTRLKey">CTRL 키를 눌렀는지 여부</param>
        private void MoveDragNode(TreeView treeView, TreeNode targetNode, TreeNode dragNode, bool pressCTRLKey)
        {
            if(dragNode.Level == 0) // 드래그 노드 레벨이 1계층인 경우 처리한다.
            {
                treeView.Nodes.Remove(dragNode);
            }
            else // 드래그 노드 레벨이 2계층 이상인 경우 처리한다.
            {
                dragNode.Parent.Nodes.Remove(dragNode);
            }

            if(pressCTRLKey) // CTRL 키를 누른 경우 처리한다.
            {
                if(targetNode == null) // 타겟 노드가 없는 경우 처리한다.
                {
                    treeView.Nodes.Insert(0, dragNode);
                }
                else // 타겟 노드가 있는 경우 처리한다.
                {
                    if(targetNode.Level == 0) // 타겟 노드 레벨이 1계층인 경우 처리한다.
                    {
                        treeView.Nodes.Insert(targetNode.Index, dragNode);
                    }
                    else // 타겟 노드 레벨이 2계층 이상인 경우 처리한다.
                    {
                        targetNode.Parent.Nodes.Insert(targetNode.Index, dragNode);
                    }
                }
            }
            else // CTRL 키를 누르지 않은 경우 처리한다.
            {
                if(targetNode == null)
                {
                    treeView.Nodes.Add(dragNode);
                }
                else
                {
                    targetNode.Nodes.Add(dragNode);
                }
            }

            treeView.SelectedNode = dragNode;

            dragNode.EnsureVisible();
        }

        #endregion
        #region 컨트롤 스크롤 하기 - ScrollControl(control)

        /// <summary>
        /// 컨트롤 스크롤 하기
        /// </summary>
        /// <param name="control">컨트롤</param>
        private void ScrollControl(Control control)
        {
            Point mousePoint = control.PointToClient(Cursor.Position);

            if((mousePoint.Y +20) > control.Height)
            {
                // 아래로 스크롤 합니다.
                SendMessage(control.Handle, 277, (IntPtr)1, (IntPtr)0);
            }
            else if(mousePoint.Y < 20)
            {
                // 위로 스크롤 합니다.
                SendMessage(control.Handle, 277, (IntPtr)0, (IntPtr)0);
            }
        }

        #endregion

        #region 컬렉션 생성하기 - CreateCollection()

        /// <summary>
        /// 컬렉션 생성하기
        /// </summary>
        /// <returns>컬렉션</returns>
        private ObservableCollection<MenuInfo> CreateCollection()
        {
            ObservableCollection<MenuInfo> collection = new ObservableCollection<MenuInfo>();

            for(int i = 1; i <= 30; i++)
            {
                collection.Add(new MenuInfo() { ID = "G" + i.ToString(), Name = "그룹 메뉴 " + i.ToString(), MenuType = "G", Description = "그룹 메뉴 설명 " + i.ToString() });
            }

            for(int i = 31; i <= 60; i++)
            {
                collection.Add(new MenuInfo() { ID = "C" + i.ToString(), Name = "컨트롤 메뉴 " + i.ToString(), MenuType = "C", Description = "컨트롤 메뉴 설명 " + i.ToString() });
            }

            for(int i = 61; i <= 90; i++)
            {
                collection.Add(new MenuInfo() { ID = "P" + i.ToString(), Name = "프로세스 메뉴 " + i.ToString(), MenuType = "P", Description = "프로세스 메뉴 설명 " + i.ToString() });
            }

            for(int i = 91; i <= 120; i++)
            {
                collection.Add(new MenuInfo() { ID = "A" + i.ToString(), Name = "액션 메뉴 " + i.ToString(), MenuType = "A", Description = "액션 메뉴 설명 " + i.ToString() });
            }

            return collection;
        }

        #endregion

        #region 메뉴 정보들 수집하기 - CollectMenuInfos(treeNodeCollection, menuInfoList)

        /// <summary>
        /// 메뉴 정보들 수집하기
        /// </summary>
        /// <param name="treeNodeCollection">트리 노드 컬렉션</param>
        /// <param name="menuInfoList">메뉴 정보 리스트</param>
        private void CollectMenuInfos(TreeNodeCollection treeNodeCollection, List<MenuInfo> menuInfoList)
        {
            foreach(TreeNode treeNode in treeNodeCollection)
            {
                CollectMenuInfos(treeNode.Nodes, menuInfoList);

                menuInfoList.Add(treeNode.Tag as MenuInfo);
            }
        }

        #endregion
        #region 노드 삭제하기 - DeleteNode(treeView, treeNode)

        /// <summary>
        /// 노드 삭제하기
        /// </summary>
        /// <param name="treeView">트리 뷰</param>
        /// <param name="treeNode">트리 노드</param>
        private void DeleteNode(TreeView treeView, TreeNode treeNode)
        {
            List<MenuInfo> menuInfoList = new List<MenuInfo>();

            menuInfoList.Add(treeNode.Tag as MenuInfo);

            foreach(TreeNode childTreeNode in treeNode.Nodes)
            {
                menuInfoList.Add(childTreeNode.Tag as MenuInfo);
            }

            CollectMenuInfos(treeNode.Nodes, menuInfoList);

            foreach(MenuInfo menuInfo in menuInfoList)
            {
                this.menuInfoDictionary.Remove(menuInfo.ID);
            }

            treeView.BeginUpdate();

            ClearData(treeNode.Nodes);

            treeNode.Nodes.Clear();

            if(treeNode.Parent == null)
            {
                treeView.Nodes.Remove(treeNode);
            }
            else
            {
                treeNode.Parent.Nodes.Remove(treeNode);
            }

            treeView.EndUpdate();
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요