How to press a button in external application - c#

First of all, have in mind that Im a beginner.
With that said, Im trying to press a button in an external application with user32.dll. I have tried a lot of solutions but cant find anything that works.
I am using 3 DllImport because I want to bring the window to the front aswell (This works fine)
It looks like this:
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String
WindowName);
[DllImportAttribute("User32.dll")]
private static extern IntPtr SetForegroundWindow(int fgr);
[DllImport("user32.dll")]
static extern bool SendMessage(IntPtr hWnd, uint Msg, int wParam, int
lParam);
const int BN_CLICKED = 245;
When I click a button, it will bring the application to the front, like this:
private void button1_Click(object sender, EventArgs e)
{
int fgr = FindWindow("TAssistMainFrm", null);
if (fgr > 0) //If found
{
MessageBox.Show("Window found!");
SetForegroundWindow(fgr);
}
else //Not Found
{
MessageBox.Show("Window Not Found!");
}
}
As I said, this works absolutly fine!
Heres the problem.
I want to press a button with ClassNN TButton10
I have tried:
SendMessage(TButton10, BN_CLICKED, 0, 0);
And a lot of other things, but Im guessing that I need to find TButton10 and declare it first. How should I do that?
Anyone that can help me out with code that works, and an explanation of the code?
Thanks a lot!

Related

C# Deselect COMobject WordDocument

In Visual Studio I've created a Word 2016 Document project. To this document I've added a custom ActionsPane control. The only thing this control does is adding a PlainTextContentControl to the active document.
if (Globals.ThisDocument.Content.Application.ActiveDocument == null) return;
var tagControl = Globals.ThisDocument.Controls.AddPlainTextContentControl(Guid.NewGuid().ToString());
tagControl.PlaceholderText = #"PLACEHOLDER";
tagControl.LockContents = true;
This all works fine, the plaintextcontrol is added and selected in the Word document. But what I want is that the control is added and that the cursor will jump to the end of the control so a user can directly start typing. The newly added control is automatically selected. How can I turn this of?
I have already tried:
var range = Globals.ThisDocument.Content;
range.Application.Selection.Collapse();
Can anyone help me out here? Thanks.
Edit:
Als tried this solution.
private static IntPtr documentHandle;
public delegate bool EnumChildProc(IntPtr hwnd, int lParam);
[DllImport("user32.dll")]
public static extern System.IntPtr SetFocus(System.IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int EnumChildWindows(IntPtr hWndParent, EnumChildProc callback, int lParam);
[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder title, int count);
private static bool EnumChildWindow_Handle(IntPtr handle, int lparam)
{
StringBuilder s = new StringBuilder(50);
GetWindowText(handle, s, 50);
Debug.WriteLine(s.ToString());
if (s.ToString() == "Microsoft Word-document")
{
documentHandle = handle;
}
return true;
}
private void MoveCursorToEndOfLastAddedTag(PlainTextContentControl ctrl)
{
EnumChildProc EnumChildWindow = new EnumChildProc(EnumChildWindow_Handle);
EnumChildWindows(Process.GetCurrentProcess().MainWindowHandle, EnumChildWindow, 0);
SetFocus(documentHandle);
}
This also doesn't work.
Finally I have success. It's not the most clean way, but it works like a charm. The only code I made is this:
private void MoveCursorToEndOfLastAddedTag(PlainTextContentControl ctrl)
{
System.Windows.Forms.SendKeys.Send("{F10}");
System.Windows.Forms.SendKeys.Send("{F10}");
System.Windows.Forms.SendKeys.Send("{RIGHT}");
}
It sends 2 times the F10 key. First time the focus is set to the ribbon, the second time the focus is given back to the document. With the right key I remove the selection from the PlainTextContentControl.
Thank you all for your help.

Open the start menu right next the program?

I've been researching how to open the Start Menu programmatically, but the problem is that I'd like it to open it right next to the application I'm creating.
I'm making a toolbar at the top of the screen with a button to open the start menu, but I'd like the Start Menu to open right underneath the button rather than near the taskbar. I'm using the code supplied in the answer to this question, which only sends the required keypress (LWin) to open the Start Menu.
Is this possible in C#? If so, how can I do it?
EDIT: Apparently, this only works on English versions of Windows, due to "Start menu" being different in each translation. This will still work, though (as long as Windows is installed in English).
I got it! This works, though I don't know how pretty it is:
public partial class Form1 : Form {
private void button1_Click(object sender, EventArgs e) {
int ShowCmd = 5;
MoveWindow(FindWindow("DV2ControlHost", "Start menu"), X_POS, Y_POS, WIDTH_HERE, HEIGHT_HERE, false);
ShowWindow(FindWindow("DV2ControlHost", "Start menu"), ShowCmd);
}
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
}
It's a mix of this question here on SO and this MSDN article modified for C#. Again, I'm not sure how good the code is, but it gets the job done.

Performing a mouse click without moving cursor

I couldn't find any solution except moving the cursor by Cursor class, clicking with mouse_event then moving the cursor to its old position. I am playing with SendInput function right now but still no chance for a good solution. Any advice?
You should use Win32 API.
Use pInvoked SendMessage from user32.dll
pInvoked Function
Then read about mouse events:
Mouse Input on msdn
And then read about: System events and Mouse Mess.......
Also there is lots of info:
Info
Here's an example following the approach Hooch suggested.
I created a form which contains 2 buttons. When you click upon the first button, the position of the second button is resolved (screen coördinates). Then a handle for this button is retrieved. Finally the SendMessage(...) (PInvoke) function is used to send a click event without moving the mouse.
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "WindowFromPoint",
CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr WindowFromPoint(Point point);
private const int BM_CLICK = 0x00F5;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Specify the point you want to click
var screenPoint = this.PointToScreen(new Point(button2.Left,
button2.Top));
// Get a handle
var handle = WindowFromPoint(screenPoint);
// Send the click message
if (handle != IntPtr.Zero)
{
SendMessage( handle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
}
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Hi", "There");
}
}

