返回首页

简介
一个可视化应用程序的共同要求是一个"列表框" - 基于行的日志,允许对一些条目之间的分化。最常见的所有会见的第一个版本,这个类的一个,是可以有不同的颜色(红色等错误行),不同的线条。
本控制线,以使自己和控制自己的高度来解决一般的问题。它提供了默认字体显示的一个基本路线类和指定颜色的,一类以显示包含图像的线条,以及一个允许用户修改其文本内容。它还允许您创建自定义行可以有任何形式展示。
这也是在研究如何创建继承UserControl类System.Windows.Forms的一个有用的自定义控制。要直接跳到如何使一个良好的控制信息,请{A}。
样品使用的控制是在我的。游戏列表,游戏信息窗格中,球员名单和聊天/日志区所有LineEditors。使用
控制提供了一个单一的。cs文件中,一旦编译成DLL,可以添加到Visual Studio,SharpDevelop,并以通常的方式,您可以拖放一个自定义控件出现类似的东西您的表单。另外,您也可以使用构造函数和手动添加控制:

LineEditor lineEditor = new LineEditor();

someContainer.Controls.Add(lineEditor);

控制公开,允许您自定义的视觉效果,以及如何与用户交互的几个属性:可编辑,用户是否可以编辑接受用户输入的行。默认为false。ShowSelection:是否突出与当前的Windows选择颜色选定行。无论开启或关闭,周围放置一个虚线矩形选定行,以确定它。默认为true。BottomAligned:滚动调整时添加一个新行,以保持相同的偏移控制的底部。这是非常有用的日志或命令提示符的风格使用的最后一个项目应该是可见的大部分时间的。默认为true。可选:用户是否可以选择控制。
你也可以使用标准提供的UserControl,当然,颜色和样式选项。
控制的最简单的使用仅仅是添加行编程,使用Line类。如果你想添加一个默认的行(文本仅在一个单一的颜色),您可以使用AddLine方法:{C}
您可以附加任意数据,这是一个控制线,但您可以使用自己的信息存储与行。
若要添加其他种类的线,您可以使用线属性,这是一个LineCollection。 (如果我没有最初写这个类。NET 1.1下前一阵子,这只会是一个Listlt; linegt;)像所有的集合,它提供添加,插入和删除线的实例的方法:
lineEditor.Lines.Add(new Line(Color.Blue, "Another test"));

lineEditor.Lines.Add(new ImageLine(Image.FromFile("test.png")));

// remember to set Editable to true

lineEditor.Lines.Add(new EditableLine(Color.Green, "Editable text"));

lineEditor.Lines.Insert(new Line(Color.Black, "At the front"), 0);

以及简单的文本行,一个ImageLine(这将显示图像的任何实例)和EditableLine(用户可以修改文本)。自定义行
,您可能要产生的许多专科线可以实施简单地创建一个位图,绘图,并使用一个ImageLine。不过,如果你想产生一个互动或复杂的线路,您可以从线类继承并修改它的行为。 EditableLine类是一个很好的指导,因为它是一个比较复杂的的类,修改线的许多方面。这里是您将要覆盖的方法:公共虚拟无效油漆(图形克,字型字体,颜色C,INT ypos)
最重要的虚拟方法,这种油漆行。您是通过绘制的字体,这一行(如果它被选中ShowSelection是真实,这可能是Windows的选择突出显示的颜色),并在这一行开始的Y位置相关联的颜色。你不应该一般涂料ypos以上或以下ypos GetHeight(字体)。建议你观察保护缩进的成员,作为最小的X坐标您使用,以确保您的生产线是在控制其他对齐。公共虚拟GetHeight(字体字体)
返回该行的高度,在其中绘制的字体。默认情况下,返回由文字,字体设置的空间。公共虚拟GETFONT字体(Font的字体)
选择一个字体来绘制,控制要求。重写此方法允许您绘制一个与别人不同的字体的行。公共虚拟线CopyTo(李线)和公共的虚拟对象的克隆()
允许被克隆行。添加任何属性添加到您的自定义类的CopyTo(),并覆盖以类似的方式克隆到EditableLine:
public override object Clone(){ return CopyTo(new MyCustomLine(Color, Text)); }
公共虚拟无效InsertText(字符串文本)
定义如何插入文本。默认情况下,它是附加的。
您可以随时查看和修改文本属性。如果您想您的线路以响应用户输入,也有一些输入您将要覆盖的方法:
public virtual bool OnKeyDown(KeyEventArgs e){return false;}

public virtual bool OnKeyUp(KeyEventArgs e){return false;}

public virtual bool OnKeyPress(KeyPressEventArgs e){return false;}

