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.
Related
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.
We need to overlay a target window with a custom shape and tracks the position of the target window such that the overlay drawing always appears above it. Also, the overlay drawing should appear in screenshots taken using BitBlt or PrintClient by screen-capturing tools like Camtasia, Debut, etc. Also, moving the target window around should not leave traces of the drawing at earlier location. The target window is not made using our code.
So far we've tried several ways but each method has its problems:
1) Layered Window:
Using a layered window as the child/owned window of the target window is the easiest thing and it works. But the problem is on Windows 7 and XP, layered windows do not appear in a BitBlt done without the CAPTUREBLT flag and the screen-capturing tools may call BitBlt without the flag, thereby skipping our window from the capture.
2) Region Window:
The crude approach to support all Windows versions then is to use a region window using SetWindowRgn and make the target window its owner. However, region windows are generally very slow in rendering complex shapes and also impact the performance of other windows, sometimes to the point of freezing the application. Region window also leaves traces on dragging the application window.
3) Subclassing and Drawing on HDC:
Another approach is to sub-class the target window and draw the shape on its HDC on the OnPaint() event inside the window procedure hook. The shape can be drawn on the desktop window instead too. The problem is that applications may draw without a paint event, like when some text is selected using the cursor, and such drawing may erase a part of the custom drawing. Tracking all possible paint events is not a good way to do this.
4) Drawing continuously in a timer:
The last resort is to draw the custom shape on the target window in a timer continuously so the drawing is always above the target, even on text selection. But this may show a bit of flicker when the text is selected. Not to mention, it is very performance heavy to draw constantly.
Question
What is the best way to achieve an overlay drawing which works on all Windows versions (since XP) at the same time appearing in screen-captures. We've exhausted all approaches. Is there some method I'm missing? Can the above mentioned ways be used with some improvement? Is DirectX an option? I'm looking for methods with fast rendering capacity to achieve this. Appreciate any help!
I think the best solution to draw an overlay window, is to use a double-buffered technique GDI, just like in this example:
Overlay Drawing in CScrollView
I have myself the same task, and the only solution was that one. Hope it help you.
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...
Is it possible to draw a custom shaped window in Qt which inherits color and transparency (glass) effects from current system theme. Ultimately I need it to look & feel just like user's taskbar adjusting to his theme. Like in this concept. I realize that it might not be possible to achieve such perfect integration, but at least make a custom shaped background which look the same as the taskbar (glass look&feel) I believe is achievable.
Partially it is answered in similar questoin - Displaying translucent / irregular-shaped windows with Qt. But still not sure how to read system theme information and apply it to QPainter.
The tricky part is that slope on the left. I'd wager you could get a title bar on a window to be taller and have the rest of the window be 0 height so the window was entirely a title bar but that slope would require rendering functions that just won't exist on Windows.
Also, you're wanting your window hide the taskbar's bevel under where your window appears. That will probably not be possible either as your window will be semi-transparent so it won't be able to block the rendered bevel of the normal taskbar.
Sorry. Might have to go back to the drawing board on your design.
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.