상세 컨텐츠

본문 제목

[C#] 이미지 서칭 후 마우스 클릭하기

PROGRAMMING/C#

by 니콜 키크드만 2023. 2. 19. 17:04

본문

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace openCvPractice1
{
    public partial class Form2 : Form
    {
        [System.Runtime.InteropServices.DllImport("User32", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string IpClassName, string IpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        internal static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, int WParam, IntPtr IParam);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern IntPtr FindWindowEx(IntPtr Parent, IntPtr Child, string lpszClass, string lpszWindows);

        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);

        public const int WM_LBUTTONDOWN = 0x201; // 마우스 왼쪽 버튼 dwon
        public const int WM_LBUTTONUP = 0x202; // 마우스 왼쪽 버튼 up
        public IntPtr findWindow;
        public Form2()
        {
            InitializeComponent();
            this.button1.Click += new EventHandler(Button1_Click);
        }

        private void Button1_Click(object? sender, EventArgs e)
        {
            findWindow = FindWindow(null, "LDPlayer");
            Bitmap sendImg = new Bitmap(@"\img\test.png");
            if (findWindow != IntPtr.Zero)
            {
                //찾았을 경우
                Debug.WriteLine("찾았습니다");
                //찾은 프로그램을 바탕으로 Graphic 정보를 가져옵니다.
                Graphics Graphicsdata = Graphics.FromHwnd(findWindow);
                //찾은 프로그램 창 크기 및 위치를 가져옵니다.
                Rectangle rect = Rectangle.Round(Graphicsdata.VisibleClipBounds);
                //플레이어 창 크기 만큼의 비트맵을 선언해줍니다.
                Bitmap bmp = new Bitmap(rect.Width, rect.Height);
                //비트맵을 바탕으로 그래픽스 함수로 선언해줍니다.
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    //찾은 플레이어의 크기만큼 화면을 캡처합니다.
                    IntPtr hdc = g.GetHdc();
                    PrintWindow(findWindow, hdc, 0x2);
                    g.ReleaseHdc(hdc);
                }

                searchIMG(bmp, sendImg);
            }
            else
            {
                //못찾았을 경우
                Debug.WriteLine("못찾았어요");
            }
        }

        public void searchIMG(Bitmap screen_img, Bitmap find_img)
        {
            try
            {

                //스크린 이미지 선언
                using (Mat ScreenMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(screen_img))
                //찾을 이미지 선언
                using (Mat FindMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(find_img))

                // 스크린 이미지에서 FindMat 이미지를 찾아라
                using (Mat res = ScreenMat.MatchTemplate(FindMat, TemplateMatchModes.CCoeffNormed))
                {
                    //찾은 이미지의 유사도를 담을 더블형 최대 최소값을 선언
                    double minval, maxval = 0;
                    // 찾은 이미지의 위치를 담을 포인트형을 선언
                    OpenCvSharp.Point minloc, maxloc;
                    //찾은 이미지의 유사도 및 위치 값을 받습니다.
                    Cv2.MinMaxLoc(res, out minval, out maxval, out minloc, out maxloc);
                    Debug.WriteLine("찾은 이미지의 유사도: " + maxval);
                    //maxval 값이 0.7~1 사이 값이 나온다면 유사한 이미지를 찾았다고 생각하면됩니다.
                    // 찾은이미지 위치를 maxloc 변수에 저장하고 있습니다.
                    //InClick(150, 150);

                    if (maxval >= 0.8)
                    {
                        Debug.WriteLine("이미지를 찾았다" + maxloc.X + " " + maxloc.Y);
                        InClick(maxloc.X, maxloc.Y);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message.ToString());
            }
        }

        public void InClick(int x, int y)
        {
            try
            {
                Debug.WriteLine("클릭한다");
                //플레이어를 찾았을 경우 클릭이벤트를 발생시킬 핸들을 가져옵니다.
                IntPtr hwnd_child = FindWindowEx(findWindow, IntPtr.Zero, "RenderWindow", "TheRender");
                int Iparam = y << 16 | x;

                SendMessage(hwnd_child, WM_LBUTTONDOWN, 1, new IntPtr(Iparam));
                SendMessage(hwnd_child, WM_LBUTTONUP, 0, new IntPtr(Iparam));
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message.ToString());
            }
        }
    }
}

 

삽질 포인트

 

1) 캡처는 윈도우 캡처도구로 해야함. 다른거로 캡처하면 사진 채널이 달라서 컨버팅 해줘야 함.
2) FindWindow / FindWindowEx 의 차이점을 알아야 한다.

클릭이 안되서 삽질을 했는데 FindWindow로 찾은 핸들러를 넣어주니 클릭이 되었다..

반응형

'PROGRAMMING > C#' 카테고리의 다른 글

Visual Studio 12.0 실행 오류  (0) 2018.11.28

관련글 더보기

댓글 영역