C++ WinAPI Conflict between SetLayeredWindowAttributes and BitBlt - c++

I have created a custom window using DWM. I painted the caption by using PaintCustomCaption() ,which is an example from MSDN. It worked properly until I added SetLayeredWindowAttributes().
Window before adding
SetLayeredWindowAttributes(hWnd,RGB(0,0,1),0,LWA_COLORKEY);
After adding
I tried changing RGB values but it was still black except RGB(0,0,0).
I wonder if BitBlt() works properly.
Edited:
The reason I added SetLayeredWindowAttributes is to solve this problem
Do you have other ways to paint the caption?
case WM_ACTIVATE: {
DwmExtendFrameIntoClientArea(hWnd,&m); // m={-1,-1,-1,-1};
break;
}
case WM_INITDIALOG: {
SetWindowPos(hWnd,NULL,0,0,500,500,SWP_NOMOVE|SWP_FRAMECHANGED);
SetWindowLongPtr(hWnd,GWL_STYLE,WS_VISIBLE|WS_OVERLAPPEDWINDOW);
SetWindowLongPtr(hWnd,GWL_EXSTYLE,WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd,RGB(0,0,1),0,LWA_COLORKEY);
RedrawWindow(hWnd,NULL,NULL,RDW_INVALIDATE|RDW_ERASE);
return true;
}
case WM_PAINT: {
hdc=BeginPaint(hWnd,&paintstruct);
PaintCustomCaption(hWnd,hdc)
EndPaint(hWnd,&paintstruct);
break;
}

If you keep the window border, you don't need to paint the caption yourself unless you want to add something to your caption.
That is, handle WM_NCCALCSIZE and WM_NCHITTEST normally.

First, use RGB(200,201,202) as the transparency key instead of RGB(0,0,1).
You may try other values but it is the best one so far I have tested.
Then, add this after HBITMAP hbmOld=(HBITMAP)SelectObject(hdcPaint,hbm); in PaintCustomCaption():
FillRect(hdcPaint,&rcClient,CreateSolidBrush(RGB(200,201,202)));

Related

C\C++ - win32: how avoid flickers with transparent controls\child controls?

i have read several tutorials\threads(even from here) and i didn't get the property answer :(
for not draw the window backgound i must do(make the control\child control transparent):
case WM_ERASEBKGND:
{
return (LRESULT)GetStockObject(NULL_BRUSH);
}
break;
until here fine.
for avoid flicker i must use Double-Buffering way and the parent window must have the WS_CLIPCHILDREN style.
if the control isn't transparent, the flicker is out. when it's not transparent, the image is drawed 1 above other. if i use the FillRect() on WM_PAINT the control is 'clean' and then show the new image... but isn't transparent :(
what can anyone advice me?

Static Control Background Color with C++

I am creating a basic GUI with the Windows API and I have run into an issue. It starts with a main window that opens with a custom background color I set (RGB(230,230,230)). It then displays text in the upper left corner with the static control.
settingstext = CreateWindow("STATIC",
"SETTINGS",
SS_LEFT | WS_CHILD,
12,
20,
100,
20,
hwnd,
NULL,
proginstance,
NULL);
ShowWindow(settingstext, 1);
This works, but when the text is displayed I need a way to change the background of it to match the main window or else it just looks like it doesn't blend in.
My question is, how do I do this? I currently use the method below and it works, but I wanted to know, is there a way to permanently set the background color somehow, right after the CreateWindow function for the static control without changing system colors, and just have it apply to that one control and not anything that sends the WM_CTLCOLORSTATIC message. I have experimented around with using the GetDC function and SetBkColor function outside of the message loop but nothing works.
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC) wParam;
SetTextColor(hdcStatic, RGB(0,0,0));
SetBkColor(hdcStatic, RGB(230,230,230));
return (INT_PTR)CreateSolidBrush(RGB(230,230,230));
}
I want to do this because...
I don't want to fill up my message loop with functions that need to be called every time the window repaints.
Have the changes apply to only this static control.
I would be very thankful for any help that could be provided, at least pointing me in the right direction, thanks.
For static text controls there's no permanent way to set the text color or their background. Even if you want to apply the changes to a single static control; you would still have to handle WM_CTLCOLORSTATIC notification message in parent dlgproc just when the control is about to be drawn.
This is due to the DefWindowProc overwriting your changes to the device context each time it handles WM_CTLCOLORSTATIC as stated in the MSDN:
By default, the DefWindowProc function selects the default system colors for the static control.
static HBRUSH hBrush = CreateSolidBrush(RGB(230,230,230));
case WM_CTLCOLORSTATIC:
{
if (settingstext == (HWND)lParam)
//OR if the handle is unavailable to you, get ctrl ID
DWORD CtrlID = GetDlgCtrlID((HWND)lParam); //Window Control ID
if (CtrlID == IDC_STATIC1) //If desired control
{
HDC hdcStatic = (HDC) wParam;
SetTextColor(hdcStatic, RGB(0,0,0));
SetBkColor(hdcStatic, RGB(230,230,230));
return (INT_PTR)hBrush;
}
}
If you're looking to make the control's background transparent over a parent dialog you could use SetBkMode(hdcStatic, TRANSPARENT).
I think there is a permanent way to do it.
Just after you create the label,use GetDC() function to get the Device Context.
Then use:
SetTextColor(hdcStatic, RGB(0,0,0));
SetBkColor(hdcStatic, RGB(230,230,230)); // Code Copied from the above answer by cpx.
And it should do .
Have you considered subclassing the static window and doing owner draw?

Set background color of a control? (WinAPI)

