NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# C# .NET Core 매크로 프로그램 만들기. (윈도우 프로그램 이동과 크기 변경)

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 매크로의 기본 기능인 마우스와 키보드 관련해서 모두 개발이 끝났습니다. 글을 쓰면서 이래저래 수정하다보니 코드가 많이 바뀌긴 했지만, 큰 줄기만 보면 누구나 쉽게 매크로 프로그램을 제작할 수 있을겁니다. 어느정도 코딩을 읽을줄 아신다면 말이죠^^; 아무튼, 매크로에서 멀티 다클라 작업을 할 때 크게 2가지 방식이 있습니다. 각각의 프로그램에 대응하는 스크립트를 하나씩 만드는것과 기준이 되는 프로그램에 스크립트를 만들어서 복사하는겁니다.

     

    단순히 기준이 되는 프로그램에서 100, 100 좌표를 클릭하는 스크립트를 만들었다고 생각 해보세요. 두번째 프로그램을 기준 프로그램 옆에 두었다고 하면 좌표만 이동해주면 하나의 스크립트로 얼마든지 여러개의 프로그램에 마우스와 키보드 신호를 줄 수 있습니다. 물론, 제약이 있긴하지만 심플하게 제작하려면 이 방법이 가장 좋습니다. 비활성 모드로 마우스와 키보드 신호를 줄 수 있다면 비활성 모드를 사용하는게 베스트이긴 합니다^^

     

    비활성 모드

    • 프로그램 핸들
    • 웹 API, 웹소켓
    • ADB

     

    현재는 프로그램 핸들 기능만 구현되어 있어서 이 부분만 테스트 해볼 수 있을거 같네요. 일단, 윈도우 프로그램의 이동과 크기 변경을 테스트 해볼텐데요. 관련 모델을 하나 생성해야 합니다. 엔지엠 6 버전에서는 프로그램 이동, 프로그램 크기 변경이 따로 있었는데요. 이번에는 하나로 합쳤습니다. 아래와 같이 AppControlModel을 만들어 보세요.

    using Ai.Api.Core;
    using Ai.Interface;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using static Ai.Api.Options;
    
    namespace Ai.Model.Action.Application
    {
        [Serializable]
        public class AppControlModel : BaseModel

     

    사용자가 선택할 수 있는 속성을 추가했는데요. 창 이동 관련 API는 총 3개입니다. 그래서, enum으로 옵션을 추가해야 합니다.

    public Point? Location { get; set; }
    public Ai.Api.Options.WindowMoveCommand Command { get; set; } = Ai.Api.Options.WindowMoveCommand.WindowPosition;

     

    Ai.Api.Options.WindowMoveCommand는 enum입니다.

            /// <summary>
            /// 창 이동 명령을 선택하세요.
            /// </summary>
            public enum WindowMoveCommand
            {
                /// <summary>
                /// 윈도우의 위치,크기,Z-order를 변경하는 함수입니다.
                /// </summary>
                WindowPosition = 0,
                /// <summary>
                /// 지정된 창의 표시 상태와 복원, 최소화 및 최대화 된 위치를 설정합니다.
                /// </summary>
                WindowPlacement = 1,
                /// <summary>
                /// 윈도우의 위치와 크기를 변경하는 함수입니다.
                /// </summary>
                MoveWindow = 2,
                /// <summary>
                /// 창 이동을 사용하지 않습니다.
                /// </summary>
                None = 3
            }

     

    프로그램의 크기를 변경하는것도 2가지 속성을 제공하고 있습니다.

    public Size? Size { get; set; }
    public Ai.Api.Options.WindowSizeOption AppControl { get; set; } = Ai.Api.Options.WindowSizeOption.None;

     

    Ai.Api.Options.WindowSizeOption은 내용이 좀 복잡합니다. 창 크기를 너비와 높이의 숫자값을 사용할수도 있지만, 최소화, 최대화도 있습니다.

    • 너비: 평면이나 넓은 물체의 가로를 잰 길이
    • 넓이: 1. 평면의 크기. 2. [수학] 일정한 평면이나 곡면이 차지하는 범위의 크기

     

    아래는 enum 코드입니다. enum에는 int도 있지만, flag도 있습니다. enum은 C#에서 정말 많이 사용되는 자료형입니다. 잘 사용하면 편리하기 때문에 기본적인 내용들은 익혀두는게 좋습니다.

            public enum WindowSizeOption : int
            {
                Normal = 1,
                Minimize = 6,
                Maximize = 3,
                Show = 5,
                Hide = 0,
                None = 99
            }

     

    먼저 프로그램 위치를 이동하는 코드를 볼까요? Location 속성은 Nullable 형식이기 때문에 null을 체크할 수 있지만, 데이터를 가져오려면 Value를 사용해야 합니다.

                if (Location.HasValue)
                {
                    if (this.MainHandles != null)
                    {
                        foreach (var handle in this.MainHandles)
                            ApplicationLocationAndSize(handle, IntPtr.Zero, this.Location.Value.X, this.Location.Value.Y, 0, 0, Ai.Api.Options.SetWindowPosFlags.SWP_NOSIZE, this.Command);
                    }
    
                    if (player.MainHandles != null)
                    {
                        foreach (var handle in player.MainHandles)
                            ApplicationLocationAndSize(handle, IntPtr.Zero, this.Location.Value.X, this.Location.Value.Y, 0, 0, Ai.Api.Options.SetWindowPosFlags.SWP_NOSIZE, this.Command);
                    }
                }

     

    위치와 크기를 처리하는 윈도우 API는 하나의 메소드로 처리할 수 있습니다. 코드가 좀 복잡해 보이긴하지만, 하나로 처리할 수 있는 윈도우 API를 사용자에게 위치와 크기로 나눠서 제공하다보니 인자(Parameter)가 많아진 느낌이 있습니다. 하지만, public static으로 Ai.Common에서 메소드를 별도로 제공하고 있어서 재정의하는 경우 Common 라이브러리의 메소드를 이용하는게 좋을듯 합니다.

            public bool ApplicationLocationAndSize(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, Ai.Api.Options.SetWindowPosFlags uFlags, Ai.Api.Options.WindowMoveCommand wmc)
            {
                switch (wmc)
                {
                    case WindowMoveCommand.WindowPosition:
                        return Ai.Api.Core.User32.SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
                    case WindowMoveCommand.WindowPlacement:
                        Rectangle rect1 = GetPlacement(hWnd);
                        rect1.X = x;
                        rect1.Y = y;
    
                        Ai.Api.Options.WINDOWPLACEMENT placement = new Ai.Api.Options.WINDOWPLACEMENT();
                        placement.length = Marshal.SizeOf(placement);
                        placement.rcNormalPosition = rect1;
                        placement.showCmd = (int)WindowControlOption.SW_SHOWNORMAL;
                        return Ai.Api.Core.User32.SetWindowPlacement(hWnd, ref placement);
                    case WindowMoveCommand.MoveWindow:
                        Rectangle rect2 = GetPlacement(hWnd);
                        return Ai.Api.Core.User32.MoveWindow(hWnd, x, y, rect2.Width, rect2.Height, true);
                }
                return false;
            }

     

    이제 어떻게 동작하는지 테스트 해볼까요? 메모장을 3개 실행하고 동시에 위치를 조정하고, 크기도 변경해보도록 하겠습니다. 핸들 추가에서 현재 메모장을 모두 추가합니다.

    4mYhGN0.jpeg

     

     

    매크로를 실행하고, 프로그램의 크기를 변경해봤는데요. 사용자가 입력한 수치대로 모든 프로그램이 동시에 사이즈가 변경되는걸 확인할 수 있습니다.

     

     

    이번에는 프로그램의 위치를 변경해볼께요. 위치는 하나만 입력할 수 있기 때문에 모든 프로그램이 겹쳐지게 됩니다. 그래서, 실행 후 수동으로 다시 펼쳐 두었습니다.

     

     

    프로그램을 최대화, 최소화도 실행할 수 있는데요. 이것보다는 프로그램을 숨기고 보이게 할 수도 있습니다. 이 기능은 약간 꼼수가 필요합니다. 프로그램이 숨겨지면 핸들을 찾을 수 없기 때문에 핸들 목록을 어딘가에 저장해둬야 합니다. 그래서, 핸들 추가 액션으로 글로벌하게 추가하고 모든 창을 숨기고 3초 후 다시 보이게 해야 합니다.

     

     

    간단하게 프로그램을 이동하거나 크기를 변경하는 방법에 대해서 알아봤는데요. 좀 더 다듬어야 할 내용들이 있긴하지만, 이정도만 구현해도 훌륭하다고 할 수 있을거 같습니다. 완성도를 더 높이고, 다듬어야 할 내용들이 있긴하지만, 이런 세세한 부분들은 나중에 하나씩 수정해 나가도록 하겠습니다.

     

    개발자에게 후원하기

    MGtdv7r.png

     

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

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

    감사합니다~

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

    댓글목록

    등록된 댓글이 없습니다.