How to create hex editor inside of winforms app - c#

I'm still confused whats better to use, datagridview or Be.HexEditor,
I am pretty sure I'll be able to do it with datagridview, but I like be.hex more, especially speed, UI etc...
But I tried to understand the code of be.hex, and I can't figure out how does it work, and also is it possible to show values from bytes arrays to the HexBox(not only from opening .bin files). it also uses dynamicFileByteProvider, and there is no info on the net about this class.
dynamicFileByteProvider = new DynamicFileByteProvider(fileName);
dynamicFileByteProvider.Changed += new EventHandler(byteProvider_Changed);
dynamicFileByteProvider.LengthChanged += new EventHandler(byteProvider_LengthChanged);
my app will open 1024 bytes files max, and also it will read bytes from comm port

I've tinkered a bit with this. What I did was
1) put an invisible picture box as control placeholder on the form, here named ph1
2) configure the HexBox control in Form_Load()
private HexBox hexBox;
private void Form1_Load(object sender, EventArgs e)
{
hexBox = new HexBox()
{
Top = ph1.Top,
Width = ph1.Width,
Height = ph1.Height,
Left = ph1.Left,
Visible = true,
UseFixedBytesPerLine = true,
BytesPerLine = 16,
ColumnInfoVisible = true,
LineInfoVisible = true,
StringViewVisible = true,
VScrollBarVisible = true
};
this.Controls.Add(hexBox);
this.Controls.Remove(ph1);
}
3) Load the actual file in DragDrop event
var filePath = ((string[])(e.Data.GetData(DataFormats.FileDrop)))[0];
var source = new FileByteProvider(filePath);
hexBox.ByteProvider = source;
hexBox.Refresh();
Example after drag/drop of a docx file onto the form:
Edit: if you wish to provide some self-generated array of bytes, it is as simple as this:
byte[] byteArr = {0xaa, 0x3f, 0x4b};
hexBox.ByteProvider = new DynamicByteProvider(byteArr);
Edit 2: To save the contents of the hex box:
I am sure there is some better way to do this. What I found for now is to simply add a handler in the hex box definition block:
hexBox.CopiedHex += HexBox_CopiedHex;
Have some kind of "save" button with such a code:
private void button1_Click(object sender, EventArgs e)
{
hexBox.SelectAll();
hexBox.CopyHex();
hexBox.SelectionLength = 0;
}
And such an event handler:
private void HexBox_CopiedHex(object sender, EventArgs e)
{
var hex = Clipboard.GetText();
var hexHex = hex.Split(' ');
var hexArr = new byte[hexHex.Length];
for (var i = 0; i < hexHex.Length; i++)
{
hexArr[i] = byte.Parse(hexHex[i], NumberStyles.AllowHexSpecifier);
}
File.WriteAllBytes(#"C:\00_Work\test.bin", hexArr);
}

To show byte[] in hexbox use new DynamicByteProvider(byte[]
To get modified byte[] from hexbox
use DynamicByteProvider.Bytes.ToArray()

Related

How to create many series

Create an object in the class "Series ema = new Series("ema");"
With the button "indicator_Click" download modal dialog.
In the window using the "ComboBox" select options: dig.type, dig.period.
Series ema = new Series("ema");
**********************************************
private void indicator_Click(object sender, EventArgs e)
{
ModalDialogBox dig = new ModalDialogBox();
{
if (dig.ShowDialog() == DialogResult.OK)
{
string formulaName = dig.type;
FinancialFormula formula = (FinancialFormula)Enum.Parse(typeof(FinancialFormula), formulaName, true);
chart1.Series.Add(ema);
chart1.DataManipulator.FinancialFormula(formula, dig.period, "price", "ema");
chart1.Series["ema"].Color = Color.Red;
chart1.Series["ema"].ChartType = SeriesChartType.Line;
chart1.Series["ema"].BorderWidth = 2;
chart1.Series["ema"].ShadowOffset = 1;
}
}
}
Next, if the indicator is not needed, delete it.
private void delete_Click(object sender, EventArgs e)
{
chart1.Series.Remove(ema);
}
I need to be able to add a second, third indicator.
If I try to add a series of the second indicator, an error occurs because the indicator already exists.
You can of course create multiple objects in a class:
Series ema1 = new Series("ema1");
Series ema2 = new Series("ema2");
Series ema3 = new Series("ema3");
but I do not like this method, because I do not know in advance how many indicators will be needed

Moving the mouse according to the given coordinates

what I want is, after recording the mouse movement and saving the coordinates/ indexes/ position, I will have to load the mouse coordinates and make the mouse move according to the loaded coordinates
i don't have code to show you because am stuck at this point
' private void button3_Click_1(object sender, EventArgs e)
{
StreamWriter writer;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
string[] cvsArray = new string[10000];
saveFileDialog1.Filter = "All files (*.All)|*.All|All files (*.*)|*.*";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
writer = File.CreateText(saveFileDialog1.FileName);
// if ((myStream = saveFileDialog1.OpenFile()) != null)
//{
for (int i = 0; i < cvsArray.Length; i++)
{
string text = richTextBox1.Text;
writer.WriteLine(text);
}
// Code to write the stream goes here.
writer.Close();
//}
}
}
private void button11_Click(object sender, EventArgs e)
{
StreamReader reader;
string Line;
string[] cvsArray;
string position;
//set the filter to dialog control
openFileDialog1.Filter = FILTER;
//check if the user selected the right file
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
//open the selected file
reader = File.OpenText(openFileDialog1.FileName);
//Read the entireline form the file
Line = reader.ReadLine();
//read while it is still not the end of the file
while (!reader.EndOfStream)
{
Line = reader.ReadLine();
//Splite the line using array
cvsArray = Line.Split(':');
position = cvsArray[0];
//position = cvsArray[1];
listBox1.Items.Add(position);
}
}
}'
This is a quick and rather dirty solution:
Let's start with a few varibles:
List<Point> points = null;
Timer tt = null;
int index = 0;
Now a button to start the recoding; it initializes a List<Point> to collect the positions and creates and starts a Timer along with lambda code to do the recoding in the Timer.Tick event:
private void btn_Record_Click(object sender, EventArgs e)
{
points = new List<Point>();
index = 0;
tt = new Timer()
{ Interval = 50, Enabled = true };
tt.Tick += (ss, ee) =>
{
if (!points.Any() || points.Last() != Control.MousePosition)
points.Add(Control.MousePosition);
};
}
Next a button to stop recording:
private void btn_Stop_Click(object sender, EventArgs e)
{
if (tt!=null) tt.Stop();
}
Finally the replay button; it uses an index to loop over the the points collection in a new Timer.Tick code but using the same timer:
private void btn_Replay_Click(object sender, EventArgs e)
{
index = 0;
tt = new Timer() { Interval = 50, Enabled = true };
tt.Tick += (ss, ee) =>
{
if (index < points.Count)
{ System.Windows.Forms.Cursor.Position = points[index++]; }
else tt.Stop();
}
A few notes:
As asked in the question this will record and reply the Mmouse coodinates. It will do so in fixed intervals, so playback will look very similar to the original movements; in fact it is so hard to tell apart that I added a slowmo button with a longer interval to demonstrate.. (But the gif got too large)
The code will record the mouse positions in screen coordinates and should capture them wherever it goes, not only inside your application. See how VS is activating the code loupe!
It will not record any other mouse events, like up, down, click, doubleclick or wheel. For those you would need a global mouse hook for capturing and some external calls for replaying.
For including other mouse events you would also need a different and extended data structure; and you would also have to go from a timer-driven model to a mouse event driven one.
The example uses buttons to start and stop. Of course the movenments to and from those buttons get included in the recorded list of positions. Instead one could use a timed start, which would start recording after a few seconds and stop recording after a few seconds of inactivity..
There are various ways you can save and load the points; the simplest one is to serialize to xml; using a string path = #"..." it could look as simple as this:
private void btn_save_Click(object sender, EventArgs e)
{
if (points == null) points = new List<Point>();
XmlSerializer xs = new XmlSerializer((points).GetType());
using (TextReader tr = new StreamReader(path))
{
points = (List<Point>)xs.Deserialize(tr);
tr.Close();
}
}
private void btn_load_Click(object sender, EventArgs e)
{
XmlSerializer xs = new XmlSerializer((points).GetType());
using (TextWriter tw = new StreamWriter(path))
{
xs.Serialize(tw, points);
tw.Close();
}
}
Other ways would be using a binary formatter or a custom conversion routine. Xml is relatively stable.
Here is a short clip:

Call a method inside an event handler function

I'm trying to implement an application in C# which generates me a QR Code. I've managed to do this, but I don't know how to call CreateQRImage(string inputData) inside the genButton_Click(object sender, EventArgs e).
I inside the windows form I have a textbox and a button, and I think that the function CreateQRImage must be called with the name of the textbox
Here is the code:
private void genButton_Click(object sender, EventArgs e)
{
}
public void CreateQRImage(string inputData)
{
if (inputData.Trim() == String.Empty)
{
System.Windows.Forms.MessageBox.Show("Data must not be empty.");
}
BarcodeWriter qrcoder = new ZXing.BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.QrCode.QrCodeEncodingOptions
{
ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H,
Height = 250,
Width = 250
}
};
string tempFileName = System.IO.Path.GetTempPath() + inputData + ".png";
Image image;
String data = inputData;
var result = qrcoder.Write(inputData);
image = new Bitmap(result);
image.Save(tempFileName);
System.Diagnostics.Process.Start(tempFileName);
}
This should do the trick:
private void genButton_Click(object sender, EventArgs e)
{
// Assuming your text box name. Also assuming UI disables button until text is entered.
this.CreateQRImage(myTextBox.Text);
}

