diff --git a/Form1.Designer.cs b/Form1.Designer.cs
new file mode 100644
index 0000000..16995d3
--- /dev/null
+++ b/Form1.Designer.cs
@@ -0,0 +1,658 @@
+namespace MemTestHelper
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.tab_control = new System.Windows.Forms.TabControl();
+ this.tab_main = new System.Windows.Forms.TabPage();
+ this.btn_hide = new System.Windows.Forms.Button();
+ this.lst_coverage = new System.Windows.Forms.ListView();
+ this.hdr_no = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.hdr_coverage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.hdr_errors = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.lbl_speed_value = new System.Windows.Forms.Label();
+ this.lbl_speed = new System.Windows.Forms.Label();
+ this.lbl_estimated_time = new System.Windows.Forms.Label();
+ this.lbl_estimated = new System.Windows.Forms.Label();
+ this.lbl_elapsed_time = new System.Windows.Forms.Label();
+ this.lbl_elapsed = new System.Windows.Forms.Label();
+ this.btn_show = new System.Windows.Forms.Button();
+ this.btn_stop = new System.Windows.Forms.Button();
+ this.btn_run = new System.Windows.Forms.Button();
+ this.cbo_threads = new System.Windows.Forms.ComboBox();
+ this.lbl_num_threads = new System.Windows.Forms.Label();
+ this.txt_ram = new System.Windows.Forms.TextBox();
+ this.btn_auto_ram = new System.Windows.Forms.Button();
+ this.tab_settings = new System.Windows.Forms.TabPage();
+ this.chk_start_min = new System.Windows.Forms.CheckBox();
+ this.chk_stop_at_total = new System.Windows.Forms.CheckBox();
+ this.chk_stop_on_err = new System.Windows.Forms.CheckBox();
+ this.txt_stop_at = new System.Windows.Forms.TextBox();
+ this.chk_stop_at = new System.Windows.Forms.CheckBox();
+ this.cbo_rows = new System.Windows.Forms.ComboBox();
+ this.btn_center = new System.Windows.Forms.Button();
+ this.ud_y_offset = new System.Windows.Forms.NumericUpDown();
+ this.lbl_y_offset = new System.Windows.Forms.Label();
+ this.ud_y_spacing = new System.Windows.Forms.NumericUpDown();
+ this.lbl_rows = new System.Windows.Forms.Label();
+ this.lbl_y_spacing = new System.Windows.Forms.Label();
+ this.ud_x_spacing = new System.Windows.Forms.NumericUpDown();
+ this.lbl_x_spacing = new System.Windows.Forms.Label();
+ this.ud_x_offset = new System.Windows.Forms.NumericUpDown();
+ this.lbl_x_offset = new System.Windows.Forms.Label();
+ this.tab_about = new System.Windows.Forms.TabPage();
+ this.txt_discord = new System.Windows.Forms.TextBox();
+ this.lbl_discord = new System.Windows.Forms.Label();
+ this.lbl_version = new System.Windows.Forms.Label();
+ this.lbl_win_height = new System.Windows.Forms.Label();
+ this.ud_win_height = new System.Windows.Forms.NumericUpDown();
+ this.tab_control.SuspendLayout();
+ this.tab_main.SuspendLayout();
+ this.tab_settings.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_y_offset)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_y_spacing)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_x_spacing)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_x_offset)).BeginInit();
+ this.tab_about.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_win_height)).BeginInit();
+ this.SuspendLayout();
+ //
+ // tab_control
+ //
+ this.tab_control.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)));
+ this.tab_control.Controls.Add(this.tab_main);
+ this.tab_control.Controls.Add(this.tab_settings);
+ this.tab_control.Controls.Add(this.tab_about);
+ this.tab_control.Location = new System.Drawing.Point(0, 0);
+ this.tab_control.Margin = new System.Windows.Forms.Padding(0);
+ this.tab_control.Name = "tab_control";
+ this.tab_control.SelectedIndex = 0;
+ this.tab_control.Size = new System.Drawing.Size(227, 382);
+ this.tab_control.TabIndex = 0;
+ //
+ // tab_main
+ //
+ this.tab_main.Controls.Add(this.btn_hide);
+ this.tab_main.Controls.Add(this.lst_coverage);
+ this.tab_main.Controls.Add(this.lbl_speed_value);
+ this.tab_main.Controls.Add(this.lbl_speed);
+ this.tab_main.Controls.Add(this.lbl_estimated_time);
+ this.tab_main.Controls.Add(this.lbl_estimated);
+ this.tab_main.Controls.Add(this.lbl_elapsed_time);
+ this.tab_main.Controls.Add(this.lbl_elapsed);
+ this.tab_main.Controls.Add(this.btn_show);
+ this.tab_main.Controls.Add(this.btn_stop);
+ this.tab_main.Controls.Add(this.btn_run);
+ this.tab_main.Controls.Add(this.cbo_threads);
+ this.tab_main.Controls.Add(this.lbl_num_threads);
+ this.tab_main.Controls.Add(this.txt_ram);
+ this.tab_main.Controls.Add(this.btn_auto_ram);
+ this.tab_main.Location = new System.Drawing.Point(4, 22);
+ this.tab_main.Margin = new System.Windows.Forms.Padding(0);
+ this.tab_main.Name = "tab_main";
+ this.tab_main.Size = new System.Drawing.Size(219, 356);
+ this.tab_main.TabIndex = 0;
+ this.tab_main.Text = "Main";
+ this.tab_main.UseVisualStyleBackColor = true;
+ //
+ // btn_hide
+ //
+ this.btn_hide.Location = new System.Drawing.Point(112, 83);
+ this.btn_hide.Name = "btn_hide";
+ this.btn_hide.Size = new System.Drawing.Size(85, 20);
+ this.btn_hide.TabIndex = 8;
+ this.btn_hide.Text = "Hide";
+ this.btn_hide.UseVisualStyleBackColor = true;
+ this.btn_hide.Click += new System.EventHandler(this.btn_hide_Click);
+ //
+ // lst_coverage
+ //
+ this.lst_coverage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)));
+ this.lst_coverage.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.hdr_no,
+ this.hdr_coverage,
+ this.hdr_errors});
+ this.lst_coverage.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lst_coverage.Location = new System.Drawing.Point(4, 154);
+ this.lst_coverage.Name = "lst_coverage";
+ this.lst_coverage.Size = new System.Drawing.Size(210, 199);
+ this.lst_coverage.TabIndex = 7;
+ this.lst_coverage.UseCompatibleStateImageBehavior = false;
+ this.lst_coverage.View = System.Windows.Forms.View.Details;
+ //
+ // hdr_no
+ //
+ this.hdr_no.Text = "No.";
+ this.hdr_no.Width = 31;
+ //
+ // hdr_coverage
+ //
+ this.hdr_coverage.Text = "Coverage (%)";
+ this.hdr_coverage.Width = 86;
+ //
+ // hdr_errors
+ //
+ this.hdr_errors.Text = "Errors";
+ this.hdr_errors.Width = 70;
+ //
+ // lbl_speed_value
+ //
+ this.lbl_speed_value.AutoSize = true;
+ this.lbl_speed_value.Location = new System.Drawing.Point(81, 137);
+ this.lbl_speed_value.Name = "lbl_speed_value";
+ this.lbl_speed_value.Size = new System.Drawing.Size(54, 13);
+ this.lbl_speed_value.TabIndex = 6;
+ this.lbl_speed_value.Text = "0.00MB/s";
+ //
+ // lbl_speed
+ //
+ this.lbl_speed.AutoSize = true;
+ this.lbl_speed.Location = new System.Drawing.Point(21, 137);
+ this.lbl_speed.Name = "lbl_speed";
+ this.lbl_speed.Size = new System.Drawing.Size(41, 13);
+ this.lbl_speed.TabIndex = 6;
+ this.lbl_speed.Text = "Speed:";
+ //
+ // lbl_estimated_time
+ //
+ this.lbl_estimated_time.AutoSize = true;
+ this.lbl_estimated_time.Location = new System.Drawing.Point(81, 122);
+ this.lbl_estimated_time.Name = "lbl_estimated_time";
+ this.lbl_estimated_time.Size = new System.Drawing.Size(62, 13);
+ this.lbl_estimated_time.TabIndex = 6;
+ this.lbl_estimated_time.Text = "00h00m00s";
+ //
+ // lbl_estimated
+ //
+ this.lbl_estimated.AutoSize = true;
+ this.lbl_estimated.Location = new System.Drawing.Point(21, 122);
+ this.lbl_estimated.Name = "lbl_estimated";
+ this.lbl_estimated.Size = new System.Drawing.Size(56, 13);
+ this.lbl_estimated.TabIndex = 6;
+ this.lbl_estimated.Text = "Estimated:";
+ //
+ // lbl_elapsed_time
+ //
+ this.lbl_elapsed_time.AutoSize = true;
+ this.lbl_elapsed_time.Location = new System.Drawing.Point(81, 107);
+ this.lbl_elapsed_time.Name = "lbl_elapsed_time";
+ this.lbl_elapsed_time.Size = new System.Drawing.Size(62, 13);
+ this.lbl_elapsed_time.TabIndex = 6;
+ this.lbl_elapsed_time.Text = "00h00m00s";
+ //
+ // lbl_elapsed
+ //
+ this.lbl_elapsed.AutoSize = true;
+ this.lbl_elapsed.Location = new System.Drawing.Point(21, 107);
+ this.lbl_elapsed.Name = "lbl_elapsed";
+ this.lbl_elapsed.Size = new System.Drawing.Size(48, 13);
+ this.lbl_elapsed.TabIndex = 6;
+ this.lbl_elapsed.Text = "Elapsed:";
+ //
+ // btn_show
+ //
+ this.btn_show.Location = new System.Drawing.Point(21, 83);
+ this.btn_show.Name = "btn_show";
+ this.btn_show.Size = new System.Drawing.Size(85, 20);
+ this.btn_show.TabIndex = 5;
+ this.btn_show.Text = "Show";
+ this.btn_show.UseVisualStyleBackColor = true;
+ this.btn_show.Click += new System.EventHandler(this.btn_show_Click);
+ //
+ // btn_stop
+ //
+ this.btn_stop.Enabled = false;
+ this.btn_stop.Location = new System.Drawing.Point(112, 53);
+ this.btn_stop.Name = "btn_stop";
+ this.btn_stop.Size = new System.Drawing.Size(85, 25);
+ this.btn_stop.TabIndex = 5;
+ this.btn_stop.Text = "Stop";
+ this.btn_stop.UseVisualStyleBackColor = true;
+ this.btn_stop.Click += new System.EventHandler(this.btn_stop_Click);
+ //
+ // btn_run
+ //
+ this.btn_run.Location = new System.Drawing.Point(21, 53);
+ this.btn_run.Name = "btn_run";
+ this.btn_run.Size = new System.Drawing.Size(85, 25);
+ this.btn_run.TabIndex = 5;
+ this.btn_run.Text = "Run";
+ this.btn_run.UseVisualStyleBackColor = true;
+ this.btn_run.Click += new System.EventHandler(this.btn_run_Click);
+ //
+ // cbo_threads
+ //
+ this.cbo_threads.DropDownHeight = 100;
+ this.cbo_threads.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbo_threads.FormattingEnabled = true;
+ this.cbo_threads.IntegralHeight = false;
+ this.cbo_threads.Location = new System.Drawing.Point(146, 28);
+ this.cbo_threads.Name = "cbo_threads";
+ this.cbo_threads.Size = new System.Drawing.Size(50, 21);
+ this.cbo_threads.TabIndex = 4;
+ this.cbo_threads.SelectionChangeCommitted += new System.EventHandler(this.cbo_threads_SelectionChangeCommitted);
+ //
+ // lbl_num_threads
+ //
+ this.lbl_num_threads.AutoSize = true;
+ this.lbl_num_threads.Location = new System.Drawing.Point(21, 33);
+ this.lbl_num_threads.Name = "lbl_num_threads";
+ this.lbl_num_threads.Size = new System.Drawing.Size(97, 13);
+ this.lbl_num_threads.TabIndex = 3;
+ this.lbl_num_threads.Text = "Number of threads:";
+ //
+ // txt_ram
+ //
+ this.txt_ram.Location = new System.Drawing.Point(146, 3);
+ this.txt_ram.Name = "txt_ram";
+ this.txt_ram.Size = new System.Drawing.Size(50, 20);
+ this.txt_ram.TabIndex = 2;
+ //
+ // btn_auto_ram
+ //
+ this.btn_auto_ram.Location = new System.Drawing.Point(21, 3);
+ this.btn_auto_ram.Margin = new System.Windows.Forms.Padding(0);
+ this.btn_auto_ram.Name = "btn_auto_ram";
+ this.btn_auto_ram.Size = new System.Drawing.Size(100, 20);
+ this.btn_auto_ram.TabIndex = 1;
+ this.btn_auto_ram.Text = "RAM to test (MB):";
+ this.btn_auto_ram.UseVisualStyleBackColor = true;
+ this.btn_auto_ram.Click += new System.EventHandler(this.btn_auto_ram_Click);
+ //
+ // tab_settings
+ //
+ this.tab_settings.Controls.Add(this.chk_start_min);
+ this.tab_settings.Controls.Add(this.chk_stop_at_total);
+ this.tab_settings.Controls.Add(this.chk_stop_on_err);
+ this.tab_settings.Controls.Add(this.txt_stop_at);
+ this.tab_settings.Controls.Add(this.chk_stop_at);
+ this.tab_settings.Controls.Add(this.cbo_rows);
+ this.tab_settings.Controls.Add(this.btn_center);
+ this.tab_settings.Controls.Add(this.ud_win_height);
+ this.tab_settings.Controls.Add(this.ud_y_offset);
+ this.tab_settings.Controls.Add(this.lbl_win_height);
+ this.tab_settings.Controls.Add(this.lbl_y_offset);
+ this.tab_settings.Controls.Add(this.ud_y_spacing);
+ this.tab_settings.Controls.Add(this.lbl_rows);
+ this.tab_settings.Controls.Add(this.lbl_y_spacing);
+ this.tab_settings.Controls.Add(this.ud_x_spacing);
+ this.tab_settings.Controls.Add(this.lbl_x_spacing);
+ this.tab_settings.Controls.Add(this.ud_x_offset);
+ this.tab_settings.Controls.Add(this.lbl_x_offset);
+ this.tab_settings.Location = new System.Drawing.Point(4, 22);
+ this.tab_settings.Margin = new System.Windows.Forms.Padding(0);
+ this.tab_settings.Name = "tab_settings";
+ this.tab_settings.Size = new System.Drawing.Size(219, 356);
+ this.tab_settings.TabIndex = 1;
+ this.tab_settings.Text = "Settings";
+ this.tab_settings.UseVisualStyleBackColor = true;
+ //
+ // chk_start_min
+ //
+ this.chk_start_min.AutoSize = true;
+ this.chk_start_min.Checked = true;
+ this.chk_start_min.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chk_start_min.Location = new System.Drawing.Point(21, 181);
+ this.chk_start_min.Name = "chk_start_min";
+ this.chk_start_min.Size = new System.Drawing.Size(96, 17);
+ this.chk_start_min.TabIndex = 8;
+ this.chk_start_min.Text = "Start minimised";
+ this.chk_start_min.UseVisualStyleBackColor = true;
+ //
+ // chk_stop_at_total
+ //
+ this.chk_stop_at_total.AutoSize = true;
+ this.chk_stop_at_total.Enabled = false;
+ this.chk_stop_at_total.Location = new System.Drawing.Point(156, 134);
+ this.chk_stop_at_total.Name = "chk_stop_at_total";
+ this.chk_stop_at_total.Size = new System.Drawing.Size(50, 17);
+ this.chk_stop_at_total.TabIndex = 6;
+ this.chk_stop_at_total.Text = "Total";
+ this.chk_stop_at_total.UseVisualStyleBackColor = true;
+ //
+ // chk_stop_on_err
+ //
+ this.chk_stop_on_err.AutoSize = true;
+ this.chk_stop_on_err.Checked = true;
+ this.chk_stop_on_err.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chk_stop_on_err.Location = new System.Drawing.Point(21, 157);
+ this.chk_stop_on_err.Name = "chk_stop_on_err";
+ this.chk_stop_on_err.Size = new System.Drawing.Size(87, 17);
+ this.chk_stop_on_err.TabIndex = 4;
+ this.chk_stop_on_err.Text = "Stop on error";
+ this.chk_stop_on_err.UseVisualStyleBackColor = true;
+ //
+ // txt_stop_at
+ //
+ this.txt_stop_at.Enabled = false;
+ this.txt_stop_at.Location = new System.Drawing.Point(100, 131);
+ this.txt_stop_at.Name = "txt_stop_at";
+ this.txt_stop_at.Size = new System.Drawing.Size(50, 20);
+ this.txt_stop_at.TabIndex = 5;
+ //
+ // chk_stop_at
+ //
+ this.chk_stop_at.AutoSize = true;
+ this.chk_stop_at.Location = new System.Drawing.Point(21, 134);
+ this.chk_stop_at.Name = "chk_stop_at";
+ this.chk_stop_at.Size = new System.Drawing.Size(80, 17);
+ this.chk_stop_at.TabIndex = 4;
+ this.chk_stop_at.Text = "Stop at (%):";
+ this.chk_stop_at.UseVisualStyleBackColor = true;
+ this.chk_stop_at.CheckedChanged += new System.EventHandler(this.chk_stop_at_CheckedChanged);
+ //
+ // cbo_rows
+ //
+ this.cbo_rows.DropDownHeight = 100;
+ this.cbo_rows.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbo_rows.FormattingEnabled = true;
+ this.cbo_rows.IntegralHeight = false;
+ this.cbo_rows.Location = new System.Drawing.Point(106, 104);
+ this.cbo_rows.Name = "cbo_rows";
+ this.cbo_rows.Size = new System.Drawing.Size(50, 21);
+ this.cbo_rows.TabIndex = 3;
+ this.cbo_rows.SelectionChangeCommitted += new System.EventHandler(this.cbo_rows_SelectionChangeCommitted);
+ //
+ // btn_center
+ //
+ this.btn_center.Location = new System.Drawing.Point(121, 13);
+ this.btn_center.Name = "btn_center";
+ this.btn_center.Size = new System.Drawing.Size(80, 25);
+ this.btn_center.TabIndex = 2;
+ this.btn_center.Text = "Center";
+ this.btn_center.UseVisualStyleBackColor = true;
+ this.btn_center.Click += new System.EventHandler(this.btn_center_Click);
+ //
+ // ud_y_offset
+ //
+ this.ud_y_offset.Location = new System.Drawing.Point(66, 30);
+ this.ud_y_offset.Maximum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ 0});
+ this.ud_y_offset.Minimum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ -2147483648});
+ this.ud_y_offset.Name = "ud_y_offset";
+ this.ud_y_offset.Size = new System.Drawing.Size(50, 20);
+ this.ud_y_offset.TabIndex = 1;
+ this.ud_y_offset.ValueChanged += new System.EventHandler(this.offset_changed);
+ //
+ // lbl_y_offset
+ //
+ this.lbl_y_offset.AutoSize = true;
+ this.lbl_y_offset.Location = new System.Drawing.Point(21, 33);
+ this.lbl_y_offset.Name = "lbl_y_offset";
+ this.lbl_y_offset.Size = new System.Drawing.Size(46, 13);
+ this.lbl_y_offset.TabIndex = 0;
+ this.lbl_y_offset.Text = "Y offset:";
+ //
+ // ud_y_spacing
+ //
+ this.ud_y_spacing.Location = new System.Drawing.Point(76, 81);
+ this.ud_y_spacing.Maximum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ 0});
+ this.ud_y_spacing.Minimum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ -2147483648});
+ this.ud_y_spacing.Name = "ud_y_spacing";
+ this.ud_y_spacing.Size = new System.Drawing.Size(50, 20);
+ this.ud_y_spacing.TabIndex = 1;
+ this.ud_y_spacing.ValueChanged += new System.EventHandler(this.offset_changed);
+ //
+ // lbl_rows
+ //
+ this.lbl_rows.AutoSize = true;
+ this.lbl_rows.Location = new System.Drawing.Point(21, 109);
+ this.lbl_rows.Name = "lbl_rows";
+ this.lbl_rows.Size = new System.Drawing.Size(84, 13);
+ this.lbl_rows.TabIndex = 0;
+ this.lbl_rows.Text = "Number of rows:";
+ //
+ // lbl_y_spacing
+ //
+ this.lbl_y_spacing.AutoSize = true;
+ this.lbl_y_spacing.Location = new System.Drawing.Point(21, 84);
+ this.lbl_y_spacing.Name = "lbl_y_spacing";
+ this.lbl_y_spacing.Size = new System.Drawing.Size(57, 13);
+ this.lbl_y_spacing.TabIndex = 0;
+ this.lbl_y_spacing.Text = "Y spacing:";
+ //
+ // ud_x_spacing
+ //
+ this.ud_x_spacing.Location = new System.Drawing.Point(76, 56);
+ this.ud_x_spacing.Maximum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ 0});
+ this.ud_x_spacing.Minimum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ -2147483648});
+ this.ud_x_spacing.Name = "ud_x_spacing";
+ this.ud_x_spacing.Size = new System.Drawing.Size(50, 20);
+ this.ud_x_spacing.TabIndex = 1;
+ this.ud_x_spacing.ValueChanged += new System.EventHandler(this.offset_changed);
+ //
+ // lbl_x_spacing
+ //
+ this.lbl_x_spacing.AutoSize = true;
+ this.lbl_x_spacing.Location = new System.Drawing.Point(21, 59);
+ this.lbl_x_spacing.Name = "lbl_x_spacing";
+ this.lbl_x_spacing.Size = new System.Drawing.Size(57, 13);
+ this.lbl_x_spacing.TabIndex = 0;
+ this.lbl_x_spacing.Text = "X spacing:";
+ //
+ // ud_x_offset
+ //
+ this.ud_x_offset.Location = new System.Drawing.Point(66, 5);
+ this.ud_x_offset.Maximum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ 0});
+ this.ud_x_offset.Minimum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ -2147483648});
+ this.ud_x_offset.Name = "ud_x_offset";
+ this.ud_x_offset.Size = new System.Drawing.Size(50, 20);
+ this.ud_x_offset.TabIndex = 1;
+ this.ud_x_offset.ValueChanged += new System.EventHandler(this.offset_changed);
+ //
+ // lbl_x_offset
+ //
+ this.lbl_x_offset.AutoSize = true;
+ this.lbl_x_offset.Location = new System.Drawing.Point(21, 8);
+ this.lbl_x_offset.Name = "lbl_x_offset";
+ this.lbl_x_offset.Size = new System.Drawing.Size(46, 13);
+ this.lbl_x_offset.TabIndex = 0;
+ this.lbl_x_offset.Text = "X offset:";
+ //
+ // tab_about
+ //
+ this.tab_about.Controls.Add(this.txt_discord);
+ this.tab_about.Controls.Add(this.lbl_discord);
+ this.tab_about.Controls.Add(this.lbl_version);
+ this.tab_about.Location = new System.Drawing.Point(4, 22);
+ this.tab_about.Margin = new System.Windows.Forms.Padding(0);
+ this.tab_about.Name = "tab_about";
+ this.tab_about.Size = new System.Drawing.Size(219, 356);
+ this.tab_about.TabIndex = 2;
+ this.tab_about.Text = "About";
+ this.tab_about.UseVisualStyleBackColor = true;
+ //
+ // txt_discord
+ //
+ this.txt_discord.Location = new System.Drawing.Point(100, 145);
+ this.txt_discord.Name = "txt_discord";
+ this.txt_discord.ReadOnly = true;
+ this.txt_discord.Size = new System.Drawing.Size(80, 20);
+ this.txt_discord.TabIndex = 1;
+ this.txt_discord.Text = "∫ntegral#7834";
+ //
+ // lbl_discord
+ //
+ this.lbl_discord.AutoSize = true;
+ this.lbl_discord.Location = new System.Drawing.Point(50, 150);
+ this.lbl_discord.Name = "lbl_discord";
+ this.lbl_discord.Size = new System.Drawing.Size(46, 13);
+ this.lbl_discord.TabIndex = 0;
+ this.lbl_discord.Text = "Discord:";
+ //
+ // lbl_version
+ //
+ this.lbl_version.AutoSize = true;
+ this.lbl_version.Location = new System.Drawing.Point(84, 120);
+ this.lbl_version.Name = "lbl_version";
+ this.lbl_version.Size = new System.Drawing.Size(69, 13);
+ this.lbl_version.TabIndex = 0;
+ this.lbl_version.Text = "Version 1.9.2";
+ //
+ // lbl_win_height
+ //
+ this.lbl_win_height.AutoSize = true;
+ this.lbl_win_height.Location = new System.Drawing.Point(18, 204);
+ this.lbl_win_height.Name = "lbl_win_height";
+ this.lbl_win_height.Size = new System.Drawing.Size(81, 13);
+ this.lbl_win_height.TabIndex = 0;
+ this.lbl_win_height.Text = "Window height:";
+ //
+ // ud_win_height
+ //
+ this.ud_win_height.Location = new System.Drawing.Point(100, 202);
+ this.ud_win_height.Maximum = new decimal(new int[] {
+ 1000,
+ 0,
+ 0,
+ 0});
+ this.ud_win_height.Minimum = new decimal(new int[] {
+ 420,
+ 0,
+ 0,
+ 0});
+ this.ud_win_height.Name = "ud_win_height";
+ this.ud_win_height.Size = new System.Drawing.Size(50, 20);
+ this.ud_win_height.TabIndex = 1;
+ this.ud_win_height.Value = new decimal(new int[] {
+ 420,
+ 0,
+ 0,
+ 0});
+ this.ud_win_height.ValueChanged += new System.EventHandler(this.ud_win_height_ValueChanged);
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(226, 381);
+ this.Controls.Add(this.tab_control);
+ this.MaximizeBox = false;
+ this.MaximumSize = new System.Drawing.Size(242, 1000);
+ this.MinimumSize = new System.Drawing.Size(242, 0);
+ this.Name = "Form1";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "MemTestHelper";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.Resize += new System.EventHandler(this.Form1_Resize);
+ this.tab_control.ResumeLayout(false);
+ this.tab_main.ResumeLayout(false);
+ this.tab_main.PerformLayout();
+ this.tab_settings.ResumeLayout(false);
+ this.tab_settings.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_y_offset)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_y_spacing)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_x_spacing)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_x_offset)).EndInit();
+ this.tab_about.ResumeLayout(false);
+ this.tab_about.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.ud_win_height)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TabControl tab_control;
+ private System.Windows.Forms.TabPage tab_main;
+ private System.Windows.Forms.TabPage tab_settings;
+ private System.Windows.Forms.TabPage tab_about;
+ private System.Windows.Forms.Button btn_auto_ram;
+ private System.Windows.Forms.TextBox txt_ram;
+ private System.Windows.Forms.Label lbl_num_threads;
+ private System.Windows.Forms.ComboBox cbo_threads;
+ private System.Windows.Forms.Button btn_show;
+ private System.Windows.Forms.Button btn_stop;
+ private System.Windows.Forms.Button btn_run;
+ private System.Windows.Forms.Label lbl_speed_value;
+ private System.Windows.Forms.Label lbl_speed;
+ private System.Windows.Forms.Label lbl_estimated_time;
+ private System.Windows.Forms.Label lbl_estimated;
+ private System.Windows.Forms.Label lbl_elapsed_time;
+ private System.Windows.Forms.Label lbl_elapsed;
+ private System.Windows.Forms.ListView lst_coverage;
+ private System.Windows.Forms.ColumnHeader hdr_no;
+ private System.Windows.Forms.ColumnHeader hdr_coverage;
+ private System.Windows.Forms.ColumnHeader hdr_errors;
+ private System.Windows.Forms.Label lbl_x_offset;
+ private System.Windows.Forms.NumericUpDown ud_x_offset;
+ private System.Windows.Forms.NumericUpDown ud_y_offset;
+ private System.Windows.Forms.Label lbl_y_offset;
+ private System.Windows.Forms.NumericUpDown ud_y_spacing;
+ private System.Windows.Forms.Label lbl_y_spacing;
+ private System.Windows.Forms.NumericUpDown ud_x_spacing;
+ private System.Windows.Forms.Label lbl_x_spacing;
+ private System.Windows.Forms.Button btn_center;
+ private System.Windows.Forms.ComboBox cbo_rows;
+ private System.Windows.Forms.Label lbl_rows;
+ private System.Windows.Forms.CheckBox chk_stop_at_total;
+ private System.Windows.Forms.TextBox txt_stop_at;
+ private System.Windows.Forms.CheckBox chk_stop_at;
+ private System.Windows.Forms.CheckBox chk_stop_on_err;
+ private System.Windows.Forms.TextBox txt_discord;
+ private System.Windows.Forms.Label lbl_discord;
+ private System.Windows.Forms.Label lbl_version;
+ private System.Windows.Forms.CheckBox chk_start_min;
+ private System.Windows.Forms.Button btn_hide;
+ private System.Windows.Forms.NumericUpDown ud_win_height;
+ private System.Windows.Forms.Label lbl_win_height;
+ }
+}
+
diff --git a/Form1.cs b/Form1.cs
new file mode 100644
index 0000000..842e1b1
--- /dev/null
+++ b/Form1.cs
@@ -0,0 +1,1016 @@
+using Microsoft.VisualBasic.Devices;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Forms;
+
+namespace MemTestHelper
+{
+ public partial class Form1 : Form
+ {
+ public Form1()
+ {
+ InitializeComponent();
+
+ init_cbo_threads();
+ init_lst_coverage();
+ init_cbo_rows();
+ center_xy_offsets();
+
+ bw_coverage = new BackgroundWorker();
+ bw_coverage.WorkerSupportsCancellation = true;
+ bw_coverage.DoWork += new DoWorkEventHandler(delegate (object o, DoWorkEventArgs args)
+ {
+ BackgroundWorker worker = o as BackgroundWorker;
+
+ while (!worker.CancellationPending)
+ {
+ update_coverage_info();
+ Thread.Sleep(UPDATE_INTERVAL);
+ }
+
+ args.Cancel = true;
+ });
+ bw_coverage.RunWorkerCompleted +=
+ new RunWorkerCompletedEventHandler(delegate (object o, RunWorkerCompletedEventArgs args)
+ {
+ // wait for all MemTests to stop completely
+ while (is_any_memtest_stopping())
+ Thread.Sleep(100);
+
+ update_coverage_info(false);
+ });
+
+ timer = new System.Timers.Timer(1000);
+ timer.Elapsed += new System.Timers.ElapsedEventHandler(delegate
+ (object sender, System.Timers.ElapsedEventArgs e)
+ {
+ Invoke(new MethodInvoker(delegate
+ {
+ int threads = (int)cbo_threads.SelectedItem;
+ var elapsed = e.SignalTime - start_time;
+
+ lbl_elapsed_time.Text = String.Format("{0:00}h{1:00}m{2:00}s",
+ (int)(elapsed.TotalHours),
+ elapsed.Minutes,
+ elapsed.Seconds);
+
+ double total_coverage = 0;
+ for (int i = 1; i <= threads; i++)
+ {
+ var info = get_coverage_info(memtest_states[i - 1].proc.MainWindowHandle);
+ if (info == null) continue;
+
+ total_coverage += info.Item1;
+ }
+
+ if (total_coverage == 0) return;
+
+ double diff = elapsed.TotalMilliseconds,
+ est = 0;
+ int cov = 0;
+ // use user input coverage %
+ if (chk_stop_at.Checked)
+ {
+ cov = Convert.ToInt32(txt_stop_at.Text);
+
+ if (chk_stop_at_total.Checked)
+ est = (diff / total_coverage * cov) - diff;
+ else
+ {
+ // calculate average coverage and use that to estimate
+ double avg = total_coverage / threads;
+ est = (diff / avg * cov) - diff;
+ }
+ }
+ else
+ {
+ // calculate average coverage and use that to estimate
+ double avg = total_coverage / threads;
+ // round up to next multiple of 100
+ cov = ((int)(avg / 100) + 1) * 100;
+ est = (diff / avg * cov) - diff;
+ }
+
+ TimeSpan est_time = TimeSpan.FromMilliseconds(est);
+ lbl_estimated_time.Text = String.Format("{0:00}h{1:00}m{2:00}s to {3}%",
+ (int)(est_time.TotalHours),
+ est_time.Minutes,
+ est_time.Seconds,
+ cov);
+
+ int ram = Convert.ToInt32(txt_ram.Text);
+ double speed = (total_coverage / 100) * ram / (diff / 1000);
+ lbl_speed_value.Text = $"{speed:f2}MB/s";
+ }));
+ });
+ }
+
+ // event handling
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ load_cfg();
+ update_form_height();
+ update_lst_coverage_items();
+ }
+
+ private void Form1_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ close_memtests();
+ save_cfg();
+ }
+
+ private void Form1_Resize(object sender, EventArgs e)
+ {
+ int threads = (int)cbo_threads.SelectedItem;
+ switch (WindowState)
+ {
+ // minimise MemTest instances
+ case FormWindowState.Minimized:
+ run_in_background(new MethodInvoker(delegate
+ {
+ for (int i = 0; i < threads; i++)
+ {
+ if (memtest_states[i] != null)
+ {
+ IntPtr hwnd = memtest_states[i].proc.MainWindowHandle;
+
+ if (!IsIconic(hwnd))
+ ShowWindow(hwnd, SW_MINIMIZE);
+
+ Thread.Sleep(10);
+ }
+ }
+ }));
+ break;
+
+ // restore previous state of MemTest instances
+ case FormWindowState.Normal:
+ run_in_background(new MethodInvoker(delegate
+ {
+ /*
+ * is_minimised is true when user clicked the hide button
+ * this means that the memtest instances should be kept minimised
+ */
+ if (!is_minimised)
+ {
+ for (int i = 0; i < threads; i++)
+ {
+ if (memtest_states[i] != null)
+ {
+ IntPtr hwnd = memtest_states[i].proc.MainWindowHandle;
+
+ ShowWindow(hwnd, SW_RESTORE);
+
+ Thread.Sleep(10);
+ }
+ }
+
+ // user may have changed offsets while minimised
+ move_memtests();
+
+ // hack to bring form to top
+ TopMost = true;
+ Thread.Sleep(10);
+ TopMost = false;
+ }
+ }));
+ break;
+ }
+ }
+
+ private void btn_auto_ram_Click(object sender, EventArgs e)
+ {
+ UInt64 free = new ComputerInfo().AvailablePhysicalMemory / (1024 * 1024);
+ txt_ram.Text = free.ToString();
+ }
+
+ private void btn_run_Click(object sender, EventArgs e)
+ {
+ if (!File.Exists(MEMTEST_EXE))
+ {
+ MessageBox.Show(MEMTEST_EXE + " not found");
+ return;
+ }
+
+ if (!validate_input()) return;
+
+ btn_auto_ram.Enabled = false;
+ txt_ram.Enabled = false;
+ cbo_threads.Enabled = false;
+ //cbo_rows.Enabled = false;
+ btn_run.Enabled = false;
+ btn_stop.Enabled = true;
+ chk_stop_at.Enabled = false;
+ txt_stop_at.Enabled = false;
+ chk_stop_at_total.Enabled = false;
+ chk_stop_on_err.Enabled = false;
+ chk_start_min.Enabled = false;
+
+ // run in background as start_memtests can block
+ run_in_background(new MethodInvoker(delegate
+ {
+ start_memtests();
+
+ if (!bw_coverage.IsBusy)
+ bw_coverage.RunWorkerAsync();
+ start_time = DateTime.Now;
+ timer.Start();
+
+ Activate();
+ }));
+ }
+
+ private void btn_stop_Click(object sender, EventArgs e)
+ {
+ Parallel.For(0, (int)cbo_threads.SelectedItem, i =>
+ {
+ if (!memtest_states[i].is_finished)
+ ControlClick(memtest_states[i].proc.MainWindowHandle, MEMTEST_BTN_STOP);
+ });
+
+ bw_coverage.CancelAsync();
+ timer.Stop();
+
+ btn_auto_ram.Enabled = true;
+ txt_ram.Enabled = true;
+ cbo_threads.Enabled = true;
+ //cbo_rows.Enabled = true;
+ btn_run.Enabled = true;
+ btn_stop.Enabled = false;
+ chk_stop_at.Enabled = true;
+ if (chk_stop_at.Checked)
+ {
+ txt_stop_at.Enabled = true;
+ chk_stop_at_total.Enabled = true;
+ }
+ chk_stop_on_err.Enabled = true;
+ chk_start_min.Enabled = true;
+
+ // wait for all memtests to fully stop
+ while (is_any_memtest_stopping())
+ Thread.Sleep(100);
+
+ MessageBox.Show("MemTest finished");
+ }
+
+ private void btn_show_Click(object sender, EventArgs e)
+ {
+ // run in background as Thread.Sleep can lockup the GUI
+ int threads = (int)cbo_threads.SelectedItem;
+ run_in_background(new MethodInvoker(delegate
+ {
+ for (int i = 0; i < threads; i++)
+ {
+ if (memtest_states[i] != null)
+ {
+ IntPtr hwnd = memtest_states[i].proc.MainWindowHandle;
+
+ if (IsIconic(hwnd))
+ ShowWindow(hwnd, SW_RESTORE);
+ else
+ SetForegroundWindow(hwnd);
+
+ Thread.Sleep(10);
+ }
+ }
+
+ is_minimised = false;
+
+ // user may have changed offsets while minimised
+ move_memtests();
+
+ Activate();
+ }));
+ }
+
+ private void btn_hide_Click(object sender, EventArgs e)
+ {
+ int threads = (int)cbo_threads.SelectedItem;
+ run_in_background(new MethodInvoker(delegate
+ {
+ for (int i = 0; i < threads; i++)
+ {
+ if (memtest_states[i] != null)
+ {
+ IntPtr hwnd = memtest_states[i].proc.MainWindowHandle;
+
+ if (!IsIconic(hwnd))
+ ShowWindow(hwnd, SW_MINIMIZE);
+
+ Thread.Sleep(10);
+ }
+ }
+
+ is_minimised = true;
+ }));
+ }
+
+ private void offset_changed(object sender, EventArgs e)
+ {
+ run_in_background(new MethodInvoker(delegate { move_memtests(); }));
+ }
+
+ private void btn_center_Click(object sender, EventArgs e)
+ {
+ center_xy_offsets();
+ }
+
+ private void cbo_rows_SelectionChangeCommitted(object sender, EventArgs e)
+ {
+ center_xy_offsets();
+ }
+
+ private void cbo_threads_SelectionChangeCommitted(object sender, EventArgs e)
+ {
+ update_lst_coverage_items();
+
+ cbo_rows.Items.Clear();
+ init_cbo_rows();
+ center_xy_offsets();
+ }
+
+ private void chk_stop_at_CheckedChanged(object sender, EventArgs e)
+ {
+ if (chk_stop_at.Checked)
+ {
+ txt_stop_at.Enabled = true;
+ chk_stop_at_total.Enabled = true;
+ }
+ else
+ {
+ txt_stop_at.Enabled = false;
+ chk_stop_at_total.Enabled = false;
+ }
+ }
+
+ private void ud_win_height_ValueChanged(object sender, EventArgs e)
+ {
+ update_form_height();
+ }
+
+ // helper functions
+
+ // TODO: error checking
+ private bool load_cfg()
+ {
+ string[] valid_keys = { "ram", "threads", "x_offset", "y_offset",
+ "x_spacing", "y_spacing", "rows", "stop_at",
+ "stop_at_value", "stop_at_total", "stop_on_error",
+ "start_min", "win_height" };
+
+ try
+ {
+ string[] lines = File.ReadAllLines(CFG_FILENAME);
+ Dictionary cfg = new Dictionary();
+
+ foreach (string l in lines)
+ {
+ string[] s = l.Split('=');
+ if (s.Length != 2) continue;
+ s[0] = s[0].Trim();
+ s[1] = s[1].Trim();
+
+ if (valid_keys.Contains(s[0]))
+ {
+ if (s[1].Length == 0) continue;
+
+ int v;
+ if (Int32.TryParse(s[1], out v))
+ cfg.Add(s[0], v);
+ else return false;
+ }
+ else return false;
+ }
+
+ foreach (KeyValuePair kv in cfg)
+ {
+ switch (kv.Key)
+ {
+ case "ram":
+ txt_ram.Text = kv.Value.ToString();
+ break;
+ case "threads":
+ cbo_threads.SelectedItem = kv.Value;
+ break;
+
+ case "x_offset":
+ ud_x_offset.Value = kv.Value;
+ break;
+ case "y_offset":
+ ud_y_offset.Value = kv.Value;
+ break;
+
+ case "x_spacing":
+ ud_x_spacing.Value = kv.Value;
+ break;
+ case "y_spacing":
+ ud_y_spacing.Value = kv.Value;
+ break;
+
+ case "stop_at":
+ chk_stop_at.Checked = kv.Value != 0;
+ break;
+ case "stop_at_value":
+ txt_stop_at.Text = kv.Value.ToString();
+ break;
+ case "stop_at_total":
+ chk_stop_at_total.Checked = kv.Value != 0;
+ break;
+
+ case "stop_on_error":
+ chk_stop_on_err.Checked = kv.Value != 0;
+ break;
+
+ case "start_min":
+ chk_start_min.Checked = kv.Value != 0;
+ break;
+
+ case "win_height":
+ ud_win_height.Value = kv.Value;
+ break;
+ }
+ }
+ }
+ catch(FileNotFoundException e)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool save_cfg()
+ {
+ try {
+ var file = new StreamWriter(CFG_FILENAME);
+ List lines = new List();
+
+ lines.Add($"ram = {txt_ram.Text}");
+ lines.Add($"threads = {(int)cbo_threads.SelectedItem}");
+
+ lines.Add($"x_offset = {ud_x_offset.Value}");
+ lines.Add($"y_offset = {ud_y_offset.Value}");
+ lines.Add($"x_spacing = {ud_x_spacing.Value}");
+ lines.Add($"y_spacing = {ud_y_spacing.Value}");
+ lines.Add($"rows = {cbo_rows.SelectedItem}");
+
+ lines.Add(string.Format("stop_at = {0}", chk_stop_at.Checked ? 1 : 0));
+ lines.Add($"stop_at_value = {txt_stop_at.Text}");
+ lines.Add(string.Format("stop_at_total = {0}", chk_stop_at_total.Checked ? 1 : 0));
+ lines.Add(string.Format("stop_on_error = {0}", chk_stop_on_err.Checked ? 1 : 0));
+
+ lines.Add(string.Format("start_min = {0}", chk_start_min.Checked ? 1 : 0));
+
+ lines.Add($"win_height = {ud_win_height.Value}");
+
+ foreach (string l in lines)
+ file.WriteLine(l);
+
+ file.Close();
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private void update_form_height()
+ {
+ Size = new Size(Size.Width, (int)ud_win_height.Value);
+ }
+
+ private bool validate_input()
+ {
+ ComputerInfo ci = new ComputerInfo();
+ UInt64 total_ram = ci.TotalPhysicalMemory / (1024 * 1024),
+ avail_ram = ci.AvailablePhysicalMemory / (1024 * 1024);
+
+ string str_ram = txt_ram.Text;
+ // automatically input available ram if empty
+ if (str_ram.Length == 0)
+ {
+ str_ram = avail_ram.ToString();
+ txt_ram.Text = str_ram;
+ }
+ else
+ {
+ if (!str_ram.All(char.IsDigit))
+ {
+ show_error_msgbox("Amount of RAM must be an integer");
+ return false;
+ }
+ }
+
+ int threads = (int)cbo_threads.SelectedItem,
+ ram = Convert.ToInt32(str_ram);
+ if (ram < threads)
+ {
+ show_error_msgbox($"Amount of RAM must be greater than {threads}");
+ return false;
+ }
+
+ if (ram > MEMTEST_MAX_RAM * threads)
+ {
+ show_error_msgbox(
+ $"Amount of RAM must be at most {MEMTEST_MAX_RAM * threads}\n" +
+ "Try increasing the number of threads\n" +
+ "or reducing amount of RAM"
+ );
+ return false;
+ }
+
+ if ((UInt64)ram > total_ram)
+ {
+ show_error_msgbox($"Amount of RAM exceeds total RAM ({total_ram})");
+ return false;
+ }
+
+ if ((UInt64)ram > avail_ram)
+ {
+ var res = MessageBox.Show(
+ $"Amount of RAM exceeds available RAM ({avail_ram})\n" +
+ "This will cause RAM to be paged to your storage,\n" +
+ "which may make MemTest really slow.\n" +
+ "Continue?",
+ "Warning",
+ MessageBoxButtons.YesNo,
+ MessageBoxIcon.Warning
+ );
+ if (res == DialogResult.No)
+ return false;
+ }
+
+ // validate stop at % and error count
+ if (chk_stop_at.Checked)
+ {
+ string str_stop_at = txt_stop_at.Text;
+
+ if (str_stop_at == "")
+ {
+ show_error_msgbox("Please enter stop at (%)");
+ return false;
+ }
+
+ if (!str_stop_at.All(char.IsDigit))
+ {
+ show_error_msgbox("Stop at (%) must be an integer");
+ return false;
+ }
+
+ int stop_at = Convert.ToInt32(str_stop_at);
+ if (stop_at <= 0)
+ {
+ show_error_msgbox("Stop at (%) must be greater than 0");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void init_lst_coverage()
+ {
+ for (int i = 0; i <= (int)cbo_threads.SelectedItem; i++)
+ {
+ string[] row = { i.ToString(), "-", "-" };
+ // first row is total
+ if (i == 0) row[0] = "T";
+
+ lst_coverage.Items.Add(new ListViewItem(row));
+ }
+ }
+
+ private void update_lst_coverage_items()
+ {
+ int threads = (int)cbo_threads.SelectedItem;
+ var items = lst_coverage.Items;
+ if (threads < items.Count)
+ {
+ for (int i = items.Count - 1; i > threads; i--)
+ items.RemoveAt(i);
+ }
+ else
+ {
+ for (int i = items.Count; i <= threads; i++)
+ {
+ string[] row = { i.ToString(), "-", "-" };
+ lst_coverage.Items.Add(new ListViewItem(row));
+ }
+ }
+ }
+
+ private void init_cbo_threads()
+ {
+ for (int i = 0; i < MAX_THREADS; i++)
+ cbo_threads.Items.Add(i + 1);
+
+ cbo_threads.SelectedItem = NUM_THREADS;
+ }
+
+ private void init_cbo_rows()
+ {
+ int threads = (int)cbo_threads.SelectedItem;
+
+ for (int i = 1; i <= threads; i++)
+ {
+ if (threads % i == 0)
+ cbo_rows.Items.Add(i);
+ }
+
+ cbo_rows.SelectedItem = threads % 2 == 0 ? 2 : 1;
+ }
+
+ void center_xy_offsets()
+ {
+ Rectangle screen = Screen.FromControl(this).Bounds;
+ int rows = (int)cbo_rows.SelectedItem,
+ cols = (int)cbo_threads.SelectedItem / rows,
+ x_offset = (screen.Width - MEMTEST_WIDTH * cols) / 2,
+ y_offset = (screen.Height - MEMTEST_HEIGHT * rows) / 2;
+
+ ud_x_offset.Value = x_offset;
+ ud_y_offset.Value = y_offset;
+ }
+
+ private void start_memtests()
+ {
+ close_all_memtests();
+
+ int threads = (int)cbo_threads.SelectedItem;
+ Parallel.For(0, threads, i =>
+ {
+ MemTestState state = new MemTestState();
+ state.proc = Process.Start(MEMTEST_EXE);
+ state.is_finished = false;
+ memtest_states[i] = state;
+
+ Thread.Sleep(threads * 25);
+
+ IntPtr hwnd = memtest_states[i].proc.MainWindowHandle;
+ double ram = Convert.ToDouble(txt_ram.Text) / threads;
+
+ ControlSetText(hwnd, MEMTEST_EDT_RAM, $"{ram:f2}");
+ ControlSetText(hwnd, MEMTEST_STATIC_FREE_VER, "Modified version by ∫ntegral#7834");
+ ControlClick(hwnd, MEMTEST_BTN_START);
+
+ if (chk_start_min.Checked)
+ ShowWindow(hwnd, SW_MINIMIZE);
+ });
+ }
+
+ private void move_memtests()
+ {
+ int x_offset = (int)ud_x_offset.Value,
+ y_offset = (int)ud_y_offset.Value,
+ x_spacing = (int)ud_x_spacing.Value - 5,
+ y_spacing = (int)ud_y_spacing.Value - 3,
+ rows = (int)cbo_rows.SelectedItem,
+ cols = (int)cbo_threads.SelectedItem / rows;
+
+ Parallel.For(0, (int)cbo_threads.SelectedItem, i =>
+ {
+ MemTestState state = memtest_states[i];
+ if (state == null) return;
+
+ IntPtr hwnd = state.proc.MainWindowHandle;
+ int r = i / cols,
+ c = i % cols,
+ x = c * MEMTEST_WIDTH + c * x_spacing + x_offset,
+ y = r * MEMTEST_HEIGHT + r * y_spacing + y_offset;
+
+ MoveWindow(hwnd, x, y, MEMTEST_WIDTH, MEMTEST_HEIGHT, true);
+ });
+ }
+
+ private void close_memtests()
+ {
+ Parallel.ForEach(memtest_states, s =>
+ {
+ try {
+ if (s != null) s.proc.Kill();
+ }
+ catch (Exception) { }
+ });
+ }
+
+ private void close_all_memtests()
+ {
+ // remove the .exe
+ string name = MEMTEST_EXE.Substring(0, MEMTEST_EXE.Length - 4);
+ var procs = Process.GetProcessesByName(name);
+ Parallel.ForEach(procs, p => { p.Kill(); });
+ }
+
+ // returns (coverage, errors)
+ private Tuple get_coverage_info(IntPtr hwnd)
+ {
+ string str = ControlGetText(hwnd, MEMTEST_STATIC_COVERAGE);
+ if (str == "") return null;
+
+ // Test over. 47.3% Coverage, 0 Errors
+ // ^^^^^^^^^^^^^^^^^^^^^^^^
+ int start = str.IndexOfAny("0123456789".ToCharArray());
+ if (start == -1) return null;
+ str = str.Substring(start);
+
+ // 47.3% Coverage, 0 Errors
+ // ^^^^
+ double coverage = Convert.ToDouble(str.Split("%".ToCharArray())[0]);
+
+ // 47.3% Coverage, 0 Errors
+ // ^^^^^^^^
+ start = str.IndexOf("Coverage, ") + "Coverage, ".Length;
+ str = str.Substring(start);
+ // 0 Errors
+ // ^
+ int errors = Convert.ToInt32(str.Substring(0, str.IndexOf(" Errors")));
+
+ return Tuple.Create(coverage, errors);
+ }
+
+ private void update_coverage_info(bool should_check = true)
+ {
+ lst_coverage.Invoke(new MethodInvoker(delegate
+ {
+ int threads = (int)cbo_threads.SelectedItem;
+ double total_coverage = 0;
+ int total_errors = 0;
+
+ // total is index 0
+ for (int i = 1; i <= threads; i++)
+ {
+ var hwnd = memtest_states[i - 1].proc.MainWindowHandle;
+ var info = get_coverage_info(hwnd);
+ if (info == null) continue;
+ double coverage = info.Item1;
+ int errors = info.Item2;
+
+ lst_coverage.Items[i].SubItems[1].Text = string.Format("{0:f1}", coverage);
+ lst_coverage.Items[i].SubItems[2].Text = errors.ToString();
+
+ if (should_check)
+ {
+ // check coverage %
+ if (chk_stop_at.Checked && !chk_stop_at_total.Checked)
+ {
+ int stop_at = Convert.ToInt32(txt_stop_at.Text);
+ if (coverage > stop_at)
+ {
+ if (!memtest_states[i - 1].is_finished)
+ {
+ ControlClick(memtest_states[i - 1].proc.MainWindowHandle,
+ MEMTEST_BTN_STOP);
+ memtest_states[i - 1].is_finished = true;
+ }
+ }
+ }
+
+ // check error count
+ if (chk_stop_on_err.Checked)
+ {
+ if (errors > 0)
+ {
+ lst_coverage.Items[i].SubItems[1].ForeColor = Color.Red;
+
+ click_btn_stop();
+ }
+ }
+ }
+
+ total_coverage += coverage;
+ total_errors += errors;
+ }
+
+ // update the total coverage and errors
+ lst_coverage.Items[0].SubItems[1].Text = string.Format("{0:f1}", total_coverage);
+ lst_coverage.Items[0].SubItems[2].Text = total_errors.ToString();
+
+ if (should_check)
+ {
+ // check total coverage
+ if (chk_stop_at.Checked && chk_stop_at_total.Checked)
+ {
+ int stop_at = Convert.ToInt32(txt_stop_at.Text);
+ if (total_coverage > stop_at)
+ click_btn_stop();
+ }
+
+ if (is_all_finished())
+ click_btn_stop();
+ }
+ }));
+ }
+
+ /*
+ * MemTest can take a while to stop,
+ * which causes the total to return 0
+ */
+ private bool is_any_memtest_stopping()
+ {
+ for (int i = 0; i < (int)cbo_threads.SelectedItem; i++)
+ {
+ IntPtr hwnd = memtest_states[i].proc.MainWindowHandle;
+ string str = ControlGetText(hwnd, MEMTEST_STATIC_COVERAGE);
+ if (str != "" && str.Contains("Ending")) return true;
+ }
+
+ return false;
+ }
+
+ /*
+ * PerformClick() only works if the button is visible
+ * switch to main tab and PerformClick() then switch
+ * back to the tab that the user was on
+ */
+ private void click_btn_stop()
+ {
+ var curr_tab = tab_control.SelectedTab;
+ if (curr_tab != tab_main)
+ tab_control.SelectedTab = tab_main;
+
+ btn_stop.PerformClick();
+ tab_control.SelectedTab = curr_tab;
+ }
+
+ private void show_error_msgbox(string msg)
+ {
+ MessageBox.Show(
+ msg,
+ "Error",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error
+ );
+ }
+
+ private bool is_all_finished()
+ {
+ for (int i = 0; i < (int)cbo_threads.SelectedItem; i++)
+ {
+ if (!memtest_states[i].is_finished)
+ return false;
+ }
+
+ return true;
+ }
+
+ private void run_in_background(Delegate method)
+ {
+ BackgroundWorker bw = new BackgroundWorker();
+ bw.DoWork += new DoWorkEventHandler(delegate (object s, DoWorkEventArgs args)
+ {
+ Invoke(method);
+ });
+ bw.RunWorkerAsync();
+ }
+
+ /*
+ * class_name should be
+ * tries to split class_name as above
+ * returns (, ) if possible
+ * otherwise, returns null
+ */
+ private Tuple split_class_name(string class_name)
+ {
+ Regex regex = new Regex(@"([a-zA-Z]+)(\d+)");
+ Match match = regex.Match(class_name);
+
+ if (!match.Success) return null;
+
+ return Tuple.Create(
+ match.Groups[1].Value,
+ Convert.ToInt32(match.Groups[2].Value)
+ );
+ }
+
+ /*
+ * class_name should be
+ * where is the name of the class to find
+ * is the nth window with that matches (1 indexed)
+ * e.g. Edit1
+ * returns the handle to the window if found
+ * otherwise, returns IntPtr.Zero
+ */
+ private IntPtr find_window(IntPtr hwnd_parent, string class_name)
+ {
+ if (hwnd_parent == IntPtr.Zero)
+ return IntPtr.Zero;
+
+ var name = split_class_name(class_name);
+ if (name == null) return IntPtr.Zero;
+
+ IntPtr hwnd = IntPtr.Zero;
+ for (int i = 0; i < name.Item2; i++)
+ hwnd = FindWindowEx(hwnd_parent, hwnd, name.Item1, null);
+
+ return hwnd;
+ }
+
+ // emulate AutoIT Control functions
+ private bool ControlClick(IntPtr hwnd_parent, string class_name)
+ {
+ IntPtr hwnd = find_window(hwnd_parent, class_name);
+ if (hwnd == IntPtr.Zero) return false;
+ SendNotifyMessage(hwnd, WM_LBUTTONDOWN, IntPtr.Zero, null);
+ SendNotifyMessage(hwnd, WM_LBUTTONUP, IntPtr.Zero, null);
+ return true;
+ }
+
+ private bool ControlSetText(IntPtr hwnd_parent, string class_name, string text)
+ {
+ IntPtr hwnd = find_window(hwnd_parent, class_name);
+ if (hwnd == IntPtr.Zero) return false;
+ SendMessage(hwnd, WM_SETTEXT, IntPtr.Zero, text);
+ return true;
+ }
+
+ private string ControlGetText(IntPtr hwnd, string class_name)
+ {
+ IntPtr hwnd_control = find_window(hwnd, class_name);
+ if (hwnd_control == IntPtr.Zero) return null;
+ int len = GetWindowTextLength(hwnd_control);
+ StringBuilder str = new StringBuilder(len + 1);
+ GetWindowText(hwnd_control, str, str.Capacity);
+ return str.ToString();
+ }
+
+ [DllImport("user32.dll", SetLastError = true)]
+ internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
+
+ // blocks
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
+
+ // doesn't block
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ static extern bool SendNotifyMessage(IntPtr hWnd, int Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ static extern int GetWindowTextLength(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool SetForegroundWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll", EntryPoint = "ShowWindow", SetLastError = true)]
+ static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+
+ // is minimised
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool IsIconic(IntPtr hWnd);
+
+ public const int WM_SETTEXT = 0xC, WM_LBUTTONDOWN = 0x201, WM_LBUTTONUP = 0x202,
+ SW_SHOW = 5, SW_RESTORE = 9, SW_MINIMIZE = 6;
+
+ private static int NUM_THREADS = Convert.ToInt32(System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS")),
+ MAX_THREADS = NUM_THREADS * 4,
+ UPDATE_INTERVAL = 200; // interval (in ms) for coverage info list
+
+ private const string MEMTEST_EXE = "memtest_6.0_no_nag.exe",
+ MEMTEST_BTN_START = "Button1",
+ MEMTEST_BTN_STOP = "Button2",
+ MEMTEST_EDT_RAM = "Edit1",
+ MEMTEST_STATIC_COVERAGE = "Static1",
+ // If you find this free version useful...
+ MEMTEST_STATIC_FREE_VER = "Static2",
+ CFG_FILENAME = "MemTestHelper.cfg";
+
+ private const int MEMTEST_WIDTH = 217,
+ MEMTEST_HEIGHT = 247,
+ MEMTEST_MAX_RAM = 2048;
+
+ private MemTestState[] memtest_states = new MemTestState[MAX_THREADS];
+ private BackgroundWorker bw_coverage;
+ private DateTime start_time;
+ private System.Timers.Timer timer;
+ private bool is_minimised = true;
+
+ class MemTestState
+ {
+ public Process proc;
+ public bool is_finished;
+ }
+ }
+}
diff --git a/Form1.resx b/Form1.resx
new file mode 100644
index 0000000..29dcb1b
--- /dev/null
+++ b/Form1.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file