• MFC之ListCtrl动态添加按钮


    先上效果图:

    图中用了一个CListCtrl插件,隐藏了网格线(LVS_EX_GRIDLINES)。

    添加了“删除”按钮(按钮上贴了图片),选中哪一行则显示在哪一行。

    有两种方式创建按钮,一种是直接根据行数(比如n行)创建n按钮,然后根据自己需求全部显示,或是动态显示,只显示所选中的那一行按钮;

    另一种是每次只创建选中行的一个按钮,并且销毁上一次创建的按钮(第一次除外)。

    本实例选用第二种方法,第一种方法也用了,但是效果不好,有其他bug.

    -----------------------------------------------------------------创建按钮源代码如下---------------------------------------------------------------------

    有4个基本文件,ButtonEx.h,   ButtonEx.cpp,   ListCtrlEx.h,   ListCtrlEx.cpp.

    //ButtonEx.h
    #pragma once
    
    #include "WDBitmapButton.h"
    // CButtonEx
    #define  WM_BN_CLICK  WM_USER + 100
    class CButtonEx : public CWDBitmapButton
    {
    	DECLARE_DYNAMIC(CButtonEx)
    
    public:
    	CButtonEx();
    	CButtonEx( int nItem, int nSubItem, CRect rect, HWND hParent );
    	virtual ~CButtonEx();
    
    protected:
    	DECLARE_MESSAGE_MAP()
    public:
    	afx_msg void OnBnClicked();
    	int m_inItem;
    	int m_inSubItem;
    	CRect m_rect;
    	HWND m_hParent;
    	BOOL bEnable;
    };
    

      

    // ButtonEx.cpp : 实现文件
    //
    
    #include "stdafx.h"
    #include "ButtonEx.h"
    
    
    // CButtonEx
    
    IMPLEMENT_DYNAMIC(CButtonEx, CButton)
    
    CButtonEx::CButtonEx()
    {
    
    }
    
    CButtonEx::~CButtonEx()
    {
    }
    
    CButtonEx::CButtonEx( int nItem, int nSubItem, CRect rect, HWND hParent )    //-
    {
        m_inItem = nItem;
        m_inSubItem = nSubItem;
        m_rect = rect;
        m_hParent = hParent;
        bEnable = TRUE;
    }
    
    BEGIN_MESSAGE_MAP(CButtonEx, CButton)
        ON_CONTROL_REFLECT(BN_CLICKED, &CButtonEx::OnBnClicked)
    END_MESSAGE_MAP()
    
    
    // CButtonEx 消息处理程序
    
    
    void CButtonEx::OnBnClicked()
    {
        // TODO: 在此添加控件通知处理程序代码
        ::SendMessage( m_hParent, WM_BN_CLICK, m_inItem, m_inSubItem );   //
    }

    //ListCtrl.h
    #pragma once #include "ButtonEx.h" #include <map> using namespace std; typedef map<int,CButtonEx*>button_map; // CListCtrlEx class CListCtrlEx : public CListCtrl { DECLARE_DYNAMIC(CListCtrlEx) public: CListCtrlEx(); virtual ~CListCtrlEx(); protected: DECLARE_MESSAGE_MAP() public: void createItemButton( int nItem, int nSubItem, HWND hMain ); void release(); void deleteItemEx( int iCount, int nItem ); button_map m_mButton; WCHAR * charToWchar(char *s); public: UINT m_uID; //void updateListCtrlButtonPos(); //void enableButton( BOOL bFlag, int iItem ); };

      

    // ListCtrlEx.cpp : 实现文件
    //
    
    #include "stdafx.h"
    #include "ListCtrlEx.h"
    #include "resource.h"
    #define  MAX_PATH 256
    
    // CListCtrlEx
    
    IMPLEMENT_DYNAMIC(CListCtrlEx, CListCtrl)
    
    CListCtrlEx::CListCtrlEx()
    {
    }
    
    CListCtrlEx::~CListCtrlEx()
    {
    }
    
    
    BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
    END_MESSAGE_MAP()
    
    
    
    // CListCtrlEx 消息处理程序
    
    void CListCtrlEx::createItemButton( int nItem, int nSubItem, HWND hMain )
    {
    
    	m_mButton.clear();
    	char *name = NULL;
    	CString strPath;
    	::GetModuleFileName( NULL, strPath.GetBuffer(MAX_PATH), MAX_PATH );
    	strPath.ReleaseBuffer();//当前文件的绝对路径
    	strPath = strPath.Left(strPath.ReverseFind(_T('\')));//文件所在目录
    	strPath=strPath.Left(strPath.ReverseFind(_T('\')));//文件目录的父目录
    
    	name = (LPSTR)(LPCSTR)strPath;
    	WCHAR name_on[256] = {};
    
    	wcscpy(name_on,charToWchar(name));
    	wcscat(name_on,L"//Invaray//Invaray//res//delete.png");
    	
    		
    	CRect rect;
    	if( !EnsureVisible(nItem, TRUE)) 
    		return ;
    
    	GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect);
    	DWORD dwStyle =  WS_CHILD | WS_VISIBLE;
    	CButtonEx *pButton = new CButtonEx(nItem,nSubItem,rect,hMain);
    	rect.bottom = rect.bottom-2;
    	pButton->Create(_T(""),dwStyle, rect, this, m_uID);
    	//m_uID++;
    	pButton->SetImage(name_on,name_on,name_on);
    	m_mButton.insert( make_pair( nItem, pButton ) );
    
    	return;
    }
    
    WCHAR * CListCtrlEx::charToWchar(char *s)
    {
    	int w_nlen=MultiByteToWideChar(CP_ACP,0,s,-1,NULL,0);
    	WCHAR *ret;
    	ret=(WCHAR*) malloc(sizeof(WCHAR)*w_nlen);
    	memset(ret,0,sizeof(ret));
    	MultiByteToWideChar(CP_ACP,0,s,-1,ret,w_nlen);
    	return ret;
    }
    
    void CListCtrlEx::release()
    {
    	button_map::iterator iter;
    	iter = m_mButton.begin();
    	while ( iter != m_mButton.end() )
    	{
    		delete iter->second;
    		iter->second = NULL;
    		iter++;
    	}
    
    }
    void CListCtrlEx::deleteItemEx( int iCount, int nItem )
    {
    	//int iCount = GetItemCount();
    	DeleteItem( nItem );
    	button_map::iterator iter;
    	button_map::iterator iterNext;
    #ifdef USE_TOPINDEX_BUTTON
    	//add-----------------------------------
    	iter = m_mButton.find( nItem );
    	iterNext = iter;
    	iterNext++;
    	while ( iterNext != m_mButton.end() )
    	{
    		iter->second->bEnable = iterNext->second->bEnable;
    		iterNext++;
    		iter++;
    	}
    	//------------------------------
    #endif
    	iter = m_mButton.find( iCount - 1 );
    	if ( iter != m_mButton.end() )
    	{
    		delete iter->second;
    		iter->second = NULL;
    		m_mButton.erase( iter );
    		//updateListCtrlButtonPos();
    	}
    }
    
    //void CListCtrlEx::updateListCtrlButtonPos()
    //{
    //	int iTopIndex = GetTopIndex();
    //	int nItem = iTopIndex;
    //	button_map::iterator iter;
    //	button_map::iterator iterUp;
    //	int iLine = 0;
    //#ifdef USE_TOPINDEX_BUTTON
    //	iter = m_mButton.find( iTopIndex );
    //	iterUp = m_mButton.begin();
    //	while ( iter != m_mButton.end() )
    //	{
    //		iterUp->second->EnableWindow( iter->second->bEnable );
    //		iter ++;
    //		iterUp++;
    //	}
    //#else
    //	for ( ; nItem < GetItemCount(); nItem++ )
    //	{
    //		iter = m_mButton.find(nItem);
    //		if( iter!= m_mButton.end() )
    //		{
    //			CRect rect;
    //			iterUp = m_mButton.find(iLine);
    //			rect = iterUp->second->m_rect;
    //			iter->second->MoveWindow( &rect );
    //			iter->second->ShowWindow( SW_SHOW );
    //			if( iLine < iTopIndex )
    //			{
    //				iterUp->second->ShowWindow( SW_HIDE );
    //			}
    //			iLine++;
    //		}
    //	}
    //#endif
    //
    //}
    
    //void CListCtrlEx::enableButton( BOOL bFlag, int iItem )
    //{
    //	button_map::iterator iter;
    //#ifdef USE_TOPINDEX_BUTTON
    //	int iTopIndex = GetTopIndex();
    //	int nItem = iItem - iTopIndex;
    //	iter = m_mButton.find( iItem );
    //	if ( iter != m_mButton.end() )
    //	{
    //		iter->second->bEnable = bFlag;
    //	}
    //	iter = m_mButton.find( nItem );
    //	if ( iter != m_mButton.end() )
    //	{
    //		iter->second->EnableWindow( bFlag );
    //	}
    //#else
    //	iter = m_mButton.find( iItem );
    //	if ( iter != m_mButton.end() )
    //	{
    //		iter->second->EnableWindow( bFlag );
    //	}
    //#endif
    //
    //}
    

      动态创建Button的函数

    createItemButton( int nItem, int nSubItem, HWND hMain ),3个参数分别是行,列,父窗口句柄;

    按钮所产生消息:

    void CButtonEx::OnBnClicked()
      {
      // TODO: 在此添加控件通知处理程序代码
      ::SendMessage( m_hParent, WM_BN_CLICK, m_inItem, m_inSubItem ); //
      }

    可以通过宏WM_BN_CLICK来接收相应的行数和列数。

    如,在你的其他文件中添加消息响应函数,ON_MESSAGE( WM_BN_CLICK, onBnCLick) ,LRESULT CXXX::onBnCLick( WPARAM wParam, LPARAM lParam ){}

  • 相关阅读:
    A 【NOIP2012 day2】疫情控制
    Leetcode(886)-可能的二分法
    判断链表是否有环
    如何判断图的连通
    图的DFS与BFS
    struct 和 class的区别
    最小生成树-kruskal算法
    Leetcode(712)-账户合并
    全局最小割
    Leetcode(29)-两数相除
  • 原文地址:https://www.cnblogs.com/shanlizi/p/6845085.html
Copyright © 2020-2023  润新知