On a windows store app project, im using a PDFtron PDFViewCtrl to display a pdf document.
I have a part of the screen where the document is displayed, and it is working well.
I would like to know if there is a way to disable surface pen funcionality on this control, because as it is right now, when i pass over document with the pen, it starts drawing lines.
This is my XAML:
<Grid x:Name="pdfViewer" Background="Transparent" Canvas.ZIndex="111" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border x:Name="PDFViewBorder" Background="White" Grid.Row="0"/>
</Grid>
and this is my code behind
MyPDFViewCtrl = new pdftron.PDF.PDFViewCtrl();
PDFViewBorder.Child = MyPDFViewCtrl;
docpdf = new pdftron.PDF.PDFDoc(file);
docpdf.InitSecurityHandler();
MyPDFViewCtrl.SetDoc(docpdf);
In the PDFViewCtrlTools project, in the Pan tool (Pan.cs), in the PointerPressedHandler method, there is a check if the pointer is a pen
else if (e.Pointer.PointerDeviceType == PointerDeviceType.Pen)
This is what causes the inking to happen. You can edit this to change the behaviour.
Related
I'm having a problem with RenderTargetBitmap whenever I render canvas and clear its children and set the rendered bitmap as background of canvas it slide toward bottom right.
can't insert images until 10 reputation :(.
WPF:
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="700"
KeyDown="Window_KeyDown">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="1" Grid.Column="1">
<Canvas x:Name="Pad">
<Rectangle Height="100" Width="100" Fill="Red" Canvas.Left="10" Canvas.Top="10"></Rectangle>
</Canvas>
</Border>
</Grid>
</Window>
c# code:
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
RenderTargetBitmap rendrer = new RenderTargetBitmap(Convert.ToInt32(Pad.ActualWidth), Convert.ToInt32(Pad.ActualHeight), 96, 96, PixelFormats.Pbgra32);
rendrer.Render(Pad);
Pad.Background = new ImageBrush(rendrer);
Pad.Children.Clear();
}
}
}
To avoid any offset problems with drawing a Visual into a RenderTargetBitmap, you may use an intermediate DrawingVisual:
var rect = new Rect(Pad.RenderSize);
var visual = new DrawingVisual();
using (var dc = visual.RenderOpen())
{
dc.DrawRectangle(new VisualBrush(Pad), null, rect);
}
var bitmap = new RenderTargetBitmap(
(int)rect.Width, (int)rect.Height, 96, 96, PixelFormats.Default);
bitmap.Render(visual);
Pad.Background = new ImageBrush(bitmap);
Pad.Children.Clear();
Note that without setting any further properties of the ImageBrush (like e.g. its Viewport), it will fill the entire area of the Rectangle. For details, see TileBrush Overview.
Your primary problem stems from the fact that, due to the 1-pixel border around the Canvas, its VisualOffset vector is (1,1). Thus, any visual effect, like the background brush, will be applied at that offset. When you render the visual into a bitmap, it captures the present appearance, and then when you set the bitmap as the brush, it gets shifted.
Ironically, one of the easiest ways to fix this is to insert another <Border/> element into your XAML:
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="1" Grid.Column="1">
<Border>
<Canvas x:Name="Pad">
<Rectangle Height="100" Width="100" Fill="Red" Canvas.Left="10" Canvas.Top="10"/>
</Canvas>
</Border>
</Border>
Then the offset caused by the outer <Border/> element is handled by the new <Border/> element's transform, rather than being applied to the <Canvas/> element.
That change alone will almost fix your code completely. However, there's one other little artifact that you may still notice: every time you render the visual, it gets just a teensy bit blurrier. This is because the default value for the Brush object's Stretch property is Stretch.Fill, and because your <Canvas/> element is not precisely an integral width or height, the bitmap (which necessarily does have integral width and height) gets stretched just a teensy bit when rendered. With each iteration, this becomes more and more apparent.
You can fix that by setting the Stretch property to Stretch.None. At the same time, you'll also want to set the brush's alignment to Left and Top:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
RenderTargetBitmap renderer = new RenderTargetBitmap(
Convert.ToInt32(Pad.ActualWidth), Convert.ToInt32(Pad.ActualHeight), 96, 96, PixelFormats.Pbgra32);
renderer.Render(Pad);
ImageBrush brush = new ImageBrush(renderer);
brush.AlignmentX = AlignmentX.Left;
brush.AlignmentY = AlignmentY.Top;
brush.Stretch = Stretch.None;
Pad.Background = brush;
Pad.Children.Clear();
}
The defaults are Center, which again incurs the rounding error and will cause both movement and blurring of the image after repeated iterations of the process.
With the above changes, I found a perfectly stable image, regardless of the number of iterations.
The "wrap in a border" idea came from here: https://blogs.msdn.microsoft.com/jaimer/2009/07/03/rendertargetbitmap-tips/
On that page you'll find a more general-purpose solution which does not require modification of the actual XAML. In your example above, the "wrap in a border" approach seems like a reasonable work-around, but it is admittedly not as clean as forcing an unadorned context into which you can render the visual, as shown on that blog page.
I programm an universal Windows platform app with Visual Studio and I want to get a simple Blur effect on my main grid layout, but I don't know how to apply a GaussianBlurEffect object on my grid. I searched for a long time and I've readed the Microsoft documentation but I don't understand the Visual Layer part.
If anyone can give me a little explaination about visuals, it would be nice :)
Sorry if my English is bad, I'm french.
You will find a lot of good samples on the Windows UI DevLabs repository
The idea of Visuals is to provide a low level API (but not as low as DirectX) to handle a lot of GPU accelerated effects on the UI. It allows you to draw what you want or create some effects on the rendering.
Here is a very basic sample to show how to apply a blur effect on a Grid. (It works the same for any other UIElement).
This code is adding a layer over the one used by the XAML renderer to render the grid. This newest layer will apply an effect on top of the image rendered by the XAML renderer.
The XAML of the page:
<Page
x:Class="BlurSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BlurSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Fill="Red" />
<Rectangle Fill="Green" Grid.Column="1" />
<Rectangle Fill="Blue" Grid.Row="1" Grid.Column="1" />
<Rectangle Fill="Yellow" Grid.Row="1" />
</Grid>
And the code behind:
public sealed partial class MainPage : Page
{
private CompositionEffectBrush brush;
private Compositor compositor;
public MainPage()
{
this.InitializeComponent();
MainGrid.SizeChanged += OnMainGridSizeChanged;
compositor = ElementCompositionPreview.GetElementVisual(MainGrid).Compositor;
// we create the effect.
// Notice the Source parameter definition. Here we tell the effect that the source will come from another element/object
var blurEffect = new GaussianBlurEffect
{
Name = "Blur",
Source = new CompositionEffectSourceParameter("background"),
BlurAmount = 100f,
BorderMode = EffectBorderMode.Hard,
};
// we convert the effect to a brush that can be used to paint the visual layer
var blurEffectFactory = compositor.CreateEffectFactory(blurEffect);
brush = blurEffectFactory.CreateBrush();
// We create a special brush to get the image output of the previous layer.
// we are basically chaining the layers (xaml grid definition -> rendered bitmap of the grid -> blur effect -> screen)
var destinationBrush = compositor.CreateBackdropBrush();
brush.SetSourceParameter("background", destinationBrush);
// we create the visual sprite that will hold our generated bitmap (the blurred grid)
// Visual Sprite are "raw" elements so there is no automatic layouting. You have to specify the size yourself
var blurSprite = compositor.CreateSpriteVisual();
blurSprite.Size = new Vector2((float) MainGrid.ActualWidth, (float) MainGrid.ActualHeight);
blurSprite.Brush = brush;
// we add our sprite to the rendering pipeline
ElementCompositionPreview.SetElementChildVisual(MainGrid, blurSprite);
}
private void OnMainGridSizeChanged(object sender, SizeChangedEventArgs e)
{
SpriteVisual blurVisual = (SpriteVisual) ElementCompositionPreview.GetElementChildVisual(MainGrid);
if (blurVisual != null)
{
blurVisual.Size = e.NewSize.ToVector2();
}
}
}
Update: Animation
To animate the blur effect, you will have to do two things:
declare the property you want to animate
create the animation
To declare the property, you will have to change the blurEffectFactory creation. Notice the declaration of the Blur.BlurAmount property :
// we convert the effect to a blur that can be used to paint the visual layer
var blurEffectFactory = compositor.CreateEffectFactory(blurEffect, new[] { "Blur.BlurAmount" });
brush = blurEffectFactory.CreateBrush();
Once declared, you can use the Blur.BlurAmount property in any animation you want. Here, I'm declaring a continuous animation of 3 seconds which will blur/unblur the image:
var blurAnimation = compositor.CreateScalarKeyFrameAnimation();
blurAnimation.InsertKeyFrame(0.0f, 100.0f);
blurAnimation.InsertKeyFrame(0.5f, 0.0f);
blurAnimation.InsertKeyFrame(1.0f, 100.0f);
blurAnimation.Duration = TimeSpan.FromSeconds(3);
blurAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
brush.StartAnimation("Blur.BlurAmount", blurAnimation);
I am working on creating a reactive UI using a map and menu at the bottom. My map is using the builtin windows phone bing maps control with a user control below it.
My XAML looks like this:
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Controls:Map x:Name="map"/>
<Border Background="{StaticResource PhoneChromeBrush}"
Grid.Row="1">
<telerikPrimitives:RadTransitionControl Grid.Row="1">
<views:OverviewPage/>
</telerikPrimitives:RadTransitionControl>
</Border>
</Grid>
And my animation looks like this. I've drawn out the time for a longer period of time to show the issues.
DoubleAnimation animation = new DoubleAnimation() { Duration = TimeSpan.FromSeconds(10), To = 480, From = 0 };
Storyboard.SetTarget(animation, map);
Storyboard.SetTargetProperty(animation, new PropertyPath(HeightProperty));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
Now, if I swap out my Map control for something else, say a Border. Everything works as you would expect, the animation is smooth. The issue is my UI updates only every half second or so if I use the map. I'm getting this lag on a Lumia 1520, I can't imagine how bad it is on a lower end device.
I am looking for some way to improve the performance of this animation or some alternative. Has anyone tried this before or do you know a good solution?
This issue is that every time the map is moved, or resized there is a bunch of calculations that have to be done by the map. When you animate the map, the size of the map updates a bunch of times in a very short time, causing the map to recalculate everything a bunch of times. Map controls in general tend to be heavy weight controls due to all the data and calculations involved. Things like animating the map size should be avoided, especially on less powerful devices, such as mobile phones.
I have a user control that shows a thumbnail and some text below it. The API I'm using returns a 480x360 letterboxed thumbnail. I'm trying to hide it so the user only sees the image without the two 45px tall bars on the top an bottom. Below are the dimensions of the thumbnail:
User Control xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Name="ThumbnailRow"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Image Source="..." Stretch="UniformToFill" VerticalAlignment="Center"/>
<Grid Grid.Row="1" Background="Gray">
<TextBlock Padding="24" Text="..." HorizontalAlignment="Left"/>
</Grid>
</Grid>
In my codebehind, I tried to modify the height of ThumbnailViewRow to hide the black bars:
private double GetScreenWidth()
{
double scaleFactor = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
double width = scaleFactor * Window.Current.Bounds.Width;
return width;
}
private double GetAdjustedThumbnailRowHeight()
{
// 38 represents 19px left & right margins in ListView
double adjustedWidth = GetScreenWidth() - 38;
double projectedHeight = (360 * adjustedWidth) / 480;
// in a full 480x360 image, I would need to shave 45 px from the top
// and bottom. In some resolutions, the image is scaled so I have
// to find the proportionate amount to trim
double toTrim = (projectedHeight * 90) / 360;
return projectedHeight - toTrim;
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
ThumbnailViewRow.Height = new GridLength(GetAdjustedThumbnailRowHeight());
}
The above code only slightly works; a large portion of the bars are still visible on both ends. On a 480x800 device, I was able to tweak some numbers to get the thumbnail to display correctly. The fix in that case was to multiply toTrim by 1.55 but I have no clue how well this would work out on devices with other resolutions. I don't have another device to test nor a WP emulator.
Could the reason for this problem be an embarrassing math mistake, or a subtlety in the way XAML works? How can I get my approach to work properly in different resolutions?
Here's a quick working example I made in WPF. (Note the explicitly-set height and width).
<Grid Margin="0, 30, 0, 0">
<Grid.RowDefinitions>
<!-- 360 - 45 - 45 = 270 -->
<RowDefinition Height="270"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Image Source="..." VerticalAlignment="Center" Width="480" Stretch="UniformToFill"/>
</Grid>
Use the Clip Property of the Image like so
<Image x:Name="myimage" Stretch="None" Source="/Assets/my_image.jpg">
<Image.Clip>
<RectangleGeometry Rect="0, 45, 480, 435"></RectangleGeometry>
</Image.Clip>
</Image>
RECT is the rectangle section of the image you want to be visible.
I am creating game for WP 8 and I am using ScrollViewer and Grid with Buttons for game board.
The problem is when game board is too lardge. Then application crashes with no exception.
Output is:
ScrollViewer content size: 2400,2400 //my debug output
The program '[3420] TaskHost.exe' has exited with code -528909961 (0xe0797977).
Here is XAML code:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ScrollViewer x:Name="ContentPanelScroll" HorizontalScrollBarVisibility="Auto">
<Grid x:Name="GamePanel" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
<!-- more RowDefinitions in this grid are addend in C# code-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<!-- more ColumnDefinitions in this grid are addend in C# code-->
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="..."/>
<!-- more buttons in this grid are addend in C# code-->
</Grid>
</ScrollViewer>
</Grid>
This is how I resize/zoom game board
private void ZoomGameBoard(double delta)
{
// typically delta = 10px;
// 20 columns and 20 rows, each zoomed to 150px is 3000x3000 px
foreach (var item in RowDefinitions)
{
var value = item.Height.Value + delta;
item.Height = new GridLength(value); // make row bigger so its content stretch
}
foreach (var item in ColumnDefinitions)
{
var value = item.Width.Value + delta;
item.Width = new GridLength(value); // make column bigger so its content stretch
}
}
Could you please tell me where is the problem or how to make larger game board?
Thx. :-)
EDIT:
My problem is probably this:
Insufficient memory to continue the execution of the program.
and this
An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Windows.ni.dll
But this exception is not thrown every time app craches (just sometimes) does not solve my problem how to display large game board.
EDIT 2:
Here is test application to demonstrate my problem. You can change size in code or use Buttons in bottom part of phone.
Whole project is here: http://www.stud.fit.vutbr.cz/~xmarec12/shared/2013/TestGameApp.zip