<转>Bitmap Buttons

简介: 转自 http://www.functionx.com/visualc/controls/bmpbtn.htm   A bitmap button is a button that display a picture or a picture and text on its face.

转自 http://www.functionx.com/visualc/controls/bmpbtn.htm

 

A bitmap button is a button that display a picture or a picture and text on its face. This is usually used the button a little explicit. There are two ways you can create a bitmap button: with or without an existing resource identifier.

A bitmap button is created using theCBitmapButton class, which is a child ofCButton, which in turn is a descendent of the CWnd class. This means that it can use many of the method of CWnd.

Because the bitmap button is in fact a customized version of a button, you must first declare a variable or pointer of it:

 

CBitmapButton *btnMap = new CBitmapButton;

Using the variable or pointer, you can call the Create() method to formally create the button. Here is an example:

BOOL CDialog6Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	. . .
	
	// TODO: Add extra initialization here
	CBitmapButton *btnMap = new CBitmapButton;

	btnMap->Create(NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, CRect(10,10,100,100), this, IDC_BTN_NEW);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

 

 

Bitmap Button Implementation

Creating a bitmap button without an identifier is considered creating it from scratch. Creating a bitmap button is more practical because you can easily use the messages of such a button and refer to it in code. Therefore, before creating a bitmap button, you can first add a button to a dialog box and specify its identifier. For a button to display a picture, it must have theBS_OWNERDRAWstyle. This means that you should check or set to True the Owner Draw option.

Visually, the most appealing aspect of a bitmap button is the picture it displays. The bitmap can be designed following the same tools and instructions we reviewed for the icons. To give a 3-D or realistic appearance to the button, you should mimic the focus effect when designing the bitmaps.

Therefore, you should create one to four bitmaps for the control. Here is how they would work:

  • If you create one bitmap, it would be used for all clicks of the button. Since the button would always appear the same, you should avoid using only one picture
  • If you create two bitmaps, the first would display as the regular picture for the button, that is, when the button is not being clicked. The second would be used when the button is clicked and the mouse is down on the button
  • If you create three bitmaps, the first would display when the button is not being accessed and another control has focus. The second picture would display when the user is clicking the button and as long as the mouse is down on the button. The third would be used when the button has focus but it is not being used
  • If you create three bitmaps, the first would display when the button is not being accessed and another control has focus. The second picture would display when the user is clicking the button and as long as the mouse is down on the button. The third would be used when the button has focus but it is not being used. The fourth would be used when the button is disabled

Since these options, to use a bitmap button to its fullest, you should strive to provide four bitmaps. After creating the bitmaps, you can load them into the button. This is done using theLoadBitmaps()method. It comes in two versions as follows:

BOOL LoadBitmaps(LPCTSTR lpszBitmapResource,
		 LPCTSTR lpszBitmapResourceSel = NULL,
                 LPCTSTR lpszBitmapResourceFocus = NULL, 
		 LPCTSTR lpszBitmapResourceDisabled = NULL );
BOOL LoadBitmaps(UINT nIDBitmapResource, 
		 UINT nIDBitmapResourceSel = 0, 
		 UINT nIDBitmapResourceFocus = 0, 
		 UINT nIDBitmapResourceDisabled = 0 );

Each version takes four arguments. The first version uses the bitmaps as string resources while the second version uses resource identifiers.

As stated above, you can one to four bitmaps. As seen on these functions, the first bitmap is required. The first argument must specify the first or default bitmap and is required. The second argument is the name or identifier of the bitmap that would be used when the button is selected. The third is used when the button has focus. The last bitmap is used when the button is disabled. Here is an example:

 

BOOL CDialog6Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	. . .
	
	// TODO: Add extra initialization here
	CBitmapButton *btnMap = new CBitmapButton;

	btnMap->Create(NULL, WS_CHILD|WS_VISIBLE|BS_OWNERDRAW, 
		      CRect(10,10,100,100), this, IDC_BTN_NEW);
	btnMap->LoadBitmaps(IDB_BMP_BTN1, IDB_BMP_BTN2, IDB_BMP_BTN3, IDB_BMP_BTN4);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

It is very likely that you may not be able to design the button on one hand and the bitmaps on the other hand at exactly the same dimensions. To adjust these measures, theCBitmapButton class is equipped with the SizeToContent()method. Its syntax is:

void SizeToContent();

When this method is called on the button, it resizes it to the size of the bitmaps. If one bitmap is larger and/or taller than the others, if you had loaded more than one, this method would resize the button to the larger and taller bitmap. For this reason, always make sure that you design bitmaps that have the same dimension. Here is an example of using this method:

BOOL CDialog6Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	. . .
	
	// TODO: Add extra initialization here
	CBitmapButton *btnMap = new CBitmapButton;

	btnMap->Create(NULL, WS_CHILD|WS_VISIBLE|BS_OWNERDRAW, 
		      CRect(10,10,100,100), this, IDC_BTN_NEW);
	btnMap->LoadBitmaps(IDB_BMP_BTN1, IDB_BMP_BTN2, IDB_BMP_BTN3, IDB_BMP_BTN4);
	btnMap->SizeToContent();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

As you may realize if you create a bitmap button strictly using this approach, it would not work. The suggestion is to "subclass" your button class so the messages sent to the bitmap button would be applied effectively. The function used to do this is the CWnd::SubclassDlgItem()method and its syntax is:

BOOL SubclassDlgItem( UINT nID, CWnd* pParent );