How can I set the backcolor of a control (equivilant of control.backcolor in .Net). I tried setBKColor with no luck.
ex: TabHwnd = createWindowEx(NULL,WC_TAB....
then how could I set the back color of TabHwnd?
Thanks
Windows will generate a message when it's painting the background of a control, and it is up to your program to respond to the message appropriately.
WM_CTLCOLORBTN
WM_CTLCOLOREDIT
WM_CTLCOLORDLG
WM_CTLCOLORLISTBOX
WM_CTLCOLORSCROLLBAR
WM_CTLCOLORSTATIC
I know this question is old, but perhaps this answer will still help some others.
What worked for me was to return a hollow brush for the background color messages. For example:
switch (msg) {
case WM_CTLCOLORDLG:
return (INT_PTR)GetStockObject(HOLLOW_BRUSH);
case WM_CTLCOLORSTATIC:
return (INT_PTR)GetStockObject(HOLLOW_BRUSH);
}
Also, you don't need to worry about deleting the "brushes" created by GetStockObject.
Try subclassing (see SetClassLong) and process WM_ERASEBKGND

How to get CEdit to scroll properly?

I have a CEdit control that's used to display a diagnostics output.
Sometimes the data overflows the screen size, so naturally I set the Vertical Scroll property to true (MFC dialog editor).
But then, when I tried to scroll the text that was in the window before isn't cleared and the new text is written over it.
The result is a big mess of everything I have scrolled past.
I've looked for a draw background property or something similar that will erase everything in the window while scrolling (before redrawing the new data).
Any suggestions?
I think you might want to set Auto VScroll and Multiline to true, and Auto HScroll to false.
We were having a similar problem. We ended up having to invalid the region of the parent window to get it to update when we got WM_VSCROLL. I tried to do as user demorge says here:
SetBkMode(hdc, TRANSPARENT) doesn't work
But our code doesn't use handles, we actually use the class CWnd, so we ended up doing this in the WindowProc instead:
switch(message)
{
...
case WM_VSCROLL:
case WM_HSCROLL:
LRESULT answer;
PAINTSTRUCT ps;
CDC* pdc;
CWnd* MyParentHWnd;
// We want the scroll to work the same way it has always worked for our
// ancestor class. Let them handle the scrolling and save off their
// return.
answer = AncestorClass::WindowProc(message, wParam, lParam);
pdc = BeginPaint(&ps);
// DO NOT change the assignement operator in the conditional below to an
// equality operator. We are actually trying to get the parent window and
// and storing locally, and then verifying that we didn't get back null.
// This is a purposeful design decision.
if (MyParentHWnd = GetParent()){
RECT MyRect;
GetClientRect(&MyRect);
ClientToScreen(&MyRect);
MyParentHWnd->ScreenToClient(&MyRect);
MyParentHWnd->InvalidateRect(&MyRect);
}
EndPaint(&ps);
return answer;
break;
...
}
Of course, I had to genericize it a little bit. I just wanted you to know that yes, there are other people that are seeing your problem, and we found how to fix it.
I tested this with VS2005, which ships with MFC 8.0. I couldn't replicate your problem.
I added one CEdit and one CRichEditCtrl to a dialog based app. Changed properties Multiline, Auto VSCroll and Vertical Scroll to true. Used SetWindowText-method to put loooooong string of text to both of them. I started the app and text scrolled just fine.
What did you do differently?
Just to be sure. You didn't use the SetCaretPos-method, did you? There was some note about that in the MSDN page. Here's the Knowledge Base article.

How to make the group-box text background transparent

I want to make a transparent dialog. I capture the OnCtlColor message in a CDialog derived class...this is the code:
HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if(bSetBkTransparent_)
{
pDC->SetBkMode(TRANSPARENT);
hbr = (HBRUSH)GetStockObject(NULL_BRUSH);
}
return hbr;
}
It works fine for all the controls but the group-box (CStatic). All the labels (CStatic) are been painted with a transparent text background but the text of the group box it is not transparent.
I already googled for this but I didn't find a solutions. Does anybody know how to make a real transparent group-box?
By the way, I am working in Windows XP. And I don't want to fully draw the control to avoid having to change the code if the application is migrated to another OS.
Thanks,
Javier
Note: I finally changed the dialog so that I don't need to make it transparent. Anyway, I add this information because maybe someone is still trying to do it. The groupbox isn't a CStatic but a CButton (I know this is not new). I changed the Windows XP theme to Windows classic and then the groupbox backgraund was transparent. The bad new is that in this case the frame line gets visible beneath the text...so if someone is following this approach I think maybe he/she would better follow the Adzm's advice.
You have two options.
You can not use Common Controls v6 (the XP-Styled controls), which will make your app lose the fanciness of newer windows versions. However IIRC the groupbox will respect the CTLCOLOR issue. If you are not using that anyway, and it is still not respecting your color, then you only have one option...
Which is to draw it yourself. I know you said you don't want to, but sometimes you have to. Thankfully a group box is a very simple control to draw. This page has an example for drawing a classic-style group box: http://www.codeguru.com/cpp/controls/controls/groupbox/article.php/c2273/ You can also draw it very simply using the UxTheme libraries that come with XP+.
If the application will be migrated to another OS, you will have plenty to deal with migrating over an MFC application in general. If that is your goal, then you should really look into developing with a cross-platform UI toolkit.
Simply set the WS_EX_TRANSPARENT extended window style for the group box.
I knows this is a 12 years old question, but it frustrates me that nobody answered it correctly so far.
All you have to do is handle WM_CTLCOLORSTATIC:
case WM_CTLCOLORSTATIC:
{
HDC hDC = (HDC)wParam;
SetTextColor(hDC, RGB(255, 255, 255));
SetBkMode(hDC, TRANSPARENT);
return (INT_PTR)GetStockObject(HOLLOW_BRUSH);
}
break;