Overlay bitmaps (writeablebitmap etc.) in windows store app - c#

I have 2 bitmaps (foreground and background) which I need to overlay on top of each other to form a new bitmap and use it as the ImageBrush for a button.
The code would look something like this (Windows 8.1 store app):
WriteableBitmap foregroundBitmap = GetForegroundBitmap();
WriteableBitmap backgroundBitmap = GetBackgroundBitmap();
ImageBrush imageBrush = new ImageBrush();
imageBrush.ImageSource = Overlay(foregroundBitmap, backgroundBitmap);
Button button = new Button();
button.Background = imageBrush;
How can I implement the Overlay(...) method above?
I tried:
backgroundBitmap.Blit(
new Rect(0, 0, backgroundBitmap.PixelWidth, backgroundBitmap.PixelHeight),
foregroundBitmap,
new Rect(0, 0, foregroundBitmap.PixelWidth, foregroundBitmap.PixelHeight),
WriteableBitmapExtensions.BlendMode.None);
but it didn't work (with BlendedMode None or Additive).
Thanks.

Try this
<Window.Resources>
<BitmapImage x:Key="image1" UriSource="DefaultImage.png"></BitmapImage>
<BitmapImage x:Key="image2" UriSource="ImageRoation.png"></BitmapImage>
</Window.Resources>
<Button Height="200" Width="200">
<Grid Height="200" Width="200">
<Grid.Background>
<ImageBrush ImageSource="{StaticResource image1}" Stretch="Fill" ></ImageBrush>
</Grid.Background>
<Grid Margin="5" Width="50" Height="50">
<Grid.Background>
<ImageBrush ImageSource="{StaticResource image2}" Stretch="Fill"></ImageBrush>
</Grid.Background>
</Grid>
</Grid>
</Button>

Related

WPF RenderTargetBitmap returns a black image

I have to "export" a UserControl as an image, I've tried to use RenderTargetBitmap, but this outputs a black image. I tried online solution, but I seem to be missing something.
Here is my code:
UserControl usage :
<uc:ImageStatusBar x:Name="OverlayPanel" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Stretch"/>
UserControl code :
<UserControl x:Class="ImageViewer.Controls.ImageStatusBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ImageViewer.Controls"
xmlns:uc="clr-namespace:ImageViewer.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid x:Name="StatusbarGrid" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="8*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StatusBar x:Name="LeftSideStaticStatusBar" Grid.Column="0">
<StatusBar.Background>
<SolidColorBrush Color="White" Opacity="0.5"/>
</StatusBar.Background>
<StatusBarItem x:Name="Logo" Height="42" Width="42" HorizontalAlignment="Right" Padding="6,0,0,0">
<Image x:Name="LogoImage"></Image>
</StatusBarItem>
</StatusBar>
<StatusBar x:Name="StatusBar" ItemsSource="{Binding}" Grid.Column="1" Padding="6,0,0,0">
<StatusBar.Background>
<SolidColorBrush Color="White" Opacity="0.5"/>
</StatusBar.Background>
<StatusBar.ItemTemplate>
<DataTemplate>
<Border BorderThickness="4 0 4 0">
<uc:StatusBarItem HorizontalAlignment="Left"/>
</Border>
</DataTemplate>
</StatusBar.ItemTemplate>
</StatusBar>
<StatusBar x:Name="RightSideStaticStatusBar" Grid.Column="2">
<StatusBar.Background>
<SolidColorBrush Color="White" Opacity="0.5"></SolidColorBrush>
</StatusBar.Background>
<StatusBarItem x:Name="IntensityBarItem" HorizontalAlignment="Right" HorizontalContentAlignment="Stretch" Width="128">
<uc:IntensityBar x:Name="IntensityBarControl" ViewModel="{Binding}"/>
</StatusBarItem>
<StatusBarItem x:Name="ScaleBarItem" HorizontalAlignment="Right" HorizontalContentAlignment="Stretch" Width="100">
<uc:ScaleBar x:Name="ScaleBarControl" ViewModel="{Binding}"></uc:ScaleBar>
</StatusBarItem>
</StatusBar>
</Grid>
</UserControl>
And the code to Generate the image. For now it's a double click on the the actual UC as I yet in the "design" part of the functionality.
private void OverlayPanel_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
RenderTargetBitmap bitmap =
new RenderTargetBitmap((int)OverlayPanel.ActualWidth,
(int)OverlayPanel.ActualHeight,
96, 96, PixelFormats.Pbgra32);
bitmap.Render(OverlayPanel);
int width = bitmap.PixelWidth;
int height = bitmap.PixelHeight;
int componentsPerPixel = 4;
int totalPixels = width * height;
int totalBytes = totalPixels * componentsPerPixel;
byte[] rgbValues = new byte[totalBytes];
var pixels = new byte[bitmap.PixelWidth * bitmap.PixelHeight];
bitmap.CopyPixels(rgbValues, bitmap.PixelWidth * bitmap.Format.BitsPerPixel / 8, 0);
using (FileStream stream = File.Create(#"D:\image3.png"))
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.QualityLevel = 90;
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream);
// If you want to export the xamDataChart to a PNG
// instead of JPEG, use this code block:
// PngBitmapEncoder encoder = new PngBitmapEncoder();
// encoder.Frames.Add(BitmapFrame.Create(bitmap));
// encoder.Save(stream);
}
}
What I am missing here? Is this the proper solution, should I try and focus on creating the image from "scratch" using the text in the component?
Two more things to mention:
uc:IntensityBar <-- it's an other image
uc:ScaleBar <-- is a grid with some lines.

