• CListBox的一个改写类(VC6添加文件的效果)


    编写一个类似VC6添加文件,单击则动态显示一个Edit编辑框与一个Button。效果如下图:

    1.新建一个类(如CMyListBox),继承自CListBox

    2.头文件中定义Edit与CButton变量

    CEdit m_edit;

    CButton m_btn;

    3.定义一个初始化函数,供对话框调用。

    首先在.cpp中定义2个ID

    #define MY_EDIT 10001

    #define MY_BTN  10002

    void CMyListBox::Init()
    {
        m_edit.Create(WS_BORDER | WS_CHILD | ES_AUTOHSCROLL,CRect(0,0,10,10),this,MY_EDIT);
        // 设置字体
        // 方法一:
        HFONT hf = reinterpret_cast<HFONT>(::GetStockObject(DEFAULT_GUI_FONT));
        m_edit.SetFont(CFont::FromHandle(hf));
        // 方法二:
        //HFONT hf = CreateFont(22,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,
        //    CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,FIXED_PITCH,_T("Courier New"));
        //if(hf != NULL)
        //{
        //    ::SendMessage(GetDlgItem(MY_EDIT)->m_hWnd,WM_SETFONT,reinterpret_cast<WPARAM>(hf),TRUE);
        //}
    
        m_btn.Create(_T("..."),WS_CHILD,CRect(0,0,10,10),this,MY_BTN);
    
        m_menu.LoadMenu(IDR_MY_MENU);
    }

    4.重载OnLButtonDown 与 OnLbnSelchange 函数

    (1)OnLbutton函数要做的是:

    获取数据个数(GetCount);

    判断左键按下是否在有效的行(GetItemRect); 不在,SetCurSel(-1);调用 更新显示函数(UpdateDisplay)。

    void CMyListBox::OnLButtonDown(UINT nFlags, CPoint point)
    {
        // TODO: 在此添加消息处理程序代码和/或调用默认值
    
        // 获取个数
        int nCount = GetCount();
        int i = 0;
        CRect rc;
        for(i=0; i<nCount; ++i)
        {
            GetItemRect(i,rc);
            if(rc.PtInRect(point))
            {
                break;
            }
        }
    
        if(i >= nCount) // 未找到,不在
        {
            SetCurSel(-1);
            UpdateDisplay(); // 更新位置函数
        }
    
        CListBox::OnLButtonDown(nFlags, point);
    }

    (2)OnLbnSelchange函数:

    判断edit与button是否可见,可见则隐藏。更新显示(UpdateDisplay)

    void CMyListBox::OnLbnSelchange()
    {
        // TODO: 在此添加控件通知处理程序代码
        if(m_edit.IsWindowVisible())
        {
            m_edit.ShowWindow(SW_HIDE);
        }
        if(m_btn.IsWindowVisible())
        {
            m_btn.ShowWindow(SW_HIDE);
        }
        UpdateDisplay();
    }

    更新显示函数(UpdateDisplay):

    获取当前所选项(GetCurSel);为LB_ERR则让edit与button隐藏

    获取按下位置的当前矩形大小GetItemRect;

    edit与button根据获取到的矩形区域,设置rect,调用MoveWindow;

    获取当前行的text,更新到edit控件上显示。

    edit设置焦点。

    // 更新显示函数
    void CMyListBox::UpdateDisplay()
    {
        int index = GetCurSel();
        if(index == LB_ERR)
        {
            if(m_edit.IsWindowVisible())
            {
                m_edit.ShowWindow(SW_HIDE);
            }
            if(m_btn.IsWindowVisible())
            {
                m_btn.ShowWindow(SW_HIDE);
            }
            return;
        }
    
        CRect rc;
        GetItemRect(index,rc); // 获取在第几行
    
        CRect rcEdit(rc.left,rc.top,rc.right-20,rc.bottom+5);
        m_edit.MoveWindow(rcEdit);
    
        CRect rcBtn(rc.right-20,rc.top,rc.right,rc.bottom+5);
        m_btn.MoveWindow(rcBtn);
    
        // 更新Edit显示内容
        CString strContent;
        GetText(index,strContent);
        m_edit.SetWindowText(strContent);
        m_edit.SetSel(0,-1); // 全选
    
        if(!m_edit.IsWindowVisible())
        {
            m_edit.ShowWindow(SW_SHOW);
        }
        if(!m_btn.IsWindowVisible())
        {
            m_btn.ShowWindow(SW_SHOW);
        }
    
        m_edit.SetFocus();
    }

    动态按钮(MY_BTN):

    自定义消息与响应函数

    afx_msg void OnMyBtnClick();
    ON_BN_CLICKED(MY_BTN,OnMyBtnClick)

    响应为 弹出一个选择文件夹对话框,点击确定后,更新CListBox中内容。

    void CMyListBox::OnMyBtnClick()
    {
        CString strPath;
    
        TCHAR szDir[MAX_PATH];
        BROWSEINFO bi;    
        bi.hwndOwner = this->m_hWnd;
        bi.pidlRoot = NULL;
        bi.pszDisplayName = szDir;
        bi.lpszTitle = _T("请选择目录");
        bi.ulFlags = BIF_STATUSTEXT | BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
        bi.lpfn = NULL;
        bi.lParam = 0;
        bi.iImage = 0;
    
        ITEMIDLIST *pidl = SHBrowseForFolder(&bi);
        if(pidl == NULL)
        {
            return;
        }
        if(!SHGetPathFromIDList(pidl,szDir))
        {
            return;
        }
        else
        {
            strPath = szDir;
            UpdateContent(strPath); // 更新CListBox数据
        }
    }

    更新CListBox数据UpdateContent:

    删除默认行,重新插入数据到当前行,末尾加上默认行,让edit与button隐藏

    // 更新ListBox内容
    void CMyListBox::UpdateContent(const CString str)
    {
        int index = GetCurSel();
        DeleteString(index);
        AddString(str);
    
        InsertFlagString();
        SetCurSel(-1);
        SetFocus();
    
        if(m_edit.IsWindowVisible())
        {
            m_edit.ShowWindow(SW_HIDE);
        }
        if(m_btn.IsWindowVisible())
        {
            m_btn.ShowWindow(SW_HIDE);
        }
    }

    4. 右键菜单:删除

    资源中添加菜单,类中定义一个CMenu变量。初始化时LoadMenu。

    右键按下时响应函数OnRButtonDown:

    void CMyListBox::OnRButtonDown(UINT nFlags, CPoint point)
    {
        // TODO: 在此添加消息处理程序代码和/或调用默认值
        CRect rc;
        CMenu *popMenu = m_menu.GetSubMenu(0);
    
        int nCount = GetCount();
        int i = 0;
        for(; i<nCount; ++i)
        {
            GetItemRect(i,rc);
            if(rc.PtInRect(point))
            {
                if(i == nCount-1)
                {
                    SetCurSel(-1);
                    popMenu->EnableMenuItem(ID_DELETE,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); 
                }
                else
                {
                    SetCurSel(i);
                    popMenu->EnableMenuItem(ID_DELETE,MF_BYCOMMAND | MF_ENABLED); 
                    break;
                }
            }
        }
        ClientToScreen(&point);
        popMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x,point.y,this);
    
        CListBox::OnRButtonDown(nFlags, point);
    }

    删除(ID_DELETE)添加处理函数OnDelete:

    void CMyListBox::OnDelete()
    {
        // TODO: 在此添加命令处理程序代码
        int index = GetCurSel();
        DeleteString(index);
    }

    此时,初步完成以上效果,当点击...按钮弹出 "选择文件对话框",点OK后,更新显示在ListBox中。唯一不足是,edit数据内容只能通过...按钮点确定后才更改,直接点击修改不起作用。可能需要窗口子类化。有时间再修改。

  • 相关阅读:
    服务器上的 Git
    进程有哪几种基本状态,在一个系统中为什么必须区分出这几种状态?
    什么是进程,进程与程序的主要区别是什么?
    什么是与时间有关的错误,是举例说明。
    试解释下列名词:程序的顺序执行,程序的并发执行。
    简述系统调用的执行过程?
    假定某系统提供硬件的访管指令(例如形式:“svc n”),为了实现系统调用,系统设计者应做哪些工作?用户又如如何请求操作系统服务?
    什么是系统调用,对操作系统的服务请求与一般子程序调用有什么区别?
    Windows系统提供什么样的接口,Unix、Linux系统的用户接口是什么?
    用户与操作系统的接口是什么?一个分时系统提供什么接口?一个批处理系统又提供什么接口?
  • 原文地址:https://www.cnblogs.com/sylar-liang/p/4120066.html
Copyright © 2020-2023  润新知