You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 local PictureBox variables 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 a Bitmap and assign it to the PictureBox's Image property 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:

  1. Fixed Variable Shadowing: Removed local PictureBox declarations in InitializeComponent() and configured the class-level controls directly, so drawing code targets the actual controls on the form.
  2. Persistent Drawing: Now draws to a Bitmap using Graphics.FromImage(), then assigns the bitmap to the PictureBox's Image property. This ensures waveforms stay visible even when the form is resized or refreshed.
  3. Improved Signal Generation:
    • Increased SignalLength for 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
  4. Better UI Polish: Added border styles, white backgrounds, and text labels to each PictureBox for clearer visualization.
  5. Corrected Startup Order: Moved Application.EnableVisualStyles() to the correct position before launching the form.

内容的提问来源于stack exchange,提问作者zenon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 17:25:24