Using text from dynamically created TextBoxes

I've got a question regarding textboxes in C#. I've made a button that will create textboxes when clicked:
private void helloButton_Click(object sender, EventArgs e)
{
TextBox txtRun = new TextBox();
TextBox txtRun2 = new TextBox();
txtRun2.Name = "txtDynamic2" + c++;
txtRun.Name = "txtDynamic" + c++;
txtRun.Location = new System.Drawing.Point(40, 50 + (20 * c));
txtRun2.Location = new System.Drawing.Point(250, 50 + (20 * c));
txtRun2.ReadOnly = true;
txtRun.Size = new System.Drawing.Size(200, 25);
txtRun2.Size = new System.Drawing.Size(200, 25);
this.Controls.Add(txtRun);
this.Controls.Add(txtRun2);
}
How can I pull the text which the user types into these newly generated textboxes to use it as arguments for a different function (which will be called by a different button)? I'm quite new at this and could use the help.
Thanks in advance.
var matches = this.Controls.Find("txtDynamic2", true);
TextBox tx2 = matches[0] as TextBox;
string yourtext = tx2.Text;
This will return an array of controls by the name txtDynamic2, in your case the first one would be the control you are looking for unless you create more controls having the same name.
This will allow you to fully access the textbox if you found it.
var text = (TextBox)this.Controls.Find("txtDynamic2", true)[0];
If you'd like to use the instantiated textboxes in other methods then you can achieve that by either passing them to the method, or storing them as members of your class.
Example of storing them in your class below.
public class YourForm
{
private TextBox txtRun;
private TextBox txtRun2;
private void helloButton_Click(object sender, EventArgs e)
{
txtRun = new TextBox();
txtRun2 = new TextBox();
// removed less interesting initialization for readability
this.Controls.Add(txtRun);
this.Controls.Add(txtRun2);
}
public void DoStuffWithTextBoxes()
{
if (txtRun != null && txtRun2 != null)
{
// Retrieve text value and pass the values to another method
SomeOtherMagicMethod(txtRun.Text, txtRun2.Text);
}
}
private void SomeOtherMagicMethod(string txtRunText, string txtRun2Text)
{
// Do more magic
}
}
You can do it very easily:
//get the text from a control named "txtDynamic"
string text = this.Controls["txtDynamic"].Text;
Just remember to make sure that your controls have unique Name property, otherwise You'll get the text from the first control that's found with the specified name.

