get all text written inside a window - c#

I want to get all text of a window.
I prepared below code.But i can only get window captions/titles.
How can i get all text written inside a window ?
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
if (!String.IsNullOrEmpty(process.MainWindowTitle))
{
IntPtr xero = new IntPtr(0);
var x = FindWindowByCaption(xero, process.MainWindowTitle);
int length = GetWindowTextLength(x);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(x, sb, sb.Capacity);
}
}

You need to enumerate all child windows of the top level windows. You can use EnumChildWindows API in order to accomplish that.
Here is the sample code i have written in C# for you
internal class Program
{
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, StringBuilder lParam);
const uint WM_GETTEXT = 0x000D;
static bool EnumAllChilds(IntPtr hWnd, IntPtr lParam)
{
StringBuilder sb = new StringBuilder(2048);
SendMessage(hWnd, WM_GETTEXT, new IntPtr(sb.Capacity), sb);
if (!string.IsNullOrEmpty($"{sb}"))
{
Console.WriteLine($"\t{hWnd:X}\t{sb}");
}
EnumChildWindows(hWnd, EnumAllChilds, lParam);
return true;
}
static bool EnumTopLevel(IntPtr hWnd, IntPtr lParam)
{
StringBuilder sb = new StringBuilder(2048);
SendMessage(hWnd, WM_GETTEXT, new IntPtr(sb.Capacity), sb);
Console.WriteLine($"TopLevel: hWnd: {hWnd:X}\t{(string.IsNullOrEmpty($"{sb}") ? "No Caption" : $"{sb}")}");
// Call for child windows
EnumChildWindows(hWnd, EnumAllChilds, lParam);
return true;
}
static void Main(string[] args)
{
// Call for TopLevel windows
EnumWindows(EnumTopLevel, IntPtr.Zero);
Console.ReadLine();
}
}

Related

Enter data in a text box of windows pop up using C#

