Magnifing glass in WPF - wpf

How can I create a non-circular magnifying glass in WPF? This has to work on controls not just an image. Every example I find online is either circular only or only works on images.
For example I have a slider, and I'd like to turn the thumb into a rectangular magnifying region to show enlarged ticks (as my ticks are displayed in the Slider track itself, not below it). I have created all the styles necessary I am just missing the ability to magnify contents underneath the thumb (as the thumb sits on top of the controls / display)
<Slider Ticks="{Binding MyCollection}" />
Thanks

It's pretty easy to just make your own 'magnifying' control. You could use a VisualBrush with a Visual property taken from the source (that you want to magnify) painted onto a plain Rectangle. See the Using VisualBrush to Show a Magnifying Glass page on the Ian G on Tap website as an example.
Better yet, here is a very simple example of a VisualBrush that is painting a Rectangle in the right column of a Grid, magnifying an Image from the left column of a Grid. You can tweak it to your liking:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Name="Image" Source="Images/BlackLogo.ico" Width="150" Height="150" />
<Rectangle Grid.Column="1">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ., ElementName=Image}"
Viewport="50,100,300,300" ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
</Grid>

Related

Helix3d WPF draw text at the top/left of HelixViewport3D

I want to show some text information at the top/left of HelixViewport3D like "ShowCameraInfo" does, which display camera information at the bottom/left of the Viewport. BillboardTextVisual3D requires a 3D point, but what I want is just like TextBlock on Canvas, which just need a 2D coordinate.
I can use TextBlock, but it cannot be captured as part of HelixViewport3D.
Any idea?
Literally a Textblock placed over the HelixViewport3D should be what you need.
There is only one problem: Viewport will not recognize if you try to manipulate the camera by initiating the mouse click on the Stackpanel.
<Grid>
<hx:HelixViewport3D>
<hx:DefaultLights/>
<hx:CubeVisual3D SideLength="7"/>
<hx:CubeVisual3D SideLength="5" Fill="Red" Center="-5,3,0"/>
</hx:HelixViewport3D>
<StackPanel Margin="5" HorizontalAlignment="Left" VerticalAlignment="Top">
<StackPanel.Background>
<SolidColorBrush Color="#FFB6B6B6" Opacity="0.4"/>
</StackPanel.Background>
<TextBlock Text="asdhfasdvfmnas" Margin="5,2"/>
<TextBlock Text="mvcbnxcvjhbkdaf" Margin="5,2"/>
<TextBlock Text="vbkjsdvj" Margin="5,2"/>
</StackPanel>
</Grid>

Drawing dynamically positioned overlays on Images in wpf

I have an Image control in my view bound to BitmapSource prop in my View Model. This property is updated with images from a camera in my Model class. To get started with drawing shapes on images (so 1 control ON another),after
reading a similar post, I tried the following with a simple Rectangle
shape with Zindex=2 so it should act as an overlay over the image. But the
below doesn't work & all I see is the image from the camera
<Canvas>
<DockPanel Width="400" Height="250">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center"
Content="IMAGE FROM CAMERA" Width="Auto"/>
<Image x:Name="CamImageDisplay"
DockPanel.Dock="Left"
Source="{Binding CurrentImage, Mode=OneWay}"
Stretch="None" Width="Auto"/>
<Rectangle Width="10" Height="5"
Fill="CadetBlue"
Panel.ZIndex="2" />
</DockPanel>
</Canvas>
I come from an MFC background where drawing shapes on bitmaps was as
easy as calling Draw3dRect(...). Having said that, my goal is to draw
a collection of shapes (just rectangles & circles) that will have
different co ordinates with each new image.
Could some one please
explain in simple terms or point to some reference that will show how
I can achieve this. Yes, there are other similar questions, but they
are really not quite aligned with my objectives. Thank you & please ask for clarifications if I am unclear in how I have asked my question.

XAML- How to fix the position of an image relative to the right hand side of the display window?

