Windows Forms无法显示信号波形?求修改代码实现幅度调制解调模拟
Fixing Your C# WinForms AM Modulation/Demodulation Waveform Display
Let's walk through the issues in your code and fix them so your signals render properly in the PictureBoxes:
Key Problems in the Original Code
- Local Variable Shadowing: In
InitializeComponent(), you're declaring new localPictureBoxvariables that overwrite the class-level ones. This means all your later drawing code targets unused local controls instead of the ones added to the form. - Incorrect Drawing Approach: Using
CreateGraphics()draws directly to the control's surface, but these drawings get erased when the form is refreshed. Instead, we should draw to aBitmapand assign it to the PictureBox'sImageproperty for persistent rendering. - Signal Demodulation Incompleteness: Multiplying the modulated signal back with the carrier leaves high-frequency components; we need a simple low-pass filter to recover the clean original modulation signal.
- Incorrect Application Startup Order:
Application.EnableVisualStyles()should be called before running the form to ensure proper UI styling.
Modified Working Code
using System; using System.Windows.Forms; using System.Drawing; using static System.Math; static class Program { [STAThread] public static void Main() { // Fixed: Enable visual styles before launching the form Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(true); Application.Run(new ModulationDemodulationExample()); } } public class ModulationDemodulationExample : Form { // Class-level controls (no shadowing in InitializeComponent) private const int SignalLength = 500; // Increased for smoother waveform rendering private PictureBox carrierSignalBox = new PictureBox(); private PictureBox modulatorSignalBox = new PictureBox(); private PictureBox modulatedSignalBox = new PictureBox(); private PictureBox demodulatedSignalBox = new PictureBox(); private double[] carrierSignal; private double[] modulatorSignal; private double[] modulatedSignal; private double[] demodulatedSignal; private double carrierFrequency = 10.0; // Higher carrier for clear AM visualization private double modulatorFrequency = 1.0; public ModulationDemodulationExample() { InitializeComponent(); GenerateSignals(); DrawAllSignals(); } private void InitializeComponent() { Text = "AM Modulation & Demodulation Simulator"; Size = new Size(850, 650); // Configure each class-level PictureBox directly carrierSignalBox.Location = new Point(10, 10); carrierSignalBox.Size = new Size(400, 250); carrierSignalBox.BorderStyle = BorderStyle.FixedSingle; carrierSignalBox.BackColor = Color.White; Controls.Add(carrierSignalBox); modulatorSignalBox.Location = new Point(10, 270); modulatorSignalBox.Size = new Size(400, 250); modulatorSignalBox.BorderStyle = BorderStyle.FixedSingle; modulatorSignalBox.BackColor = Color.White; Controls.Add(modulatorSignalBox); modulatedSignalBox.Location = new Point(420, 10); modulatedSignalBox.Size = new Size(400, 250); modulatedSignalBox.BorderStyle = BorderStyle.FixedSingle; modulatedSignalBox.BackColor = Color.White; Controls.Add(modulatedSignalBox); demodulatedSignalBox.Location = new Point(420, 270); demodulatedSignalBox.Size = new Size(400, 250); demodulatedSignalBox.BorderStyle = BorderStyle.FixedSingle; demodulatedSignalBox.BackColor = Color.White; Controls.Add(demodulatedSignalBox); } private void GenerateSignals() { carrierSignal = new double[SignalLength]; modulatorSignal = new double[SignalLength]; modulatedSignal = new double[SignalLength]; demodulatedSignal = new double[SignalLength]; for (int i = 0; i < SignalLength; i++) { // Normalize x to 0-2π range for smoother signal cycles double x = (double)i / SignalLength * 2 * PI; carrierSignal[i] = Sin(carrierFrequency * x); modulatorSignal[i] = 0.5 * Sin(modulatorFrequency * x); // Lower amplitude to avoid overmodulation modulatedSignal[i] = (1 + modulatorSignal[i]) * carrierSignal[i]; // Standard AM formula // Demodulate: multiply with carrier then apply low-pass filter double rawDemod = modulatedSignal[i] * carrierSignal[i]; demodulatedSignal[i] = LowPassFilter(rawDemod, i); } } // Simple moving average low-pass filter to remove high-frequency carrier noise private double LowPassFilter(double currentValue, int index) { if (index == 0) return currentValue; // Adjust alpha for more/less smoothing (0.1 = gentle filter) double alpha = 0.1; return alpha * currentValue + (1 - alpha) * demodulatedSignal[index - 1]; } private void DrawAllSignals() { DrawSignal(carrierSignalBox, carrierSignal, Color.Blue, "Carrier Signal"); DrawSignal(modulatorSignalBox, modulatorSignal, Color.Red, "Modulator Signal"); DrawSignal(modulatedSignalBox, modulatedSignal, Color.Green, "Modulated Signal"); DrawSignal(demodulatedSignalBox, demodulatedSignal, Color.Black, "Demodulated Signal"); } void DrawSignal(PictureBox pictureBox, double[] signal, Color color, string label) { // Create a bitmap matching the PictureBox dimensions Bitmap bmp = new Bitmap(pictureBox.Width, pictureBox.Height); using (Graphics g = Graphics.FromImage(bmp)) { g.Clear(Color.White); Pen pen = new Pen(color, 2); // Thicker pen for better visibility // Calculate scaling to fit the signal in the PictureBox double xScale = (double)pictureBox.Width / (signal.Length - 1); double yScale = pictureBox.Height / 3.0; // Leave space for labels double yOffset = pictureBox.Height / 2.0; // Draw the signal line (flip Y to match screen coordinates where top = 0) for (int i = 0; i < signal.Length - 1; i++) { int x1 = (int)(i * xScale); int y1 = (int)(yOffset - signal[i] * yScale); int x2 = (int)((i + 1) * xScale); int y2 = (int)(yOffset - signal[i + 1] * yScale); g.DrawLine(pen, x1, y1, x2, y2); } // Add a label to each PictureBox for clarity using (Font font = new Font("Arial", 12)) { g.DrawString(label, font, Brushes.Black, 10, 10); } } // Assign the bitmap to the PictureBox (persists through form refreshes) pictureBox.Image = bmp; } }
What Changed:
- Fixed Variable Shadowing: Removed local
PictureBoxdeclarations inInitializeComponent()and configured the class-level controls directly, so drawing code targets the actual controls on the form. - Persistent Drawing: Now draws to a
BitmapusingGraphics.FromImage(), then assigns the bitmap to the PictureBox'sImageproperty. This ensures waveforms stay visible even when the form is resized or refreshed. - Improved Signal Generation:
- Increased
SignalLengthfor smoother, more detailed waveforms - Adjusted frequencies and amplitudes to create a clear, recognizable AM effect
- Added a simple low-pass filter to clean up the demodulated signal
- Increased
- Better UI Polish: Added border styles, white backgrounds, and text labels to each PictureBox for clearer visualization.
- Corrected Startup Order: Moved
Application.EnableVisualStyles()to the correct position before launching the form.
内容的提问来源于stack exchange,提问作者zenon
相关产品推荐
相关产品推荐

