- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# PlayerListCtrl.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 // PlayerListCtrl.cpp : implementation file
    00023 //
    00024
    00025 #include "stdafx.h"
    00026 #include "mplayerc.h"
    00027 #include "PlayerListCtrl.h"
    00028 #include ".\playerlistctrl.h"
    00029
    00030 // CInPlaceEdit
    00031
    00032 CInPlaceEdit::CInPlaceEdit(int iItem, int iSubItem, CString sInitText)
    00033         : m_sInitText( sInitText )
    00034 {
    00035         m_iItem = iItem;
    00036         m_iSubItem = iSubItem;
    00037         m_bESC = FALSE;
    00038 }
    00039
    00040 CInPlaceEdit::~CInPlaceEdit()
    00041 {
    00042 }
    00043
    00044 BEGIN_MESSAGE_MAP(CInPlaceEdit, CEdit)
    00045         //{{AFX_MSG_MAP(CInPlaceEdit)
    00046         ON_WM_KILLFOCUS()
    00047         ON_WM_NCDESTROY()
    00048         ON_WM_CHAR()
    00049         ON_WM_CREATE()
    00050         //}}AFX_MSG_MAP
    00051 END_MESSAGE_MAP()
    00052
    00054 // CInPlaceEdit message handlers
    00055
    00056 BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg)
    00057 {
    00058         if(pMsg->message == WM_KEYDOWN)
    00059         {
    00060                 if(pMsg->wParam == VK_RETURN
    00061                 || pMsg->wParam == VK_DELETE
    00062                 || pMsg->wParam == VK_ESCAPE
    00063                 || GetKeyState(VK_CONTROL))
    00064                 {
    00065                         ::TranslateMessage(pMsg);
    00066                         ::DispatchMessage(pMsg);
    00067                         return TRUE;                    // DO NOT process further
    00068                 }
    00069         }
    00070
    00071         return CEdit::PreTranslateMessage(pMsg);
    00072 }
    00073
    00074 void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd)
    00075 {
    00076         CEdit::OnKillFocus(pNewWnd);
    00077
    00078         CString str;
    00079         GetWindowText(str);
    00080
    00081         LV_DISPINFO dispinfo;
    00082         dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
    00083         dispinfo.hdr.idFrom = GetDlgCtrlID();
    00084         dispinfo.hdr.code = LVN_ENDLABELEDIT;
    00085         dispinfo.item.mask = LVIF_TEXT;
    00086         dispinfo.item.iItem = m_iItem;
    00087         dispinfo.item.iSubItem = m_iSubItem;
    00088         dispinfo.item.pszText = m_bESC ? NULL : LPTSTR((LPCTSTR)str);
    00089         dispinfo.item.cchTextMax = str.GetLength();
    00090         GetParent()->GetParent()->SendMessage(WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo);
    00091
    00092         DestroyWindow();
    00093 }
    00094
    00095 void CInPlaceEdit::OnNcDestroy()
    00096 {
    00097         CEdit::OnNcDestroy();
    00098
    00099         delete this;
    00100 }
    00101
    00102
    00103 void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
    00104 {
    00105         if(nChar == VK_ESCAPE || nChar == VK_RETURN)
    00106         {
    00107                 if(nChar == VK_ESCAPE) m_bESC = TRUE;
    00108                 GetParent()->SetFocus();
    00109                 return;
    00110         }
    00111
    00112         CEdit::OnChar(nChar, nRepCnt, nFlags);
    00113 }
    00114
    00115 int CInPlaceEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
    00116 {
    00117         if(CEdit::OnCreate(lpCreateStruct) == -1)
    00118                 return -1;
    00119
    00120         // Set the proper font
    00121         CFont* font = GetParent()->GetFont();
    00122         SetFont(font);
    00123
    00124         SetWindowText(m_sInitText);
    00125         SetFocus();
    00126         SetSel(0, -1);
    00127         return 0;
    00128 }
    00129
    00130 // CInPlaceComboBox
    00131
    00132 CInPlaceComboBox::CInPlaceComboBox(int iItem, int iSubItem, CList<CString>& lstItems, int nSel)
    00133 {
    00134         m_iItem = iItem;
    00135         m_iSubItem = iSubItem;
    00136
    00137         m_lstItems.AddTail(&lstItems);
    00138         m_nSel = nSel;
    00139         m_bESC = FALSE;
    00140 }
    00141
    00142 CInPlaceComboBox::~CInPlaceComboBox()
    00143 {
    00144 }
    00145
    00146 BEGIN_MESSAGE_MAP(CInPlaceComboBox, CComboBox)
    00147         //{{AFX_MSG_MAP(CInPlaceComboBox)
    00148         ON_WM_CREATE()
    00149         ON_WM_KILLFOCUS()
    00150         ON_WM_CHAR()
    00151         ON_WM_NCDESTROY()
    00152         ON_CONTROL_REFLECT(CBN_CLOSEUP, OnCloseup)
    00153         //}}AFX_MSG_MAP
    00154 END_MESSAGE_MAP()
    00155
    00157 // CInPlaceComboBox message handlers
    00158
    00159 int CInPlaceComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
    00160 {
    00161         if (CComboBox::OnCreate(lpCreateStruct) == -1)
    00162                 return -1;
    00163
    00164         // Set the proper font
    00165         CFont* font = GetParent()->GetFont();
    00166         SetFont(font);
    00167
    00168         for(POSITION pos = m_lstItems.GetHeadPosition(); pos != NULL;)
    00169                 AddString((LPCTSTR)(m_lstItems.GetNext(pos)));
    00170
    00171         SetFocus();
    00172         SetCurSel(m_nSel);
    00173         return 0;
    00174 }
    00175
    00176 BOOL CInPlaceComboBox::PreTranslateMessage(MSG* pMsg)
    00177 {
    00178         if(pMsg->message == WM_KEYDOWN)
    00179         {
    00180                 if(pMsg->wParam == VK_RETURN
    00181                 || pMsg->wParam == VK_ESCAPE)
    00182                 {
    00183                         ::TranslateMessage(pMsg);
    00184                         ::DispatchMessage(pMsg);
    00185                         return TRUE;                            // DO NOT process further
    00186                 }
    00187         }
    00188
    00189         return CComboBox::PreTranslateMessage(pMsg);
    00190 }
    00191
    00192 void CInPlaceComboBox::OnKillFocus(CWnd* pNewWnd)
    00193 {
    00194         CComboBox::OnKillFocus(pNewWnd);
    00195
    00196         CString str;
    00197         GetWindowText(str);
    00198
    00199         LV_DISPINFO dispinfo;
    00200         dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
    00201         dispinfo.hdr.idFrom = GetDlgCtrlID();
    00202         dispinfo.hdr.code = LVN_ENDLABELEDIT;
    00203         dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM;
    00204         dispinfo.item.iItem = m_iItem;
    00205         dispinfo.item.iSubItem = m_iSubItem;
    00206         dispinfo.item.pszText = m_bESC ? NULL : LPTSTR((LPCTSTR)str);
    00207         dispinfo.item.cchTextMax = str.GetLength();
    00208         dispinfo.item.lParam = GetCurSel();
    00209         GetParent()->GetParent()->SendMessage(WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo);
    00210
    00211         PostMessage(WM_CLOSE);
    00212 }
    00213
    00214 void CInPlaceComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
    00215 {
    00216         if(nChar == VK_ESCAPE || nChar == VK_RETURN)
    00217         {
    00218                 if(nChar == VK_ESCAPE) m_bESC = TRUE;
    00219                 GetParent()->SetFocus();
    00220                 return;
    00221         }
    00222
    00223         CComboBox::OnChar(nChar, nRepCnt, nFlags);
    00224 }
    00225
    00226 void CInPlaceComboBox::OnNcDestroy()
    00227 {
    00228         CComboBox::OnNcDestroy();
    00229
    00230         delete this;
    00231 }
    00232
    00233 void CInPlaceComboBox::OnCloseup()
    00234 {
    00235         GetParent()->SetFocus();
    00236 }
    00237
    00238 // CInPlaceListBox
    00239
    00240 CInPlaceListBox::CInPlaceListBox(int iItem, int iSubItem, CList<CString>& lstItems, int nSel)
    00241 {
    00242         m_iItem = iItem;
    00243         m_iSubItem = iSubItem;
    00244
    00245         m_lstItems.AddTail(&lstItems);
    00246         m_nSel = nSel;
    00247         m_bESC = FALSE;
    00248 }
    00249
    00250 CInPlaceListBox::~CInPlaceListBox()
    00251 {
    00252 }
    00253
    00254 BEGIN_MESSAGE_MAP(CInPlaceListBox, CListBox)
    00255         //{{AFX_MSG_MAP(CInPlaceListBox)
    00256         ON_WM_CREATE()
    00257         ON_WM_KILLFOCUS()
    00258         ON_WM_CHAR()
    00259         ON_WM_NCDESTROY()
    00260         //}}AFX_MSG_MAP
    00261 END_MESSAGE_MAP()
    00262
    00264 // CInPlaceListBox message handlers
    00265
    00266 int CInPlaceListBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
    00267 {
    00268         if(CListBox::OnCreate(lpCreateStruct) == -1)
    00269                 return -1;
    00270
    00271         // Set the proper font
    00272         CFont* font = GetParent()->GetFont();
    00273         SetFont(font);
    00274
    00275         for(POSITION pos = m_lstItems.GetHeadPosition(); pos != NULL;)
    00276         {
    00277                 AddString( (LPCTSTR) (m_lstItems.GetNext( pos )) );
    00278         }
    00279         SetCurSel( m_nSel );
    00280         SetFocus();
    00281         return 0;
    00282 }
    00283
    00284 BOOL CInPlaceListBox::PreTranslateMessage(MSG* pMsg)
    00285 {
    00286         if(pMsg->message == WM_KEYDOWN)
    00287         {
    00288                 if(pMsg->wParam == VK_RETURN
    00289                 || pMsg->wParam == VK_ESCAPE)
    00290                 {
    00291                         ::TranslateMessage(pMsg);
    00292                         ::DispatchMessage(pMsg);
    00293                         return TRUE;                            // DO NOT process further
    00294                 }
    00295         }
    00296
    00297         return CListBox::PreTranslateMessage(pMsg);
    00298 }
    00299
    00300 void CInPlaceListBox::OnKillFocus(CWnd* pNewWnd)
    00301 {
    00302         CListBox::OnKillFocus(pNewWnd);
    00303
    00304         CString str;
    00305         GetWindowText(str);
    00306
    00307         LV_DISPINFO dispinfo;
    00308         dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
    00309         dispinfo.hdr.idFrom = GetDlgCtrlID();
    00310         dispinfo.hdr.code = LVN_ENDLABELEDIT;
    00311         dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM;
    00312         dispinfo.item.iItem = m_iItem;
    00313         dispinfo.item.iSubItem = m_iSubItem;
    00314         dispinfo.item.pszText = m_bESC ? NULL : LPTSTR((LPCTSTR)str);
    00315         dispinfo.item.cchTextMax = str.GetLength();
    00316         dispinfo.item.lParam = GetCurSel();
    00317         GetParent()->GetParent()->SendMessage(WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo);
    00318
    00319         PostMessage(WM_CLOSE);
    00320 }
    00321
    00322 void CInPlaceListBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
    00323 {
    00324         if(nChar == VK_ESCAPE || nChar == VK_RETURN)
    00325         {
    00326                 if(nChar == VK_ESCAPE) m_bESC = TRUE;
    00327                 GetParent()->SetFocus();
    00328                 return;
    00329         }
    00330
    00331         CListBox::OnChar(nChar, nRepCnt, nFlags);
    00332 }
    00333
    00334 void CInPlaceListBox::OnNcDestroy()
    00335 {
    00336         CListBox::OnNcDestroy();
    00337
    00338         delete this;
    00339 }
    00340
    00341
    00342
    00343 // CPlayerListCtrl
    00344
    00345 IMPLEMENT_DYNAMIC(CPlayerListCtrl, CListCtrl)
    00346 CPlayerListCtrl::CPlayerListCtrl(int tStartEditingDelay)
    00347         : m_tStartEditingDelay(tStartEditingDelay)
    00348         , m_nItemClicked(-1)
    00349 {
    00350 }
    00351
    00352 CPlayerListCtrl::~CPlayerListCtrl()
    00353 {
    00354 }
    00355
    00356 void CPlayerListCtrl::PreSubclassWindow()
    00357 {
    00358         EnableToolTips(TRUE);
    00359
    00360         CListCtrl::PreSubclassWindow();
    00361 }
    00362
    00363 int CPlayerListCtrl::HitTestEx(CPoint& point, int* col) const
    00364 {
    00365         if(col) *col = 0;
    00366
    00367         int row = HitTest(CPoint(0, point.y), NULL);
    00368
    00369         if((GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
    00370                 return row;
    00371
    00372         int nColumnCount = ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
    00373
    00374         for(int top = GetTopIndex(), bottom = GetBottomIndex(); top <= bottom; top++)
    00375         {
    00376                 CRect r;
    00377                 GetItemRect(top, &r, LVIR_BOUNDS);
    00378
    00379                 if(r.top <= point.y && point.y < r.bottom)
    00380                 {
    00381                         for(int colnum = 0; colnum < nColumnCount; colnum++)
    00382                         {
    00383                                 int colwidth = GetColumnWidth(colnum);
    00384
    00385                                 if(point.x >= r.left && point.x <= (r.left + colwidth))
    00386                                 {
    00387                                         if(col) *col = colnum;
    00388                                         return top;
    00389                                 }
    00390
    00391                                 r.left += colwidth;
    00392                         }
    00393                 }
    00394         }
    00395
    00396         return -1;
    00397 }
    00398
    00399 int CPlayerListCtrl::GetBottomIndex() const
    00400 {
    00401         CRect r;
    00402         GetClientRect(r);
    00403
    00404         int nBottomIndex = GetTopIndex() + GetCountPerPage() - 1;
    00405
    00406         if(nBottomIndex >= GetItemCount())
    00407         {
    00408                 nBottomIndex = GetItemCount() - 1;
    00409         }
    00410         else if(nBottomIndex < GetItemCount())
    00411         {
    00412                 CRect br;
    00413                 GetItemRect(nBottomIndex, br, LVIR_BOUNDS);
    00414
    00415                 if(br.bottom < r.bottom)
    00416                         nBottomIndex++;
    00417         }
    00418
    00419         return(nBottomIndex);
    00420 }
    00421
    00422 CImageList* CPlayerListCtrl::CreateDragImageEx(LPPOINT lpPoint)
    00423 {
    00424         if(GetSelectedCount() <= 0)
    00425                 return NULL;
    00426
    00427         CRect cSingleRect, cCompleteRect(0, 0, 0, 0);
    00428         GetClientRect(cSingleRect);
    00429         int nWidth = cSingleRect.Width();
    00430
    00431         // Start and Stop index in view area
    00432         int nIndex = GetTopIndex() - 1;
    00433         int nBottomIndex = GetBottomIndex();
    00434
    00435         // Determine the size of the drag image (limite for
    00436         // rows visibled and Client width)
    00437         while((nIndex = GetNextItem(nIndex, LVNI_SELECTED)) != -1 && nIndex <= nBottomIndex)
    00438         {
    00439                 GetItemRect(nIndex, cSingleRect, LVIR_BOUNDS);
    00440 /*
    00441                 CRect r;
    00442                 GetItemRect(nIndex, r, LVIR_LABEL);
    00443                 cSingleRect.left = r.left;
    00444 */
    00445                 if(cSingleRect.left < 0) cSingleRect.left = 0;
    00446                 if(cSingleRect.right > nWidth) cSingleRect.right = nWidth;
    00447
    00448                 cCompleteRect |= cSingleRect;
    00449         }
    00450
    00451         //
    00452         // Create bitmap in memory DC
    00453         //
    00454         CClientDC cDc(this);
    00455         CDC cMemDC;
    00456         CBitmap cBitmap;
    00457
    00458         if(!cMemDC.CreateCompatibleDC(&cDc))
    00459                 return NULL;
    00460
    00461         if(!cBitmap.CreateCompatibleBitmap(&cDc, cCompleteRect.Width(), cCompleteRect.Height()))
    00462                 return NULL;
    00463
    00464         CBitmap* pOldMemDCBitmap = cMemDC.SelectObject(&cBitmap);
    00465         // Here green is used as mask color
    00466         cMemDC.FillSolidRect(0, 0, cCompleteRect.Width(), cCompleteRect.Height(), RGB(0, 255, 0));
    00467
    00468         // Paint each DragImage in the DC
    00469         nIndex = GetTopIndex() - 1;
    00470         while((nIndex = GetNextItem(nIndex, LVNI_SELECTED)) != -1 && nIndex <= nBottomIndex)
    00471         {
    00472                 CPoint pt;
    00473                 CImageList* pSingleImageList = CreateDragImage(nIndex, &pt);
    00474
    00475                 if(pSingleImageList)
    00476                 {
    00477                         GetItemRect(nIndex, cSingleRect, LVIR_BOUNDS);
    00478
    00479                         pSingleImageList->Draw(&cMemDC,
    00480                                 0,
    00481                                 CPoint(cSingleRect.left - cCompleteRect.left, cSingleRect.top - cCompleteRect.top),
    00482                                 ILD_MASK);
    00483
    00484                         pSingleImageList->DeleteImageList();
    00485                         delete pSingleImageList;
    00486                 }
    00487         }
    00488
    00489         cMemDC.SelectObject(pOldMemDCBitmap);
    00490
    00491         //
    00492         // Create the imagelist with the merged drag images
    00493         //
    00494         CImageList* pCompleteImageList = new CImageList;
    00495
    00496         pCompleteImageList->Create(cCompleteRect.Width(),
    00497                                         cCompleteRect.Height(),
    00498                                         ILC_COLOR | ILC_MASK, 0, 1);
    00499
    00500         // Here green is used as mask color
    00501         pCompleteImageList->Add(&cBitmap, RGB(0, 255, 0));
    00502
    00503         //
    00504         // as an optional service:
    00505         // Find the offset of the current mouse cursor to the imagelist
    00506         // this we can use in BeginDrag()
    00507         //
    00508         if(lpPoint)
    00509         {
    00510                 lpPoint->x = cCompleteRect.left;
    00511                 lpPoint->y = cCompleteRect.top;
    00512         }
    00513
    00514         return(pCompleteImageList);
    00515 }
    00516
    00517 bool CPlayerListCtrl::PrepareInPlaceControl(int nRow, int nCol, CRect& rect)
    00518 {
    00519         if(!EnsureVisible(nRow, TRUE)) return(false);
    00520
    00521         int nColumnCount = ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
    00522         if(nCol >= nColumnCount || GetColumnWidth(nCol) < 5) return(false);
    00523
    00524         int offset = 0;
    00525         for(int i = 0; i < nCol; i++) offset += GetColumnWidth(i);
    00526
    00527         GetItemRect(nRow, &rect, LVIR_BOUNDS);
    00528
    00529         CRect rcClient;
    00530         GetClientRect(&rcClient);
    00531         if(offset + rect.left < 0 || offset + rect.left > rcClient.right)
    00532         {
    00533                 CSize size(offset + rect.left, 0);
    00534                 Scroll(size);
    00535                 rect.left -= size.cx;
    00536         }
    00537
    00538         rect.left += offset;
    00539         rect.right = rect.left + GetColumnWidth(nCol);
    00540         if(rect.right > rcClient.right) rect.right = rcClient.right;
    00541
    00542         rect.DeflateRect(1, 0, 0, 1);
    00543
    00544         if(nCol == 0)
    00545         {
    00546                 CRect r;
    00547                 GetItemRect(nRow, r, LVIR_LABEL);
    00548                 rect.left = r.left-1;
    00549         }
    00550
    00551         return(true);
    00552 }
    00553
    00554 CEdit* CPlayerListCtrl::ShowInPlaceEdit(int nItem, int nCol)
    00555 {
    00556         CRect rect;
    00557         if(!PrepareInPlaceControl(nItem, nCol, rect))
    00558                 return(NULL);
    00559
    00560         DWORD dwStyle = /*WS_BORDER|*/WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL;
    00561
    00562         LV_COLUMN lvcol;
    00563         lvcol.mask = LVCF_FMT;
    00564         GetColumn(nCol, &lvcol);
    00565         dwStyle |= (lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT ? ES_LEFT
    00566                 : (lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT ? ES_RIGHT
    00567                 : ES_CENTER;
    00568
    00569         CEdit* pEdit = new CInPlaceEdit(nItem, nCol, GetItemText(nItem, nCol));
    00570         pEdit->Create(dwStyle, rect, this, IDC_EDIT1);
    00571
    00572         m_fInPlaceDirty = false;
    00573
    00574         return pEdit;
    00575 }
    00576
    00577 CComboBox* CPlayerListCtrl::ShowInPlaceComboBox(int nItem, int nCol, CList<CString>& lstItems, int nSel)
    00578 {
    00579         CRect rect;
    00580         if(!PrepareInPlaceControl(nItem, nCol, rect))
    00581                 return(NULL);
    00582
    00583         DWORD dwStyle = /*WS_BORDER|*/WS_CHILD|WS_VISIBLE|WS_VSCROLL/*|WS_HSCROLL*/
    00584                 |CBS_DROPDOWNLIST|CBS_DISABLENOSCROLL/*|CBS_NOINTEGRALHEIGHT*/;
    00585         CComboBox* pComboBox = new CInPlaceComboBox(nItem, nCol, lstItems, nSel);
    00586         pComboBox->Create(dwStyle, rect, this, IDC_COMBO1);
    00587
    00588         CorrectComboListWidth(*pComboBox, GetFont());
    00589
    00590         int width = GetColumnWidth(nCol);
    00591         if(pComboBox->GetDroppedWidth() < width)
    00592                 pComboBox->SetDroppedWidth(width);
    00593
    00594         m_fInPlaceDirty = false;
    00595
    00596         return pComboBox;
    00597 }
    00598
    00599 CListBox* CPlayerListCtrl::ShowInPlaceListBox(int nItem, int nCol, CList<CString>& lstItems, int nSel)
    00600 {
    00601         CRect rect;
    00602         if(!PrepareInPlaceControl(nItem, nCol, rect))
    00603                 return(NULL);
    00604
    00605         DWORD dwStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL/*|WS_HSCROLL*/|LBS_NOTIFY;
    00606         CListBox* pListBox = new CInPlaceListBox(nItem, nCol, lstItems, nSel);
    00607         pListBox->Create(dwStyle, rect, this, IDC_LIST1);
    00608
    00609         CRect ir;
    00610         GetItemRect(m_nItemClicked, &ir, LVIR_BOUNDS);
    00611
    00612         pListBox->SetItemHeight(-1, ir.Height());
    00613
    00614         CDC* pDC = pListBox->GetDC();
    00615         CFont* pWndFont = GetFont();
    00616         pDC->SelectObject(pWndFont);
    00617         int width = GetColumnWidth(nCol);
    00618         POSITION pos = lstItems.GetHeadPosition();
    00619         while(pos)
    00620         {
    00621                 int w = pDC->GetTextExtent(lstItems.GetNext(pos)).cx + 16;
    00622                 if(width < w) width = w;
    00623         }
    00624         ReleaseDC(pDC);
    00625
    00626         CRect r;
    00627         pListBox->GetWindowRect(r);
    00628         ScreenToClient(r);
    00629         r.top = ir.bottom;
    00630         r.bottom = r.top + pListBox->GetItemHeight(0) * (pListBox->GetCount() + 1);
    00631         r.right = r.left + width;
    00632         pListBox->MoveWindow(r);
    00633
    00634         m_fInPlaceDirty = false;
    00635
    00636         return pListBox;
    00637 }
    00638
    00639 BEGIN_MESSAGE_MAP(CPlayerListCtrl, CListCtrl)
    00640         ON_WM_VSCROLL()
    00641         ON_WM_HSCROLL()
    00642         ON_WM_MOUSEWHEEL()
    00643         ON_WM_LBUTTONDOWN()
    00644         ON_WM_TIMER()
    00645         ON_WM_LBUTTONDBLCLK()
    00646         ON_NOTIFY_REFLECT(LVN_MARQUEEBEGIN, OnLvnMarqueeBegin)
    00647         ON_NOTIFY_REFLECT(LVN_INSERTITEM, OnLvnInsertitem)
    00648         ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnLvnDeleteitem)
    00649         ON_EN_CHANGE(IDC_EDIT1, OnEnChangeEdit1)
    00650         ON_CBN_DROPDOWN(IDC_COMBO1, OnCbnDropdownCombo1)
    00651         ON_CBN_SELENDOK(IDC_COMBO1, OnCbnSelendokCombo1)
    00652         ON_LBN_SELCHANGE(IDC_LIST1, OnLbnSelChangeList1)
    00653         ON_NOTIFY_EX(HDN_ITEMCHANGINGA, 0, OnHdnItemchanging)
    00654         ON_NOTIFY_EX(HDN_ITEMCHANGINGW, 0, OnHdnItemchanging)
    00655         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
    00656         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
    00657 END_MESSAGE_MAP()
    00658
    00659 // CPlayerListCtrl message handlers
    00660
    00661 void CPlayerListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
    00662 {
    00663         if(GetFocus() != this) SetFocus();
    00664         CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
    00665 }
    00666
    00667 void CPlayerListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
    00668 {
    00669         if(GetFocus() != this) SetFocus();
    00670         CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
    00671 }
    00672
    00673 BOOL CPlayerListCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
    00674 {
    00675         if(GetFocus() != this) SetFocus();
    00676         return CListCtrl::OnMouseWheel(nFlags, zDelta, pt);
    00677 }
    00678
    00679 void CPlayerListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
    00680 {
    00681         CListCtrl::OnLButtonDown(nFlags, point);
    00682
    00683         if(GetFocus() != this) SetFocus();
    00684
    00685         KillTimer(1);
    00686
    00687         int m_nItemClickedNow, m_nSubItemClickedNow;
    00688
    00689         if((m_nItemClickedNow = HitTestEx(point, &m_nSubItemClickedNow)) < 0)
    00690         {
    00691                 m_nItemClicked = -1;
    00692         }
    00693         else if(m_nItemClicked == m_nItemClickedNow /*&& m_nSubItemClicked == m_nSubItemClickedNow*/)
    00694         {
    00695                 m_nSubItemClicked = m_nSubItemClickedNow;
    00696
    00697                 LV_DISPINFO dispinfo;
    00698                 dispinfo.hdr.hwndFrom = m_hWnd;
    00699                 dispinfo.hdr.idFrom = GetDlgCtrlID();
    00700                 dispinfo.hdr.code = LVN_BEGINLABELEDIT;
    00701                 dispinfo.item.mask = 0;
    00702                 dispinfo.item.iItem = m_nItemClicked;
    00703                 dispinfo.item.iSubItem = m_nSubItemClicked;
    00704                 if(GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo))
    00705                 {
    00706                         if(m_tStartEditingDelay > 0)
    00707                         {
    00708                                 SetTimer(1, m_tStartEditingDelay, NULL);
    00709                         }
    00710                         else
    00711                         {
    00712                                 dispinfo.hdr.code = LVN_DOLABELEDIT;
    00713                                 GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo);
    00714                         }
    00715                 }
    00716         }
    00717         else
    00718         {
    00719                 m_nItemClicked = m_nItemClickedNow;
    00720                 m_nSubItemClicked = m_nSubItemClickedNow;
    00721
    00722                 SetItemState(m_nItemClicked, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
    00723         }
    00724 }
    00725
    00726 void CPlayerListCtrl::OnTimer(UINT nIDEvent)
    00727 {
    00728         if(nIDEvent == 1)
    00729         {
    00730                 KillTimer(1);
    00731
    00732                 UINT flag = LVIS_FOCUSED;
    00733                 if((GetItemState(m_nItemClicked, flag) & flag) == flag && m_nSubItemClicked >= 0)
    00734                 {
    00735                         LV_DISPINFO dispinfo;
    00736                         dispinfo.hdr.hwndFrom = m_hWnd;
    00737                         dispinfo.hdr.idFrom = GetDlgCtrlID();
    00738                         dispinfo.hdr.code = LVN_DOLABELEDIT;
    00739                         dispinfo.item.mask = 0;
    00740                         dispinfo.item.iItem = m_nItemClicked;
    00741                         dispinfo.item.iSubItem = m_nSubItemClicked;
    00742                         GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo);
    00743                 }
    00744         }
    00745
    00746         CListCtrl::OnTimer(nIDEvent);
    00747 }
    00748
    00749 void CPlayerListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
    00750 {
    00751         KillTimer(1);
    00752
    00753         CListCtrl::OnLButtonDblClk(nFlags, point);
    00754 }
    00755
    00756 void CPlayerListCtrl::OnLvnMarqueeBegin(NMHDR* pNMHDR, LRESULT* pResult)
    00757 {
    00758         LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    00759         *pResult = 1;
    00760 }
    00761
    00762 void CPlayerListCtrl::OnLvnInsertitem(NMHDR* pNMHDR, LRESULT* pResult)
    00763 {
    00764         LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    00765         m_nItemClicked = -1;
    00766         *pResult = 0;
    00767 }
    00768
    00769 void CPlayerListCtrl::OnLvnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult)
    00770 {
    00771         LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    00772         m_nItemClicked = -1;
    00773         *pResult = 0;
    00774 }
    00775
    00776 void CPlayerListCtrl::OnEnChangeEdit1()
    00777 {
    00778         m_fInPlaceDirty = true;
    00779 }
    00780
    00781 void CPlayerListCtrl::OnCbnDropdownCombo1()
    00782 {
    00783         CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_COMBO1);
    00784
    00785         CRect ir;
    00786         GetItemRect(m_nItemClicked, &ir, LVIR_BOUNDS);
    00787
    00788         CRect r;
    00789         pCombo->GetWindowRect(r);
    00790         ScreenToClient(r);
    00791         r.bottom = r.top + ir.Height() + pCombo->GetItemHeight(0)*10;
    00792         pCombo->MoveWindow(r);
    00793 }
    00794
    00795 void CPlayerListCtrl::OnCbnSelendokCombo1()
    00796 {
    00797         m_fInPlaceDirty = true;
    00798 }
    00799
    00800 void CPlayerListCtrl::OnLbnSelChangeList1()
    00801 {
    00802         m_fInPlaceDirty = true;
    00803         SetFocus();
    00804 }
    00805
    00806 BOOL CPlayerListCtrl::OnHdnItemchanging(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
    00807 {
    00808         LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
    00809 //      SetFocus();
    00810         *pResult = 0;
    00811         return FALSE;
    00812 }
    00813
    00814 int CPlayerListCtrl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
    00815 {
    00816         int col;
    00817         int row = HitTestEx(point, &col);
    00818         if(row == -1)
    00819                 return -1;
    00820
    00821         CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
    00822         int nColumnCount = pHeader->GetItemCount();
    00823
    00824         CRect rect;
    00825         GetItemRect(row, &rect, LVIR_BOUNDS);
    00826
    00827         for(int colnum = 0; colnum < nColumnCount; colnum++)
    00828         {
    00829                 int colwidth = GetColumnWidth(colnum);
    00830
    00831                 if(colnum == col)
    00832                 {
    00833                         rect.right = rect.left + colwidth; break;
    00834                 }
    00835
    00836                 rect.left += colwidth;
    00837         }
    00838
    00839         pTI->hwnd = m_hWnd;
    00840         pTI->uId = (UINT)((row<<10)+(col&0x3ff)+1);
    00841         pTI->lpszText = LPSTR_TEXTCALLBACK;
    00842         pTI->rect = rect;
    00843
    00844         return pTI->uId;
    00845 }
    00846
    00847 BOOL CPlayerListCtrl::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
    00848 {
    00849         TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
    00850         TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
    00851
    00852         UINT nID = pNMHDR->idFrom;
    00853
    00854         if(pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND)
    00855         || pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
    00856         {
    00857                 // idFrom is actually the HWND of the tool
    00858                 nID = ::GetDlgCtrlID((HWND)nID);
    00859         }
    00860
    00861         if(nID == 0)            // Notification in NT from automatically
    00862                 return FALSE;           // created tooltip
    00863
    00864         if(pNMHDR->code == TTN_NEEDTEXTA) pTTTA->lParam = (LPARAM)m_hWnd;
    00865         else if(pNMHDR->code == TTN_NEEDTEXTW) pTTTW->lParam = (LPARAM)m_hWnd;
    00866
    00867         *pResult = 0;
    00868
    00869         return GetParent()->SendMessage(WM_NOTIFY, id, (LPARAM)pNMHDR);
    00870 }
    00871