What I want to do is force the main frame window background color to be completely transparent.
The only very first method I've found so far is the SetTransparent(wxByte alpha)function. However, this seems to be setting the transparency for the children controls as well - and I don't want that.
I've been trying multiple ways to achieve that, none worked though. Also, most questions regarding this seem to be outdated. Is there any working method (for Windows) which will allow me to set the full transparency for the main frame window?
#Jerry Coffin pointed me in the right direction and I have made a working solution for this. However I still think that mixing both WinAPI and wxWidgets is not the best idea. But well, it works.
wxColour transparentColor = wxColour(wxTransparentColour);
SetBackgroundColour(transparentColor);
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
SetWindowLong(GetHandle(), GWL_EXSTYLE, GetWindowLong(GetHandle(), GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(GetHandle(), transparentColor.GetRGB(), 255, LWA_ALPHA);
SetLayeredWindowAttributes(GetHandle(), transparentColor.GetRGB(), 255, LWA_COLORKEY);
Related
I'm making this app in Haxe which compiles to C++ code. I'm using the SetLayeredWindowAttributes() function to set the background of the window to be fully transparent. The problem is that this works completely fine only on certain monitors, but not on others.
If I launch the app on my main monitor, which I believe to be 32-bit (if that matters), the background doesn't change at all, or will flicker and then completely disappear until I focus another window.
However, if I connect another monitor and run the app on that one, the background does become transparent, and the transparency persists even if I move it back to my main monitor. Even with the 2nd monitor connected at the same time. If I launch it on the main one, transparency fails.
I have tried changing the color values between 0xFFffffff/0xffffff, etc, but no combination of these work.
This same problem occurs even on a completely different machine with different hardware than mine. My hardware: Lenovo Ideapad L340-15IRH, i5-9300H, Gpu(s) Gtx 1650, Intel HD 630.
Please help me, what am I doing wrong?
Code to enable transparency, using windows.h inside a C++ function:
HWND hWnd = GetActiveWindow();
res = SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 0, LWA_COLORKEY);
Code which creates the transparent background, in main haxe code:
transparentsquare = new FlxSprite(0, 0).makeGraphic(screenW, screenH, FlxColor.WHITE);
add(transparentsquare);
It doesn't matter if I enable transparency before everything has loaded, I can enable it by pressing a key at any time and it still fails if I enable it after the app has fully loaded. Also, obviously graphics are not drawn in the C++ function but in the haxe code, so I can't use any fancy DirectX APIs and what-not.
When I bitblt onto my transparent window, a bmp smaller than the client area, it draws a fussy surrounding area instead of transparent like the set colorkey from:
SetLayeredWindowAttributes(hwnd, RGB(0,255,0), 120, LWA_COLORKEY | LWA_ALPHA); //colorkey & win alpha
The blit looks like this:
The candle-like test image makes its own area transparent like it should, but the surrounding client area gets grayed out according to the window-alpha value (120). Any ideas how to fix this? I've tried:
SetBkColor(hdc, crKey); and generating a background with
FillRect(background_hdc, &background_rect, hbrush); and blitting that first
Where neither work.
I have the feeling this should be alot easier than I'm making it out to be, and I still feel something like SetBkColor(hdc,crKey); should do the trick, but it doesnt. Maybe there is a similar command that does that I'm looking for?
Isnt it funny how you solve the problem just after you formulate it properly?
Obviously the hbrBackground in the WNDCLASSEX wc;
defines the background of the window. So by setting the brush background when registering the window like so:
wc.hbrBackground=CreateSolidBrush(RGB(240, 20, 120)); //COLORREF==crKey
it gets crKey cancelled out during the blit along with the bmps crKey color. Thanks.
I have met an exactly problem which metioned in the MSDN Topic:DWM Blur Behind Overview.
After DwmEnableBlurBehindWindow was called, the client area became a beautiful glass, but unfortunatly, all of black text on the controls(BUTTONs,EDITs,STATICs etc) became transparent too, just like that Topic on MSDN.
Any way to fix this?
By the way, My develop env is VC++ 6.0, and I have to draw some glowing text with DrawThemeTextEx API, so I can't use DwmExtendFrameIntoClientArea simplely. I MUST use DwmEnableBlurBehindWindow to enable the glass effect of client region.
Thanks a lot!
2012/6/19
Update:
By changing the TRANSPARENT KEY COLOR of a window to a non-black color with "SetLayeredWindowAttributes", then using "DwmExtendFrameIntoClientArea" can solve the caption text problem of CONTROLS(BUTTONs,EDITs etc) on the glass window.
But in this way, "DrawThemeTextEx" could not work properly. It looks like that DrawThemeTextEx could only use the RGB(0,0,0) as its TRANSPARENT KEY COLOR.
So, is there any API could change the TRANSPARENT KEY COLOR which used by "DrawThemeTextEx" within ?
My ultimate goal is to draw some glowing text on a glass(Aero) window without the "DwmEnableBlurBehindWindow" side effects which metioned in the MSDN Topic:DWM Blur Behind Overview,http://msdn.microsoft.com/en-us/library/aa969537.aspx.
And if there is another way to do it, I'm very glad to hear :)
And thanks a lot, again! :)
Take a look at Painting the caption title in MSDN:
Find the line HBITMAP hbmOld = (HBITMAP)SelectObject(hdcPaint, hbm); in the example.
Then, add this line after it:
// You should have set RGB(200,201,202) as the transparency key
FillRect(hdcPaint,&rcClient,CreateSolidBrush(RGB(200,201,202)));
Although the effect does not seem to be perfect, it solves the problem.
Reference: C++ WinAPI Conflict between SetLayeredWindowAttributes and BitBlt
I am having a strange problem ( well, at least i find it strange =) ). I am writing my own GUI library, which is a wrapper around windows api (and yes, i am aware of WTL and frameworks like MFC =) ). At the current stage i have incapsulated common controls in such manner: for example, Edit class consists of a simple window and an standard edit window above it ( MainWindow -> GhostWindow -> EditBox ). That is how i can for example change a background colour of an edit inside an edit class itself:
myedit->SetBkColor ( RGB ( 0, 0, 0 ) );
And it worked fine, until i called InitCommonControlsEx and attached manifest file to my program. After doing this, my edits become capable of changing colours only when they have focus. To be honest, i don't have a comprehensive thoughts about why do the behave like this and what am i doing wrong, so i will appreciate any help.
Thank you, #535.
When you attach the version 6 manifest, the call to InitcommonControlsEx becomes unnecessary.
Anyway. with the version 6 common controls loaded, XP theming is used even for the standard windows controls. The background colors for the controls are painted using the xp-theme color, so the WM_CTLCOLOR* messages are used less.
You are currently overriding the coolor of various control elements using the WM_CTLCOLOR* messages?
Well, everything is much easier, than i thought. I was just too inattentive =( When one don't use styling, one cane use ::SetBkColor(...) to change background colour, and return a brush from WM_CTLCOLOR* to change a border colour. Things become different after enabling styling. Now ::SetBkColor(...) correspond to focus colour and returning brush changes background colour. Shame on me =(
I'm wondering how to make a window transparent, not cutout holes or the same transparency overall.
Well, just say I want to slap a PNG image of a rose or something and have it blend nicely with stuff behind and allow stuff behind to redraw and have their changes shine through the transparent parts of the picture/window.
I could (or would like to) use something like wxWidgets or OpenGL. But rather not Qt or GTK.
I found out that it's actually pretty simple to throw up a transparent picture on the screen using wxW:
wxScreenDC dc;
wxBitmap bmp(wxT("test.png"), wxBITMAP_TYPE_PNG);
dc.DrawBitmap(bmp, 250, 100, true);
Now I has to find out how to handle updates and such, it has to be ( maybe partially redrawn ) when something beneath updates.
As it is right now it just redraws itself ontop of itself, making it become fully opacue in a while.
There was another version of wxScreenDC::DrawBitmap that took a window as an argument, maybe it's that one solves this?
How about using shaped frames?
wxBitmap m_bmp = wxBitmap(_T("redroseonwhite.png"), wxBITMAP_TYPE_PNG);
SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
wxRegion region(m_bmp, *wxWHITE);
bool m_hasShape = SetShape(region);
Look *wxWidgets-2.9.0\samples\shaped* for the full example.
See wxTopLevelWindow::SetTransparent.
If the platform supports it will set the window to be translucent.
So I guess wxWidgets can do it.
If you are willing to do something other than C++, there may be other cross platform options like JavaFx and Adobe AIR.