How to get only NEW text from TextBox?

private void tbLog_TextChanged(object sender, TextChangedEventArgs e)
{
//Get only NEW text added to Log
}
/*
LOG
old message...
old message...
old message...
old message...
NEW message...
NEW message...
NEW message...
NEW message...
NEW message...
*/
How to I get only NEW text from the TextBox?
Perhaps you should be using the TextChangedEventArgs.Changes property:
var fullText = tbLog.Text;
if (e.Changes.Any())
{
var additions = e.Changes.Where(tc => tc.AddedLength > 0);
var newTexts = additions.Select(tc => fullText.Substring(tc.Offset, tc.AddedLength));
// TODO: Do stuff with the new pieces of text
}
Something like this?
private string old_text = "";
private void tbLog_TextChanged(object sender, TextChangedEventArgs e)
{
if(old_text != tbLog.Text)
{
writeLog(tbLog.Text);
old_text = tbLog.Text;
}
}
For desktop WPF text boxes, you should be able to use TextChangedEventArgs.Changes to enumerate the changes. Note a single event may contain several changes.
The TextChange class has Offset, AddedLength, and RemovedLength properties that give you the exact range of characters that were changed.
private void textTx1Asc_TextChanged(object sender, EventArgs e)
{
string s;
//get only the new chars
s = textTx1Asc.Text;
s = s.Remove(0, prev_len);
//update prev_len for next time
prev_len = textTx1Asc.TextLength;
//s contains only the new characters, process here
}

Categories

Resources