Elements loaded via XamlReader() and from MainWindow.Xaml behave differently?

I have the following Viewbox in MainWindow.Xaml:
<Viewbox x:Name="R1C1Viewbox" Grid.Row="1" Grid.Column="2"
Grid.ColumnSpan="1" Grid.RowSpan="1">
<Border x:Name="R1C1Border" BorderBrush="White" CornerRadius="3"
BorderThickness="2" Background="White"
Height="40" Width="40" Margin="0,3,3,0">
<Grid x:Name="R1C1Grid">
<TextBlock x:Name="R1C1TextBlock1" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Arial" FontWeight="Bold" Text="+" FontSize="22"></TextBlock>
<Polygon x:Name="R1C1LED"
Points="0,0 15,0 0,15"
Stroke="#FFED1C24"
StrokeThickness="1">
<Polygon.Fill>
<RadialGradientBrush>
<GradientStop Color="White" Offset="2.5"/>
<GradientStop Color="Black"/>
</RadialGradientBrush>
</Polygon.Fill>
</Polygon>
<Button x:Name="R1C1Button" Background="Transparent"
BorderBrush="Transparent">
</Button>
</Grid>
</Border>
</Viewbox>
In my code behind, I define 2 RadialGradientBrushes for the Polygon.Fill property:
public static RadialGradientBrush ledOn = new RadialGradientBrush();
public static RadialGradientBrush ledOff = new RadialGradientBrush();
ledOn.GradientStops.Add(new GradientStop(Colors.Red, .8));
ledOn.GradientStops.Add(new GradientStop(Colors.White, 0));
ledOff.GradientStops.Add(new GradientStop(Colors.White, 2.5));
ledOff.GradientStops.Add(new GradientStop(Colors.Black, 0));
If I load the viewbox only from MainWindow.xaml, I can use:
R1C1LED.Fill = ledOn;
or
R1C1LED.Fill = ledOff;
and the fill changes as expected. If I load the exact same xaml from a file using XamlReader(), the Viewbox displays exactly as expected but using the code behind to change the fill as above doesn't change the fill and no errors are generated.
Example code:
private void OnTest(object sender, RoutedEventArgs e)
{
var xaml =
#"<Window
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'
mc:Ignorable='d'
Title='WPF App' Height='450' Width='800'>
<StackPanel Orientation='Vertical'>
<Button x:Name='R1C1LED' Content='Load Data' />
</StackPanel>
</Window>";
var win = (Window)XamlReader.Parse(xaml);
var button = (Button)win.FindName("R1C1LED");
button.Background = Brushes.Red;
button.Click += (obj, args) => { MessageBox.Show("Hi!"); };
win.Show();
}

