I am trying to use ScaleTransform to shrink a WebView, while scaling (zooming) the contents properly. i.e., If I scale the WebView to 50% of the size using ScaleTransform, the contents should likewise scale to 50% zoom level, so you can see the same contents as before, just shrunk to fit the new size of the WebView.
I know it's possible, because the AdControl does properly scale its contents when you apply a ScaleTransform, and the AdControl internally uses a WebView control to display the ad.
Example code that works with an AdControl:
double scale = 0.75;
ad.RenderTransform = new TransformGroup() {
Children = {
new ScaleTransform() { ScaleX = scale, ScaleY = scale }
}
};
If that same code is applied to a WebView control, it does shrink the size of the control, but the contents are clipped instead of shrunk.
Properly scaling the control's contents should not require the use of JavaScript injection or any other "kludgy" approaches, since it is highly doubtful that Microsoft's AdControl would use such techniques. It should all be able to be handled in the XAML or code-behind (C#).
Thanks for the help!
Related
my canvas is 1920*1080 and I'm adding an image that its width is 200 and height is 200 too,
I want the image to go to the top right corner, and after setting the following code and running the application
I see that the image overflows the canvas:
Image img = new Image();
img.Source = SOURCE;
img.Width = 200;
img.Height = 200;
screen.Canvas.Children.Add(img); // I have already created screen obj and a canvas before
img.SetValue(Canvas.LeftProperty, 1720);
img.SetValue(Canvas.TopProperty, 0);
after I checked it manually, I saw that if I put the Canvas.Left 1350 it fit the target,
but I can't understand why it happens
...................
And about the canvas parent:
it's in the window and I maximize the window at startup also I'm using the code below in its window constructor to maximize the canvas too:
var resolution = Screen.PrimaryScreen.Bounds;
Canvas.Width = resolution.Width; // i put the name of the canvas, Canvas :)
Canvas.Height = resolution.Height;
.................
another update:
I find out however I get the screen size 1920x1080 but the real size is 1536x864 so can anyone help how to get the real screen size? :)
So the problem was I wasn't setting the actual width and height for my canvas,
when I use the resolution width and height, what I get is 1920x1080 but also I checked in my display setting that I have 125% scale so it makes the size 1536x864 so I got this number with RenderSize:
screen.Canvas.Width = screen.RenderSize.Width;
screen.Canvas.Height = screen.RenderSize.Height;
And also it's worth mentioning that if you use it in the constructor the RenderSize will be 0
Why my resolution of Thinkpad T450s is 1536px width?
I am using skia to do drawing on a SwapChainPanel (via ANGLE), and all is going well. However, the one issue that I am having is that the content is being scaled on high DPI screens.
I have a hi-res (x2) and a normal (x1) screen on my machine here. The contents of the panel look great on the 1x display, but when I drag it over, the window resizes and scales the contents. How do I tell the panel not to scale the contents, but to rather let me adjust my side?
My current solution is to create my renderbuffer at the desired scale (eg: panel.Width * 2) and then use the RenderTransform property and set the ScaleTransform (eg: 0.5).
The content now appears smooth and crisp, but now the layout is affected. Since the render transform has "resized" the panel.
What is the correct way to do this?
EDIT
This is what I am doing to create the buffer:
https://github.com/mono/SkiaSharp/blob/master/source/SkiaSharp.Views/SkiaSharp.Views.UWP/AngleSwapChainPanel.cs#L199-L285
You essentially have to set scale on DXGISwapChain to be inverse of swap chain panel composition scale using IDXGISwapChain2.SetMatrixTransform method:
SwapChainPanel panel = ...;
IDXGISwapChain2 swapChain = ...;
DXGI_MATRIX_3X2_F scale;
inverseScale._11 = 1.0f / swapChainPanel.CompositionScaleX;
inverseScale._22 = 1.0f / swapChainPanel.CompositionScaleY;
var hr = swapChain.SetMatrixTransform(ref scale);
if (hr < 0)
Marshal.ThrowExceptionForHR(hr);
I don't know exactly how to obtain the swapchain object reference through the library you're using, though.
I want to load an image and put it into a viewbox. The image is displayed correctly, but, when I'm going to get it's width and height, it's both NaN.
This is my image load code :
Image img = new Image();
img.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("1.png");
Viewbox vb = new Viewbox();
vb.Width = img.Width;
vb.Height = img.Height;
vb.Child = img;
cnv.Children.Add(vb);
The reason I want to get the image width and height is so I could resize it (via viewbox resize) later inside the application.
Any idea how to get the image dimension?
And this is how I'm going to resize it (via mouse wheel)
private void cnv_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (vb != null)
{
vb.Width += Mouse.MouseWheelDeltaForOneLine;
vb.Height += Mouse.MouseWheelDeltaForOneLine;
}
}
And it returns error and said that vb.Width is not a valid value.
Questions to sum this up :
How to get the image width / height in wpf?
How to resize the viewbox (which will also result in image resize) via mouse wheel? For example, if I scroll up the wheel, the width and height is added by 1, and if I scroll down the wheel, the width and height is reduced by 1.
Thank you
P.S. Viewbox vb; and Image img; is a global variable, I just shorten the script down.
P.S.S. I know if the Viewbox width and height initialized by a number, lets say 100 and 100, it will work, I just wanna know how to get the image original size.
EDIT :
The resize can be achieved by detecting whether it's scrolled up or down by detecting e.Delta > 0 or e.Delta < 0
(Source : http://social.msdn.microsoft.com/Forums/vstudio/en-US/170c4fd0-1441-4d83-903d-594af75f8fb4/detect-mouse-scroll)
It seems as though the Image object is not fully loaded at that stage. I believe that you can use the Width and Height properties of the ImageSource class instead. That should be fully loaded at this stage.
ImageSource.Width Property
ImageSource.Height Property
For other users, you can also possibly find the values that you want from the ActualWidth and ActualHeight properties of the Image class (inherited from the FrameworkElement class) instead of the more usual Width and Height properties.
FrameworkElement.ActualHeight Property
FrameworkElement.ActualWidth Property
The image original size can only be obtained in Pixels while your WPF controls are measured in Device Independent Pixels so you're going to have to make a translation from Pixels to Device Independent Pixels and back wherever necessary.
That said, to obtain the width and height for a png file, you can load it into a BitmapImage instead of Image and query the PixelWidth and PixelHeight properties for the BitmapImage.
Again, be aware that this is the only place in your code where you're going to be dealing with Pixels, all Width and Height properties (including ActualWidth and ActualHeight, only set after the control is fully rendered) are measured in Device Independent Pixels. This can be misleading because in a lot of situations this happens to be a 1:1 conversion but this is not guaranteed to be the case.
More info can be found here: http://msdn.microsoft.com/en-us/library/windows/desktop/ff684173%28v=vs.85%29.aspx
So my application runs in fixed size window and in full screen. The problem I'm facing is how to properly scale the current contents of the panel (which depend on the application use) when the window is resized. This is my current code:
private void Form1_ClientSizeChanged(object sender, EventArgs e)
{
System.Drawing.Drawing2D.Matrix transformMatrix = new System.Drawing.Drawing2D.Matrix();
float px = panel2.Width;
float py = panel2.Height;
panel2.Width = this.Width / 2;
panel2.Height = panel2.Width;
panel2.Location = new Point(this.Width - panel2.Width - 30, 30);
transformMatrix.Scale(panel2.Width / px, panel2.Height / py);
panel2.Region.Transform(transformMatrix);
//Rest of the code
}
But the drawn content doesn't scale, and if I use Invalidate() or Refresh() the drawn content gets cleared (the panel is redrawn empty). What am I missing?
.NET doesn't remember what's drawn on the panel, as simple as that. As soon as anything invalidates the windows bitmap buffer (causing a WM_PAINT), it's going to be repainted again. So, you have to draw what you want to draw using the Paint event (or overriding OnPaint).
However, there is another way that might be easier to implement - don't paint into a Panel. Instead, paint into a PictureBox (or rather, a Bitmap assigned to the Image property of the PictureBox). The Bitmap will be reused when invalidating (and redrawing) the picture box, so nothing will be lost. By using PictureBox.ScaleMode, you can define how you want the picture box to scale the bitmap, and it will do so as well as it can.
In any case, transforming the Region property doesn't do anything useful - you're simply changing the region, not doing anything to the drawing itself. To use 2D transformation matrices, you want to apply them on a Graphics object during the drawing (in Paint handler or OnPaint override) - drawing anything on the Graphics object will then transform everything you're trying to draw, which in your case means scaling the painting.
So you have to decide: do you want to just scale a stored bitmap with the painted image, or do you want to redraw it all from scratch (which also means you can pick any level of detail you can provide)?
I think that you're mistaking what the Region property is meant for. According to the MSDN docs (empasis mine, replace 'window' with 'control' when reading):
The window region is a collection of pixels within the window where the operating system permits drawing. The operating system does not display any portion of a window that lies outside of the window region. The coordinates of a control's region are relative to the upper-left corner of the control, not the client area of the control.
All that you're doing is changing the region that the OS will allow painting, which explains why you're not seeing anything. I think that you should be resizing the control when the form is resized, either through Anchor, or through my preference of Dock with several controls, or a panel like TableLayoutPanel where it will handle scaling and relative sizing for you.
Thank you for your answers, but I wrote my own function and logic that serves the purpose for this application. Basically the function checks for the state of the application variables, and calls the appropriate function that originally drew the content, and since those functions use the panel width and height as arguments they properly scale the drawn content and retain the drawing composition.
P.S. I'll accept Luaan's answers since it offers a valid alternative and is complete.
Is there an easy way to set the zoom level for a windows form in C#? In VBA there was a zoom property of the form.
I had the same problem and I solved it this way in c#. Code goes on Form load
float scaleX = ((float)Screen.PrimaryScreen.WorkingArea.Width / 1024);
float scaleY = ((float)Screen.PrimaryScreen.WorkingArea.Height / 768);
SizeF aSf = new SizeF(scaleX, scaleY);
this.Scale(aSf);
This "more or less" scales form and all children. Loops forever in 800x600 (?)
You have to set the following Form properties:
AutoscaleMode = Font
AutoSize = False
You can get some kind of zoom by assigning different Font to the Form, all the controls will be zoomed accordingly if AutoScaleMode set to Font. Also settings AutoSize to False will keep form size intact, the controls will grow to the center of the form. You need to set up all Anchors correctly and test the look, since its just "kind of zoom".
So basically here is sample constructor:
public Form1()
{
InitializeComponent();
AutoSize = false;
AutoScaleMode = AutoScaleMode.Font;
Font = new Font("Trebuchet MS",
10.0f,
FontStyle.Regular,
GraphicsUnit.Point,
((byte)(204))
);
}
After form has been shown assigning new Font will mess up all the controls and this trick will not work.
There is no way (that I know of) to do what you ask with typical WinForms.
If you're doing custom painting/drawing, you can zoom that by using a zoom transform, but so far as I know there is no "Zoom" property for the form in the entire world of .NET and native Windows/C++ APIs combined.
You could probably rig something yourself such that you scale controls by a constant factor. And you can probably find 3rd-party controls/surfaces which support this. And who knows what is possible with WPF. But in a typical WinForms world, no.