List Control如何实现下面的效果?
VIEW为Report,如何是其他view能够实现也可以
1 单元格显示多行字符。
2 单元格高度随字符行数自动变换。
3 可以编辑单元格,接受回车,鼠标移开自动保存的界面谢谢
VIEW为Report,如何是其他view能够实现也可以
1 单元格显示多行字符。
2 单元格高度随字符行数自动变换。
3 可以编辑单元格,接受回车,鼠标移开自动保存的界面谢谢
// DropDownList.h
#pragma once
#include <vector>
#include <string>
using namespace std;
// CInplaceComboBox
class CInplaceComboBox : public CComboBox
{
DECLARE_DYNAMIC(CInplaceComboBox)
public:
CInplaceComboBox(int item, int col, CString& text);
virtual ~CInplaceComboBox();
protected:
CString _text;
int _item;
int _subItem;
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnNcDestroy();
afx_msg void OnKillFocus(CWnd* pNewWnd);
void SelfDestroy(void);
};
// CDropDownListCtrl
class CDropDownListCtrl : public CListCtrl
{
DECLARE_DYNAMIC(CDropDownListCtrl)
public:
CDropDownListCtrl();
virtual ~CDropDownListCtrl();
void setComboItems(vector<string>& domains) { _domains=domains; }
protected:
vector<string> _domains;
DECLARE_MESSAGE_MAP()
public:
CComboBox* EditSubLabel(int nItem, int nCol);
int HitTestEx(CPoint& point, int* col);
afx_msg void OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
};
//////////////////////////////////////////////////////////////////
//
// DropDownListCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "DropDownListCtrl.h"
#include ".\dropdownlistctrl.h"
#define IDC_INPLACECOMBO 75001
// CInplaceComboBox
IMPLEMENT_DYNAMIC(CInplaceComboBox, CComboBox)
BEGIN_MESSAGE_MAP(CInplaceComboBox, CComboBox)
ON_WM_NCDESTROY()
ON_WM_KILLFOCUS()
// ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnCbnKillfocus)
END_MESSAGE_MAP()
// CInplaceComboBox message handlers
CInplaceComboBox::CInplaceComboBox(int item, int col, CString& text)
:_text(text),_item(item),_subItem(col)
{
}
CInplaceComboBox::~CInplaceComboBox()
{
}
// CDropDownListCtrl message handlers
void CInplaceComboBox::OnNcDestroy()
{
CComboBox::OnNcDestroy();
delete this;
}
void CInplaceComboBox::OnKillFocus(CWnd* pNewWnd)
{
CComboBox::OnKillFocus(pNewWnd);
SelfDestroy();
}
void CInplaceComboBox::SelfDestroy(void)
{
CString str;
GetWindowText(str);
if( !str.IsEmpty()) {
// Send Notification to parent of ListView ctrl
LV_DISPINFO dispinfo;
dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
dispinfo.hdr.idFrom = GetDlgCtrlID();
dispinfo.hdr.code = LVN_ENDLABELEDIT;
dispinfo.item.mask = LVIF_TEXT;
dispinfo.item.iItem = _item;
dispinfo.item.iSubItem = _subItem;
dispinfo.item.pszText = LPTSTR((LPCTSTR)str);
dispinfo.item.cchTextMax = str.GetLength();
GetParent()->GetParent()->SendMessage( WM_NOTIFY, GetParent()->GetDlgCtrlID(),
(LPARAM)&dispinfo );
}
DestroyWindow();
}
//////////////////////////////////////////////////////////////////////////////////////////////
// DropDownList.cpp
// CDropDownListCtrl
IMPLEMENT_DYNAMIC(CDropDownListCtrl, CListCtrl)
BEGIN_MESSAGE_MAP(CDropDownListCtrl, CListCtrl)
// ON_WM_CREATE()
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnLvnEndlabeledit)
ON_WM_LBUTTONDOWN()
ON_WM_HSCROLL()
ON_WM_VSCROLL()
END_MESSAGE_MAP()
CDropDownListCtrl::CDropDownListCtrl()
{
}
CDropDownListCtrl::~CDropDownListCtrl()
{
}
CComboBox* CDropDownListCtrl::EditSubLabel(int nItem, int nCol)
{
// Make sure that the item is visible
CString text = GetItemText( nItem, nCol );
if( !EnsureVisible( nItem, TRUE ) || text.IsEmpty() ) return NULL;
// Make sure that nCol is valid
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
if( nCol >= nColumnCount || GetColumnWidth(nCol) < 5 )
return NULL;
// Get the column offset
int offset = 0;
for( int i = 0; i < nCol; i++ )
offset += GetColumnWidth( i );
CRect rect;
GetItemRect( nItem, &rect, LVIR_BOUNDS );
// Now scroll if we need to expose the column
CRect rcClient;
GetClientRect( &rcClient );
if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
{
CSize size;
size.cx = offset + rect.left;
size.cy = 0;
Scroll( size );
rect.left -= size.cx;
}
// Get Column alignment
LV_COLUMN lvcol;
lvcol.mask = LVCF_FMT;
GetColumn( nCol, &lvcol );
DWORD dwStyle ;
if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)
dwStyle = ES_LEFT;
else if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT)
dwStyle = ES_RIGHT;
else dwStyle = ES_CENTER;
rect.left += offset+4;
rect.right = rect.left + GetColumnWidth( nCol ) - 3 ;
if( rect.right > rcClient.right) rect.right = rcClient.right;
rect.bottom = rect.top+200;
dwStyle |= WS_BORDER|WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST;
CComboBox *cb = new CInplaceComboBox(nItem, nCol, text);
cb->Create( dwStyle, rect, this, IDC_INPLACECOMBO );
cb->SetFocus();
for( size_t i = 0; i<_domains.size(); ++i) cb->AddString(_domains[i].c_str());
cb->SelectString(-1,text);
return cb;
}
int CDropDownListCtrl::HitTestEx(CPoint& point, int* col)
{
int colnum = 0;
int row = HitTest( point, NULL );
if( col ) *col = 0;
// Make sure that the ListView is in LVS_REPORT
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
return row;
// Get the top and bottom row visible
row = GetTopIndex();
int bottom = row + GetCountPerPage();
if( bottom > GetItemCount() )
bottom = GetItemCount();
// Get the number of columns
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
// Loop through the visible rows
for( ;row <=bottom;row++)
{
// Get bounding rect of item and check whether point falls in it.
CRect rect;
GetItemRect( row, &rect, LVIR_BOUNDS );
if( rect.PtInRect(point) )
{
// Now find the column
for( colnum = 0; colnum < nColumnCount; colnum++ )
{
int colwidth = GetColumnWidth(colnum);
if( point.x >= rect.left
&& point.x <= (rect.left + colwidth ) )
{
if( col ) *col = colnum;
return row;
}
rect.left += colwidth;
}
}
}
return -1;
}
void CDropDownListCtrl::OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
//NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
// TODO: Add your control notification handler code here
//*pResult = 0;
LV_DISPINFO *plvDispInfo = (LV_DISPINFO *)pNMHDR;
LV_ITEM *plvItem = &plvDispInfo->item;
if (plvItem->pszText != NULL)
{
SetItemText(plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
}
*pResult = FALSE;
}
void CDropDownListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
int index;
CListCtrl::OnLButtonDown(nFlags, point);
int colnum;
if( ( index = HitTestEx( point, &colnum )) != -1 )
{
UINT flag = LVIS_FOCUSED;
if( (GetItemState( index, flag ) & flag) == flag && colnum == 1)
{
// Add check for LVS_EDITLABELS
// if( GetWindowLong(m_hWnd, GWL_STYLE) & LVS_EDITLABELS )
EditSubLabel( index, colnum );
}
else
SetItemState( index, LVIS_SELECTED | LVIS_FOCUSED ,
LVIS_SELECTED | LVIS_FOCUSED);
}
}
void CDropDownListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( GetFocus() != this ) SetFocus();
CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CDropDownListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( GetFocus() != this ) SetFocus();
CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}
http://www.codeproject.com/KB/miscctrl/gridctrl.aspx
http://www.codeproject.com/KB/miscctrl/adding___quot_merge_cells.aspx
1 http://www.vckbase.com/code/viewcode.asp?id=2914
此类只能编辑,不能改变行高2 Tr0j4n
代码是与组合框的结合。3 muzizongheng http://www.codeproject.com/KB/miscctrl/gridctrl.aspx
不能自适应行高
http://www.codeproject.com/KB/miscctrl/adding___quot_merge_cells.aspx
此类功能确实强大,但是不能多行显示字符,不能输入回车符谢谢回答
编辑框已经接受回车,可以输入多行的问题已经解决,但是输入之后单元格显示的是一行。现在的问题是:
如何让单元格显示多行并且行的高度自动跟随输入文字的行数变化?
m_nFormat = DT_LEFT|DT_VCENTER/*|DT_SINGLELINE*/|DT_NOPREFIX | DT_END_ELLIPSIS; //change by jg for multi line.第二, void CGridCtrl::OnEndEditCell(int nRow, int nCol, CString str)里添加一句:
CString strCurrentText = GetItemText(nRow, nCol);
if (strCurrentText != str)
{
SetItemText(nRow, nCol, str);
if (ValidateEdit(nRow, nCol, str) &&
SendMessageToParent(nRow, nCol, GVN_ENDLABELEDIT) >= 0)
{
SetModified(TRUE, nRow, nCol);
RedrawCell(nRow, nCol); RedrawWindow();//add by jg for multi line text.
}
else
{
SetItemText(nRow, nCol, strCurrentText);
}
} CGridCellBase* pCell = GetCell(nRow, nCol);
if (pCell)
pCell->OnEndEdit();第三, 就是那个void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)里,//add by jg for multi line.
CRect rect;
UINT nFormat = DT_WORDBREAK | DT_CALCRECT;
int nDescrHeight = dc.DrawText(str, rect, nFormat);
//end
。。
if (nDescrHeight > m_Rect.Height())
{
((CGridCtrl*)GetParent())->SetRowHeight(m_nRow, nDescrHeight);
}
代码如下:
CInPlaceEdit::CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
int nRow, int nColumn, CString sInitText,
UINT nFirstChar)
{
m_sInitText = sInitText;
m_nRow = nRow;
m_nColumn = nColumn;
m_nLastChar = 0;
m_bExitOnArrows = (nFirstChar != VK_LBUTTON); // If mouse click brought us here,
// then no exit on arrows m_Rect = rect; // For bizarre CE bug.
DWORD dwEditStyle = WS_BORDER|WS_CHILD|WS_VISIBLE/*| ES_AUTOHSCROLL*/ | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL //add by jg for multiline
| dwStyle;void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_TAB/* || nChar == VK_RETURN*/) //delete by jg for multiline
{
m_nLastChar = nChar;
GetParent()->SetFocus(); // This will destroy this window
return;
}
C/C++ code
//add by jg for multi line.
CRect rect;
UINT nFormat = DT_WORDBREAK | DT_CALCRECT;
int nDescrHeight = dc.DrawText(str, rect, nFormat);
//end
。。
if (nDescrHeight > m_Rect.Height())
{
((CGridCtrl*)GetParent())->SetRowHeight(m_nRow, nDescrHeight);
}这段代码是不是添加在void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
函数的最下面。现在只剩下单元格内回车自动改变行高。
CRect rect = ParentRect;
UINT nFormat = DT_WORDBREAK | DT_CALCRECT;
int nDescrHeight = dc.DrawText(str, rect, nFormat);
//end
if (nDescrHeight > m_Rect.Height())
{
((CGridCtrl*)GetParent())->SetRowHeight(m_nRow, nDescrHeight);
}