2011-06-28 14 views
6

実際のライブラリがなく、座標(x、y)に「次元(x、y、xx、yy)」の表示オブジェクト以外の最小のグラフィックがあるプラットフォームでは、IシンプルなGUIを作成する

私は、画面上にオブジェクトのセットを表示し、選択されたオブジェクトを強調表示し、ユーザーがオブジェクト間を移動できるようにするためのロジスティクスの原理を理解することができます。それぞれのオブジェクトにハイライトを移動することは簡単ですが、私は人々がこれについてどのように考えるかを理解したいと思います。obj.highlight()のようなメソッドを使ってオブジェクトを作成する方法obj 。ハイライトは、他のすべてのオブジェクトでハイライトをオフにしますか?現在のオブジェクトをスキップし、ハイライトをオフにして、現在のオブジェクトをtrueに設定するだけで、オブジェクトの配列を介して次のループを行うだけですか?強調表示は、選択されたオブジェクトの上に別のオブジェクトを透明な中心で描画することによって実現されます。

これはシングルスレッドシステムです(しかし、少量の非同期処理が可能です)。

私は概念的なアイデアを探していますが、独自のグラフィックス呼び出しを使用しないVBのコードが役に立ちます。百万の方法で答えることができる一つの質問... :)

である。しかし限り、あなたはピクセル(またはリモートでのようなもの)を描くことができるよう

答えて

2

さて、あなたはGUIを描くことができます。手元にあるオブジェクト指向言語をお持ちの場合は、現在のオブジェクトを強調表示したり強調表示を解除したりすることはしません。私は焦点を当ててそれから焦点を外し、オブジェクト自体が再描画されるべきかどうか、それがどのように行われるべきかを決定させます。

すべてのオブジェクトが何らかの種類のコンテナに配置されていると、自動的に前のオブジェクトのフォーカスを解除することができます。ナビゲーションキー(Tabなど)を押すかマウスボタンを押すと、そのコンテナはそのメッセージを処理して次のオブジェクトにフォーカスを合わせ、最後のオブジェクトのフォーカスを外します。

プログラミングが必要ですが、そのコンセプトは非常に簡単です。それはあなたがそれがうまく動作し、滑らかに見えるようにしたいときに難しくなります、あらゆる種類のアニメーションとトランジションがあります...しかし、私が言ったように、コンセプトはシンプルで、OOを必要としません。あなたはもっときれいな結果を出します。私は、DOSベースのGUIをASCIIベースのGUIで、雨の日の午後に、必要に応じてプログラムすることができると思います。

3

私は、.NET C#を使用してフォームにペイントすることによって、独自のコントロールフレームワークを実行する小さなサンプルアプリケーションをコーディングしました。この結果にシンプルなだけで何か:私は再帰的にすべてのコントロールを無効にすると、クリックされたものを切り替えることでIsSelectedをやった

enter image description here

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; 

        } 

       } 

      } 

     } 
    } 
} 
関連する問題