C# WPF element position not in correct place - c#

I'm developing a vision processing application using WPF and EmguCV 3.0. My issue is that the element isn't positioned correctly on-screen. I have viewed what the padding is, and it returns all sides as 0. The ImageBox element from Emgu, which is what I am using to display the images, is encapsulated in a Windows Forms Host control. I have two other ImageBox elements, which display properly. Each of the ImageBox elements are within their own tab in a TabControl. On startup, I set the width and height properties of all the ImageBoxes and their canvases.
An additional thing to note is that the other two ImageBoxes also overflow out of their boundaries, but are reset back into the boundaries after switching back and forth between the tabs. This only happens once.
Here is a link to screenshots of what the UI looks like. http://imgur.com/a/RwG17
Additionally, here is the XAML and C# code for the ImageBoxes.
<TabItem x:Name="ImageTabControlHSV">
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="HSV" />
</StackPanel>
</TabItem.Header>
<Canvas x:Name="HSVImageCanvas">
<WindowsFormsHost>
<emui:ImageBox x:Name="HSVImageBox"/>
</WindowsFormsHost>
</Canvas>
</TabItem>
//Width and height properties are gotten from camera image.
HSVImageBox.Width = ratioWidth;
HSVImageBox.Height = ratioHeight;
HSVImageCanvas.Width = width;
HSVImageCanvas.Height = height;
HSVImageCanvas.MaxHeight = height;
HSVImageCanvas.MaxWidth = width;
Any help or suggestions would be greatly appreciated.
UPDATE: Putting a counter for how many times the problematic ImageBox has been selected and using Canvas.SetTop() and Canvas.SetLeft() seems to be a workaround. I would still like to know why the canvas is changing its position.

You might try performing a Canvas.SetTop(HSVImageCanvas, HSVImageCanvas.Top) and Canvas.SetLeft(HSVImageCanvas, HSVImageCanvas.Left).
Doug

Related

Wrong images loaded

I was developing an UWP app. I am using UWP "Image" control to show images in my app. All images are loaded properly most of the time. But occasionally few images not loading properly. Sometimes it is loaded in cropped version and sometimes loaded a black box which is never set from app. My code to set image:
XAML:
<Image x:Name="FavoritePen"
Source="{Binding FavPenSource, Mode=OneWay}"
Height="44"
Width="44"
Margin="0,10,10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"/>
CS:
private string favPenSource =
"ms-appx:///Assets/Images/NoteList/ic_main_tb_favorite_on.svg";
public string FavPenSource
{
get
{
return favPenSource;
}
set
{
SetProperty(ref favPenSource, value);
}
}
Black box loaded:
Wrong image loaded with cropped version:
Additionally, this is a very rare case, may be 1/100 frequency.
I googled and tried many solutions but it didn't help. I found that some people faced same issue but didn't find a proper solution yet. (Issue_1 , Issue_2, Issue_3 , Issue_4)
Can anyone please help me to solve the issue!!
Add View Box element, This is the x, y coordinates of the image inside the element along with the height and width. The default size is 300×150 size. Since I do not see the full container source, check if the SVG element is not beyond the parent container. You can remove the Horizontal/Vertical Alignment.
Sometimes it is loaded in cropped version and sometimes loaded a black box which is never set from app. My code to set image:
The problem is the svg file has been specified height and width property, when you render them with fix size image control, the svg content will display beyond the bound.
For this problem, please edit svg content and set it's height and width property as auto
<svg width="auto" height="auto" viewBox="0 0 469 476" version="1.1" xmlns="http://www.w3.org/2000/svg">

How to continue scaling the image visually?

