//txtMessage is the RichTextBox control in question,
//When we hit the close button, we hide the RichTextBox control that should be displayed at startup, and show the powershellInteractiveControl:
private void btnClose_Click(object sender, EventArgs e) {
m_powershellInteractiveControl1.Visible = true;
txtMessage.Visible = false;
btnClose.Visible = false;
}
//When the powershellInteractiveControl sets visible to false, we set visible of txtMessage to true:
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {
m_powershellInteractiveControl1.Visible = visibleState;
txtMessage.Visible = !visibleState;
btnClose.Visible = !visibleState;
};
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {
txtMessage.Visible = !visibleState;
btnClose.Visible = !visibleState;
};
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {
m_powershellInteractiveControl1.Visible = visibleState;
txtMessage.Visible = !visibleState;
btnClose.Visible = !visibleState;
};
public event Action<bool> ControlVisibleChangeEvent = (bool visibleState) => { };
This is a event that is subscribed to by the creator of the object that this event is a property of. You can see above that at instantiaton of the object, a default empty delegate is assigned as a subscription. This is to ensure that the ControlVisibleChangeEvent never is null, and thus when it is called, I do not have to check if it is null or not.private void btnClose_Click(object sender, EventArgs e) {
//Invert the visible property:
this.Visible = !this.Visible;
//pass the status to all subscribers:
ControlVisibleChangeEvent(this.Visible);
}
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {
txtMessage.Visible = !visibleState;
btnClose.Visible = !visibleState;
};
private void btnClose_Click(object sender, EventArgs e) {
//Invert the visible property:
this.Visible = !this.Visible;
//pass the status to all subscribers:
ControlVisibleChangeEvent(this.Visible); <<<-------------------- HERE
}
public static class RichTextBoxExtensions {
public static void AppendText(this RichTextBox box, string text, Color color) {
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
It is used by a object that gets instantiated twice, once for the RichTextBox Control (txtMessage) that disappears, and once for a RichTextBox Control that acts as a console in the powershellInteractiveContrforeach (char c in outText) {
if (TheTextBox.InvokeRequired) {
// It's on a different thread, so use Invoke.
lock(m_LockObject) {
PrintTextCallback ourDelegate = new PrintTextCallback(printText);
TheTextBox.Invoke(ourDelegate, new object[] { c, TheTextBox, TextColor });
}
}
else {
lock (m_LockObject) {
// It's on the same thread, no need for Invoke
TheTextBox.AppendText(c.ToString(), TextColor); //Here is the extension method usage
}
}
Thread.Sleep(PrintDelay);
}
private static void printText(Char c, RichTextBox theTextbox, Color printColor) {
theTextbox.AppendText(c.ToString(), printColor);
if (c.Equals('\n')) {
theTextbox.SelectionStart = theTextbox.TextLength;
theTextbox.ScrollToCaret();
}
}
public static class RichTextBoxExtensions {
private static object m_lock = new object();
public static void AppendText(this RichTextBox box, string text, Color color) {
if(box.InvokeRequired) {
lock(m_lock) {
//Nothing here, code still breaks
}
}
else {
lock (m_lock) {
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
}