How do I achieve desktop overlay blur on Windows? - c#

When I was installing AMD graphics drivers on Windows 10, I noticed a blurred background look, which is a style I want to achieve in my application.
I have tried using UpdateLayeredWindow, but it does not apply a blur effect. I have tried using DwmExtendFrameIntoClientArea and DwmEnableBlurBehindWindow but I am unsure how to customize window coloring
and image overlays.
There is a DwmGetColorizationColor function, but there is no matching DwmSetColorizationColor function. There are ways to set system-wide coloring, but I would like colorization to affect solely my application window. Also, Aero Glass™ was removed from Windows 8 and 10.
How do I include these effects in my application using WinForms in a way that works on Windows 8/10? If WPF can render these effects, how does it do it and how do I achieve a similar effect on WinForms?

After months of searching, I have finally found the answer. To achieve the glass effect on Windows 10, one must use the undocumented SetWindowCompositionAttribute function in user32.dll.
BOOL WINAPI SetWindowCompositionAttribute(HWND hwnd, WINCOMPATTRDATA* pAttrData)
where the layout of the WINCOMPATTRDATA structure is:
struct WINCOMPATTRDATA {
DWORD attribute; // the attribute to query, see below
PVOID pData; //buffer to store the result
ULONG dataSize; //size of the pData buffer
};
and attribute can have values from the DWMWINDOWATTRIBUTE enum.

Related

Typesetting text with .NET

I'm writing a WinForms .NET program that needs to lay some text out on a page (with a few basic geometric/vector graphics). Is there an equivalent of OS X's Core Graphics and/or Core Text? So far, I am just using a PrintDocument and using the Graphics object provided by the PrintPageEventArgs to draw text on the page, but there's very little control over things such as interword spacing, interline spacing etc. and a lot of stuff has to be done manually.
I feel like I'm missing something; is there a better way for typesetting text on a page? I don't mind using 3rd party solutions as long as they are free for personal use.
This will be used for typesetting a small variety of documents, including one-page brochures/fliers (where most text is variable but images are static), award certificates (where most text and images are static but some text is variable), timetables, etc.
WinForms
When you use WinForms it is close to impossible to do proper type setting and yes, almost everything must be done manually. There are a couple of reasons for this:
You don't get detailed glyph information
The text measurement is horrible inaccurate, both the GDI+ and the GDI based version.
Windows Presentation Foundation
If you use WPF this is an entirely different matter as you get detailed geometrical information about each glyph.
However, you can interleave the two, a bit messy, but possible. Although, I do not recommend it as the graphics and bitmaps are not directly interchangeable which can result in slow performance.
If you want to look at the possibility you need to import the System.Windows.Media into your project to access the typeface and glyph capability of WPF.
You will meet a couple of other challenges as well:
The font lists between WinForm and WPF are not identical (more font and font types with WPF).
You cannot just use a WPF glyph and draw it to a WinForm bitmap.
The values from the glyph are, as expected, in em so they need to be converted to pixels based on point size.
However, you can get this (not limited to) information:
All details (too many to list here):
http://msdn.microsoft.com/en-us/library/system.windows.media.glyphtypeface.aspx
Conclusion
But if you stick with GDI+ and WinForms the best approach you can take is probably to use the GDI based TextMetrics class.
You will in any case experience possibly padding issues, you cannot set char spacing and so forth.
You will have to calculate baseline for each typeface and size by using top + ascent:
FontFamily ff = myFont.FontFamily;
float lineSpace = ff.GetLineSpacing(myFont.Style);
float ascent = ff.GetCellAscent(myFont.Style);
float baseline = myFont.GetHeight(ev.Graphics) * ascent / lineSpace;
PointF renderPt = new PointF(pt.X, pt.Y - baseline));
ev.Graphics.DrawString("My baselined text", myFont, textBrush, renderPt);
I do not know of any third-party library that can do this within the WinForm environment, I believe for the reasons mentioned here and the pain it would cause.
In conclusion I can only recommend you to take a look at Windows Presentation Foundation/WPF for a better ground to achieve proper type setting as you will get stuck in a lot of compromises using WinForms for this (I made a font viewer which is where I came across WPF as I wanted to show glyphs and detailed information about it including black-box and so forth - that was painful enough).
UPDATE:
WebBrowser as type-setting engine
A possible work-around of this is to use the WebBrowser control to do the setting. It's not an actual hack, but a bit hack-ish as it establish a initially unnecessary dependency on the IE browser on the user's computer.
However, this can turn out to be flexible when it comes to type setting as you have the same simple controls over text as with any HTML page.
To get a result you attach the HTML with styles and attributes for the text. You can even combine it with images and so forth (obviously).
The control can be for example on another hidden form not visible to the user.
After dropping in the WebControl on the form or creating it manually setting HTML is done in a single step:
WebBrowser1.DocumentText = "<span style='font-size:24px;'>Type-setting</span> <span style='font-family:sans-serif;font-size:18px;font-style:italic;'>using the browser component.</span>";
Next step is to grab what you render as HTML as an image which can be done as this:
using mshtml;
using System.Drawing;
using System.Runtime.InteropServices;
[ComImport, InterfaceType((short)1), Guid("3050F669-98B5-11CF-BB82-00AA00BDCE0B")]
private interface IHTMLElementRenderFixed
{
void DrawToDC(IntPtr hdc);
void SetDocumentPrinter(string bstrPrinterName, IntPtr hdc);
}
public Bitmap GetImage(string id)
{
HtmlElement e = webBrowser1.Document.GetElementById(id);
IHTMLImgElement img = (IHTMLImgElement)e.DomElement;
IHTMLElementRenderFixed render = (IHTMLElementRenderFixed)img;
Bitmap bmp = new Bitmap(e.OffsetRectangle.Width, e.OffsetRectangle.Height);
Graphics g = Graphics.FromImage(bmp);
IntPtr hdc = g.GetHdc();
render.DrawToDC(hdc);
g.ReleaseHdc(hdc);
return bmp;
}
From: Saving images from a WebBrowser Control
Now you can place the bitmap on to your normal page. ..Or just use the control directly on the form with reduced interactive capability (right-click menu could easily become a problem if not).
Not knowing the exact usage that this is for, this may or may not be a suitable solution but it gives some powerful options and can be in place of a third-party solution.
Components
Looking high and low it seem that this area is not so much targeted. I could find one component that comes close but the pattern continues: one will be hitting a nail with a sledgehammer. It ends up in the same category as the WebBrowser work-around.
This component is really a full fledged editor but by disabling most of it it can perhaps be used to simply display formatted text/graphics with type setting sort of at hand:
http://www.textcontrol.com/en_US/products/dotnet/overview/
Another possibility is to use a PDF component to set up the content and use a component to render the PDF as graphics (commercial):
http://www.dynamicpdf.com/Generate-PDF-.NET.aspx
http://www.dynamicpdf.com/Rasterizer-PDF-.NET.aspx
Non-commercial:
http://www.pdfsharp.net/?AspxAutoDetectCookieSupport=1
Using GhostScript to get image:
http://www.codeproject.com/Articles/32274/How-To-Convert-PDF-to-Image-Using-Ghostscript-API
The obvious static alternative
..and corky perhaps, but in any case I'll include it as simplicity sometimes works best -
If it is not a absolute requirement to be able to create these pages dynamically, generate all the text and graphics in Illustrator/Photoshop/inDesign etc. and save the result as images to be displayed.
In order to lay down text: there are several possibilities:
A simple label, that lets you simple text manipulation (like font, placement, color, etc.)
A rich text document that you may change the properties of the control to suite your needs, keep in mind that this one may present some simple images, etc.
An image -> that you may create dynamically, with the graphics object, with the onpaint event. this is not recomended, as its a very low level approach, but as you know as low level as you get, the more power you gain.
Combination of many controls, in a custom control you create, that you hold the information you want to draw / write in local members -> then keeping cont to when you change something, then set a flag (_needToBeRepainted = true;), and then on repainting, if(_needToBeRepainted) draw everything.
please let me know if you need further assistance solving this one.

