Why window smaller than actualwidth? - c#

I want capture window but The actual window size seems to be smaller than the figure.
this is code
<Window x:Class="FileRead.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="620" Height="340" >
<Grid>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="ReadImageButton" Width="100" Height="30" Margin="10" Click="ReadImage_Click">
LoadImage
</Button>
<Button x:Name="ReadTextButton" Width="100" Height="30" Margin="10" Click="ReadText_Click">
LoadText
</Button>
<Button x:Name="CaptueScreenButton" Width="80" Height="30" Margin="10" Click="CaptueScreenButton_Click">
ScreenCapture
</Button>
<Button x:Name="CaptuerWindowButton" Width="80" Height="30" Margin="10" Click="CaptuerWindowButton_Click">
WindowCapture
</Button>
I couldn't find a problem.
private void CaptuerWindowButton_Click(object sender, RoutedEventArgs e)
{
int width = (int)this.ActualWidth;
int height = (int)this.ActualHeight;
Point point = this.PointToScreen(new Point(0, 0));
CheckLable.Content = string.Format("{0} / {1}", this.Width, this.ActualWidth);
using (Bitmap bmp = new Bitmap(width, height))
{
using (Graphics gr = Graphics.FromImage(bmp))
{
gr.CopyFromScreen( (int)point.X, (int)this.Top, 0, 0, bmp.Size);
}
bmp.Save(ImagePath + "/WindowCapture.png", ImageFormat.Png);
}
}
result image
There is always a difference of about 15 points.:
help me please.
enter image description here

The cause of your problem is that size of a window include the area that draw by OS, which was called "non-client area", usually include frame, border, drop show effect. And your calculation didn't consider that. The right code will like
var clientTopLeft = this.PointToScreen(new System.Windows.Point(0, 0));
// calculate the drop show effect offset.
var shadowOffset = SystemParameters.DropShadow ? clientTopLeft.X - Left -
((WindowStyle == WindowStyle.None && ResizeMode < ResizeMode.CanResize) ? 0 : SystemParameters.BorderWidth) : 0;
// exclude left and right drop shadow area
int width = (int)(Width - 2 * shadowOffset);
// exclude bottom drop shadow area
int height = (int)(Height - shadowOffset);
using (Bitmap bmp = new Bitmap(width, height))
{
using (Graphics gr = Graphics.FromImage(bmp))
{
gr.CopyFromScreen((int)(Left + shadowOffset),
(int)Top, 0, 0, bmp.Size);
}
bmp.Save("WindowCapture.png");
}

Related

WPF disable anti-aliasing of Text when using RenderTargetBitmap at other than 96 DPI

after hours of trial and error I need your help!
I am attempting to create a image files that represents WPF controls, but I need all text/graphics to be Aliased (i.e. not Anti-Aliased). I need the image to be created with a DPI higher than the default of 96.0 as the text quality is insufficient for my need at that level.
Whenever I render the image using RenderTargetBitmap using a DPI other than 96.0 then the Text is anti-aliased and I am not able to prevent it. Rendering at 96.0 DPI the text is not anti-aliased and displays correctly - but not at a sufficient quality level.
The rendering code:
namespace TestRenderBitmap
{
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
public partial class RenderTargetBitmapTestWindow
{
public RenderTargetBitmapTestWindow()
{
InitializeComponent();
}
private void cmdRender_Click(object sender, RoutedEventArgs e)
{
var requiredDpi = 96.0;
SaveToPngStream(controlToRender, requiredDpi);
}
public void SaveToPngStream(FrameworkElement control, double targetDpi)
{
var encoder = EncodeControlToImage(control, targetDpi);
using (var filestream = new FileStream("output.png", FileMode.Create))
encoder.Save(filestream);
}
private BitmapEncoder EncodeControlToImage(FrameworkElement control, double targetDpi)
{
var bmp = GetBitmapFromControl(control, targetDpi);
var encoder = new PngBitmapEncoder { Interlace = PngInterlaceOption.Off };
encoder.Frames.Add(BitmapFrame.Create(bmp));
return encoder;
}
private RenderTargetBitmap GetBitmapFromControl(FrameworkElement control, double targetDpi)
{
const double screenDpi = 96d;
var height = control.ActualHeight;
var width = control.ActualWidth;
var dv = new DrawingVisual();
using (var ctx = dv.RenderOpen())
{
var br = new VisualBrush { Visual = control };
ctx.DrawRectangle(br, null, new Rect(0, 0, width, height));
}
var bmp = new RenderTargetBitmap((int)(width / screenDpi * targetDpi), (int)(height / screenDpi * targetDpi),
targetDpi, targetDpi, PixelFormats.Default);
bmp.Render(dv);
return bmp;
}
}
}
The XAML code for this is:
<Grid>
<Grid TextOptions.TextRenderingMode="Aliased" TextOptions.TextFormattingMode="Display" x:Name="controlToRender" HorizontalAlignment="Left" VerticalAlignment="Top" Background="White">
<TextBlock VerticalAlignment="Center" TextWrapping="Wrap" HorizontalAlignment="Center" FontSize="10.667" FontFamily="Arial" Margin="33,41,55,56" Text="Hello World" />
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="100" Margin="22,26,0,0" VerticalAlignment="Top" Width="107"/>
</Grid>
<Button x:Name="cmdRender" Content="Render" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="75" Click="cmdRender_Click" Margin="0,0,10,10" />
</Grid>
at 96.0 DPI I get an image (zoomed) that looks like this:
96DPI Image
at 192DPI this image looks like this:192DPI Image

