mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
@@ -1,19 +1,9 @@
|
||||
- 自动战斗
|
||||
- 新增界面显示干员阵容和攻略链接
|
||||
- 优化作业制作器,支持拖动,UI 调整;同时将老版本也一起放进去了
|
||||
- 修复编队时干员识别错误的问题
|
||||
- 修复突袭模式不开始的问题
|
||||
## 全新版本!
|
||||
|
||||
- 刷理智
|
||||
- 新增 `覆潮之下` 活动关卡导航
|
||||
- 修复关卡掉落识别错误及崩溃问题
|
||||
|
||||
- 肉鸽
|
||||
- 修复源石锭不够时购买收藏品卡住的问题
|
||||
|
||||
- 其他
|
||||
- 修复自动更新后崩溃的问题
|
||||
- 修复 `覆潮之下` 返回按钮不一样卡住的问题
|
||||
- 新增一个兼容老旧设备的“兼容模式”连接方式
|
||||
- 将 Python 接口文件一起打包到压缩包里了!
|
||||
- 为 HyperV 蓝叠新增一个自动获取端口号的小后门,详见 [文档](https://github.com/MaaAssistantArknights/MaaAssistantArknights/blob/master/docs/%E6%A8%A1%E6%8B%9F%E5%99%A8%E6%94%AF%E6%8C%81.md#%E8%93%9D%E5%8F%A0%E6%A8%A1%E6%8B%9F%E5%99%A8-hyper-v-%E7%89%88%E6%9C%AC)
|
||||
- 新增自动战斗抄作业功能!欢迎加 [Q 群](https://jq.qq.com/?_wv=1027&k=ICIzu7lv) 分享/获取作业~
|
||||
- 肉鸽新增识别干员练度,自动选择最优干员及技能,不用再手动改文件了!
|
||||
- 信用商店新增支持优先购买和自定义黑名单
|
||||
- 全模拟器支持自动连接(如果还是连不上请参考 [模拟器支持情况](https://github.com/MaaAssistantArknights/MaaAssistantArknights/blob/master/docs/%E6%A8%A1%E6%8B%9F%E5%99%A8%E6%94%AF%E6%8C%81.md) 及 [常见问题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/blob/master/docs/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98.md#%E8%BF%9E%E6%8E%A5%E9%94%99%E8%AF%AF%E4%B8%8D%E7%9F%A5%E9%81%93-adb-%E8%B7%AF%E5%BE%84%E6%80%8E%E4%B9%88%E5%A1%AB%E5%86%99)
|
||||
- 重写关卡掉落识别,支持识别所有材料
|
||||
- 新增支持定时执行
|
||||
- 其他大量优化及问题修复
|
||||
|
||||
@@ -53,8 +53,7 @@ MAA 的意思是 MAA Assistant Arknights
|
||||
|
||||
1. 请根据 [模拟器支持情况](docs/模拟器支持.md),进行对应的操作。
|
||||
2. 解压压缩包,到 **没有中文或特殊符号** 的文件夹路径。
|
||||
3. 第一次运行软件,**请使用管理员权限** 打开 `MeoAsstGui.exe`。运行过一次后,后续不再需要管理员权限。
|
||||
4. 开始运行后,除 `自动关机` 外,所有设置均不可再修改。
|
||||
3. 开始运行后,除 `自动关机` 外,所有设置均不可再修改。
|
||||
|
||||
目前仅对 `16:9` 分辨率支持较好,最低支持 `1280 * 720`,更高不限。非 `16:9` 分辨率可能会有奇奇怪怪的问题,正在进一步适配中_(:з」∠)_
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
1. 在蓝叠模拟器的安装目录下找到 `bluestacks.conf` 这个文件
|
||||
2. 开启 MAA,会在同目录下生成 `gui.json` ,打开它
|
||||
3. 新增一个字段 `Bluestacks.Config.Path`,填入 `bluestacks.conf` 的完整路径(注意斜杠要用转义 `\\`)
|
||||
4. LinkStart!
|
||||
4. LinkStart!
|
||||
|
||||
### 夜神模拟器
|
||||
|
||||
@@ -29,10 +29,11 @@
|
||||
|
||||
### MuMu 模拟器
|
||||
|
||||
支持。但是可能会
|
||||
支持。但
|
||||
|
||||
- 一直连接出错:暂时不知道是什么原因,可尝试使用 [自定义连接](#自定义连接)
|
||||
- 卡在主界面无法识别,过一会提示任务出错:和 MuMu 的渲染方式有关,推荐换模拟器(
|
||||
- 需要使用管理员权限打开 MAA 才能自动获取 adb 路径和地址(因为 MuMu 本身是管理员启动的)
|
||||
- 如果不希望管理员启动,可以在 MAA 设置中自行填写 adb 路径和地址
|
||||
- 可能会卡在主界面无法识别,过一会提示任务出错:和 MuMu 的渲染方式有关,暂时不知道根本原因,推荐换模拟器(
|
||||
|
||||
### MuMu 手游助手(星云引擎)
|
||||
|
||||
@@ -44,10 +45,9 @@
|
||||
|
||||
### 雷电模拟器
|
||||
|
||||
勉强支持。雷电总有莫名其妙的问题,可以试试看,不保证能用(
|
||||
支持。
|
||||
|
||||
另外雷电的连接地址会在 `127.0.0.1:5555` 和 `emulator-5554` 之间反复横跳,不同的电脑还可能会不一样,也有重启就变成另一个了的情况。
|
||||
所以如果一个连不上,换另一个试试。后面我们会想办法去适配一下雷电的这套逻辑(~~也可能会咕咕~~
|
||||
但雷电的连接地址会在 `127.0.0.1:5555` 和 `emulator-5554` 之间反复横跳,不同的电脑还可能会不一样,也有重启就变成另一个了的情况。所以如果一个连不上,可以换另一个试试~
|
||||
|
||||
### 逍遥模拟器
|
||||
|
||||
@@ -61,8 +61,8 @@
|
||||
|
||||
勉强支持。
|
||||
|
||||
- 需要使用 [自定义连接](#自定义连接) 的方式来连接,连接配置选择 `WSA`
|
||||
- 由于本软件仅对 720p 以上 `16:9` 分辨率支持较好,WSA 无法修改分辨率,所以请手动拖动窗口大小,尽量贴近 16:9 比例
|
||||
- 需要使用 [自定义连接](#自定义连接) 的方式来连接,尝试连接配置选择 `WSA 旧版本` 或 `通用配置`
|
||||
- 由于本软件仅对 720p 以上 `16:9` 分辨率支持较好,WSA 无法修改分辨率,所以请手动拖动窗口大小,尽量贴近 16:9 比例(如果你的显示器是 16:9 的,可以直接全屏)
|
||||
- 但是! WSA 的截图经常莫名其妙截出来一个白屏,导致识别异常,还是不推荐使用
|
||||
|
||||
### AVD
|
||||
@@ -74,7 +74,5 @@
|
||||
1. 下载 [adb](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) 并解压
|
||||
2. 进入软件 `设置` - `连接设置`,填写 adb 路径及地址(需要填写 IP + 端口,例如 `127.0.0.1:5555` )
|
||||
|
||||
|
||||
**注意 :** 若是使用手机,在非 `16:9` 分辨率下,部分功能不稳定(但也凑合能用),尤其是基建,几乎是不可用状态,正在进一步适配中。推荐使用 `16:9` 分辨率,经过的测试验证最多,也最稳定。
|
||||
另外手机其实是可以通过 `adb shell wm size` 的方式来硬改分辨率的,使用完再改回来。等有空出一篇详细一点的文档,有兴趣的朋友们可先自行尝试一下~
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
#### 写作业
|
||||
|
||||
- exe 同目录下有简易的制作器,可以结合 [文档](战斗流程协议.md) 使用
|
||||
- `stage_name` 需要是关卡中文名(但危机合约的关卡又需要是关卡 id, 目前有点乱,之后版本会想办法统一下)
|
||||
- 地图坐标获取:填写 `stage_name` 后直接开一局,会在目录下生成 `map.png`, 可以用于参考。后面会想办法直接在制作器上显示坐标(画饼)
|
||||
- 支持演习模式,不用一直浪费理智测试的
|
||||
- 若某个干员名字一直识别不对,可以打开日志 `asst.log` 看一下到底被识别成了什么,并修改 `resource/tasks.json` - `CharsNameOcrReplace` 进行正则替换
|
||||
- 推荐在作业描述里填上你自己的名字(作者名)、参考的攻略视频 url, 其他想说的等等(
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
"devices": "[Adb] devices",
|
||||
"addressRegex": "(.+)\tdevice",
|
||||
"connect": "[Adb] connect [Address]",
|
||||
"uuid": "[Adb] -s [Address] shell \"settings get secure android_id | awk 'NR == 1 {p = $0} NR > 1 {print p; p = $0} END{printf p}' \"",
|
||||
"uuid": "[Adb] -s [Address] shell settings get secure android_id",
|
||||
"click": "[Adb] -s [Address] shell input tap [x] [y]",
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init=",
|
||||
@@ -116,7 +116,7 @@
|
||||
"devices": "[Adb] devices",
|
||||
"addressRegex": "(.+)\tdevice",
|
||||
"connect": "[Adb] connect [Address]",
|
||||
"uuid": "[Adb] -s [Address] shell echo 1234567",
|
||||
"uuid": "[Adb] -s [Address] shell settings get secure android_id",
|
||||
"click": "[Adb] -s [Address] shell input tap [x] [y]",
|
||||
"swipe": "[Adb] -s [Address] shell input swipe [x1] [y1] [x2] [y2] [duration]",
|
||||
"display": "[Adb] -s [Address] shell dumpsys window displays | grep init=",
|
||||
|
||||
@@ -6321,7 +6321,8 @@
|
||||
"Roguelike1StageEncounterUnknown",
|
||||
"Roguelike1ChooseOperFlag",
|
||||
"Roguelike1StageEncounterSpecialClose",
|
||||
"Roguelike1EnterAfterRecruit"
|
||||
"Roguelike1EnterAfterRecruit",
|
||||
"Roguelike1StageTraderLeave"
|
||||
]
|
||||
},
|
||||
"Roguelike1GetDrop1": {
|
||||
|
||||
@@ -100,22 +100,20 @@ bool asst::MatchImageAnalyzer::match_templ(const cv::Mat templ)
|
||||
{
|
||||
cv::Mat matched;
|
||||
|
||||
Log.trace(__FUNCTION__, "raw_roi", m_roi.to_string());
|
||||
|
||||
if (m_roi.x < 0) {
|
||||
Log.info(__FUNCTION__, "roi is out of range");
|
||||
Log.info("roi is out of range", m_roi.to_string());
|
||||
m_roi.x = 0;
|
||||
}
|
||||
if (m_roi.y < 0) {
|
||||
Log.info(__FUNCTION__, "roi is out of range");
|
||||
Log.info("roi is out of range", m_roi.to_string());
|
||||
m_roi.y = 0;
|
||||
}
|
||||
if (m_roi.x + m_roi.width >= m_image.cols) {
|
||||
Log.info(__FUNCTION__, "roi is out of range");
|
||||
if (m_roi.x + m_roi.width > m_image.cols) {
|
||||
Log.info("roi is out of range", m_roi.to_string());
|
||||
m_roi.width = m_image.cols - m_roi.x;
|
||||
}
|
||||
if (m_roi.y + m_roi.height >= m_image.rows) {
|
||||
Log.info(__FUNCTION__, "roi is out of range");
|
||||
if (m_roi.y + m_roi.height > m_image.rows) {
|
||||
Log.info("roi is out of range", m_roi.to_string());
|
||||
m_roi.height = m_image.rows - m_roi.y;
|
||||
}
|
||||
|
||||
@@ -144,6 +142,9 @@ bool asst::MatchImageAnalyzer::match_templ(const cv::Mat templ)
|
||||
cv::minMaxLoc(matched, &min_val, &max_val, &min_loc, &max_loc);
|
||||
|
||||
Rect rect(max_loc.x + m_roi.x, max_loc.y + m_roi.y, templ.cols, templ.rows);
|
||||
if (max_val > 2.0) {
|
||||
max_val = 0;
|
||||
}
|
||||
if (max_val > m_templ_thres * 0.7) { // 得分太低的肯定不对,没必要打印
|
||||
Log.trace("match_templ |", m_templ_name, "score:", max_val, "rect:", rect.to_string(), "roi:", m_roi.to_string());
|
||||
}
|
||||
|
||||
@@ -211,7 +211,10 @@ bool ProcessTask::_run()
|
||||
// 例如,进入吃理智药的界面了,相当于上一次点蓝色开始行动没生效
|
||||
// 所以要给蓝色开始行动的次数减一
|
||||
for (const std::string& reduce : cur_task_ptr->reduce_other_times) {
|
||||
--m_exec_times[reduce];
|
||||
auto& v = m_exec_times[reduce];
|
||||
if (v > 0) {
|
||||
--v;
|
||||
}
|
||||
}
|
||||
|
||||
// 后置固定延时
|
||||
|
||||
@@ -253,13 +253,12 @@ bool asst::StageDropsImageAnalyzer::analyze_baseline()
|
||||
|
||||
// split
|
||||
int threshold = task_ptr->mask_range.first;
|
||||
int pre_value = 0;
|
||||
uchar pre_value = 0;
|
||||
for (int i = 0; i < bounding.cols; ++i) {
|
||||
int value = 0;
|
||||
uchar value = 0;
|
||||
for (int j = 0; j < bounding.rows; ++j) {
|
||||
value += bounding.at<uchar>(0, i);
|
||||
value = std::max(value, bounding.at<uchar>(j, i));
|
||||
}
|
||||
value /= bounding.rows;
|
||||
bool is_white = value > threshold && pre_value - value < threshold;
|
||||
pre_value = value;
|
||||
|
||||
|
||||
@@ -160,10 +160,18 @@ namespace MeoAsstGui
|
||||
|
||||
private void procConnectInfo(JObject details)
|
||||
{
|
||||
if (details["what"].ToString() == "Connected")
|
||||
var what = details["what"].ToString();
|
||||
switch (what)
|
||||
{
|
||||
var svm = _container.Get<SettingsViewModel>();
|
||||
svm.ConnectAddress = details["details"]["address"].ToString();
|
||||
case "Connected":
|
||||
var svm = _container.Get<SettingsViewModel>();
|
||||
svm.ConnectAddress = details["details"]["address"].ToString();
|
||||
break;
|
||||
|
||||
case "UnsupportedResolution":
|
||||
var mainModel = _container.Get<TaskQueueViewModel>();
|
||||
mainModel.AddLog("分辨率过低\n请设置为 720p 或更高", "darkred");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,11 +617,7 @@ namespace MeoAsstGui
|
||||
}
|
||||
}
|
||||
settings.TryToSetBlueStacksHyperVAddress();
|
||||
if (settings.AdbPath.Length == 0)
|
||||
{
|
||||
error = "请选择 adb 路径";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = AsstConnect(_handle, settings.AdbPath, settings.ConnectAddress, settings.ConnectConfig);
|
||||
if (!ret)
|
||||
{
|
||||
|
||||
@@ -23,10 +23,10 @@ namespace MeoAsstGui
|
||||
{
|
||||
private static readonly Dictionary<string, string> emulatorIdDict = new Dictionary<string, string> {
|
||||
{ "HD-Player", "BlueStacks"},
|
||||
{ "LdVBoxHeadless", "LDPlayer"},
|
||||
{ "NoxVMHandle", "Nox"},
|
||||
{ "NemuHeadless", "MuMuEmulator"},
|
||||
{ "MEmuHeadless", "XYAZ"}
|
||||
{ "dnplayer", "LDPlayer"},
|
||||
{ "Nox", "Nox"},
|
||||
{ "NemuPlayer", "MuMuEmulator"},
|
||||
{ "MEmu", "XYAZ"}
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, List<string>> adbRelativePathDict = new Dictionary<string, List<string>> {
|
||||
@@ -77,5 +77,34 @@ namespace MeoAsstGui
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<string> GetAdbAddresses(string adbPath)
|
||||
{
|
||||
var addresses = new List<string>();
|
||||
using (Process process = new System.Diagnostics.Process())
|
||||
{
|
||||
process.StartInfo.FileName = adbPath;
|
||||
process.StartInfo.Arguments = "devices";
|
||||
// 禁用操作系统外壳程序
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.Start();
|
||||
var output = process.StandardOutput.ReadToEnd();
|
||||
var outLines = output.Split(new[] { '\r', '\n' });
|
||||
foreach (var line in outLines)
|
||||
{
|
||||
if (line.StartsWith("List of devices attached") ||
|
||||
line.Length == 0 ||
|
||||
!line.Contains("device"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var address = line.Split('\t')[0];
|
||||
addresses.Add(address);
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,42 +964,36 @@ namespace MeoAsstGui
|
||||
{
|
||||
SetAndNotify(ref _connectConfig, value);
|
||||
ViewStatusStorage.Set("Connect.ConnectConfig", value);
|
||||
if (ConnectAddress.Length == 0)
|
||||
{
|
||||
UpdateAddressByConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, List<string>> ConfigAddressesMapping = new Dictionary<string, List<string>>
|
||||
private readonly Dictionary<string, string> DefaultAddress = new Dictionary<string, string>
|
||||
{
|
||||
{ "General", new List<string> {""} },
|
||||
{ "BlueStacks", new List<string> {"127.0.0.1:5555", "127.0.0.1:5556", "127.0.0.1:5557" } },
|
||||
{ "MuMuEmulator", new List<string>{"127.0.0.1:7555"} },
|
||||
{ "LDPlayer", new List<string>{ "127.0.0.1:5555", "emulator-5554" } },
|
||||
{ "Nox", new List<string> { "127.0.0.1:62001", "127.0.0.1:59865" } },
|
||||
{ "XYAZ", new List<string> {"127.0.0.1:21503" } },
|
||||
{ "WSA", new List<string> { "127.0.0.1:58526" } },
|
||||
{ "General", "" },
|
||||
{ "BlueStacks", "127.0.0.1:5555" },
|
||||
{ "MuMuEmulator", "127.0.0.1:7555" },
|
||||
{ "LDPlayer", "emulator-5554" },
|
||||
{ "Nox", "127.0.0.1:62001" },
|
||||
{ "XYAZ", "127.0.0.1:21503" },
|
||||
{ "WSA","127.0.0.1:58526" },
|
||||
};
|
||||
|
||||
private void UpdateAddressByConfig()
|
||||
{
|
||||
var addresses = ConfigAddressesMapping[ConnectConfig];
|
||||
ConnectAddress = addresses.FirstOrDefault();
|
||||
//ConnectAddressList.Clear();
|
||||
//foreach (var address in addresses)
|
||||
//{
|
||||
// ConnectAddressList.Add(address);
|
||||
//}
|
||||
}
|
||||
|
||||
public bool RefreshAdbConfig(ref string error)
|
||||
{
|
||||
var adapter = new WinAdapter();
|
||||
var emulators = adapter.RefreshEmulatorsInfo();
|
||||
List<string> emulators;
|
||||
try
|
||||
{
|
||||
emulators = adapter.RefreshEmulatorsInfo();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
error = "检测模拟器出错\n请使用管理员权限打开本软件\n或手动设置连接";
|
||||
return false;
|
||||
}
|
||||
if (emulators.Count == 0)
|
||||
{
|
||||
error = "未检测到任何模拟器\n请尝试使用管理员权限打开本软件\n或手动设置连接";
|
||||
error = "未检测到任何模拟器\n请使用管理员权限打开本软件\n或手动设置连接";
|
||||
return false;
|
||||
}
|
||||
else if (emulators.Count > 1)
|
||||
@@ -1009,8 +1003,32 @@ namespace MeoAsstGui
|
||||
}
|
||||
ConnectConfig = emulators.First();
|
||||
AdbPath = adapter.GetAdbPathByEmulatorName(ConnectConfig) ?? AdbPath;
|
||||
UpdateAddressByConfig();
|
||||
TryToSetBlueStacksHyperVAddress();
|
||||
if (ConnectAddress.Length == 0)
|
||||
{
|
||||
var addresses = adapter.GetAdbAddresses(AdbPath);
|
||||
// 傻逼雷电已经关掉了用别的 adb 还能检测出来这个端口 device
|
||||
if (addresses.Count == 1 && addresses.First() != "emulator-5554")
|
||||
{
|
||||
ConnectAddress = addresses.First();
|
||||
}
|
||||
else if (addresses.Count > 1)
|
||||
{
|
||||
foreach (var address in addresses)
|
||||
{
|
||||
if (address == "emulator-5554" && ConnectConfig != "LDPlayer")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ConnectAddress = address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConnectAddress.Length == 0)
|
||||
{
|
||||
ConnectAddress = DefaultAddress[ConnectConfig];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -169,6 +169,26 @@ namespace MeoAsstGui
|
||||
LogItemViewModels.Clear();
|
||||
}
|
||||
|
||||
public void SelectedAll()
|
||||
{
|
||||
foreach (var item in TaskItemViewModels)
|
||||
{
|
||||
if (item.Name == "无限刷肉鸽")
|
||||
continue;
|
||||
item.IsChecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void InverseSelected()
|
||||
{
|
||||
foreach (var item in TaskItemViewModels)
|
||||
{
|
||||
if (item.Name == "无限刷肉鸽")
|
||||
continue;
|
||||
item.IsChecked = !item.IsChecked;
|
||||
}
|
||||
}
|
||||
|
||||
public async void LinkStart()
|
||||
{
|
||||
Idle = false;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<RowDefinition Height="60" />
|
||||
<RowDefinition Height="60" />
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox x:Name="TaskList" Grid.Row="0" Width="200" Margin="10" HorizontalAlignment="Center"
|
||||
<ListBox x:Name="TaskList" Grid.Row="0" Width="200" Margin="0,10,0,0" HorizontalAlignment="Center"
|
||||
dd:DragDrop.IsDragSource="{Binding Idle}" dd:DragDrop.IsDropTarget="{Binding Idle}"
|
||||
ItemsSource="{Binding Path=TaskItemViewModels}">
|
||||
<ListBox.ItemTemplate>
|
||||
@@ -36,7 +36,9 @@
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<CheckBox Grid.Row="1" IsChecked="{Binding Shutdown}" Content="自动关机" HorizontalAlignment="Center" Margin="5" />
|
||||
<Button Grid.Row="1" Command="{s:Action SelectedAll}" Content="全选" HorizontalAlignment="Center" Width="100" Height="30" Margin="-100,0,0,0" VerticalAlignment="Top" />
|
||||
<Button Grid.Row="1" Command="{s:Action InverseSelected}" Content="反选" HorizontalAlignment="Center" Width="100" Height="30" Margin="100,0,0,0" VerticalAlignment="Top" />
|
||||
<CheckBox Grid.Row="1" IsChecked="{Binding Shutdown}" Content="自动关机" HorizontalAlignment="Center" Margin="0,34,0,0" />
|
||||
<Button Grid.Row="2" Command="{s:Action LinkStart}" IsEnabled="{Binding Idle}" Content="LinkStart !" HorizontalAlignment="Center" Width="120" Height="50" Margin="5" />
|
||||
<Button Grid.Row="3" Command="{s:Action Stop}" Content="停止" HorizontalAlignment="Center" Width="120" Height="50" Margin="5" />
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user