using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using WelsonJS.Service; public class ScreenMatching { // User32.dll API 함수 선언 [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll")] public static extern int GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] public static extern IntPtr GetDC(IntPtr hWnd); [DllImport("user32.dll")] public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); [DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll")] public static extern int GetWindowTextLength(IntPtr hWnd); [DllImport("gdi32.dll")] private static extern bool BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop); private const int SRCCOPY = 0x00CC0020; // 델리게이트 선언 public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); // RECT 구조체 선언 [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } public List templateImages; string templateFolderPath; public ScreenMatching(string workingDirectory) { templateFolderPath = Path.Combine(workingDirectory, "app/assets/img/_templates"); templateImages = new List(); LoadTemplateImages(); } public void LoadTemplateImages() { var files = System.IO.Directory.GetFiles(templateFolderPath, "*.png"); foreach (var file in files) { Bitmap bitmap = new Bitmap(file); bitmap.Tag = System.IO.Path.GetFileName(file); templateImages.Add(bitmap); } } // 화면을 기준으로 찾기 public List CaptureAndMatchAllScreens() { var results = new List(); for (int i = 0; i < Screen.AllScreens.Length; i++) { Screen screen = Screen.AllScreens[i]; Bitmap mainImage = CaptureScreen(screen); foreach (Bitmap templateImage in templateImages) { Point matchLocation = FindTemplate(mainImage, (Bitmap)templateImage.Clone(), out double maxCorrelation); results.Add(new ScreenMatchResult { FileName = templateImage.Tag.ToString(), ScreenNumber = i, Location = matchLocation, MaxCorrelation = maxCorrelation }); } } return results; } public static Bitmap CaptureScreen(Screen screen) { Rectangle screenSize = screen.Bounds; Bitmap bitmap = new Bitmap(screenSize.Width, screenSize.Height); using (Graphics g = Graphics.FromImage(bitmap)) { g.CopyFromScreen(screenSize.Left, screenSize.Top, 0, 0, screenSize.Size); } return bitmap; } // 윈도우 핸들을 기준으로 찾기 public List CaptureAndMatchAllWindows() { var results = new List(); // 모든 윈도우 핸들을 열거 EnumWindows((hWnd, lParam) => { if (IsWindowVisible(hWnd)) { try { string windowTitle = GetWindowTitle(hWnd); Bitmap windowImage = CaptureWindow(hWnd); if (windowImage != null) { foreach (var templateImage in templateImages) { Point matchLocation = FindTemplate(windowImage, templateImage, out double maxCorrelation); string templateFileName = templateImage.Tag as string; var result = new ScreenMatchResult { FileName = templateFileName, WindowHandle = hWnd, WindowTitle = windowTitle, Location = matchLocation, MaxCorrelation = maxCorrelation }; results.Add(result); } } } catch { } } return true; }, IntPtr.Zero); return results; } public string GetWindowTitle(IntPtr hWnd) { int length = GetWindowTextLength(hWnd); StringBuilder sb = new StringBuilder(length + 1); GetWindowText(hWnd, sb, sb.Capacity); return sb.ToString(); } public Bitmap CaptureWindow(IntPtr hWnd) { GetWindowRect(hWnd, out RECT rect); int width = rect.Right - rect.Left; int height = rect.Bottom - rect.Top; if (width <= 0 || height <= 0) return null; Bitmap bitmap = new Bitmap(width, height); Graphics graphics = Graphics.FromImage(bitmap); IntPtr hDC = graphics.GetHdc(); IntPtr windowDC = GetDC(hWnd); bool success = BitBlt(hDC, 0, 0, width, height, windowDC, 0, 0, SRCCOPY); ReleaseDC(hWnd, windowDC); graphics.ReleaseHdc(hDC); return success ? bitmap : null; } public Point FindTemplate(Bitmap mainImage, Bitmap templateImage, out double maxCorrelation) { int mainWidth = mainImage.Width; int mainHeight = mainImage.Height; int templateWidth = templateImage.Width; int templateHeight = templateImage.Height; Point bestMatch = Point.Empty; maxCorrelation = 0; for (int x = 0; x <= mainWidth - templateWidth; x++) { for (int y = 0; y <= mainHeight - templateHeight; y++) { if (IsTemplateMatch(mainImage, templateImage, x, y)) { bestMatch = new Point(x, y); maxCorrelation = 1; // 완전 일치 return bestMatch; } } } return bestMatch; } private bool IsTemplateMatch(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY) { int templateWidth = templateImage.Width; int templateHeight = templateImage.Height; for (int x = 0; x < templateWidth; x++) { for (int y = 0; y < templateHeight; y++) { if (mainImage.GetPixel(x + offsetX, y + offsetY) != templateImage.GetPixel(x, y)) { return false; } } } return true; } }