NGMsoftware

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

    학습


    C# C# .NET Core 매크로 프로그램 만들기. (마우스 클릭 드래그 1부)

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 오늘은 마우스 클릭 드래그에 대해서 알아볼건데요. 이미 마우스 클릭은 개발했기 때문에 이전 글을 참고하시면 될거 같아요. 우선, 마우스 드래그는 이동시키고 싶은 어떤 물체에서 마우스를 누르고, 이동할 위치까지 마우스를 움직인 후 버튼을 때면 됩니다. 사람이 이 동작을 할 때는 무의식중에 무심코 동작을 하겠지만, 컴퓨터에게는 하나씩 설명해줘야 해요. 그래서, 비전문가나 일반인 또는 어린아이에게 순서대로 설명을 잘 하는 사람이 프로그래밍이나 매크로 제작도 잘 합니다. 너무 당연한 이야기인가요?

     

    우선, 마우스 관련 액션들을 아래와 같이 만들었습니다. 이전까지 클릭 하나만 있었는데요. 항목은 미리 다 추가해두었어요.

    zMuVA8y.png

     

     

    간단하게 드래그를 하려면 마우스 다운과 마우스 업만 있으면 됩니다. 아래는 마우스 다운과 업에 대한 API인데요. 어떤 API를 사용하느냐에 따라서 코드가 달라집니다. 윈도우는 기본적으로 마우스 API를 4개 제공하고 있습니다. 활성 방식 2개와 비활성 방식 2개예요. 엔지엠 매크로는 총 7가지의 API를 제공합니다.

    • Event (활성 소프트웨어 신호)
    • Input (활성 소프트웨어 신호)
    • SendMessage (비활성 소프트웨어 신호)
    • PostMessage (비활성 소프트웨어 신호)
    • Class DD (활성 하드웨어 신호)
    • Interception (활성 하드웨어 신호)
    • Arduino (활성 하드웨어 신호)

     

    우선, 마우스 다운부터 하나씩 살펴볼께요. 아래 코드는 Event 방식의 마우스 다운 코드입니다. 딱히 코드에 별거 없습니다. 마이크로소프트에서 제공해주는 user32 라이브러리의 mouse_event API를 호출하면 됩니다. 아래 flags의 인자로 2를 넘겨주면 왼쪽 버튼으로 동작합니다. 참고로, 오른쪽은 4를 넘겨주면 됩니다.

    [DllImport("user32.dll")]
    private static extern void mouse_event(int flags, int dX, int dY, int buttons, int extraInfo);
    
    public void MouseLeftDown()
    {
        mouse_event(2, 0, 0, 0, 0);
    }

     

    input 방식도 event와 동일하지만, 약간 더 복잡합니다. 추가적인 정보를 요구하기 때문인데요. 우선, 아래와 같이 구조체를 하나 만들어주세요.

        internal struct MOUSEINPUT
        {
            internal Int32 X;
            internal Int32 Y;
            internal UInt32 MouseData;
            internal UInt32 Flags;
            internal UInt32 Time;
            internal IntPtr ExtraInfo;
        }

     

    그리고, user32 라이브러리 API도 만들어줍니다.

            [DllImport("user32.dll", SetLastError = true)]
            internal static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] inputs, Int32 sizeOfInputStructure);

     

    마지막으로 비활성 마우스 동작은 아래와 같은데요. 이전에 만든 마우스 클릭에서 다운과 업을 분리하면 됩니다.

    // Mouse Click
    Ai.Common.Windows.PostMessage(controlHandle.Value, Ai.Api.Options.WindowMessage.WM_LBUTTONDOWN, (int)Ai.Api.Options.MouseAction.LeftDown, Windows.MakeLParam(position));
    Ai.Common.Windows.PostMessage(controlHandle.Value, Ai.Api.Options.WindowMessage.WM_LBUTTONUP, (int)Ai.Api.Options.MouseAction.LeftUp, Windows.MakeLParam(position));

     

    마우스 다운 비활성 API입니다.

    Ai.Common.Windows.PostMessage(controlHandle.Value, Ai.Api.Options.WindowMessage.WM_LBUTTONDOWN, (int)Ai.Api.Options.MouseAction.LeftDown, Windows.MakeLParam(position));

     

    마우스 업 비활성 API입니다.

    Ai.Common.Windows.PostMessage(controlHandle.Value, Ai.Api.Options.WindowMessage.WM_LBUTTONUP, (int)Ai.Api.Options.MouseAction.LeftUp, Windows.MakeLParam(position));

     

    user32 API의 마우스 플래그입니다.

    public enum WindowMessage : int
    {
        Down = 0x0201,
        Up = 0x0202
    }

     

    윈도우에서 마우스를 사용하기 위한 API는 모두 만들었고, 이제 마우스 모델이 실행될 때 처리해야 할 비즈니스 로직을 설계해봅시다. 전체 코드는 아래와 같습니다.

            public override string? Excute(Ai.Interface.IPlayer player)
            {
                string? id = base.Excute(player);
    
                Ai.Definition.DeviceInputType inputType = Definition.DeviceInputType.Windows;
                if (this.InputType == Definition.ChildDeviceInputType.Inheritance)
                    inputType = player.DeviceInputType;
                else
                    inputType = (Ai.Definition.DeviceInputType)Enum.Parse(typeof(Ai.Definition.DeviceInputType), this.InputType.ToString());
    
                switch (inputType)
                {
                    case Definition.DeviceInputType.Windows:
                    case Definition.DeviceInputType.Event:
                    case Definition.DeviceInputType.Input:
                        Ai.Common.Mouse.Run(Ai.Definition.MouseAction.Down, this.Coordinate, this.MouseButton, inputType, this.UseRelative);
                        break;
                    case Definition.DeviceInputType.PostMessage:
                    case Definition.DeviceInputType.SendMessage:
                        if (player.ControlHandles != null)
                        {
                            foreach (var handle in player.ControlHandles)
                            {
                                Point coordinate = InactiveMouseLocation(handle, this._windowRect, this.Coordinate);
                                Ai.Common.Mouse.Run(Ai.Definition.MouseAction.Down, coordinate, this.MouseButton, inputType, this.UseRelative, controlHandle: handle);
                            }
                        }
                        break;
                }
    
                return id;
            }

     

    액션이 실행되기 위한 선행 조건들을 먼저 실행하고, 윈도우 API를 호출했습니다. 그리고, 결과에 대해서 자신의 속성을 채워줍니다. 이제 매크로를 실행하고, 아래와 같이 마우스 다운과 업을 하나씩 추가하세요. 그리고, 그림판에 다운과 업 좌표를 다르게 설정한 후 실행하면 드래그와 같은 효과가 나타납니다.

     

     

    잘 동작하는군요. 이번에는 비활성으로 동작하게 만들어볼께요. 입력 방식을 선택하고, 핸들을 잡아주세요.

    slropos.png

     

     

    매크로를 실행하면 활성 모드와 동일하게 동작합니다. 하지만, 비활성 모드이기 때문에 실제로 마우스가 이동하지 않습니다. 그림판과 같은 경우에는 마우스 다운과 업으로 드래그하는듯한 느낌을 줄 수 있습니다. 물론, 동작도 잘 됩니다. 하지만, 아래와 같이 윈도우의 아이콘은 움직일 수 없습니다.

     

     

    다음 시간에는 실제로 드래그하는것과 동일한 효과를 줄 수 있는 드래그 액션을 만들어 보고, 윈도우 바탕화면에서 아이콘을 이동하도록 해보겠습니다. 윈도우에서 마우스를 조작하는 방법은 여러가지가 다양하게 있는데요. 문제는 윈도우 신호를 받아들이는 프로그램마다 처리가 제각각이라는 점입니다. 그래서, 윈도우 API를 적절하게 가공할 수 있도록 옵션을 선택할 수 있게 만들어야 합니다.

     

    개발자 혼자 사용하는 경우라면, 굳이 옵션을 만들고 복잡하게 조건에 따라 코드를 분리할 필요가 없습니다. 자동화 할 프로그램 또는 시스템에 맞게 제작하면 되기 때문입니다. 하지만, 불특정 다수가 사용하는 편집기 프로그램은 여러가지 상황과 시나리오를 모두 고려해야 합니다. 어떤 상황에서 어떤 프로그램에 사용할지 모르기 때문입니다. 만약, API가 다양하지 못하면 모든 상황에 유연하게 대처하기가 어려워집니다. 그리고, 프로그램을 매번 패치하는 것도 많은 비용이 발생하니까요^^

     

    개발자에게 후원하기

    MGtdv7r.png

     

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

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

    감사합니다~

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

    댓글목록

    등록된 댓글이 없습니다.