From: Sunny on
hello every one.
I write a Ctrl,named CCtrlListWnd,which is derived from CWnd. and i want to
know how to add a ScroolBar to the CCtrlListWnd.

Can some one help me.Thanks for your attention and suggestion.

The code is below:

/********************************************************************************************/
// Author: sound_of_nature
// Email: sound_of_nature(a)hotmail.com
// Verion: 1.0
// Date: 5/12/2008
/********************************************************************************************/
// CtrlListWnd.h : header file
//
#pragma once
#define WM_ITEMCHANGED WM_USER+10
#define MIN_HEIGHT 18

enum 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;
};

////////////////////////////////////////////////////////////////////////////////////////
// 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(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT&
rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
};


/********************************************************************************************/
// Author: sound_of_nature
// Email: sound_of_nature(a)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 handlers



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 of 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())
{
::SendMessage(GetParent()->GetSafeHwnd(),WM_ITEMCHANGED,(WPARAM)(this),(LPARAM)(&m_ItemInfo));
}
}

void CExtensibleEdit::PreSubclassWindow()
{
ASSERT( (GetStyle() & ES_AUTOHSCROLL) == 0);
CEdit::PreSubclassWindow();
}

//////////////////////////////////////////////////////////////////////////////////////
// CCtrlListWnd
////
IMPLEMENT_DYNAMIC(CCtrlListWnd, CWnd)

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_ITEMCHANGED,OnItemChanged)
END_MESSAGE_MAP()



// CCtrlListWnd message handlers

ITEM *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(ES_MULTILINE | WS_CHILD | WS_VISIBLE | WS_TABSTOP |
WS_BORDER
|lpItemInfo->m_nStyle&~ES_AUTOHSCROLL|ES_AUTOVSCROLL,CRect(0,0,rcClient.Width(),30),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 rcParentWindow;
CWnd *pParentWnd = GetParent();
ENSURE(pParentWnd!=NULL);
pParentWnd->GetClientRect(rcParentWindow);
unsigned int cx = rcParentWindow.Width();
unsigned int cy = rcParentWindow.Height();
unsigned int nWndHeight = 1;
CRect rcReDraw;
//LockWindowUpdate();
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++,cx+4,pItemInfor->m_nHeight,SWP_SHOWWINDOW|SWP_NOZORDER);
rcReDraw.top = nWndHeight;
nWndHeight+=pItemInfor->m_nHeight;
}else
{
tpItem->m_pControl->SetWindowPos(this,-2,nWndHeight++,cx+4,tpItem->m_nHeight,SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOZORDER);
nWndHeight+=tpItem->m_nHeight;
}
}
SetWindowPos(pParentWnd,0,0,cx,max(nWndHeight,cy),SWP_NOMOVE|SWP_SHOWWINDOW|SWP_NOZORDER); //UnlockWindowUpdate(); CRect rcClient; GetClientRect(rcClient); rcReDraw.left = rcClient.left; rcReDraw.right = rcClient.right; rcReDraw.bottom = rcClient.bottom; 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(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT&rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext){ // TODO: Add your specialized code here and/or call the base class CString strMyClass = AfxRegisterWndClass( CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH) ::GetStockObject(WHITE_BRUSH), ::LoadIcon(NULL, IDI_APPLICATION)); return CWnd::Create(strMyClass, lpszWindowName,WS_VISIBLE|WS_CHILD|dwStyle, rect, pParentWnd, nID, pContext);}

From: Sunny on
The following show how to use the CCtrlList :


CtestDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here
m_pWndCtrl = new CCtrlListWnd;
m_pWndCtrl->Create(_T("Test"),0,CRect(0,0,0,0),this,1);
ITEMINFOR ItemInfo;
ItemInfo.m_ctlType = EditCTL;
ItemInfo.m_nStyle = ES_WANTRETURN;
for(int i=0;i<10;i++)
{
ItemInfo.m_nPos = i;
m_pWndCtrl->InsertItem(&ItemInfo);
}
return TRUE; // return TRUE unless you set the focus to a control
}


From: Joseph M. Newcomer on
See below...
On Mon, 12 May 2008 16:24:39 +0800, "Sunny" <sound_of_nature(a)hotmail.com> wrote:

>hello every one.
>I write a Ctrl,named CCtrlListWnd,which is derived from CWnd. and i want to
>know how to add a ScroolBar to the CCtrlListWnd.
>
>Can some one help me.Thanks for your attention and suggestion.
>
>The code is below:
>
>/********************************************************************************************/
>// Author: sound_of_nature
>// Email: sound_of_nature(a)hotmail.com
>// Verion: 1.0
>// Date: 5/12/2008
>/********************************************************************************************/
>// CtrlListWnd.h : header file
>//
>#pragma once
>#define WM_ITEMCHANGED WM_USER+10
****
Do not ever use WM_ as a prefix for user-defined messages; it leads to severe confusion.
Use a generic prefix such as UWM_ or WMU_ to indicate user defined, or MYCTRL_ or
something like that. Consider "WM_" to be a "reserved" prefix in the universe and not
avaiable for anyone outside Microsoft (the number of times I've had questions asking about
obscure "Windows messages" which were really user-defined messages shows that this
confusion is very real)
****
>#define MIN_HEIGHT 18
>
>enum 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;
>};
>
>////////////////////////////////////////////////////////////////////////////////////////
>// 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(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT&
>rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
>};
****
Note that to get scrollbars, you need to include the WS_HSCROLL and/or WS_VSCROLL styles;
I tend to do a Create method of the form

