I'm trying to grab a window by the process name and focus it, then take a screenshot of it. It works perfectly unless I have Teamviewer open (not even while using teamviewer to screenshare, just when teamviewer is running)
When teamviewer is running the window isn't focused or brought to the foreground, and the rect it screenshots is very small (33x21) where normally it would be 1600x900.
Here is the code in question:
proc = Process.GetProcessesByName(procName)[0];
SetForegroundWindow(proc.MainWindowHandle);
ShowWindow(proc.MainWindowHandle, SW_RESTORE);
Rect rect = new Rect();
GetWindowRect(proc.MainWindowHandle, ref rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Graphics.FromImage(bmp).CopyFromScreen(rect.left, rect.top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);
Here is where I'm getting those functions:
[DllImport("user32.dll")]
private static extern IntPtr ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);
I too have found that teamViewer break UI Automation. Disabling the "Present this Application" function re-enables UI Automation to work.
I have encountered a similar problem. On two Windows 7 Pro computers I noticed that with the TeamViewer client running the following code stops working.
var wordProcess = Process.GetProcessesByName("winword")
.FirstOrDefault(process => process.MainWindowTitle.Contains(documentName));
Setting a breakpoint and inspecting single running WINWORD process reveals that Process.MainWindowTitle property is blank most of the times. While WinWord windows taskbar icon clearly shows the title.
Exiting TeamViewer restores the things back to normal: Process.MainWindowTitle every time becomes properly populated.
I have reported the issue to the TeamViewer team.
Tested with:
TeamViewer 9 ver. 9.0.27339, set for unattended access; MS Word 2007
Related
I want to tile two windows programs horizontally in C#. It's for a data view program using Chrome for viewing 2d images and Unity3d is for 3d and navigation.
For example, i can select two programs in windows task manager, and the context has an option to tile them.
Is there a handle in the .Net framework for tiling different program windows?
Probably the best thing is to use MoveWindow (Where hWnd is the window to move):
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
MoveWindow(ApplicationHandle, 600, 600, 600, 600, true);
If you don't know the window pointer, you can use the FindWindow functionality.
Also worth a read is MSDN SetWindowPos (Very similar to MoveWindow).
We have a C# base frame program here in the company, it is able to run C# codes. When it starts, it runs in full screen mode, besides we have more program that runs in parallel.
I would like to put our program to the left side, another program to the right side on the screen at startup.
How can I move or resize 3rd party program windows in C#?
You can do it with MoveWindow WinAPI function:
//Import:
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
//Usage:
MoveWindow(ApplicationHandle, 600, 600, 600, 600, True);
As a fun office project we are building a cool transitional background Winform's app to replace the standard windows desktop background.
One of the challenges is that we need our WinForm window to sit on top of the desktop background and icons but not the taskbar.
Is there some way to precisely adjust the Z-Index of a winform window so that it sits on top of the windows desktop but still allows the taskbar and other windows to sit on top of it?
Thank you for the assistance in getting this working. The following worked for us.
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
const short SWP_NOMOVE = 0X2;
const short SWP_NOSIZE = 1;
const short SWP_NOZORDER = 0X4;
const int SWP_SHOWWINDOW = 0x0040;
Usage as follows.
// Our desktop is the top most window.
IntPtr desktop = new IntPtr(0);
// The running form we are testing this code with.
IntPtr form1 = System.Windows.Forms.Application.OpenForms[0].Handle;
// So we're setting our window Z-index to that of the desktop,
// but we setting flags for showing the window and then not not moving and resizing it.
SetWindowPos(form1, desktop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
The Spy++ is really a great tool to learn about the structure of windows and child windows. We found out that setting the IntPtr to Zero will automatically make it select the Desktop (most top) window.
Download spy++ http://mdb-blog.blogspot.com/2010/11/microsoft-spy-or-spyxx-for-download.html then check what's the desktop handle and the start menu handle respectively. This is just to make the proof of concept later you have to find out a better way of taking the handles. Using P\Invoke calls you can get those windows z-order
int GetZOrder(IntPtr hWnd)
{
var z = 0;
for (IntPtr h = hWnd; h != IntPtr.Zero; h = GetWindow(h, 3)) z++;
return z;
}
That code was copied from this question How to get the z-order in windows?
Then you can use SetWindowPos https://msdn.microsoft.com/en-us/library/windows/desktop/ms633545%28v=vs.85%29.aspx to position your own windows exactly where you want it to be. If you are using windows 8 have in mind that a lot of folks have ClassicShell installed on their machines. Good luck.
I'm developing a .NET app that involves text analyzing.
i would like to retrieve the text from the current focused window active text box. And much preferably from the location of the Windows cursor
This should be independent of the process, meaning if the user is writing in Word i would like to retrieve the words typed "near" the position of the cursor, also in Chrome or IE url etc.
Does anyone knows of a good solution to this in .NET?
A good starting point would be to get the control that the mouse is over, which can be done like this:
[DllImport("user32.dll")]
static extern IntPtr ChildWindowFromPoint(IntPtr hWndParent, Point Point);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(Point Point);
[DllImport("user32.dll")]
static extern bool ScreenToClient(IntPtr hWnd, ref Point lpPoint);
//...
Point p = Cursor.Position;
IntPtr phwnd = WindowFromPoint(Cursor.Position);
ScreenToClient(phwnd, ref p);
IntPtr hwnd = ChildWindowFromPoint(phwnd, p);
From there you can get the text from the control in a method similar to the one answered here:
https://stackoverflow.com/a/7740920/1794305
I wanna send key stroke to a program even if it is running in background. But I can do this only for NOTEPAD like this,
[DllImport("user32.dll")]
protected static extern byte VkKeyScan(char ch);
[DllImport("user32.dll", SetLastError = true)]
protected static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
protected static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
char Key = // key value to send
IntPtr hWnd = FindWindowEx(_handle, IntPtr.Zero, "edit", null); // _handle is the windows handle of the program (here its notepad)
PostMessage(hWnd, WM_KEYDOWN, VkKeyScan(Key), 0);
But for all other applications I can't send keystrokes if its in background. Since I don't know the lpszClass of that program (I think this is the userControl name of the typing area in that program. For NotePad it is "edit". I found this surfing internet).
For all other applications what I'm doing is, get the application to foreground, then send the key, then again get my program foreground. I need my program to be run as foreground always.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
SetForegroundWindow(_handle); // _handle is the windows handle of the program
System.Threading.Thread.Sleep(50); // Waiting few milliseconds till application coming to foreground.
wsh.SendKeys(Key.ToString(), ref wait); // wsh is WshShellClass wsh= new WshShellClass();
SetForegroundWindow(_mainHandle); // _mainHandle is the windows handle of my application
But this way is not working. some keys getting missed and the program foreground->background->foregound->background...... like its dancing...
How to send keys to other applications if its running in background.
or are there any way/source to find the lpszClass of a program ?
Sorry if I have missed any required information. this is a large application. I have posted only required parts here. If someone needs any additional information, pls ask.
I think you'll need to have the background program install a low-level keyboard hook via the win32 function SetWindowsHookEx().
Here's the MSDN documentation for SetWindowsHookEX()
http://msdn.microsoft.com/en-us/library/ms644990(v=vs.85).aspx
And here's the KB article on how to do it from C#
http://support.microsoft.com/kb/318804
This article goes into some detail, too: http://www.codeguru.com/columns/vb/article.php/c4829
I expect your app will get caught by various spyware/anti-virus software as a keyboard logger, though.
Good luck.
You may be able to figure out the lpszClass of the program using an inspection tool such as WinSpy++. It gives you a crosshair that you can drag and position over the desired control. This was able to easily provide me with the "edit" class name for notepad.
If things aren't working, click the "More>>" button in the lower right of WinSpy++, then click the "Locate" button to view the control hierarchy; you may need to post the WM_KEYDOWN message to one of the parent or child controls instead.