2011-06-28 33 views
6

在一个没有真实库的平台上,以及除坐标(x,y)上的维度(x,y,xx,yy)显示对象之外的裸露最小图形,I试图创建一个简单的gui从零开始创建一个简单的GUI

有人可以指向一个参考,我可以理解在屏幕上显示一组对象所涉及的逻辑原理,并突出显示所选对象,允许用户在对象之间导航并突出显示每个对象似乎应该很简单,但我想了解人们是如何看待这个的

如何用obj.highlight()方法创建一个对象,其中obj 。高光会tur在所有其他物体中突出显示?会简单地做一个下一个循环通过一个对象数组,跳过当前对象,关闭突出显示,然后将当前对象设置为true?突出显示可以通过在透明中心的选定对象之上绘制另一个对象来完成。

这是一个单线程系统(但允许少量的异步处理)。

我在寻找更多的概念性想法,但VB中不使用专有图形调用的代码可能会有用。

回答

2

那么这是一个问题,可以在一百万的方式来回答... :)

但只要你可以绘制像素(或任何远程喜欢它),你可以得出一个GUI。如果你手头有面向对象的语言,我不会选择突出显示当前对象。我会给予焦点并从焦点中移除焦点,并让对象自己决定是否应该重新绘制,以及应该如何完成。

如果所有对象都放置在某种容器中,则可以自动忽略前一个对象。当您按导航键(如Tab)或按下鼠标按钮时,该容器可以处理该消息并聚焦下一个对象并取消聚焦最后一个对象。

它需要一些编程,但这个概念很简单。当你希望它表现良好,看起来光滑,有各种各样的动词和转换时,它变得更加困难......但正如我所说的,这个概念很简单,你甚至不需要面向对象来做到这一点,尽管它可能会给你是一个更清洁的结果。如果需要的话,我想我可以在一个下雨的下午在DOS批处理程序中编写一个基于ASCII的GUI。

3

我已经编写了一个小样本应用程序,它通过使用.Net C#在表单上绘画来完成自己的控件框架。简简单单就好这个结果:

enter image description here

我已经通过递归禁用所有的控制和切换的点击一个完成的IsSelected。 查看零件与window.MouseUp += (sender, arg) =>

选择可以通过鼠标或Tab键。

该代码方法应该可以移植到其他语言,并可在线转换为VB.Net。

相关的代码片段:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows.Forms; 
using System.Drawing; 
using System.Threading; 
using System.Threading.Tasks; 

namespace CustomGUI 
{ 
    static class Program 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Form window = new Form1(); 
      window.BackColor = Color.Gray; 

      Graphics api = window.CreateGraphics(); 

      GUIControl form = new GUIControl(); 
      form.Location = new Point(30,30); 
      form.Size = new Size(200, 300); 

      GUIControl control1 = new GUIControl(); 
      control1.Location = new Point(0, 0); 
      control1.Size = new Size(200, 130); 
      control1.Background = Color.Blue; 

      GUIControl control11 = new GUIControl(); 
      control11.Location = new Point(140, 30); 
      control11.Size = new Size(30, 30); 
      control11.Background = Color.Red; 

      GUIControl control12 = new GUIControl(); 
      control12.Location = new Point(30, 30); 
      control12.Size = new Size(30, 30); 
      control12.Background = Color.Red; 
      control12.BorderColor = Color.Green; 
      control12.BorderWidth = 5; 

      GuiLabel control2 = new GuiLabel(); 
      control2.Location = new Point(10, 200); 
      control2.Size = new Size(180, 30); 
      control2.Background = Color.Green; 
      control2.Text = "Hello World!"; 

      control1.AddChild(control11); 
      control1.AddChild(control12); 

      form.AddChild(control1); 
      form.AddChild(control2); 

      window.MouseUp += (sender, arg) => 
      { 
       // hit test the control where the mouse has landed 
       IGUIContainer control = form.HitTest(arg.Location); 
       if (control != null) 
       { 
        // recursive on all controls 
        foreach (var ct in (new IGUIContainer[] { form }).Traverse(c => c.Controls)) 
        { 
         //deselecting all others 
         if (ct != control) ct.IsSelected = false; 
        } 
        control.IsSelected = !control.IsSelected; 
       } 
       window.Invalidate(); // force paint 
      }; 

