NGMsoftware

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

    학습


    C# C# .NET 매크로 프로그램 만들기. (기계식 또는 하드웨어 방식 키보드 매크로 3부)

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 앞서 기계식 하드웨어 마우스와 키보드 매크로를 어떻게 만드는지 알아봤습니다. 하드웨어 기계식 마우스 매크로는 생각보다 간단하게 만들 수 있었는데요. 문제는 키보드입니다. 소프트웨어 방식으로 키보드 매크로를 만들면 자동으로 한영이 토글되면서 한글과 영어가 섞여 있어도 문제없이 입력됩니다. 아래와 같이 입력하는걸 말하는거죠.

     

     

    오늘 알아볼 기계식 하드웨어 키보드는 소프트웨어 방식과 다르게 실제로 한영키를 번갈아가면서 눌러줘야 합니다. 이걸 하려면 자동화를 적용할 대상 프로그램의 IME 모드를 알아내야 합니다. 그래야 기계적으로 한영키를 누르고 타이핑을 이어서 할 수 있기 때문입니다. 일단 IEM 모드를 어떻게 알아낼 수 있는지부터 알아볼까요?

     

    아래 윈도우 API는 활성화된 창의 핸들 정보를 가져옵니다. IME를 알아내기 위해서는 해당 창의 핸들을 알아야 하기 때문입니다.

    [DllImport("user32.dll")]
    internal static extern IntPtr GetActiveWindow();

     

    IME를 가져오는 윈도우 API입니다.

    using System.Runtime.InteropServices;
    using System.Security;
    
    namespace Ai.Api.Core
    {
        [SuppressUnmanagedCodeSecurityAttribute]
        internal class Ime32
        {
            [DllImport("imm32.dll")]
            internal static extern IntPtr ImmGetDefaultIMEWnd(IntPtr hWnd);
        }
    }

     

    이제 키보드 타이핑 전에 마우스로 클릭해야 하는지 이해가 가실겁니다. 활성화된 창을 찾고, 그 창에서 IME 모드를 알아내야 하기 때문입니다. 물론, 핸들 추가 액션을 이용해서 핸들 값을 넘겨도 되긴합니다. 하지만, 이렇게하면 핸들 설정을 관리해야 합니다. 하드웨어 기계식 매크로 환경에서 핸들을 추가하면 마우스 좌표가 비활성 모드로 설정되기 때문에 문제가 될수도 있습니다. 실제로는 문제가 안되지만 다클라 환경이 더해지면 문제가 될 수 있습니다.

     

    그래서, 마우스로 클릭해서 해당 창을 활성화 시키고 IME 정보를 알아낸 후 키보드를 입력할 수 있도록 해줘야 합니다. 그리고, 한가지 더 문제가 있는데요. 입력할 텍스트가 숫자나 영어라면 키보드 다운과 업으로 처리할 수 있습니다. 하지만, 2바이트로 구성된 한글의 경우 바로 입력할 수 있는 방법이 없습니다. 그렇기 때문에 자소분리 로직에 따라서 1바이트 기호로 변환한 후 영어 키보드와 매핑해서 입력되도록 해야 합니다.

     

    텍스트를 한글자씩 처리하기 위해서 split을 이용하거나 array로 변환할 수 있습니다. 그리고, 아래와 같이 정규식을 이용해서 캐릭터(Char)가 한글인지 쉽게 판단할 수 있습니다.

    internal static bool IsHangul(string text)
    {
        return Regex.IsMatch(text, @"[ㄱ-ㅎ가-힣]");
    }

     

    캐릭터가 한글이면 대상 프로그램의 IME가 영어 입력 모드인지 알아내야 합니다. 한글인데 영어 입력 모드라면 한영키를 한번 눌러주면 됩니다.

    public static bool IsEnglishForIME(IntPtr mainHandle)
    {
        IntPtr ime = Ime32.ImmGetDefaultIMEWnd(mainHandle);
        IntPtr status = User32.SendMessageTimeout(ime, 643, new IntPtr(0x5), new IntPtr(0), SendMessageTimeoutFlag.SMTO_NORMAL, 1000, out IntPtr result);
    
        if (result.ToInt32() == 0)
            return true; // 영어
        else
            return false; // 한국어
    }

     

    이제 한글인 경우에만 작동하는 메소드를 하나 추가해주세요. 이 메소드는 한글의 자소를 분리해서 키보드의 키와 매핑시켜줍니다.

    internal static string[] SplitJaso(char hangul, bool convertEnglish = false)
    {
        int choIndex, jungIndex, jongIndex;
        ushort uTempCode = 0x0000;
        uTempCode = Convert.ToUInt16(hangul);
    
        int iUniCode = uTempCode - _codeBaseStart;
        choIndex = iUniCode / (21 * 28);
        iUniCode = iUniCode % (21 * 28);
        jungIndex = iUniCode / 28;
        iUniCode = iUniCode % 28;
        jongIndex = iUniCode;
    
        List<string> jasoList = new List<string>();
        string cho, jung, jong;
    
        if (convertEnglish)
        {
            cho = _choEngTable[choIndex];
            jung = _jungEngTable[jungIndex];
            jong = _jongEngTable[jongIndex];
        }
        else
        {
            cho = _choTable[choIndex];
            jung = _jungTable[jungIndex];
            jong = _jongTable[jongIndex];
        }
    
        if (!string.IsNullOrEmpty(cho))
        {
            jasoList.Add(cho);
        }
    
        if (!string.IsNullOrEmpty(jung))
        {
            jasoList.Add(jung);
        }
    
        if (!string.IsNullOrEmpty(jong))
        {
            jasoList.Add(jong);
        }
    
        return jasoList.ToArray();
    }

     

    한글이면 분리된 자음과 모음을 반복하면서 타이핑 해줍니다.

    foreach (var keyCode in keyCodeList)
    {
        foreach (char s in keyCode)
        {
            player.Manager.SerialPort.Write($"KD{s}");
            System.Threading.Thread.Sleep(speed);
            player.Manager.SerialPort.Write($"KU{s}");
        }
    }

     

    만약, 영어라면 자소를 분리할 필요가 없습니다. 아래와 같이 캐릭터 코드를 바로 입력하면 됩니다.

    player.Manager.SerialPort.Write($"KD{inputValue}");
    System.Threading.Thread.Sleep(speed);
    player.Manager.SerialPort.Write($"KU{inputValue}");

     

    이제 완성된 스크립트를 실행 해볼까요? 아래 동영상과 같이 하드웨어 방식으로도 한글과 영어를 자동으로 인식해서 IME를 변경해가면서 타이핑하는걸 확인할 수 있습니다.

     

     

    요즘 작업 속도가 점점 느려지고 있습니다. 제작 의뢰가 많기도 하지만, 새롭게 만드는 인공지능 매크로에서는 이전 버전에서 개선되어야 할 기능들을 하나씩 테스트하고 검증하면서 새로운 아이디어들을 적용시키고 있습니다. 그리고, 불합리하다고 생각되는 것들을 개선해 나가다보니 할일이 점점 많아지네요. 유튜브도 어떻게하면 정보를 더 잘 전달할지를 생각하다가 자막과 보이스를 달기로 했습니다. 이 작업도 생각보다 오래 걸리네요 ㅎㅎ;

     

    빨리 빨리 기능도 추가하고, 아이디어로만 가지고 있던 기능들을 추가하고 싶지만 급하다고 해서 스파게티 소스를 만들수는 없어서 천천히 하나씩 만들기로 했습니다. 기록을 남기기 위해서 유튜브와 글도 꾸준히 작성해야겠죠? 나중에 왜 이렇게 만들었는지 기억이 안날수도 있으니 참고용 자료로 괜찮을거 같아요. 에디터 편의 기능을 좀 더 개선하고, OCR 기능을 알아보도록 할께요.

     

    개발자에게 후원하기

    MGtdv7r.png

     

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

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

    감사합니다~

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

    댓글목록

    등록된 댓글이 없습니다.