Why Repaint the Windowless Control using DirectShow(.NET)?

I am playing a video using IVMRWindowlessControl9 i.e. WindowlessControl w/ VMR-9. When I initially had difficulty setting the video up, I noticed many examples found online had this piece of code in the Window's Paint handler:
IntPtr hdc = e.Graphics.GetHdc();
int hr = 0;
hr = windowlessCtrl.RepaintVideo(this.Handle, hdc);
e.Graphics.ReleaseHdc(hdc);
My video is playing correctly yet I do not have the above code. What does the above code do and is there a point in using it?
In most cases you don't need to repaint the video explicitly because the video renderer does it automatically. Yes, if the hosting window needs - for any reason - to request forced replaint, such as as part of WM_PAINT window message handler, then RepaintVideo method is here at your service.
See more on MSDN, VMR Windowless Mode:
During playback, the application should notify the VMR of the
following Windows messages:
WM_PAINT: Call IVMRWindowlessControl::RepaintVideo to repaint the
image.
As to what it does:
if the video is being drawn using a destination colour key, then it paints the key colour into the destination window.
if the image is letterboxed, or part of it falls on another monitor, it will paint the parts that are not covered by the image.
So it may be that you won't see any difference if it is not done at all, if none of these things apply.

How to get Windows 7 aero selection color?