      window.KeyUp += (sender, key) => 
      { 
       if (key.KeyCode == Keys.Tab && key.Modifiers == Keys.None) 
       { 
        var selected = (new IGUIContainer[] { form }).Traverse(c => c.Controls).FirstOrDefault(c => c.IsSelected); 

        IGUIContainer parent; 

        if (selected == null) 
        { 
         parent = form; 
        } 
        else 
        { 
         parent = selected; 
        } 

        IGUIContainer control; 

        if (parent.Controls.Count > 0) 
        { 
         control = parent.Controls[0]; 
        } 
        else 
        { 
         control = GUIControl.Next(parent); 
        } 

        if (control == null) control = form; 

        foreach (var ct in (new IGUIContainer[] { form }).Traverse(c => c.Controls)) 
        { 
         if (ct != control) ct.IsSelected = false; 
        } 

        control.IsSelected = true; 

        window.Invalidate(); 
       } 
      }; 

      window.Paint += (sender, args) => 
      { 
       form.Draw(api, new Point(0,0)); 
      }; 

      Application.Run(window); 
     } 
    } 
} 

所有所需的类和接口:

IDrawable:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 

namespace CustomGUI 
{ 
    public interface IDrawable 
    { 
     Point Location { get; set; } 
     Size Size { get; set; } 
     Rectangle GetRealRect(Point origin); 
     void Draw(Graphics gfxApi, Point origin); 
    } 
} 

IGUIContainer:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 

namespace CustomGUI 
{ 
    delegate void SelectionChangedHandler(object sender, bool newIsSelected); 

    interface IGUIContainer : IUIElement 
    { 
     IGUIContainer Parent { get; set; } 
     List<IGUIContainer> Controls { get; } 
     void AddChild(IGUIContainer child); 
     bool IsSelected { get; set; } 
     event SelectionChangedHandler SelectionChanged; 
     IGUIContainer HitTest(Point mouseCoord); 
    } 
} 

的UIElement:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 
using System.Diagnostics; 

namespace CustomGUI 
{ 
    abstract class UIElement : IUIElement 
    { 
     private Point _location; 
     private Size _size; 
     private Color _background; 
     private Color _foreground; 
     private Color _borderColor; 
     private int _borderWidth; 

     public UIElement() 
     { 
      _foreground = Color.Black; 
      _background = Color.White; 
      _borderColor = Color.Transparent; 
     } 

     public Point Location 
     { 
      get 
      { 
       return _location; 
      } 
      set 
      { 
       _location = value; 
      } 
     } 

     public Size Size 
     { 
      get 
      { 
       return _size; 
      } 
      set 
      { 
       _size = value; 
      } 
     } 

     public virtual void Draw(Graphics drawingApi, Point origin) 
     { 

      Rectangle inside = GetRealRect(origin); 

      Pen borderPen = new Pen(new SolidBrush(_borderColor), _borderWidth); 
      drawingApi.FillRectangle(new SolidBrush(_background), inside); 
      drawingApi.DrawRectangle(borderPen, inside); 
     } 

     public Rectangle ClientRect 
     { 
      get 
      { 
       return new Rectangle(_location, _size); 
      } 
     } 


     public Color Background 
     { 
      get 
      { 
       return _background; 
      } 
      set 
      { 
       _background = value; 
      } 
     } 

     public Color Foreground 
     { 
      get 
      { 
       return _foreground; 
      } 
      set 
      { 
       _foreground = value; 
      } 
     } 


     public Rectangle GetRealRect(Point origin) 
     { 
      int left = ClientRect.Left + origin.X; 
      int top = ClientRect.Top + origin.Y; 
      int width = ClientRect.Width; 
      int height = ClientRect.Height; 

      Debug.WriteLine("GetRealRect " + left + ", " + top + ", " + width + ", " + height); 

      return new Rectangle(left, top, width, height); 
     } 


