MFC学习笔记(1)——颜色、图片简单自绘

关于各种图片加载,使用统一的函数,从资源加载

#pragma once
#include <atlimage.h>    

BOOL LoadCImageFromResourse(CImage *pImage, UINT nResID, LPCTSTR lpTyp, HMODULE hModule)
{
       if (pImage == NULL) 
       return FALSE;
    pImage->Destroy();

    if (lpTyp == _T("BMP"))
    {
        pImage->LoadFromResource(hModule, MAKEINTRESOURCE(nResID));
        return TRUE;
    }
    // 查找资源
    HRSRC hRsrc = ::FindResource(hModule, MAKEINTRESOURCE(nResID), lpTyp);
    if (hRsrc == NULL) 
        return FALSE;

    // 加载资源
    HGLOBAL hImgData = ::LoadResource(hModule, hRsrc);
    if (hImgData == NULL)
    {
        ::FreeResource(hImgData);
        return FALSE;
    }

    // 锁定内存中的指定资源
    LPVOID lpVoid = ::LockResource(hImgData);

    LPSTREAM pStream = NULL;
    DWORD dwSize = ::SizeofResource(hModule, hRsrc);
    HGLOBAL hNew = ::GlobalAlloc(GHND, dwSize);
    LPBYTE lpByte = (LPBYTE)::GlobalLock(hNew);
    ::memcpy(lpByte, lpVoid, dwSize);

    // 解除内存中的指定资源
    ::GlobalUnlock(hNew);

    // 从指定内存创建流对象
    HRESULT ht = ::CreateStreamOnHGlobal(hNew, TRUE, &pStream);
    if (ht != S_OK)
    {
        GlobalFree(hNew);
    }
    else
    {
        // 加载图片
        pImage->Load(pStream);
        if (pImage->GetBPP() == 32)  //确认该图片包含Alpha通道    
        {
            for (int i = 0; i < pImage->GetWidth(); i++)
                for (int j = 0; j < pImage->GetHeight(); j++)
                {
                    byte* pByte = (byte*)pImage->GetPixelAddress(i, j);
                    pByte[0] = pByte[0] * pByte[3] / 255;
                    pByte[1] = pByte[1] * pByte[3] / 255;
                    pByte[2] = pByte[2] * pByte[3] / 255;
                }
        }
        GlobalFree(hNew);
    }
    // 释放资源
    ::FreeResource(hImgData);
    
    return TRUE;
}


1、对话框背景绘图

BOOL CMFCTest1Dlg::OnEraseBkgnd(CDC* pDC)
{
    CRect rect;
    GetClientRect(rect);
    CDC mdc;
    mdc.CreateCompatibleDC(pDC);
    CImage img;
    LoadCImageFromResourse(&img,IDB_PNG2,L"PNG",AfxGetInstanceHandle());
    CBitmap bmp;
    bmp.CreateCompatibleBitmap(pDC,img.GetWidth(),img.GetHeight());
    mdc.SelectObject(&bmp);
    img.Draw(mdc, CRect(0,0, img.GetWidth(), img.GetHeight()));
    //pDC->BitBlt(0,0,rect.Width(),rect.Height(),&mdc,0,0, SRCCOPY);
    pDC->SetStretchBltMode(STRETCH_HALFTONE);//防止失真
    pDC->StretchBlt(0,0,rect.Width()-200,rect.Height()-100,&mdc,0,0, img.GetWidth(), img.GetHeight(),SRCCOPY);
    return TRUE;
}

2、静态文本和编辑框的文字颜色和背景

HBRUSH CMFCTest1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	//pDC是控件文字颜色和背景的DC
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	// 根据控件ID来决定颜色
	switch (pWnd->GetDlgCtrlID())
	{
	case IDC_STATIC:
	{
		//和SetBkColor只能存一,透明时只能传回空画刷
		pDC->SetBkMode(TRANSPARENT);
		pDC->SetTextColor(RGB(255, 255, 255));
		//pDC->SetBkColor(RGB(0,255,0));
		return (HBRUSH)(GetStockObject(NULL_BRUSH));
	}
	case IDC_EDIT1:
	{
		pDC->SetTextColor(RGB(255, 0, 0));
		pDC->SetBkMode(TRANSPARENT);
		static CBrush br(RGB(255,255,0));
		return br;
	}
	default:
		return hbr;
		break;
	}
}

3、按钮的简单自绘