Image control and Image resizing when Stretch is set to Uniform

I have this peculiar problem. I am having a user control . I am making an app for Windows 8.1 where I would choose an image from my Picture gallery. The image would open in my app with Stretch is Uniform and Horizontal And vertical alignment to center.
My user control will appear where I tap on the image. Now the problem is , when the image Stretch was none , I was able to magnify the correct region (around my click) , but now when I make it Stretch to Uniform and Set the horizontal and vertical Alignment to Center , I am getting other pixel information in my user control.
I want to know how to fix it.Any how , the images can be of 2*Full HD also or they can be HD or even less.
Secondly , I want to know the boundaries of the image . With boundaries I want to say that , my user control shouldnt go above the boundaries of the image .
How to implement that. If my code is needed , I would paste it , If required.
Have this video for reference . This is what I have to develop ! I have the user control ready and I am getting exact pixels for Stretch=NONE , and no Horizontal And Vertical Alignment set.
This is my code for my app
I believe the issue is with how you use the control, rather than the image. If you avoid doing the bitmap cropping and replacing, it would speed up dramatically and likely work for all stretch types.
I've modified the source to show this - removing the Cropping completely. If you need cropping for other reasons, you should consider using the unsafe keyword (and property setting to allow) in order to dramatically speed up its use.
Also, to avoid the lagging/jumping upward, I added IsHitTestVisible="False" so that your delta wouldn't be interrupted by hovering over your image.
I see you have the 45-degree code already - since it wasn't in your source, I only added an example of 90 degree rotation when you get to the sides - so you can see how to set a RenderTransformOrigin point.
MainPage.xaml:
<Page x:Name="page1"
x:Class="controlMagnifier.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:controlMagnifier"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="ParentGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" PointerReleased="ParentGrid_OnPointerReleased" >
<Canvas x:Name="InkPresenter" Height="auto" Width="auto">
<Image Stretch="Uniform" x:Name="image2" >
<Image.Source >
<BitmapImage UriSource="/Assets/wallpaper.jpg" />
</Image.Source>
</Image>
</Canvas>
<local:MagnifierUsercontrol x:Name="MagnifyTip" Visibility="Collapsed" ManipulationMode="All"
IsHitTestVisible="False" Height="227" Width="171"
VerticalContentAlignment="Bottom" HorizontalContentAlignment="Center">
</local:MagnifierUsercontrol>
</Grid>
</Page>
MainPage.xaml.cs:
using System;
using Windows.Foundation;
using Windows.Storage;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
namespace controlMagnifier
{
public sealed partial class MainPage : Page
{
public const int XAxis = 200;
public const int YAxis = 435;
private readonly RotateTransform myRotateTransform = new RotateTransform {CenterX = 0.5, CenterY = 1};
private readonly ScaleTransform myScaleTransform = new ScaleTransform {ScaleX = 1, ScaleY = 1};
private readonly TransformGroup myTransformGroup = new TransformGroup();
private readonly TranslateTransform myTranslateTransform = new TranslateTransform();
public WriteableBitmap CurrentBitmapObj, CurrentCroppedImage = null;
public Point currentContactPt, GridPoint;
public Thickness margin;
public PointerPoint pt;
public double xValue, yValue;
public MainPage()
{
InitializeComponent();
ParentGrid.Holding += Grid_Holding;
image2.PointerMoved += InkCanvas_PointerMoved;
image2.PointerReleased += ParentGrid_OnPointerReleased;
margin = MagnifyTip.Margin;
image2.CacheMode = new BitmapCache();
myTransformGroup.Children.Add(myScaleTransform);
myTransformGroup.Children.Add(myRotateTransform);
myTransformGroup.Children.Add(myTranslateTransform);
MagnifyTip.RenderTransformOrigin = new Point(0.5, 1);
MagnifyTip.RenderTransform = myTransformGroup;
}
private void Grid_Holding(object sender, HoldingRoutedEventArgs e)
{
try
{
GridPoint = e.GetPosition(image2);
myTranslateTransform.X = xValue - XAxis;
myTranslateTransform.Y = yValue - YAxis;
MagnifyTip.RenderTransform = myTransformGroup;
MagnifyTip.Visibility = Visibility.Visible;
}
catch (Exception)
{
throw;
}
}
private void InkCanvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
try
{
pt = e.GetCurrentPoint(image2);
currentContactPt = pt.Position;
xValue = currentContactPt.X;
yValue = currentContactPt.Y;
if (xValue > 300)
{
myRotateTransform.Angle = -90;
}
else if (xValue < 100)
{
myRotateTransform.Angle = 90;
}
else
{
myRotateTransform.Angle = 0;
}
MagnifyTip.RenderTransform = myRotateTransform;
myTranslateTransform.X = xValue - XAxis;
myTranslateTransform.Y = yValue - YAxis;
MagnifyTip.RenderTransform = myTransformGroup;
}
catch (Exception)
{
throw;
}
finally
{
e.Handled = true;
}
}
private async void StoreCrrentImage()
{
try
{
var storageFile =
await
StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/wallpaper.jpg",
UriKind.RelativeOrAbsolute));
using (
var fileStream =
await storageFile.OpenAsync(FileAccessMode.Read))
{
var bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
var writeableBitmap =
new WriteableBitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
fileStream.Seek(0);
await writeableBitmap.SetSourceAsync(fileStream);
CurrentBitmapObj = writeableBitmap;
writeableBitmap.Invalidate();
}
}
catch (Exception)
{
// Graphics g=new Graphics();
throw;
}
finally
{
}
}
private void ParentGrid_OnPointerReleased(object sender, PointerRoutedEventArgs e)
{
MagnifyTip.Visibility = Visibility.Collapsed;
}
}
}
MagnifierUsercontrol.xaml:
<UserControl
x:Class="controlMagnifier.MagnifierUsercontrol"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:controlMagnifier"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Height="227" Width="171">
<Canvas x:Name="controlCanvas" x:FieldModifier="public" Height="Auto" Width="Auto" >
<Grid Height="227" Width="171" HorizontalAlignment="Center" Canvas.Left="0" Canvas.Top="0">
<Border x:FieldModifier="public" x:Name="imgBorder" Width="150" CornerRadius="50,50,50,50" Margin="13,25,13,97">
<Border.Background>
<ImageBrush x:FieldModifier="public" x:Name="image1" />
</Border.Background>
</Border>
<TextBlock x:Name="txtreading" Height="30" Width="80" Margin="0,-145,0,0" FontWeight="Bold" Foreground="Red" FontSize="20" Text="ABC" TextAlignment="Center" />
<!--<Image Height="120" Width="150" Margin="0,-50,0,0" Source="Assets/SmallLogo.scale-100.png" ></Image>-->
<Path x:Name="MagnifyTip" Data="M25.533,0C15.457,0,7.262,8.199,7.262,18.271c0,9.461,13.676,19.698,17.63,32.338 c0.085,0.273,0.34,0.459,0.626,0.457c0.287-0.004,0.538-0.192,0.619-0.467c3.836-12.951,17.666-22.856,17.667-32.33 C43.803,8.199,35.607,0,25.533,0z M25.533,32.131c-7.9,0-14.328-6.429-14.328-14.328c0-7.9,6.428-14.328,14.328-14.328 c7.898,0,14.327,6.428,14.327,14.328C39.86,25.702,33.431,32.131,25.533,32.131z" Fill="#FFF4F4F5" Stretch="Fill" Stroke="Black" UseLayoutRounding="False" Height="227" Width="171" />
</Grid>
</Canvas>
</UserControl>
Let me know if this helps or if there is further toward your specific question.