这些方法返回true,如果你处理的按键,并希望抑制默认的行动,他们会导致。记住,你需要控制的可编辑属性设置为true,关键事件。鼠标的方法将被添加后,在以后的版本类似的模式。
如果你想提供线,用户可以编辑,您可能要继承从EditableLine而不是线。
这种控制直接继承自UserControl,它一直是我的启发,来看看如何写从该基地的可用控制。使得它比较容易做到的。NET,但也有几点,这引起了我一点点的困难。第一个步骤
要做的第一件事是画你的控制,压倒一切的OnPaint。这就是所谓的每次要画您的控制,所以我试图有些高效能缓存笔和画笔。您还需要创建一个InitializeComponent方法(美国拼写强制性),以确保控制可以出现在你的IDE自定义控制,并从构造函数中调用它。在此方法中,你应该把:
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |

         ControlStyles.DoubleBuffer | ControlStyles.Selectable | 

         ControlStyles.StandardClick , true)

看看Control.SetStyle文档,以确定您需要哪些样式,但UserPaint和可选的大多数控件的本质。
如果您正在创建一个绘画可以是复杂的控制,你可能会考虑缓存整个图像画和更新分开,当它需要做。我在地图上控制使用这种技术,我地质的映射器,可能有一个复杂的地图上绘制数千贝塞尔段,并在我的Abaria游戏观者,其中有数百个3D三角形画照明。但对于大多数控件,像这样的,你可以很容易地执行在涂料中的所有计算。鼠标交互
为了让您的控制与用户交互,你需要做出反应的鼠标。通常情况下,你将要使用鼠标选择一个项目,可能鼠标移动拖动项目或悬停突出显示(但要记住,这样做的力量许多重绘,所以使你的绘制代码效率)。
你想覆盖的方法是:
protected override void OnMouseDown(MouseEventArgs e)

protected override void OnMouseUp(MouseEventArgs e) // maybe

protected override void OnMouseMove(MouseEventArgs e) // maybe

一个典型的鼠标处理程序是像这样LineEditor之一:
protected override void OnMouseDown(MouseEventArgs e){

    base.OnMouseDown(e);

    if(!Selectable) return;

    Focus();

    SelectedIndex = GetIndexAt(e.X, e.Y);            

    Invalidate();

}

你应该始终调用base.Whatever(E),因为不这样做会导致默认行为没有发生,奇怪的事情发生。 GetIndexAt方法是一种常见的要求,返回鼠标下的项目的索引。
要实现拖动,你将有您在OnMouseDown /上设置一个切换,并执行的OnMouseMove拖动鼠标。我有没有C#示例的技术,因为它不是在这个控制实施。
设置StandardClick风格(见第一步),导致被解雇,通过设置鼠标选择项目向下的Click和DoubleClick事件,你让这些事件是有益的。键盘
乍一看,使用键盘也很容易。至于用鼠标,覆盖获得键盘的功能有三种方法:
protected override void OnKeyDown(KeyEventArgs e)

protected override void OnKeyUp(KeyEventArgs e)

protected override void OnKeyPress(KeyPressEventArgs e)

KeyPress的是可打印字符,出于某种原因,退格(8)和输入(13)。 KeyDown和KeyUp提供的所有键(KeyDown的重复,如果按住按键),并告诉你的关键和修饰符(SHIFT,ALT,CTRL)。
然而,接受所有相关的键和字符,你需要"劫持"控制助记符(下划线的字母,你可以用Alt来激活控制)等,以防止框架。要做到这一点,你需要重写两个方法:BOOL保护覆盖IsInputKey(密钥k)
是否给定的关键是要通过这种控制处理。返回true如果您想看到在OnKeyUp /向下键。你应该总是返回base.IsInputKey(K)如果您不希望其正常状态不同,治疗的关键。 LineEditor的情况下,箭头键返回true。保护覆盖BOOL IsInputChar(CHAR彗星)
给定的字符是否应控制处理。返回true如果您想看到OnKeyPress这个关键 - 如果不这样做,它可以控制助记符劫持。对于一个像这样的文字控制的,你总是希望从该方法返回真实的。
导航内的控制,一旦你能够处理的关键事件是作为读者的练习左 - 虽然你可能会EditableLine.KeyDown方法能够得到一些启示。最重要的一点是保持跟踪光标的位置,这样你就可以插入,删除,修改文​​本在正确的点。要测量正确地放置插入符的部分字符串,你应该使用在此摘录从EditableLine.Paint Graphics.MeasureCharacterRanges方法(不Graphics.MeasureString):
StringFormat sf = new StringFormat();

