2011-06-28 30 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; 

        } 

       } 

      } 

     } 
    } 
}