├── .gitignore ├── GenshinBalladsOfBreezeAider ├── App.config ├── obj │ └── Debug │ │ └── .NETFramework,Version=v4.5.AssemblyAttributes.cs ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Program.cs ├── GenshinBalladsOfBreezeAider.csproj ├── frmMain.resx ├── frmMain.Designer.cs └── frmMain.cs ├── README.md └── GenshinBalladsOfBreezeAider.sln /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | *.cache 3 | GenshinBalladsOfBreezeAider/obj/ 4 | GenshinBalladsOfBreezeAider/bin/ 5 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] 5 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GenshinBalladsOfBreezeAider 2 | 3 | ### 2022.06.29(荒泷极上盛世豪鼓大祭典版本)说明 4 | 5 | 支持了自动点按 6 | 7 | 由于命中特效变大变华丽了导致影响了下一拍的识别, 以及长按弹起的图层放到了判定点标志的下面所以长按识别非常不稳定, 干脆砍掉了 8 | 9 | 我直接摆烂用自动点按+手动长按过任务拿奖励就算了, 不调参了 10 | 11 | ### 2021.10.21(镜花听世版本)说明 12 | 13 | 现已支持镜花听世活动的长按操作 14 | 15 | 添加F10快捷键开启自动演奏 16 | 17 | ### 以下是风物之歌版本的说明: 18 | 19 | 原神风花节风物之歌音游辅助程序, 能够自动演奏, 1920*1080分辨率下自测大师难度能全连 20 | 21 | 只是用简单的屏幕像素颜色识别和模拟按键实现的, 判断黄圈挡住黑圈的时候模拟按下对应的键, 低分辨率下识别率会比较低 22 | 23 | "更改文本、应用等项目的大小"不是100%的时候可能会由于换算小数结果不在预期导致识别位置偏差 24 | 25 | 食用方法: 26 | 27 | 1.以管理员身份运行本程序 28 | 29 | 2.打开原神到风物之歌选择难度界面 30 | 31 | 3.切换到桌面, 点击本程序的开始自动演奏 32 | 33 | 4.切换回原神, 点击开始演奏 34 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace GenshinBalladsOfBreezeAider.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("GenshinBalladsOfBreezeAider")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GenshinBalladsOfBreezeAider")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("8f757167-5c25-4d6f-af68-5940dd1f2021")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenshinBalladsOfBreezeAider", "GenshinBalladsOfBreezeAider\GenshinBalladsOfBreezeAider.csproj", "{8F757167-5C25-4D6F-AF68-5940DD1F2021}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {8F757167-5C25-4D6F-AF68-5940DD1F2021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {8F757167-5C25-4D6F-AF68-5940DD1F2021}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {8F757167-5C25-4D6F-AF68-5940DD1F2021}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {8F757167-5C25-4D6F-AF68-5940DD1F2021}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {A0BD4C93-75E0-4AB4-9436-C14D7E6081CB} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Security.Principal; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace GenshinBalladsOfBreezeAider 10 | { 11 | static class Program 12 | { 13 | /// 14 | /// 应用程序的主入口点。 15 | /// 16 | [STAThread] 17 | static void Main() 18 | { 19 | Application.EnableVisualStyles(); 20 | Application.SetCompatibleTextRenderingDefault(false); 21 | WindowsIdentity identity = WindowsIdentity.GetCurrent(); 22 | WindowsPrincipal principal = new WindowsPrincipal(identity); 23 | if (principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)) 24 | { 25 | Application.Run(new frmMain()); 26 | } 27 | else 28 | { 29 | ProcessStartInfo startInfo = new ProcessStartInfo(); 30 | startInfo.FileName = Application.ExecutablePath; 31 | startInfo.Arguments = string.Join(" ", ""); 32 | startInfo.Verb = "runas"; 33 | Process.Start(startInfo); 34 | Application.Exit(); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace GenshinBalladsOfBreezeAider.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GenshinBalladsOfBreezeAider.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性,对 51 | /// 使用此强类型资源类的所有资源查找执行重写。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/GenshinBalladsOfBreezeAider.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8F757167-5C25-4D6F-AF68-5940DD1F2021} 8 | WinExe 9 | GenshinBalladsOfBreezeAider 10 | GenshinBalladsOfBreezeAider 11 | v4.7.2 12 | 8.0 13 | 512 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | false 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Form 61 | 62 | 63 | frmMain.cs 64 | 65 | 66 | 67 | 68 | frmMain.cs 69 | 70 | 71 | ResXFileCodeGenerator 72 | Resources.Designer.cs 73 | Designer 74 | 75 | 76 | True 77 | Resources.resx 78 | True 79 | 80 | 81 | SettingsSingleFileGenerator 82 | Settings.Designer.cs 83 | 84 | 85 | True 86 | Settings.settings 87 | True 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/frmMain.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/frmMain.Designer.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace GenshinBalladsOfBreezeAider 3 | { 4 | partial class frmMain 5 | { 6 | /// 7 | /// 必需的设计器变量。 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// 清理所有正在使用的资源。 13 | /// 14 | /// 如果应释放托管资源,为 true;否则为 false。 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows 窗体设计器生成的代码 25 | 26 | /// 27 | /// 设计器支持所需的方法 - 不要修改 28 | /// 使用代码编辑器修改此方法的内容。 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.btnStart = new System.Windows.Forms.Button(); 33 | this.lblStatus = new System.Windows.Forms.Label(); 34 | this.lblStatusTitle = new System.Windows.Forms.Label(); 35 | this.groupGenshinProcess = new System.Windows.Forms.GroupBox(); 36 | this.lblWarring = new System.Windows.Forms.Label(); 37 | this.lblDpi = new System.Windows.Forms.Label(); 38 | this.lblRatio = new System.Windows.Forms.Label(); 39 | this.lblDpiTitle = new System.Windows.Forms.Label(); 40 | this.lblRatioTitle = new System.Windows.Forms.Label(); 41 | this.btnDebugScreenshot = new System.Windows.Forms.Button(); 42 | this.lblWindowSize = new System.Windows.Forms.Label(); 43 | this.lblWindowSizeTitle = new System.Windows.Forms.Label(); 44 | this.lblWindowLocation = new System.Windows.Forms.Label(); 45 | this.lblWindowLocationTitle = new System.Windows.Forms.Label(); 46 | this.lblWindowType = new System.Windows.Forms.Label(); 47 | this.lblWindowTypeTitle = new System.Windows.Forms.Label(); 48 | this.debugTextBox = new System.Windows.Forms.TextBox(); 49 | this.groupGenshinProcess.SuspendLayout(); 50 | this.SuspendLayout(); 51 | // 52 | // btnStart 53 | // 54 | this.btnStart.Enabled = false; 55 | this.btnStart.Location = new System.Drawing.Point(122, 241); 56 | this.btnStart.Name = "btnStart"; 57 | this.btnStart.Size = new System.Drawing.Size(120, 30); 58 | this.btnStart.TabIndex = 0; 59 | this.btnStart.Text = "开始自动演奏(F10)"; 60 | this.btnStart.UseVisualStyleBackColor = true; 61 | this.btnStart.Click += new System.EventHandler(this.btnStart_Click); 62 | // 63 | // lblStatus 64 | // 65 | this.lblStatus.AutoSize = true; 66 | this.lblStatus.ForeColor = System.Drawing.Color.Red; 67 | this.lblStatus.Location = new System.Drawing.Point(120, 23); 68 | this.lblStatus.Name = "lblStatus"; 69 | this.lblStatus.Size = new System.Drawing.Size(89, 12); 70 | this.lblStatus.TabIndex = 1; 71 | this.lblStatus.Text = "未找到原神进程"; 72 | // 73 | // lblStatusTitle 74 | // 75 | this.lblStatusTitle.AutoSize = true; 76 | this.lblStatusTitle.Location = new System.Drawing.Point(49, 23); 77 | this.lblStatusTitle.Name = "lblStatusTitle"; 78 | this.lblStatusTitle.Size = new System.Drawing.Size(65, 12); 79 | this.lblStatusTitle.TabIndex = 2; 80 | this.lblStatusTitle.Text = "程序状态:"; 81 | // 82 | // groupGenshinProcess 83 | // 84 | this.groupGenshinProcess.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 85 | | System.Windows.Forms.AnchorStyles.Right))); 86 | this.groupGenshinProcess.Controls.Add(this.lblWarring); 87 | this.groupGenshinProcess.Controls.Add(this.lblDpi); 88 | this.groupGenshinProcess.Controls.Add(this.lblRatio); 89 | this.groupGenshinProcess.Controls.Add(this.lblDpiTitle); 90 | this.groupGenshinProcess.Controls.Add(this.lblRatioTitle); 91 | this.groupGenshinProcess.Controls.Add(this.btnDebugScreenshot); 92 | this.groupGenshinProcess.Controls.Add(this.lblWindowSize); 93 | this.groupGenshinProcess.Controls.Add(this.lblWindowSizeTitle); 94 | this.groupGenshinProcess.Controls.Add(this.lblWindowLocation); 95 | this.groupGenshinProcess.Controls.Add(this.lblWindowLocationTitle); 96 | this.groupGenshinProcess.Controls.Add(this.lblWindowType); 97 | this.groupGenshinProcess.Controls.Add(this.lblWindowTypeTitle); 98 | this.groupGenshinProcess.Location = new System.Drawing.Point(22, 53); 99 | this.groupGenshinProcess.Name = "groupGenshinProcess"; 100 | this.groupGenshinProcess.Size = new System.Drawing.Size(304, 181); 101 | this.groupGenshinProcess.TabIndex = 4; 102 | this.groupGenshinProcess.TabStop = false; 103 | this.groupGenshinProcess.Text = "原神窗口信息"; 104 | // 105 | // lblWarring 106 | // 107 | this.lblWarring.ForeColor = System.Drawing.Color.Red; 108 | this.lblWarring.Location = new System.Drawing.Point(6, 140); 109 | this.lblWarring.Name = "lblWarring"; 110 | this.lblWarring.Size = new System.Drawing.Size(283, 38); 111 | this.lblWarring.TabIndex = 9; 112 | // 113 | // lblDpi 114 | // 115 | this.lblDpi.AutoSize = true; 116 | this.lblDpi.Location = new System.Drawing.Point(126, 117); 117 | this.lblDpi.Name = "lblDpi"; 118 | this.lblDpi.Size = new System.Drawing.Size(29, 12); 119 | this.lblDpi.TabIndex = 8; 120 | this.lblDpi.Text = "未知"; 121 | // 122 | // lblRatio 123 | // 124 | this.lblRatio.AutoSize = true; 125 | this.lblRatio.Location = new System.Drawing.Point(126, 93); 126 | this.lblRatio.Name = "lblRatio"; 127 | this.lblRatio.Size = new System.Drawing.Size(29, 12); 128 | this.lblRatio.TabIndex = 8; 129 | this.lblRatio.Text = "未知"; 130 | // 131 | // lblDpiTitle 132 | // 133 | this.lblDpiTitle.AutoSize = true; 134 | this.lblDpiTitle.Location = new System.Drawing.Point(7, 117); 135 | this.lblDpiTitle.Name = "lblDpiTitle"; 136 | this.lblDpiTitle.Size = new System.Drawing.Size(35, 12); 137 | this.lblDpiTitle.TabIndex = 7; 138 | this.lblDpiTitle.Text = "DPI:"; 139 | // 140 | // lblRatioTitle 141 | // 142 | this.lblRatioTitle.AutoSize = true; 143 | this.lblRatioTitle.Location = new System.Drawing.Point(6, 93); 144 | this.lblRatioTitle.Name = "lblRatioTitle"; 145 | this.lblRatioTitle.Size = new System.Drawing.Size(53, 12); 146 | this.lblRatioTitle.TabIndex = 7; 147 | this.lblRatioTitle.Text = "长宽比:"; 148 | // 149 | // btnDebugScreenshot 150 | // 151 | this.btnDebugScreenshot.Location = new System.Drawing.Point(216, 41); 152 | this.btnDebugScreenshot.Name = "btnDebugScreenshot"; 153 | this.btnDebugScreenshot.Size = new System.Drawing.Size(75, 23); 154 | this.btnDebugScreenshot.TabIndex = 6; 155 | this.btnDebugScreenshot.Text = "显示位置"; 156 | this.btnDebugScreenshot.UseVisualStyleBackColor = true; 157 | this.btnDebugScreenshot.Visible = false; 158 | this.btnDebugScreenshot.Click += new System.EventHandler(this.btnDebugScreenshot_Click); 159 | // 160 | // lblWindowSize 161 | // 162 | this.lblWindowSize.AutoSize = true; 163 | this.lblWindowSize.Location = new System.Drawing.Point(126, 69); 164 | this.lblWindowSize.Name = "lblWindowSize"; 165 | this.lblWindowSize.Size = new System.Drawing.Size(29, 12); 166 | this.lblWindowSize.TabIndex = 0; 167 | this.lblWindowSize.Text = "未知"; 168 | // 169 | // lblWindowSizeTitle 170 | // 171 | this.lblWindowSizeTitle.AutoSize = true; 172 | this.lblWindowSizeTitle.Location = new System.Drawing.Point(6, 69); 173 | this.lblWindowSizeTitle.Name = "lblWindowSizeTitle"; 174 | this.lblWindowSizeTitle.Size = new System.Drawing.Size(53, 12); 175 | this.lblWindowSizeTitle.TabIndex = 0; 176 | this.lblWindowSizeTitle.Text = "分辨率:"; 177 | // 178 | // lblWindowLocation 179 | // 180 | this.lblWindowLocation.AutoSize = true; 181 | this.lblWindowLocation.Location = new System.Drawing.Point(126, 45); 182 | this.lblWindowLocation.Name = "lblWindowLocation"; 183 | this.lblWindowLocation.Size = new System.Drawing.Size(29, 12); 184 | this.lblWindowLocation.TabIndex = 0; 185 | this.lblWindowLocation.Text = "未知"; 186 | // 187 | // lblWindowLocationTitle 188 | // 189 | this.lblWindowLocationTitle.AutoSize = true; 190 | this.lblWindowLocationTitle.Location = new System.Drawing.Point(6, 45); 191 | this.lblWindowLocationTitle.Name = "lblWindowLocationTitle"; 192 | this.lblWindowLocationTitle.Size = new System.Drawing.Size(77, 12); 193 | this.lblWindowLocationTitle.TabIndex = 0; 194 | this.lblWindowLocationTitle.Text = "左上角坐标:"; 195 | // 196 | // lblWindowType 197 | // 198 | this.lblWindowType.AutoSize = true; 199 | this.lblWindowType.Location = new System.Drawing.Point(126, 21); 200 | this.lblWindowType.Name = "lblWindowType"; 201 | this.lblWindowType.Size = new System.Drawing.Size(29, 12); 202 | this.lblWindowType.TabIndex = 0; 203 | this.lblWindowType.Text = "未知"; 204 | // 205 | // lblWindowTypeTitle 206 | // 207 | this.lblWindowTypeTitle.AutoSize = true; 208 | this.lblWindowTypeTitle.Location = new System.Drawing.Point(7, 21); 209 | this.lblWindowTypeTitle.Name = "lblWindowTypeTitle"; 210 | this.lblWindowTypeTitle.Size = new System.Drawing.Size(65, 12); 211 | this.lblWindowTypeTitle.TabIndex = 0; 212 | this.lblWindowTypeTitle.Text = "窗口状态:"; 213 | // 214 | // debugTextBox 215 | // 216 | this.debugTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 217 | | System.Windows.Forms.AnchorStyles.Left) 218 | | System.Windows.Forms.AnchorStyles.Right))); 219 | this.debugTextBox.Location = new System.Drawing.Point(11, 275); 220 | this.debugTextBox.Margin = new System.Windows.Forms.Padding(2); 221 | this.debugTextBox.Multiline = true; 222 | this.debugTextBox.Name = "debugTextBox"; 223 | this.debugTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 224 | this.debugTextBox.Size = new System.Drawing.Size(315, 6); 225 | this.debugTextBox.TabIndex = 5; 226 | this.debugTextBox.Visible = false; 227 | // 228 | // frmMain 229 | // 230 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 231 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 232 | this.ClientSize = new System.Drawing.Size(348, 283); 233 | this.Controls.Add(this.debugTextBox); 234 | this.Controls.Add(this.groupGenshinProcess); 235 | this.Controls.Add(this.lblStatusTitle); 236 | this.Controls.Add(this.lblStatus); 237 | this.Controls.Add(this.btnStart); 238 | this.MaximizeBox = false; 239 | this.MinimizeBox = false; 240 | this.Name = "frmMain"; 241 | this.Text = "原神风物之歌/镜花听世辅助程序"; 242 | this.groupGenshinProcess.ResumeLayout(false); 243 | this.groupGenshinProcess.PerformLayout(); 244 | this.ResumeLayout(false); 245 | this.PerformLayout(); 246 | 247 | } 248 | 249 | #endregion 250 | 251 | private System.Windows.Forms.Button btnStart; 252 | private System.Windows.Forms.Label lblStatus; 253 | private System.Windows.Forms.Label lblStatusTitle; 254 | private System.Windows.Forms.GroupBox groupGenshinProcess; 255 | private System.Windows.Forms.Label lblWindowSize; 256 | private System.Windows.Forms.Label lblWindowSizeTitle; 257 | private System.Windows.Forms.Label lblWindowLocation; 258 | private System.Windows.Forms.Label lblWindowLocationTitle; 259 | private System.Windows.Forms.Label lblWindowType; 260 | private System.Windows.Forms.Label lblWindowTypeTitle; 261 | private System.Windows.Forms.TextBox debugTextBox; 262 | private System.Windows.Forms.Button btnDebugScreenshot; 263 | private System.Windows.Forms.Label lblRatio; 264 | private System.Windows.Forms.Label lblRatioTitle; 265 | private System.Windows.Forms.Label lblDpi; 266 | private System.Windows.Forms.Label lblDpiTitle; 267 | private System.Windows.Forms.Label lblWarring; 268 | } 269 | } 270 | 271 | -------------------------------------------------------------------------------- /GenshinBalladsOfBreezeAider/frmMain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Reflection; 7 | using System.Runtime.InteropServices; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace GenshinBalladsOfBreezeAider 12 | { 13 | public partial class frmMain : Form 14 | { 15 | private int genshinWindowX = 0; 16 | private int genshinWindowY = 0; 17 | private int genshinWindowWdith = 0; 18 | private int genshinWindowHeight = 0; 19 | private bool working = false; 20 | 21 | #region -- 按键钩子 -- 22 | [DllImport("user32.dll", EntryPoint = "keybd_event")] 23 | public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); 24 | #endregion --按键钩子 -- 25 | 26 | #region -- 窗口钩子 -- 27 | [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)] 28 | private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 29 | 30 | [DllImport("user32.dll")] 31 | private static extern int GetWindowRect(IntPtr hwnd, out Rectangle lpRect); 32 | 33 | [DllImport("user32.dll")] 34 | private static extern bool GetClientRect(IntPtr hwnd, out Rectangle lpRect); 35 | 36 | [DllImport("user32.dll")] 37 | private static extern IntPtr GetDC(IntPtr ptr); 38 | [DllImport("gdi32.dll")] 39 | private static extern int GetDeviceCaps(IntPtr hdc, int nIndex); 40 | [DllImport("user32.dll", EntryPoint = "ReleaseDC")] 41 | private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc); 42 | 43 | const int HORZRES = 8; 44 | const int VERTRES = 10; 45 | const int DESKTOPVERTRES = 117; 46 | const int DESKTOPHORZRES = 118; 47 | 48 | private IntPtr hwndGenshin = IntPtr.Zero; 49 | #endregion -- 窗口钩子 -- 50 | 51 | #region -- 按键监听钩子 -- 52 | protected delegate int HookProc(int nCode, int wParam, IntPtr lParam); 53 | 54 | [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 55 | protected static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId); 56 | 57 | [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 58 | protected static extern int UnhookWindowsHookEx(int idHook); 59 | 60 | [StructLayout(LayoutKind.Sequential)] 61 | protected class KeyboardHookStruct 62 | { 63 | public int vkCode; 64 | public int scanCode; 65 | public int flags; 66 | public int time; 67 | public int dwExtraInfo; 68 | } 69 | 70 | protected int _handleToHook; 71 | protected HookProc _hookCallback; 72 | #endregion -- 按键监听钩子 -- 73 | 74 | public static float DpiScaleX 75 | { 76 | get 77 | { 78 | IntPtr hdc = GetDC(IntPtr.Zero); 79 | float ScaleX = (float)GetDeviceCaps(hdc, DESKTOPHORZRES) / (float)GetDeviceCaps(hdc, HORZRES); 80 | ReleaseDC(IntPtr.Zero, hdc); 81 | return ScaleX; 82 | } 83 | } 84 | 85 | public static float DpiScaleY 86 | { 87 | get 88 | { 89 | IntPtr hdc = GetDC(IntPtr.Zero); 90 | float ScaleY = (float)(float)GetDeviceCaps(hdc, DESKTOPVERTRES) / (float)GetDeviceCaps(hdc, VERTRES); 91 | ReleaseDC(IntPtr.Zero, hdc); 92 | return ScaleY; 93 | } 94 | } 95 | 96 | public frmMain() => InitializeComponent(); 97 | 98 | protected override void OnShown(EventArgs e) 99 | { 100 | base.OnShown(e); 101 | #if DEBUG 102 | btnDebugScreenshot.Visible = true; 103 | debugTextBox.Visible = true; 104 | #endif 105 | _hookCallback = new HookProc(HookCallbackProcedure); 106 | _handleToHook = SetWindowsHookEx(13, _hookCallback, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0); 107 | 108 | FindGenshinProcess(); 109 | } 110 | 111 | protected override void OnClosing(CancelEventArgs e) 112 | { 113 | UnhookWindowsHookEx(_handleToHook); 114 | Process.GetCurrentProcess().Kill(); 115 | base.OnClosing(e); 116 | } 117 | 118 | private int HookCallbackProcedure(int nCode, int wParam, IntPtr lParam) 119 | { 120 | KeyboardHookStruct keyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); 121 | if (wParam == 0x100 || wParam == 0x104) //KeyDown事件 122 | { 123 | switch (keyboardHookStruct.vkCode) 124 | { 125 | case (int)Keys.F12: 126 | SaveDebugImage(); 127 | break; 128 | case (int)Keys.F11: 129 | Invoke(new Action(() => debugTextBox.AppendText($"{DateTime.Now.ToString("HH:mm:ss fff")}\r\n"))); 130 | break; 131 | case (int)Keys.F10: 132 | Start(); 133 | break; 134 | } 135 | } 136 | return 0; 137 | } 138 | 139 | private void FindGenshinProcess() 140 | { 141 | lblStatus.Text = $"未找到原神进程"; 142 | lblStatus.ForeColor = Color.Red; 143 | Task.Run(() => 144 | { 145 | while (!working) 146 | { 147 | while (hwndGenshin == IntPtr.Zero) 148 | { 149 | hwndGenshin = FindWindow("UnityWndClass", "原神"); 150 | Task.Delay(100).Wait(); 151 | } 152 | 153 | GetWindowRect(hwndGenshin, out Rectangle windowRect); 154 | GetClientRect(hwndGenshin, out Rectangle clientRect); 155 | 156 | Invoke(new Action(() => 157 | { 158 | try 159 | { 160 | if (!working) 161 | { 162 | lblStatus.Text = $"已找到原神进程,未开始自动演奏"; 163 | lblStatus.ForeColor = Color.Black; 164 | } 165 | 166 | if (windowRect.X < -16000 || (windowRect.X == 0 && windowRect.Y == 0 && windowRect.Width == Screen.PrimaryScreen.Bounds.Width && windowRect.Height == Screen.PrimaryScreen.Bounds.Height)) //全屏 167 | { 168 | genshinWindowX = 0; 169 | genshinWindowY = 0; 170 | genshinWindowWdith = (int)Math.Round(Screen.PrimaryScreen.Bounds.Width * DpiScaleX); 171 | genshinWindowHeight = (int)Math.Round(Screen.PrimaryScreen.Bounds.Height * DpiScaleY); 172 | 173 | lblWindowType.Text = "全屏"; 174 | lblWindowLocation.Text = $"(0,0)"; 175 | } 176 | else //窗口化 177 | { 178 | Rectangle tempRect = new Rectangle(windowRect.X, windowRect.Y, windowRect.Width - windowRect.X, windowRect.Height - windowRect.Y); 179 | Rectangle rect = new Rectangle(tempRect.X + (tempRect.Width - clientRect.Width) - 3, tempRect.Y + (tempRect.Height - clientRect.Height) - 3, clientRect.Width, clientRect.Height); 180 | 181 | if (DpiScaleX > 1 || DpiScaleY > 1) 182 | rect = new Rectangle((int)Math.Round(rect.X * DpiScaleX), (int)Math.Round(rect.Y * DpiScaleY), (int)Math.Round(rect.Width * DpiScaleX), (int)Math.Round(rect.Height * DpiScaleY)); 183 | 184 | genshinWindowX = rect.X; 185 | genshinWindowY = rect.Y; 186 | genshinWindowWdith = rect.Width; 187 | genshinWindowHeight = rect.Height; 188 | 189 | lblWindowType.Text = "窗口化"; 190 | lblWindowLocation.Text = $"({genshinWindowX},{genshinWindowY})"; 191 | } 192 | 193 | lblDpi.Text = $"{DpiScaleX * 100}%"; 194 | 195 | if (genshinWindowWdith / 16 * 9 == genshinWindowHeight) 196 | { 197 | lblRatio.Text = "16:9"; 198 | lblRatio.ForeColor = Color.Black; 199 | lblWarring.Text = ""; 200 | 201 | if (DpiScaleX != 1) 202 | lblWarring.Text = "您显示设置-更改文本、应用等项目的大小不是100%,可能在坐标换算中产生偏移。"; 203 | } 204 | else 205 | { 206 | if (genshinWindowWdith / 16 * 10 == genshinWindowHeight) 207 | lblRatio.Text = "16:10"; 208 | else if (genshinWindowWdith / 4 * 3 == genshinWindowHeight) 209 | lblRatio.Text = "4:3"; 210 | else if (genshinWindowWdith / 5 * 4 == genshinWindowHeight) 211 | lblRatio.Text = "5:4"; 212 | else 213 | lblRatio.Text = "未知"; 214 | lblRatio.ForeColor = Color.Red; 215 | lblWarring.Text = "尚未适配当前分辨率,请切换到长宽比为16:9的分辨率"; 216 | } 217 | 218 | lblWindowSize.Text = $"{genshinWindowWdith}×{genshinWindowHeight}"; 219 | 220 | btnStart.Enabled = true; 221 | } 222 | catch 223 | { 224 | } 225 | })); 226 | Task.Delay(100).Wait(); 227 | } 228 | }); 229 | } 230 | 231 | private void btnStart_Click(object sender, EventArgs e) => Start(); 232 | 233 | private void Start() 234 | { 235 | if (working) 236 | { 237 | working = false; 238 | btnStart.Text = "开始自动演奏(F10)"; 239 | lblStatus.Text = $"已找到原神进程,未开始自动演奏"; 240 | lblStatus.ForeColor = Color.Black; 241 | FindGenshinProcess(); 242 | return; 243 | } 244 | else 245 | { 246 | debugIndex = 1; 247 | working = true; 248 | lblStatus.Text = $"已开始自动演奏"; 249 | lblStatus.ForeColor = Color.Green; 250 | btnStart.Text = "停止自动演奏(F10)"; 251 | } 252 | Task.Run(() => 253 | { 254 | Dictionary dicKeysNextPressTime = new Dictionary(); 255 | 256 | int width = (int)Math.Round(Screen.PrimaryScreen.Bounds.Width * DpiScaleX); 257 | int height = (int)Math.Round(Screen.PrimaryScreen.Bounds.Height * DpiScaleY); 258 | 259 | bool wHolding = false, sHolding = false, aHolding = false, dHolding = false, iHolding = false, kHolding = false, jHolding = false, lHolding = false; 260 | 261 | double aScaleX = 376 / 1920.0; 262 | double sScaleX = 573 / 1920.0; 263 | double dScaleX = 787 / 1920.0; 264 | double jScaleX = 1133 / 1920.0; 265 | double kScaleX = 1347 / 1920.0; 266 | double lScaleX = 1545 / 1920.0; 267 | double aScaleY = 731 / 1080.0; 268 | double sScaleY = 819 / 1080.0; 269 | double dScaleY = 870 / 1080.0; 270 | double jScaleY = 870 / 1080.0; 271 | double kScaleY = 819 / 1080.0; 272 | double lScaleY = 731 / 1080.0; 273 | 274 | //(double aTailX, double aTailY) = Rotate(376 + 190, 731, 376, 731, -45); 275 | //(double sTailX, double sTailY) = Rotate(573 + 190, 819, 573, 819, -60); 276 | //(double dTailX, double dTailY) = Rotate(787 + 190, 870, 787, 870, -75); 277 | //(double jTailX, double jTailY) = Rotate(1133 + 190, 870, 1133, 870, -105); 278 | //(double kTailX, double kTailY) = Rotate(1347 + 190, 819, 1347, 819, -120); 279 | //(double lTailX, double lTailY) = Rotate(1545 + 190, 731, 1545, 731, -135); 280 | 281 | //double aScaleTailX = aTailX / 1920.0; 282 | //double sScaleTailX = sTailX / 1920.0; 283 | //double dScaleTailX = dTailX / 1920.0; 284 | //double jScaleTailX = jTailX / 1920.0; 285 | //double kScaleTailX = kTailX / 1920.0; 286 | //double lScaleTailX = lTailX / 1920.0; 287 | 288 | //double aScaleTailY = aTailY / 1080.0; 289 | //double sScaleTailY = sTailY / 1080.0; 290 | //double dScaleTailY = dTailY / 1080.0; 291 | //double jScaleTailY = jTailY / 1080.0; 292 | //double kScaleTailY = kTailY / 1080.0; 293 | //double lScaleTailY = lTailY / 1080.0; 294 | 295 | while (working) 296 | { 297 | Bitmap memoryImage = new Bitmap(width, height); 298 | Graphics memoryGraphics = Graphics.FromImage(memoryImage); 299 | memoryGraphics.CopyFromScreen(0, 0, 0, 0, new Size(width, height)); 300 | 301 | #region -- 镜花听世/风物之歌 -- 302 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.253125, 0.37685, Keys.W, 0.2526, 0.461, ref wHolding); 303 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.253125, 0.823148, Keys.S, 0.253125, 0.773, ref sHolding); 304 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.127083, 0.6, Keys.A, 0.165625, 0.616, ref aHolding); 305 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.378125, 0.6, Keys.D, 0.340625, 0.616, ref dHolding); 306 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.74739583, 0.37685, Keys.I, 0.7475, 0.461, ref iHolding); 307 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.74739583, 0.823148, Keys.K, 0.7475, 0.773, ref kHolding); 308 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.62135416, 0.6, Keys.J, 0.659, 0.616, ref jHolding); 309 | //StartAutoPressKeyAndRecordCD(dicKeysNextPressTime, memoryImage, 0.872917, 0.6, Keys.L, 0.835, 0.616, ref lHolding); 310 | #endregion -- 镜花听世/风物之歌 -- 311 | 312 | #region -- 荒 泷 极 上 盛 世 豪 鼓 大 祭 典 -- 313 | StartAutoPressKeyAndRecordCD2(dicKeysNextPressTime, memoryImage, aScaleX, aScaleY, Keys.A, ref aHolding); 314 | StartAutoPressKeyAndRecordCD2(dicKeysNextPressTime, memoryImage, sScaleX, sScaleY, Keys.S, ref sHolding); 315 | StartAutoPressKeyAndRecordCD2(dicKeysNextPressTime, memoryImage, dScaleX, dScaleY, Keys.D, ref dHolding); 316 | StartAutoPressKeyAndRecordCD2(dicKeysNextPressTime, memoryImage, jScaleX, jScaleY, Keys.J, ref jHolding); 317 | StartAutoPressKeyAndRecordCD2(dicKeysNextPressTime, memoryImage, kScaleX, kScaleY, Keys.K, ref kHolding); 318 | StartAutoPressKeyAndRecordCD2(dicKeysNextPressTime, memoryImage, lScaleX, lScaleY, Keys.L, ref lHolding); 319 | #endregion -- 荒 泷 极 上 盛 世 豪 鼓 大 祭 典 -- 320 | 321 | memoryGraphics.Dispose(); 322 | memoryImage.Dispose(); 323 | } 324 | }); 325 | } 326 | 327 | private void btnDebugScreenshot_Click(object sender, EventArgs e) => SaveDebugImage(); 328 | 329 | [Obsolete] 330 | private void StartAutoPressKeyAndRecordCD(Dictionary dicKeysNextPressTime, Bitmap bmp, double scaleX, double scaleY, Keys key, double scaleHoldX, double scaleHoldY, ref bool holding) 331 | { 332 | if (dicKeysNextPressTime.ContainsKey(key)) 333 | { 334 | if (dicKeysNextPressTime[key] < DateTime.Now) 335 | dicKeysNextPressTime[key] = StartAutoPressKey(bmp, scaleX, scaleY, key, scaleHoldX, scaleHoldY, ref holding); 336 | } 337 | else 338 | dicKeysNextPressTime.Add(key, StartAutoPressKey(bmp, scaleX, scaleY, key, scaleHoldX, scaleHoldY, ref holding)); 339 | } 340 | 341 | private void StartAutoPressKeyAndRecordCD2(Dictionary dicKeysNextPressTime, Bitmap bmp, double scaleX, double scaleY, Keys key, ref bool holding) 342 | { 343 | if (dicKeysNextPressTime.ContainsKey(key)) 344 | { 345 | if (dicKeysNextPressTime[key] < DateTime.Now) 346 | dicKeysNextPressTime[key] = StartAutoPressKey2(bmp, scaleX, scaleY, key, ref holding); 347 | } 348 | else 349 | dicKeysNextPressTime.Add(key, StartAutoPressKey2(bmp, scaleX, scaleY, key, ref holding)); 350 | } 351 | 352 | private (double x, double y) Rotate(double targetX, double targetY, double centerX, double centerY, double angle) 353 | { 354 | double x = (targetX - centerX) * Math.Cos(Math.PI / 180.0 * angle) - (targetY - centerY) * Math.Sin(Math.PI / 180.0 * angle) + centerX; 355 | double y = (targetX - centerX) * Math.Sin(Math.PI / 180.0 * angle) + (targetY - centerY) * Math.Cos(Math.PI / 180.0 * angle) + centerY; 356 | return (x, y); 357 | } 358 | 359 | private int debugIndex = 1; 360 | private void SaveDebugImage() 361 | { 362 | int width = (int)Math.Round(Screen.PrimaryScreen.Bounds.Width * DpiScaleX); 363 | int height = (int)Math.Round(Screen.PrimaryScreen.Bounds.Height * DpiScaleY); 364 | Size size = new Size(width, height); 365 | Bitmap memoryImage = new Bitmap(width, height); 366 | Graphics memoryGraphics = Graphics.FromImage(memoryImage); 367 | memoryGraphics.CopyFromScreen(0, 0, 0, 0, size); 368 | 369 | #region -- 镜花听世/风物之歌 -- 370 | #region -- 点按判定位置 -- 371 | //DrawDebugLine(0.253125, 0.37685, memoryImage, Keys.W); 372 | //DrawDebugLine(0.253125, 0.823148, memoryImage, Keys.S); 373 | //DrawDebugLine(0.127083, 0.6, memoryImage, Keys.A); 374 | //DrawDebugLine(0.378125, 0.6, memoryImage, Keys.D); 375 | //DrawDebugLine(0.74739583, 0.37685, memoryImage, Keys.I); 376 | //DrawDebugLine(0.74739583, 0.823148, memoryImage, Keys.J); 377 | //DrawDebugLine(0.62135416, 0.6, memoryImage, Keys.K); 378 | //DrawDebugLine(0.872917, 0.6, memoryImage, Keys.L); 379 | #endregion -- 点按判定位置 -- 380 | 381 | #region -- 长按判定位置 -- 382 | //DrawDebugLine(0.2526, 0.461 - 0.15, memoryImage, Keys.W); 383 | //DrawDebugLine(0.165625, 0.616 - 0.15, memoryImage, Keys.S); 384 | //DrawDebugLine(0.253125, 0.773 - 0.15, memoryImage, Keys.A); 385 | //DrawDebugLine(0.340625, 0.616 - 0.15, memoryImage, Keys.D); 386 | //DrawDebugLine(0.7475, 0.461 - 0.15, memoryImage, Keys.I); 387 | //DrawDebugLine(0.659, 0.616 - 0.15, memoryImage, Keys.J); 388 | //DrawDebugLine(0.7475, 0.773 - 0.15, memoryImage, Keys.K); 389 | //DrawDebugLine(0.835, 0.616 - 0.15, memoryImage, Keys.L); 390 | #endregion -- 长按判定位置 -- 391 | #endregion -- 镜花听世/风物之歌 -- 392 | 393 | #region -- 荒 泷 极 上 盛 世 豪 鼓 大 祭 典 -- 394 | DrawDebugLine(376 / 1920.0, 731 / 1080.0, memoryImage, Keys.A); 395 | DrawDebugLine(573 / 1920.0, 819 / 1080.0, memoryImage, Keys.S); 396 | DrawDebugLine(787 / 1920.0, 870 / 1080.0, memoryImage, Keys.D); 397 | DrawDebugLine(1133 / 1920.0, 870 / 1080.0, memoryImage, Keys.J); 398 | DrawDebugLine(1347 / 1920.0, 819 / 1080.0, memoryImage, Keys.K); 399 | DrawDebugLine(1545 / 1920.0, 731 / 1080.0, memoryImage, Keys.L); 400 | 401 | //(double aX, double aY) = Rotate(376 + 190, 731, 376, 731, -45); 402 | //(double sX, double sY) = Rotate(573 + 190, 819, 573, 819, -60); 403 | //(double dX, double dY) = Rotate(787 + 190, 870, 787, 870, -75); 404 | //(double jX, double jY) = Rotate(1133 + 190, 870, 1133, 870, -105); 405 | //(double kX, double kY) = Rotate(1347 + 190, 819, 1347, 819, -120); 406 | //(double lX, double lY) = Rotate(1545 + 190, 731, 1545, 731, -135); 407 | 408 | //DrawDebugLine(aX / 1920.0, aY / 1080.0, memoryImage, Keys.A); 409 | //DrawDebugLine(sX / 1920.0, sY / 1080.0, memoryImage, Keys.S); 410 | //DrawDebugLine(dX / 1920.0, dY / 1080.0, memoryImage, Keys.D); 411 | //DrawDebugLine(jX / 1920.0, jY / 1080.0, memoryImage, Keys.J); 412 | //DrawDebugLine(kX / 1920.0, kY / 1080.0, memoryImage, Keys.K); 413 | //DrawDebugLine(lX / 1920.0, lY / 1080.0, memoryImage, Keys.L); 414 | #endregion -- 荒 泷 极 上 盛 世 豪 鼓 大 祭 典 -- 415 | 416 | memoryImage.Save(Application.StartupPath + @$"\Screenshot{debugIndex++}.jpg"); 417 | 418 | void DrawDebugLine(double scaleX, double scaleY, Bitmap highDpiScreenshot, Keys key) 419 | { 420 | int xw = (int)Math.Round(genshinWindowWdith * scaleX) + genshinWindowX; 421 | int yw = (int)Math.Round(genshinWindowHeight * scaleY) + genshinWindowY; 422 | for (int i = xw - 25; i < xw + 25; i++) 423 | highDpiScreenshot.SetPixel(i, yw, Color.Red); 424 | for (int i = yw - 25; i < yw + 25; i++) 425 | highDpiScreenshot.SetPixel(xw, i, Color.Red); 426 | Graphics g = Graphics.FromImage(highDpiScreenshot); 427 | g.DrawString(key.ToString(), new Font("宋体", 12), Brushes.Red, xw, yw); 428 | g.Dispose(); 429 | } 430 | } 431 | 432 | [Obsolete] 433 | private DateTime StartAutoPressKey(Bitmap bmp, double scaleX, double scaleY, Keys key, double scaleHoldX, double scaleHoldY, ref bool holding) 434 | { 435 | byte byteKey = (byte)key; 436 | byte code = key switch 437 | { 438 | Keys.W => Convert.ToByte(0x11), 439 | Keys.S => Convert.ToByte(0x1F), 440 | Keys.A => Convert.ToByte(0x1E), 441 | Keys.D => Convert.ToByte(0x20), 442 | Keys.I => Convert.ToByte(0x17), 443 | Keys.K => Convert.ToByte(0x25), 444 | Keys.J => Convert.ToByte(0x24), 445 | Keys.L => Convert.ToByte(0x26), 446 | _ => throw new Exception() 447 | }; 448 | 449 | if (holding) 450 | { 451 | //弹起 452 | int xHold = (int)Math.Round(genshinWindowWdith * scaleHoldX) + genshinWindowX; 453 | int yHold = (int)Math.Round(genshinWindowHeight * scaleHoldY) + genshinWindowY; 454 | int yTail = (int)Math.Round(genshinWindowHeight * (scaleHoldY - 0.15)) + genshinWindowY; 455 | 456 | var colorHold = bmp.GetPixel(xHold, yHold); 457 | var colorTail = bmp.GetPixel(xHold, yTail); 458 | 459 | if (colorHold.R > 240 && colorHold.G > 210 && colorHold.B > 210 && colorTail.B < 250) 460 | { 461 | Task.Run(() => keybd_event(byteKey, code, 2, 0)); 462 | holding = false; 463 | if (debugTextBox.Visible) 464 | BeginInvoke(new Action(() => debugTextBox.AppendText($"弹起按键:{key} ----{DateTime.Now}\r\n"))); 465 | //SaveDebugImage()"); 466 | return DateTime.Now; 467 | } 468 | } 469 | else 470 | { 471 | //点按 472 | int x = (int)Math.Round(genshinWindowWdith * scaleX) + genshinWindowX; 473 | int y = (int)Math.Round(genshinWindowHeight * scaleY) + genshinWindowY; 474 | 475 | Color color = bmp.GetPixel(x, y); 476 | if (color.R > 240 && color.G > 210 && color.G < 240 && color.B > 50 && color.B < 80) 477 | { 478 | keybd_event(byteKey, code, 0, 0); 479 | if (debugTextBox.Visible) 480 | BeginInvoke(new Action(() => debugTextBox.AppendText($"点按按键{key}----{DateTime.Now}\r\n"))); 481 | Task.Delay(50).ContinueWith(_ => keybd_event(byteKey, code, 2, 0)); 482 | //SaveDebugImage(); 483 | return DateTime.Now.AddMilliseconds(200); 484 | } 485 | 486 | //长按 487 | int xHold = (int)Math.Round(genshinWindowWdith * scaleHoldX) + genshinWindowX; 488 | int yHold = (int)Math.Round(genshinWindowHeight * scaleHoldY) + genshinWindowY; 489 | int yTail = (int)Math.Round(genshinWindowHeight * (scaleHoldY - 0.15)) + genshinWindowY; 490 | 491 | var colorHold = bmp.GetPixel(xHold, yHold); 492 | var colorTail = bmp.GetPixel(xHold, yTail); 493 | 494 | if (colorHold.R > 240 && colorHold.G > 240 && colorHold.B > 230 && colorTail.B == 255) 495 | { 496 | keybd_event(byteKey, code, 1, 0); 497 | holding = true; 498 | 499 | if (debugTextBox.Visible) 500 | BeginInvoke(new Action(() => debugTextBox.AppendText($"按住按键:{key} ----{DateTime.Now}\r\n"))); 501 | //SaveDebugImage(); 502 | return DateTime.Now.AddMilliseconds(500); 503 | } 504 | } 505 | return DateTime.Now; 506 | } 507 | 508 | 509 | private DateTime StartAutoPressKey2(Bitmap bmp, double scaleX, double scaleY, Keys key, ref bool holding) 510 | { 511 | byte byteKey = (byte)key; 512 | byte code = key switch 513 | { 514 | Keys.W => Convert.ToByte(0x11), 515 | Keys.S => Convert.ToByte(0x1F), 516 | Keys.A => Convert.ToByte(0x1E), 517 | Keys.D => Convert.ToByte(0x20), 518 | Keys.I => Convert.ToByte(0x17), 519 | Keys.K => Convert.ToByte(0x25), 520 | Keys.J => Convert.ToByte(0x24), 521 | Keys.L => Convert.ToByte(0x26), 522 | _ => throw new Exception() 523 | }; 524 | 525 | //点按 526 | int x = (int)Math.Round(genshinWindowWdith * scaleX) + genshinWindowX; 527 | int y = (int)Math.Round(genshinWindowHeight * scaleY) + genshinWindowY; 528 | 529 | Color color = bmp.GetPixel(x, y); 530 | if (color.B < 200) 531 | { 532 | keybd_event(byteKey, code, 0, 0); 533 | if (debugTextBox.Visible) 534 | BeginInvoke(new Action(() => debugTextBox.AppendText($"点按按键{key}----{DateTime.Now}\r\n"))); 535 | Task.Delay(20).ContinueWith(_ => keybd_event(byteKey, code, 2, 0)); 536 | //SaveDebugImage(); 537 | return DateTime.Now.AddMilliseconds(100); 538 | } 539 | return DateTime.Now; 540 | } 541 | } 542 | } 543 | --------------------------------------------------------------------------------