sf.SetMeasurableCharacterRanges (

        new CharacterRange[]{ new CharacterRange(0, ci) } );

sf.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;

cx = indent + (ci > 0 ? g.MeasureCharacterRanges(

     s, font,

     new RectangleF(0, 0, Host.Parent.ClientSize.Width, font.Height), sf

  )[0].GetBounds(g).Right : 0);
滚动
另一种常见的要求是一个滚动控制时出现过小,或者其内容变得过大,可用的空间。我的技术是包括类,这是停靠适当的(在这种情况下,DockStyle.Right),可见在需要时的滚动条的一个实例。
// in InitializeComponent

scrollbar = new VScrollBar();

scrollbar.Dock = DockStyle.Right;

scrollbar.Visible = false;

scrollbar.Scroll += new ScrollEventHandler(ScrollbarMoved);

this.Controls.Add(scrollbar);

每当发生变化,修改控制的内容时,可能会影响滚动条(在onResize受到,或在这种情况下,通过添加或删除行),你应该调用一个RecalculateScrollbar方法,它看起来像这样的东西LineEditor:
private void RecalculateScrollbar(){

    int bottom = 0;

    foreach(Line line in lines) bottom += line.GetHeight(Font);

    if(bottom < ClientSize.Height){

        scrollbar.Visible = false;

        scrollbar.Value = 0;

        return;

    }

    scrollbar.Visible = true;

    scrollbar.Maximum = bottom;

    scrollbar.LargeChange = ClientSize.Height;

    scrollbar.SmallChange = Font.Height;

    lastSBValue = scrollbar.Value;

}

它也是非常有用的一个VisibleWidth属性:
public int VisibleWidth {

    get { return ClientSize.Width - (scrollbar.Visible ? scrollbar.Width : 0); }

}

...工作时可以使用在什么地方包住,当添加水平滚动条,依此类推。
滚动条的事件处理程序通常可以简单调用Invalidate力控制重绘滚动条的值应在涂料中的检查项目绘制在正确的地方。
这个例子涉及一个垂直滚动条(可能是最常见),但水平滚动条非常相似。唯一需要注意的是,如果你有两个滚动,你应该在右下角背景颜色绘制"死亡空间",缩短了两个滚动条。

回答

评论会员:EmmanuelN 时间:2011/12/14
我目前尝试运行您的代码到一个80线程系统,但不知何故,它看起来像它只能检测60。是否有任何线程/处理器的限制
评论会员:?Vivek_India 时间:2011/12/14
您的文章,是一个尚未另一篇文章中,强调了多核时代的重要性.. {S0}
评论会员:Sajjitha古纳瓦德纳 时间:2011/12/14
8内核带来...然后16 ... {S0}
我想事情会变得有趣... ... {S0}

Sajjitha古纳瓦德纳
评论会员:PawJershauge 时间:2011/12/14
嘿,首先,漂亮的方​​案

但是,我得到这个错误:类别不exsist在这行代码:
((System.ComponentModel.ISupportInitialize)(this.performanceCounter1))EndInit();
在这个文件ProcessorUtilization.Designer.cs中,可以帮助吗??

最好的问候
评论会员:Sajjitha古纳瓦德纳 时间:2011/12/14
嗨,

你使用。NET 2和Visual Studio 2005?我完全不知道为什么你得到上面的错误... ...但由于我没有得到这个错误(VS 2005中的。NET 2)我想知道这是否可能是版本问题?



Sajjitha古纳瓦德纳
评论会员:PawJershauge 时间:2011/12/14
是IM使用VS2005和我有在计算机上的净2。我不知道,为什么IM收到此错误,从来没有见过它之前。或许也可能是硬件的IM使用或东西。
但是,任何方式很好的代码... ... {S0}
评论会员:PawJershauge 时间:2011/12/14
!好了,我发现这个问题
看来,微软错过了PerformanceCounter类的东西,这个类需要启用页面文件。 {S4}的{S4}的{S4}的{S4}的
,如果你有一个XP系统上禁用你的页面文件,你会得到这个错误。
我启用了页面文件,并重新启动计算机,你的程序正常工作。

不要问我为什么类需要的页面文件,但我googled问题,一段时间后,
我发现这在MS支持的信息]向下滚动到"替代方法"部分。

关于
爪jershauge
评论会员:Sajjitha古纳瓦德纳 时间:2011/12/14
尼斯你找到了一个解决方案... ...我从来没有
知道
Sajjitha古纳瓦德纳
评论会员:PawJershauge 时间:2011/12/14
,那么它也有点难以找到类似这样的错误
它不是很明显,页面文件有什么做的preformancecouter的,反正不是在我的世界...
嘿嘿。