I have a ScrollViewer with Image in it. I attached listener to MouseWheel event so I could zoom in/out the image. The code looks like this:
private void ImageMouseWheel(object sender, MouseWheelEventArgs e)
{
Matrix matrix = image.LayoutTransform.Value;
if (e.Delta > 0)
matrix.ScaleAt(1.5, 1.5, e.GetPosition(image).X, e.GetPosition(image).Y);
else
matrix.ScaleAt(1.0 / 1.5, 1.0 / 1.5, e.GetPosition(image).X, e.GetPosition(image).Y);
image.LayoutTransform = new MatrixTransform(matrix);
}
It pretty much works, but it has odd quirk -- when the image is so zoomed out that is at state "fit to parent" visually I cannot it zoom out more (visually), but the matrix is scaled still.
This is bad in sense that any computation after this point is wrong, and also it has strange effect in UI, say user starts from "fit to parent" zoom:
zoom out --> visually no change, internally matrix is zoomed out
zoom in --> surprise, visually no change, internally matrix is zoomed in
zoom in --> visually zoom in, matrix is also changed (OK)
Because of those problems I would like either to continue zooming out visually in order to keep both things (internal and visual) in sync.
How to achieve this?
Xaml:
<DockPanel>
<ScrollViewer Name="imageScrollViewer" Grid.Column="1" MouseWheel="ImageMouseWheel"
CanContentScroll="true" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Image MouseWheel="ImageMouseWheel" Name="image" Source="{Binding Path=Bitmap}"
MouseMove="Image_MouseMove"></Image>
</ScrollViewer>
</DockPanel>
Update: Originally I asked how to continue scaling visually or stop internally, but I found out that the last step of zooming out, when the image hits the state "fit to parent" is already out of sync internally-visually. For example position of the mouse is not correctly decoded above such image when moving the mouse around. Only when I zoom in a little the positions are correct. So the only way I see is to scale it visually correctly.
Hmm, I am tempted to delete this embarrassing question, but on the other hand maybe someone will have the same problem in future.
The problem is image is zoomed out, but later the dock panel zoom it in back. The image does not know about it so the math goes astray. The solution is to add some container which does not do additional scaling on itself, like stack panel.
Thus the solution lies in xaml:
<DockPanel>
<StackPanel>
...
</StackPanel>
</DockPanel>

How are the semi-transparent blur windows in OSX and W10 Start Menu created?

I'm currently working on a window that focuses on some elements on screen while blurring the rest of the area.
Using common methods like the WindowCompositionAttribute and the others are not suitable for this situation as there are limitations to it and it doesn't meet the standards regarding the intensity of the blur, contrast and colors which should be strict.
What i have managed to solve my problem was building an image stream with a light image encoder to enhance performance but then that wasn't enough. So, i thought of writing a motion detection algorithm to only steam when there's motion, but it still didn't change the performance drops.
What i need is something like those of the native OSX windows and Windows 10 Start Menu, so how are they created and run efficiently without any heavy load on the performance?
To create a new Window from scratch you have to set WindowsStyle to none (AllowTransparency="True" can be set only along with WindowsStyle="None") and from there build the style of the window.
However, you will face several issues if you follow this approach:
-no buttons (minimize, close)
-no support for fullscreen (taskbar issues)
I would suggest you to have a base view and include the other views inside the main view(which has the blur effect).
The blur effect could be obtained easily by doing something like below:
<Grid>
<Grid Margin="5" Background="#FF3782DC">
<!--<Grid.Background>
<Image Source="test.png"></Image>
</Grid.Background>-->
<Grid.Effect>
<BlurEffect Radius="100" />
</Grid.Effect>
</Grid>
<TextBlock
x:Name="textBlock"
Height="61"
Margin="136,82,211,0"
VerticalAlignment="Top"
Text="test"
TextWrapping="Wrap" />
</Grid>
I've set a color for the background, but you could set an image as background and by default it would be blurred (here you should set a binding and every time the view changes, you have to take a snapshot of the screen and set the source of the Image). However you will probably have some performance issues, but with a good encoder (JPEGencoder) it will be fast enough.
Hope that helps you!

how to stretch/resize svgs in uwp's xaml?

