I am trying to use API GetBkColor and GetSysColor(COLOR_WINDOW) to get color of window but its giving me wrong value.
When I get color of wndow by using some tool its diffeent from what I get from API.
Any suggestion of how to get right value of color?
In case if window is using gradient color then how can I find the color at particular pixel?
GetBkColor returns value of a COLORREF value for the current background color on success. To obtain red, green and blue components of the color, use the GetRValue, GetGValue, and GetBValue macros, respectively. Is that what do you need? OR what kind of "right value" do you mean?
To obtain a pixel color, use GetPixel function:
COLORREF color;
HDC hdc_ = GetDC(NULL); //get dc of whole screen
color = GetPixel(hdc_, x, y);
Hope this will help you somehow.
GetBkColor tells you the current background color for text, but the window may change it as it draws, so this isn't going to give you the value.
GetSysColor(COLOR_WINDOW) is the recommended default color for a window given the current color scheme, but many windows choose a different color. You can try to get the WNDCLASS for the window and check the hbrBackground field, but not all windows rely on that mechanism for setting its background color.
To get the color at a particular pixel, you can use GetPixel. This is fine for sampling a couple pixels, but don't try to read every pixel in a window by calling this a zillion times--it's too slow for that.
Related
I'm trying to do something like what Auslogics Disk Defrag does with its custom window:
As can be seen, the blurred semi transparent shadow surrounding the window is much darker than the standard one, so the program must be drawing it by itself. The problem is, I can't find a way to paint anything transparent around a window.
In an answer to a similiar question, someone suggested creating a slightly bigger transparent window (using WS_EX_LAYERED + SetLayeredWindowAttributes()) behind the actual application window, and then do the translucent drawing on the transparent one. Not only does it sound like an ugly hack, it doesn't actually work. If, for example, one tries to draw a semi transparent black rectangle on a transparent window via GDI+, alpha blending is applied to the shape's color over the window background color (which would also be the transparency color) and then the shape is drawn with the calculated color, which obviously is not the window transparency, resulting in an opaque rectangle.
The semi transparent shadow is actually done by Gaussian Blur of the black square.
You can use this effect to create glows and drop shadows and use the
composite effect to apply the result to the original image. It is
useful in photo processing for filters like highlights and shadows.
You can use the output of this effect for input into lighting effects,
like the Specular Lighting or Diffuse Lighting effects, because the
alpha channel is blurred, too and lighting effects use the alpha
channel to determine surface geometry as a height map.
This effect is used by the built-in Shadow effect.
Refer: Gaussian blur effect
Then remove the standard frame, the entire window is your client area, so you can draw shadow in the extended frame.
Refer: Drawing in the Extended Frame Window
I think I've found a solution that works for me. I was hoping I wouldn't have to create an extra window just for the shadow, but every method I could find or think of would require me to draw all the controls by myself and/or somehow correct their alpha values.
So, I'm using a layered window with per pixel alpha. I paint over it with Direct2D, or, alternatively, I use some PNGs with transparency for the edges and corners of the shadow and copy them on a memory DC. Either way I simply recreate the shadow with the right dimensions when the window is resized, and call UpdateLayeredWindowIndirect. Both methods seem to be working well on Windows 7 and 10, and so far I haven't found any glitches.
Preventing it from showing on the taskbar was a bit tricky. All the ways I know have drawbacks. What worked best for me was making the layered window owned by the main one. At least that way it will only be visible on the desktop where the program is actually running, unlike other alternatives which would force it to show on every virtual desktop. Finally, because I disable that window, I interact with it by processing WM_SETCURSOR.
I know how to get the colour of a certain pixel on the screen via:
HDC dc = GetDC(NULL);
COLORREF color = GetPixel(dc, x, y);
However, GetDC retrieves the whole screen if the parameter is NULL. How would I get it to retrieve the colour of a specific pixel for a program, say for Notepad instead of the whole screen?
Please note I'm pretty new to C++ so it would be good if you explained it in layman's terms.
I have a written a class which is able to display animated GIF files with Direct 2d as in this example from MSDN:
https://code.msdn.microsoft.com/windowsapps/Windows-Imaging-Component-65abbc6a/sourcecode?fileId=127204&pathId=969071766
The GIF which I display is a continuously growing/shrinking not filled blue circle. All other pixels are White / the Background is White.
Unlike the example posted I create a CWnd, without Caption and Border, with the size of the GIF, with a ID2D1RenderTarget filling the whole CWnd and place it above the Content of my MainFrame.
Since I never used Direct2d before I assumed I can simply apply SetLayerdWindow() on my CWnd to reach my goal of only displaying the blue Circle.
SetLayeredWindowAttributes(RGB(255,255,255), 204, LWA_ALPHA | LWA_COLORKEY);
This should result in a CWnd with no White Pixels + 80% Transparency. Unfortunately the resulting Window is 80% transparent but none of the WhitePixels where removed/ the white pixels are still drawn.
Why does LWA_COLORKEY not work in this case?
And how can I achieve that either my CWnd or ID2D1HwndRenderTarget will draw white as fully transparent?!
Note:
Besides that I've tried just for fun to draw a fully transparent background with the ID2D1HwndRenderTarget like:
m_pHwndRT->Clear(D2D1::ColorF(D2D1::ColorF::White, 0.0f));
With Microsoft stating: "The alpha value for the color to be constructed. An alpha channel value ranges from 0.0 to 1.0, where 0.0 represents a fully transparent color and 1.0 represents a fully opaque color. The default value is 1.0."
Which results in a fully white opaque window... Which made me wonder if this whole Transparency stuff is working at all
I'm displaying a bitmap using GDI+. After loading the bitmap from a DLL resource I set the background colour (blue - #0000FF) to transparent using TransparentBlt. On Windows Vista and later this works as expected.
However, on a Windows XP system we're testing on this only works when any tooltip (e.g. the "title" property in IE, or Windows Explorer's tooltip shown when hovering the mouse over a file, etc) is displayed. The rest of the time the background colour is still blue.
Has anyone encountered this before, or know of a way to stop this occurring and for the blue to be properly made transparent?
Edit: After further investigation I found that setting colour depth in Windows XP to 16 bit colours instead of 32 bit colours caused TransparentBlt to start working normally again. Obviously this isn't an ideal solution, specifying what colour depth must be used, but does this give any hint to what might be happening?
Edit2: Code sample included.
m_pGDIBitmap = new Gdiplus::Bitmap(_Module.m_hInst, MAKEINTRESOURCE(lImageResource));
m_hMemDC = CreateCompatibleDC(hdc);
Gdiplus::Graphics myGraphics(m_hMemDC);
myGraphics.DrawImage(m_pGDIBitmap,
Gdiplus::Rect(0, 0, m_pGDIBitmap->GetWidth(), m_pGDIBitmap->GetHeight()),
0,
0,
m_pGDIBitmap->GetWidth(),
m_pGDIBitmap->GetHeight(),
Gdiplus::UnitPixel, &imAtt);
SetStretchBltMode(hdc, HALFTONE);
SetBrushOrgEx(hdc, rcBounds.left, rcBounds.top, NULL);
TransparentBlt(hdc, rcBounds.left, rcBounds.top, iScaledWidth, iScaledHeight, m_hMemDC, 0, 0, iBitmapWidth, iBitmapHeight, GetPixel(m_hMemDC, 0, 0));
You must show some sample code - the code that loads the bitmap and the code that blits it to display.
From the symptoms that you describe, my guess is that you load the bitmap not in its native format, but in the current display format. This means, that when the bit depth of the bitmap differs from the bit depth of the display, an automatic color space conversion is made. When this happens, the color that you provide to TransparentBlt is actually different from the color in the bitmap.
Possible alternative solutions:
Make sure that the bitmap is loaded in its native format without conversion.
Allow the conversion to take place, but instead of providing a hardcoded color value to TransparentBlt, make a GetPixel of a known "transparent" pixel of the bitmap (like top-left), and provide this value to the TransparentBlt.
What I ended up doing was more of a workaround, but it did work. I changed the background colour to black and added the following code before the DrawImage call:
Gdiplus::ImageAttributes imAtt;
imAtt.SetColorKey(Gdiplus::Color(0, 0, 0), Gdiplus::Color(0, 0, 0), Gdiplus::ColorAdjustTypeBitmap);
For some reason using this with blue as the background didn't work and using TransparentBlt on its own with either colour didn't work, but the combination applied the transparency correctly on the various OSes and colour depths that I tried.
If I had access to a paint program that supported bitmap files with an alpha channel, i.e. 32 bit bitmaps, I suspect making the background explicitly transparent and then using AlphaBlend would have worked as well but I didn't have the ability to try that at the time.
I can't draw a pattern with a transparent background. This is my snippet :
bitmap.CreateBitmap(8, 8, 1, 1, &bits)
brush.CreatePatternBrush(&bitmap)
hbrush = pCgrCurrentDC->SelectObject(&brush);
// set text color
TextCol = pCgrCurrentDC->SetTextColor(CgrColourPalRGB);
int oldBkgrdMode = pCgrCurrentDC->SetBkMode(TRANSPARENT);
//draw polygon
pCgrCurrentDC->Polygon(CgrBuffer, n);
The doc on msdn doesn't mention anything about transparency. I guess this mode could be used? Or is this a bug ?
Thanks!
Mode TRANSPARENT means that background will not be filled before your brush is drawn. But your brush does not contain any transparent pixels in it and it redraws background pixels anyway. Fourth argument in CreateBitmap was set to 1 in your sample. That means bitmap is monochrome.
You need to use 32-bit bitmap to use transparency in brushes. GDI supports transparency with some limits. Use GDI+ for full transparency support.