How can I retreive system colors related to current Aero style? I especially need the colors used in the selection gradient. SystemColors structure does not contain required colors.
Alternatively: How can I use WinAPI to draw selection on the specific canvas (Graphics object)?
OK, so the answer to the initial question is: there is no way to determine the specific colors I asked for. It is evaluated by internal theming routines provided by the OS.
Fortunately, there is a way to ask the OS to draw a themed piece of control, so called part. .NET provides two classes for drawing UI:
System.Windows.Forms.VisualStyles for themed UI and
System.Windows.Forms.ControlPaint for non-themed "Windows Classic".
Selection I asked for may be drawn by the following code:
// Graphics g = ...
VisualStyleRenderer selectionRenderer = new VisualStyleRenderer(VisualStyleElement.TreeView.Item.Selected);
selectionRenderer.DrawBackground(g, someRectangle);
Unfortunately, neither TreeView.Item.Selected, nor ListView.Item.Selected is supported by the default window theme. However, one may switch theme to the Explorer using WinAPI via p/invoke:
// C++
SetWindowTheme(hwnd, L"Explorer", nullptr);
And then P/invoke his way through few UXTheme.h routines, which works perfectly.
The system-defined color of the background of the selected items which includes the selected text and selected menu items as well is located at System.Drawing.KnownColor.Highlight
You may then use the Color struct to get a color from a KnownColor
Example
System.Drawing.Color.FromKnownColor(System.Drawing.KnownColor.Highlight);
Thanks,
Happy Holidays! :)

Get drop shadow dimensions of window

I need to know the drop shadow dimensions of a window. I tried receiving values via the GetSystemMetrics WinAPI function, but I could not find the parameter to pass over.
Any idea on how I can get this value globally (or for a single window handle)? I know that the width of a drop shadow depends on the window type (dialog/normal/and so on).
Ibwould implement this functionality using C#, but C++ would also be fine.
There is a way using the DWM API to figure out the size of the drop shadow, however, it does not work until the window is visible.
In previous versions of Windows, there was the Client Rect, and the Window Rect. But ever since Vista came out, there has been a third Rect for a window called the Extended Frame Bounds. The third rect is larger than the Client Rect and smaller than the Window Rect, and excludes the area taken up by the drop shadow.
Call DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(RECT)) to read the Extended Frame Bounds rect. This function is from <dwmapi.h>, and is
not available in Windows XP or earlier.
Note that if you call this before the window has been shown, you will get incorrect results.
EDIT:
Note that Extended Frame Bounds are in physical pixel coordinates, and are not affected by the Scaling features of Windows. You may need to convert back to virtual coordinates, or convert the virtual coordinates to physical coordinates to make them match.
As far as I know there is no way of obtaining that information. Programs such as WindowClippings solve it by taking a screenshot and cropping to the shadow dimensions afterwards.

flickering in dot plot on windows 7 aero theme

We ported win-form application legacy code developed in c# .net framework 1.1 to c# .net 3.5.
There is functionality for drawing dot plot and apply different shapes(polygon,square etc.) on dots in plot.
You can change size of applied shape by dragging using mouse what happening is when dragging shape some part get invisible till we drop to new point and also draws very slow speed.
you can call it as flickering .
this functionality works fine in windows xp, in windows 7 works fine
with basic and classic theme
it flickers only when aero theme is applied in windows 7
i have tried
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/aaed00ce-4bc9-424e-8c05-c30213171c2c
and
Flickering in a Windows Forms app
none of them helped.
after time stamping execution time i found that
for (int i=0; i < arraypnts.Length - 1; i++) {
g.DrawLine(Pens.Black, arraypnts[i], arraypnts[i+1]);
}
// draw the last line
g.DrawLine(Pens.Black, arraypnts[0], arraypnts[arraypnts.Length-1]);
takes hell lot of time when aero theme applied compared to basic theme applied
I had a similar problem long time ago and after a while finally found the solution by redrawing components only when setting the Object visibility to false first.
Object.Visible = false
//redraw your components
Object.Visible = true
I dont know if this is possible in your case but worth a try!
I think you need to use double buffer for you form object.
this.DoubleBuffered = true;
Well I found a workaround for the flickering problem. Just disable the desktop composition — you can do it either at application level or OS level.
For application level, go to exe file -> right click -> compatibility-> check disable desktop composition.
Foror OS level (and better visual appearance), start->right click
computer -> properties -> Advance system settings -> Advance tab ->
performance settings -> visual effects->custom-> uncheck Enable
desktop composition.
“works fine with Aero off” …sounds like a recourse issue to me…. Are you drawing in a paint event? If not where are you obtaining your graphics object from? You can programmatically disable desktop composition, I need it for some projects I do… but nothing related to drawing…
[DllImport("dwmapi.dll")]
private static extern int DwmIsCompositionEnabled(ref bool enabled);
const uint DWM_EC_DISABLECOMPOSITION = 0;
const uint DWM_EC_ENABLECOMPOSITION = 1;
[DllImport("dwmapi.dll", EntryPoint = "DwmEnableComposition")]
private static extern uint DwmEnableComposition(uint compositionAction);
usage:
DwmEnableComposition(DWM_EC_ENABLECOMPOSITION);

Categories

Resources