Using Process to display an external program inside winforms - c#

I am trying to embed part of an external program (part of its window) inside a existing WinForm that I am developing.
Following examples online, I came out with the following. I assume that the process name is unique , singular and that it is already open, in the example:
private void button1_Click(object sender, EventArgs e)
{
Process[] myProc = Process.GetProcessesByName("the_external_program_i_want");
Process p = myProc[0];
IntPtr appWin = p.MainWindowHandle;
SetParent(appWin, this.Handle);
SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
MoveWindow(appWin, panel1.Location.X, panel1.Location.Y, panel1.Width, panel1.Height, true);
}
My issue is that after i close my WinForm, I realised that this external program will trigger a pop-up box saying that "program_name has stopped working".
My question is that is there additional functions that I will neeed to call, to close the external program correctly, within the WinForm?
Thanks!

First of all make the p variable accesible to the whole class.
Then add a event listener to the FormClosing event:
this.FormClosing += Window_FormClosing;
void Window_FormClosing(object sender, FormClosingEventArgs e)
{
p.Kill();
}

Related

How to detect if a window is closed C#, Windows Form App?

So, I'm making a payroll management system as a hobby project to help my resume and general knowledge of c#. So, I'm making a UI and I can open a new window just fine with this code:
private void button1_Click(object sender, EventArgs e)
{
CreateAdminAcct createAcct = new CreateAdminAcct();
createAcct.StartPosition = FormStartPosition.CenterScreen;
createAcct.Show();
this.Hide();
}
however, I don't know the event to check when the little red "x" button is clicked, because when that button is clicked, I want to go back to the main screen because I hide the main screen when that button is clicked, and when i click the red "x" on the screen that just opened, it closes, but the application continues to run in the background.
If there is some better way to manage multiple menus, I'm open to suggestions, however, this is what I've found easiest.
Thanks in advance
I second Robert Harvey's suggestion; this gives the user the reassurance tha tht emain window is still open/ nothing got lost, but it's unreachably "behind" the CreateAdminAcct form while the CreateAdminAcct form is open
private void button1_Click(object sender, EventArgs e)
{
CreateAdminAcct createAcct = new CreateAdminAcct();
createAcct.StartPosition = FormStartPosition.CenterScreen;
createAcct.ShowDialog();
//do any code here that needs to access createAcct before it's lost
MessageBox.Show(createAcct.NewAdmin.Name);
}
If you really do want to hide your main form, pass the main form itself to createAcct, and make it createAcct's job to re-open the main form when it is closing
private void button1_Click(object sender, EventArgs e)
{
CreateAdminAcct createAcct = new CreateAdminAcct(this); //note passing this form to constructor
createAcct.StartPosition = FormStartPosition.CenterScreen;
createAcct.Show();
}
class CreateAcctForm : Form{
private Form _showWhenClosing;
CreateAcctForm(Form revertTo){
InitializeComponent();
_showWhenClosing = revertTo;
}
}
void Form_Closing(object sender, ...){ //event
_showWhenClosing.Show();
}
Side note: please rename your controls after you drop them ona form. code that's stuffed with label57, textbox25 is effectively obfuscated and really wearisome to follow

Quitting WPF Application after Window Closed

I have a method in class where I call loginWindow.ShowDialog(); which brings up a Window, however when you press Close (X in top right) it doesn't Quit the application, rather continues to run whatever is below loginWindow.ShowDialog(); in that method.
How am I able to quit the application entirely if that Window is closed?
I tried to use:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
System.Windows.Application.Current.Shutdown();
base.OnClosing(e);
}
Although this didn't shut the application down, which confuses me. When I was using loginWindow.Show(); this wasn't a problem.
I don't know how your application runs, based on your sample code I have two solutions.
Solution 1:- Every window has DialogResult property. Inside the OnClosing event assign DialogResult = true; and call the Shutdown method. The windows who is responsible to call will get the result from return value of ShowDialog() method
For example:-
private void SecondWindow_OnClosing(object sender, CancelEventArgs e)
{
DialogResult = true;
System.Windows.Application.Current.Shutdown();
}
Below event, is from the First screen, calling the Second Window.
private void Button_Click(object sender, RoutedEventArgs e)
{
SecondWindow secondWindow = new SecondWindow();
var dialogResult = secondWindow.ShowDialog();
if (dialogResult.HasValue && dialogResult.Value == false)
{
// any code of yours which must not be executed after the second
// window has closed the process
}
}
Once, the DialogResult is assigned true, the first window will check only if it is false execute the below code or else ignore.
Solution 2:- We will get the Current Application Running Process and Kill the whole process that is your whole application.
private void SecondWindow_OnClosing(object sender, CancelEventArgs e)
{
Process.GetCurrentProcess().Kill();
}
There is a shutdown mode that you can define in the App.Xaml
The default option is OnLastWindowClosed. If it is OnExplicitShutdown than the application wants you to call Application.Shutdown(). What this means is, if you close all windows the application is still running because it is expecting a Application.Shutdown() to be called. This is an explicit shutdown.
Other two options are implicit meaning the Application.Shutdown() method will be called when the last window is closed or when the main window is closed.
Can you check what option you have defined?

Automatically clicking OK button in c# app

