[MFC] 手动美化 MFC 窗体

本文详细介绍了如何手动美化MFC窗体,包括去除边框实现可拖动窗口,添加背景图片及颜色,为按钮设置PNG透明背景,修改普通按钮样式,以及处理ESC和ENTER键避免程序退出。同时,还提供了编辑控件修改字体大小的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

去除边框

1.把窗口边框改成无边框:在这里插入图片描述

但只这样做会导致无法拖动窗口。

2.在类向导中添加这个消息:OnHcHitTest在这里插入图片描述

3.修改这个消息处理函数的返回值为:HTCAPTION在这里插入图片描述


添加背景图片

1.准备一张 bmp 格式的图片(其他格式我没有实验,可能会有问题),在项目中添加资源,选择 BitMap ,导入:在这里插入图片描述

在这里插入图片描述

2.在 OnPaint() 函数中添加如下代码:

// 上面还有一部分代码,是 vs 自动生成的
else
	{
    
    
		//CDialogEx::OnPaint();			// 这是原本的,注释掉

		/*
			从这里开始是我们自己的代码 ---------------
		*/ 
		
		CPaintDC   dc(this);
		CRect   rect;
		GetClientRect(&rect);												// 获取对话框长宽      
		CDC   dcBmp;															// 定义并创建一个内存设备环境
		dcBmp.CreateCompatibleDC(&dc);						// 创建兼容性DC
		CBitmap   bmpBackground;
		bmpBackground.LoadBitmap(IDB_BITMAP1);    // 载入资源中图片
		BITMAP   m_bitmap;												// 图片变量               
		bmpBackground.GetBitmap(&m_bitmap);			// 将图片载入位图中
		
		//将位图选入临时内存设备环境
		CBitmap* pbmpOld = dcBmp.SelectObject(&bmpBackground);
		
		//调用函数显示图片StretchBlt显示形状可变
		dc.SetStretchBltMode(COLORONCOLOR);			// 防止 bmp 图片压缩后失真
		dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &dcBmp, 0, 0, m_bitmap.bmWidth, m_bitmap.bmHeight, SRCCOPY);
	}

注意:背景图片在窗口拉伸时会失真,但配合无边框使用时不需要在意,因为本身无边框窗体不支持拉伸窗口。


添加背景颜色

这个没有添加背景图片好用,但还是记录一下吧。
1.类向导里添加消息处理函数 : WM_CTLCOLOR
2.在 xxxDlg.h 的 protected 里添加成员变量:CBrush m_brush;
3.在 WM_CTLCOLOR 的处理函数 OnCtlColor() 中 ,修改返回值为 m_brush

HBRUSH Ctestmfc2Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    
    
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何特性


	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return /*hbr*/m_brush;
}

4.在 OnInitDialog() 中添加代码,绘制背景颜色:

m_brush.CreateSolidBrush(RGB(255, 255, 102));

给按钮添加背景图片

比起 bmp 图片,显然按钮必须要用 png 的透明图片更加好看,但是 MFC 对 png 的支持并不太友好,我找了很久,终于在这篇文章的启发下完成了这个功能:https://www.codeproject.com/Articles/26887/A-user-draw-button-that-supports-PNG-files-with-tr

https://github.com/JustLoveI/GdipButton 这里的代码更新,但是我没有调通,所以我用的时上面连接里的代码。

以防链接失效,这里记录下具体实现过程,不愿看英文的人也可以直接看我下面写的。

1.首先需要几个文件
CGdiPlusBitmap.h

#pragma once

class CGdiPlusBitmap
{
    
    
public:
	Gdiplus::Bitmap* m_pBitmap;

public:
	CGdiPlusBitmap()							{
    
     m_pBitmap = NULL; }
	CGdiPlusBitmap(LPCWSTR pFile)				{
    
     m_pBitmap = NULL; Load(pFile); }
	virtual ~CGdiPlusBitmap()					{
    
     Empty(); }

	void Empty()								{
    
     delete m_pBitmap; m_pBitmap = NULL; }

	bool Load(LPCWSTR pFile)
	{
    
    
		Empty();
		m_pBitmap = Gdiplus::Bitmap::FromFile(pFile);
		return m_pBitmap->GetLastStatus() == Gdiplus::Ok;
	}

