Let's take a look at the text message interface of the iPhone.
I just saw this interface and the saliva couldn't stop.
Dry your saliva and quickly imitate it.
Initial Practice:
Based on UserControl, you can create a user control that contains TextBolck to display multiple lines of text,
Use Path and Geometry to draw a graph with a small tail, and then draw a light effect.
It is done.
Although the results can be achieved, it is still inappropriate to think carefully.
The problem is that the self-made control only displays text. To display images, you have to write a bunch of code,
Too rigid. Why can't I use the WPF framework or features to make the control more flexible?
The drawing effect and the layout control effect will be OK. As for whether the content contains text or images, hand it over to WPF.
Finished.
Based on this, I immediately thought of writing a Template for the TextBlock control.
Drawing a complex image is a bit illusory, and the result is abandoned.
Ideas:
Decorater is adopted under the verbose of the boss. At first glance, I cannot touch the north,
Border is inherited from this class. To put it bluntly, it is a container that contains a sub-element, a custom Decorater.
Draws a graphic background and manages the display of child elements. If the image or text is displayed, hand it over to the child element.
Complete.
Why not use Border? The truth is that it is enough to use it, and it is clean.
(Of course, the container also has Panel and ContentControl. Decorater is enough here ).
Let's take a look at the final effect:
It mainly uses the methods of the base class:
MeasureOverride: calculates the size of the required space by measuring the child element.
ArrangeOverride: displays the position of sub-elements.
OnRender: a self-painting function that draws a graph with a small tail. It is equivalent to OnPaint.
Custom IDecorator class:
Public class iDecorator: Decorator {
Public iDecorator (){
This. HorizontalAlignment = System. Windows. HorizontalAlignment. Right;
}
Public bool Direction {
Get {return (bool) GetValue (DirectionProperty );}
Set {SetValue (DirectionProperty, value );}
}
Protected override Size MeasureOverride (Size constraint ){
Size result = new Size ();
If (Child! = Null ){
Child. Measure (constraint );
Result. Width = Child. DesiredSize. Width + padding. Left + padding. Right;
Result. Height = Child. DesiredSize. Height + padding. Top + padding. Bottom;
If (result. Height <35 ){
Result. Height = 35;
Padding. Top = padding. Bottom = (result. Height-Child. DesiredSize. Height)/2;
}
}
Return result;
}
Protected override Size ArrangeOverride (Size arrangeSize ){
If (Child! = Null ){
Child. Arrange (new Rect (new Point (padding. Left, padding. Top ),
Child. DesiredSize ));
}
Return arrangeSize;
}
Protected override void OnRender (DrawingContext dc ){
If (Child! = Null ){
Geometry cg = null;
Brush brush = null;
Pen pen = new Pen ();
Pen. Brush = new SolidColorBrush (Colors. Black );
Pen. Thickness = 1;
If (Direction ){
// Generate the image and background color of the tail on the right
Cg = CreateGeometryTailAtRight ();
Brush = CreateBrushTailAtRight ();
}
Else {
// Generate the image and background color of the tail on the left
Cg = CreateGeometryTailAtLeft ();
Brush = CreateBrushTailAtLeft ();
}
Dc. DrawGeometry (brush, pen, cg );
// Draw the illumination effect
GradientStopCollection gscLight = new GradientStopCollection ();
GscLight. Add (new GradientStop (Color. FromArgb (0xDA, 0xFF, 0xFF, 0xFF), 0 ));
GscLight. Add (new GradientStop (Color. FromArgb (0x68, 0xFF, 0xEF, 0xFF), 1 ));
Brush lightBrush = new LinearGradientBrush (gscLight, new Point (0, 0), new Point (0, 1 ));
Dc. DrawRoundedRectangle (lightBrush, null, new Rect (22, 1, this. ActualWidth-45, 20), 10, 10 );
}
// Omit Part of the code...
Public static void OnDirectionPropertyChangedCallback (DependencyObject d, DependencyPropertyChangedEventArgs e ){
Var self = d as iDecorator;
Self. HorizontalAlignment = (bool) e. NewValue?
HorizontalAlignment. Right: HorizontalAlignment. Left;
}
Private Thickness padding = new Thickness (25, 6, 25, 6 );
Public static readonly DependencyProperty DirectionProperty =
DependencyProperty. Register ("Direction", typeof (bool), typeof (iDecorator ),
New FrameworkPropertyMetadata (true, FrameworkPropertyMetadataOptions. AffectsRender, ondireproperpropertychangedcallback ));
}
Usage:
The text message box's tail is on the right side:
<Local: iDecorator HorizontalAlignment = "Right" Direction = "True">
<TextBlock MaxWidth = "200" Foreground = "Black" TextWrapping = "Wrap"> where did I go two days ago ??? </TextBlock>
</Local: iDecorator>
The tail of the text message box is on the left:
Set Direction to False.
<Local: iDecorator HorizontalAlignment = "Right" Direction = "False">
<TextBlock MaxWidth = "200" Foreground = "Black" TextWrapping = "Wrap"> where did I go two days ago ??? </TextBlock>
</Local: iDecorator>
Success!
Although there are still some details of the effect is still a little worse, but It works.
Source code: http://files.cnblogs.com/kongxianghai/iMessageDemoSln.rar
Development Environment: VS2010,. NetFramWork4.0.
From the white ocean