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