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).
Related
In WPF is it possible to make a Window "Always on top" of another external process window?
Suppose I would want my application to show always over the "notepad.exe" window only?
You're looking for the SetWindowPos function. In C#, you can implement a wrapper as such:
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
You can learn more on pinvoke about the supported parameters that you can pass - you will need to reliably identify the window handle for the process, and then overlay the window.
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 use unmanaged libraries to obtain video stream from IP Camera.
There is function:
[DllImport("client.dll", EntryPoint = "Network_ClientStartLive", SetLastError = true)]
protected static extern int Network_ClientStartLive(
ref IntPtr pStream,
IntPtr hDev,
IntPtr pClientInfo,
[MarshalAs(UnmanagedType.FunctionPtr)] ReadDatacbf lpfnCallbackFunc = null,
UInt32 dwUserData = 0
);
The pClientInfo is a pointer to structure type of:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
protected struct LiveConnect
{
public UInt32 dwChannel;
public IntPtr hPlayWnd;
public UInt32 dwConnectMode;
}
where hPlayWnd is a handle of window in which video stream must be output.
The library detects the video resolution by size of this window (during the call to Network_ClientStartLive). I checked it on C++ MFC program, where output window is Picture control and by setting size with method MoveWindow was defined output video resolution.
In the C# version of this program I'm using a PictureBox-control to draw the video stream. The video is displayed but the size of the PictureBox does not affect to video stream resolution. I tried several methods to change PictureBox size:
setting pictureBox.Size
using WinAPI SetWindowPos:
[DllImport("user32.dll")]
private static extern bool SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int x,
int y,
int width,
int height,
uint uFlags);
In both methods the size of the control was changed but the camera library continued to output video stream in maximum resolution.
How can I solve this problem?
Thanks!
Every control in Windows Forms has a SizeChanged (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.sizechanged(v=vs.110).aspx) event. Maybe its possible to add code to change the video resolution manually in this event handler? If not, the PictureBox handle you provide may not be sending WM_SIZE messages which would be what the unmanaged library would be looking for. As mentioned in one of the comments, Spy++ (included with Visual Studio) would be a useful program to monitor the messages and make sure that the handle values and the events are what you expect them to be.
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.