I am using Visual Studio 2010, C#, on Windows 7.
I have added a notify control to my project and set it to an icon I have imported to the project. The icon image is really good looking if I just preview it, but once I run my code and see it in the system tray, then it's really terrible, like the sides are dotted instead of straight lines and so on. I have tried 16x16, 24x24, 32x32 and 48x48 of the same file but I am having terrible results.
Have I missed anything?
myNotifyIcon.Icon = SysDir.Properties.Resources.icon2_32_ico_rgba;
The problem with directly using the icon in your resources is that instead of choosing the right icon version in you icon file, the framework simply scales the default icon version to whatever size the notification area needs. That's why you are seeing jagged edges.
To get the best quality, you'll need to choose the right size in your icon by yourself.
First, instead of directly setting your NotifyIcon.Icon to an icon in your resources, create a new Icon instance. Doing so will allow you to choose a specific icon size in your icon resource. Using SystemInformation.SmallIconSize will get you the size the notification area needs.
So :
myNotifyIcon.Icon = new Icon(Properties.Resources.MyIcon, SystemInformation.SmallIconSize);
Now, SystemInformation.SmallIconSize always returns the right icon size, but only if your application is DPI-aware (otherwise, it always returns 16). If your application isn't DPI-aware, and it is used on a system where DPI-scaling is enabled, the line above will select the 16x16 icon in your resource, at it'll be scaled up to whatever size the notification area needs (in other words, ugly icon).
By making your app DPI-aware, SystemInformation.SmallIconSize will return the right size, taking into account DPI-scaling. For instance, if DPI-scaling is at 150%, SystemInformation.SmallIconSize will return 24 (16 × 1.5).
To make your app DPI-aware, simply add this to your app.manifest, inside the <asmv1:assembly> tag:
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
Edit:
The info I am linking seems to be suspect at this point. Try it out, but if it isn't working, then I suggest you edit your question to post screenshots of all your experiments (each icon size and how it gets scaled).
Original:
32x32x256 is the right size and color depth according to this link:
http://www.hhhh.org/cloister/csharp/icons/
But you have to be very careful when constructing that image:
Take a 16x16x256 image, and get it to look nice
Double it to 32x32 (careful not to blur or resample if doing this in a paint program)
The reason is that Windows will "resize" the 32x32 image to 16x16 by simply throwing away 3/4 of the pixels. The link above demonstrates this phenomenon with a couple screenshots:
Before:
After:
I'm not sure how much of the color-depth pickyness (256 colors only?)/resampling issues are still true on Windows 7, but it certainly seems to be the case on XP.
I use NotifyIcon in a C# WinForms application and no matter what the icon I use contains, after 2 resolution changes it ends up blurry.
My best guess is, that windows doesn't actually rescale the original every time but rescales the (already rescaled) version from the icon cache.
The only solution I found so far was setting the icon again after a resolution/dpi change:
SystemEvents.DisplaySettingsChanged += (sender, eventArgs) => {
trayIcon.Icon = MyIcon;
};
I tried all kind of resolutions and bit depths in the icons but they all got blurred eventually. Now I only use a single 16x16 32b image in the icon and so far it works great on all tested displays.
Related
I am developing a WinForms application in C#. It uses a panel to draw an image of the Mandelbrot fractal. In the manual for the program and whenever I post about it somewhere, I recommend people to set their scaling setting to 100%, as otherwise the images won't look nice. This is because on other settings, the image is scaled up after drawing it, and it becomes blurry. All other controls are blurry too.
For example: my panel is 500x500. The scaling in my Windows is set to 125%. When I run the program, the panel is internally still 500x500, but it appears as 625x625, blurry. Instead, when the program is run, I want the panel to internally resize to 625x625, and appear as 625x625 too.
I have found the following solution: I found out about SetProcessDPIAware() (from here). Setting that makes the window not scale (it appears as if it was at the 100% scale setting), but the text does (and without becoming blurry). I can then, at the start of the program, calculate the appropriate multiplier (dpi = DpiX / 96) and give that to a huge method that includes commands like
xentrylabel.Location = new Point((int)(xentrylabel.Location.X * dpi),(int)(xentrylabel.Location.Y * dpi));
xentry.Location = new Point((int)(xentry.Location.X * dpi), (int)(xentry.Location.Y * dpi));
xentry.Size = new Size((int)(xentry.Width * dpi), (int)(xentry.Height * dpi));
One for every control property that might need to be updated. While writing this question, I got this idea and got started with it. However, I realised that this will need very many lines of code, so I wonder if there isn't a built-in way to do this. It seems like an option that many would like to go for, rather than their applications becoming blurry or hard to read on screens with high dpi.
Is this way of manually correcting positions and sizes the way to go, or is there a built-in way to scale the form for other DPI settings by actually scaling everything in the form, instead of scaling the end result?
Edit: From some comments it seems as if SetProcessDPIAware() alone should scale up everything. But in my experience, it doesn't. Here are some screenshots:
Application on 100% scale setting:
https://i.stack.imgur.com/pws9B.png
Application on 125% scale setting without SetProcessDPIAware():
https://i.stack.imgur.com/cE4Wx.png
Application on 125% scale setting with SetProcessDPIAware():
https://i.stack.imgur.com/oVA8W.png
We solved the issue of rendering controls for high DPI screens with scaling greater than 100% in Chem4Word by creating a WPF user control which is hosted in an ElementHost control, which is set to fill the form.
WinForm
+- ElementHost
+- WPFUserControl
Looking at your uploaded images, that's exactly the problem which is solved by using a WPF user control.
I've been working on a UWP application that will initially be deployed only to Surface Pro 4 (Maybe some SP3s) devices but I'm having a real difficult time getting my UI to fit on the screen.
Right now my Designer window is set to '12" Tablet (2160 x 1440) 150% Scale' with it locked in landscape mode (the only way this app will be used) so that the 'Effective: 1440 x 960' resolution is set.
I've got my MainPage page set to 960 x 1440 with a Frame for display content essentially filling the entire 960 x 1440 but when I run the app (either in full screen or windowed) it cuts off the content of my MainPage (not just the frame content but part of my app sidebar menu).
That all being said my question(s): How do I get my UWP to scale my content to fit inside what ever size window the app is displayed in when running (full screen or user adjusted window size), OR what settings do I need/How do I configure it to display my entire MainPage contents on my SP4 screen (2736 x 1824) in fullscreen without just trial/error adjusting elements manually until they fit.
I'm more concerned with the second question because I don't just want this app to do what I want (because I know I can figure it out myself by manually sizing elements) but I want to understand why it's doing what it's doing and the right way to go about doing what I want to do.
I did a lot of searching but could not find the answer to my question, if this is a duplicate please feel free to link the answer.
Thanks in advance.
The Designer just gives you a general guide on how things would look. The demensions are not for SP4 specifically.
At 150% DPI, try setting your MainPage to 1824, 1216.
You can call
ApplicationView.GetForCurrentView().VisibleBounds
at runtime to find how many pixels(epx) that your screen is currently set to.
Note that these are effective pixels. They are different from the physical pixels of the device. All UWP UI measurements are epx based. So when you see this -
<Button Width="24" />
You should know that the value 24 is measured in epx.
To find out what epx really is, give this a read.
I am having trouble making a NotifyIcon in Windows 10 whose icon resource looks anything but a blurry mess.
This happens with both icons from the SystemIcons class, or my own using Properties.Resources. I have tried creating a new instance of the icon with the Icon (Icon original, int width, int height) constructor, and all sorts of other mad things, including this nugget:
Icon ico = Icon.FromHandle((new Icon(Resources.InfoIcon, 256, 256).ToBitmap()).GetHicon());
to no avail. Any advice would be appreciated!
The poor icon in the screenshot is easy to address, you forgot to set the NotifyIcon.BalloonTipIcon property. Or use the NotifyIcon.ShowBalloonTip() method overload that takes ToolTipIcon. With ToolTipIcon.Info you'll get the high resolution system default icon. For example:
notifyIcon1.ShowBalloonTip(5000, "eDIDIO",
"Connected successfully!", ToolTipIcon.Info);
Which produces:
If you want your own icon to show up in this notification "balloon" then you have to work around a restriction in the ResourceManager.GetObject() method. Which is what you are using when you write "Resources.InfoIcon". GetObject() does not have enough arguments to be selective about the icon size you prefer. Use the code shown in this answer. Never use GetHicon() btw, it does a very poor job at color palette mapping and can only produce a 16 color icon.
Like I said in the title when i built to mobile the letter became too small. I think it is because phone has more pixel for his little screen.
Well I tried to fix text by simply making text to images in photoshop. But how can I make InputFields text (not the placeholder).
At a guess, your Canvas' CanvasScaler's UI Scale Mode is probably set to Constant Pixel Size, and if your mobile device's resolution is too high, text will appear small.
Try changing the UI Scale Mode to Scale With Screen Size and change the properties it provides as needed.
(if your Canvas doesn't have a CanvasScaler component, click the Add Component button and add it)
I am trying to take a screenshot of an application and I would like to make the parts of the rectangle that are not part of the applications region be transparent. So for instance on a standard windows application I would like to make the rounded corners transparent.
I wrote a quick test application which works on on XP (or vista/windows 7 with aero turned off):
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
// Just find a window to test with
IntPtr hwnd = FindWindowByCaption(IntPtr.Zero, "Calculator");
WINDOWINFO info = new WINDOWINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
GetWindowInfo(hwnd, ref info);
Rectangle r = Rectangle.FromLTRB(info.rcWindow.Left, info.rcWindow.Top, info.rcWindow.Right, info.rcWindow.Bottom);
IntPtr hrgn = CreateRectRgn(info.rcWindow.Left, info.rcWindow.Top, info.rcWindow.Right, info.rcWindow.Bottom);
GetWindowRgn(hwnd, hrgn);
// fill a rectangle which would be where I would probably
// write some mask color
g.FillRectangle(Brushes.Red, r);
// fill the region over the top, all I am trying to do here
// is show the contrast between the applications region and
// the rectangle that the region would be placed in
Region region = Region.FromHrgn(hrgn);
region.Translate(info.rcWindow.Left, info.rcWindow.Top);
g.FillRegion(Brushes.Blue, region);
}
When I run this test app on XP (or Vista/Windows 7 with Aero off), I get something like this, which is great because I can eek an xor mask out of this that can be used later with BitBlt.
removed dead Imageshack link - Screenshot
Here is the problem, on Vista or Windows 7 with Aero enabled, there isn't necessarily a region on the window, in fact in most cases there isn't. Can anybody help me figure out some way to build a mask like this on these platforms?
Here are some of the approaches I have already tried...
1. Using the PrintWindow function: This doesn't work because it gives back a screenshot taken of the window with Aero off and this window is a different shape from the window returned with Aero on
2 Using the Desktop Window Manager API to get a full size thumbnail: This didn't work because it draws directly to the screen and from what I can tell you can't get a screenshot directly out of this api. Yeah, I could open a window with a pink background, show the thumbnail, take a screenshot then hide this temporary window but thats a horrible user experience and a complete hack I would rather not have my name on.
3. Using Graphics.CopyFromScreen or some other pinvoke variant of this: This doesn't work because I can't assume that the window I need information from is at the top of the z-order on the screen.
Right now, the best solution I can think of is to special case Aero on Windows 7 and Vista to manually rub out the corners by hard coding some graphics paths I paint out but this solution would suck since any application that performs custom skinning will break this.
Can you think of another or better solution?
If you are here, thanks for taking time to read this post, I appreciate any help or direction that you can offer!
If you are looking for a finished application, there is 7capture, which captures also the translucency, so images can be saved to PNG format for later compositing.
EDIT:
The original question and comments indicate you are looking to produce a region on Windows Vista/7 that you can then use to mask out parts the captured image, as is done with Windows XP and non-Aero UIs. Using a region is not going to give you the result you are looking for, since the window outline is not computed as a region, but as an image with variable transparency - RGBA. The Alpha channel in that image is your mask, but it's not an on-off mask like a region, but a gradual mask with a range of values from pixels being fully included to being fully masked out.
Although it uses undocumented APIs, the code at http://spazzarama.wordpress.com/2009/02/12/screen-capture-with-vista-dwm/ will capture to a RGBA buffer which you can then use to render or save the image with the shadow and other translucency effects intact.
In DwmCapture.cs Change
BackBufferFormat = Format.X8R8G8B8
to
BackBufferFormat = Format.A8R8G8B8
(X8->A8)
And you should then be able to access both the usual RGB data plus transparency from the captured buffer. This can then be saved as a PNG or other format with alpha-channel for composing.
Removed idea that is terrible but would have been awesome back in the '90s
You say that using the DWM API only allows you to capture directly to the screen... could you create a window offscreen (say, X = -100000px, Y = -100000px) but visible (maybe even hidden?) and draw the screenshot to it? Since when using the DWM each window has a backing texture, I'm thinking it might still get drawn fine even though the target isn't directly onscreen.
Also, if you want to go the DirectX route and access the actual DX texture backing the window, I found a few leads that might help (especially the first link):
http://spazzarama.wordpress.com/2009/02/12/screen-capture-with-vista-dwm/
http://channel9.msdn.com/forums/TechOff/251261-Help-Getting-the-shared-window-texture-out-of-DWM-/
http://web.archive.org/web/20080625183653/http://www.aeroxp.org/board/index.php?showtopic=6286
http://www.youtube.com/watch?v=hRTgFTMnT_U
Using Graphics.CopyFromScreen or some other pinvoke variant of this:
This doesn't work because I can't
assume that the window I need
information from is at the top of the
z-order on the screen.
If you know which window you need the information from, can you bring it to the front, call Graphics.CopyFromScreen, and then reset its z-index? I know from experience that Aero does odd things when items are in the background in order to make their glass interface work correctly (partial rendering etc). This may not be great UX; however, it would be a special case and used only when Aero is turned on.
You can take a look at the source code of AeroShot, as described on the main page, it can capture rounded edges and with the Aero Glass transparency effect and save it to a PNG file. It's written in C#.