I am developing an application for which the GUI is being written/ displayed using XAML. I have most of the desired elements displayed on the GUI at the moment, and am now working on the layout- positioning the various elements in particular places.
Most of the controls/ buttons, etc are aligned to the left, and stay 'bound' to the left hand side of the GUI even if I resize the window by dragging its left hand edge further to the left (the icons, etc move to stay their relative distance from the edge of the window).
However, I have one element which I want to align to the right, so that it will stay 'bound' to the right hand side of the GUI- if I resize the window by dragging its right hand edge further to the right, it should move to stay its relative distance from the edge of the window... at the moment, that element is staying at the position that I have drawn it (i.e. 900 pixels from the left), no matter what the size of the window is- so if I resize the width of the window to less than 900 pixels, that element cannot be seen.
The XAML markup I have used for the elements that I want bound to the left hand side of the GUI is, for example:
<Button Style="{DynamicResource NoChromeButton}" Click="backBtn_Click" Margin="0, 0, 0, 0" HorizontalAlignment="Left" >
<Image Source="C:\...\abc.png" Height="30" Width="40" />
</Button>
The XAML markup that I am trying to use for the element I want bound to the right hand side of the GUI is:
<Button Style="{DynamicResource NoChromeButton}" Click="referThis" Margin="0, 0, 0, 0" HorizontalAlignment="Right" >
<TextBlock>Button XYZ</TextBlock>
</Button>
However, setting the HorizontalAlignment to Right, doesn't actually move the text button to the right- it's still bound to the left hand side of the display... The only way I have found of moving it towards the right, is to set a large value for its 'x' position, i.e. Margin="900, 0, 0, 0", but then the position is not relative to the size of the window, so if I drag the right hand edge too far to the left, that button is outside the displayed area of the window, so I can't see it...
How I can I set the property of the button so that its position is relative to the right hand edge of the display window?
Edit
All of the elements in question are displayed inside the same <Grid> and <StackPanel> tags, i.e.
<StackPanel>
<Grid ...>
<Button ... HorizontalAlignment="Left">
</Button>
...
<Button ... HorizontalAlignment="Right">
</button>
...
</Grid>
...
</StackPanel>
The basic idea of the following solution is the Grid.
Create a ColumnDefinition with fixed width for each element you want aligned to the left, and a ColumnDefinition with fixed width for each element you want aligned to the right. On the middle, create a ColumnDefinition with a Width="*", so WPF first calculates the size of the other columns, based on their fixed length, and then it fills the remaining space with the middle-column.
Remember that each button has to set the Grid.Column property correctly to declare the column it wants to belong to.
As you resize the Window, the Grid updates its layout and the flexible children. In this case, the only flexible child is the middle-column.
Here's a simple implementation:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Margin" Value="10"/>
</Style>
</Grid.Resources>
<Button Grid.Column="0" Content="Button1Left"/>
<Button Grid.Column="1" Content="Button2Left"/>
<Button Grid.Column="3" Content="Button1Right"/>
<Button Grid.Column="4" Content="Button2Right"/>
</Grid>
For more complete tutorials about the Grid control, check this, this and this.
Notice that I've set a simple style for the buttons with certain dimensions and margins only to make clear the result, but you can use your own style.
It would be good to know the container including the button (grid, panel, others?):
Anyway If you put:
<Button HorizontalAlignment="Right"
in
<StackPanel Orientation="Horizontal">
It should work... Check too if there is no contradiction bring by the style...

ScreenShot as Button content

I want to do something similar to Microsoft Powerpoint: I want to capture the current screen (or one grid from the current window), and then to set it as the content of the button (like powerpoint where there is a preview of the slides at the side bar).
What is the best way to do that? My current idea is to save it to PNG and then reload it as an image at the content of the button, but I'm sure there is a better way.
Thank you!
Try this:
<Grid>
<Viewbox
x:Name="Viewer"
Stretch="Uniform"
DataContext="{Binding ElementName=Thumbnail1, Path=Data}">
<Grid Width="224" Height="168" SnapsToDevicePixels="True" Margin="4,0,4,0">
<Grid.Background>
<VisualBrush Stretch="Uniform" TileMode="None" Visual="{Binding}" AlignmentY="Center"/>
</Grid.Background>
</Grid>
</Viewbox>
</Grid>
I was using saving as PNG approach in the beginning. Then I have found out the way as above. DataContext of the ViewBox is a canvas. I could create live previews of my screens this way however my screens were canvas objects.

Image control in WPF Stretches Image When Stretch Set to None

I have an image control inside a grid displaying a 16x16 icon. But for some reason even though I set the properties so it would remain 16x16 it looks stretched.
Code :
<UserControl x:Class="ChatControls.UserListItem"
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"
mc:Ignorable="d" d:DesignHeight="28" d:DesignWidth="132">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" MinWidth="24" MaxWidth="24" />
<ColumnDefinition Width="171*" />
</Grid.ColumnDefinitions>
<Image Name="imgIcon" Source="/ChatControls;component/Images/NormalUser.png" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None" />
<Label Content="Muhammad[A]" Grid.Column="1" Name="lblNick" VerticalContentAlignment="Center" Padding="8,5,5,5" />
</Grid>
</UserControl>
Is there any reason for this?
UPDATE 1:
Yes at runtime also :(
Many thanks in advance.
Actually, I've seen that regularly with PNG images. It seems that the default resolution for PNG is 72dpi, while the default screen resolution in WPF is 96dpi. WPF tries to take this into account by rendering png bitmaps scaled to 133% of their pixel size, which is technically correct but normally not what the user wants. You can either use a gif or jpg instead, or you can combine the image with a LayoutTransform scaling it to 0.75 of its size, or just stick with setting the size of the image control explicitly.
I find I often have to explicitly specify the Width and Height of Image controls to get them to appear correctly:
<Image
Name="imgIcon"
Source="/ChatControls;component/Images/NormalUser.png"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="16"
Height="16"
/>
First of all, your XAML definition of your 171* is a bit odd. Your best approach is to do this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
You need to look into XAML layout passes in order to understand what this is doing.
Secondly, because you're using a dynamic image source (loaded as a URI), it will be streamed so the width during the first layout pass will be 24, but after the image has been streamed, the control will resize dynamically. If you want to enforce sizing, your best bet is to use a border around the image as a 0 width container. Like this
<Border Grid.Column="0" Grid.Row="0" BorderThickness="0" BorderBrush="Black">
<!-- UniformToFill: Scale to completely fill output area.
Aspect ratio is preserved. Cropping may occur.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="UniformToFill" />
</Border>
Enforcing a width and a height around an image is a shorthanded way of doing this. The other thing you may want to do is to explicitly define the way the source image is loaded like this:
<Image Width="200">
<Image.Source>
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>
Which will not load the full image but will resize before load as opposed to dynamically. For further reference review http://msdn.microsoft.com/en-us/library/ms748873.aspx
I agree with the accepted answer, but I don't think it explains why, it just explains that it works.
It happens because of the image pixels that is dependent on the screen resolution, it should be device independent so that to remains same on any screen resolution
So use this to do so.
<Image Width = "24" Height = "24" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased" Stretch = "None"/>
replace Width and Height with the original size of the image
This'll help you

Resources