I made my first WPF app and brought it to work to use. My work computer's monitor is a maximum of 1680 x 1050, 96 dpi, Win 7 system, whereas my home computer is 1920 x 1080p, 96 dpi, Win 7.
The app doesn't display correctly on the work computer. Text is cluttered and 'doesn't fit' where it should, etc (the problem seems to be with the font sizing, only). I'm reading that I did just about everything wrong in regards to making the app support multiple resolutions, so I certainly have some reworking to do.
The odd thing is the work computer appears incorrectly at all lower resolutions, whereas my home computer appears correctly at all lower resolutions, including 1680 x 1050 - meaning I can't duplicate the problem on the computer I am working on the app on.
Here is the font I am using since that seems to be where the problem may lie:
<Setter Property="FontFamily" Value="Linux Libertine G"/>
What other factors could be affecting the appearance of my app besides resolution?
Related
WPF documentation and tutorials state that WPF is resolution independent which I understood shows a window in the same size in different resolutions (1600x1200 -> native and 1024x768) and/or DPI settings. However, when I tried a sample app. with different resolutions the sizes are different. On the net I found http://www.wpflearningexperience.com/?p=41, which use "native resolution" in order to see the same window size on different computers, however I could not understand the underlying concept.
Why native resolution for LCD is vital and resolution indepence is a term instead of DPI independence? Probably, I do not know/use terminology well, but I need a clarification in order to understand this issue.
I do not want to answer my own questions, but I think I got the point. Sorry for this premature question, but after a while I noticed the problem.
As far as I understand WPF uses System DPI (which you set by changing through Windows Desktop Settings) as a scale factor. For example in the tutorial above one of the computers have a native resolution of 1600x1200 and 96 DPI (94 actually as stated in the tutorial). Everything is fine because System DPI (96) is quite close to the real DPI (94) and WPF can use this information to scale your window.
As you know a Device Independent Unit is 1/96 inch and with the numbers above real pixel size (physical pixel on your screen) is multiplied with ( (1/96) * 96 ) which is equal to 1. So if you have a window with 300 DIU, then you will see ( 300/96 ) inch on your screen.
However, when you change your resolution without changing System DPI, here comes the problem which confused my mind. Say, you set the screen resolution to 1024x768 without changing the System DPI (still it is 96) and run the application again and you see a bigger window. This is the reqult of wrong System DPI and naturally wrong scale factor for WPF. WPF does not know much about your real DPI, it only uses the information you give to it which is System DPI. Let's recalculate our window size with this new settings. First we need scale factor which is ( (1/96) * 96 ) equal to 1. We can say that 1 logical pixel is also 1 physical pixel on screen. However, we changed the resolution and 300 pixel is not the same with the previous resolution. Previously we have 1600 pixel on the diagonal which is also 17 inch in length. However, we have 1024 pixel for 17 inch now. 300 pixel is almost 5 inch on our new resolution (1024x768), but only 3.18 inch in the previous resolution (1600x1200). Therefore, WPF cannot be resolution independent due to the wrong DPI value and draws a larger window with the new resolution.
So, how I fix the problem (in my words, I do not claim that this is an absolute solution)! When I change the resolution, I also changed the DPI value which is true for this new resolution. For example, for my own monitor the diagonal size is 17 inch with a resolution of 1024x768, I use the formula (1024 pixel / 17 inch) and find that my new true DPI is almost 60 DPI. I set the System DPI to 60 (through the Desktop Settings of course) and it works. Not perfectly, due to the rounding errors during the calculations, but in practice values can be considered equal.
WPF uses System DPI in order to be resolution independent and you need to set actual DPI (real DPI value for current resolution). You need to set DPI in order to help WPF to be resolution free. Finally (and I think very crucially) you have do one more thing, at least on Windows XP, you need a restart in order to enable your DPI settings with the new value. If you do not (as I did), WPF still make the calculations wrong and draw in different size.
These are my understanding and results from the tests I did, but I cannot claim they are absolute. I just want to share it with the people who may find this information useful. Please comment/edit my post if you find any error or think that needs improvement.
When the Display Settings is set to either Small or Large the default font for a WinForm is set to Microsoft Sans Serif, 8.25pt. And everything on the form scales properly. However, when it is set to Medium it changes the default font to Microsoft Sans Serif, 7.8pt, which causes various breaking issues on the form.
Is there a specific reason why the font's size only changes on the Medium setting?
Yes, by default if you go past Medium (anything more than 125%) then Windows starts to help and emulates a video adapter set at 96 dots per inch. Same as Small. This works by Windows letting the program actually draw into an in-memory bitmap and rescaling the bitmap before blitting it to the screen. This is an appcompat feature and the result is in general not considered pretty, particularly text becomes 'fuzzy'. It does however help keep the program usable on very high resolution screens and prevents the main window from having the size of a postage stamp. Disabling this feature is the subject of this answer, otherwise the exact opposite of what you are looking for.
It works this way because 125% scaling has been around for a long time already, at least as far back as 2001 with the XP release. So programs are expected to know how to deal with it. Enabling automatic DPI scalling at 125% is not an option.
Does anyone know what measurement units are used by Silverlight/WFP? For example, if I create a new button and set its height to 150, is that 150 pixels? points? millimeters?
I design all of my applications in Adobe Illustrator before proceeding to code, and although I try and set everything to the dimensions in my Illustrator file, the Silverlight application is usually larger.
Although in theory, 1 unit in WPF is 1/96th of an inch, that's frequently not the case in practice.
It's usually true when printing. But it's rarely true on screen. The reason for this is that Windows almost always knows the true resolution of a printer, but almost never knows the true resolution of a screen.
For example, I have three screens attached to my computer. Windows thinks that they all have a resolution of 96 pixels per inch. Actually they don't. Two of them have a resolution of 101 pixels per inch, and one has a resolution of 94 pixels per inch. (Why? Because Windows has no way of working the true resolutions out for itself, and I haven't told it. The fiction that they all have the same pixel size is close to the truth, and turns out to be a convenient fiction.)
So when I create, say, a Rectangle in WPF with Width and Height both set to 96, the size of the Rectangle actually depends on which screen it appears on. Windows thinks that all 3 screens have a resolution of 96 pixels per inch, and so it'll render the rectangle as being 96 pixels tall and wide no matter which screen it appears on. That'll make it appear 0.95 inches tall on two of the screens, and 1.02 inches tall on the third.
So in practice, that means that units in WPF on my computer here are either 1/100th of an inch, or 1/94th of an inch in practice. (I.e., in practice, the size of 1 unit in WPF is exactly the size of 1 pixel on my particular setup, no matter how big the pixels happen to be.)
I could change that. I could reconfigure Windows - I could tell it the actual resolution of all 3 screens, in which case the nominal and actual WPF unit sizes would coincide. Or I could lie - I could claim that I have 200 pixel per inch screens, in which case everything would be massive...
The basic problem here is that there is no standard way for the computer to discover the true size of the physical pixels on the screen, and very few people bother to set it up by hand. (And in fact you can cause problems by configuring it 'correctly', because a lot of software doesn't behave correctly when you do.) So the majority of Windows computers don't report physical pixel sizes correctly to WPF - they can't because they don't know.
Consequently, there's no reliable answer to the question - 1 unit in WPF could be pretty much anything on screen. (In practice, most of the time, it turns out to be 1 pixel, simply because if you don't tell Windows anything else, it defaults to assuming that your screens have pixels that are 1/96th of an inch tall, which is the same as 1 WPF unit. And for most desktop screens, that's actually quite likely to be a good guess. But this isn't universal. On systems configured with what used to be called 'large fonts' for example, you'll find a different nominal screen resolution, and 1 WPF unit will correspond to slightly more than 1 physical pixel - about 1.2 in fact.)
With printers, it's all much more predictable. Printers are invariably able to report their resolutions correctly. So if you print something that's 96 WPF units high, you can be confident that it will be 1 inch high.
MSDN's documentation states that the FrameworkElement.Height property (for Silverlight) refers to:
The height, in pixels, of the object
However, for WPF it refers to:
a device-independent unit (1/96th inch) measurement
So, to answer your question... pixels for Silverlight, device-independent units for WPF.
The documentation refers to Pixels, however these are Pixels where there are 96 such pixels per inch. A line of Width 96 when display on a 120 DPI display will be 120 actual device pixels. Similarly such a line drawn on a printer output which has 600 DPI will be 600 pixels long.
They are Device Independent Units.
You can find more detailed explanations here.
I'm learning about WPF. WPF uses device-independent pixels. But I can't really understand them. Why are they better than device-dependent pixels, if most other apps are device-dependent and WPF apps aren't? Would they stick out?
The advantage of device independent pixels is that when specifying a UI you can determine the size that UI components will appear on the user's device, regardless of the user's screen resolution. Unfortunately, it's not quite as simple as that, as it requires the user to have various settings set 'correctly', and it can be overridden by a user who wants to change the resolution of their device (e.g. a partially sighted user who wants to run at a low resolution to make text easier to read).
In addition to the other link posted, you can also check out this one:
Is WPF Really Resolution Independent?
Note that you can turn on snapping a control to device pixels with the SnapsToDevicePixels set to true to avoid the blurriness that occurs when a horizontal/vertical line is drawn on the boundary between two device pixels.
Before understanding device independent unit, it is required to understand what DPI is. DPI is dots per inch, that means there would be certain number (96 usually) of pixels in an inch . But what is important to understand is in Win32 environment this inch is not fixed in size as a physical inch. So when the number of dots increases / decreases by changing the resolution there would more / less number of dots in an inch as a result the "inch" size increases or decreases.
However in case of WPF the inch size is as good as a physical inch as a result every time the DPI changes the system adjusts it self accordingly.
It's about UI and font scaling depending on the system's DPI setting:
Not all applications are DPI-aware: some
use hardware pixels as the primary
unit of measurement; changing the
system DPI has no effect on these
applications. Many other applications
use DPI-aware units to describe font
sizes, but use pixels to describe
everything else. Making the DPI too
small or too large can cause layout
problems for these applications,
because the applications' text scales
with the system's DPI setting, but the
applications' UI does not. This
problem has been eliminated for
applications developed using WPF.
WPF supports automatic scaling by
using the device independent pixel as
its primary unit of measurement,
instead of hardware pixels; graphics
and text scale properly without any
extra work from the application
developer.
This is taken from the link Kishore provided. (http://msdn.microsoft.com/en-us/library/ms748373.aspx)
I’m creating a windows mobile app which uses a custom GUI. It has an image as background and some text and images rendered on it. I want to do as little image processing in the app itself, so I’m creating different skins for different screen resolutions. If I need to support another screen resolution I’ll just add another skin.
But what concerns me is that different emulator images have different sizes on their taskbars and menu bars, so the size of the actual form is not the same for all devices with the same resolution. So far I’ve found emulators where the taskbar and menu is either 104 (usually VGA, WVGA…) or 52 (QVGA, QWVGA…) pixels high. Do those menus always take up 52 or 104 pixels, or do device vendors or power users install things like a 3px high battery meter so the menu suddenly takes up 107 pixels?
From what I've seen with windows mobile, there is a standard screen size and the various emulator's sizes are scalings of that standard size IE 104px is a scale factor of 2 over 52px. In NETCF at least, the drawing API handled the scaling fairly well.
yep i remember having problems with this in the past as well - iirc the default bar size was a multiple of 26 or something (so 52 and 104 seems to fit) - i dont have the code here unfortunately, but i think it used something like this:
uint titleBarHeight = GetSystemMetrics(SM_CYCAPTION);
if(!titleBarHeight)
{
GetLastError()
..blah
blah..
}
i remember there being a problem with the apps detecting if the bottom button bar was present, but that might have just been the order i did things in at load-time..
hth
fusi