Writablebitmap Indexed8 writepixels

I try to change writablebitmap using writepixels() method, but it doesn't change any pixels.
it has following consructor
public void createWbm(int viewportW, int viewportH)
{
writeableBitmap = new WriteableBitmap(
viewportW,
viewportH,
96,
96,
PixelFormats.Indexed8,
new BitmapPalette(Form1.form1.getColors()));
i.Source = writeableBitmap;
}
and I use this method calling leftbuttondown event, but there is not any change. Is it necessary to use two loops(outer for row of pixels and inner for columns ) to paint every pixle or it is possible use just writepixels() method? thanks
void BrushPixel(MouseEventArgs e)
{
byte[] ColorData = { 0, 0, 0, 0 }; // B G R
Int32Rect rect = new Int32Rect(
(int)(e.GetPosition(i).X),
(int)(e.GetPosition(i).Y),
1,
1);
writeableBitmap.WritePixels( rect, ColorData, 4, 0);
}
You are incorrectly using it,
at this format (8-bit) your array ColorData either represents an 1x4, 4x1 or 2x2 pixels image.
therefore rect dimensions should match either of these sizes
Keep in mind that these are indices to colors in a palette, not BGR values as you've commented.
Here's a simple example :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var bitmap = new WriteableBitmap(100, 100, 96, 96, PixelFormats.Indexed8, BitmapPalettes.Halftone256);
int width = 50;
int height = 50;
var pixels = new byte[width*height];
var random = new Random();
random.NextBytes(pixels);
bitmap.WritePixels(new Int32Rect(0, 0, width, height), pixels, width, 0);
Image1.Source = bitmap;
}
}
XAML :
<Window x:Class="WpfApplication14.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350"
SnapsToDevicePixels="True"
UseLayoutRounding="True">
<Grid>
<Border HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="Black"
BorderThickness="1">
<Image x:Name="Image1" Stretch="None" />
</Border>
</Grid>
</Window>
Note : at this format stride parameter always equals width because a pixel length in bytes is 1.
I strongly suggest you to use WriteableBitmapEx instead, it makes WriteableBitmap manipulation way easier. Beware that it supports only PixelFormats.Pbgra32 but unless you really have a specific reason to use 8-bit I can only recommend it, it can draw many primitives such as lines, rectangles, circles etc ...

