CCtrlView 雑記 |
Last Updated: Feb.14,2007 |
| 使用しているコンパイラは、Microsoft Visual C++ 6.0 です。これ以外のバージョンでは記述と食い違うことがあるかも知れません。 | |
CCtrlView から派生させて CListBoxView を作ってみました。ポイントになるのは、コンストラクタと OnChildNotify あたりでしょうか。編集機能とシリアライズ機能も付けてみましたが、MFC の CListView の方が便利なのでほとんど用途はないかもしれません。ソースを丸ごと載せておきます。ヘッダーファイルはこちら。
// ListBoxView.cpp : インプリメンテーション ファイル
//
// Copyright (c) 2007 AOK. All Rights Reserved.
//
#include "stdafx.h"
#include "ListBoxView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CLBEdit - 編集用のエディットコントロール
CLBEdit::CLBEdit()
: m_nCurIndex(-1)
{
}
CLBEdit::~CLBEdit()
{
}
BEGIN_MESSAGE_MAP(CLBEdit, CEdit)
//{{AFX_MSG_MAP(CLBEdit)
ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillFocus)
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CLBEdit メッセージ ハンドラ
CListBoxView* CLBEdit::GetView() const
{
CWnd* pWnd = GetParent();
ASSERT_VALID(pWnd);
ASSERT_KINDOF(CListBoxView, pWnd);
return (CListBoxView*)pWnd;
}
void CLBEdit::BeginEdit(int nItem, LPCTSTR pszText)
{
ASSERT(nItem != LB_ERR);
m_nCurIndex = nItem;
m_sPreText = pszText;
SetFont(GetView()->GetFont());
SetWindowText(pszText);
}
void CLBEdit::EndEdit()
{
if (m_nCurIndex == -1) return;
CString sText;
GetWindowText(sText);
CListBoxView* pView = GetView();
if (sText.IsEmpty())
{
pView->GetListBox().DeleteString(m_nCurIndex);
pView->AdjustListBox();
}
else if (m_sPreText.Compare(sText) != 0)
{
pView->GetListBox().InsertString(m_nCurIndex, sText);
pView->GetListBox().DeleteString(m_nCurIndex+1);
pView->AdjustListBox();
}
m_nCurIndex = -1;
}
void CLBEdit::OnChange()
{
CString sText;
GetWindowText(sText);
CListBoxView* pView = GetView();
if (m_sPreText.Compare(sText) != 0)
pView->GetDocument()->SetModifiedFlag(TRUE);
}
void CLBEdit::OnKillFocus()
{
EndEdit();
ShowWindow(SW_HIDE);
}
void CLBEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_RETURN)
{
int nSave = m_nCurIndex;
ShowWindow(SW_HIDE);
if (nSave != -1)
GetView()->GetListBox().SetCurSel(nSave);
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
/////////////////////////////////////////////////////////////////////////////
// CListBoxView
IMPLEMENT_DYNCREATE(CListBoxView, CCtrlView)
CListBoxView::CListBoxView()
: CCtrlView(_T("LISTBOX"), AFX_WS_DEFAULT_VIEW
| WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN
| LBS_NOINTEGRALHEIGHT | LBS_NOTIFY)
{
}
CListBoxView::~CListBoxView()
{
}
BEGIN_MESSAGE_MAP(CListBoxView, CCtrlView)
//{{AFX_MSG_MAP(CListBoxView)
ON_WM_CREATE()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CListBoxView メッセージ ハンドラ
int CListBoxView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CCtrlView::OnCreate(lpCreateStruct) == -1)
return -1;
//SendMessage(WM_SETFONT, (WPARAM)::GetStockObject(DEFAULT_GUI_FONT), 0);
m_edit.Create(WS_CHILD|WS_BORDER|ES_AUTOHSCROLL,
CRect(0,0,0,0), this, GetDlgCtrlID()+1);
return 0;
}
CListBox& CListBoxView::GetListBox() const
{
return *(CListBox*)this;
}
void CListBoxView::AdjustListBox()
{
ASSERT((GetStyle() & LBS_MULTICOLUMN) == 0);
CListBox& lb = GetListBox();
CString str;
CSize size;
int dx = 0;
CDC* pDC = lb.GetDC();
CFont *pOldFont = pDC->SelectObject(GetFont());
int c = lb.GetCount();
for (int i = 0; i < c; i++)
{
lb.GetText(i, str);
size = pDC->GetTextExtent(str + _T(' '));
if (size.cx > dx) dx = size.cx;
}
lb.SetHorizontalExtent(dx);
pDC->SelectObject(pOldFont);
lb.ReleaseDC(pDC);
}
void CListBoxView::SerializeRaw(CArchive& ar)
{
CListBox& lb = GetListBox();
CString sText;
if (ar.IsStoring())
{
int nCount = lb.GetCount();
for (int i = 0; i < nCount; i++)
{
lb.GetText(i, sText);
if (!sText.IsEmpty())
ar.WriteString(sText + _T("\r\n"));
}
}
else
{
lb.ResetContent();
while (ar.ReadString(sText))
lb.AddString(sText);
AdjustListBox();
}
}
void CListBoxView::OnSize(UINT nType, int cx, int cy)
{
CCtrlView::OnSize(nType, cx, cy);
if (m_edit.GetSafeHwnd())
{
CRect rect;
m_edit.GetWindowRect(&rect);
m_edit.SetWindowPos(NULL, 0, 0, cx, rect.Height(),
SWP_NOMOVE|SWP_NOZORDER);
}
}
BOOL CListBoxView::OnChildNotify(UINT message, WPARAM wParam,
LPARAM lParam, LRESULT* pLResult)
{
if (message == WM_COMMAND)
{
switch (HIWORD(wParam))
{
case LBN_ERRSPACE:
break;
case LBN_SELCHANGE:
OnSelChange(GetListBox().GetCurSel());
return TRUE;
case LBN_DBLCLK:
OnDblClk(GetListBox().GetCurSel());
return TRUE;
case LBN_SELCANCEL:
break;
case LBN_SETFOCUS:
break;
case LBN_KILLFOCUS:
break;
default:
break;
}
}
return CCtrlView::OnChildNotify(message, wParam, lParam, pLResult);
}
void CListBoxView::OnSelChange(int nItem)
{
if (nItem == LB_ERR) return;
CString s;
GetListBox().GetText(nItem, s);
CWnd* pWnd = AfxGetMainWnd();
ASSERT_VALID(pWnd);
ASSERT_KINDOF(CFrameWnd, pWnd);
((CFrameWnd*)pWnd)->SetMessageText(s);
}
void CListBoxView::OnDblClk(int nItem)
{
if (nItem == LB_ERR) return;
CRect rect;
GetListBox().GetItemRect(nItem, &rect);
int cy = ::GetSystemMetrics(SM_CYBORDER);
/* 全く同じサイズにすると編集状態かどうか分かりにくいため */
rect.InflateRect(0, cy+1, 0, cy+1);
CString sText;
GetListBox().GetText(nItem, sText);
m_edit.BeginEdit(nItem, sText);
m_edit.MoveWindow(&rect, FALSE);
m_edit.ShowWindow(SW_SHOWNORMAL);
m_edit.SetFocus();
}
新規行挿入と行削除は実装していませんが、
で、OK です。
| Back | Copyright (c) 2007 AOK. All Rights Reserved. |