I create my window using CreateWindowEx, but I only get an icon in the task bar; both the window's title bar and the icon that shows when I Alt+Tab show this type of dummy icon: . I set both the hIcon and the hIconSm fields in the WNDCLASSEX to the value returned from ::LoadIcon(hInstance, IDI_APPLICATION) (not NULL).
The .ico file itself was made out of a .png which I genereated through http://converticon.com to 16x16, 32x32 and 96x96 (what are the recommended sizes btw?). Could it be that I'm using the wrong sizes or color depth? If so, why does it work in the task bar (different size)? Thanks!
The icon must be defined as a resource somewhere. In your resource header there should be a line like this:
#define IDI_MYICON 1000
Then in your call to LoadIcon() it should be something like:
wc.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_MYICON));
If you're using Visual Studio it's pretty easy to add resources. Just right click Resources in the solution explorer.
Related
Problem description
I want to create a Windows API app in C which renders the menu and the caption buttons in the same non-client area, similar to Firefox
In order to do this, I've determined the solution needs to:
be type WS_POPUP, in order for the menu to be aligned to the top
take ownership of the non-client area (where the menu is rendered)
manually render the minimize/maximize/close buttons
The solution needs to work on Windows 7, 8, and 10 (and ideally future versions too).
How it looks now
I have a test program available on GitHub.
In my app, I've overridden the appropriate events:
WM_NCCALCSIZE, WM_NCHITTEST, WM_NCLBUTTONDOWN, WM_NCLBUTTONUP, WM_NCMOUSEMOVE, WM_NCPAINT
And then I repaint non-client areas on these events:
WM_NCACTIVATE, WM_SETTEXT
Here's an example of how I'm doing the rendering:
// globals set elsewhere
RECT customAreaRect, minRect, maxRect, closeRect, coverMenuRect;
BOOL maximized;
// ...
LRESULT OnPaintNCA(HWND hWnd, WPARAM wParam, LPARAM lParam) {
RECT windowRect;
HRGN hRgn = NULL;
GetWindowRect(hWnd, &windowRect);
if (wParam == 1) {
hRgn = CreateRectRgnIndirect(&windowRect);
} else {
hRgn = (HRGN)wParam;
}
if (hRgn) {
// Carve out the area for custom content
HRGN captionButtonRgn = CreateRectRgnIndirect(&customAreaRect);
CombineRgn(hRgn, hRgn, captionButtonRgn, RGN_XOR);
DeleteObject(captionButtonRgn);
// Force default painting for non-client area
LRESULT ret = DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
// black background covering part of menu, behind buttons
HDC hDC = GetWindowDC(hWnd);
FillRect(hDC, &coverMenuRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
HTHEME hTheme = OpenThemeData(hWnd, TEXT("WINDOW"));
DrawThemeBackground(hTheme, hDC, WP_MINBUTTON, partState, minRect, NULL);
DrawThemeBackground(hTheme, hDC, maximized ? WP_RESTOREBUTTON : WP_MAXBUTTON, partState, maxRect, NULL);
DrawThemeBackground(hTheme, hDC, WP_CLOSEBUTTON, partState, closeRect, NULL);
CloseThemeData(hTheme);
}
}
The rendered result looks like this:
Unfortunately, the styles used for the parts (minimize, maximize/restore, close) look like the styles for Windows 7/8, and not the native Windows 10 controls. I've been searching for a way to do this for several days without luck. I need help understanding how to render these buttons for Windows 10 using the Windows API.
Current status (and what I've tried so far)
My first hunch was that I need to properly enable Visual Styles.
Per this article, calls checking the OS version will get Windows 8 unless you specifically target Windows 10 via a manifest. Click here to view my manifest. This does work:
Before GetVersionEx returned major=6, minor=2, build=9200
Now GetVersionEx returns major=10, minor=0, build=10586
Per the official "Enabling Visual Styles" article, I made sure to use Common Controls version 6.
Added linker input for Comctl32.lib
Call is made to InitCommonControls on program start
Added dependency for version 6 to the application manifest
Here are some screenshots of relevant project settings that I have tried:
Other ideas
I'm running low on things to try. Before throwing in the towel, there were some things I was going to try:
Idea 1: using GetThemeStream which allows you to retrieve the size/bitmap for controls.
Load aero msstyles file like so:
HMODULE themeFile = LoadLibraryEx(TEXT("C:\\Windows\\Resources\\Themes\\aero\\aero.msstyles"), NULL, LOAD_LIBRARY_AS_DATAFILE);
Get the bitmap for the part (minimize button, maximize button, etc) like so (passing the loaded theme file):
GetThemeStream(h, WP_MAXBUTTON, MAXBS_NORMAL, TMT_DISKSTREAM, (void**)&buffer, &bufferSize, themeFile);
Load the bitmap; it appears to be in PNG format (I haven't gotten this far)
Draw the bitmap
Idea 2: copy the non-client area from a hidden window which has the caption area (and minimize, maximize, close buttons).
Create a window which has the caption and min/max buttons, never activating it.
In the non-client paint, get the DC for that Window and capture the pixels for the min/max/close button
Render them using bitblt
I think the issue comes from trying to use WM_NCPAINT on OS version >= Win Vista.
Since Vista all NC rendering is controlled by DWM (desktop window manager). If you still dare to handle WM_NCPAINT, DWM rendering will be turned off and you get "old-school" look:
From the Shell Revealed Blog:
The DWM doesnt have any legacy worries because applications cannot
draw inside the glass frame, since its rendered and managed by a
totally different process. If an application tries to do it, Windows
will detect it and remove the glass frame entirely (and therefore
revert to the Basic frame), so that the application can draw what it
wants to draw.
To get proper results, you have to do it the "DWM way" (specifically the sections "Removing the Standard Frame" and "Drawing in the Extended Frame Window"). This works by letting DWM render the frame within the client area, so you can paint over it. Also with this solution you don't have to draw the caption buttons on your own. This answer summarizes the required steps (under "Aero supported solution").
The caveat is that you propably have to draw the menu on your own and you can't use most of GDI API for that, because GDI ignores the alpha channel and things will look ugly if the frame is translucent (Vista and Win 7 by default, Win8+ with extensions). BitBlt() works if the source is a memory DC that contains a 32bpp bitmap with an alpha channel. GDI+ works aswell.
I could begin by asking the question outright or by citing my sources (this, this, this, and this) descriptively, but I'll walk you ll through what I'm trying to do instead.
Let's start with a main window. It has its own window class whose hbrBackground is set to COLOR_BTNFACE + 1. Now let's do
EnableThemeDialogTexture(hwnd, ETDT_ENABLE | ETDT_USETABTEXTURE)
so the tab control we're about to add will be drawn with visual styles. (Try Windows XP with the standard Luna theme for best results.) Now let's add a tab control and two tabs.
On the first tab, we create an instance (let's call it container) of a new window class. This window class is going to hold various controls. I could set hbrBackground to COLOR_BTNFACE + 1, but then it will draw over the tab background. So I want this new child window to be transparent. So what I do is
set the class hbrBackground to GetStockObject(HOLLOW_BRUSH)
set container's extended style to WS_EX_TRANSPARENT
set the class WM_ERASEBKGND handler to do SetBkMode((HDC) wParam, TRANSPARENT); return 0; to set the device context and have Windows draw the transparent background.
So far so good, right? I'm not sure if I'm really doing all this correctly, and I'd like this to also be flicker-free, which doesn't seem to happen: when I resize the window (at least in wine) I get either flicker or garbage drawn (even in child controls, somehow!). Windows XP in a VM just shows flicker. I tried tweaking some settings but to no avail.
But wait, now I want to have another control, one that just draws some bitmap data. On the next tab, create another container, then have a third window class area as a child of that. area only draws in the upper-left 100x100 area and has scrollbars; the rest of the window area should be transparent.
Right now, what I have for area is:
the window class hbrBackground set to NULL and styles CS_HREDRAW and CS_VREDRAW set
the extended window style being 0
the WM_ERASEBKGND simply doing return 1;
the WM_PAINT filling the entire update rect with COLOR_BTNFACE + 1 before drawing, and rendering all of it
This is flicker-free, but obviously not transparent. NOW I'm really not sure what to do, because I want the area to be transparent in such a way that it shows the tab control background. Again, I tried tweaking settings to bring them closer to what I tried above with container, but I got either flicker or invalidation leftovers when I tried.
So how do I get both of these custom control types (the container and the drawing area) to be both flicker-free and transparent?
I presently must target Windows XP at a minimum, though if the solution would be easier with Vista+ only I'd be happy to keep that solution on the side in case I ever drop XP support (unfortunately Stack Overflow doesn't let me hand out silver medals...).
Thanks!
To paint your window in a manner that is "flicker free", you will need to paint your window to a bitmap, then copy the bitmap to the destination device context. On Windows XP, you will need to create a bitmap, adjust the origin of the drawing DC and then paint your window. On Vista and later you can use BeginBufferedPaint and its associated routines to do the buffering for you.
Once you have buffered painting working, you can then use WM_PRINTCLIENT to paint your window's parent window into the your drawing DC before you do any actual drawing. Unfortunately, not all windows will support WM_PRINTCLIENT.
You could consider using DrawThemeParentBackground, rather than WM_PRINTCLIENT directly.
Combining these two methods together will leave you with transparent flicker-free drawing.
I am currently working on an existing Linux application called Xpad, which is a sticky notes application written in C. I try to implement transparency but I have a hard time achieving what I want. A sticky note looks like this.
I have a (toplevel) gtk_window with a gtk_textview.
If the background color of the textview is set with the function gtk_widget_override_background_color() to a transparant color (GdkRGBA where alpha value is smaller than 1), the color of the gtk_window behind it, becomes more visible.
However, I don't want to see the gtk_window, but the applications behind the gtk_window, such as the browser, libreoffice, or the desktop.
If the gtk_window is set to a certain transparancy, either with gtk_widget_override_background_color() or with gtk_widget_set_opacity(), the whole widget, including the window decorations become (partially) transparent.
To make the relations between the visible objects more clear, I have created a diagram of the different parts, and marked the place where I believe the transparency issue is taking place.
Anybody have any ideas how to make the textview background transparent, without making the window decorations transparent, so I can see whatever is behind this application?
Set a proper RGBA visual for the widget
w = //some GtkWidget or GtkWidget derived klass (i.e. GtkWindow)
gtk_widget_set_app_paintable (w, TRUE); // important or you will get solid color
// the next 3 lines should be wrapped in a func which is also hooked to "screen-changed"
GdkScreen *screen = gtk_widget_get_screen (w);
GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
gtk_widget_set_visual(w, visual);
gtk_widget_show_all(w);
g_signal_connect(G_OBJECT(w), "screen-changed", G_CALLBACK(screen_changed_contaniing_above_code), NULL);
Hi there just a quick question I hope someone can help me with I am loading a logo onto my dialog application into a static picture holder using the .rc file and adding this code.
ICON IDI_MYICON,IDC_STATIC_IMAGE,120,154,21,20
However my problem is this will only display a 64x64 image max and the banner I have loaded is 242x74 in size am I using the wrong method in using ICON? I did try bitmap but didnt work either.
Thanks
The 21,20 in your statement is the width and height of the icon control in dialog units. Dialog units vary depending on things like screen DPI and the font selected. There are typically 2-4 pixels per dialog unit. You've basically given the icon something on the order of 64x64 to display in.
To get the icon control sized pixel-perfectly, you can to resize it dynamically, e.g., during WM_INITDIALOG.
Also, I'm not sure which method the dialog box code uses to load the icon--some (like LoadIcon) restrict the size to a "standard" size which others (like LoadImage) do not.
When a child window of my application is opened and I view the ALT+TAB menu, the application icon looks pixellated. I assume that Windows uses a low resolution version of the icon (16x16 pixel I think). What can I do that Windows selects the right version which would be 32x32 pixel?
I assigned an icon to the window in question that has 16x16, 24x24, 32x32, 48x38 and 256x256 in true color. Please note that VS says in the proterties that 32x32 is used and that it works fine for the main window of my application where I assigned the exact same icon.
The caption bar of a Windows application window display icons in 16x16 pixels. The Alt-Tab list, however, shows icons in 32x32 pixels. It uses the same icon as is set for the window. If you only set a 32x32 one, the caption bar has to scale it down, which tends to look ugly as it uses nearest-neighbor interpolation. So how does one support both?
The answer is the ICO file! It supports embedding multiple icons in one file, typically the same (or similar) icon in various sizes and, less commonly, color formats.
Browsers, Windows, and others are typically designed to smartly use the appropriately sized variant within a given ICO file. So the answer is to have an ICO file with both sizes (or more) inside. The result is that the caption bar correctly uses the 16x16 version and Alt-Tab uses the larger 32x32 one.
The methods for saving an ICO file with multiple icons inside varies from program to program. However, GIMP can easily do it (and it's free). The trick is to have your variously-sized icons as separate layers. When you go to save it as an ICO file, GIMP will prompt you with the ability to set the size and color format of each layer. A good tutorial, with images, can be read here.
If anyone has any links or suggestions for creating multi-icon ICO files in other programs, feel free to add them. Also, I'm unsure if the Visual Studio built-in image editor can do it or not — I've rarely bothered with it.
Fixed the problem. I put the icon on the wrong form. As I don't think that this question will be of any help for anybody feel free to delete it.