Using SizeF for user control dimensions - c#

As the tittle says I am looking for a way to use SizeF instead of normal Size for setting and getting Control dimensions.

Controls are using integer values internally and the size and locations cannot be set to float numbers.
SizeF has a ToSize method
Size size = sizeF.ToSize();
Or
myControl.Size = sizeF.ToSize();

Controls are backed by the Windows API, which use integer based (pixel) sizing. As such, SizeF would not be appropriate or have any effect. You could always use a SizeF, then map to a Size when you set the values.
Note that, in WPF, all of the location and size types now use double precision, and do allow adjustments smaller than per pixel, since they're being rendered using DirectX instead of as windows handles.

Related

Why this Bitmap Image changes its size after I load it?

Quick question:
I have this 1000 x 1000 bitmap image:
and I use this routine to load it:
private BitmapSource initialBitmap = new BitmapImage(new Uri("C:\\Users\\...\\Desktop\\Original.bmp"));
Why after I load it, and right after I step over the above line, I see it as 800 x 800?
P.S I want it to be 1000 x 1000 and without using any Resize functions. It was working and suddenly it is 800*800 !
The values returned by BitmapSource.Width and BitmapSource.Height are not in pixels, but rather WPF's device-independent units, which are always 96 dpi. E.g.:
Gets the width of the bitmap in device-independent units (1/96th inch per unit).
If you want to know the actual pixel width and height, you need to use the PixelWidth and PixelHeight properties.
Your question isn't very specific, but if what you are actually concerned about is having the bitmap display at the same size in which it was authored, then the easiest solution is to make sure you author it at 96 dpi. Whatever program you're using to author the bitmap likely has a place where you can set the bitmap resolution. Typically this can be set with or without changing the pixel dimensions of the image (i.e. scaling the image larger or smaller); you want to do it without scaling the image, so that the pixel dimensions remain the same but the dpi changes to match what WPF is using.
Note that this still won't guarantee the bitmap displays at a specific pixel size. The display resolution can be and often is different from 96 dpi, in which case WPF will scale images to ensure that the physical dimensions of the image (i.e. the dimensions in inches, millimeters, etc.) are correct according to the information in the bitmap. For example, 960 pixels wide at 96 dpi means 10" wide. On a 120 dpi display, this means displaying the bitmap large enough so that its width uses 1200 display pixels.
If you want or need the bitmap to display at exactly the same number of display pixels regardless of the display resolution, then you'll have to set a transform where you display the image to reverse the effect of the scaling that WPF would otherwise do. This requires knowing the display resolution, of course.
Here are some other related Stack Overflow questions which you might find useful:
RenderTargetBitmap renders image of a wrong size
WPF for LCD screen Full HD
Screen Resolution Problem In WPF?
This is by design. Note the MSDN documentation for BitmapSource.Width/Height:
Gets the width of the bitmap in device-independent units (1/96th inch
per unit). (Overrides ImageSource.Width.)
Instead you should use the PixelWidth / PixelHeight property:
Gets the width of the bitmap in pixels.
A rather confusing choice or terms, imo, but there you go..

Determining height of a block of text in a console application

I'm trying to determine the size of the textframe that will be needed for a block of text. This is to then be exported for an InDesign script to create the page. All in a console application.
I've tried to create a WPF TextBlock and assign the Text and a Width, but the Height and ActualHeight is NaN.
How can I determine the size of a textframe that will be needed for some text? Is using a WPF / Winforms textblock the best solution (to try and take advantage of existing code), or is there some other, better workflow?
There are two classes in C# that are used to draw text. TextRenderer and Graphics.
TextRenderer uses GDI to render the text, whereas Graphics uses GDI+. The two use a slightly different method for laying out text.
You can make use of Graphics.MeasureString or TextRenderer.MeasureText
Example
using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}
For your case I would suggest using TextRenderer. Text wrapping example -
var size = TextRenderer.MeasureText(text, font, new Size(width, height), TextFormatFlags.WordBreak);
The third argument is size of the drawing rectangle. You can pass height as 0 if you don't know it.

Is there a way to crop and deskew a quadrilateral from an image in a Windows Store (WinRT) application?

I'm writing an application for the windows store that uses Canny Edge Detection to find the borders of a document on an image. I need to be able to crop this image once the corners are found. I can use the WriteableBitmapExtension methods to crop a rectangle, but the problem is that it will rarely be a rectangle, but rather a quadrilateral.
I read about something called Aforge that may be able to do it, but it doesn't support Silverlight/WinRT it looks like. I know this should be possible with OpenGL, but it would most likely require I change a large portion of my application. Are there any alternatives?
You could implement it with WriteableBitmapEx using Blit and n alpha mask for the region you want to crop. Just create the mask dynamically with the result from the Canny edge detection. Make sure all pixels you want to keep have an alpha value of 255 and the ones you want to crop have an alpha value of 0 in the mask bitmap. Then use the Blit method on the original image, supply the generated alpha mask bitmap as parameter and the BlendMode.Alpha as well. This won't really reduce the size of the original image but at least the unwanted pixels are gone.
Before the alpha masking you could already crop rectangular using the min, max of x and y from your edge detection result. This way the size is also reduced and your alpha masking should be faster as a bonus.

