How are custom Windows Borders and styles done? - windows

I have seen a program recently that has got what appears to be a custom Window border.
I don't know how this is accomplished. If anyone does know then please do tell me as this is interesting.
I am mostly interested in something similar shown in the picture
Window example of what I am trying to accomplish

You must handle the non-client messages like WM_NCPAINT. Depending on your design you might need to call DwmDefWindowProc as well.
Use SetWindowRgn if you want XP style rounded edges or SetLayeredWindowAttributes for full alpha support and custom shadows.

Related

How to make CGWindowListCreateImage render correct background color?

Capturing an image of an off-screen window with CGWindowListCreateImage is a common way to create QuickLook style zoom-in animations, but this seems create an image with the wrong background colour, slightly lighter than the real window.
This causes a flash at the end of the animation which kind of ruins the effect.
Does anyone have any idea why this happens and what can be done about it?
EDIT: I created a demonstration app for this problem. It is a bit large and complex for a Stack Overflow question, but the relevant code is probably in the ZoomingWindow.m methods takeSnapshot and makeAndPrepareSnapshotWindow.
Setting the window appearance to textured in Interface Builder fixed this. Of course that also changes the color of the window, but that is acceptable in this particular case.

Changing the background of an edit control on getting focus

I want to change the background color of an edit control (i.e. regular EDIT window class) in that control's EN_SETFOCUS. I know that I should handle WM_CTLCOLOR, do SetBkColor() on the DC I get, and return a handle to a brush with the background color. HOWEVER, when I do that from EN_SETFOCUS, my control isn't invalidated or redrawn properly. Basically I get a 1-pixel border in the wrong color around my text; so a rectangle within the black border that is already around the control itself. If I move my mouse cursor over the control, some parts of that wrong border are redrawn correctly, and sometimes the whole artifact disappears after a small amount of time, as if some timer is causing a complete redraw.
I have tried invalidating the control in various places, RedrawWindow, SelectRgn(NULL) on the DC, playing with wS_CLIPCHILDREN and -SIBLINGS of the dialog, invalidating the dialog on the rect the control is at, but none of this works. I have also found a vague reference to a similar problem online in a post from 2001 (!) but no solution. Has anyone ever encountered this? Any ideas on other things I could try?
FWIW, this is using VS9 on WinXP, and using MFC, but I've also send messages 'by hand' and that didn't change anything, I don't think MFC in this case is the culprit. Of course I could be wrong :)
Edit:
Code of the dialog of the screenshots below (minimal sample) is here: http://pastebin.com/zepdhdp5 . This is a small wizard-generated app - nothing special, the full source code can be downloaded from https://www.dropbox.com/s/d8nxaryoo0vclue/edit_control_redrawing_sample.zip .
The control looks like this after it gets focus:
and like this when it loses focus:
As you can see, it looks like there a border around the text area that doesn't get invalidated.
I have tried to reproduce this with pure win32, but when I don't use commonctrl6, it doesn't exhibit the problem. I can't manage to get commonctrl6 to work in win32 though, so I'm suspecting now that it's got something to do with that.
Well what do you know - after another day of intermittently attempting various things and trying different angles in google searches, I found the magic keyword: non-client area invalidation. Which led me to http://forums.codeguru.com/showthread.php?307470-Invalidate-NC-area , which contains the solution:
SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DRAWFRAME);
(in the SetFocus/KillFocus handlers)
My theory of what's going on is that the commonctrl6 visual styles manager treats the border around the edit control as non-client area, and miscalculates the area to be invalidated by one pixel when the control gets the focus. SWP_DRAWFRAME seems to be the only thing that forces a complete update of the control, RedrawWindow() with RDW_FRAME didn't cut it.
Ah well, hopefully my question here at least saves someone down the line from wasting his time like I have...

Notification area flyout link area