Save didnt work the drawing WinRT

The application is running all good but when i'll go to save is like the margin move the picture and the drawing i do move too. What i'm doing wrong or what i need to do to fix that. I think is a geometry problem.
Xaml Code:
<Page
x:Class="DrawingWithMe.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrawingWithMe"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Viewbox>
<Grid x:Name="Grid1" Height="768" Width="1366">
<Canvas x:Name="funnyCanvas" Background="White" Margin="162,10,254,42">
<Rectangle x:Name="Rectangle1" Fill="#FFF4F4F5" Stroke="Black"></Rectangle>
<Image x:Name="image" Source="Assets/Test.gif" Stretch="UniformToFill"/>
</Canvas>
</Grid>
</Viewbox>
<Page.BottomAppBar>
<AppBar x:Name="AppBar" Padding="10,0,10,0">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button Name="Save" Content="Save" VerticalAlignment="Top" Click="Save_Click_1" Grid.Column="1"></Button>
<Button Name="Erase" Content="Erase All" VerticalAlignment="Top" Click="Erase_Click_1" Grid.Column="2"></Button>
<Button x:Name="Copytoclipboard" Content="Copy To ClipBoard" VerticalAlignment="Top" Click="Copytoclipboard_Click_1"></Button>
<Button x:Name="Pastefrom" Content="Paste From ClipBoard" VerticalAlignment="Top" Click="Pastefrom_Click_1"></Button>
<Button x:Name="Recognizeword" Content="Recognize" VerticalAlignment="Top" Click="Recognizeword_Click_1"></Button>
</StackPanel>
</Grid>
</AppBar>
</Page.BottomAppBar>
</Page>
C# Code:
public async void TestingBlit()
{
var backgroundBmp = await BitmapFactory.New(1, 1).FromContent(new Uri(BaseUri, #"///Assets/Test.gif"));
//Image foreground
WriteableBitmap foregroundBmp;
using (InMemoryRandomAccessStream a = new InMemoryRandomAccessStream())
{
await _inkManager.SaveAsync(a);
a.Seek(0);
foregroundBmp = await new WriteableBitmap(1,1).FromStream(a);
}
// Combined
backgroundBmp.Blit(new Rect(0, 0, foregroundBmp.PixelWidth, foregroundBmp.PixelHeight), foregroundBmp,new Rect(0, 0, foregroundBmp.PixelWidth, foregroundBmp.PixelHeight), WriteableBitmapExtensions.BlendMode.ColorKeying);
// Save
Windows.Storage.Pickers.FileSavePicker save = new Windows.Storage.Pickers.FileSavePicker();
save.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
save.DefaultFileExtension = ".gif";
save.FileTypeChoices.Add("GIF", new string[] { ".gif" });
StorageFile filesave = await save.PickSaveFileAsync();
Guid encoderId = Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId;
await WinRTXamlToolkit.Imaging.WriteableBitmapSaveExtensions.SaveToFile(backgroundBmp, filesave, encoderId);
//List<InkStroke> tmp = _inkManager.GetStrokes().ToList();
//tmp.RemoveAt(0);
//RenderStroke(tmp.ElementAt(0), Colors.SkyBlue, 10, 1);
SurfaceImageSource surfaceImageSource = new SurfaceImageSource((int)Rectangle1.ActualWidth, (int)Rectangle1.ActualHeight, true);
ImageBrush brush = new ImageBrush();
brush.ImageSource = image.Source;
Rectangle1.Fill = brush;
}
private void RenderStroke(InkStroke stroke, Color color, double width, double opacity = 1)
{
// Each stroke might have more than one segments
var renderingStrokes = stroke.GetRenderingSegments();
//
// Set up the Path to insert the segments
var path = new Windows.UI.Xaml.Shapes.Path();
path.Data = new PathGeometry();
((PathGeometry)path.Data).Figures = new PathFigureCollection();
var pathFigure = new PathFigure();
pathFigure.StartPoint = renderingStrokes.First().Position;
((PathGeometry)path.Data).Figures.Add(pathFigure);
//
// Foreach segment, we add a BezierSegment
foreach (var renderStroke in renderingStrokes)
{
pathFigure.Segments.Add(new BezierSegment()
{
Point1 = renderStroke.BezierControlPoint1,
Point2 = renderStroke.BezierControlPoint2,
Point3 = renderStroke.Position
});
}
// Set the general options (i.e. Width and Color)
path.StrokeThickness = width;
path.Stroke = new SolidColorBrush(color);
// Opacity is used for highlighter
path.Opacity = opacity;
funnyCanvas.Children.Add(path);
}
}
}
You put the content in a Viewbox, which will stretch it. You need to calculate the on-screen coordinates of your rectangle.
Give this a try.
var scalex = MyViewbox.GetScaleChildX();
var scaley = MyViewbox.GetScaleChildY();
SurfaceImageSource surfaceImageSource = new SurfaceImageSource((int)(scalex * Rectangle1.ActualWidth), (int)(scaley * Rectangle1.ActualHeight), true);
public static double GetChildScaleX(this Viewbox viewbox)
{
if (viewbox.Child == null)
throw new InvalidOperationException("Can't tell effective scale of a Viewbox child for a Viewbox with no child.");
var fe = viewbox.Child as FrameworkElement;
if (fe == null)
throw new InvalidOperationException("Can't tell effective scale of a Viewbox child for a Viewbox with a child that is not a FrameworkElement.");
if (fe.ActualWidth == 0)
throw new InvalidOperationException("Can't tell effective scale of a Viewbox child for a Viewbox with a child that is not laid out.");
return viewbox.ActualWidth / fe.ActualWidth;
}
GetChildScaleY is the same, but with Heights (taken from here).
(Make sure you name your Viewbox)
<Viewbox x:Name="MyViewbox">