Measure size of unicode string to calculate row height [duplicate]

Calling TextRenderer.MeasureText as follows:
TextRenderer.MeasureText(myControl.Text, myControl.Font);
and comparing the result to the size of the control to check if text fits. The results are sometimes incorrect. Have observed the following two issues:
Often when a Label is set to AutoSize, TextRenderer will report a width that is 1 pixel wider than the auto-sized width of the Control.
False negative where TextRenderer reports a width smaller than the control's but the text is still cut off. This occurred with "EstaciĆ³n de trabajo" -- not sure if the accent could somehow affect the width calculation?
Is there any way to improve the accuracy of the MeasureText method? Should I be calling one of the overrides that accepts a device context and/or format flags?
I know it's probably no actual anymore. Yet for future readers here is a simple yet accurate method of measuring text in a control:
Graphics g=Graphics.FromHwnd(YOUR CONTROL HERE.Handle);
SizeF s=g.MeasureString("YOUR STRING HERE", Font, NULL, NULL, STRING LENGTH HERE, 1)
Is there any way to improve the accuracy of the MeasureText method? Should I be calling one of the overrides that accepts a device context and/or format flags?
You have answered your question by yourself. Actually MeasureText based on Win32 DrawTextEx, and this function cannot work without valid device context. So when you call MeasureText override without hdc, it internally create desktop compatible hdc to do measurement.
Of course measurement depends on additional TextFormatFlags. Also keep in mind that Label painting (and measurement) depends on UseCompatibleTextRendering.
So general conclusion you should use MeasureText for your own code, for example when you then call DrawText with exactly same parameters, in all other cases size returned by MeasureText cannot be treated as precise.
If you need to get expected Label size, you should use GetPreferredSize method.
Check out the TextFormatFlags parameter to this function:
TextRenderer::MeasureText(String, Font, Size, TextFormatFlags)
http://msdn.microsoft.com/en-us/library/8wafk2kt.aspx
"The Size, in pixels, of text drawn on a single line with the specified font. You can manipulate how the text is drawn by using one of the DrawText overloads that takes a TextFormatFlags parameter. For example, the default behavior of the TextRenderer is to add padding to the bounding rectangle of the drawn text to accommodate overhanging glyphs. If you need to draw a line of text without these extra spaces you should use the versions of DrawText and MeasureText that take a Size and TextFormatFlags parameter. For an example, see MeasureText(IDeviceContext, String, Font, Size, TextFormatFlags)."
hth
I don't know if I have a perfect solution but I ran into this when I was doing WinForms a few years back. The way I ended up compensating was by adjusting the returned measurement by a percentage. I cannot recall what I used (maybe 5% or 105?), but I do recall that I ended up using a constant percentage across the app and always rounded up.
I haven't got enough points to comment yet, so I've had to put this as an answer:
Perhaps ClearType affects measurement accuracy, because although a character has a known width calculated from its glyph, its rendering and position are adjusted to place axial lines on whole pixels.
Just a thought.

imageList.Draw doesn't draw with different size?

The ImageList has a method named "Draw":
imageList.Draw(graphics, bounds.X, bounds.Y, bounds.Width, bounds.Height, imgIndex);
I use this method to draw an image on a graphics object of a PrintDocument. When using the original image size (16 x 16 pixels), the image is drawn correct. If however, I change the bounds size, nothing is drawn. Even changing the size to 32 x 32 (double size) has no effect. Nothing is drawn. I need to change the drawn size because of the different dpi ... Where am I gong wrong ?
Edit: The solution seems to be simply to use the g.DrawImage method instead. Why imageList.Draw() doesn't draw is still a mistery to me ...
g.DrawImage(imageList.Images[imgIndex], bounds);
ImageList.Draw() is a bit unusual, it takes advantage of the built-in support that the native image list code inside of Windows has for rendering an image in the list. This is an optimization, it avoids the cost of converting the internal image as stored in the native image list back to a managed Image object.
One side-effect however is that this drawing happens without regard for any of the transforms that were applied to the Graphics object. A 16x16 image in the list is going to be rendered as 16x16 pixels on paper. Which is indeed a bit hard to find back, printers have very high resolution (600 dots per inch is typical), that image turns into a decimal point.
Image lists were really meant to be the source of images for the TreeView and ListView controls, it is not a good general purpose collection object for images. Like a List<Image>. Your workaround is good, the Image property converts the internal bitmap back to a managed Image, Graphics.DrawImage() will then scale it appropriately to get a size on paper that's close to the size on the screen. However with the graininess you get from making an image 6 times larger. Note that you should Dispose() that object.

Categories