I made a flyout window in the notification area using WinAPI and my goal was to make it similar to the flyout windows that show up when you click some of the icons in the notification area, like the Volume icon.
I already succeeded in making it look and behave similar to the other ones, but there is one thing I can't seem to figure out. The link area of the flyout windows has a darker blueish background and there is a subtle difference in the look between Windows 7 and Windows 8. A picture of it in Windows 7 can be seen here
http://msdn.microsoft.com/en-us/library/windows/desktop/aa511448.aspx#flyouts
I achieved this by painting this link area of my flyout window manually in the right colors (including the gradient at the topmost part of the section) using the WM_PAINT message, but I just feel like it's too much of a hack, especially because it's not affected by changing themes in Windows. For example, if I set the "Windows Classic" theme this area should be grey and not blue.
So, my question is, am I missing something in how this can be achieved without painting the window manually. I noticed that the details pane in Explorer windows in Win 7 has the same look. I've searched quite a bit for answers but I haven't found anything yet. This is my first time doing a GUI using the WinAPI so I have very little experience, and therefore I'm assuming there is something that I just don't know about.
UPDATE:
I did manage to figure out how to draw this area without painting it manually. It can be drawn by using the OpenThemeData and DrawThemeBackground functions
HTHEME aeroTheme = OpenThemeData(hWnd, L"FLYOUT");
DrawThemeBackground(aeroTheme, hdc, FLYOUT_LINKAREA, 0, &rect, &rect);
This obviously only works when themes are enabled, so for non-themed cases I draw a normal rectangle with the appropriate color.
I'm not an expert in WinAPI so I can't offer any advice on achieving the look you want without manual painting.
However, if you're successfully achieving the appearance for a particular color theme, I'd suggest you look at the GetSysColor function and use this when creating your brushes for painting. This should allow you to get the correct colors based on the theme that has been set. More info (including a swatch table) can be found here.
Hope this helps.

Windows Vista/7 glass completely broken?

I'm trying to get the media player glass effect for an application, but I'm facing roadblocks all around. Is it me, or is it the API?
I started by calling:
MARGINS margins = { -1, -1, -1, -1 };
HRESULT result = ::DwmExtendFrameIntoClientArea(m_hWnd, &margins);
And erasing the background to black on:
OnEraseBkgnd
Everything was fine until I added an edit box. With EditBox, places where black text appears are replaced with glass. The problem is blown out of proportion with more advanced controls like ComboBoxEx and that like. Those start to look like mess.
The bright side with this approach is that the alpha blended images look alright. And are gradually blended into the glass.
The solution for edit boxes seems to be using WS_EX_LAYERED with LWA_COLORKEY and using some awful color for glass masking, and erasing the background to that color. Unfortunately this breaks other things. The alpha blending on icons looks super ugly with shadows blended to radioactive green, and the glass itself becomes click-throughable, even though I don't have a WS_EX_TRANSPARENT style on the window.
The third suggestion is sort of custom composition with GDI+, but that seems to be a bad approach, since GDI+ is a software fallback, and I can't find a way how to render EditBox or ComboBoxEx to an image that I could use for composition later.
Am I missing something?
The sources at SO also seem to face the same problems:
link1
link2
Kenny Kerr wrote an excellent article on displaying controls on glass, using edit controls as an example:
http://weblogs.asp.net/kennykerr/archive/2007/01/23/controls-and-the-desktop-window-manager.aspx
The simple answer is, you cannot do this.
All the standard controls render themselves with normal GDI calls. Normal GDI calls are alpha unaware and mostly set the alpha channel to zero.
The more complicated answer is, you can: There are some samples on the net where standard controls are mixed with aero glass. They fall into two basic categories:
WinForms (.NET) samples. WinForms don't actually use the native controls - the WinForms controls are all rewritten versions that, amongst other features, blit using alpha aware routines. This example is depressingly simple and makes me realize how much Microsoft hate native developers.
Subclassed samples: The only way to get the regular/native controls to paint on aero glass is to sublclass the controls, catch WM_PAINT messages to create a DIBBitmap, call WM_PRINT to render the controls content onto it. Use the DWM functions to repair the alpha channel data. Paint the resulting alpha'd bitap yourself using AlphaBlend.
This article on CodeProject contains a reference implementation that subclasses most of the standard controls rather well.
Try changing your text/foreground color on controls like the edit box to something "almost black" (like #010101). Then you should be able to skip the other rendering issues except alpha transparency for images/icons.
Edit: Drawing other stuff - might be some weird approaches to handle compatibility, but then again classic apps aren't glass themed by default ... don't know. Just try to avoid drawing stuff yourself, if possible.

Creating a quick look style zooming effect

I would like to create an effect than an image zooms up from a thumbnail size to full screen.
I am not sure what's the right steps to achieve this. Should I create a transparent full screen window and animate a layer on top of it?
Take a look at this CoreGraphics example. Specifically, take a look at the "grow" and "shrink" animations. That's how Apple does it, and that's what you'll want to do too.
Your solution of a transparent window with a CALayer inside is probably the best supported way to do it.
One thing that seems like it should be a good solution (at least it's the first thing I thought of when I wanted to do this) but isn't is NSView's enterFullScreenMode:withOptions:. If memory serves, it was originally meant to do what you're talking about here, but the animation was taken out and it generally doesn't work that well now.

Resources