Using a rectangle to create a search region on an image

I have an Image viewer that displays an image. I want to draw a rectangle using the mouse over the image and get the x and y coordinates of the rectangle (X1, X2, Y1, and Y2). I will use these coordinates to create a search region and find the max and min values in an array that have the exact number of pixels as the image in both axes.
Can anyone guide me to a direction to start please?
You should use a canvas to display the image and draw a rectangle over it.
Example:
MainWindow.xaml:
<Window x:Class="CanvasRectangleSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Grid>
<Canvas x:Name="SampleImageCanvas"
MouseMove="SampleImageCanvas_MouseMove"
MouseDown="SampleImageCanvas_MouseDown"
Width="512" Height="389">
<Canvas.Background>
<!--Here you set the image to display -> You probably want to bind it to something. -->
<ImageBrush x:Name="SampleImage" Stretch="Uniform" ImageSource="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg">
</ImageBrush>
</Canvas.Background>
<!-- Here you draw whatever you want on the canvas. -->
<!-- You'll probably want to bind its width and height to something too. -->
<Rectangle x:Name="ROI" Stroke="#FFF1133E" Width="50" Height="50"/>
</Canvas>
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
namespace CanvasRectangleSample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
// Handling the redrawing of the rectangle according to mouse location
private void SampleImageCanvas_MouseMove(object sender, MouseEventArgs e)
{
//get mouse location relative to the canvas
Point pt = e.MouseDevice.GetPosition(sender as Canvas);
//here you set the rectangle loction relative to the canvas
Canvas.SetLeft(ROI, pt.X - (int)(ROI.Width / 2));
Canvas.SetTop(ROI, pt.Y - (int)(ROI.Height / 2));
}
private void SampleImageCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
//Here you should handle saving the rectangle location
//don't forget to calculate the proportion between Canvas's size and real Image's size.
}
}
}
If you want you can limit the rectangle relocation to the canvas area with an if expression checking if the canvas area containes the mouse locaion
Thanks for the pointers and help:
Here is my finished code and it works. You place the mouse anywhere on the canvas hold mouse down and drag to create the rectangle. It could use some more improvement to drag and create the rectangle in any direction.
XAML:
<Canvas Name="ImageCanvas"
MouseMove="ImageCanvas_MouseMove"
MouseDown="ImageCanvas_MouseDown"
Height="240" Width="320"
HorizontalAlignment="Left"
Margin="87,514,0,0" VerticalAlignment="Top" MouseLeftButtonUp="ImageCanvas_MouseLeftButtonUp">
<Canvas.Background>
<ImageBrush x:Name="Image" Stretch="Uniform" ImageSource="C:\image.bmp">
</ImageBrush>
</Canvas.Background>
<Rectangle x:Name="ROI" Stroke="#FFF1133E" Width="20" Height="20" Canvas.Left="155" Canvas.Top="115" />
</Canvas>
Code:
double topLeftX = 0;
double topLeftY = 0;
double bottomRightX = 0;
double bottomrigthY = 0;
bool setRect = false;
private void ImageCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
topLeftY = topLeftX = bottomrigthY = bottomRightX = 0;
setRect = true;
System.Windows.Point pt = e.MouseDevice.GetPosition(sender as Canvas);
topLeftX = pt.X; topLeftY = pt.Y;
}
private void ImageCanvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (setRect == true)
{
//get mouse location relative to the canvas
System.Windows.Point pt = e.MouseDevice.GetPosition(sender as Canvas);
Canvas.SetLeft(ROI, topLeftX);
Canvas.SetTop(ROI, topLeftY);
ROI.Width = System.Math.Abs((int)(pt.X - topLeftX));
ROI.Height = System.Math.Abs((int)(pt.Y - topLeftY));
commandReturnTB.Text = (Convert.ToString(pt.X) + "," + Convert.ToString(pt.Y))+"\n";
}
}
private void ImageCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
System.Windows.Point pt = e.MouseDevice.GetPosition(sender as Canvas);
bottomRightX = pt.X;
bottomrigthY = pt.Y;
ROI.Width = System.Math.Abs((int)(bottomRightX - topLeftX));
ROI.Height = System.Math.Abs((int)(bottomrigthY - topLeftY));
Canvas.SetLeft(ROI, topLeftX);
Canvas.SetTop(ROI, topLeftY);
setRect = false;
commandReturnTB.Text = topLeftX + "," + topLeftY + "--" + bottomRightX + "," + bottomrigthY;
}

Categories

Resources