Transparente GroupBox
-
Hallo zusammen,
habe eine Frage bezgl. transparenter Groupboxen. Da diese Buttons sind, lässt sich der Hintergrund nicht einfach mit WM_CTLCOLOR ändern. Deshalb habe ich das folgende Klasse CTGroupBox runtergeladen:
http://www.codeguru.com/cpp/controls/controls/groupbox/article.php/c2273So die GroupBox zu erstellen auch die Radiobuttons zu positionieren ist kein Problem. Jedoch kann ich nicht mehr die Radiobuttons anklicken.
Hier einige wichtige Funktionen aus der Klasse CTGroupBox:
void CTGroupBox::PreSubclassWindow() { ModifyStyle(0, BS_OWNERDRAW|BS_GROUPBOX); CButton::PreSubclassWindow(); } // Since groupboxes never get WM_DRAWITEM even if they are BS_OWNERDRAW, // we must handle our painting in OnPaint. // Fortunately they have no such things like focus rects or "pressed" states. void CTGroupBox::OnPaint() { CRect rc; CPoint ptStart, ptEnd; CSize seText; CString sText, sTemp; CPen pnFrmDark, pnFrmLight, *ppnOldPen; int iUpDist, nSavedDC; DWORD dwStyle, dwExStyle; CPaintDC dc(this); // device context for painting // save dc state nSavedDC = dc.SaveDC(); // window rect GetWindowRect(&rc); ScreenToClient(&rc); // determine text length GetWindowText(sTemp); sText.Format(_T(" %s "), sTemp); // looks better with a blank on each side seText = dc.GetTextExtent(sText); // distance from window top to group rect iUpDist = (seText.cy / 2); // calc rect and start/end points dwStyle = GetStyle(); dwExStyle = GetExStyle(); // handle the extended windows styles if (dwExStyle & WS_EX_DLGMODALFRAME) { rc.DeflateRect(2*GetSystemMetrics(SM_CXEDGE), 2*GetSystemMetrics(SM_CYEDGE)); rc.left--; } if (dwExStyle & WS_EX_CLIENTEDGE) { rc.DeflateRect(GetSystemMetrics(SM_CXEDGE)+1, GetSystemMetrics(SM_CYEDGE)+1); rc.left--; if (dwExStyle & WS_EX_DLGMODALFRAME) { rc.right++; } } if(dwExStyle & WS_EX_STATICEDGE) { rc.DeflateRect(2*GetSystemMetrics(SM_CXBORDER), 2*GetSystemMetrics(SM_CYBORDER)); rc.left--; } // handle text alignment (Caution: BS_CENTER == BS_LEFT|BS_RIGHT!!!) ptStart.y = ptEnd.y = rc.top + iUpDist; if ((dwStyle & BS_CENTER) == BS_RIGHT) // right aligned { ptEnd.x = rc.right - OFS_X; ptStart.x = ptEnd.x - seText.cx; } else if ((!(dwStyle & BS_CENTER)) || ((dwStyle & BS_CENTER) == BS_LEFT))// left aligned / default { ptStart.x = rc.left + OFS_X; ptEnd.x = ptStart.x + seText.cx; } else if ((dwStyle & BS_CENTER) == BS_CENTER) // text centered { ptStart.x = (rc.Width() - seText.cx) / 2; ptEnd.x = ptStart.x + seText.cx; } if (dwStyle & BS_FLAT) // "flat" frame { VERIFY(pnFrmDark.CreatePen(PS_SOLID, 1, RGB(0, 0, 0))); VERIFY(pnFrmLight.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHILIGHT))); ppnOldPen = dc.SelectObject(&pnFrmDark); dc.MoveTo(ptStart); dc.LineTo(rc.left, ptStart.y); dc.LineTo(rc.left, rc.bottom); dc.LineTo(rc.right, rc.bottom); dc.LineTo(rc.right, ptEnd.y); dc.LineTo(ptEnd); dc.SelectObject(&pnFrmLight); dc.MoveTo(ptStart.x, ptStart.y+1); dc.LineTo(rc.left+1, ptStart.y+1); dc.LineTo(rc.left+1, rc.bottom-1); dc.LineTo(rc.right-1, rc.bottom-1); dc.LineTo(rc.right-1, ptEnd.y+1); dc.LineTo(ptEnd.x, ptEnd.y+1); } else // 3D frame { VERIFY(pnFrmDark.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW))); VERIFY(pnFrmLight.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHILIGHT))); ppnOldPen = dc.SelectObject(&pnFrmDark); dc.MoveTo(ptStart); dc.LineTo(rc.left, ptStart.y); dc.LineTo(rc.left, rc.bottom-1); dc.LineTo(rc.right-1, rc.bottom-1); dc.LineTo(rc.right-1, ptEnd.y); dc.LineTo(ptEnd); dc.SelectObject(&pnFrmLight); dc.MoveTo(ptStart.x, ptStart.y+1); dc.LineTo(rc.left+1, ptStart.y+1); dc.LineTo(rc.left+1, rc.bottom-1); dc.MoveTo(rc.left, rc.bottom); dc.LineTo(rc.right, rc.bottom); dc.LineTo(rc.right, ptEnd.y-1); dc.MoveTo(rc.right-2, ptEnd.y+1); dc.LineTo(ptEnd.x, ptEnd.y+1); } // draw text (if any) if (!sText.IsEmpty() && !(dwExStyle & (BS_ICON|BS_BITMAP))) { if (!IsWindowEnabled()) { ptStart.y -= iUpDist; dc.DrawState(ptStart, seText, sText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL); } else { dc.SetBkMode(TRANSPARENT); dc.DrawText(sText, CRect(ptStart, ptEnd), DT_VCENTER|DT_LEFT|DT_SINGLELINE|DT_NOCLIP); } } // cleanup dc.SelectObject(ppnOldPen); dc.RestoreDC(nSavedDC); }
Ich erzeuge die Gruppenbox auf dem Hauptfenster. Dazu habe ich in der Headerdatei einen Member angelegt und im Kosntruktor Speicher belegt:
CTGroupBox *btnMat; ... btnMat = new CTGroupBox;
So jetzt kommt der Unterschied zu dem auf Codeguru angegebenem Beispiel. Dort wird in der OnInitDialog folgender Quellcode gefunden, den ich nicht nachvollziehen kann:
m_TGrpBox1.SubclassDlgItem(IDC_GRPBOX1, this);
Ich erzeuge meine GroupBox aber mit Create:
btnMat->Create(_T("Test Group Box"),WS_VISIBLE|BS_GROUPBOX , CRect(xpos,ypos,xpos+xlength,ypos+3* ylength),this,IDC_BTN_MAT);
Die GroupBox wird richtig erzeugt aber wie gesagt auf die Radiobuttons kann ich nicht zugreifen. Kann mir bitte jemand weiterhelfen? Komme einfach nicht weiter..
-
das liegt an der z-Order deiner Gruppbox welche vor deinem radiobuttons liegt. Aber um die z-order nicht durcheinander zu bringen, erzeungst du mit dem resourceneditor in dialog deine Groupbox und subclasst die groupbox auf deine klasse.
m_TGrpBox1.SubclassDlgItem(IDC_GRPBOX1, this);
m_TGrpBox1 ist der deine CTGroupBox welche du im header mit
CTGroupBox m_TGrpBox1;
erstellt. IDC_GRPBOX1 ist die ID deine Groupbox im Dialog und this ist der this-zeiger deines dialoges, damit die nachrichten auch zugeordnet werden können.
Das wars.weiteres unter
http://msdn.microsoft.com/en-us/library/0wx11zk9(VS.80).aspxund auf ähnlichen seiten, ich hoffe das hilt weiter
-
Die Z-Order darf bei Groupboxen nichts ausmachen, denn diese sollten auf einen WM_NCHITTEST brav HTTRANSPARENT zurückgeben.
Evtl. wurde hier was falsch überschrieben. Dito sollten Sie in der Tab-Order vor den Radios liegen um die Accelerator Steuerung nicht durcheinander zu bringen
-
Hallo zusammen,
also die Radiobuttons erzeuge ich nach der GroupBox. Jedoch ist die übergeordnete Klasse vom Typ CWnd. Und für die gibt es keine OnInitDialog.
Deshalb führe ich den Befehl
btnMat->SubclassDlgItem(IDC_BTN_MAT, this);
vor der Erzeugung der GroupBox mit Create durch.Das mit der z-Order habe ich mir auch schon überlegt. Falls ich nämlich die GroupBox als CButton erzeuge, so kann ich auf die Radiobuttons zugreifen. Ich will jedoch den Hintergrund transparent haben und auch die Captions verändern. Dies geht ja für Buttons nur über eigene Klassen.
Damit bin ich aber leider noch keinen Schritt weitergekommen
-
So Problem gelöst:
Zuerst GroupBox erstellen, dann die Radiobuttons. Anschliessend die Radiobuttons mit BringWindowToTop() "nach vorne " bringen und schon kann man die Radiobuttons auswählen.