MFC Gradient Background and Control Transparency Processing

Keywords: Programming

 

mfc realizes background color gradient of a dialog box

If it is a single document view structure, the code is implemented in OnDraw, and if it is a dialog structure, the OnPain function in the cpp where the dialog box is located (if not, please derive from the class wizard) can implement the following code. This example is implemented in the dialog structure, a dialog box, and the effect is as follows

CPaintDC dc(this); // device context for painting
    CRect Rect;
	GetClientRect(Rect);
	CRect rectClient;
	CDC dcMen, dcBkgnd;
	CBitmap bitmapTemp, *pOldBitmap;
	GetClientRect(&rectClient);
	bitmapTemp.CreateCompatibleBitmap(&dc, rectClient.Width(), rectClient.Height());
	dcMen.CreateCompatibleDC(&dc);
	pOldBitmap = dcMen.SelectObject(&bitmapTemp);
	/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Main code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
	int r1=217,g1=236,b1=235;
	int r2=255,g2=255,b2=235;
	for (int i=0;i<rectClient.Width();i++)
	{
		int r,g,b;
		r=r1+(i*(r2-r1))/rectClient.Width();
		g=g1+(i*(g2-g1))/rectClient.Width();
		b=b1+(i*(b2-b1))/rectClient.Width();
		dcMen.FillSolidRect(i,0,1,rectClient.Height(),RGB(r,g,b));
	}
	/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
	dc.BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &dcMen, 0, 0, SRCCOPY);//Draw pictures to main DC
	dcMen.SelectObject(pOldBitmap);//Memory reset
	bitmapTemp.DeleteObject();

Above is the horizontal gradient. Longitudinal gradient only needs to modify several parameters, such as:

int r1=217,g1=236,b1=235;
int r2=255,g2=255,b2=235;
for (int i=0;i<rectClient.Height();i++)
{
    int r,g,b;
    r=r1+(i*(r2-r1))/rectClient.Height();
    g=g1+(i*(g2-g1))/rectClient.Height();
    b=b1+(i*(b2-b1))/rectClient.Height();
    dcMen.FillSolidRect(0,i,rectClient.Width(),1,RGB(r,g,b));
}

When background images are added to the MFC dialog box, it will cause shadows around the control, which is very beautiful. Therefore, we need to transparent the shadows. At this point, you need to use the message function OnCtlColor() in MFC.

HBRUSH CCPPDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
 
	//< TODO: Change any features of DC here
	if(nCtlColor == CTLCOLOR_STATIC )
	{
		pDC->SetBkMode(TRANSPARENT);//Setting Background Transparency
        pDC->SetTextColor(RGB(0,0,0));  
		hbr=(HBRUSH)::GetStockObject(NULL_BRUSH);
	}
	//< TODO: If the default is not the required brush, return another brush
	return hbr;
}

Note that if other check radio s and other controls need background coloring, the code needs to be placed at the front of the function, and the interface property Clip Children property needs to be set to false, otherwise the transparency effect will be invalid.

In addition, when the static control is set to a transparent background, updating the text on the static file will cause text overlap. There are the following solutions

//Scenario 1:
CRect rc;
GetDlgItem(IDC_STATIC_APPINFO)->GetWindowRect(&rc);
ScreenToClient(&rc);
InvalidateRect(&rc);
SetDlgItemText(IDC_STATIC_APPINFO,str);
//Option two
GetDlgItem(IDC_STATIC_APPINFO)->ShowWindow(SW_HIDE);
SetDlgItemText(IDC_STATIC_APPINFO,str);
GetDlgItem(IDC_STATIC_APPINFO)->ShowWindow(SW_SHOW);

Explanation: Although the above methods can solve the problem of text overlap, it will bring the problem of flicker. If not frequent and fast refresh is enough, otherwise it needs to be solved by self-drawing control.

But the above can not handle the background of radio buttons and check boxes, you need to add the following code

HBRUSH CCPPDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
 
 //< TODO: Change any features of DC here
 UINT id = pWnd->GetDlgCtrlID();
 if(id == IDC_RADIO_EXPMODE||IDC_RADIO_TRAINMODE||IDC_CHECK_TRACK||IDC_CHECK_SCENE||IDC_EXIT_BUTTON||IDC_MIN_BUTTON)
 {
  pDC->SetBkMode(TRANSPARENT);
  CRect rc;
  pWnd->GetWindowRect(&rc);
  ScreenToClient(&rc);
  CDC* dc = GetDC();
  pDC->BitBlt(0,0,rc.Width(),rc.Height(),dc,rc.left,rc.top,SRCCOPY); //Draw the background picture of the parent window onto the button first
  ReleaseDC(dc);
 
  hbr = (HBRUSH) ::GetStockObject(NULL_BRUSH);
 }   
 //< TODO: If the default is not the required brush, return another brush
 return hbr;
}

Design sketch:

The background of RADIO control is not transparent in the figure. When the above method has been tested, it is effective.

 

 

Posted by sades on Thu, 31 Jan 2019 03:51:15 -0800