Reputation: 153
Recently I was working with WPF and C#, and I wanted to make an editor for an A4 page (A JPG template with the size of an A4)
The thing is, I want to put some text in a certain place on the JPG and to be able to see it as I write the text (like a live preview).
This is what I achieved by now:
XAML
<Window x:Class="Tut.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Tut"
mc:Ignorable="d"
Title="Neshalet Logo ltd." Height="900" Width="1400">
<Border Padding="10">
<StackPanel Margin="0,10,0,0">
<Grid Height="839">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width=".3*"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="0,2,22,817" HorizontalAlignment="Right" Grid.Column="2" FontSize="15">
בחר מוצר
</TextBlock>
<!-- Combo box for product type -->
<ComboBox x:Name="productType" Grid.Column="1" VerticalAlignment="Top" Height="25" Margin="10,0,17,0" >
<ComboBoxItem>באנרים</ComboBoxItem>
<ComboBoxItem>שקפים וניירות</ComboBoxItem>
<ComboBoxItem>וינילים</ComboBoxItem>
<ComboBoxItem>קשיחים הדפסה ישירה</ComboBoxItem>
<ComboBoxItem>הדבקה</ComboBoxItem>
</ComboBox>
<Image Source ="/Resources/a4.jpg" Grid.Column="0" Margin="10,35,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
</Image>
<!-- Main window -->
<StackPanel Grid.Column="1" Grid.ColumnSpan="2" Margin="10,40,0,0">
<Grid Height="492">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- SO Number-->
<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,5,22,472"><Run Text="מספר הזמנה"/></TextBlock>
<TextBox x:Name="SO" DataContextChanged="drawSO" Height="25" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,0,5,0"/>
<!-- Costumer name -->
<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,34,22,440"><Run Text="שם לקוח"/></TextBlock>
<TextBox Grid.Column="0" Height="25" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,30,5,0"/>
<!-- Order date -->
<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,64,22,410"><Run Text="תאריך"/></TextBlock>
<Button Grid.Column="1" Margin="9,62,122,410" Click="getDate" Content="היום" RenderTransformOrigin="0.5,0.5"/>
<DatePicker x:Name="todaysDate" Grid.Column="0" Height="25" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,60,5,0"/>
<!-- Supply date -->
<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,93,22,381"><Run Text="תאריך אספקה"/></TextBlock>
<DatePicker x:Name ="deliveryDate" Margin="0,90,5,377" />
<!-- Folder -->
<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,123,22,351"><Run Text="נשמר בתיקיה"/></TextBlock>
<ComboBox x:Name="folderName" Grid.Column="0" Margin="0,120,5,347">
<ComboBoxItem Content="ktanot"/>
<ComboBoxItem Content="GZM"/>
<ComboBoxItem Content="UV"/>
<ComboBoxItem Content="SLAVA WATER PRINTS"/>
</ComboBox>
<!-- Folder -->
<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,154,22,320"><Run Text="קוד משלוח"/></TextBlock>
<ComboBox x:Name="DeliveryCode" Grid.Column="0" Margin="0,150,5,317">
<ComboBoxItem Content="איסוף עצמי"/>
<ComboBoxItem Content="מסירה"/>
<ComboBoxItem Content="משלוח"/>
</ComboBox>
<Button Margin="230,362,270,96" Click="Button_Click">
כאן
</Button>
</Grid>
</StackPanel>
<Label Content="תצוגה מקדימה" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Column="0"/>
</Grid>
<!-- Image preview -->
</StackPanel>
</Border>
C#
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
DateTime today = DateTime.Today.Date;
String path = @"/Resources/a4.jpg";
Bitmap order = null;
Font f = new Font("Arial", 200, GraphicsUnit.Pixel);
private void getDate(object sender, RoutedEventArgs e)
{
String t = today.ToShortDateString();
todaysDate.Text = t;
}
private void drawSO(object sender, DependencyPropertyChangedEventArgs e)
{
}
private void Button_Click(object sender, RoutedEventArgs e)
{
String orderNum = SO.Text;
using (var stream = File.OpenRead(path))
{
order = (Bitmap)Bitmap.FromStream(stream);
}
using (order)
using (var graphics = Graphics.FromImage(order))
using (f)
{
graphics.DrawString(orderNum, f, System.Drawing.Brushes.White, order.Height/2, order.Width/2);
order.Save(path);
}
}
}
The thing is that I made the program write the text only on a button click (as you can see on Button_Click()
, but I want to to display the text I write on SO Number text box while I'm writing it.
Is there any way to refresh the image view on the window as I write the text and not on a Button click event?
Here is an example: I want the text entered in the text box will be on the jpg
Upvotes: 0
Views: 200
Reputation: 169200
The thing is that I made the program write the text only on a button click (as you can see on
Button_Click()
, but I want to to display the text I write on SO Number text box while I'm writing it. Is there any way to refresh the image view on the window as I write the text and not on aButton
click event?
Try to handle the TextChanged
event for the TextBox
instead of handling the Click
event for the Button
:
<TextBox x:Name="SO" TextChanged="" ... />
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
String orderNum = SO.Text;
using (var stream = File.OpenRead(path))
{
order = (Bitmap)Bitmap.FromStream(stream);
}
using (order)
using (var graphics = Graphics.FromImage(order))
using (f)
{
graphics.DrawString(orderNum, f, System.Drawing.Brushes.White, order.Height / 2, order.Width / 2);
order.Save(path);
}
}
Note that the event handler will be invoked on each key press. If this is not desired for performance reasons, you might consider binding to a string
property and implement some delay as suggested here.
Upvotes: 1
Reputation: 2363
Just bind the Text
property of the TextBlock
to use the TextBox
's Text
.
Like so:
<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,5,22,472" Text="{Binding ElementName=SO, Path=Text, UpdateSourceTrigger=PropertyChanged}"/>
UPDATE
After the comments and the edited question.
You could place the TextBlock
after the Image
in a grid and then generate new image with all of the visuals included.
It would go something like this:
<Grid x:Name="imageToExport">
<Image Source ="/Resources/a4.jpg" Grid.Column="0" Margin="10,35,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="Some text here that will appear on top of the image"/><!-- The text property can use binding instead -->
</Grid>
Then you would save it as a jpeg, like this:
Image myImage = new Image();
FormattedText text = new FormattedText("ABC",
new CultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(this.FontFamily, FontStyles.Normal, FontWeights.Normal, new
FontStretch()),
this.FontSize,
this.Foreground);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawText(text, new Point(2, 2));
drawingContext.Close();
RenderTargetBitmap bmp = new RenderTargetBitmap(180, 180, 120, 96,
PixelFormats.Pbgra32);
bmp.Render(drawingVisual);//In here you could just pass the name of the grid "imageToExport"
myImage.Source = bmp;
NOTE
Please note the code for saving the visual is from MSDN
Upvotes: 1