Morning all,
I have a c# app where if you press a start button a dialog box will open and the OK button will be automatically pressed. The problem is I don't know how to do this.
The code is below:
private void Start_Click(object sender, EventArgs e)
{
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
var videoSource = captureDevice.VideoDevice;
FinalVideo = captureDevice.VideoDevice;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}
}
I have tried:
Removing the if statement to directly run whats inside it
Put DialogResult.OK = true before the if statement
CaptureDevice.DialogResult.OK = true before the if statement;
Image shows the dialogbox when start is pressed
This dialog let you select the source capturing device. If you want to bypass this dialog you should specify source device in your code. if you use AForge.Net this link help you. if not search for appropriate solution in documentation of component or library you use.
Add a new button to your form. Call it "Settings". In the event handler for this button, you roughly put the first half of what you have now for the Start button. Create a Settings object in your MainForm in which you will store the camera chosen.
private void Settings_Click(object sender, EventArgs e)
{
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
settings.VideoSource = captureDevice.VideoDevice;
}
}
private void Start_Click(object sender, EventArgs e)
{
FinalVideo = settings.VideoSource;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}
Hope this helps.
I have sort of found a solution to the question and it was to use:
SendKeys.Send("{ENTER}");
I used it before the if statement and it works with the Start_Click method but when i use it in a method called Start_Vid(), I get the error:
'SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method'
I have no idea why it should not work and what the error message means so should I be creating another question to have this answered or can it be solved in here do you think?

How to kill a Windows Process through a WPF ListView?

I am a WPF newbee trying to build my own Windows Task Manager.
Right now i have a window with all the active processes running on my machine showing in a ListView.
Now here is my problem: I have a button called End Process. I want to select a process from the ListView and kill it by pressing the End Process button. I just cant figure it out how to do that.
I have this code (C#) assigned to the button:
private void End_Process_Click(object sender, RoutedEventArgs e)
{
Process[] procs=Process.GetProcessesByName(ProcessesListView.SelectedItem.ToString());
foreach (Process p in procs)
{
p.Kill();
}
}
I suspect the items in your list are the actual Process objects. If so, you can do something like this:
private void End_Process_Click(object sender, RoutedEventArgs e)
{
Process process = (Process)ProcessesListView.SelectedItem;
process.Kill();
}

How to disable drag/drop when a dialog box is open

I am working on a large application and am adding some drag/drop functionality to it. Specifically, I am allowing the user to drag and drop a file into the main window to open the file.
The problem is that the drag/drop operation is still allowed to happen when the main window is displaying a dialog box (for example, a properties window for an item in the currently-open file). I would rather not allow this to happen if the main window is displaying a modal dialog box. This is because loading the new file in the application while the dialog box is open would probably crash the program: the code calling the dialog box does not expect the open file to be changed while the dialog box is open (that is why the dialog box was modal...).
The main application is written in C++, but I am posting a C# sample. The symptom/behavior is the same on both platforms, but I can demonstrate it in much less code with C#. I am very familiar with both languages/platforms so I can translate any answers to the appropriate language as needed.
To demonstrate the problem with my sample code, compile and run the following C# code. It will create a "main window" that is a valid drop target. Drag and drop a file from Windows Explorer onto the main window: you should see a "dropped" message box. Now, click the button on the form to pop up a dialog box. Again, attempt to drag and drop a file onto the main window while the dialog box is open. Notice that the drop is allowed even though a modal dialog box is open. How can I prevent this from happening when the dialog is open?
The obvious answer is to temporarily set AllowDrop to false while opening the dialog box. The problem is that the main application is very large and so there are numerous places that open dialog boxes. It will be difficult to find every single place that opens a dialog and add this code. Plus, every developer here would need to know to perform this action every time they open a modal window; it is unlikely that everyone will remember. I am worried that this is not a very good solution.
Surely there is a more maintainable method of doing this that doesn't require adding code in every place that a dialog is opened?
using System;
using System.Windows.Forms;
using System.Drawing;
public class MyDialog : Form {
public MyDialog() {
Text = "MyDialog";
}
}
public class MainForm : Form {
public MainForm() {
Button btn = new Button();
btn.Location = new Point(0, 0);
btn.Text = "ShowDialog";
btn.Size = new Size(75, 23);
btn.Click += new EventHandler(GoToDialog);
this.AllowDrop = true;
this.Controls.Add(btn);
this.Text = "Drop Target";
this.DragDrop += new DragEventHandler(this.MyDragDrop);
this.DragEnter += new DragEventHandler(this.MyDragEnter);
}
private void MyDragDrop(object sender, DragEventArgs e) {
MessageBox.Show("dropped");
}
private void MyDragEnter(object sender, DragEventArgs e) {
e.Effect = DragDropEffects.Copy;
}
private void GoToDialog(object sender, EventArgs e) {
using (MyDialog ab = new MyDialog()) {
ab.ShowDialog(this);
}
}
}
static class Program {
[STAThread]
static void Main() {
Application.Run(new MainForm());
}
}
I'm not sure how things work in C#, so let me know if this answer is incorrect. In C++ MFC, the main window is disabled when a dialog is displayed. You can test to see if the main window is disabled and ignore the drop if so.
private void MyDragDrop(object sender, DragEventArgs e) {
if (CanFocus)
MessageBox.Show("dropped");
}
private void MyDragEnter(object sender, DragEventArgs e) {
if (CanFocus)
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}

Categories