public:
BOOL Create(const CRect & r, UINT id, CWnd * parent) {
return Create( ..., WS_CHILD | WS_VSCROLL | WS_VISIBLE | ..., ...);

Window creation of a custom subclass is far too valuable to leave up to the caller of your
class. Note also that you will probably need to AfxRegisterClass the class as well, and
this must be part of your class definition; it is not to be left up to the caller. I'll
typically do. You should not depend on the caller to register the class and pass it in.

protected:
CString classname;
so at some point I create the class name, e.g.,

BOOL Create(...as above) {
if(classname.IsEmpty())
classname = AfxRegisterClass(_T("CtrlListWnd") _T("...guid here..."));
return Create(classname, ...etc..);
}

Note that if I want to have styles, what I will first do is
BOOL Create(DWORD style, ...)
{
style &= ~STYLES_I_WANT_FORBIDDEN;
style |= STYLES_WHICH_ARE_MANDATORY;
...register class name
return CreateWindow(..etc...);
}

so the only styles the user can pass in might be WS_VSCROLL (if scrollbars are supposed to
be optional) or WS_VISIBLE (if visibility is desired), and so on. But mostly I don't
allow the user to specify the style, and in no case do I let the caller specify the window
class. The window name matters only for controls like static, edit, and other variants
where you want them preloaded with content; the "window name" (which is the caption) is
typically NULL for any case you don't care about; the CreateWindow API fails to document
that this parameter is permitted to be NULL.
joe
****
>
>
>/********************************************************************************************/
>// Author: sound_of_nature
>// Email: sound_of_nature(a)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 handlers
>
>
>
>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 of 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())
> {
> ::SendMessage(GetParent()->GetSafeHwnd(),WM_ITEMCHANGED,(WPARAM)(this),(LPARAM)(&m_ItemInfo));
> }
****
Not necessary
GetParent()->SendMessage(UWM_ITEM_CHANGED, ...etc..)
because a child window must ALWAYS have a parent.
****
>}
>
>void CExtensibleEdit::PreSubclassWindow()
>{
> ASSERT( (GetStyle() & ES_AUTOHSCROLL) == 0);
> CEdit::PreSubclassWindow();
>}
>
>//////////////////////////////////////////////////////////////////////////////////////
>// CCtrlListWnd
>////
>IMPLEMENT_DYNAMIC(CCtrlListWnd, CWnd)
>
>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_ITEMCHANGED,OnItemChanged)
>END_MESSAGE_MAP()
>
>
>
>// CCtrlListWnd message handlers
>
>ITEM *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(ES_MULTILINE | WS_CHILD | WS_VISIBLE | WS_TABSTOP |
>WS_BORDER
>|lpItemInfo->m_nStyle&~ES_AUTOHSCROLL|ES_AUTOVSCROLL,CRect(0,0,rcClient.Width(),30),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 rcParentWindow;
> CWnd *pParentWnd = GetParent();
> ENSURE(pParentWnd!=NULL);
> pParentWnd->GetClientRect(rcParentWindow);
> unsigned int cx = rcParentWindow.Width();
> unsigned int cy = rcParentWindow.Height();
> unsigned int nWndHeight = 1;
> CRect rcReDraw;
> //LockWindowUpdate();
> 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++,cx+4,pItemInfor->m_nHeight,SWP_SHOWWINDOW|SWP_NOZORDER);
> rcReDraw.top = nWndHeight;
> nWndHeight+=pItemInfor->m_nHeight;
> }else
> {
> tpItem->m_pControl->SetWindowPos(this,-2,nWndHeight++,cx+4,tpItem->m_nHeight,SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOZORDER);
> nWndHeight+=tpItem->m_nHeight;
> }
> }
> SetWindowPos(pParentWnd,0,0,cx,max(nWndHeight,cy),SWP_NOMOVE|SWP_SHOWWINDOW|SWP_NOZORDER); //UnlockWindowUpdate(); CRect rcClient; GetClientRect(rcClient); rcReDraw.left = rcClient.left; rcReDraw.right = rcClient.right; rcReDraw.bottom = rcClient.bottom; 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(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT&rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext){ // TODO: Add your specialized code here and/or call the base class CString strMyClass = AfxRegisterWndClass( CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH) ::GetStockObject(WHITE_BRUSH), ::LoadIcon(NULL, IDI_APPLICATION)); return CWnd::Create(strMyClass,
>lpszWindowName,WS_VISIBLE|WS_CHILD|dwStyle, rect, pParentWnd, nID, pContext);}
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Sunny on
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(a)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(a)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 of 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

From: Sunny on
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 scroolbarstill can't work. how can i make the scroll bar work.thanks.the changed codeis following:/********************************************************************************************/// Author: sound_of_nature// Email: sound_of_nature(a)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(a)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 of 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);}