代码之家  ›  专栏  ›  技术社区  ›  Dark Star1

在C中模拟雷达的最佳方法是什么?

  •  2
  • Dark Star1  · 技术社区  · 16 年前

    我的表单中有一个分组框内的图片框,背景图片是雷达的图片。我的目的是在运行时在雷达区域(覆盖)内动态加载微小的jpeg图像,但我不确定实现这一点的最佳方法。 所有疯狂的想法都受到欢迎(但我更喜欢理智、容易做的想法)。 谢谢大家。

    4 回复  |  直到 12 年前
        1
  •  3
  •   Jason Williams    16 年前

    这很大程度上取决于“雷达”的外观,但几乎可以肯定的是,您需要实现绘制事件处理程序,并自己绘制雷达显示的内容。一个图片框只能让你做到这一点(“不是很好”)。

    GDI+非常容易用于绘制圆、线、文本和图像,并且可以完全控制显示器的外观。

        2
  •  2
  •   LunaTick    16 年前

    至于实际例子:

      // Among others
      using System.Collections.Generic;
      using System.Drawing;
      using System.IO;
    
      class TinyPic {
        public readonly Image Picture;
        public readonly Rectangle Bounds;
    
        public TinyPic(Image picture, int x, int y) {
          Picture = picture;
          Bounds = new Rectangle(x, y, picture.Width, picture.Height);
        }
      }
    
      class MyForm : Form {
    
        Dictionary<String, TinyPic> tinyPics = new Dictionary<String, TinyPic>();
    
        public MyForm(){
          InitializeComponent(); // assuming Panel myRadarBox
                                 // with your background is there somewhere;
          myRadarBox.Paint += new PaintEventHandler(OnPaintRadar);
        }
    
        void OnPaintRadar(Object sender, PaintEventArgs e){
          foreach(var item in tinyPics){
            TinyPic tp = item.Value;
            e.Graphics.DrawImageUnscaled(tp.Picture, tp.Bounds.Location);
          }
        }
    
        void AddPic(String path, int x, int y){
          if ( File.Exists(path) ){
            var tp = new TinyPic(Image.FromFile(path), x, y);
            tinyPics[path] = tp;
            myRadarBox.Invalidate(tp.Bounds);
          }
        }
    
        void RemovePic(String path){
          TinyPic tp;
          if ( tinyPics.TryGetValue(path, out tp) ){
            tinyPics.Remove(path);
            tp.Picture.Dispose();
            myRadarBox.Invalidate(tp.Bounds);
          }
        }
      }
    

    当然,这是非常基本的,假设图像源是路径,不处理许多复杂的事情,但这是快速和肮脏的jist它,你当然可以建立。

        3
  •  2
  •   MusiGenesis    12 年前

    Click here 运行一个示例应用程序,演示如何执行雷达的基本操作(至少是一种方法)。注意:这个应用程序不会对微小图像进行双重缓冲或透明处理。

    项目的源代码是 here .

    更新 代码:

    public partial class Form1 : Form
    {
        private Bitmap _canvas;
        private float _sweepStartAngle = -90;
        private float _sweepAngle = 15;
        private SolidBrush _sweepBrush = new SolidBrush(Color.Red);
        private Rectangle _sweepRect;
        private Timer _sweepTimer = new Timer();
        private Bitmap _submarine;
        private Point _submarinePosition = new Point(0, 0);
        private Random rnd = new Random();
    
        public Form1()
        {
            InitializeComponent();
    
            _canvas = new Bitmap(pbScope.Width, pbScope.Height);
            pbScope.Image = _canvas;
            _sweepRect = new Rectangle(0, 0, pbScope.Width, pbScope.Height);
    
            _submarine = (Bitmap)pbSubmarine.Image;
    
            RedrawScope();
    
            _sweepTimer.Interval = 100;
            _sweepTimer.Tick += new EventHandler(_sweepTimer_Tick);
            _sweepTimer.Start();
        }
    
        void _sweepTimer_Tick(object sender, EventArgs e)
        {
            _sweepStartAngle += _sweepAngle;
            RedrawScope();
        }
    
        private void RedrawScope()
        {
            using (Graphics g = Graphics.FromImage(_canvas))
            {
                // draw the background
                g.DrawImage(pbBackground.Image, 0, 0);
    
                // draw the "sweep"
                GraphicsPath piepath = new GraphicsPath();
                piepath.AddPie(_sweepRect, _sweepStartAngle, _sweepAngle);
                g.FillPath(_sweepBrush, piepath);
                //g.FillPie(_sweepBrush, _sweepRect, _sweepStartAngle, _sweepAngle);
    
                // move the submarine and draw it
                _submarinePosition.X += rnd.Next(3);
                _submarinePosition.Y += rnd.Next(3);
                // check if submarine intersects with piepath
                Rectangle rect = new Rectangle(_submarinePosition, _submarine.Size);
                Region region = new Region(piepath);
                region.Intersect(rect);
                if (!region.IsEmpty(g))
                {
                    g.DrawImage(_submarine, _submarinePosition);
                }
            }
            pbScope.Image = _canvas;
        }
    
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _sweepTimer.Stop();
            _sweepTimer.Dispose();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            //GraphicsPath piepath = new GraphicsPath();
            //piepath.AddPie(
    
        }
    
    }
    
       private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
            this.pbScope = new System.Windows.Forms.PictureBox();
            this.pbBackground = new System.Windows.Forms.PictureBox();
            this.pbSubmarine = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.pbScope)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbBackground)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbSubmarine)).BeginInit();
            this.SuspendLayout();
            // 
            // pbScope
            // 
            this.pbScope.Location = new System.Drawing.Point(12, 12);
            this.pbScope.Name = "pbScope";
            this.pbScope.Size = new System.Drawing.Size(300, 300);
            this.pbScope.TabIndex = 0;
            this.pbScope.TabStop = false;
            // 
            // pbBackground
            // 
            this.pbBackground.Image = ((System.Drawing.Image)(resources.GetObject("pbBackground.Image")));
            this.pbBackground.Location = new System.Drawing.Point(341, 12);
            this.pbBackground.Name = "pbBackground";
            this.pbBackground.Size = new System.Drawing.Size(300, 300);
            this.pbBackground.TabIndex = 1;
            this.pbBackground.TabStop = false;
            this.pbBackground.Visible = false;
            // 
            // pbSubmarine
            // 
            this.pbSubmarine.Image = ((System.Drawing.Image)(resources.GetObject("pbSubmarine.Image")));
            this.pbSubmarine.Location = new System.Drawing.Point(658, 45);
            this.pbSubmarine.Name = "pbSubmarine";
            this.pbSubmarine.Size = new System.Drawing.Size(48, 48);
            this.pbSubmarine.TabIndex = 2;
            this.pbSubmarine.TabStop = false;
            this.pbSubmarine.Visible = false;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(326, 328);
            this.Controls.Add(this.pbSubmarine);
            this.Controls.Add(this.pbBackground);
            this.Controls.Add(this.pbScope);
            this.Name = "Form1";
            this.Text = "Radar";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
            ((System.ComponentModel.ISupportInitialize)(this.pbScope)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbBackground)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbSubmarine)).EndInit();
            this.ResumeLayout(false);
    
        }
    
        4
  •  0
  •   MusiGenesis    16 年前

    最简单的方法是将小的jpeg加载到小的PictureBox中,并在运行时将它们添加到主PictureBox的控件集合(即将它们放在PictureBox上)。

    因为这可能会产生闪烁,所以稍微复杂一点的方法是将主图片和小图片保留在类级位图对象中,并且在主PictureBox的绘制事件中,使用DrawImage将主图片和每个小图片复制到二级位图(名为“DoubleBuffer”或类似的内容)上。方法,然后将DoubleBuffer复制到PictureBox(也使用DrawImage)。每当需要更新显示并重新绘制所有内容时,只需调用PictureBox的Invalidate方法。

    这里有大量的例子来说明如何使用这些方法。祝你好运,听起来很有趣(如果你正在重写经典的街机游戏《潜水艇》,请告诉我——我喜欢这个游戏)。