Re: Can Some one help me to Add a ScroolBar to the CCtrlListWnd
 
Hi Joseph M. Newcomer [MVP],Thanks For your help.
With your suggestion,now i change some code. i use it as following
m_pWndCtrl = new CCtrlListWnd;
 m_pWndCtrl->Create(WS_VISIBLE|WS_VSCROLL|WS_CHILD,CRect(0,0,400,400),this,1); ITEMINFOR ItemInfo; ItemInfo.m_ctlType = EditCTL; ItemInfo.m_nStyle = ES_WANTRETURN|ES_MULTILINE|ES_AUTOVSCROLL; for(int i=0;i<10;i++) {  ItemInfo.m_nPos = i;  m_pWndCtrl->InsertItem(&ItemInfo); }but the scroolbar still can't work. how can i make the scroll bar work.thanks.the changed code is following:/********************************************************************************************/// Author: sound_of_nature// Email: sound_of_nature@hotmail.com// Verion: 1.0// Date: 5/12/2008/********************************************************************************************/// CtrlListWnd.h : header file//#pragma once#define WM_USER_ITEMCHANGED WM_USER+10#define MIN_HEIGHT 18enum ItemCtrlType{EditCTL,PICCTL,ListCTL,LinkCtl};/////////////////////////////////////////////////////////////////////////////////////////ITEM////class ITEMINFOR{public: ItemCtrlType m_ctlType; unsigned int m_nPos; int m_nHeight; DWORD m_nStyle;public: ITEMINFOR& operator=(ITEMINFOR itemInfo) {  m_ctlType = itemInfo.m_ctlType;  m_nHeight = itemInfo.m_nHeight;  m_nPos = itemInfo.m_nPos;  m_nStyle = itemInfo.m_nStyle;  return (*(ITEMINFOR*)this); };};class ITEM{public: ITEM() {  m_ctlType = EditCTL;  m_nPos = 0;  m_nHeight = MIN_HEIGHT;  m_pControl = NULL; }; ~ITEM() {  delete m_pControl;  m_pControl = NULL; };public: ItemCtrlType m_ctlType; unsigned int m_nPos; int m_nHeight; CWnd *m_pControl;};//////////////////////////////////////////////////////////////////////////////////////// CExtensibleEdit////class CExtensibleEdit : public CEdit{ DECLARE_DYNAMIC(CExtensibleEdit)public: CExtensibleEdit(); virtual ~CExtensibleEdit();protected: DECLARE_MESSAGE_MAP()protected: afx_msg void OnEnUpdate();protected: virtual void PreSubclassWindow();public: ITEMINFOR m_ItemInfo; virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINTnID);};////////////////////////////////////////////////////////////////////////////////////////// CCtrlListWnd////class CCtrlListWnd : public CWnd{ DECLARE_DYNAMIC(CCtrlListWnd)public: CMap <unsigned int,unsigned int ,ITEM* ,ITEM* > m_mapItem; CCtrlListWnd(); virtual ~CCtrlListWnd();protected: DECLARE_MESSAGE_MAP()public: ITEM *CreateControl(ITEMINFOR* lpItemInfo); BOOL InsertItem(ITEMINFOR* lpItemInfo); void RepositionItems(ITEMINFOR *pItemInfor); afx_msg LRESULT OnItemChanged(WPARAM wParam,LPARAM lParam);public: virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINTnID, CCreateContext* pContext = NULL); virtual BOOL CreateEx(DWORD dwExStyle, DWORD dwStyle, const RECT& rect,CWnd* pParentWnd, UINT nID, LPVOID lpParam = NULL); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);protected: static CString m_classname;};/********************************************************************************************/// Author: sound_of_nature// Email: sound_of_nature@hotmail.com// Verion: 1.0// Date: 5/12/2008/********************************************************************************************/// CtrlListWnd.cpp : implementation file//#include "stdafx.h"#include "WndEX.h"/////////////////////////////////////////////////////////////////////////////////////////////// CExtensibleEdit////IMPLEMENT_DYNAMIC(CExtensibleEdit, CEdit)CExtensibleEdit::CExtensibleEdit(){}CExtensibleEdit::~CExtensibleEdit(){}BEGIN_MESSAGE_MAP(CExtensibleEdit, CEdit) ON_CONTROL_REFLECT(EN_UPDATE, &CExtensibleEdit::OnEnUpdate)END_MESSAGE_MAP()// CExtensibleEdit message handlersBOOL CExtensibleEdit::Create(DWORD dwStyle, const RECT& rect, CWnd*pParentWnd, UINT nID){ // TODO: Add your specialized code here and/or call the base class dwStyle&=~ES_AUTOHSCROLL; dwStyle|=WS_VISIBLE|WS_CHILD|WS_BORDER; return CEdit::Create(dwStyle, rect, pParentWnd, nID);}void CExtensibleEdit::OnEnUpdate(){ CClientDC dc(this); //get the size of the text CFont *pOldFont = dc.SelectObject(GetFont()); CString Str; GetWindowText(Str); CSize sizeText = dc.GetTextExtent(Str); long TextHeight = sizeText.cy; dc.SelectObject(pOldFont); //get the inside size f the edit CRect Rect; GetRect(&Rect); //get the external size of the edit CRect wRect; GetWindowRect(&wRect); sizeText.cy *=  GetLineCount(); CRect rcParentClient; GetParent()->GetClientRect(rcParentClient); Rect.bottom = Rect.top+sizeText.cy+MIN_HEIGHT; Rect.right = Rect.left+rcParentClient.Width(); CalcWindowRect(&Rect); m_ItemInfo.m_nHeight = Rect.Height(); TRACE("OldHeight=%d,NewHeight=%d\n",wRect.Height(), Rect.Height()); if(wRect.Height() != Rect.Height()) {  GetParent()->SendMessage(WM_USER_ITEMCHANGED,(WPARAM)(this),(LPARAM)(&m_ItemInfo)); }}void CExtensibleEdit::PreSubclassWindow(){ ASSERT( (GetStyle() & ES_AUTOHSCROLL) == 0); CEdit::PreSubclassWindow();}//////////////////////////////////////////////////////////////////////////////////////// CCtrlListWnd////IMPLEMENT_DYNAMIC(CCtrlListWnd, CWnd)CString CCtrlListWnd::m_classname = _T("");CCtrlListWnd::CCtrlListWnd(){}CCtrlListWnd::~CCtrlListWnd(){ POSITION pos = m_mapItem.GetStartPosition(); unsigned int nkey; ITEM* pItem = NULL; while (pos != NULL) {  m_mapItem.GetNextAssoc(pos, nkey, pItem);  delete pItem;  pItem = NULL; }}BEGIN_MESSAGE_MAP(CCtrlListWnd, CWnd) ON_MESSAGE(WM_USER_ITEMCHANGED,OnItemChanged) ON_WM_VSCROLL()END_MESSAGE_MAP()// CCtrlListWnd message handlersITEM *CCtrlListWnd::CreateControl(ITEMINFOR* lpItemInfo){ if (lpItemInfo==NULL)return NULL; ITEM *lpItem = new ITEM; if (lpItem == NULL)return NULL; switch (lpItemInfo->m_ctlType) { case EditCTL:  {   CExtensibleEdit *pCtl = new CExtensibleEdit;   if (pCtl!=NULL)   {    CRect rcClient;    GetClientRect(rcClient);    if(!pCtl->Create(lpItemInfo->m_nStyle,CRect(0,0,0,0),this,lpItemInfo->m_nPos))    {     delete lpItem;     lpItem = NULL;     delete pCtl;     pCtl = NULL;    }else    {     lpItemInfo->m_nHeight =(lpItemInfo->m_nHeight>MIN_HEIGHT)?lpItemInfo->m_nHeight:MIN_HEIGHT;     pCtl->m_ItemInfo = (*lpItemInfo);     lpItem->m_ctlType = EditCTL;     lpItem->m_nHeight = lpItemInfo->m_nHeight;     lpItem->m_nPos = lpItemInfo->m_nPos;     lpItem->m_pControl = pCtl;     return lpItem;    }   }  }  break; case PICCTL:  break; case ListCTL:  break; case LinkCtl:  break; } return NULL;}BOOL CCtrlListWnd::InsertItem(ITEMINFOR* lpItemInfo){ ITEM *lpItem = CreateControl(lpItemInfo); if(lpItem==NULL)return FALSE; ITEM *tpItem = NULL; unsigned int ipos = lpItem->m_nPos; unsigned int size = m_mapItem.GetSize(); if(ipos==-1) {  lpItemInfo->m_nPos = size;  lpItem->m_nPos = size;  m_mapItem[size]=lpItem;  OnItemChanged((WPARAM)lpItem->m_pControl,(LPARAM)lpItemInfo);  return TRUE; } m_mapItem.Lookup(ipos,tpItem); if(tpItem==NULL) {  m_mapItem[ipos]=lpItem; }else {  for(unsigned int ct = size;ct>ipos;ct--)  {   m_mapItem.Lookup(ct-1,tpItem);   m_mapItem[ct]=tpItem;  }  m_mapItem[ipos]=lpItem; } OnItemChanged((WPARAM)lpItem->m_pControl,(LPARAM)lpItemInfo); return TRUE;}void CCtrlListWnd::RepositionItems(ITEMINFOR *pItemInfor){ unsigned int size = m_mapItem.GetSize(); if (size<=0)return ; CRect rcReDraw; GetClientRect(rcReDraw); unsigned int nWndWidth = rcReDraw.Width(); unsigned int nWndHeight = 1; for(unsigned int ct =0;ct<size;ct++) {  ITEM *tpItem = NULL;  m_mapItem.Lookup(ct,tpItem);  ENSURE(tpItem!=NULL);  ENSURE(tpItem->m_pControl!=NULL);  if (ct<pItemInfor->m_nPos)  {   nWndHeight+=tpItem->m_nHeight+1;  }else if (ct==pItemInfor->m_nPos)  {   tpItem->m_nHeight = pItemInfor->m_nHeight;   tpItem->m_pControl->SetWindowPos(this,-2,nWndHeight++,nWndWidth+4,pItemInfor->m_nHeight,SWP_SHOWWINDOW|SWP_NOZORDER);   rcReDraw.top = nWndHeight;   nWndHeight+=pItemInfor->m_nHeight;  }else  {   tpItem->m_pControl->SetWindowPos(this,-2,nWndHeight++,nWndWidth+4,tpItem->m_nHeight,SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOZORDER);   nWndHeight+=tpItem->m_nHeight;  } } /*GetScrollBarCtrl(SB_VERT)->SetScrollRange(0,nWndHeight);*/ ShowWindow(SW_SHOW); InvalidateRect(&rcReDraw); UpdateWindow();}LRESULT CCtrlListWnd::OnItemChanged(WPARAM wParam,LPARAM lParam){ CWnd *pWnd = (CWnd*)wParam; ENSURE(pWnd!=NULL); ITEMINFOR *pItemInfor = (ITEMINFOR *)lParam; ENSURE(pItemInfor!=NULL); if (pItemInfor->m_nHeight<=0)return 1; RepositionItems(pItemInfor) return 0;}BOOL CCtrlListWnd::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd,UINT nID, CCreateContext* pContext){ // TODO: Add your specialized code here and/or call the base class if (m_classname.IsEmpty()) {  // Register your unique class name that you wish to use  WNDCLASS wndcls;  memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults  wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;  //you can specify your own window procedure  wndcls.lpfnWndProc = ::DefWindowProc;  wndcls.hInstance = AfxGetInstanceHandle();  wndcls.hIcon = LoadIcon(wndcls.hInstance,MAKEINTRESOURCE(IDI_APPLICATION));  wndcls.hCursor = LoadCursor(wndcls.hInstance, MAKEINTRESOURCE(IDC_ARROW));  wndcls.hbrBackground = (HBRUSH)(::GetStockObject(WHITE_BRUSH));  wndcls.lpszMenuName = NULL;  // Specify your own class name for using FindWindow later  wndcls.lpszClassName = _T("CtrlListWnd");  m_classname =  _T("CtrlListWnd");  // Register the new class and trace if it fails  if(!AfxRegisterClass(&wndcls))  {   TRACE("Class Registration Failed\n");   return FALSE;  } } return CWnd::Create(m_classname , NULL, dwStyle, rect, pParentWnd, nID,pContext);}BOOL CCtrlListWnd::CreateEx(DWORD dwExStyle,DWORD dwStyle, const RECT& rect,CWnd* pParentWnd, UINT nID, LPVOID lpParam){ // TODO: Add your specialized code here and/or call the base class if (m_classname.IsEmpty()) {  // Register your unique class name that you wish to use  WNDCLASS wndcls;  memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults  wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;  //you can specify your own window procedure  wndcls.lpfnWndProc = ::DefWindowProc;  wndcls.hInstance = AfxGetInstanceHandle();  wndcls.hIcon = LoadIcon(wndcls.hInstance,MAKEINTRESOURCE(IDI_APPLICATION));  wndcls.hCursor = LoadCursor(wndcls.hInstance, MAKEINTRESOURCE(IDC_ARROW));  wndcls.hbrBackground = (HBRUSH)(::GetStockObject(WHITE_BRUSH));  wndcls.lpszMenuName = NULL;  // Specify your own class name for using FindWindow later  wndcls.lpszClassName = _T("CtrlListWnd");  m_classname =  _T("CtrlListWnd");  // Register the new class and trace if it fails  if(!AfxRegisterClass(&wndcls))  {   TRACE("Class Registration Failed\n");   return FALSE;  } } return CWnd::CreateEx(dwExStyle, _T("CtrlListWnd") , NULL, dwStyle, rect,pParentWnd, nID, lpParam);}void CCtrlListWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar){ // TODO: Add your message handler code here and/or call default MessageBox(_T("OnVScroll")); CWnd::OnVScroll(nSBCode, nPos, pScrollBar);}sunny5/13/2008