やりたいこと
2023/5/3時点の、Google Play Games BETA のプレイ画面に対して、プレイ画面が他のウィンドウの下にあっても、スワイプ操作したい。
やったこと
Powershell Core 7.3 から、SendMessage 関数 を呼び出して、スワイプ操作をエミュレートしたメッセージを送信した。
### C#
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public static class Win32
{
[DllImport("user32.dll")]
static extern IntPtr FindWindow(
string lpClassName,
string lpWindowName
);
public static IntPtr FindWindowByName(string lpWindowName)
{
return FindWindow(null, lpWindowName);
}
[DllImport("user32.dll")]
static extern int GetWindowThreadProcessId(
IntPtr hWnd,
IntPtr ProcessId
);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
static extern bool SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
int uFlags
);
[DllImport("user32.dll")]
static extern bool AttachThreadInput(
int idAttach,
int idAttachTo,
bool fAttach
);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(
IntPtr hWnd,
uint Msg,
int wParam,
int lParam
);
static void SimulateBackGround(
string lpWindowName,
string simualtedTask,
int x = 0,
int y = 0,
int movedX = 0,
int movedY = 0
)
{
var targetWnd = FindWindowByName(lpWindowName);
var wakfuThreadID = GetWindowThreadProcessId(targetWnd, IntPtr.Zero);
var foreWnd = GetForegroundWindow();
var windowThreadProcessId = GetCurrentThreadId();
AttachThreadInput(windowThreadProcessId, wakfuThreadID, true);
int mousePos = (y << 16) | (x & 0xffff);
int movedMousePos = (movedY << 16) | (movedX & 0xffff);
const int WM_MOUSEMOVE = 0x0200;
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
const int MK_LBUTTON = 0x0001;
switch (simualtedTask)
{
case "tap":
SendMessage(targetWnd, WM_MOUSEMOVE, 0, mousePos);
SendMessage(targetWnd, WM_LBUTTONDOWN, MK_LBUTTON, mousePos);
System.Threading.Thread.Sleep(50);
SendMessage(targetWnd, WM_MOUSEMOVE, 0, mousePos);
SendMessage(targetWnd, WM_LBUTTONUP, 0, mousePos);
break;
case "swipe":
SendMessage(targetWnd, WM_MOUSEMOVE, 0, mousePos);
SendMessage(targetWnd, WM_LBUTTONDOWN, MK_LBUTTON, mousePos);
System.Threading.Thread.Sleep(100);
SendMessage(targetWnd, WM_MOUSEMOVE, 0, movedMousePos);
SendMessage(targetWnd, WM_LBUTTONDOWN, MK_LBUTTON, movedMousePos);
System.Threading.Thread.Sleep(110);
SendMessage(targetWnd, WM_LBUTTONUP, 0, movedMousePos);
break;
default:
break;
}
const int SWP_NOSIZE = 0x0001;
const int SWP_NOMOVE = 0x0002;
const int SWP_SHOWWINDOW = 0x0040;
SetWindowPos(foreWnd, -1, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(foreWnd, -2, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
AttachThreadInput(windowThreadProcessId, wakfuThreadID, false);
}
public static void TapBackGround(
string lpWindowName,
int x,
int y
)
{
SimulateBackGround(lpWindowName, "tap", x, y);
}
public static void SwipeBackGround(
string lpWindowName,
int x,
int y,
int movedX,
int movedY
)
{
SimulateBackGround(lpWindowName, "swipe", x, y, movedX, movedY);
}
}
"@
### Powershell
Set-Variable WINDOW_TITLE -Option Constant -Value "操作したいアプリのウィンドウタイトル"
[int]$local:startXforSwipe = 500
[int]$local:startYforSwipe = 600
[int]$local:endXforSwipe = 1000
[int]$local:endYforSwipe = 600
[Win32]::SwipeBackGround(
${WINDOW_TITLE},
${startXforSwipe},
${startYforSwipe},
${endXforSwipe},
${endYforSwipe}
)
# tap
# [int]$local:xforTap = 500
# [int]$local:yforTap = 600
# [Win32]::TapBackGround(
# ${WINDOW_TITLE},
# ${xforTap},
# ${yforTap}
# )
やっていて困ったこと
参考