#region Top Part
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// PrintForm1.cs 17-Dec-17 v1.1.4.27
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// Run This On a Worker Thread
// so it's independent of Smesa
// as an App within an App.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// Brought to PrintBlaster NameSpace
// v2.3.7.28 21-Jan-2018 (Beginning)
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// v2.5.9.31 09-Feb-2018 Isolated &
// Ready for Further Development!
// v3.2.3.47 05-Apr-2018 ^ Beginning
// v3.2.4.47 09 Near Total Concept!
// v3.3.4.48 18-Apr-2018
// v4.3.5.49 22-Apr-2018 Integrated.
// v4.3.5.51 Mmf2-Data Mechanisms.
// v4.3.5.52 9-May-18 Up/Down Move.
// v4.4.5.53 Mapped in to Lock Out.
// (c) John P. Edwards 20-May-2018
// Revision4.5.7.54 FileWatcher impl.
// v4.5.7.57nobadges Brings in MCD stuff.
// and MyToolbox 09-Jun-18
// v4.5.7.57nobagiac 22-Jun-2018 Rescued!
// v4.5.7.58 Abouts Perfected 02-Jul
// v4.5.7.58nobloop 03-Jul-2018
// Integrating with MyCustomDialogs
// v4.5.7.58nobluff 05-Jul-2018 Viewer,
// About, and Skip Togglerized. 4 Kinds!
// v4.5.8.60 18-Jul-18 Shared Info!
// v4.5.8.60 23-Jul-18 FULLY TESTED! 26-Jul
// v4.5.8.61 04-Aug Integration w/ Shared.sme
// v4.5.9.63 Omega Plan
// v4.5.9.63 15-Aug-2018 Complete & TestsWell.
// v4.5.9.64 21-Aug Fixed and finalized.
// v4.6.9.65 29-Aug-2018 Viewer Rapid-Fire!
// v4.6.9.67 06-Sep-2018 Shared, Skip, Testing
// v4.6.9.69 17- " " Perfected PathPb & FSWs!
// v4.7.0.70 18-" " Assy Thread Safe & IO Safe.
// v4.7.0.71 19-Sep About Colors.
// v4.7.0.72 21-"" "" Added Invert List Tool.
// v4.7.1.73 23-Sep Perfected OpenFolder mods.
// v4.7.1.75 28 " " PageSetup1 & 2 ProtoTypes.
// v4.7.1.76 30-Sep MCT.SaveList & GetList mods.
// v4.8.0.76 30-Sep MCT.SaveList & GetList mods.
// v4.8.1.77 03-Oct Proves New Design Model!
// v4.8.1.78 08-Oct Sort List Option.
// v4.8.2.81 20-Oct Switch to Editor.
// v4.8.3.84 06-Nov-2018 Myriad Mods.
// v4.9.4.90 27-Nov-2018 ReadRemovals() and
// GetSelectedIndex() integration completed.
// NOTE: See calls to GetSelectedIndex();
// v4.9.4.92 04-Dec-2018 Killed.sme Mods.
// v4.9.5.94 13-Dec-2018 ME2PB Killed 1 & 2
// v4.9.5.96 31-Dec-2018 Integrate Prototype.
// v5.0.6.03 23-Mar-2019 Alphabetize overlook
// v5.1.6.07 19-Apr-2019 SetPaths Assurances.
// v5.1.7.09 24-Apr-2019 Debugged & Tested.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
// Custom References:
using MyCustomLibrary;
using MyEditor;
// Class Aliases:
using MCD = MyCustomLibrary.Dialogs;
using MCT = MyCustomLibrary.MyToolbox;
using SNM = MyCustomLibrary.SafeNativeMethods;
// Property Aliases:
using PFR = PrintBlaster.Properties.Resources;
using PFS = PrintBlaster.Properties.Settings;
namespace PrintBlaster
{
public partial class PrintForm1 : Form
{
// See PrintFormHeader.cs for Globals:
/// 1st Instance only
/// Class Constructor. (1 of 2)
/// Ist Instance here, and 2nd
/// Instance is the only other
/// Class Constructor. v4.5.8.61
/// (c) 02-Aug-2018 by -JpE-
/// For G.A.S.I.T.
///
public PrintForm1() // Class Constructor 1 of 2
{
WaitCursor();
Args = Environment
.GetCommandLineArgs();
Detect();
SetPaths();
ClearMarkers();
if (Which > 0 && Which < 7)
{ // When Sent by MyEditor
// & a 1st instance.
Switch1(Which);
Close();
}
else // Normal App Start.
InitializeComponent();
}
#endregion Top Part
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Paths and Mmf Magic
// First Instance Only.
private void SetPaths()
{
// Assure variable integrity.
var root = MCT.GetRoot;
if (string.IsNullOrEmpty(root)
|| !Directory.Exists(root)) throw
new ArgumentException(PFR.Err7);
var myAp = root + PFR.PrintApp;
// Ascertain the PrintBlaster Path.
PbPath = File.Exists(myAp)
? myAp : Args[0];
if (File.Exists(PbPath))
WriteShared.AppRoot =
Path.GetDirectoryName(PbPath);
// Ascertain "MyEditor.exe" Path.
GetEdPath();
GetMappedPathAndWrapUp(root);
if (!string.IsNullOrEmpty(PbPath)
&& File.Exists(PbPath))
Args[0] = PbPath;
}
private void
GetMappedPathAndWrapUp(string root)
{
var file = root + PFR.MMF1;
// Ascertain the Editor.sme Path.
if (File.Exists(file))// ^ (MMF1)
PFS.Default.PathEditor = file;
else GetEditorPath();
// do it ^ old school otherwise!
PFS.Default.PathSetup =
root + PFR.PageSetup;
PFS.Default.PathForm =
root + PFR.Form;
PFS.Default.Save();
Data = GetData2();
WriteSetupPath();
}
// First Instance Only.
// Get "Editor.sme" Path from file.
private void GetEditorPath()
{
var docu = MCT.GetDocFolder;
var path = docu + PFR.EditorFile;
if (File.Exists(path))
{
path = ReadPath(path);// reused var
if (!string.IsNullOrEmpty(path)
&& File.Exists(path))
PFS.Default.PathEditor = path;
else GetOldSchool();
}
else GetOldSchool();
}
// First Instance Only. Last Try to
// Get "Editor.sme" Path another way.
private void GetOldSchool()
{
string answ = "", fl = PFR.MMF1;
var dir = Path
.GetDirectoryName(PbPath);
if (!string.IsNullOrEmpty(dir)
&& Directory.Exists(dir)
&& File.Exists(dir+fl))
answ = dir+fl;
dir = Path.GetDirectoryName(EdPath);
if (string.IsNullOrEmpty(answ))
if (!string.IsNullOrEmpty(dir)
&& Directory.Exists(dir)
&& File.Exists(dir+fl))
answ = dir+fl;
dir = Path.GetDirectoryName(
PFS.Default.PathEditor);
if (string.IsNullOrEmpty(answ))
if (!string.IsNullOrEmpty(dir)
&& Directory.Exists(dir)
&& File.Exists(dir+fl))
answ = dir+fl;
if (!string.IsNullOrEmpty(answ)
&& File.Exists(answ))
PFS.Default.PathEditor = answ;
}
#region Data Doc
// Args[0] = path // (PB\Bin\Release)
// Args[1] = size // (0 for autosize)
// Args[2] = offset // (0 for autosize)
// Args[3] = 1; // Flip Byte Switch ON!
// Args[4] = true; // read sent msg.
// Args[5] = "mmf2";// unique name.
// Args[6] = true; // delete after read.
// Args[7] = view length from offset. (Optional)
// ^ defaults to 0L which goes to the end of size.
#endregion
// First Instance Only.
public static object[] GetData2()
{
var path = PFS.Default.PathSetup;
return new object[]
{
path, 1, 0, new
Collection {1}, true,
Path.GetFileNameWithoutExtension(
path), true
};
}
// First Instance Only.
private static void WriteSetupPath()
{
if (string.IsNullOrEmpty(
PFS.Default.PathSetup)) throw
new ArgumentException(PFR.Err5);
var path = MCT.GetDocFolder +
PFR.PathSetup;
var file = PFS.Default.PathSetup;
var data = new[]
{
file, "1", "0", "null", "true",
Path.GetFileNameWithoutExtension(
file), "true"
};
File.WriteAllLines(path, data);
File.SetLastAccessTime(
path, DateTime.Now);
}
// First Instance Only.
// Ascertain "MyEditor.exe" Path.
// typical ^v Quickie for All.
// v5.1.6.07 19-Mar-2019
private void GetEdPath()
{
var d = MCT.GetRoot;
var f = d + PFR.EdApp;
// New & Improved Quick Way.
if (!string.IsNullOrEmpty(d)
&& Directory.Exists(d)
&& File.Exists(f)) EdPath = f;
else // else do it the old way.
{ // Note ReUsing Var f
f = MCT.GetDocFolder + PFR.PathMe;
if (File.Exists(f))
EdPath = ReadPath(f);
// try ^ reading it.
// or...
if (string.IsNullOrEmpty(EdPath)
|| !File.Exists(EdPath)
&& (!string.IsNullOrEmpty(Args[0])
&& File.Exists(Args[0])))
EdPath = Args[0];
}
}
public static string ReadPath(string fn)
{
if (string.IsNullOrEmpty(fn)
|| !File.Exists(fn)) return "";
var file = File.ReadAllText(fn);
if (string.IsNullOrEmpty(file)
|| !File.Exists(file)) return "";
return file;
}
#endregion Paths and Mmf Magic
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Load, Watcher, B2F, Closing
private void PrintLoad
(object sender, EventArgs e)
{
Size = PFS.Default.PF_Size;
Location = PFS.Default.PF_Loca;
// v4.9.4.90 27-Nov-2018 -JpE-
ToggleLastAccessSort.Checked =
PFS.Default.SortByAccess;
ToggleSortAlphabetical.Checked =
PFS.Default.SortAlphabet;
// REM: ListBoxLoad Checks Favs.
ListBoxLoad();
RoadKill(); // <-= Hook v4.9.5.95!
BtfWatcher = new FileSystemWatcher();
SetupBtfWatcher();
SkipWatcher = new FileSystemWatcher();
SetupSkipWatcher();
SharedWatcher = new FileSystemWatcher();
SetupSharedWatcher();
KilledWatcher = new FileSystemWatcher();
SetupKilledWatcher();
SkipToggle.Checked = MCT.Skip;
if (ReadSharedData()) GetProperties();
SelectedChanged("PrintLoad", e);
ArrowCursor();
GetFileCount();
listBox1.SelectedIndexChanged +=
SelectedChanged;
TestCodeVisibility();
}
private void TestCodeVisibility()
{
TestCode1.Visible =
TestCode2.Visible =
TestCode3.Visible =
TestCode4.Visible = MCT.Testing;
}
// ReUsed elsewhere now too.
// v4.5.9.63 17-Aug-2018 -JpE-
private void GetProperties()
{
ForeColor = _formFore;
BackColor = _formBack;
listBox1.ForeColor = _foreColor;
listBox1.BackColor = _backColor;
listBox1.Font = _boxFont;
Validate();
}
private void SetupBtfWatcher()
{
BtfWatcher.NotifyFilter =
NotifyFilters.FileName;
BtfWatcher.InternalBufferSize = 8192;
BtfWatcher.EnableRaisingEvents = false;
// Setup File System Watcher:
BtfWatcher.Path = // for Mapped File.
Path.GetDirectoryName(
PFS.Default.PathForm);
BtfWatcher.Filter = Path
.GetFileName(
PFS.Default.PathForm);
// Create Eventhandler...
BtfWatcher.Created += BtfEventHandler;
BtfWatcher.EnableRaisingEvents = true;
}
private void BtfEventHandler(
object sender, FileSystemEventArgs e)
{
#region testcode
//var txt = listBox1.InvokeRequired
// ? "Invoke Required."
// : "Invoke NOT Required!";
//txt = "PrintForm Class " + txt;
//MessageBox.Show(txt); //PFR.BtfText);
#endregion
if (listBox1.InvokeRequired)
Invoke(new Invoker1(
Bring2Front));
else
Bring2Front();
}
// Bring UI window (hWnd) to front
// using SNM.B2F. Ref it.
private void Bring2Front()
{
BtfWatcher.EnableRaisingEvents = false;
SNM.B2F(Process
.GetCurrentProcess()
.MainWindowHandle);
// v Thread Safe / IO Safe.
MemoryMapper.ReadBytes(GetData3());
// ^ Reset trigger by..| effectively
// | deleting it with: data[6] = true;
BtfWatcher.EnableRaisingEvents = true;
}
private static object[] GetData3()
{
var p3 = PFS.Default.PathForm;
#region Release Test Code
//MessageBox.Show(string.Format(
// "p3 is {0}", p3));
#endregion
var nm = Path. // } to simplify.
GetFileNameWithoutExtension(p3);
// Then just return the object array.
return new object[]
{
p3, 1, 0, new Collection {1},
true, nm, true
};
}
private void PrintFormClosing(
object sender, FormClosingEventArgs e)
{
if (MyPrintDoc != null)
MyPrintDoc.Dispose();
PFS.Default.PF_Size = Size;
PFS.Default.PF_Loca = Location;
ListBoxSave();
UpdateFavorites();
PFS.Default.SortByAccess =
ToggleLastAccessSort.Checked;
PFS.Default.SortAlphabet =
ToggleSortAlphabetical.Checked;
PFS.Default.Save();
var fn = WriteShared.AppRoot
+ PFR.PB;
if (File.Exists(fn))
File.Delete(fn);
}
#endregion Load, Watcher, B2F, Closing
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Detect if Smesa sent.
/// Detect Task Selected from Smesa
/// My Editor Project has sent a special
/// request for a particular Form
/// from This Project. PrintForm isn't shown
/// unless it was an actual Run from Smesa Class
/// See Smesa PrintItemHandler in Smesa Options.
///
private void Detect()
{
if (Args.Length < 3) return;
// Which = 0; ^
Which = Args[1].Contains(Key1)
? 7 : Detect(Args);
}
#region Shared IntraProcess
// Critical for both instances. <-=
// Must Be Static & Hard Coded.
// ThreadSafe \ ProcessSafe \ IOSafe
private static int Detect(
IList args)
{
// Print v v Preview is Default.
var item = 1;
PbMutex.WaitOne();
// Defaults to Preview.
var sent = args[1];
// File>>Page Setup
if (sent.Contains("Page")) item = 2;
// File>>Print File or Selection
if (sent.Contains("This")) item = 3;
// File>>Print Font & Color v5.1.7.09
if (sent.Contains("Font")// 24Apr2019
&& sent.Contains("Color"))item = 5;
// Code Set Here. Legend Also.
if (args.Count() > 3) item = 3;
// Batch handler is^above at 3;
#region Release TestCode.
//const string can =
// "Font request made" +
// " it to Detect(IList);";
//if (item.Equals(5))
// MessageBox.Show(can);
#endregion
PbMutex.ReleaseMutex();
return item;
}
#endregion Shared IntraProcess
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
private void Switch1(int which)
{
ArrowCursor();
switch (which)
{
case 1: PrintPreview1();
break;
case 3: PrintThis1();
break;
case 5: FontSelect1();// New v5.1.7
break;
default: PageSetup1();
break;
}
}
private void PrintFormKeyDown(
object sender, KeyEventArgs e)
{
if (e.KeyData.Equals(Keys.Escape))
Close();
}
#endregion Detect if Smesa sent.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region File Menu Items
private void AddFilesClick(
object sender, EventArgs e)
{
// Easy using existing code to Select files.
Smesa.SetDirectory();
var dir = Directory.GetCurrentDirectory();
var fnm = Smesa.GetDefaultFileName(0);
if (listBox1.SelectedItems.Count > 0)
{
fnm = listBox1.SelectedItems[0].ToString();
dir = Path.GetDirectoryName(fnm);
// Justin Case
if ( string.IsNullOrEmpty(fnm)
|| string.IsNullOrEmpty(dir)
|| !File.Exists(fnm)
|| !Directory.Exists(dir))
return;
}
var args = new[]{ fnm };
args = Smesa.FileNameGet(args, dir);
// if viable, add to the top of list.
if (args == null
|| args.Count() == 1
&& args[0] == fnm) return;
foreach (var file in args
.Where(file => !listBox1
.Items.Contains(file)))
listBox1.Items.Insert(0, file);
GetFileCount(); // NOTE: ^ inversion;
UpdateFavorites();
}
private void FontSelectClick(
object sender, EventArgs e)
{ FontSelect1(); }
private void PageSetupClick(
object sender, EventArgs e)
{ PageSetup1(); }
// convert selection / collection
// to Args String Array and let
// PrintPreview(); Handle the rest.
private void PreviewClick(
object sender, EventArgs e)
{
if (listBox1.SelectedItems
.Count < 1) return;
GetArgs(sender);
PrintPreview1();
}
///
/// convert selection / collection
/// to Args String Array and let
/// PrintThis(); Handle the rest.
///
///
///
private void PrintThisClick(
object sender, EventArgs e)
{
if (listBox1.SelectedItems
.Count < 1) return;
GetArgs(sender);
PrintThis1();
}
private void GetArgs(object sender)
{
var l = listBox1
.SelectedItems.Count + 2;
Args = new string[l];
Args[0] = PbPath;
Args[1] = sender.ToString();
for (var i = 2; i < l; ++i) Args[i] =
listBox1.SelectedItems[
i - 2].ToString();
}
private void ExitClick(
object sender, EventArgs e)
{
if(MCD.YesNoDialog(PFR.Exit)) Close();
}
#endregion File Menu Items
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Edit Menu Items
#region NOTE:
// Several of the Main Menu Items are simply linked to the equivalent Context Menu Item. (And vise-versa)
#endregion
private void SelectAllClick(
object sender, EventArgs e)
{
var c = listBox1.Items.Count;
listBox1.ClearSelected();
for (var i = c-1; i > -1; --i)
listBox1.SetSelected(i, true);
}
// Send this selection to
// (or open) Smesa via CommandLine.
// uses existing 2nd Instance & MMF.
// a simple call to
// MCL.MyToolbox.RunApp(); But...
// ...make sure the args are right.
private void AddToEditorClick(
object sender, EventArgs e)
{
if (string.IsNullOrEmpty(EdPath)
|| !File.Exists(EdPath)
|| !MCD.YesNoDialog(PFR.Edit))
return;
// else 1 extra for EdPath itself.
var count = 1 + listBox1
.SelectedItems.Count;
var args = new string[count];
var i = 0;
args[i++] = EdPath;
for ( ; i < count; ++i)
args[i] = listBox1
.SelectedItems[i - 1]
.ToString();
WaitCursor();
MCT.RunApp(args);
Thread.Sleep(1000);
ArrowCursor();
}
/// Flip byte 8190 to 1
/// in Watched File:
/// "Editor.sme" on AppRoot dir
/// v4.8.2.81 23-Oct-2018
///
///
///
private void Switch2Editor(
object sender, EventArgs e)
{
if (!MCD.YesNoDialog(
PFR.GoEdit, "", 1)) return;
if (MyEditorIsRunning())
{
var f = Path.GetDirectoryName(
EdPath) + PFR.MMF1;
var n = Path
.GetFileNameWithoutExtension(f);
var args = new object[]
{
f, Smesa.EditorSize,
Smesa.Offset1 -2,
new Collection {1},
false, n, false
};
if (!MemoryMapper
.ReverseWriteBytes(args))
MessageBox.Show(PFR.Failed);
}
else Process.Start(EdPath);
}
private bool MyEditorIsRunning()
{
return File.Exists(
Path.GetDirectoryName(
EdPath) + PFR.ME);
}
#endregion Edit Menu Items
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region View Menu Items
// See PrintForm3.cs
// v4.7.1.73 23-Sep-2018
private void OpenFolderClick(
object sender, EventArgs e)
{
var list = listBox1.SelectedItems;
if (list.Count < 1) return;
if (!MCD.YesNoDialog(PFR.Open)) return;
var launched = new Collection();
var was = MCT.Skip;
MCT.Skip = true;
foreach (var dir in list.Cast()
.Select(Path.GetDirectoryName).Where(
dir => !string.IsNullOrEmpty(
dir) && Directory.Exists(dir)
&& !launched.Contains(dir)))
{ launched.Add(dir);
MCT.OpenFolder(dir); }
MCT.Skip = was;
}
private void ShowInViewerClick(
object sender, EventArgs e)
{
if (listBox1.SelectedItems.Count < 1
|| string.IsNullOrEmpty(PbPath)) return;
if ( !MCD.YesNoDialog(PFR.Show)) return;
var dir = Path.GetDirectoryName(PbPath);
if (string.IsNullOrEmpty(dir)
|| !Directory.Exists(dir)) return;
var app = dir + PFR.Sme;
if (!File.Exists(app)) return;
// And Send to ShowMeForm
SharedWatcher // v4.8.3.84
.EnableRaisingEvents = false;
foreach (string file in
listBox1.SelectedItems)
{ MCT.RunApp(file, string.Format(
"Viewing: {0}", file), app);
Thread.Sleep(800); }
SharedWatcher // ^ wait a sec.
.EnableRaisingEvents = true;
}
#endregion View Menu Items
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Tools Menu Items
private void AboutClick(
object sender, EventArgs e)
{
var args = new[]
{
AssemblyTitle,
AssemblyProduct,
AssemblyVersion,
AssemblyCopyright,
AssemblyCompany,
PFR.About
};
var colors = new Collection
{
listBox1.ForeColor,
listBox1.BackColor,
ForeColor, BackColor
};
MCD.AboutApp(colors, args);
}
/// Uses a dummy file-exists
/// "flag" as a Universal Boolean:
/// AppRoot + "skip.sme" esta nada.
/// Exists == true : Not == false;
///
///
///
private void ToggleSkip(
object sender, EventArgs e)
{
var skip = MCT.Skip;
if (!MCD.YesNoDialog(PFR.Toggle))
SkipToggle.Checked = skip;
else // Test code that...
{ // ...became a Feature!
Thread.Sleep(250);
MCT.Skip = !skip;
#region NOTE:
// ^ This tiny lil guy triggers
// the PBF2.SkipEventHandler and thus
// Resets the SkipToggle.Checked value.
// Even if Smesa.Preferences made the change!
#endregion
}
}
private void InvertListClick(
object sender, EventArgs e)
{
if (!MCD.YesNoDialog(
PFR.Invert)) return;
var slct = listBox1.SelectedItems;
var temp = new Collection