	operator Gdiplus::Bitmap*() const			{
    
     return m_pBitmap; }
};


class CGdiPlusBitmapResource : public CGdiPlusBitmap
{
    
    
protected:
	HGLOBAL m_hBuffer;

public:
	CGdiPlusBitmapResource()					{
    
     m_hBuffer = NULL; }
	CGdiPlusBitmapResource(LPCTSTR pName, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL)
												{
    
     m_hBuffer = NULL; Load(pName, pType, hInst); }
	CGdiPlusBitmapResource(UINT id, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL)
												{
    
     m_hBuffer = NULL; Load(id, pType, hInst); }
	CGdiPlusBitmapResource(UINT id, UINT type, HMODULE hInst = NULL)
												{
    
     m_hBuffer = NULL; Load(id, type, hInst); }
	virtual ~CGdiPlusBitmapResource()			{
    
     Empty(); }

	void Empty();

	bool Load(LPCTSTR pName, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL);
	bool Load(UINT id, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL)
												{
    
     return Load(MAKEINTRESOURCE(id), pType, hInst); }
	bool Load(UINT id, UINT type, HMODULE hInst = NULL)
												{
    
     return Load(MAKEINTRESOURCE(id), MAKEINTRESOURCE(type), hInst); }
};

inline
void CGdiPlusBitmapResource::Empty()
{
    
    
	CGdiPlusBitmap::Empty();
	if (m_hBuffer)
	{
    
    
		::GlobalUnlock(m_hBuffer);
		::GlobalFree(m_hBuffer);
		m_hBuffer = NULL;
	} 
}

inline
bool CGdiPlusBitmapResource::Load(LPCTSTR pName, LPCTSTR pType, HMODULE hInst)
{
    
    
	Empty();

	HRSRC hResource = ::FindResource(hInst, pName, pType);
	if (!hResource)
		return false;
	
	DWORD imageSize = ::SizeofResource(hInst, hResource);
	if (!imageSize)
		return false;

	const void* pResourceData = ::LockResource(::LoadResource(hInst, hResource));
	if (!pResourceData)
		return false;

	m_hBuffer  = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
	if (m_hBuffer)
	{
    
    
		void* pBuffer = ::GlobalLock(m_hBuffer);
		if (pBuffer)
		{
    
    
			CopyMemory(pBuffer, pResourceData, imageSize);

			IStream* pStream = NULL;
			if (::CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream) == S_OK)
			{
    
    
				m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
				pStream->Release();
				if (m_pBitmap)
				{
    
     
					if (m_pBitmap->GetLastStatus() == Gdiplus::Ok)
						return true;

					delete m_pBitmap;
					m_pBitmap = NULL;
				}
			}
			::GlobalUnlock(m_hBuffer);
		}
		::GlobalFree(m_hBuffer);
		m_hBuffer = NULL;
	}
	return false;
}


GdipButton.h

//
// GdipButton.h : Version 1.0 - see article at CodeProject.com
//
// Author:  Darren Sessions
//          
//
// Description:
//     GdipButton is a CButton derived control that uses GDI+ 
//     to support alternate image formats
//
// History
//     Version 1.0 - 2008 June 10
//     - Initial public release
//
// License:
//     This software is released under the Code Project Open License (CPOL),
//     which may be found here:  http://www.codeproject.com/info/eula.aspx
//     You are free to use this software in any way you like, except that you 
//     may not sell this source code.
//
//     This software is provided "as is" with no expressed or implied warranty.
//     I accept no liability for any damage or loss of business that this 
//     software may cause.
//
///

#pragma once

// GdipButton.h : header file
//

class CGdiPlusBitmapResource;
/
// CGdipButton window

class CGdipButton : public CButton
{
    
    
public:

	CGdipButton();
	virtual ~CGdipButton();

	// image types
	enum	{
    
    
				STD_TYPE	= 0,
				ALT_TYPE,
				DIS_TYPE
			};

	// sets the image type
	void SetImage(int type);

	BOOL LoadAltImage(UINT id, LPCTSTR pType);
	BOOL LoadStdImage(UINT id, LPCTSTR pType);

	// if false, disables the press 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值