NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 팁 앤 테크
  • 매뉴얼

    팁과 테크니컬 노하우를 확인하세요.

    팁 앤 테크

    팁과 테크니컬 노하우를 확인하세요.

    본 사이트의 컨텐츠는 저작권법의 보호를 받으므로 무단 복사, 게재, 배포 등을 금합니다.

    커스텀 윈도우 창 바둑판 정렬 매크로. (윈도우 창 타일 모양 배열)

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 얼마전에 다클라 다계정하시는 고객분이 창을 어떻게 정렬할지 문의한적이 있습니다. 보통은 창을 하나씩 선택해서 직접 창 크기와 위치를 설정하면 되긴하는데요. 좀 더 편리하게 작업할 수 있도록 커스텀 모듈을 만들어봤습니다. 대부분은 아마도 [ 윈도우 이동 ], [ 윈도우 크기 ] 액션을 사용하고 있을겁니다. 자~ 커스텀 모듈을 만들기 위해 비주얼 스튜디오를 실행하고, 새로운 프로젝트를 하나 추가 해줍니다.

    n0T4Rme.png

     

     

    커스텀 모듈을 만들기 위한 셋팅 및 학습은 아래 게시판을 먼저 학습하고 이 글을 읽어야 합니다.

    [ 커스텀 모듈 개발 환경 만들기 ]

     

    어떻게 동작하는지는 아래 동영상을 참고하세요. 10개의 그림판은 미리 등록 해두었습니다. 바둑판 배열은 가로 4, 세로 3입니다.

    0MnKmOG.gif

     

     

    커스텀 모듈의 전체 소스입니다. 입맛에 맞게 수정해서 사용해도 됩니다^^

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Linq;
    using System.Xml.Serialization;
    
    namespace CustomWindowTileSortModule
    {
        [Serializable]
        public class WindowSorterModel : NGM.Models.Interface.BaseCustomToolModel, NGM.Models.Interface.IHandleModel
        {
            private string _findControl;
    
            /// <summary>
            /// 도구 상자에 표시될 카테고리 이름을 가져옵니다.
            /// </summary>
            public override string DisplayCategory => "NGMsoftware";
    
            /// <summary>
            /// 도구 상자에 표시될 액션 이름을 가져옵니다.
            /// </summary>
            public override string DisplayName => "창 정렬";
    
            [XmlIgnore]
            [Browsable(false)]
            [ReadOnly(true)]
            public IntPtr MainHandle { get; set; }
    
            [XmlIgnore]
            [Browsable(false)]
            [ReadOnly(true)]
            public IntPtr ControlHandle { get; set; }
    
            [XmlIgnore]
            [Browsable(false)]
            [ReadOnly(true)]
            public string Title { get; set; }
    
            [XmlIgnore]
            [Browsable(false)]
            [ReadOnly(true)]
            public List<NGM.Models.Item.HandleItem> Children { get; set; }
    
            [XmlIgnore]
            [Category("Data")]
            [DisplayName("창 목록")]
            [Browsable(true)]
            public List<string> Titles { get; set; } = new List<string>();
    
            [Category("Action")]
            [DisplayName("가로 그림자 영역")]
            [Browsable(true)]
            [DefaultValue(0)]
            public int HorizontalShadowSize { get; set; }
    
            [Category("Action")]
            [DisplayName("세로 그림자 영역")]
            [Browsable(true)]
            [DefaultValue(0)]
            public int VerticalShadowSize { get; set; }
    
            [Category("Action")]
            [DisplayName("가로 수")]
            [Browsable(true)]
            [DefaultValue(1)]
            public int HorizontalCount { get; set; } = 1;
    
            [Category("Action")]
            [DisplayName("세로 수")]
            [Browsable(true)]
            [DefaultValue(1)]
            public int VerticalCount { get; set; } = 1;
    
            [Category("Action")]
            [DisplayName("윈도우 API")]
            [Browsable(true)]
            [DefaultValue(typeof(NGM.API.Options.WindowMoveCommand), "SetWindowPos")]
            public NGM.API.Options.WindowMoveCommand Command { get; set; } = NGM.API.Options.WindowMoveCommand.SetWindowPos;
    
            [Category("Action")]
            [DisplayName("창 추가")]
            [Browsable(true)]
            [DefaultValue(null)]
            [Editor(typeof(NGM.Models.TypeEditor.FindControlEditor), typeof(System.Drawing.Design.UITypeEditor))]
            public virtual string FindControl
            {
                get { return _findControl; }
                set
                {
                    if (Titles == null)
                        Titles = new List<string>();
    
                    _findControl = value;
                    if (string.IsNullOrEmpty(value))
                    {
                        if (MainView != null && MainView is NGM.Interface.IEditor)
                            (MainView as NGM.Interface.IEditor).RefreshProperty();
    
                        return;
                    }
    
                    List<string> nodes;
                    nodes = value.Split(new string[] { NGM.Definition.DOMSeparator }, StringSplitOptions.RemoveEmptyEntries).ToList();
                    Titles.Add(NGM.Common.GetMiddleString(nodes.FirstOrDefault(), "(", ")"));
    
                    if (MainView != null && MainView is NGM.Interface.IEditor)
                        (MainView as NGM.Interface.IEditor).RefreshProperty();
                }
            }
    
            public override void Execute()
            {
                IntPtr handle = IntPtr.Zero;
                int mw = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
                int mh = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
    
                int cw = mw / this.HorizontalCount;
                int ch = mh / this.VerticalCount;
    
                int x = HorizontalShadowSize > 0 ? -HorizontalShadowSize : 0;
                int y = 0;
    
                for (int i = 0; i < Titles.Count; i++)
                {
                    var handles = NGM.Common.GetHandles(Titles[i], this.Children.Select(s => s.Node).ToList());
                    handle = handles.Item1;
    
                    if (handle != IntPtr.Zero)
                        NGM.API.Window.SetWindowPosition(
                            handle,
                            IntPtr.Zero,
                            x,
                            y, 
                            cw + HorizontalShadowSize * 2,
                            ch + VerticalShadowSize * 2,
                            NGM.API.Options.SetWindowPosFlags.SWP_SHOWWINDOW,
                            this.Command);
    
                    if ((i + 1) % this.HorizontalCount == 0)
                    {
                        y += ch;
                        x = HorizontalShadowSize > 0 ? -HorizontalShadowSize : 0;
                    }
                    else
                    {
                        x += cw;
                    }
                }
            }
        }
    }

     

     

    그림판은 클라이언트에 그림자 영역이 존재합니다. 그래서, 정렬하고나면 각각의 클라이언트가 간격을 가지게 됩니다. 보통 그림자 영역이 있는 윈도우 창들은 가로 8, 세로 4의 그림자 영역을 가집니다. 윈도우 10에서만 그렇고, 윈도우 11에서는 아직 확인해보진 못했습니다. 아마 동일하지 않을까요^^?

    5JQ2Jii.gif

     

     

    게임 다클라 다계정으로 돌리는 분들은 각자 창 배열, 창 정리 프로그램을 사용하고 있을겁니다. 어떤걸 쓰는지는 모르겠지만요. 간단한 산수만 할줄알면 창 배열은 누구나 쉽게 할 수 있지만, 문제는 코딩을 해야 한다는 겁니다. 이 부분이 진입장벽을 높이는 주 원인이죠. 그래서, 첨부 파일로 커스텀 모듈을 첨부 해두었습니다. 엔지엠 에디터의 관리자 메뉴에서 도구 모음 설치로 첨부된 dll을 선택해주면 자동 설치 됩니다.

    [ 커스텀 모듈 다운로드 ]

    X536Pzb.png

     

     

    개발자에게 후원하기

    MGtdv7r.png

     

    추천, 구독, 홍보 꼭~ 부탁드립니다.

    여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~

    감사합니다~

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.