Tjena alla behöver hjälp med att ändra denna koden så att den utgår från det aktiva fönstret som 0,0 i x,y kordinaten. Som det är nu utgår den från skärmens övre vänstra hörn. Koden genererar ett musklick. Tror du du kan visa i koden hur det ska göras? Är inte så hemma på just detta område med API. Point pt = PointToScreen(new Point(50,50)); Vadå fönstret inte skapat än? Jag ska ju inte peka i något fönster jag själv har skapat utan i ett aktivt fönster på skärmen ex notepad fönstret. Du måste hämta koordinaterna för de fönstret som du ska utgå ifrån och därefter addera med dina X och Y positioner. Istället för FindWindow() skulle du kanske eventuellt kunna använda EnumWindows eller GetActiveWindow. Verkar inte fungera. Okej, testa denna. Observera att du måste ändra "Untitled - Notepad" till namnet på det program som du ska hämta koordinaterna för. Tackar så mycket det börjar bli bra nu ;-) Hej igen! Hmm vad tusan??? Verkar som om musknappen alldrig släpps upp. Funkar bra nu med process och allt. Jag har byggt upp en liten testapplikation med en knapp i ett windowsforms och när jag klickar på den knappen simmulers ett musklick. Oj då, fel av mig. Det verkar ha smygit sig in en liten bugg. Jeep nu funkar det utmärkt!!!Behöver hjälp med att modifiera koden!!!
Hoppas någon kan ändra den rätt.
<code>
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class MyForm : Form
{
[DllImport("user32.dll", EntryPoint = "mouse_event")]
static public extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENTF_MOVE = 0x01;
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x03;
private const int MOUSEEVENTF_ABSOLUTE = 0x8000;
public static void Main()
{
Application.Run(new MyForm());
}
public MyForm()
{
MouseClickAt(50, 50);
}
private void MouseClickAt(int x, int y)
{
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP,
x * (65535/Screen.PrimaryScreen.Bounds.Width),
y * (65535/Screen.PrimaryScreen.Bounds.Height),
0,
0
);
}
}
</code>Sv: Behöver hjälp med att modifiera koden!!!
MVH HenrikSv: Behöver hjälp med att modifiera koden!!!
MouseClickAt(pt.X, pt.Y);
Nu tror jag inte det fungerar i konstruktorn, eftersom fönstret då inte är skapat, utan du får lägga koden någon annan stans.
MSSv: Behöver hjälp med att modifiera koden!!!
Sv: Behöver hjälp med att modifiera koden!!!
Du får klistra in nedanstående kod och testa. OBS! Det är torrkodat så det är inte säkert att det fungerar.. kanske kan vara en hjälp på vägen iaf.
<code>
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hwnd, ref RECT rc);
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string className, string windowName);
[StructLayout(LayoutKind.Sequential)]
private struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public MyForm()
{
int x = 50;
int y = 50;
IntPtr hwnd = FindWindow(null, "notepad");
RECT rect = new RECT();
if (GetWindowRect(hwnd, ref rect)) {
MouseClickAt(rect.Left + x, rect.Top + y)
}
{
</code>
/JohanSv: Behöver hjälp med att modifiera koden!!!
Denna if satts exikveras aldrig.
Vad beror det på?
<code>
if (GetWindowRect(hwnd, ref rect)) {
MouseClickAt(rect.Left + x, rect.Top + y)
}
</code>
Fick lite info om Get WindowRect() i söken:
SUMMARY
Under Windows NT and Windows 95, GetWindowRect() returns FALSE (to indicate failure) if the desktop window handle is used. Under Win32s, GetWindowRect() returns TRUE if the desktop window handle is used, however, the RECT structure is not correctly filled in.
On Win32s, GetWindowRect() returns TRUE unconditionally because the 16-bit Windows GetWindowRect() has no return value. Therefore, before calling GetWindowRect() on Win32s, you should first check that the window handle is not the desktop window handle.
MVH Henrik LarssonSv: Behöver hjälp med att modifiera koden!!!
<code>
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class MyForm : Form
{
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hwnd, ref RECT rc);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string className, string windowName);
[DllImport("user32.dll", EntryPoint = "mouse_event")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENTF_MOVE = 0x01;
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x03;
private const int MOUSEEVENTF_ABSOLUTE = 0x8000;
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public static void Main()
{
Application.Run(new MyForm());
}
public MyForm()
{
int x = 10;
int y = 10;
string appname = "Untitled - Notepad";
IntPtr hwnd = FindWindow(null, appname);
RECT rect = new RECT();
if (GetWindowRect(hwnd, ref rect)) {
if (SetForegroundWindow(hwnd)) {
MouseClickAt(rect.Left + x, rect.Top + y);
} else {
MessageBox.Show(appname + " är igång men kunde inte aktiveras.");
}
} else {
MessageBox.Show(appname + " är inte igång!");
}
}
private void MouseClickAt(int x, int y)
{
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP,
Screen.PrimaryScreen.Bounds.Left + (x * (65535/Screen.PrimaryScreen.Bounds.Width)),
Screen.PrimaryScreen.Bounds.Top + (y * (65535/Screen.PrimaryScreen.Bounds.Height)),
0,
0
);
}
}
</code>
/JohanSv: Behöver hjälp med att modifiera koden!!!
Enda problemet är att jag inte kan ta det på programmets namn (det som står uppe i det blå) eftersom det ändras hela tiden. Kan man inte ta och använda Processen ist? För den heter ju samma hela tiden.
Hoppas du inte ger upp på mig nu. Det börjar bli riktigt bra.
MVH Henrik LarssonSv: Behöver hjälp med att modifiera koden!!!
Jo, det ska går bra att använda Process-klassen. Om inte "GetProcessesByName" passar dig så finns det även "GetProcessById" och "GetProcesses".
Testa följande:
<code>
int x = 10;
int y = 10;
string appname = "notepad";
System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(appname);
if (processes.Length>0) {
RECT rect = new RECT();
if (GetWindowRect(processes[0].MainWindowHandle, ref rect) && SetForegroundWindow(processes[0].MainWindowHandle)) {
MouseClickAt(rect.Left + x, rect.Top + y);
}
}
</code>
/JohanSv: Behöver hjälp med att modifiera koden!!!
Nu är det så att när jag skickade ett musklick till painshop pro för att sätta ut en punkt med penseln så funkar det bra men när jag rör musen fortsätter penseln måla så det verkar som om musknappen alldrig släpps upp utan förblir nertryckt. Liknande fel syns vid alla musklick som simmulerats.
Hoppas du kan hjälpa mig med problemet Johan. Du har varit som en gud hitills.
Hur kan man få reda vad processen har för ID?
MVH Henrik LarssonSv: Behöver hjälp med att modifiera koden!!!
Ändra följande rad:
<code>
private const int MOUSEEVENTF_LEFTUP = 0x03;
</code>
... till:
<code>
private const int MOUSEEVENTF_LEFTUP = 0x04;
</code>
Det borde hjälpa men jag har inte testat..
Process.ID ger dig processens id (men det var kanske inte så du menade?)
Ska du göra ett automagiskt ritprogram, eller ? :)
/JohanSv: Behöver hjälp med att modifiera koden!!!
Automatiskt ritprogram ;) Kanske inte är en så dum ide ;))
Tackar för denna utmärkta support!!
Men har en liten annan fråga nu. De funktionerna vi har använt för att få ta i den aktuella processens skärmkordinater känns som om man kan använda dem på något bra sätt för att ta en skärmdump på det aktuella fönstret. Som jag kör nu så simmulerar jag ett tryck på prtscr och plockar ut det aktuella fönstret där ur, men det funkar inte så bra eftersom jag har det i en "evighetsloop" som konstant ligger och övervakar det aktuella fönstret. Undrar om någon vet hur man kan göra på ett bättre sätt för att ta en skärmdump på det aktulla fönstret??
MVH Henrik Larsson