2011-06-28 44 views
6

Trên nền tảng không có sẵn thư viện thực và đồ họa tối thiểu khác với "đối tượng hiển thị kích thước (x, y, xx, yy) tại tọa độ (x, y), tôi Có thể ai đó chỉ cho tôi một tham chiếu nơi tôi có thể hiểu các nguyên tắc hậu cần liên quan đến việc hiển thị một tập hợp các đối tượng trên màn hình, và làm nổi bật đối tượng được chọn, cho phép người dùng điều hướng giữa các đối tượng Có vẻ như nó phải đơn giản để làm, nhưng tôi muốn hiểu cách mọi người nghĩ về điều này.Tạo GUI đơn giản từ đầu

Làm thế nào để tạo một đối tượng với một phương thức như obj.highlight(), nơi obj .highlight sẽ tur n tắt làm nổi bật trong tất cả các đối tượng khác? Có thể chỉ đơn giản là làm một vòng lặp tiếp theo thông qua một mảng các đối tượng, bỏ qua đối tượng hiện tại, tắt làm nổi bật và sau đó đặt đối tượng hiện tại thành true? Việc tô sáng sẽ được thực hiện bằng cách vẽ một đối tượng khác lên trên đối tượng được chọn với một trung tâm trong suốt.

Đây là một hệ thống luồng đơn, (nhưng cho phép một lượng nhỏ xử lý không đồng bộ).

Tôi đang tìm kiếm nhiều ý tưởng khái niệm hơn nhưng mã trong VB không sử dụng các cuộc gọi đồ họa độc quyền có thể hữu ích.

Trả lời

2

Vâng đó là một câu hỏi có thể được trả lời trong một triệu cách ... :)

Nhưng chừng nào bạn có thể vẽ pixel (hoặc bất cứ điều gì từ xa như nó), bạn có thể vẽ một GUI. Nếu bạn có một ngôn ngữ hướng đối tượng trong tầm tay, tôi sẽ không chọn để làm nổi bật và làm mờ sáng đối tượng hiện tại. Tôi sẽ đưa ra nếu tập trung và loại bỏ tập trung từ nó, và để cho các đối tượng tự quyết định xem nó nên được vẽ lại và làm thế nào nên được thực hiện.

Bạn có thể tự động lấy nét đối tượng trước đó nếu tất cả đối tượng được đặt trong một số loại vùng chứa. Khi bạn nhấn phím điều hướng (như Tab) hoặc nhấn nút chuột, vùng chứa đó có thể xử lý thông báo đó và lấy tiêu điểm đối tượng tiếp theo và không lấy nét đối tượng cuối cùng.

Nó đòi hỏi một số chương trình, nhưng khái niệm này khá dễ dàng. Nó trở nên khó khăn hơn khi bạn muốn nó hoạt động tốt, trông bóng bẩy, có tất cả các loại anumations và transitions ... Nhưng như tôi đã nói, khái niệm rất đơn giản và bạn thậm chí sẽ không cần OO để làm điều đó, mặc dù nó có thể sẽ cho bạn một kết quả sạch hơn nhiều. Tôi nghĩ rằng tôi có thể lập trình một GUI dựa trên ASCII trong DOS Lô vào một buổi chiều mưa nếu tôi cần.

3

Tôi đã mã hóa một ứng dụng mẫu nhỏ có khung điều khiển của riêng nó bằng cách vẽ trên biểu mẫu bằng .Net C#. Chỉ cần một cái gì đó đơn giản với kết quả này:

enter image description here

tôi đã thực hiện các IsSelected bằng cách đệ quy vô hiệu hóa tất cả các điều khiển và chuyển đổi qua lại các nhấp một. Xem phần với window.MouseUp += (sender, arg) =>.

Lựa chọn có thể đi qua chuột hoặc phím Tab.

Cách tiếp cận mã nên được di chuyển sang các ngôn ngữ khác và có thể dịch trực tuyến sang VB.Net.

đoạn có liên quan của mã:

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); 
     } 
    } 
} 

Tất cả các lớp học cần thiết và giao diện:

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); 
     } 
    } 
} 

mở rộng (đối với phương pháp Traverse để san bằng đệ quy):

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; 

        } 

       } 

      } 

     } 
    } 
} 
Các vấn đề liên quan