From f73b18032938377969d9375166a60e9f6591c412 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 29 Jul 2024 15:04:22 +0900 Subject: [PATCH] Some works for #124 --- .../{TemplateMatching.cs => ScreenTimer.cs} | 110 ++++++++++++------ .../WelsonJS.Service/ServiceMain.cs | 60 ++++++---- .../WelsonJS.Service/WelsonJS.Service.csproj | 4 +- app.js | 10 +- 4 files changed, 124 insertions(+), 60 deletions(-) rename WelsonJS.Toolkit/WelsonJS.Service/{TemplateMatching.cs => ScreenTimer.cs} (55%) diff --git a/WelsonJS.Toolkit/WelsonJS.Service/TemplateMatching.cs b/WelsonJS.Toolkit/WelsonJS.Service/ScreenTimer.cs similarity index 55% rename from WelsonJS.Toolkit/WelsonJS.Service/TemplateMatching.cs rename to WelsonJS.Toolkit/WelsonJS.Service/ScreenTimer.cs index c7ff1f9..e37e77c 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/TemplateMatching.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/ScreenTimer.cs @@ -1,51 +1,85 @@ -// this is prototype code -// https://github.com/gnh1201/welsonjs +/* + * WelsonJS.Service + * + * filename: + * ScreenTimer.cs + * + * description: + * WelsonJS - Build a Windows app on the Windows built-in JavaScript engine + * + * website: + * - https://github.com/gnh1201/welsonjs + * - https://catswords.social/@catswords_oss + * - https://teams.live.com/l/community/FEACHncAhq8ldnojAI + * + * author: + * Namhyeon Go + * + * license: + * GPLv3 or MS-RL(Microsoft Reciprocal License) + */ using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.ServiceProcess; +using System.Timers; using System.Windows.Forms; using WelsonJS.Service; -public class TemplateMatching +public class ScreenTimer : System.Timers.Timer { - public void Test(string workingDirectory) + private static List templateImages = new List(); + private string templateDirectory; + + public string WorkingDirectory { get; set; } + public ServiceBase Parent { get; set; } + + public class MatchedResult { - string templateFolderPath = Path.Combine(workingDirectory, "assets/img/templates"); + public string FileName; + public int ScreenNumber; + public Point Location; + public double MaxCorrelation; + } - // Load all template images - List templateImages = LoadTemplateImages(templateFolderPath); + public ScreenTimer() + { + Elapsed += OnTimeElapsed; - // try template matching - List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)> results = - CaptureAndMatchAllScreens(templateImages); + templateDirectory = Path.Combine(WorkingDirectory, "assets/img/templates"); + LoadTemplateImages(); + } - // print results - foreach (var result in results) + private void OnTimeElapsed(object sender, ElapsedEventArgs e) + { + List matchedResults = CaptureAndMatchAllScreens(); + + ServiceMain svc = (ServiceMain)Parent; + matchedResults.ForEach(result => { - Console.WriteLine($"Template: {result.FileName}, Screen: {result.ScreenNumber}, " + - $"Location: (x: {result.Location.X}, y: {result.Location.Y}), " + - $"Max Correlation: {result.MaxCorrelation}"); + svc.Log(svc.DispatchServiceEvent("screenTime", new object[] { + result.FileName, + result.ScreenNumber, + result.Location.X, + result.Location.Y, + result.MaxCorrelation + })); + }); + } + + public void LoadTemplateImages() + { + string[] imageFiles = Directory.GetFiles(templateDirectory, "*.png"); + foreach (string file in imageFiles) + { + templateImages.Add(new Bitmap(file)); } } - public static List LoadTemplateImages(string folderPath) + public List CaptureAndMatchAllScreens() { - var templates = new List(); - var files = Directory.GetFiles(folderPath, "*.png"); - - foreach (var file in files) - { - templates.Add(new Bitmap(file)); - } - - return templates; - } - - public static List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)> - CaptureAndMatchAllScreens(List templateImages) - { - var results = new List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)>(); + var results = new List(); for (int i = 0; i < Screen.AllScreens.Length; i++) { @@ -57,14 +91,20 @@ public class TemplateMatching Point matchLocation = FindTemplate(mainImage, templateImage, out double maxCorrelation); string templateFileName = templateImage.Tag as string; - results.Add((templateFileName, i, matchLocation, maxCorrelation)); + results.Add(new MatchedResult + { + FileName = templateFileName, + ScreenNumber = i, + Location = matchLocation, + MaxCorrelation = maxCorrelation + }); } } return results; } - public static Bitmap CaptureScreen(Screen screen) + public Bitmap CaptureScreen(Screen screen) { Rectangle screenSize = screen.Bounds; Bitmap bitmap = new Bitmap(screenSize.Width, screenSize.Height); @@ -77,7 +117,7 @@ public class TemplateMatching return bitmap; } - public static Point FindTemplate(Bitmap mainImage, Bitmap templateImage, out double maxCorrelation) + public Point FindTemplate(Bitmap mainImage, Bitmap templateImage, out double maxCorrelation) { int mainWidth = mainImage.Width; int mainHeight = mainImage.Height; @@ -103,7 +143,7 @@ public class TemplateMatching return bestMatch; } - private static double CalculateCorrelation(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY) + private double CalculateCorrelation(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY) { int templateWidth = templateImage.Width; int templateHeight = templateImage.Height; diff --git a/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs b/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs index 3841d3a..02e6ea3 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs @@ -35,6 +35,7 @@ namespace WelsonJS.Service private static List timers; private string workingDirectory; private string scriptName; + private bool disabledScreenTimer = false; private string scriptFilePath; private string scriptText; private ScriptControl scriptControl; @@ -52,12 +53,23 @@ namespace WelsonJS.Service timers = new List(); // set default timer - Timer timer = new Timer + Timer defaultTimer = new Timer { Interval = 60000 // 1 minute }; - timer.Elapsed += OnElapsedTime; - timers.Add(timer); + defaultTimer.Elapsed += OnElapsedTime; + timers.Add(defaultTimer); + + // set screen timer + if (!disabledScreenTimer) + { + timers.Add(new ScreenTimer + { + Parent = this, + WorkingDirectory = workingDirectory, + Interval = 1000 // 1 second + }); + } } internal void TestStartupAndStop(string[] args) @@ -82,6 +94,10 @@ namespace WelsonJS.Service case "script-name": scriptName = entry.Value; break; + + case "--disable-screen-timer": + disabledScreenTimer = true; + break; } } @@ -127,7 +143,7 @@ namespace WelsonJS.Service scriptControl.AddCode(scriptText); // initialize - Log(DispatchServiceEvent(scriptName, "start")); + Log(DispatchServiceEvent("start")); } catch (Exception ex) { @@ -152,7 +168,7 @@ namespace WelsonJS.Service try { - Log(DispatchServiceEvent(scriptName, "stop")); + Log(DispatchServiceEvent("stop")); scriptControl?.Reset(); } catch (Exception ex) @@ -168,7 +184,7 @@ namespace WelsonJS.Service { try { - Log(DispatchServiceEvent(scriptName, "elapsedTime")); + Log(DispatchServiceEvent("elapsedTime")); } catch (Exception ex) { @@ -176,11 +192,6 @@ namespace WelsonJS.Service } } - private string DispatchServiceEvent(string name, string eventType) - { - return InvokeScriptMethod("dispatchServiceEvent", name, eventType); - } - private string InvokeScriptMethod(string methodName, params object[] parameters) { if (scriptControl != null) @@ -195,15 +206,6 @@ namespace WelsonJS.Service return "void"; } - - private void Log(string message) - { - using (StreamWriter writer = new StreamWriter(logFilePath, true)) - { - writer.WriteLine($"{DateTime.Now}: {message}"); - } - } - private Dictionary ParseArguments(string[] args) { var arguments = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -219,12 +221,30 @@ namespace WelsonJS.Service var value = arg.Substring(index + 1); arguments[key] = value; } + else + { + var key = arg.Substring(2); + arguments[key] = ""; + } } } return arguments; } + public void Log(string message) + { + using (StreamWriter writer = new StreamWriter(logFilePath, true)) + { + writer.WriteLine($"{DateTime.Now}: {message}"); + } + } + + public string DispatchServiceEvent(string eventType, object[] args = null) + { + return InvokeScriptMethod("dispatchServiceEvent", scriptName, eventType, args); + } + public string GetWorkingDirectory() { return workingDirectory; diff --git a/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj b/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj index 4965e9c..e1534fb 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj +++ b/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj @@ -90,6 +90,9 @@ + + Component + Component @@ -104,7 +107,6 @@ ProjectInstaller.cs - diff --git a/app.js b/app.js index c943b2a..1ea8cba 100644 --- a/app.js +++ b/app.js @@ -589,7 +589,7 @@ function initializeWindow(name, args, w, h) { } } -function dispatchServiceEvent(name, eventType) { +function dispatchServiceEvent(name, eventType, args) { var app = require(name); // load the service @@ -597,8 +597,9 @@ function dispatchServiceEvent(name, eventType) { return (function(action) { if (eventType in action) { try { - var f = action[eventType]; - if (typeof f === "function") return f(); + return (function(f) { + return (typeof f !== "function" ? null : f(args)); + })(action[eventType]); } catch (e) { console.error("Exception:", e.message); } @@ -606,7 +607,8 @@ function dispatchServiceEvent(name, eventType) { })({ start: app.onServiceStart, stop: app.onServiceStop, - elapsedTime: app.onServiceElapsedTime + elapsedTime: app.onServiceElapsedTime, + screenTime: app.onServiceScreenTime }); } else { console.error("Could not find", name + ".js");