In Visual Studio, create an app to upload a file and delete specific lines after pressing a button.
You can build a simple app in Visual Studio that lets a user upload a file, process it, and remove specific lines when a button is clicked. The easiest way is to create a Windows Forms App (C#).
Here's a clean, working approach 👇
________________________________________
🧱 1. Create the Project
1. Open Visual Studio
2. Click Create new project
3. Choose Windows Forms App (.NET)
4. Name it (e.g., FileLineEditor)
________________________________________
🎨 2. Design the UI
Drag these controls onto the form:
• Button → btnUpload (Text: "Upload File")
• Button → btnProcess (Text: "Remove Lines")
• TextBox → txtLinesToRemove
(Placeholder: e.g., 1,3,5)
• OpenFileDialog → openFileDialog1
________________________________________
⚙️ 3. Code Logic
📂 Upload File
Double-click the Upload button and add:
string filePath = "";
private void btnUpload_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog1.FileName;
MessageBox.Show("File loaded: " + filePath);
}
}
________________________________________
✂️ Remove Specific Lines
Double-click the Process button:
private void btnProcess_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(filePath))
{
MessageBox.Show("Please upload a file first.");
return;
}
// Get lines to remove (e.g. "1,3,5")
var linesToRemove = txtLinesToRemove.Text
.Split(',')
.Select(x => int.Parse(x.Trim()))
.ToHashSet();
var lines = File.ReadAllLines(filePath);
var filteredLines = lines
.Where((line, index) => !linesToRemove.Contains(index + 1))
.ToArray();
File.WriteAllLines(filePath, filteredLines);
MessageBox.Show("Lines removed successfully!");
}
________________________________________
🧠 How It Works
• User uploads a file
• Enters line numbers (like 2,4,6)
• App removes those lines
• File is overwritten with updated content
________________________________________
🚀 Optional Improvements
If you want to make it more powerful:
• Preview file in a TextBox
• Save as a new file instead of overwriting
• Allow removing lines by keyword instead of number
• Add drag & drop support
________________________________________
If you want, I can also show you:
• A WPF version (modern UI)
• A web app version (upload via browser)
• Or how to remove lines based on text patterns instead of numbers
Make it so a textbox shows the path of the chosen file.
Good idea—that's exactly how most apps behave 👍
You just need to put the selected file path into a TextBox after using OpenFileDialog.
________________________________________
🧱 1. Add a TextBox
In Visual Studio:
• Drag a TextBox onto your form
• Name it: txtFilePath (in Properties → Name)
________________________________________
⚙️ 2. Update your Upload Button code
Modify your button click like this:
string filePath = "";
private void btnUpload_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog1.FileName;
// Show path in textbox
txtFilePath.Text = filePath;
}
}
________________________________________
🧠 What's happening
• User clicks Upload
• File dialog opens
• When they pick a file:
o FileName gets the path
o You assign it to the TextBox → it displays on screen
________________________________________
✨ Optional improvements
Make it read-only (so user can't edit it)
Select the TextBox → Properties:
• Set ReadOnly = true
________________________________________
Show only file name (not full path)
txtFilePath.Text = Path.GetFileName(filePath);
________________________________________
Show full path as tooltip (nice UX)
toolTip1.SetToolTip(txtFilePath, filePath);
________________________________________
If you want next steps, I can help you:
• Display file content in a big textbox
• Highlight the lines that will be removed
• Or add a “Save As” instead of overwriting the file
Adapt a textbox size depending on the size of the file name.
You can make your TextBox resize automatically based on the file name length, but there's a catch: in Visual Studio WinForms, a TextBox doesn't auto-size horizontally by itself—you have to calculate it.
Here are the best ways to do it 👇
________________________________________
✅ Option 1: Resize based on text width (recommended)
Use TextRenderer.MeasureText to calculate how wide the text is, then resize the TextBox.
💻 Code:
private void AdjustTextBoxWidth()
{
int padding = 10; // extra space so it's not tight
var textSize = TextRenderer.MeasureText(txtFilePath.Text, txtFilePath.Font);
txtFilePath.Width = textSize.Width + padding;
}
👉 Call it after setting the text:
txtFilePath.Text = filePath;
AdjustTextBoxWidth();
________________________________________
⚠️ Important note
If your file path is very long, the TextBox can grow too much and break your layout.
👉 So it's smart to add a maximum width:
int maxWidth = 400;
txtFilePath.Width = Math.Min(textSize.Width + padding, maxWidth);
________________________________________
✅ Option 2: Keep size fixed but scroll (simpler)
Instead of resizing, you can:
• Set TextBox → AutoSize = false
• Set Width = fixed value
• Set ScrollBars = Horizontal
👉 This keeps your UI clean and avoids stretching.
________________________________________
✅ Option 3: Multiline + wrap (for long paths)
If you want it to grow vertically instead:
• Set:
o Multiline = true
o WordWrap = true
________________________________________
🧠 Pro tip (best UX)
Most real apps do this:
• Fixed-size TextBox
• Show full path on hover (tooltip)
• Or show shortened path like:
C:\...\Documents\file.txt
________________________________________
🚀 Clean combo solution
txtFilePath.Text = filePath;
// Resize nicely
var size = TextRenderer.MeasureText(txtFilePath.Text, txtFilePath.Font);
txtFilePath.Width = Math.Min(size.Width + 10, 400);
// Tooltip for full path
toolTip1.SetToolTip(txtFilePath, filePath);
________________________________________
If you want, I can show you how to:
• Auto-shorten long paths like Windows does
• Or make the UI responsive (resizes with the window)
Let's' say i want a button to upload the G-code or ngc file, then a button called simplify that will change the G-code the way i want and then save a copy on the same directory of the uploaded file.
Yes—you can build exactly that in Visual Studio with a simple WinForms workflow:
• 📂 Upload G-code (.gcode / .ngc)
• ⚙️ “Simplify” button processes it
• 💾 Save a modified COPY in the same folder
________________________________________
🧱 1. UI you need (Form1)
Add these controls:
• Button → btnUpload (“Upload G-code”)
• Button → btnSimplify (“Simplify & Save”)
• TextBox → txtFilePath (ReadOnly = true)
________________________________________
🧠 2. Store file path globally
At the top of your form:
string filePath = "";
________________________________________
📂 3. Upload button (select file)
private void btnUpload_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "G-code files (*.gcode;*.ngc)|*.gcode;*.ngc|All files (*.*)|*.*";
if (dialog.ShowDialog() == DialogResult.OK)
{
filePath = dialog.FileName;
txtFilePath.Text = filePath;
}
}
________________________________________
⚙️ 4. Simplify + Save Copy
This is where your “magic” happens.
Example simplification rules:
• Remove comment lines (;)
• Remove empty lines
• Trim spaces
private void btnSimplify_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(filePath))
{
MessageBox.Show("Please upload a file first.");
return;
}
string[] lines = File.ReadAllLines(filePath);
var simplified = lines
.Select(l => l.Trim())
.Where(l => !string.IsNullOrWhiteSpace(l))
.Where(l => !l.StartsWith(";")) // remove comments
.ToArray();
// Create new file name in same folder
string folder = Path.GetDirectoryName(filePath);
string name = Path.GetFileNameWithoutExtension(filePath);
string ext = Path.GetExtension(filePath);
string newFilePath = Path.Combine(folder, name + "_simplified" + ext);
File.WriteAllLines(newFilePath, simplified);
MessageBox.Show("Saved: " + newFilePath);
}
________________________________________
💾 What this does
When user clicks Simplify:
✔ Reads original file
✔ Applies your rules
✔ Creates new file like:
original.ngc
→ original_simplified.ngc
✔ Saves in SAME folder
________________________________________
🧠 Easy to extend later
You can upgrade “simplify” to:
• Remove G0 rapid moves
• Remove duplicate lines
• Remove tool change commands (T commands)
• Compress repeated coordinates
• Optimize feed rates
________________________________________
🚀 Best structure (recommended)
Keep:
• filePath → original file
• never overwrite original unless user chooses
________________________________________
If you want, I can next help you build:
🔥 a real G-code optimizer (CNC-style cleaner)
🔥 or a preview window that shows “before vs after” changes side-by-side
Let's say i have a line that contains G01 X193.143390 Y231.249054 Z0.000000 F400.000000? how to remove every Z0.000000 and F400.000000 but keep the rest.
Yes—you can clean that line by removing specific “tokens” (Z and F values) while keeping everything else in Visual Studio.
In G-code, this is best done with string replacement or regex.
________________________________________
✅ Option 1 (simple Replace — good if format is consistent)
string line = "G01 X193.143390 Y231.249054 Z0.000000 F400.000000";
line = line.Replace("Z0.000000", "")
.Replace("F400.000000", "")
.Trim();
________________________________________
⚠️ Problem with this method
It ONLY works if:
• values are exactly the same every time
But in real G-code you might have:
Z0.1
Z0.000
F1200
F400.5
________________________________________
🚀 Option 2 (BEST): Regex removal (recommended)
This removes any Z<number> and F<number> no matter the value.
using System.Text.RegularExpressions;
string line = "G01 X193.143390 Y231.249054 Z0.000000 F400.000000";
line = Regex.Replace(line, @"Z-?\d+(\.\d+)?", "");
line = Regex.Replace(line, @"F-?\d+(\.\d+)?", "");
line = Regex.Replace(line, @"\s+", " ").Trim();
________________________________________
🧠 What this does
🔹 Z-?\d+(\.\d+)?
Removes:
• Z0
• Z0.000
• Z12.5
• Z-3.2
🔹 F-?\d+(\.\d+)?
Removes:
• F400
• F400.000
• F1200.5
________________________________________
✨ Final result
Input:
G01 X193.143390 Y231.249054 Z0.000000 F400.000000
Output:
G01 X193.143390 Y231.249054
________________________________________
💡 Cleaner version for your simplify pipeline
var simplified = lines
.Select(l => Regex.Replace(l, @"Z-?\d+(\.\d+)?", ""))
.Select(l => Regex.Replace(l, @"F-?\d+(\.\d+)?", ""))
.Select(l => Regex.Replace(l, @"\s+", " ").Trim())
.Where(l => !string.IsNullOrWhiteSpace(l))
.ToArray();
________________________________________
🚀 Pro tip (important for CNC)
Be careful:
• Removing F changes feed rate behavior
• Removing Z changes depth positioning
👉 Always test on safe files first
________________________________________
If you want, I can help you build:
🔥 “smart G-code optimizer” (keeps safe moves, removes only redundant values)
🔥 or a rule system like checkboxes: “Remove Z”, “Remove F”, “Remove comments” 👍
XIAO SEEED-RP2040 send text through USB.
If you're using a XIAO RP2040 (based on the Raspberry Pi RP2040 chip), sending text over USB is straightforward because the board exposes a USB CDC serial interface (it shows up like a virtual COM port).
Here's how to do it depending on your environment:
________________________________________
🧩 Option 1: Arduino (easiest)
1. Install the Seeed XIAO RP2040 board package.
2. Select the correct board and port.
3. Use Serial to send text over USB.
Example:
void setup() {
Serial.begin(115200);
while (!Serial); // wait for USB connection
}
void loop() {
Serial.println("Hello from XIAO RP2040!");
delay(1000);
}
📌 Open the Serial Monitor in Arduino IDE → you'll see the text.
________________________________________
🐍 Option 2: MicroPython
If you flashed MicroPython firmware:
Example:
import time
import sys
while True:
print("Hello from XIAO RP2040!")
time.sleep(1)
📌 Connect with a serial terminal (e.g., Thonny or PuTTY) to view output.
________________________________________
⚙️ Option 3: CircuitPython
With CircuitPython:
import time
while True:
print("Hello via USB!")
time.sleep(1)
📌 Output appears in the serial console (and sometimes via USB REPL).
________________________________________
🧠 What's actually happening
• The RP2040 uses USB as a virtual serial port (CDC).
• Your computer sees it like /dev/ttyACM0 (Linux/macOS) or COMx (Windows).
• Serial.print() or print() sends bytes over USB to your PC.
________________________________________
🔍 Troubleshooting
• Make sure the correct port is selected.
• If nothing shows, try resetting the board.
• On Arduino: ensure while (!Serial); is used for boards that need it.
• Use a proper USB data cable (not charge-only).
________________________________________
If you tell me which environment you're using (Arduino, bare-metal C/C++, MicroPython, etc.), I can give you a more tailored example or help you send structured data instead of plain text.
In Visual Studio open a port and read what it says with a Windows Forms App.
Here's a simple Windows Forms (WinForms) app in Microsoft Visual Studio that opens a serial port and displays what your XIAO RP2040 sends.
________________________________________
🧱 1. Create the UI
Add these controls to your form:
• ComboBox → comboBoxPorts
• Button → btnRefresh (text: “Refresh”)
• Button → btnConnect (text: “Connect”)
• TextBox → txtOutput
o Multiline = true
o ScrollBars = Vertical
o Dock = Fill (optional)
________________________________________
⚙️ 2. Code
Add this at the top:
using System.IO.Ports;
Fields:
SerialPort serialPort = new SerialPort();
________________________________________
🔄 Load available ports
private void RefreshPorts()
{
comboBoxPorts.Items.Clear();
comboBoxPorts.Items.AddRange(SerialPort.GetPortNames());
if (comboBoxPorts.Items.Count > 0)
comboBoxPorts.SelectedIndex = 0;
}
Call it:
private void Form1_Load(object sender, EventArgs e)
{
RefreshPorts();
}
Button:
private void btnRefresh_Click(object sender, EventArgs e)
{
RefreshPorts();
}
________________________________________
🔌 Connect to the port
private void btnConnect_Click(object sender, EventArgs e)
{
if (serialPort.IsOpen)
{
serialPort.Close();
btnConnect.Text = "Connect";
return;
}
try
{
serialPort.PortName = comboBoxPorts.SelectedItem.ToString();
serialPort.BaudRate = 115200;
serialPort.NewLine = "\n";
serialPort.DataReceived += SerialPort_DataReceived;
serialPort.Open();
btnConnect.Text = "Disconnect";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
________________________________________
📥 Receive data (important: cross-thread safe)
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string data = serialPort.ReadLine();
this.Invoke(new Action(() =>
{
txtOutput.AppendText(data + Environment.NewLine);
}));
}
catch { }
}
________________________________________
⚠️ Important notes
• Close Thonny before running this (it locks the port)
• Make sure baud rate matches your MicroPython (115200)
• print() on RP2040 works perfectly with ReadLine()
________________________________________
🧪 Test it
On your RP2040 (MicroPython):
import time
while True:
print("Hello from RP2040")
time.sleep(1)
Run your WinForms app → Connect → you should see lines appearing live.
________________________________________
🚀 Nice upgrades (if you want)
• Add a Send button to write to the board (serialPort.WriteLine(...))
• Auto-scroll toggle
• Timestamp each message
• Handle disconnect/reconnect cleanly
________________________________________
If you want, I can extend this into a full serial monitor app (like Arduino Serial Monitor but custom).
Micropython and Thonny, convert data received from usb to actual numerical value.
If you want to take data coming from USB serial in Thonny (MicroPython on RP2040) and convert it into a real number (int or float), you just need to parse the string you receive.
________________________________________
🧠 1. Basic idea
USB data always arrives as text (string):
"123"
"45.67"
You must convert it:
• int() → whole numbers
• float() → decimal numbers
________________________________________
✅ 2. Convert received USB input to number
Example (integer):
while True:
data = input() # receives string from USB
value = int(data) # convert to number
print("Number is:", value)
________________________________________
Example (float):
while True:
data = input()
value = float(data)
print("Float is:", value)
________________________________________
⚠️ 3. Important safety (avoid crashes)
If PC sends bad data, conversion will crash. Use try:
while True:
data = input()
try:
value = float(data)
print("OK value:", value)
except:
print("Invalid number:", data)
________________________________________
🔁 4. Example with PC (WinForms sending)
If your C# sends:
serialPort.WriteLine("25.5");
MicroPython receives:
data = input() # "25.5"
value = float(data) # 25.5
________________________________________
🧠 5. Use it in real projects (sensor style)
while True:
data = input()
try:
temperature = float(data)
if temperature > 30:
print("HOT")
else:
print("OK")
except:
print("Bad data")
________________________________________
🚀 Key takeaway
✔ USB data = string
✔ int() / float() = conversion
✔ always use try/except for stability
________________________________________
If you want next step, I can show you:
• sending numbers from RP2040 → C# and graphing them 📊
• or building a full sensor dashboard system 👍
In a Windows Forms App, in Visual Studio, I have a file with multiple coordinates X and Y, I want to take line by line remove the X and Y but keep the numerical values and have one line for X, go to next line and put Y for every line so instead of having X Y, X Y, X Y, I have X, Y, X, Y, X, Y, based on the code I already have.
You're already very close — your current code cleans the G-code nicely, but it keeps X and Y on the same line because you never split them apart.
What you want is an extra transformation step:
Take each simplified line → extract X value and Y value → output them on separate lines.
________________________________________
✅ Fix: modify your btnSimplify_Click
Add a final parsing step after your simplified array is created.
Replace ONLY this part:
File.WriteAllLines(newFilePath, simplified);
with this:
________________________________________
✅ ADD THIS INSTEAD (X line then Y line)
var output = new List();
foreach (var line in simplified)
{
var xMatch = Regex.Match(line, @"X-?\d+(\.\d+)?");
var yMatch = Regex.Match(line, @"Y-?\d+(\.\d+)?");
if (xMatch.Success)
output.Add(xMatch.Value.Substring(1)); // remove X
if (yMatch.Success)
output.Add(yMatch.Value.Substring(1)); // remove Y
}
File.WriteAllLines(newFilePath, output);
________________________________________
🔥 What this does
Turns:
X10 Y20
X30 Y40
Into:
10
20
30
40
________________________________________
⚠️ Important detail
• Substring(1) removes the X/Y letter
• Keeps only numbers
• Maintains order: X then Y per line
________________________________________
If you later want a cleaner version (faster + safer parsing), I can simplify your whole method, but this is the minimal “drop-in” fix you asked for.
Only keep 2 numerical values after the dot.
Add a rounding step when you store the values.
✅ FIX (safe + correct parsing)
Replace your loop with this version:
var output = new List();
var culture = System.Globalization.CultureInfo.InvariantCulture;
foreach (var line in simplified)
{
var xMatch = Regex.Match(line, @"X-?\d+(\.\d+)?");
var yMatch = Regex.Match(line, @"Y-?\d+(\.\d+)?");
if (xMatch.Success)
{
double x = double.Parse(xMatch.Value.Substring(1), culture);
output.Add(x.ToString("0.00", culture));
}
if (yMatch.Success)
{
double y = double.Parse(yMatch.Value.Substring(1), culture);
output.Add(y.ToString("0.00", culture));
}
}
File.WriteAllLines(newFilePath, output);
✅ What you'll get now
Correct output:
119.92
263.38
196.13
69.86
50.81
...
________________________________________
⚡ Optional improvement (recommended)
If you want even more safety (no crashes on bad lines):
double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out double x)
________________________________________
If you want next upgrade, I can also help you:
• keep X and Y on same line like X10.00 Y20.00
• or export directly to CSV for CNC / Excel / Fusion 360
• or visualize toolpath in WinForms (pretty useful for G-code)
In Visual Studio with a Windows Forms App, i can upload a file and connect to a port, now i want to press a button called "btnStartCom" that will read the file and send the first two lines to the port, and after receiving the message OK from the receiver it sends the next two lines and so and so, all based on my current code.
You're basically building a handshaked streaming sender (send 2 lines → wait for “OK” → send next 2 lines). This is a very common serial/CNC pattern.
________________________________________
✅ Core idea
1. Read file into lines
2. Send first 2 lines
3. Wait until device replies "OK"
4. Send next 2 lines
5. Repeat until end
________________________________________
⚠️ Important design rule
You must not block the UI thread, so we use:
• async/await
• or a background Task
Perfect — your structure is already solid. We'll now add a proper streaming sender with “2 lines → wait OK → next 2 lines” directly into your code style.
I'll keep it clean and compatible with what you already have.
________________________________________
✅ WHAT WE ADD
You will get:
• btnStartCom
• async sender loop
• OK handshake system
• minimal changes to your existing code
________________________________________
🔧 STEP 1 — add these GLOBAL VARIABLES (top of class)
Add under your SerialPort serialPort = new SerialPort();
string[] gcodeLines;
int sendIndex = 0;
TaskCompletionSource okWaiter;
________________________________________
🔧 STEP 2 — modify your DataReceived (IMPORTANT FIX)
Replace your current SerialPort_DataReceived with this:
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string data = serialPort.ReadExisting();
this.Invoke(new Action(() =>
{
textBoxOutput.AppendText(data);
textBoxOutput.SelectionStart = textBoxOutput.Text.Length;
textBoxOutput.ScrollToCaret();
// check for OK from device
if (data.Contains("OK"))
{
okWaiter?.TrySetResult(true);
}
}));
}
catch
{
// ignore disconnect glitches
}
}
________________________________________
🔧 STEP 3 — ADD START BUTTON (btnStartCom)
Create a button and add:
private async void btnStartCom_Click(object sender, EventArgs e)
{
if (!serialPort.IsOpen)
{
MessageBox.Show("Connect to port first!");
return;
}
if (string.IsNullOrEmpty(filePath))
{
MessageBox.Show("Upload a file first!");
return;
}
gcodeLines = File.ReadAllLines(filePath);
sendIndex = 0;
while (sendIndex < gcodeLines.Length)
{
// take 2 lines
string line1 = gcodeLines[sendIndex];
string line2 = (sendIndex + 1 < gcodeLines.Length) ? gcodeLines[sendIndex + 1] : "";
serialPort.WriteLine(line1);
if (!string.IsNullOrWhiteSpace(line2))
serialPort.WriteLine(line2);
sendIndex += 2;
// WAIT FOR OK
okWaiter = new TaskCompletionSource();
await okWaiter.Task;
}
MessageBox.Show("G-code sent successfully!");
}
________________________________________
🧠 HOW IT WORKS
Loop:
1. Send 2 lines
2. Wait until device sends:
OK
3. Send next 2 lines
4. Repeat
________________________________________
⚡ DEVICE SIDE EXPECTATION
Your RP2040 / MicroPython / firmware must send:
OK
after processing each pair.
________________________________________
🚀 OPTIONAL IMPROVEMENTS (if you want next level)
✔ progress bar
progressBar1.Value = (sendIndex * 100) / gcodeLines.Length;
________________________________________
✔ safer OK detection
if (data.Trim().ToUpper().Contains("OK"))
________________________________________
✔ emergency stop button
serialPort.WriteLine("STOP");
________________________________________
⚠️ IMPORTANT REAL-WORLD NOTE
Your current design is:
“block next send until OK”
This is perfect for:
• CNC control
• GRBL-style devices
• RP2040 motion controllers
BUT if your firmware ever sends multiple messages at once, we may need to buffer parsing more strictly.
________________________________________
If you want, I can next help you upgrade this into:
• 🔁 resume after disconnect
• 📍 live position tracking
• 📉 real G-code preview graph
• ⚡ streaming 1 line at a time (faster & safer than 2-line batching)
Just tell me 👍