PC 프로그램에서 카카오 PC 대화방에 특정 메세지를 전달하는 코드다.

 

1
2
        [System.Runtime.InteropServices.DllImport("User32", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
cs

 

FindWindow 를 통해서 대화창 프로세스 정보를 가져온다.

 

1
2
3
4
5
6
7
8
9
10
                IntPtr hd01 = FindWindow(null, "카카오톡 대화방 제목");
                if (hd01 != IntPtr.Zero)
                {
                    IntPtr hd03 = FindWindowEx(hd01, IntPtr.Zero, "RichEdit20W""");
                    if (hd03 != IntPtr.Zero)
                    {
                        SendMessage(hd03, 0x000c0, "전달할 말");
                        PostMessage(hd03, 0x01000xD0x1C001);
                    }
                }
cs

 

 

 

위 코드를 실행하면 PC 카카오톡 대화방 창을 찾은 후 메세지를 전달할 수 있다.

728x90

이번에는 실행 중인 프로세스를 찾아서 해당 프로세스에 키값을 넘겨주는 것을 진행하도록 하겠습니다.

 

1
2
3
4
5
        [System.Runtime.InteropServices.DllImport("User32", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 
        [System.Runtime.InteropServices.DllImport("User32", EntryPoint = "SetForegroundWindow")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
cs

 

DLL 을 추가하여 위 2가지 API 를 사용할수 있게 선언해줍니다.

 

FindWindow 로 현재 실행중이 앱플레이어를 찾습니다. (모모앱플레이어 기준으로 작성하도록 하겠습니다.)

SetForegroundWindow 로 플레이어로 포커스를 가져옵니다.

 

 

 

플레이어를 지정해줄 TextBox를 하나 추가해주세요

 

1
2
            IntPtr procHandler = FindWindow(null, textBox6.Text);
            SetForegroundWindow(procHandler);
cs

 

TextBox 에서 프로세스 이름을 가져와 포커스를 가져옵니다.

 

1
2
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern void keybd_event(uint vk, uint scan, uint flags, uint extraInfo);
cs

 

위에 키보드 이벤트를 발생시켜줄  api 를 추가합니다.

추가로 발생시킬 키를 설정할 button 을 하나 추가한 후에 아래 번개 모양을 클릭해줍니다.

 

추가후 keydown에 button2_down 을 추가해줍니다.

 

Keys 를 하나 선언해줍니다.

Keys returnKey;

1
2
3
4
5
        private void button2_down(object sender, KeyEventArgs e)
        {
            returnKey = e.KeyCode;
            button2.Text = e.KeyCode.ToString();
        }
cs

 

해당 button2 을 누르고 원하는 키를 입력하면 아래와 같이 설정되는걸 확인할수 있습니다.

 

이제 해당 키를 발생시키도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
        System.Windows.Forms.Timer timer;
 
        public Form1()
        {
            InitializeComponent();
            timer = new System.Windows.Forms.Timer();
            timer.Interval = 3000;
            timer.Tick += new EventHandler(check);
        }
cs

 

3초에 한번씩 체크하기 위해 위와같이 타이머를 추가했습니다.

 

PrintScreenAndCheck 함수를 작성합니다.

강의 1,2 번에서 진행한 화면을 캡쳐해서 숫자를 인식하는 코드와

숫자 인식율을 올리기위해서 RGB 값을 체크해 흰부분을 제외하고는 검은색 처리하는 코드가 들어가 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
        public void PrintScreenAndCheck()
        {
            System.Drawing.Size mSize = new System.Drawing.Size(mWidth, mHeigt);
            Bitmap image = new Bitmap(mWidth, mHeigt);
            Graphics g = Graphics.FromImage(image);
 
            try
            {
                g.CopyFromScreen(mX, mY, 00, mSize);
            }
            catch (Win32Exception w)
            {
                Console.WriteLine(w.Message);
            }
 
            int R, G, B = 0;
 
            for (int i = 0; i < image.Width; i++)
            {
                for (int j = 0; j < image.Height; j++)
                {
                    Color c = image.GetPixel(i, j);
                    R = c.R;
                    G = c.G;
                    B = c.B;
 
                    if (R > 160 && G > 160 && B > 160)
                    {
                        image.SetPixel(i, j, Color.White);
                    }
                    else
                    {
                        image.SetPixel(i, j, Color.Black);
                    }
 
                }
            }
 
            image = ResizeImage(image, pictureBox1.Width, pictureBox1.Height);
            pictureBox1.Image = image;
 
            image.Save("save.jpg"System.Drawing.Imaging.ImageFormat.Jpeg);
 
            var engine = new TesseractEngine(@"./tessdata""eng", EngineMode.Default);
            Pix pix = Pix.LoadFromFile("save.jpg");
            var result = engine.Process(pix);
            String HpString = result.GetText();
            String[] split = HpString.Split('/');
 
            if (split.Length > 1)
            {
                HpString = split[0];
            }
 
            label1.Text = HpString;
        }
cs

 

 

리니지M 게이지마가 1235/1358 이런식으로 리턴하기때문에 / 아래는 날리고 앞에 현재 에너지 상태만 가져오도록 추가했습니다.

 

이제 3초에 한번씩 위 함수를 호출한 후 에너지 설정한 값보다 작다면 설정한 키를 호출하도록 하겠습니다.

타이머에 추가해준 check 함수를 작성합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        void check(object sender, EventArgs e)
        {
            Console.WriteLine("check");
            PrintScreenAndCheck();
            int Hp = 0;
            int Hplimit = 0;
            try
            {
                Hp = Convert.ToInt32(label1.Text);
                Hplimit = Convert.ToInt32(textBox2.Text);
 
                if(Hp < Hplimit)
                {
                    keybd_event((byte)returnKey, 00x000);
                    Delay(100);
                    keybd_event((byte)returnKey, 00x020);
                }
            }
            catch (System.FormatException w)
            {
                Console.WriteLine(w.Message);
            }
        }
cs

 

모모앱플레이어의 경우 키 다운 업 사이제 Delay를 안주면 인식을 안합니다.

 

 

매크로 강좌는 여기까지입니다.

감사합니다.

728x90

이번에는 캡쳐해서 가져온 이미지를 Tesseract.3.0.2.0 를 이용해서 문자 인식을 할 예정입니다.

 

먼저 해당 Tesseract 비주얼스튜디오에서 설치해보도록 하겠습니다.

 

프로젝트 -> NuGet 패키지 관리에 들어갑니다.

 

찾아보기에서 Tesseract 검색 및 설치를 진행합니다.

 

 

설치완료 후 참조 영역에 아래와 같이 Tesseract 추가되어 있으면 기본적인 설치는 끝났습니다.

 

tessdata.vol1.egg

tessdata.vol2.egg

(알집으로 분할 압축했습니다. 알집으로 압축 풀고 진행해주세요)

 

위 데이터 파일을 다운받아서 진행하고 있는 프로젝트 실행 위치에 복사해줍니다.

저같은경우는 bin -> Debug 상태에서 진행하고 있습니다.

 

 

소스코드로 돌아가서 이제 문자인식을 진행하면 됩니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using Tesseract;
 
 
 
        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.ShowDialog(this);
 
            System.Drawing.Size mSize = new System.Drawing.Size(mWidth, mHeigt);
            Bitmap image = new Bitmap(mWidth, mHeigt);
            Graphics g = Graphics.FromImage(image);
 
            try
            {
                g.CopyFromScreen(mX, mY, 00, mSize);
            }
            catch (Win32Exception w)
            {
                Console.WriteLine(w.Message);
            }
 
            image = ResizeImage(image, pictureBox1.Width, pictureBox1.Height);
            pictureBox1.Image = image;
 
            Pix pix = PixConverter.ToPix(image);        
 
            var engine = new TesseractEngine(@"./tessdata""eng", EngineMode.Default);
            
            var result = engine.Process(pix);
            result.GetText();
 
            label1.Text = result.GetText();
        }
 
cs

 

문자인식 라이브러리도 아래와같이 초기화 해줍니다.

  var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);

 

문자인식에 사용할 그림파일을 아래와 같이 Pix 형식으로 불러옵니다.

Pix pix = PixConverter.ToPix(image); 

 

Process 함수가 현재 그림파일의 문자를 인식하는 함수입니다.
  var result = engine.Process(pix);

 

해당 결과같을 아래와 같은 형식으로 받을수 있습니다.
            result.GetText();

 

form 에 label1을 하나 추가하여 결과같을 보여줄수있도록 추가하였습니다.

 

위와같이 결과같이 정상적으로 출력이 된다면 정상적으로 진행한 상태입니다.

 

이번 강좌에서는 NuGet 패키지에서 Tesseract 검색 추가하여

문자 인식하는 함수를 사용해보았습니다.

 

다음강좌에서는 해당 값을 바탕으로

에너지가 일정 이하가 된다면

키보드 이벤트 or 마우스 이벤트를 발생시키는 부분을 진행하겠습니다.

728x90

이번에는

비주얼 스튜디오 2017 C# 으로 진행할 예정입니다.

https://developer.microsoft.com/ko-kr/windows/downloads

 

 

Visual Studio Community 설치하시면 됩니다.

설치시에 .net 데스크톱 개발을 선택해주세요~

 

프로젝트-> Windows Forms 로 생성 해주세요

 

 

 

폼 디자인으로 들어가셔서 아래와 같이 현재 에너지를 보여줄 PictureBox 하나랑

에너지 게이지 방 위치를 지정할 button1 하나를 생성해주세요

 

 

 

 

button1 번을 누르면 마우스 커서를 변경하고 에너지 위치를 지정해주는 부분을 만들어 보겠습니다.

먼저 button1 번을 더블클릭해주세요~

더블클릭하면 위와같이 함수가 생성됩니다.

 

폼1 에서 에너지바 위치를 저장할 변수를 선언합니다. x,y width, heigt

 

1
2
3
4
        public int mX = 0;
        public int mY = 0;
        public int mWidth = 0;
        public int mHeigt = 0;
cs

 

폼1 위에 전체화면으로 폼2를 그려줄려고 합니다.

아래와 같이 폼2를 추가해주세요

 

 

Form2 는 전체화면이면서 약간 투명한 화면을 가지고 그위에서 사용자가

리니지 에너지 바를 드래그해서 선택할수 있게 하려고 합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    public partial class Form2 : Form
    {
        Pen pen = new Pen(Color.Red);
        Rectangle rect;
 
        int mX = 0;
        int mY = 0;
 
        Boolean isHold = false;
 
        public Form2()
        {
            InitializeComponent();
 
            this.Opacity = 0.73;
 
 
 
//전체화면 설정 부분
 
            this.StartPosition = FormStartPosition.Manual;
            Rectangle fullScrenn_bounds = Rectangle.Empty;
            foreach (var screen in Screen.AllScreens)
            {
                fullScrenn_bounds = Rectangle.Union(fullScrenn_bounds, screen.Bounds);
            }
            this.ClientSize = new Size(fullScrenn_bounds.Width, fullScrenn_bounds.Height);
            this.Location = new Point(fullScrenn_bounds.Left, fullScrenn_bounds.Top);
 
           //전체화면 설정 부분
 
 
            Cursor = Cursors.Cross;
            this.Paint += new System.Windows.Forms.PaintEventHandler(Form2_Paint);
            this.MouseMove += new System.Windows.Forms.MouseEventHandler(Form2_MouseMove);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(Form2_MouseDown);
            this.MouseUp += new System.Windows.Forms.MouseEventHandler(Form2_MouseUp);
        }
 
 
 
        private void Form2_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(pen, rect);
        }
 
 
 
        private void Form2_MouseDown(object sender, MouseEventArgs e)
        {
            isHold = true;
            rect.Location = e.Location;
            mX = Cursor.Position.X;
            mY = Cursor.Position.Y;
        }
 
 
 
        private void Form2_MouseMove(object sender, MouseEventArgs e)
        {
            if (isHold)
            {
                int width = e.Location.X - rect.Location.X;
                int height = e.Location.Y - rect.Location.Y;
 
                rect.Width = width;
                rect.Height = height;
 
                this.Invalidate();
            }
        }
 
 
 
        private void Form2_MouseUp(object sender, MouseEventArgs e)
        {
            isHold = false;
            this.Opacity = 0.001;
 
            int width = e.Location.X - rect.Location.X;
            int height = e.Location.Y - rect.Location.Y;
 
            rect.Width = width;
            rect.Height = height;
 
            ((Form1)(this.Owner)).mX = mX;
            ((Form1)(this.Owner)).mY = mY;
 
            ((Form1)(this.Owner)).mWidth = rect.Width;
            ((Form1)(this.Owner)).mHeigt = rect.Height;
            Close();
        }
 
cs

 

 

마우스 다운/무브/업 을 체크해서 빨간색 사각형을 그려주는 소스 코드 입니다.

마우스가 업이 들어왔을때 FORM2를 종료하고 X,Y.Width, Height 값을 Form1으로 넘겨줍니다.

 

1
2
3
4
5
6
            ((Form1)(this.Owner)).mX = mX;
            ((Form1)(this.Owner)).mY = mY;
 
            ((Form1)(this.Owner)).mWidth = rect.Width;
            ((Form1)(this.Owner)).mHeigt = rect.Height;
 
cs

 

폼2가 할일은 여기서 끝입니다. 이제 사용자가 지정한 위치에 화면을 가져와서

Form 1에서 추가한 PictureBox 에 보여주도록 하겠습니다.

 

    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.ShowDialog(this);
 
            //Form2 가 close 된 후 아래 호출 됨 
 
 
 
            System.Drawing.Size mSize = new System.Drawing.Size(mWidth, mHeigt);
            Bitmap image = new Bitmap(mWidth, mHeigt);
            Graphics g = Graphics.FromImage(image);
 
            try
            {
                g.CopyFromScreen(mX, mY, 00, mSize);
            }
            catch (Win32Exception w)
            {
                Console.WriteLine(w.Message);
            }
 
          
            image = ResizeImage(image, pictureBox1.Width, pictureBox1.Height);
            pictureBox1.Image = image;
        }
 
 
 
        public static Bitmap ResizeImage(Image image, int width, int height)
        {
            var destRect = new Rectangle(00, width, height);
            var destImage = new Bitmap(width, height);
 
            destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
 
            using (var graphics = Graphics.FromImage(destImage))
            {
                graphics.CompositingMode = CompositingMode.SourceCopy;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
 
                using (var wrapMode = new ImageAttributes())
                {
                    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                    graphics.DrawImage(image, destRect, 00, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
                }
            }
 
            return destImage;
        }
 
 
cs

 

PictureBox 크기에 맞게 이미지를 조정하기 위해 ResizeImage 함수를 하나 추가했습니다.

폼2에서 가져온 위치와 크기만큼 캡쳐한 후 PictureBox 보여줍니다.

 

 

제 1강은 여기 까지 C#의 기본적인 사항으로 마치도록 하겠습니다.

 

다음 포스팅에서는 해당 이미지를 숫자인식이 잘되도록 흑백으로 변경 후

tessnet2 DLL 통해 숫자 인식 결과까지 나오게 하도록 하겠습니다.

 

궁금한점은 댓글로 달아주세요~

728x90

흥미위주의 예제를 찾다보니 모바일게임 매크로가 적당할 것 같아서 이번에 진행 해보려고 합니다.

아래 두가지가 키포인트로 생각 됩니다.

 

#1 게임상 숫자 인식하기 (Tesseract)

#2 유사 이미지 찾아내기 (opencv)

 

아래 링크는 완성 된 예제 파일입니다. 참고하세요~

http://yc0345.tistory.com/211

 

728x90

DLL 호출하고 나서 계속 저런 에러가 나서 프로그램이 종료되었다..

비쥬얼 스튜디오에서

Ctrl+Alt+E 를 누른 후

Under "Managed Debugging Assistants" PInvokeStackImbalance 항목을 uncheck 하면 된다.

 

 

728x90

+ Recent posts