Since the creators update came out, uwp can use svg images as briefly explained here (minute 3).
I have this svg (48x48) and i can use it fine, if (and only if) i set the image's width&height to 48 and the strech to none:
<Image Source="ms-appx:///Assets//check.svg" Height="48" Width="48" Stretch="None"/>
If i set the stretch to fill, the image disappears. If i increase the width and height i can see that the icon is pinned to the upper left corner of the image (screenshot with a different svg but same size). Isn't Stretch=Fill and a fixed height/width the intended way to scale an image?
It looks to my as if the stretching algorithm does not grasp that my svg is supposed to be 48x48. Am i doing it wrong, or are there workarounds?
Okay, so here is how I solved this!
YouTube Video for this!
Open the SVG file
The SVG file Width and Height - set these to auto!
I've been having the same issue all morning and was about to completely give up on Svg support, seems mad that you can't get a scalable format to scale properly...
But, I had one more go and I think I've worked this out.
It seems that you need to tell the SvgImageSource to rasterize at the SVG's original design size and then get the Image to scale it. Not sure it's a particularly helpful approach, but certainly solves it as of build 15063.
<Image Width="24" Stretch="Uniform" VerticalAlignment="Center">
<Image.Source>
<SvgImageSource UriSource="ms-appx:///Assets/salesorder.folder.plain.svg"
RasterizePixelHeight="48"
RasterizePixelWidth="48" />
</Image.Source>
</Image>
So if the SVG was 48x48 we turn it into a bitmap at 48x48 using the RasterizePixelHeight and RasterizePixelWidth values and then the image scales that to 24x24.
Hope that helps.
Update
I just re-read your question and realised that you were looking to increase the scale whereas I've been working to decrease it. Looks as though the technique still works, but as you scale up you're going to lose any sharpness of image due to the bitmap scale process. I think this points to a fundamental flaw in the current implementation. They seem to be rendering the svg as a bitmap, and we have to tell it the original size to get it to render properly, and then they allow the bitmap code to do the rest of the work.
I think it's somewhat debateable whether this is true support or an odd half way house. Somewhere someone suggested that Adobe Illustrator can generate XAML paths, I think I'm going to look at that to see whether I can get a better quality output, shame though because I really like Inkscape :-(
For me, it worked with modifying SVG file like this:
Add appropriate preserveAspectRatio property to svg tag. For me it was "xMinYMin meet".
Set viewbox property of svg tag to this template "0 0 ActualHeight ActualWidth", in my case it was "0 0 1050 805".
Set height and width of svg tag to "auto".
Now svg element is relative to Height, Width and Stretch properties you provide in your XAML page or view.
It might be needed to rebuild the project for XAML Designer to take effect.
SVG File:
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 1050 805" width="auto" height="auto" ... > ... </svg>
XAML File:
<Image
Width="200"
Source="ms-appx:///Assets/Photos/Illustrations/sample.svg"
Stretch="UniformToFill" />
For me it works only if you set RasterizePixelHeight and RasterizePixelWidth to the svg original resolution (e.g. document properties in Inkscape).
For me it worked without setting those Properties, but adding preserveAspectRatio="xMinYMin" to the <svg ...> tag and deleting width and height from the <svg ...> tag.

How do you get the REAL position of objects in silverlight?

How do you get the REAL position of objects in silverlight?
I have a header image centered on the screen. When I make the browser window smaller, obviously, the header's left side goes off the screen. Finding out the actual position is good to know if you want to position objects on top of the image.
I capture the Content_Resized and I run a little test:
if (App.Current.Host.Content.ActualWidth > header.Width)
{
TEST = Canvas.GetLeft(header);
}
else
{
TEST = Canvas.GetLeft(header);
}
TEST always returns zero.
EDIT: header sits on a grid instead of a canvas. "Well, there is your problem..." So a better question might be this. How would I get the margins of an image sitting on a grid?
I probably should just answer the question but how to find the position of an element relative to another is probably something that has been answered before (by myself and others) here and elsewhere on the tinternet.
However if your goal is to place an item over an image then place the image in a Grid and then add the item as child of the Grid. That way you assign the relative position over the image as the margin of the item and let Silverlight's layout system do the rest.
As a general rule if you feel that you need to write code to move stuff about when the size of things change then unless you are writing a custom panel or something you're probably not using Silverlight layout system properly.
Edit:
Try this experiment:-
<Grid x:Name="LayoutRoot">
<Grid x:Name="headerContainer" Margin="50, 60, 0, 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image Source="YourLargeImage" />
<Image Source="YourSmallerImage" HorizontalAlignment="Center" VerticalAlignment="Top" />
</Grid>
</Grid>
Now try changing the inner grid's Margin to move its position around the screen. Note the smaller image always remains at the top center of the large image.
I got it working.
First of all, these images are on a grid, not a canvas. But switching the grid to a canvas caused lots of other problems one of which is that I could not have the header image centered like before.
The solution was to change the margin of the smaller image sitting on top of the larger header image when the content resized like this:
blankbarimage.Margin = new Thickness((App.Current.Host.Content.ActualWidth - header.Width) / 2, 0, 0, 0);
and, by the way, you create a content resized method like this:
App.Current.Host.Content.Resized += new EventHandler(Content_Resized);
So, to answer my own question, the way you get the REAL position of object in silverlight is (if they are on a grid) by looking at their margin settings.

Categories