The first argument is the resource ID of the existing button. The second argument is the control that is hosting the button; this is usually the dialog box but it can be another control container.

  1. Open the Geometry1application
  2. On the main menu, click Insert -> Resource... Click Bitmap and click New
  3. Using the Proeprties window, change the bitmaps ID to IDB_CANCEL_DISABLED and change its size to Width = 75, Height = 23
  4. Design it as follows:
  5. In the same way add new bitmaps. Change their IDs and design them as follows:

    IDB_CANCEL_FOCUS

    IDB_CANCEL_NRM

    IDB_CANCEL_SELECTED

    IDB_HELP_DISABLED

    IDB_HELP_FOCUS

    IDB_HELP_NORMAL

    IDB_HELP_SELECTED

    IDB_OK_DEFAULT

    IDB_OK_DISABLED

    IDB_OK_FOCUS

    IDB_OK_SELECTED

     

  6. In the header of the CGeomeSheet class, declare three CBitmapButtonvariables as follows:
    private:
    	CBitmapButton btnBmpOK, btnBmpCancel, btnBmpHelp;
    };
  7. Use the constructor to load the bitmaps of each button:
    CGeomeSheet::CGeomeSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
    	:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
    {
    	m_psh.dwFlags |= PSH_NOAPPLYNOW;
    
    	AddPage(&Quad);
    	AddPage(&Circ);
    	AddPage(&G3D);
    
    	btnBmpOK.LoadBitmaps(IDB_OK_DEFAULT, IDB_OK_SELECTED,
    		                 IDB_OK_FOCUS, IDB_OK_DISABLED);
    	btnBmpCancel.LoadBitmaps(IDB_CANCEL_NORMAL, IDB_CANCEL_SELECTED,
                                 IDB_CANCEL_FOCUS, IDB_CANCEL_DISABLED);
    	btnBmpHelp.LoadBitmaps(IDB_HELP_NORMAL, IDB_HELP_SELECTED,
                               IDB_HELP_FOCUS, IDB_HELP_DISABLED);
    }
  8. To customize the existing buttons, implement the OnInitDialog event of the CGeomeSheet class as follows (most of the code is used because the buttons were already created by default; this means that we have to manually change their style):
    BOOL CGeomeSheet::OnInitDialog()
    {
    	BOOL bResult = CPropertySheet::OnInitDialog();
    
    	// TODO: Add your specialized code here
    	// We need a handle to each
    	CButton *btnOK, *btnCancel, *btnHelp;
    
    	// Get a handle to each of the existing buttons
    	btnOK = reinterpret_cast<CButton *>(GetDlgItem(IDOK));
    	btnCancel = reinterpret_cast<CButton *>(GetDlgItem(IDCANCEL));
    	btnHelp = reinterpret_cast<CButton *>(GetDlgItem(IDHELP));
    
    	// Get the style of the button(s)
    	LONG GWLOK = GetWindowLong(btnOK->m_hWnd, GWL_STYLE);
    	LONG GWLCancel = GetWindowLong(btnCancel->m_hWnd, GWL_STYLE);
    	LONG GWLHelp = GetWindowLong(btnHelp->m_hWnd, GWL_STYLE);
    
    	// Change the button's style to BS_OWNERDRAW
    	SetWindowLong(btnOK->m_hWnd, GWL_STYLE, GWLOK | BS_OWNERDRAW);
    	SetWindowLong(btnCancel->m_hWnd, GWL_STYLE, GWLCancel | BS_OWNERDRAW);
    	SetWindowLong(btnHelp->m_hWnd, GWL_STYLE, GWLHelp | BS_OWNERDRAW);
    
    	// Subclass each button
    	btnBmpOK.SubclassDlgItem(IDOK, this);
    	btnBmpCancel.SubclassDlgItem(IDCANCEL, this);
    	btnBmpHelp.SubclassDlgItem(IDHELP, this);
    
    	return bResult;
    }
  9. Test the application:

  10. After using it, close it and return to MSVC
相关文章
|
3天前
|
云安全 数据采集 人工智能
古茗联名引爆全网,阿里云三层防护助力对抗黑产
阿里云三层校验+风险识别,为古茗每一杯奶茶保驾护航!
古茗联名引爆全网,阿里云三层防护助力对抗黑产
|
3天前
|
存储 机器学习/深度学习 人工智能
大模型微调技术:LoRA原理与实践
本文深入解析大语言模型微调中的关键技术——低秩自适应(LoRA)。通过分析全参数微调的计算瓶颈,详细阐述LoRA的数学原理、实现机制和优势特点。文章包含完整的PyTorch实现代码、性能对比实验以及实际应用场景,为开发者提供高效微调大模型的实践指南。
495 1
kde
|
3天前
|
人工智能 关系型数据库 PostgreSQL
n8n Docker 部署手册
n8n是一款开源工作流自动化平台,支持低代码与可编程模式,集成400+服务节点,原生支持AI与API连接,可自托管部署,助力团队构建安全高效的自动化流程。
kde
332 3
|
3天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践
本文介绍RAG(检索增强生成)技术,结合Spring AI与本地及云知识库实现学术分析AI应用,利用阿里云Qwen-Plus模型提升回答准确性与可信度。
226 91
AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践
|
4天前
|
传感器 人工智能 算法
数字孪生智慧水务系统,三维立体平台,沃思智能
智慧水务系统融合物联网、数字孪生与AI技术,实现供水全流程智能监测、预测性维护与动态优化。通过实时数据采集与三维建模,提升漏损控制、节能降耗与应急响应能力,推动水务管理从经验驱动迈向数据驱动,助力城市水资源精细化、可持续化管理。
282 143
|
18天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
7天前
|
人工智能 移动开发 自然语言处理
阿里云百炼产品月刊【2025年9月】
本月通义千问模型大升级,新增多模态、语音、视频生成等高性能模型,支持图文理解、端到端视频生成。官网改版上线全新体验中心,推出高代码应用与智能体多模态知识融合,RAG能力增强,助力企业高效部署AI应用。
353 1