void CButtonEx::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	CDC dc;
	dc.Attach(lpDIS->hDC);//或者用FromHandle
	CRect rect(lpDIS->rcItem);
	CString btnText;
	GetWindowText(btnText);
	// 绘制按钮的选中动态
	COLORREF bkColor;
	if (lpDIS->itemState & ODS_SELECTED)
	{
		bkColor = GetSysColor(COLOR_BTNFACE);
		dc.DrawEdge(rect,BDR_SUNKENINNER,BF_RECT);
		rect.OffsetRect(2, 2);
	}
	else {
		bkColor = RGB(200, 200, 200);
		dc.DrawEdge(rect, BDR_RAISEDINNER, BF_RECT);
	}
	// 填充绘制背景色
	dc.FillSolidRect(rect, bkColor);
	// 双缓冲绘制按钮图标png图片
	CImage img;
	LoadCImageFromResourse(&img, m_hIconId, _T("PNG"), AfxGetInstanceHandle());
	img.Draw(dc,CRect(10, (rect.Height() - 20) / 2, 20, 20), CRect(0, 0, img.GetWidth(), img.GetHeight()));
	// 绘制获得焦点的边框
	if (lpDIS->itemState & ODS_FOCUS)
	{
		rect.DeflateRect(1, 1);
		dc.DrawFocusRect(rect);
	}
	// 绘制文字
	COLORREF crOldColor = dc.SetTextColor(RGB(255, 0, 0));
	dc.SetBkMode(TRANSPARENT);//文字背景透明
	dc.DrawText(btnText, btnText.GetLength(), rect,
		DT_SINGLELINE | DT_VCENTER | DT_CENTER);
	dc.SetTextColor(crOldColor);
	dc.Detach();
}

4、对话框标题栏自绘

在OnInitDialog里设置标题文字,及任务栏的样式

	SetWindowText(L"测试");
	ModifyStyle(NULL, WS_SYSMENU | WS_MINIMIZEBOX);

LRESULT CMFCTest1Dlg::OnNcHitTest(CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	UINT nRet = CDialog::OnNcHitTest(point);
	ScreenToClient(&point);
	if (HTCLIENT == nRet && point.y < 25)
	{
		return HTCAPTION;
	}
	return nRet;
}

5、下拉列表自绘

void CMyComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	CDC dc;
	dc.Attach(lpDIS->hDC);
	CString str;
	GetLBText(lpDIS->itemID, str);
	COLORREF cor;
	if (ODS_SELECTED & lpDIS->itemState)
	{
		cor = GetSysColor(COLOR_HIGHLIGHT);
		dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
		dc.FillSolidRect(&lpDIS->rcItem, cor);
		if (lpDIS->itemAction & ODA_FOCUS)
		{
			//dc.DrawFocusRect(&lpDIS->rcItem);
		}
	}
	else {
		cor = GetSysColor(COLOR_WINDOW);
		dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
		dc.FillSolidRect(&lpDIS->rcItem, cor);
	}
	//dc.SetBkMode(TRANSPARENT);
	//dc.SetTextColor(RGB(0,0,0));
	// 双缓冲绘制按钮图标png图片
	CImage img;
	LoadCImageFromResourse(&img, GetImage(lpDIS->itemID), _T("PNG"), AfxGetInstanceHandle());
	img.Draw(dc,CRect(4, (lpDIS->rcItem).top +((lpDIS->rcItem).bottom- (lpDIS->rcItem).top - 16) / 2, 16, 16)
            , CRect(0, 0, img.GetWidth(), img.GetHeight()));
	CRect rcc(lpDIS->rcItem);
	rcc.left += 4 + 16 + 4;
	dc.DrawText(str, rcc,DT_LEFT|DT_VCENTER|DT_SINGLELINE);
	dc.Detach();
}

void CMyComboBox::AddItem(LPCTSTR szText, int nImage)
{
	sData* pData = new sData;
	pData->nImage = nImage;
	pData->szText = szText;
	int i = GetCount();
	AddString(szText);
	SetItemData(i,(DWORD)pData);
}

void CMyComboBox::GetLBText(int nIndex, CString& rString) const
{
	ASSERT(nIndex < GetCount());
	sData* pData = (sData*)GetItemData(nIndex);
	rString = pData->szText;
}
UINT CMyComboBox::GetImage(int nIndex) const
{
	ASSERT(nIndex < GetCount());
	sData* pData = (sData*)GetItemData(nIndex);
	return pData->nImage;
}

6、CListCtrl的颜色和字体的自绘

void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	CDC dc;
	dc.Attach(lpDIS->hDC);
	CRect rect = lpDIS->rcItem,rc;
	int nItem = lpDIS->itemID;
	CHeaderCtrl* pHeader = GetHeaderCtrl();
	// 假设排序列是1
	int sortlist = 1;
	int i = 0, nCount = pHeader->GetItemCount();
	while (i < nCount)
	{
		pHeader->GetItemRect(i, rc);
		rc.top = rect.top;
		rc.bottom = rect.bottom;
		if (ODS_SELECTED & lpDIS->itemState)
		{
			dc.FillSolidRect(rc, GetSysColor(COLOR_HIGHLIGHT));
			dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
		}
		else {
			if (sortlist == i) {
				// 如果选中的列和当前列相等,就颜色加深
				if (nItem % 2)
					dc.FillSolidRect(rc, RGB(180, 190, 176));
				else
					dc.FillSolidRect(rc, RGB(140, 190, 176));
				dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
			}
			else {
				if (nItem % 2)
					dc.FillSolidRect(rc, RGB(200, 210, 196));
				else
					dc.FillSolidRect(rc, RGB(165, 210, 196));
				dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
			}
		}
		CString str = GetItemText(nItem, i);
		dc.DrawText(str, rc, DT_VCENTER | DT_SINGLELINE|DT_CENTER);
		++i;
	}
	dc.Detach();
}






你可能感兴趣的:(MFC学习笔记(1)——颜色、图片简单自绘)