|
|
How to place a .exe file into the panel in visual studio windows form application c#.
using this
System.Diagnostics.Process.Start("calc.exe");
the calculator.exe will pop up after a button is being clicked. how do i do it in a way such that the calculator is being displayed in the panel after the button is clicked?
and also if i want to run another exe file of my own in this panel how do i go about doing it?
|
|
|
|
|
Using the SetParent API might help you achieve this.
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);
void LoadProcessInPanel
{
...
Process process = Process.Start("calc.exe");
SetParent(process.MainWindowHandle, myPanel.Handle);
...
}
modified 10-Mar-12 1:44am.
|
|
|
|
|
Unless Calc.exe starts a lot quicker than it does on my PC, you need a delay before you change the parent - it won't work until the window is fully constructed.
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
The solution Abhinav gave you will not work as is: you need to wait for the window to be fully loaded before you set the new value:
Process process = Process.Start("calc.exe");
Thread.Sleep(500);
SetParent(process.MainWindowHandle, myPanel.Handle);
You will also need to move it to a "sensible" location within your panel after you display it.
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
private const short SWP_NOMOVE = 0X2;
private const short SWP_NOSIZE = 1;
private const short SWP_NOZORDER = 0X4;
private const int SWP_SHOWWINDOW = 0x0040;
private void myButton_Click(object sender, EventArgs e)
{
Process process = Process.Start("calc.exe");
Thread.Sleep(500);
IntPtr processHandle = process.MainWindowHandle;
SetParent(processHandle, myPanel.Handle);
SetWindowPos(processHandle, 0, 0, 0, myPanel.Bounds.Width, myPanel.Bounds.Height, SWP_NOZORDER | SWP_SHOWWINDOW);
}
You might want to look at this: Window Tabifier[^] - it's a bit more complex that you appear to need, but it does everything you want to!
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
You can use the IsWindowVisible[^] function with a while loop instead of sleeping the thread
|
|
|
|
|
I need another coffee...
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
I've just been playing around with this as your question interested me. There's a bit more to just setting the parent handle. This is what I came up with after a little research and testing, it will still need further work but it's a start:
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
public const int GWL_STYLE = -16;
public const int WS_VISIBLE = 0x10000000;
[DllImport("User32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("User32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("User32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("User32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
}
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
internal class ProcessWrapper
{
private Process process = null;
public ProcessWrapper(Process process)
{
this.process = process;
}
public void Close()
{
if (process != null)
process.CloseMainWindow();
}
public void PlaceInControl(Control control)
{
if (control != null && process != null)
{
while (
process.MainWindowHandle == IntPtr.Zero ||
!NativeMethods.IsWindowVisible(process.MainWindowHandle))
{
process.Refresh();
}
process.WaitForInputIdle();
NativeMethods.SetParent(process.MainWindowHandle, control.Handle);
NativeMethods.SetWindowLong(
process.MainWindowHandle,
NativeMethods.GWL_STYLE,
NativeMethods.WS_VISIBLE);
Resize(control.ClientRectangle);
}
}
public void Resize(Rectangle rectangle)
{
if (process != null)
NativeMethods.MoveWindow(
process.MainWindowHandle,
rectangle.X,
rectangle.Y,
rectangle.Width,
rectangle.Height,
true);
}
}
using System;
using System.Diagnostics;
using System.Windows.Forms;
public partial class FormMain : Form
{
private ProcessWrapper processWrapper;
public FormMain()
{
InitializeComponent();
FormClosing += new FormClosingEventHandler(FormMainFormClosing);
panel.Resize += new EventHandler(PanelResize);
processWrapper = new ProcessWrapper(Process.Start("calc.exe"));
processWrapper.PlaceInControl(panel);
}
private void PanelResize(object sender, EventArgs e)
{
if (processWrapper != null)
processWrapper.Resize(panel.ClientRectangle);
}
private void FormMainFormClosing(object sender, FormClosingEventArgs e)
{
if (processWrapper != null)
processWrapper.Close();
}
}
|
|
|
|
|
See this[^] article.
/ravi
|
|
|
|
|
i have tried out and it works! but right now i am facing another problem! how do i adjust the panel width and height? I fixed my panel on the top left hand side with a width of 400px and height 400px. however after the button is being clicked, the exe appear but the position of the panel shifted. how do i ensure that the panel stays where it was as of before?
and also before the exe file is being displayed in the panel, it will pop up the exe first. how can i do it in such a way that it wont pop up and will be displayed immediately in the panel?
|
|
|
|
|
I'm trying to figure out how to pass pointers to variable length arrays. I can't seem to get this to work. Any help? It looks like this:
<pre>
class CHandler:
public int ReadFileBytes(string fileName, byte[] dataForReturn)
{
FileStream fs = File.OpenRead(fileName);
dataForReturn = new byte[fs.length];
fs.Read(dataForReturn, 0, dataForReturn.Length);
fs.Close();
int status = 1;
return status;
}
class DUser:
private void button_Click(...)
{
Read_File(fileName, byte[]dataForReturn);
}
public int Read_File(string fileName, Byte[]* data)
{
CHandler fio = new CHandler();
int result = fio.ReadFileBytes(fileName, data);
}
|
|
|
|
|
MichCl wrote: how to pass pointers to variable length arrays
Not in C#.
CHandler -- can it be static?
ReadFileBytes -- looks OK, but why not return the numbre of bytes read? (Or -1 on failure?)
Read_File -- out byte[] data (no asterisk)
button_Click -- should probably declare dataForReturn
|
|
|
|
|
|
For an app I'm working on, I want the user to be able to include wildcards when specifying the files to open from the command line, e.g. myapp C:\projects\*.cs .
But that causes trouble when I try to extract the path and filename (filespec) with System.IO.Path -- the wildcard characters cause Exceptions.
As a work around, I'm using the following, which works OK, but I doubt it's very robust:
private void
OpenFiles
(
string[] Paths
)
{
foreach ( string path in Paths )
{
int off = path.LastIndexOfAny ( new char[] { '\\' , ':' } ) + 1 ;
string p = off==0 ? ".\\" : path.Substring ( 0 , off ) ;
string f = path.Substring ( off ) ;
foreach ( string fn in System.IO.Directory.GetFiles ( p , f ) )
{
OpenFile ( fn ) ;
}
}
return ;
}
Does anyone here have a better solution to this?
|
|
|
|
|
That is basically it, I created this just the other day:
string folder="";
int i=pattern.LastIndexOf(@"\");
if (i>=0) {
folder=args.Substring(0,i);
pattern=pattern.Substring(i+1);
}
string[] files=Directory.GetFiles(folder, pattern);
Mind you it only accepts wildcards in the fillname itself, not in the folder path. If you need that, you'd have to code a recursive scan.
|
|
|
|
|
I think yours trims off the last backslash, which could be a problem if the only backslash is the first character e.g. \*.cs .
Luc Pattyn wrote: not in the folder path
Right, I don't need that (at this time). But I'm thinking about it.
P.S. What about C:*.cs ?
|
|
|
|
|
PIEBALDconsult wrote: What about C:*.cs ?
I don't care about that, I consider it a bad path, it should have a \ in there.
|
|
|
|
|
|
Not for me it isn't.
|
|
|
|
|
Well, I don't often use it myself, but it's easy enough to handle.
|
|
|
|
|
OK OK! I powered up an ALphaServer...
DIR SYS$SYSTEM:*.COM
|
|
|
|
|
Is it running Mono yet?
|
|
|
|
|
No; you know that OpenVMS is immune to virus.
And here's another example:
JB> def/sys/tra=(con,ter) C BADGER$DQA1:[000000.USERS.badger.]
JB> dir c:*.c
|
|
|
|
|
Message Removed
modified 10-Mar-12 10:10am.
|
|
|
|
|
See the 3rd reply on this[^] page.
/ravi
|
|
|
|