I have to enter the file path in a text box of windows popup
I have tried a piece of the code which can return the handle of a window based on its name.
class Program
{
private const int WM_GETTEXT = 13;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
static void Main(string[] args)
{
IntPtr Hwnd = FindWindow(null, "Choose File to Upload");
// Alloc memory for the buffer that recieves the text
IntPtr Handle = Marshal.AllocHGlobal(100);
// send WM_GWTTEXT message to the notepad window
int NumText = (int)SendMessage(Hwnd, WM_GETTEXT, (IntPtr)50, Handle);
// copy the characters from the unmanaged memory to a managed string
string Text = Marshal.PtrToStringUni(Handle);
}
my pop looks like:
I need to set data in a text box of the window.

Using SendMessage() to write to Excel in C#

I made before a program where I could open a process of the notepad and while it's opened, be able to write in it from the C# program console. Now I'm trying to do the same but with the excel, I can run the process, I can open it and I can kill it. But when I try to write in it with the SendMessage() method, nothing happens, is there a way I can do this? Or am I missing something? Thanks!
Here's what I tried so far
Declarations
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
//include SendMessage
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
[DllImport("User32.dll")]
static extern int SetForegroundWindow(IntPtr point);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
extern static int SendMessageGetTextLength(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
const uint WM_PASTE = 0x302;
const int WM_SETTEXT = 0X000C;
const int WM_GETTEXTLENGTH = 0x000E;
const int EM_SETSEL = 0x00B1;
const int EM_REPLACESEL = 0x00C2;
static void Main(string[] args)
{
//Abre o programa
Process prcss = new Process();
prcss.StartInfo.FileName = "excel.exe";
prcss.Start();
string aux = prcss.StartInfo.FileName;
//Verifica se o processo está a correr
Process[] processlist = Process.GetProcesses();
Code to write in it with the SendMessage().
case "2":
while (true)
{
//Testar com o SendMessage
Console.WriteLine("\nTexto: \n");
string texto = Console.ReadLine();
if (aux.Length == 0)
{
return;
}
if (prcss != null)
{
IntPtr notepadTextbox = FindWindowEx(prcss.MainWindowHandle, IntPtr.Zero, "edit", null);
int length = SendMessageGetTextLength(notepadTextbox, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
if (!notepadTextbox.Equals(IntPtr.Zero))
{
//sending the message to the textbox
SendMessage(notepadTextbox, WM_SETTEXT, 0, texto);
SendMessage(notepadTextbox, EM_SETSEL, length, length);
SendMessage(notepadTextbox, EM_REPLACESEL, 1, texto + "\n");
}
}
Console.WriteLine("Sair? (S)im / (N)ão");
sair = Console.ReadLine();
if (sair == "s" || sair == "S")
{
IntPtr k = prcss.MainWindowHandle;
SetForegroundWindow(k);
prcss.Kill();
break;
}
}

Cefsharp change the parameter passed to the site the width and height of the screen c#

can you help, how you can change the screen size, which cefsharp transmits ? I go to ipleak.net and saw
Your screen: 1920 x 1080
Available screen: 1920 x 1040
Is there any way to change it ?
I tried that, but it didnt work
DllImport("user32.dll", EntryPoint = "SetWindowPos")]
static extern bool SetWindowPos(
int hWnd, // window handle
int hWndInsertAfter, // placement-order handle
int X, // horizontal position
int Y, // vertical position
int cx, // width
int cy, // height
uint uFlags); // window positioning flags
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
protected delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
protected static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
protected static extern bool IsWindowVisible(IntPtr hWnd);
public static IntPtr m_hwndForm;
protected static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
{
int size = GetWindowTextLength(hWnd);
if (size++ > 0 && IsWindowVisible(hWnd))
{
StringBuilder sb = new StringBuilder(size);
GetWindowText(hWnd, sb, size);
string strName = sb.ToString();
if (strName.Contains("Form111111"))
m_hwndForm = hWnd;
}
return true;
}
...
EnumWindows(new EnumWindowsProc(EnumTheWindows), IntPtr.Zero);
SetWindowPos(m_hwndForm.ToInt32(), 0, 10, 20, 600, 800, 0x0040);
InitializeChromium();
or
settings.CefCommandLineArgs.Add("Screen-width", "800");
settings.CefCommandLineArgs.Add("Screen-height", "600");
I've found, that's possible through chrome DevTools protocol using setDeviceMetrics method. Many thanks to amaitland!
var client = browser.GetDevToolsClient();
await client.Emulation.SetDeviceMetricsOverrideAsync(1000, 800, 1, true);
You also need to fully initialize CefSharp browser before use this method.

notepad character decoding

I am reading text from a notepad opened by my program.and this is my code
const int WM_GETTEXT = 0x000D;
const int WM_GETTEXTLENGTH = 0x000E;
[DllImport("User32.dll", EntryPoint = "SendMessage")]
extern static int SendMessageGetTextLength(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
extern static IntPtr SendMessageGetText(IntPtr hWnd, int msg, IntPtr wParam, [Out] StringBuilder lParam);
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
public static string GetText(IntPtr hwnd)
{
if (hwnd == IntPtr.Zero)
throw new ArgumentNullException("hwnd");
IntPtr handler = FindWindowEx(hwnd, new IntPtr(0), "Edit", null);
int length = SendMessageGetTextLength(handler, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
if (length > 0 && length < int.MaxValue)
{
length++;
StringBuilder sb = new StringBuilder(length);
SendMessageGetText(handler, WM_GETTEXT, (IntPtr)sb.Length, sb);
return sb.ToString();
}
return String.Empty;
}
It is getting the text but in a special encoding.
For example, if the text entered is 'hello' it gets '興梀㇨ȿڳㇺ'.
What is the encoding of this text so I can decode it to ASCII?
Your problem is in fact that you are passing sb.Length in the WM_GETTEXT message, when in fact you should be passing sb.Capacity or even just length.
I would do it like this:
if (length > 0 && length < int.MaxValue)
{
StringBuilder sb = new StringBuilder(length+1);
SendMessageGetText(handler, WM_GETTEXT, (IntPtr)length+1, sb);
return sb.ToString();
}
I'd also point out that WM_GETTEXT will not return more than 64k characters to the length < int.MaxValue isn't what you need.
Of course, in the longer run it may be better to use the Unicode throughout so that you can support international text.
I personally would always opt for using the Unicode APIs and use the following p/invoke declarations:
[DllImport("User32.dll", EntryPoint = "SendMessage",
CharSet = CharSet.Unicode, SetLastError = true)]
extern static int SendMessageGetTextLength(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", EntryPoint = "SendMessage",
CharSet = CharSet.Unicode, SetLastError = true)]
extern static IntPtr SendMessageGetText(IntPtr hWnd, int msg, IntPtr wParam, StringBuilder lParam);
[DllImport("user32.dll", EntryPoint = "FindWindowEx",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
Since you're writing in managed code, you may as well use the managed code automation interfaces, which does all the interop for you. Why reinvent the wheel?
using System.Windows.Automation;
public static string GetText(IntPtr hwnd)
{
IntPtr hwndEdit = FindWindowEx(hwnd, IntPtr.Zero, "Edit", null);
return (string)AutomationElement.FromHandle(hwndEdit).
GetCurrentPropertyValue(AutomationElement.NameProperty);
}
You can even make the automation do the FindWindowEx for you:
public static string GetText(IntPtr hwnd)
{
var editElement = AutomationElement.FromHandle(hwnd).
FindFirst(TreeScope.Subtree,
new PropertyCondition(
AutomationElement.ClassNameProperty, "Edit"));
return (string)editElement.GetCurrentPropertyValue(AutomationElement.NameProperty);
}

Keyboard Hook Not Catching Every Key

I'm having a problem with a Global Keyboard Hook.
For the most part, it works. Bu,t in the section below, it should be stopping the enter key from being passed onto the focused program. It only works about half the time.
Any ideas as to why it would block the enter key sometimes and not others?
Here is the relevant code:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
And:
_hookID = SetHook(_proc);
And:
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
Keys keyName;
bool validKey;
int vkCode = Marshal.ReadInt32(lParam);
keyName = (Keys)vkCode;
validKey = monitorKeys.Contains(keyName.ToString()); //checks if the current key is in our list of keys to monitor
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
vkCode = Marshal.ReadInt32(lParam);
keyName = (Keys)vkCode;
if (validKey && keyName == Keys.Enter && altActive == false && ctrlActive == false)
{
char c = new char();
c = KeyConvertor.ToAscii(keyName);
}
displayBuffer += c.ToString();
//do some db lookups on the current word here
lblBuffer.Text = displayBuffer;
return (IntPtr)1; //no key is sent to program This only works about half the time even though (IntPtr)1 is being returned.
}
return CallNextHookEx(_hookID, nCode, wParam, lParam); //key is passed on to program
}
}
else if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)
{
//trap the key
return (IntPtr)1;
}
return CallNextHookEx(_hookID, nCode, wParam, lParam); //key is passed on to program
}

Categories

Resources