mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
782 lines
27 KiB
C#
782 lines
27 KiB
C#
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2015-2016 Baldur Karlsson
|
|
* Copyright (c) 2014 Crytek
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.Threading;
|
|
using WeifenLuo.WinFormsUI.Docking;
|
|
using renderdocui.Code;
|
|
using renderdoc;
|
|
using System.IO;
|
|
using System.Drawing.Imaging;
|
|
using System.Drawing.Drawing2D;
|
|
|
|
using Process = System.Diagnostics.Process;
|
|
|
|
namespace renderdocui.Windows
|
|
{
|
|
public partial class LiveCapture : DockContent
|
|
{
|
|
MainWindow m_Main = null;
|
|
ImageList thumbs = null;
|
|
|
|
Core m_Core = null;
|
|
|
|
Thread m_ConnectThread = null;
|
|
bool m_TriggerCapture = false;
|
|
bool m_QueueCapture = false;
|
|
int m_CaptureNumFrames = 1;
|
|
int m_CaptureFrameNum = 0;
|
|
int m_CaptureCounter = 0;
|
|
bool m_Disconnect = false;
|
|
TargetControl m_Connection = null;
|
|
|
|
bool m_IgnoreThreadClosed = false;
|
|
|
|
string m_Host;
|
|
UInt32 m_RemoteIdent;
|
|
|
|
class CaptureLog
|
|
{
|
|
public uint remoteID;
|
|
public string exe;
|
|
public string api;
|
|
public DateTime timestamp;
|
|
|
|
public bool saved;
|
|
public bool opened;
|
|
|
|
public string path;
|
|
public bool local;
|
|
};
|
|
|
|
class ChildProcess
|
|
{
|
|
public int PID;
|
|
public uint ident;
|
|
public string name;
|
|
public bool added = false;
|
|
};
|
|
|
|
List<ChildProcess> m_Children = new List<ChildProcess>();
|
|
|
|
public LiveCapture(Core core, string host, UInt32 remoteIdent, MainWindow main)
|
|
{
|
|
InitializeComponent();
|
|
|
|
if (SystemInformation.HighContrast)
|
|
toolStrip1.Renderer = new ToolStripSystemRenderer();
|
|
|
|
m_Core = core;
|
|
m_Main = main;
|
|
|
|
this.DoubleBuffered = true;
|
|
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
|
|
|
|
Icon = global::renderdocui.Properties.Resources.icon;
|
|
|
|
m_Connection = null;
|
|
m_Host = host;
|
|
m_RemoteIdent = remoteIdent;
|
|
|
|
childProcessLabel.Visible = false;
|
|
childProcesses.Visible = false;
|
|
|
|
m_ConnectThread = null;
|
|
|
|
Text = (m_Host.Length > 0 ? (m_Host + " - ") : "") + "Connecting...";
|
|
connectionStatus.Text = "Connecting...";
|
|
connectionIcon.Image = global::renderdocui.Properties.Resources.hourglass;
|
|
|
|
thumbs = new ImageList();
|
|
thumbs.ColorDepth = ColorDepth.Depth24Bit;
|
|
|
|
thumbs.ImageSize = new Size(256, 144);
|
|
captures.TileSize = new Size(400, 160);
|
|
captures.LargeImageList = thumbs;
|
|
|
|
captures.Columns.AddRange(new ColumnHeader[] { new ColumnHeader(), new ColumnHeader(), new ColumnHeader() });
|
|
}
|
|
|
|
public void QueueCapture(int frameNum)
|
|
{
|
|
m_CaptureFrameNum = frameNum;
|
|
m_QueueCapture = true;
|
|
}
|
|
|
|
private void LiveCapture_Shown(object sender, EventArgs e)
|
|
{
|
|
m_ConnectThread = Helpers.NewThread(new ThreadStart(ConnectionThreadEntry));
|
|
m_ConnectThread.Start();
|
|
}
|
|
|
|
private void ConnectionThreadEntry()
|
|
{
|
|
try
|
|
{
|
|
string username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
|
|
|
|
m_Connection = StaticExports.CreateTargetControl(m_Host, m_RemoteIdent, username, true);
|
|
|
|
if (m_Connection.Connected)
|
|
{
|
|
string api = "...";
|
|
if (m_Connection.API.Length > 0) api = m_Connection.API;
|
|
this.BeginInvoke((MethodInvoker)delegate
|
|
{
|
|
if (m_Connection.PID == 0)
|
|
{
|
|
connectionStatus.Text = String.Format("Connection established to {0} ({1})", m_Connection.Target, api);
|
|
Text = String.Format("{0} ({1})", m_Connection.Target, api);
|
|
}
|
|
else
|
|
{
|
|
connectionStatus.Text = String.Format("Connection established to {0} [PID {1}] ({2})",
|
|
m_Connection.Target, m_Connection.PID, api);
|
|
Text = String.Format("{0} [PID {1}] ({2})", m_Connection.Target, m_Connection.PID, api);
|
|
}
|
|
connectionIcon.Image = global::renderdocui.Properties.Resources.connect;
|
|
});
|
|
}
|
|
else
|
|
{
|
|
throw new ReplayCreateException(ReplayCreateStatus.NetworkIOFailed);
|
|
}
|
|
|
|
while (m_Connection.Connected)
|
|
{
|
|
m_Connection.ReceiveMessage();
|
|
|
|
if (m_TriggerCapture)
|
|
{
|
|
m_Connection.TriggerCapture((uint)m_CaptureNumFrames);
|
|
m_TriggerCapture = false;
|
|
}
|
|
|
|
if (m_QueueCapture)
|
|
{
|
|
m_Connection.QueueCapture((uint)m_CaptureFrameNum);
|
|
m_QueueCapture = false;
|
|
m_CaptureFrameNum = 0;
|
|
}
|
|
|
|
if (m_Disconnect)
|
|
{
|
|
m_Connection.Shutdown();
|
|
m_Connection = null;
|
|
return;
|
|
}
|
|
|
|
if (m_Connection.InfoUpdated)
|
|
{
|
|
this.BeginInvoke((MethodInvoker)delegate
|
|
{
|
|
connectionStatus.Text = String.Format("Connection established to {0} ({1})", m_Connection.Target, m_Connection.API);
|
|
Text = String.Format("{0} ({1})", m_Connection.Target, m_Connection.API);
|
|
connectionIcon.Image = global::renderdocui.Properties.Resources.connect;
|
|
});
|
|
|
|
m_Connection.InfoUpdated = false;
|
|
}
|
|
|
|
if (m_Connection.CaptureExists)
|
|
{
|
|
uint capID = m_Connection.CaptureFile.ID;
|
|
DateTime timestamp = new DateTime(1970, 1, 1, 0, 0, 0);
|
|
timestamp = timestamp.AddSeconds(m_Connection.CaptureFile.timestamp).ToLocalTime();
|
|
byte[] thumb = m_Connection.CaptureFile.thumbnail;
|
|
string path = m_Connection.CaptureFile.path;
|
|
bool local = m_Connection.CaptureFile.local;
|
|
|
|
this.BeginInvoke((MethodInvoker)delegate
|
|
{
|
|
CaptureAdded(capID, m_Connection.Target, m_Connection.API, thumb, timestamp, path, local);
|
|
});
|
|
m_Connection.CaptureExists = false;
|
|
}
|
|
|
|
if (m_Connection.CaptureCopied)
|
|
{
|
|
uint capID = m_Connection.CaptureFile.ID;
|
|
string path = m_Connection.CaptureFile.path;
|
|
}
|
|
|
|
if (m_Connection.ChildAdded)
|
|
{
|
|
if (m_Connection.NewChild.PID != 0)
|
|
{
|
|
try
|
|
{
|
|
ChildProcess c = new ChildProcess();
|
|
c.PID = (int)m_Connection.NewChild.PID;
|
|
c.ident = m_Connection.NewChild.ident;
|
|
c.name = Process.GetProcessById((int)m_Connection.NewChild.PID).ProcessName;
|
|
|
|
lock (m_Children)
|
|
{
|
|
m_Children.Add(c);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// process expired/doesn't exist anymore
|
|
}
|
|
}
|
|
|
|
m_Connection.ChildAdded = false;
|
|
}
|
|
}
|
|
|
|
this.BeginInvoke((MethodInvoker)delegate
|
|
{
|
|
connectionStatus.Text = "Connection closed";
|
|
connectionIcon.Image = global::renderdocui.Properties.Resources.disconnect;
|
|
|
|
ConnectionClosed();
|
|
});
|
|
}
|
|
catch (ReplayCreateException)
|
|
{
|
|
this.BeginInvoke((MethodInvoker)delegate
|
|
{
|
|
Text = (m_Host.Length > 0 ? (m_Host + " - ") : "") + "Connection failed";
|
|
connectionStatus.Text = "Connection failed";
|
|
connectionIcon.Image = global::renderdocui.Properties.Resources.delete;
|
|
|
|
ConnectionClosed();
|
|
});
|
|
}
|
|
}
|
|
|
|
Image MakeThumb(Size s, Stream st)
|
|
{
|
|
Bitmap thumb = new Bitmap(s.Width, s.Height, PixelFormat.Format32bppArgb);
|
|
|
|
Graphics g = Graphics.FromImage(thumb);
|
|
|
|
g.Clear(Color.Transparent);
|
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
|
|
if (st != null)
|
|
{
|
|
try
|
|
{
|
|
using (var im = Image.FromStream(st))
|
|
{
|
|
float x = 0, y = 0;
|
|
float width = 0, height = 0;
|
|
|
|
float srcaspect = (float)im.Width / (float)im.Height;
|
|
float dstaspect = (float)s.Width / (float)s.Height;
|
|
|
|
if (srcaspect > dstaspect)
|
|
{
|
|
width = s.Width;
|
|
height = width / srcaspect;
|
|
|
|
y = (s.Height - height) / 2;
|
|
}
|
|
else
|
|
{
|
|
height = s.Height;
|
|
width = height * srcaspect;
|
|
|
|
x = (s.Width - width) / 2;
|
|
}
|
|
|
|
g.DrawImage(im, x, y, width, height);
|
|
}
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
// swallow - invalid thumbnail just allow it to be transparent
|
|
}
|
|
}
|
|
|
|
g.Dispose();
|
|
|
|
return thumb;
|
|
}
|
|
|
|
private void captures_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
|
|
{
|
|
deleteMenu.Enabled = (captures.SelectedItems.Count > 0);
|
|
saveMenu.Enabled = saveThisCaptureToolStripMenuItem.Enabled =
|
|
openMenu.Enabled = openThisCaptureToolStripMenuItem.Enabled =
|
|
(captures.SelectedItems.Count == 1);
|
|
|
|
if(captures.SelectedItems.Count == 1)
|
|
newInstanceToolStripMenuItem.Enabled = (captures.SelectedItems[0].Tag as CaptureLog).local;
|
|
}
|
|
|
|
private void captures_MouseDoubleClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (captures.SelectedItems.Count == 1)
|
|
OpenCapture(captures.SelectedItems[0].Tag as CaptureLog);
|
|
}
|
|
|
|
private void captures_MouseClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Right && captures.SelectedItems.Count > 0)
|
|
rightclickContext.Show(captures.PointToScreen(e.Location));
|
|
}
|
|
|
|
private void OpenCapture(CaptureLog log)
|
|
{
|
|
m_Main.LoadLogfile(log.path, !log.saved, log.local);
|
|
log.opened = true;
|
|
}
|
|
|
|
private bool SaveCapture(CaptureLog log)
|
|
{
|
|
string path = m_Main.GetSavePath();
|
|
|
|
// we copy the temp log to the desired path, but the log item remains referring to the temp path.
|
|
// This ensures that if the user deletes the saved path we can still open or re-save it.
|
|
if (path.Length > 0)
|
|
{
|
|
try
|
|
{
|
|
if (log.local)
|
|
{
|
|
File.Copy(log.path, path, true);
|
|
}
|
|
else
|
|
{
|
|
m_Core.Renderer.CopyCaptureFromRemote(log.path, path, this);
|
|
m_Core.Renderer.DeleteCapture(log.path, false);
|
|
}
|
|
|
|
log.saved = true;
|
|
log.path = path;
|
|
m_Core.Config.AddRecentFile(m_Core.Config.RecentLogFiles, path, 10);
|
|
m_Main.PopulateRecentFiles();
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
MessageBox.Show("Couldn't save to " + path + Environment.NewLine + ex.ToString(), "Cannot save",
|
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public bool CheckAllowClose()
|
|
{
|
|
m_IgnoreThreadClosed = true;
|
|
|
|
foreach (ListViewItem i in captures.Items)
|
|
{
|
|
var log = i.Tag as CaptureLog;
|
|
|
|
if (log.saved) continue;
|
|
|
|
captures.SelectedItems.Clear();
|
|
Activate();
|
|
captures.Focus();
|
|
i.Selected = true;
|
|
|
|
DialogResult res = MessageBox.Show(String.Format("Save this logfile from {0} at {1}?", log.exe, log.timestamp.ToString("T")),
|
|
"Unsaved log", MessageBoxButtons.YesNoCancel);
|
|
|
|
if (res == DialogResult.Cancel)
|
|
{
|
|
m_IgnoreThreadClosed = false;
|
|
return false;
|
|
}
|
|
|
|
if (res == DialogResult.Yes)
|
|
{
|
|
bool success = SaveCapture(log);
|
|
|
|
if (!success)
|
|
{
|
|
m_IgnoreThreadClosed = false;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_IgnoreThreadClosed = false;
|
|
return true;
|
|
}
|
|
|
|
public void CleanItems()
|
|
{
|
|
foreach (ListViewItem i in captures.Items)
|
|
{
|
|
var log = i.Tag as CaptureLog;
|
|
|
|
if (!log.saved)
|
|
{
|
|
try
|
|
{
|
|
if (log.path == m_Core.LogFileName)
|
|
{
|
|
m_Main.OwnTemporaryLog = true;
|
|
}
|
|
else
|
|
{
|
|
m_Core.Renderer.DeleteCapture(log.path, log.local);
|
|
}
|
|
}
|
|
catch (System.Exception)
|
|
{
|
|
// couldn't delete log - deleted from under us?
|
|
}
|
|
}
|
|
}
|
|
captures.Items.Clear();
|
|
}
|
|
|
|
private void LiveCapture_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
if (CheckAllowClose() == false)
|
|
{
|
|
e.Cancel = true;
|
|
return;
|
|
}
|
|
|
|
KillThread();
|
|
}
|
|
|
|
private void KillThread()
|
|
{
|
|
if (m_ConnectThread.ThreadState != ThreadState.Aborted &&
|
|
m_ConnectThread.ThreadState != ThreadState.Stopped)
|
|
{
|
|
m_Disconnect = true;
|
|
m_ConnectThread.Join();
|
|
}
|
|
}
|
|
|
|
private void LiveCapture_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
m_Main.LiveCaptureClosed(this);
|
|
|
|
captures.LargeImageList.Images.Clear();
|
|
thumbs.Dispose();
|
|
|
|
KillThread();
|
|
CleanItems();
|
|
}
|
|
|
|
private bool CheckAllowDelete()
|
|
{
|
|
bool needcheck = false;
|
|
|
|
bool multiple = captures.SelectedItems.Count > 1;
|
|
|
|
foreach (ListViewItem i in captures.SelectedItems)
|
|
needcheck |= !(i.Tag as CaptureLog).saved;
|
|
|
|
if (!needcheck || captures.SelectedItems.Count == 0)
|
|
return true;
|
|
|
|
Focus();
|
|
|
|
DialogResult res = MessageBox.Show(String.Format("Are you sure you wish to delete {0}?", multiple ? "these logs" : "this log") +
|
|
"\nAny log currently opened will be closed.",
|
|
multiple ? "Unsaved logs" : "Unsaved log", MessageBoxButtons.YesNoCancel);
|
|
|
|
if (res == DialogResult.Cancel || res == DialogResult.No)
|
|
return false;
|
|
|
|
if (res == DialogResult.Yes)
|
|
return true;
|
|
|
|
return true;
|
|
}
|
|
|
|
private void DeleteCaptureUnprompted(ListViewItem item)
|
|
{
|
|
var log = item.Tag as CaptureLog;
|
|
|
|
if (!log.saved)
|
|
{
|
|
if (log.path == m_Core.LogFileName)
|
|
{
|
|
m_Main.OwnTemporaryLog = true;
|
|
m_Main.CloseLogfile();
|
|
}
|
|
|
|
try
|
|
{
|
|
m_Core.Renderer.DeleteCapture(log.path, log.local);
|
|
}
|
|
catch (System.Exception)
|
|
{
|
|
// couldn't delete log - deleted from under us?
|
|
}
|
|
}
|
|
|
|
captures.Items.Remove(item);
|
|
}
|
|
|
|
private void openCapture_Click(object sender, EventArgs e)
|
|
{
|
|
if (captures.SelectedItems.Count == 1)
|
|
OpenCapture(captures.SelectedItems[0].Tag as CaptureLog);
|
|
}
|
|
|
|
private void openNewWindow_Click(object sender, EventArgs e)
|
|
{
|
|
if (captures.SelectedItems.Count == 1)
|
|
{
|
|
var log = captures.SelectedItems[0].Tag as CaptureLog;
|
|
|
|
var temppath = m_Core.TempLogFilename(log.exe);
|
|
|
|
if (!log.local)
|
|
{
|
|
MessageBox.Show("Can't open log in new instance with remote server in use", "Cannot open new instance",
|
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
File.Copy(log.path, temppath);
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
MessageBox.Show("Couldn't save log to temporary location" + Environment.NewLine + ex.ToString(), "Cannot save temporary log",
|
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
var process = new System.Diagnostics.Process();
|
|
process.StartInfo = new System.Diagnostics.ProcessStartInfo(Application.ExecutablePath, String.Format("--tempfile \"{0}\"", temppath));
|
|
process.Start();
|
|
}
|
|
}
|
|
|
|
private void saveCapture_Click(object sender, EventArgs e)
|
|
{
|
|
if (captures.SelectedItems.Count == 1)
|
|
SaveCapture(captures.SelectedItems[0].Tag as CaptureLog);
|
|
}
|
|
|
|
private void deleteCapture_Click(object sender, EventArgs e)
|
|
{
|
|
bool allow = CheckAllowDelete();
|
|
|
|
if (!allow) return;
|
|
|
|
foreach (ListViewItem i in captures.SelectedItems)
|
|
DeleteCaptureUnprompted(i);
|
|
}
|
|
|
|
private void captures_KeyUp(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Delete)
|
|
{
|
|
deleteCapture_Click(sender, null);
|
|
}
|
|
}
|
|
|
|
private void CaptureAdded(uint ID, string executable, string api, byte[] thumbnail, DateTime timestamp, string path, bool local)
|
|
{
|
|
if (thumbnail == null || thumbnail.Length == 0)
|
|
{
|
|
using (Image t = MakeThumb(thumbs.ImageSize, null))
|
|
{
|
|
thumbs.Images.Add(t);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
using (var ms = new MemoryStream(thumbnail))
|
|
using (Image t = MakeThumb(thumbs.ImageSize, ms))
|
|
{
|
|
thumbs.Images.Add(t);
|
|
}
|
|
}
|
|
|
|
CaptureLog log = new CaptureLog();
|
|
log.remoteID = ID;
|
|
log.exe = executable;
|
|
log.api = api;
|
|
log.timestamp = timestamp;
|
|
log.saved = false;
|
|
log.path = path;
|
|
log.local = local;
|
|
|
|
string title = log.exe;
|
|
if (!local)
|
|
title += " (Remote)";
|
|
|
|
var item = new ListViewItem(new string[] { title, log.api, log.timestamp.ToString() }, thumbs.Images.Count - 1);
|
|
item.Tag = log;
|
|
if(!local)
|
|
item.SubItems[0].Font = new Font(item.SubItems[0].Font, FontStyle.Italic);
|
|
|
|
captures.Items.Add(item);
|
|
}
|
|
|
|
private void ConnectionClosed()
|
|
{
|
|
if (m_IgnoreThreadClosed) return;
|
|
|
|
if (captures.Items.Count <= 1)
|
|
{
|
|
if (captures.Items.Count == 1)
|
|
{
|
|
var log = captures.Items[0].Tag as CaptureLog;
|
|
|
|
if (log.opened)
|
|
return;
|
|
|
|
OpenCapture(log);
|
|
if (!log.saved)
|
|
{
|
|
log.saved = true;
|
|
m_Main.OwnTemporaryLog = true;
|
|
}
|
|
}
|
|
|
|
// auto-close and load log if we got a capture. If we
|
|
// don't haveany captures but DO have child processes,
|
|
// then don't close just yet.
|
|
if(captures.Items.Count == 1 || m_Children.Count == 0)
|
|
Close();
|
|
|
|
// if we have no captures and only one child, close and
|
|
// open up a connection to it (similar to behaviour with
|
|
// only one capture
|
|
if (captures.Items.Count == 0 && m_Children.Count == 1)
|
|
{
|
|
uint ident = m_Children[0].ident;
|
|
var live = new LiveCapture(m_Core, m_Host, ident, m_Main);
|
|
m_Main.ShowLiveCapture(live);
|
|
Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void triggerCapture_Click(object sender, EventArgs e)
|
|
{
|
|
m_CaptureNumFrames = (int)numFrames.Value;
|
|
if (captureDelay.Value == 0)
|
|
{
|
|
m_TriggerCapture = true;
|
|
}
|
|
else
|
|
{
|
|
m_CaptureCounter = (int)captureDelay.Value;
|
|
captureCountdown.Enabled = true;
|
|
triggerCapture.Enabled = false;
|
|
triggerCapture.Text = String.Format("Triggering in {0}s", m_CaptureCounter);
|
|
}
|
|
}
|
|
|
|
private void queueCap_Click(object sender, EventArgs e)
|
|
{
|
|
m_CaptureFrameNum = (int)captureFrame.Value;
|
|
m_QueueCapture = true;
|
|
}
|
|
|
|
private void captureCountdown_Tick(object sender, EventArgs e)
|
|
{
|
|
m_CaptureCounter--;
|
|
|
|
if (m_CaptureCounter == 0)
|
|
{
|
|
m_TriggerCapture = true;
|
|
captureCountdown.Enabled = false;
|
|
triggerCapture.Enabled = true;
|
|
triggerCapture.Text = "Trigger Capture";
|
|
}
|
|
else
|
|
{
|
|
triggerCapture.Text = String.Format("Triggering in {0}s", m_CaptureCounter);
|
|
}
|
|
}
|
|
|
|
private void childUpdateTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
// remove any stale processes
|
|
for (int i = 0; i < m_Children.Count; i++)
|
|
{
|
|
try
|
|
{
|
|
// if this throws an exception the process no longer exists so we'll remove it
|
|
Process.GetProcessById(m_Children[i].PID);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
if (m_Children[i].added)
|
|
childProcesses.Items.RemoveByKey(m_Children[i].PID.ToString());
|
|
|
|
// process expired/doesn't exist anymore
|
|
m_Children.RemoveAt(i);
|
|
|
|
// don't increment i, check the next element at i (if we weren't at the end
|
|
i--;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < m_Children.Count; i++)
|
|
{
|
|
if (!m_Children[i].added)
|
|
{
|
|
string text = String.Format("{0} [PID {1}]", m_Children[i].name, m_Children[i].PID);
|
|
|
|
m_Children[i].added = true;
|
|
childProcesses.Items.Add(m_Children[i].PID.ToString(), text, 0).Tag = m_Children[i].ident;
|
|
}
|
|
}
|
|
|
|
if (m_Children.Count > 0)
|
|
{
|
|
childProcessLabel.Visible = childProcesses.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
childProcessLabel.Visible = childProcesses.Visible = false;
|
|
}
|
|
}
|
|
|
|
private void childProcesses_MouseDoubleClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (childProcesses.SelectedItems.Count == 1 && childProcesses.SelectedItems[0].Tag is uint)
|
|
{
|
|
uint ident = (uint)childProcesses.SelectedItems[0].Tag;
|
|
var live = new LiveCapture(m_Core, m_Host, ident, m_Main);
|
|
m_Main.ShowLiveCapture(live);
|
|
}
|
|
}
|
|
}
|
|
}
|