Нажатие на кнопку в ToolBar (SendMessage) в стороннем приложении(!Не в InternetExplorer!)
Нашел код тут:
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,
bool bInheritHandle,
int processId
);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true)]
static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll")]
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint dwFreeType);
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr handle);
public enum VirtualFreeExTypes : uint {
MEM_DECOMMIT = 0x4000,
MEM_RELEASE = 0x8000
}
[Flags]
public enum AllocationType {
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection {
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[Flags]
public enum ProcessAccessFlags : uint {
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int Left, Top, Right, Bottom;
}
const int WM_USER = 0x0400;
const int TB_GETITEMRECT = (WM_USER + 29);
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
public static int MAKELONG(int x, int y)
{
return (x & 0xffff) | ((y & 0xffff) << 16);
}
public static RECT ByteArrayToRect(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
RECT stuff = (RECT)Marshal.PtrToStructure(
handle.AddrOfPinnedObject(), typeof(RECT));
handle.Free();
return stuff;
}
static void Main(string[] args)
{
//IntPtr ptr = WinAPI.FindWindow(null, "Выберите файл");
//IntPtr window = FindWindowByIndex(ptr, 1, "ToolbarWindow32");
IntPtr ptr = FindWindow("ThunderRT6FormDC", "Form1");
IntPtr window = FindWindowEx(ptr, IntPtr.Zero, "Toolbar20WndClass",string.Empty);
IntPtr nNumberOfBytesRead;
int dwProcessID;
GetWindowThreadProcessId(window, out dwProcessID);
IntPtr hProcess = OpenProcess((ProcessAccessFlags.VirtualMemoryOperation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.VirtualMemoryWrite), false, dwProcessID);
IntPtr Pointer = VirtualAllocEx(hProcess, (IntPtr)0, 4096, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
RECT bi;
SendMessage(window, TB_GETITEMRECT, (IntPtr)1 /* индекс кнопки*/, (IntPtr)Pointer);
byte[] buffer = new byte[16];
ReadProcessMemory(hProcess, (Pointer), buffer, (uint)buffer.Length, out nNumberOfBytesRead);
bi = ByteArrayToRect(buffer);
PostMessage(window, WM_LBUTTONDOWN, (IntPtr)0, (IntPtr)MAKELONG(bi.Left, bi.Top));
PostMessage(window, WM_LBUTTONUP, (IntPtr)0, (IntPtr)MAKELONG(bi.Left, bi.Top));
VirtualFreeEx(hProcess, Pointer, 0, (uint)VirtualFreeExTypes.MEM_RELEASE);
CloseHandle(hProcess);
}
Но это пример нажатия ToolBar в InternetExplorer. Как бы адаптировать его под WindowsForms(форма скорей всего VB6). Контроллер многострадальный msvb_lib_toolbar, который как класс на форме не находится, хотя Spy++ его показывает. Путем проб и ошибок было выяснено, что найти его можно как класс Toolbar20WndClass(да, 20 - это часть имени класса). Собственно, вопрос простой. Как из-под C# WindowsForm нажать кнопку в контроле Toolbar20WndClass на приложении созданном на VB6?
Ответы (1 шт):
Автор решения: Евгений Бубнов
→ Ссылка
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("USER32.DLL")]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,
bool bInheritHandle,
int processId
);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true)]
static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll")]
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint dwFreeType);
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr handle);
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[Flags]
public enum MouseEventFlags : uint
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
public enum VirtualFreeExTypes : uint
{
MEM_DECOMMIT = 0x4000,
MEM_RELEASE = 0x8000
}
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left, Top, Right, Bottom;
}
const int WM_USER = 0x0400;
const int TB_GETITEMRECT = (WM_USER + 29);
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
public static int MAKELONG(int x, int y)
{
return (x & 0xffff) | ((y & 0xffff) << 16);
}
public static RECT ByteArrayToRect(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
RECT stuff = (RECT)Marshal.PtrToStructure(
handle.AddrOfPinnedObject(), typeof(RECT));
handle.Free();
return stuff;
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr form = FindWindow("ThunderRT6FormDC", "Form1");
IntPtr toolbar = FindWindowEx(form, IntPtr.Zero, "Toolbar20WndClass", string.Empty);
IntPtr msvb_tool = FindWindowEx(toolbar, IntPtr.Zero, "msvb_lib_toolbar", string.Empty);
IntPtr nNumberOfBytesRead;
RECT winRect = new RECT();
GetWindowRect(msvb_tool, out winRect);
int dwProcessID;
GetWindowThreadProcessId(msvb_tool, out dwProcessID);
IntPtr hProcess = OpenProcess((ProcessAccessFlags.VirtualMemoryOperation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.VirtualMemoryWrite), false, dwProcessID);// prc.Handle;//Process.GetCurrentProcess(); //
IntPtr Pointer = VirtualAllocEx(hProcess, (IntPtr)0, 4096, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
RECT bi;
SendMessage(msvb_tool, TB_GETITEMRECT, (IntPtr)0 /* индекс кнопки*/, (IntPtr)Pointer);
byte[] buffer = new byte[16];
ReadProcessMemory(hProcess, (Pointer), buffer, (uint)buffer.Length, out nNumberOfBytesRead);
bi = ByteArrayToRect(buffer);
PostMessage(msvb_tool, WM_LBUTTONDOWN, (IntPtr)0, (IntPtr)MAKELONG(bi.Left, bi.Top));
PostMessage(msvb_tool, WM_LBUTTONUP, (IntPtr)0, (IntPtr)MAKELONG(bi.Left, bi.Top));
VirtualFreeEx(hProcess, Pointer, 0, (uint)VirtualFreeExTypes.MEM_RELEASE);
CloseHandle(hProcess);
}
}
Вот рабочий код! Пользуйтесь! Помог мне разобраться WinSpy, указав на матрешку контролов.