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로 찾은 핸들러를 넣어주니 클릭이 되었다..
Visual Studio 12.0 실행 오류 (0) | 2018.11.28 |
---|
댓글 영역