     public int BorderWidth 
     { 
      get 
      { 
       return _borderWidth; 
      } 
      set 
      { 
       _borderWidth = value; 
      } 
     } 

     public Color BorderColor 
     { 
      get 
      { 
       return _borderColor; 
      } 
      set 
      { 
       _borderColor = value; 
      } 
     } 
    } 
} 

GUIControl:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 

namespace CustomGUI 
{ 
    class GUIControl : UIElement, IGUIContainer 
    { 
     private IGUIContainer _parent; 
     private List<IGUIContainer> _controls = new List<IGUIContainer>(); 
     private bool _isSelected; 

     public List<IGUIContainer> Controls 
     { 
      get 
      { 
       return _controls; 
      } 
     } 

     public override void Draw(Graphics api, Point origin) 
     { 
      Point original = origin; 

      base.Draw(api, origin); 

      origin.Offset(this.Location); 

      foreach (var ctrl in Controls) 
      { 
       ctrl.Draw(api, origin); 
      } 

      if (IsSelected) 
      { 
       Pen selection = new Pen(Color.Yellow, 3); 
       selection.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot; 
       api.DrawRectangle(selection, GetRealRect(original)); 
      } 

     } 

     public IGUIContainer HitTest(Point coord) 
     { 
      Point newOrigin = coord; 
      newOrigin.Offset(-this.Location.X, -this.Location.Y); 

      foreach (var ctrl in Controls) 
      { 
       IGUIContainer hit = ctrl.HitTest(newOrigin); 
       if (hit != null) 
       { 
        return hit; 
       } 
      } 

      return ClientRect.Contains(coord) ? this : null; 
     } 

     public bool IsSelected 
     { 
      get 
      { 
       return _isSelected; 
      } 
      set 
      { 
       _isSelected = value; 

       if (SelectionChanged != null) 
       { 
        SelectionChanged(this, _isSelected); 
       } 
      } 
     } 

     public event SelectionChangedHandler SelectionChanged; 

     public void AddChild(IGUIContainer child) 
     { 
      // if you need to implement event propagation this is the place to attach them to children 
      child.Parent = this; 
      Controls.Add(child); 
     } 

     public IGUIContainer Parent 
     { 
      get 
      { 
       return _parent; 
      } 
      set 
      { 
       _parent = value; 
      } 
     } 

     public static IGUIContainer Next(IGUIContainer self) 
     { 
      if (self.Parent != null && 
       self.Parent.Controls.Count - 1 > self.Parent.Controls.IndexOf(self)) 
      { 
       return self.Parent.Controls[self.Parent.Controls.IndexOf(self) + 1]; 
      } 
      else if (self.Parent != null) 
      { 
       return Next(self.Parent); 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 
} 

GUILabel:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 

namespace CustomGUI 
{ 
    class GuiLabel : GUIControl 
    { 
     public string Text { get; set; } 
     public Font Font { get; set; } 

     public GuiLabel() 
     { 
      Font = new Font(new FontFamily("Tahoma"), 12, FontStyle.Regular);    
     } 

     public override void Draw(System.Drawing.Graphics api, System.Drawing.Point origin) 
     { 
      base.Draw(api, origin); 

      Rectangle controlRect = GetRealRect(origin); 
      SizeF size = api.MeasureString(Text, Font); 

      Point textPosition = new Point(controlRect.Location.X + (int)(controlRect.Width - size.Width)/2, 
             controlRect.Location.Y + (int)(controlRect.Height - size.Height)/2); 

      api.DrawString(Text, Font, new SolidBrush(Foreground), textPosition); 
     } 
    } 
} 

扩展(对于遍历方法来弄平递归):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace CustomGUI 
{ 
    static class Extensions 
    { 
     public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse) 
     { 

      foreach (T item in source) 
      { 

       yield return item; 

       IEnumerable<T> seqRecurse = fnRecurse(item); 

       if (seqRecurse != null) 
       { 

        foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse)) 
        { 

         yield return itemRecurse; 

        } 

       } 

      } 

     } 
    } 
}