Control not properly positioning programmatically

So im trying to place an Ellipse (named Dot) on a random location inside a grid.
But it only spawns on 1/4th (lower right) of the grid instead of the complete grid.
Example: When i put the margin of the Dot to Dot.Margin = new Thickness(0, 0, 0, 0); the Dot will spawn in the center of the screen. When i change it to Dot.Margin = new Thickness(200, 0, 0, 0); it will have a very small offset to the right but not even close to 200 pixels.
Outcome after creating alot of circles without removing them:
http://i.imgur.com/3XCMYyC.png
The red rectangle is the spawn area.
C#
//Gives Dot a position
public void placeDot()
{
//Give Dot random position
// The farthest left the dot can be
double minLeft = 0;
// The farthest right the dot can be without it going off the screen
double maxLeft = spawnArea.ActualWidth - Dot.Width;
// The farthest up the dot can be
double minTop = 0;
// The farthest down the dot can be without it going off the screen
double maxTop = spawnArea.ActualHeight - Dot.Height;
double left = RandomBetween(minLeft, maxLeft);
double top = RandomBetween(minTop, maxTop);
Dot.Margin = new Thickness(left, top, 0, 0);
}
//createEllipse method, used for creating new Dots
public void createEllipse()
{
spawnArea.Children.Remove(Dot);
//Create new Dot
DotImg.ImageSource =
new BitmapImage(new Uri(#"Images/hitcircle.png", UriKind.Relative));
Dot = new Ellipse() { Width = hitcircleSettingPath, Height = hitcircleSettingPath, Fill = DotImg, };
//Activates placeDot() method to give the Dot a random location
placeDot();
//Add Dot to the game area
spawnArea.Children.Add(Dot);
}
XAML This is the complete XAML i think there might be something wrong with the XAML but below is a shorter snippet where it does work how i want it but without the other stuff.
<Window x:Name="Grid" x:Class="ReactieSnelheid_Game.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:ReactieSnelheid_Game"
mc:Ignorable="d"
Title="Dot Program" Height="768" Width="1366" WindowStartupLocation="CenterScreen" Cursor="Pen" Icon="Images/icon.ico" ResizeMode="NoResize" WindowState="Maximized" WindowStyle="None" Background="Black" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="{x:Null}" KeyDown="Grid_KeyDown">
<Grid x:Name="backgroundImageGrid" Margin="0,0,0,0" MouseDown="LayoutRoot_MouseDown">
<Grid.Background>
<ImageBrush x:Name="backgroundBrush" ImageSource="Images/background.png" Opacity="0.25"/>
</Grid.Background>
<Grid x:Name="gameWrapper">
<Grid.Background>
<SolidColorBrush Color="Black" Opacity="0.25"/>
</Grid.Background>
<Label x:Name="reactionTime" Content="1000ms" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" FontSize="40" FontFamily="PMingLiU-ExtB" Foreground="White"/>
<Label x:Name="circleSize" Content="150x150" HorizontalAlignment="Left" Margin="10,73,0,0" VerticalAlignment="Top" FontSize="26.667" FontFamily="PMingLiU-ExtB" Foreground="White" Background="{x:Null}"/>
<Label x:Name="dotCount" Content="000000" HorizontalAlignment="Left" Margin="28,0,0,-1" Foreground="White" FontSize="80" RenderTransformOrigin="0.5,0.5" FontFamily="PMingLiU-ExtB" VerticalAlignment="Bottom" Background="{x:Null}">
<Label.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleX="-11.056"/>
<RotateTransform/>
<TranslateTransform X="-8.305"/>
</TransformGroup>
</Label.RenderTransform>
</Label>
<Label x:Name="scoreCount" Content="9999999999999999" Margin="0,0,10,10" Foreground="White" FontSize="80" FontFamily="PMingLiU-ExtB" HorizontalAlignment="Right" Height="106" VerticalAlignment="Bottom"/>
<Rectangle x:Name="startTimerBtn" RenderTransformOrigin="0.39,-0.75" Margin="144,10,0,0" Width="128" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" MouseDown="startTimerBtn_MouseDown">
<Rectangle.Fill>
<ImageBrush ImageSource="Images/starttimer.png"/>
</Rectangle.Fill>
</Rectangle>
<Grid x:Name="spawnArea" Margin="0,115,0,121" Background="Red"/>
</Grid>
<Grid x:Name="pauseScreen">
<Grid.Background>
<SolidColorBrush Color="#FF81D650" Opacity="0.25"/>
</Grid.Background>
<Grid x:Name="pauseScreenBtns" Margin="389,153,389,152" HorizontalAlignment="Center" VerticalAlignment="Center">
<Rectangle x:Name="Startbtn" Height="332" Width="332" MouseDown="Startbtn_MouseDown" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="129,0,127,76">
<Rectangle.Fill>
<ImageBrush ImageSource="Images/Start.png"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="settingsBtn" MouseDown="settingsBtn_MouseDown" Margin="-5,189,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="129" Height="63">
<Rectangle.Fill>
<ImageBrush ImageSource="Images/settings.png"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="resetBtn" MouseDown="resetBtn_MouseDown" Margin="0,190,-6,0" Width="128" Height="62" HorizontalAlignment="Right" VerticalAlignment="Top">
<Rectangle.Fill>
<ImageBrush ImageSource="Images/reset.png"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="quitBtn" RenderTransformOrigin="0.39,-0.75" Margin="232,399,0,0" Width="129" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" MouseDown="quitBtn_MouseDown">
<Rectangle.Fill>
<ImageBrush ImageSource="Images/quit.png"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Grid>
</Grid>
</Window>
Shorter XAML
<Window x:Class="TESTPROJECTEN.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:TESTPROJECTEN"
mc:Ignorable="d"
Title="MainWindow" Height="768" Width="1366">
<Grid x:Name="gameWrapper">
<Grid x:Name="spawnArea"/>
</Grid>
</Window>
Ellipse has Alignment = Stretch by default. But you set a fixed Width and Height so it looks like ellipse is centered. Try set location relative to top left corner
Dot = new Ellipse() { Width = hitcircleSettingPath, Height = hitcircleSettingPath, Fill = DotImg, };
Dot.HorizontalAlignment = HorizontalAlignment.Left;
Dot.VerticalAlignment = VerticalAlignment.Top;
it will have a very small offset to the right but not even close to
200 pixels.
First of all, as far as I remember, WPF doesn't use those numbers as pixels, but as some internal values. I can't remember the name of those units, but bottom line, they are not pixels.
Now for your actual problem:
Wpf grid places all his child controls by default in the center, so when you are putting the ellipse inside the grid and set a margin 200, it sets the margin from the center.
With that in mind, you can change your random algorithm to make the bubbles appear all over the grid:
//Gives Dot a position
public void placeDot()
{
//Give Dot random position
double halfSide = (spawnArea.ActualWidth - Dot.Width) / 2;
// The farthest left the dot can be
double minLeft = -(halfSide - (Dot.ActualWidth / 2));
// The farthest right the dot can be without it going off the screen
double maxLeft = halfSide - (Dot.ActualWidth / 2);
// The farthest up the dot can be
double minTop = -(halfSide - (Dot.ActualHeight / 2));
// The farthest down the dot can be without it going off the screen
double maxTop = halfSide - (Dot.ActualHeight / 2);
double left = RandomBetween(minLeft, maxLeft);
double top = RandomBetween(minTop, maxTop);
Dot.Margin = new Thickness(left, top, 0, 0);
}
I hope I didn't miss anything. I didn't run this code, so it might need adjustments, but this is the main line to follow.
Happy Coding! :)

WPF inkcanvas background image resize

before i add label on ink canvas image look like this
elhard = new Ellipse();
elhard.Height = 5;
elhard.Width = 5;
elhard.Fill = Brushes.DarkOrange;
InkCanvas.SetLeft(elhard, Mouse.GetPosition(inkcanvas).X);
InkCanvas.SetTop(elhard, Mouse.GetPosition(inkcanvas).Y);
inkcanvas.Children.Add(elhard);
lblhard = new System.Windows.Controls.Label();
lblhard.FontSize = 25;
lblhard.Content = hard_tisue[hardinc];
lblhard.Foreground = new SolidColorBrush(System.Windows.Media.Colors.DarkMagenta);
InkCanvas.SetLeft(lblhard, Mouse.GetPosition(inkcanvas).X);
InkCanvas.SetTop(lblhard, Mouse.GetPosition(inkcanvas).Y);
inkcanvas.Children.Add(lblhard);
//this is my xml
<InkCanvas x:Name="inkcanvas" ResizeEnabled="False" EditingModeInverted="None" Cursor="Pen" MouseMove="inkcanvas_MouseMove" MouseDown="inkcanvas_MouseDown" MouseRightButtonDown="inkcanvas_MouseRightButtonDown" MouseLeave="inkcanvas_MouseLeave" MoveEnabled="False" UseLayoutRounding="False" ClipToBounds="False" ScrollViewer.HorizontalScrollBarVisibility="Visible" >
<InkCanvas.Background >
<ImageBrush Stretch="None" />
</InkCanvas.Background>
</InkCanvas>
<!--<Image Name="inkcanvas_image" Height="{Binding ActualHeight, ElementName=border}" Width="{Binding ActualWidth,ElementName=border}" Stretch="Fill" Margin="1,1,1,1" />-->
</Border>
this is how background image in ink canvas moves to left side how to prevent image from moving

Create 2 tabs dynamically with different contents wpf

The following code creates 2 tabs on the click of a button, but does not display any content. I'm still learning this and want to know what the mistake is.
Code behind
public void button2_Click(object sender, RoutedEventArgs e)
{
popUp1.IsOpen = false;
Canvas canvas4 = new Canvas();
ScrollViewer viewer4 = new ScrollViewer();
viewer4.Content = canvas4;
string txtfl = File.ReadAllText(textBox1.Text);
TextBlock txbl1 = new TextBlock();
txbl1.Text = txtfl;
canvas4.Children.Add(txbl1);
TabItem newTab1 = new TabItem();
newTab1.Header = "Text File";
newTab1.Content = viewer4;
tabctrl1.Items.Add(newTab1);
tabctrl1.SelectedItem = newTab1;
Brush br = new SolidColorBrush(Colors.White);
Canvas canvas2 = new Canvas();
canvas2.Background = br;
ScrollViewer viewer2 = new ScrollViewer();
viewer2.Content = canvas2;
TabItem newTab2 = new TabItem();
newTab2.Header = "Test";
newTab2.Content = viewer2;
tabctrl1.Items.Add(newTab2);
}
TabControl is created using XAML
XAML
<Window ... >
<Grid>
<Popup Name="popUp1" Width="500" Height="300" Placement="Center" IsEnabled="False" IsOpen="False">
<Canvas x:Name="myCanvas1" Width="500" Height="300" Visibility="Visible">
<Button Content="Button" Height="38" HorizontalAlignment="Left" Margin="12,71,0,0" Name="button1" VerticalAlignment="Top" Width="151" Click="button2_Click" />
</Canvas>
</Popup>
<TabControl Name="tabctrl1" Width="1345" Height="28" Margin="0,24,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="2">
<TabControl.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FF3A60AD" Offset="0.528"/>
<GradientStop Color="#FF6A85D8" Offset="0.01"/>
</LinearGradientBrush>
</TabControl.Background>
</TabControl>
</Grid>
</Window>
Hi the reason your code does not appear to work is because the Height of the tab control is set to 28.
Try changing it to 280, you should then be able to see the content.
<TabControl Name="tabctrl1" Width="1345" Height="280" Margin="0,24,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="2">

Categories