Send key "MediaPlayPause" to an application without setting focus to it

I am creating a program that will send media key inputs (such as MediaPlayPause, MediaNextTrack, etc) to an application that I have the IntPtr of. Sort of like a virtual remote control.
So after researching I found this, which almost tells me exactly how to solve my problem.
However, there are three problems with the approach mentioned in the link.
I cannot set the application as foreground window as I need my application to be focused.
They use the SendKeys function which requires the target window to be focused, goes against problem 1.
From what I know, SendKeys cannot send keyboard buttons such as the keyboard Play/Pause button.
In the end, I am rather confused on what I have to use (SendInput?, SendMessage?).
Any help would be appreciated.
EDIT
Using the answer I received, I hacked together the sample code below.
Theoretically, it is supposed to find notepad and insert the letter "L" into it.
However nothing shows up on notepad, nor does the application crash. Is there an obvious error I am missing?
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, IntPtr lParam);
const int WM_KEYDOWN = 0x100;
//const int WM_KEYUP = 0x101;
const int L_KEY = 0x4C;
private void button1_Click(object sender, EventArgs e)
{
IntPtr ip = FindWindowByCaption(0, "Untitled - Notepad");
SendMessage(ip, WM_KEYDOWN, L_KEY, IntPtr.Zero);
//SendMessage(ip, WM_KEYUP, L_KEY, IntPtr.Zero);
}
Most of these keys are translated to WM_APPCOMMAND* messages... so you can try SendMessage, the other option being SendInput (if the application is DirectInput-based)...
Check out the links in Windows API for common media player functions? - perhaps there is some information you can use...
As for the focus problem - there is no 100% reliable solution (see How do I send key strokes to a window without having to activate it using Windows API?)... best you can achieve with 100% reliability is to focus the application, send the keys, refocus your application... except you would write some sort of device driver (kernel mode)...
To send multimedia keys, including Play/Pause, NextTrack, PrevTrack, etc, you can use keybd_event:
public class Program
{
public const int KEYEVENTF_EXTENTEDKEY = 1;
public const int KEYEVENTF_KEYUP = 0;
public const int VK_MEDIA_NEXT_TRACK = 0xB0;
public const int VK_MEDIA_PLAY_PAUSE = 0xB3;
public const int VK_MEDIA_PREV_TRACK = 0xB1;
[DllImport("user32.dll")]
public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo);
public static void Main(string[] args)
{
keybd_event(VK_MEDIA_PLAY_PAUSE, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // Play/Pause
//keybd_event(VK_MEDIA_PREV_TRACK, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // PrevTrack
//keybd_event(VK_MEDIA_NEXT_TRACK, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // NextTrack
}
Here is a list to the supported key codes that this windows api can handle:
https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
The SendKeys class is very nice, but it's also limited. The approach above sends the key command directly to Windows OS.

Scrolling textboxes programmatically using WndProc messages

I'm trying to scroll a textbox using the form's WndProc method. The code I've come up with so far, after scouring the internet, looks like this:
private void ScrollTextBox()
{
scrollMessage = Message.Create(TabContents.Handle, 0x00B6, new IntPtr(0x0003), new IntPtr(0x0000));
this.WndProc(ref scrollMessage);
}
where TabContents is a TextBox.
For some reason, nothing happens when i call this method. I'd like to know why. I realise that i can accomplish the same with the MoveToCaret method, but I'm curious why this is not working.
EDIT:
As in the posted answer from Beaner, I wrote another method using SendMessage:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private void ScrollTextBox2(int lines)
{
SendMessage(TabContents.Handle, 0x00B6, new IntPtr(0), new IntPtr(lines));
}
This seems to work %100. I'm still curious why this.WndProc(ref message) doesn't work, given a message created with the same set of parameters.
This may be possible, but I have never tried it that way. I have used SendMessage to send a windows message directly to the textbox to cause scrolling.
private const int WM_VSCROLL = 0x115;
private const int SB_BOTTOM = 7;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam,
IntPtr lParam);
// Scroll to the bottom, but don't move the caret position.
SendMessage(TabContents.Handle, WM_VSCROLL, (IntPtr) SB_BOTTOM, IntPtr.Zero);

Categories

Resources