00001
00002
00003
00004
00005
00006 #include "stdafx.h"
00007 #include "FdmApp.h"
00008 #include "ListCtrlEx.h"
00009
00010 #ifdef _DEBUG
00011 #define new DEBUG_NEW
00012 #undef THIS_FILE
00013 static char THIS_FILE[] = __FILE__;
00014 #endif
00015
00016 CListCtrlEx::CListCtrlEx()
00017 {
00018 UseGrid ();
00019 m_clrGrid = GetSysColor (COLOR_3DFACE);
00020 m_pSelImages = NULL;
00021 ZeroMemory (m_appszCols, sizeof (m_appszCols));
00022 m_sortMode = LCSM_NONE;
00023 m_iSortCol = -1;
00024 m_sortModeSupport = LCSM_ALL_SUPPORTED;
00025 m_cTotalCols = 0;
00026 }
00027
00028 CListCtrlEx::~CListCtrlEx()
00029 {
00030 }
00031
00032 BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
00033
00034 ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
00035 ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
00036 ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnDeleteitem)
00037 ON_NOTIFY_REFLECT(LVN_DELETEALLITEMS, OnDeleteallitems)
00038 ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
00039 ON_WM_PARENTNOTIFY()
00040 ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
00041 ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemchanged)
00042
00043 ON_COMMAND_RANGE (1, LISTEX_MAXCOLUMNS, OnShowCol)
00044 END_MESSAGE_MAP()
00045
00046 BOOL RGBIsEqual (COLORREF clr1, COLORREF clr2)
00047 {
00048 return abs (GetRValue (clr1) - GetRValue (clr2)) < 10 &&
00049 abs (GetGValue (clr1) - GetGValue (clr2)) < 10 &&
00050 abs (GetBValue (clr1) - GetBValue (clr2)) < 10;
00051 }
00052
00053 void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDraw)
00054 {try{
00055 int cCols = GetHeaderCtrl ()->GetItemCount ();
00056 CDC *dc = CDC::FromHandle (lpDraw->hDC);
00057 int xStart = lpDraw->rcItem.left;
00058 CImageList *pImages = GetImageList (LVSIL_SMALL);
00059 BOOL bNeedBorder = FALSE;
00060
00061 CHeaderCtrl* pHdr = GetHeaderCtrl ();
00062
00063 for (int i = 0; i < cCols; i++)
00064 {
00065 LVITEM item;
00066 TCHAR szItem [10000];
00067 int colWidth = GetColumnWidth (pHdr->OrderToIndex (i));
00068
00069 xStart += 5;
00070 colWidth -= 5;
00071
00072 item.iItem = lpDraw->itemID;
00073 item.iSubItem = i;
00074 item.pszText = szItem;
00075 item.cchTextMax = sizeof (szItem);
00076 item.mask = LVIF_IMAGE | LVIF_TEXT;
00077
00078 GetItem (&item);
00079
00080 if (i == 0)
00081 {
00082 item.state = GetItemState (lpDraw->itemID, LVIS_SELECTED|LVIS_FOCUSED);
00083
00084 COLORREF clrBg = m_vInfo [lpDraw->itemID].clrBg;
00085 COLORREF clrText = m_vInfo [lpDraw->itemID].clrText;
00086
00087 if (item.state & LVIS_FOCUSED)
00088 bNeedBorder = TRUE;
00089
00090 if (item.state & LVIS_SELECTED)
00091 {
00092 clrBg = GetSysColor (COLOR_HIGHLIGHT);
00093 clrText = GetSysColor (COLOR_HIGHLIGHTTEXT);
00094 if (bNeedBorder == FALSE)
00095 {
00096 if (GetSelectionMark () == (int)lpDraw->itemID)
00097 bNeedBorder = TRUE;
00098 }
00099 }
00100
00101 CBrush br;
00102 CPen pen;
00103 CBrush *oldBr;
00104 CPen *oldPen;
00105
00106 if (RGBIsEqual (clrBg, clrText))
00107 clrText = (~clrText) & 0x00FFFFFF;
00108
00109 dc->SetTextColor (clrText);
00110
00111 br.CreateSolidBrush (clrBg);
00112 pen.CreatePen (PS_SOLID, 1, clrBg);
00113
00114 oldBr = dc->SelectObject (&br);
00115 oldPen = dc->SelectObject (&pen);
00116
00117 dc->Rectangle (&lpDraw->rcItem);
00118
00119 if (m_bGrid)
00120 {
00121 CPen pen1 (PS_SOLID, 1, m_clrGrid);
00122 dc->SelectObject (&pen1);
00123 dc->MoveTo (lpDraw->rcItem.left, lpDraw->rcItem.bottom-1);
00124 dc->LineTo (lpDraw->rcItem.right, lpDraw->rcItem.bottom-1);
00125 dc->SelectObject (oldPen);
00126 }
00127
00128 dc->SelectObject (oldBr);
00129 dc->SelectObject (oldPen);
00130
00131 if (pImages)
00132 {
00133 CPoint pt;
00134 pt.x = xStart;
00135 pt.y = lpDraw->rcItem.top;
00136 if (m_pSelImages && (item.state & LVIS_SELECTED))
00137 m_pSelImages->Draw (dc, item.iImage, pt, ILD_TRANSPARENT);
00138 else
00139 pImages->Draw (dc, item.iImage, pt, ILD_TRANSPARENT);
00140
00141 IMAGEINFO inf;
00142 pImages->GetImageInfo (item.iImage, &inf);
00143
00144 xStart += inf.rcImage.right - inf.rcImage.left + 5;
00145 colWidth -= inf.rcImage.right - inf.rcImage.left + 5;
00146 }
00147 }
00148
00149 if (*item.pszText)
00150 {
00151 int needX = GetStringWidth (item.pszText);
00152 BOOL bDrawText = TRUE;
00153
00154 RECT rcText = lpDraw->rcItem;
00155 rcText.left = xStart;
00156 rcText.right = xStart + colWidth - 5;
00157
00158 if (needX > colWidth-5)
00159 {
00160 RECT rc = rcText;
00161 int dx = GetStringWidth ("...");
00162 if (dx <= colWidth-5)
00163 {
00164 rc.left = rc.right - dx;
00165 dc->DrawText ("...", &rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
00166 rcText.right = rc.left - 5;
00167 }
00168 else
00169 bDrawText = FALSE;
00170 }
00171
00172 if (bDrawText)
00173 dc->DrawText (szItem, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_NOPREFIX);
00174 }
00175
00176 xStart += colWidth;
00177
00178 if (m_bGrid)
00179 {
00180
00181 CPen pen (PS_SOLID, 1, m_clrGrid);
00182 CPen *oldPen = dc->SelectObject (&pen);
00183 dc->MoveTo (xStart-1, lpDraw->rcItem.top);
00184 dc->LineTo (xStart-1, lpDraw->rcItem.bottom);
00185 dc->SelectObject (oldPen);
00186 }
00187 }
00188
00189 if (bNeedBorder)
00190 {
00191 dc->SetTextColor (m_vInfo [lpDraw->itemID].clrText);
00192 RECT rc = lpDraw->rcItem;
00193 rc.bottom--; rc.right--;
00194 dc->DrawFocusRect (&rc);
00195 }
00196
00197 }catch (...){}
00198 }
00199
00200 void CListCtrlEx::OnClick(NMHDR* , LRESULT* pResult)
00201 {
00202 OnClick ();
00203 *pResult = 0;
00204 }
00205
00206 void CListCtrlEx::OnClick()
00207 {
00208
00209 }
00210
00211 void CListCtrlEx::OnRclick(NMHDR* nm, LRESULT* pResult)
00212 {
00213 if (nm->hwndFrom == m_hWnd)
00214 OnRClick ();
00215
00216 *pResult = 0;
00217 }
00218
00219 void CListCtrlEx::OnRClick()
00220 {
00221
00222 }
00223
00224 void CListCtrlEx::OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult)
00225 {
00226 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
00227
00228 m_vInfo.erase (m_vInfo.begin () + pNMListView->iItem);
00229
00230 OnDeleteItem (pNMListView);
00231
00232 *pResult = 0;
00233 }
00234
00235 void CListCtrlEx::OnDeleteallitems(NMHDR* , LRESULT* pResult)
00236 {
00237 OnDeleteAllItems ();
00238
00239 *pResult = 0;
00240 }
00241
00242 void CListCtrlEx::OnDeleteItem(NM_LISTVIEW* )
00243 {
00244
00245 }
00246
00247 void CListCtrlEx::OnDeleteAllItems()
00248 {
00249
00250 }
00251
00252 int CListCtrlEx::AddItem(LPCSTR pszItem, COLORREF clrBg, COLORREF clrText, int iImage, BOOL bAddToBeginning)
00253 {
00254 int c = bAddToBeginning ? 0 : GetItemCount ();
00255
00256 ListEx_ItemInfo info;
00257 info.clrBg = clrBg;
00258 info.clrText = clrText;
00259 if (bAddToBeginning)
00260 m_vInfo.insert (m_vInfo.begin (), info);
00261 else
00262 m_vInfo.push_back (info);
00263
00264 c = InsertItem (c, "", iImage);
00265 if (*pszItem)
00266 SetItemText (c, 0, pszItem);
00267
00268 return c;
00269 }
00270
00271 void CListCtrlEx::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
00272 {
00273 LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
00274
00275 OnKeyDown (pLVKeyDow->wVKey);
00276
00277 *pResult = 0;
00278 }
00279
00280 void CListCtrlEx::OnKeyDown(WORD )
00281 {
00282
00283 }
00284
00285 int CListCtrlEx::GetItemImage(int iItem)
00286 {
00287 LVITEM item;
00288
00289 item.iItem = iItem;
00290 item.iSubItem = 0;
00291 item.mask = LVIF_IMAGE;
00292 GetItem (&item);
00293
00294 return item.iImage;
00295 }
00296
00297 void CListCtrlEx::SetItemImage(int iItem, int iImage)
00298 {
00299 LVITEM item;
00300
00301 item.iItem = iItem;
00302 item.iSubItem = 0;
00303 item.mask = LVIF_IMAGE;
00304 item.iImage = iImage;
00305 SetItem (&item);
00306
00307 CRect rc;
00308 GetItemRect (iItem, &rc, LVIR_BOUNDS);
00309 InvalidateRect (&rc);
00310 }
00311
00312 void CListCtrlEx::OnForceUpdate()
00313 {
00314
00315 }
00316
00317 BOOL CListCtrlEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
00318 {
00319 LPNMHDR nm = (LPNMHDR) lParam;
00320
00321 if (nm->code == NM_RELEASEDCAPTURE)
00322 {
00323 RebuildAIndex ();
00324 OnForceUpdate ();
00325 return TRUE;
00326 }
00327
00328 return CListCtrl::OnNotify(wParam, lParam, pResult);
00329 }
00330
00331 void CListCtrlEx::UseGrid(BOOL bUse)
00332 {
00333 m_bGrid = bUse;
00334 }
00335
00336 void CListCtrlEx::SaveState(LPCSTR pszName)
00337 {
00338 int *piWidthes;
00339 fsnew (piWidthes, int, m_cTotalCols);
00340
00341 int aOrder [LISTEX_MAXCOLUMNS];
00342 GetColumnOrderArray ((int*) aOrder, GetHeaderCtrl ()->GetItemCount ());
00343
00344 for (int i = 0; i < m_cTotalCols; i++)
00345 if (m_aIndex [i] != -1)
00346 piWidthes [i] = GetColumnWidth (aOrder [m_aIndex [i]]);
00347 else
00348 piWidthes [i] = -1;
00349
00350 CString strIndexes = pszName, strWidthes = pszName;
00351 strIndexes += 'I';
00352 strWidthes += 'W';
00353
00354 _App.get_SettingsStore ()->WriteProfileBinary (_T ("Settings\\View\\ListViews"), strIndexes, (LPBYTE)m_aIndex, m_cTotalCols * sizeof (int));
00355 _App.get_SettingsStore ()->WriteProfileBinary (_T ("Settings\\View\\ListViews"), strWidthes, (LPBYTE)piWidthes, m_cTotalCols * sizeof (int));
00356
00357 delete [] piWidthes;
00358 }
00359
00360 void CListCtrlEx::ReadState(LPCSTR pszName)
00361 {
00362 CHeaderCtrl* pHdr = GetHeaderCtrl ();
00363 int *piWidthes;
00364
00365 Initialize ();
00366
00367 LPBYTE pbW, pbI;
00368 UINT uSizeI, uSizeW;
00369
00370 CString strIndexes = pszName, strWidthes = pszName;
00371 strIndexes += 'I';
00372 strWidthes += 'W';
00373
00374 if (_App.get_SettingsStore ()->GetProfileBinary (_T ("Settings\\View\\ListViews"), strIndexes, &pbI, &uSizeI) &&
00375 _App.get_SettingsStore ()->GetProfileBinary (_T ("Settings\\View\\ListViews"), strWidthes, &pbW, &uSizeW) &&
00376 uSizeI == m_cTotalCols * sizeof (int) && uSizeW == m_cTotalCols * sizeof (int))
00377 {
00378 CopyMemory (m_aIndex, pbI, m_cTotalCols * sizeof (int));
00379 piWidthes = (int*) pbW;
00380
00381 for (int i = m_cTotalCols - 1; i >= 0; i--)
00382 if (m_aIndex [i] == -1)
00383 DeleteColumn (i);
00384
00385 int aOrder [LISTEX_MAXCOLUMNS];
00386 int iCorr = 0;
00387
00388 for (i = 0; i < m_cTotalCols; i++)
00389 {
00390 if (m_aIndex [i] != -1)
00391 aOrder [m_aIndex [i]] = i - iCorr;
00392 else
00393 iCorr ++;
00394 }
00395
00396 pHdr->SetOrderArray (GetHeaderCtrl ()->GetItemCount (), (int*) aOrder);
00397
00398 RebuildAIndex ();
00399
00400 for (i = 0; i < m_cTotalCols; i++)
00401 {
00402 if (piWidthes [i] > 0)
00403 SetColumnWidth (aOrder [m_aIndex [i]], piWidthes [i]);
00404 }
00405
00406 delete [] pbW;
00407 delete [] pbI;
00408 }
00409 }
00410
00411 void CListCtrlEx::SetItemColor(int iItem, COLORREF clr, BOOL bUpdate)
00412 {
00413 m_vInfo [iItem].clrText = clr;
00414 if (bUpdate)
00415 Update (iItem);
00416 }
00417
00418 void CListCtrlEx::SetSelectedImages(CImageList *pImages)
00419 {
00420 m_pSelImages = pImages;
00421 }
00422
00423 void CListCtrlEx::DeleteHdrItem(int iItem)
00424 {
00425 int aOrder [LISTEX_MAXCOLUMNS];
00426 GetColumnOrderArray ((int*) aOrder, GetHeaderCtrl ()->GetItemCount ());
00427 int iCol = aOrder [m_aIndex [iItem]];
00428 DeleteColumn (iCol);
00429 RebuildAIndex ();
00430 OnForceUpdate ();
00431 }
00432
00433 void CListCtrlEx::OnParentNotify(UINT message, LPARAM lParam)
00434 {
00435
00436 if (LOWORD (message) == WM_RBUTTONDOWN)
00437 {
00438 CMenu menu, m;
00439 menu.CreateMenu ();
00440 m.CreateMenu ();
00441 m.AppendMenu (MF_POPUP, (UINT) menu.m_hMenu, "-");
00442
00443 int cCols = GetHeaderCtrl ()->GetItemCount ();
00444
00445 for (int i = 0; i < m_cTotalCols; i++)
00446 {
00447 UINT state = 0;
00448 if (m_aIndex [i] != -1)
00449 {
00450 state = MF_CHECKED;
00451 if (cCols == 1)
00452
00453 state |= MF_GRAYED;
00454 }
00455
00456 menu.AppendMenu (MF_STRING | state, i+1, m_appszCols [i]);
00457 }
00458
00459 CPoint pt (LOWORD (lParam), HIWORD (lParam));
00460 ClientToScreen (&pt);
00461 menu.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_LEFTALIGN, pt.x, pt.y, this);
00462 menu.DestroyMenu ();
00463 }
00464 else
00465 CListCtrl::OnParentNotify(message, lParam);
00466 }
00467
00468 void CListCtrlEx::RebuildAIndex()
00469 {
00470 int cCols = GetHeaderCtrl ()->GetItemCount ();
00471
00472 for (int i = 0; i < m_cTotalCols; i++)
00473 m_aIndex [i] = -1;
00474
00475 int aOrder [LISTEX_MAXCOLUMNS];
00476 GetColumnOrderArray ((int*) aOrder, cCols);
00477
00478 HDITEM item;
00479 item.mask = HDI_LPARAM;
00480 for (i = 0; i < cCols; i++)
00481 {
00482 GetHeaderCtrl ()->GetItem (aOrder [i], &item);
00483
00484 m_aIndex [item.lParam] = i;
00485 }
00486 }
00487
00488 void CListCtrlEx::Initialize()
00489 {
00490 m_cTotalCols = GetHeaderCtrl ()->GetItemCount ();
00491
00492 HDITEM item;
00493 item.mask = HDI_LPARAM;
00494 for (int i = 0; i < m_cTotalCols; i++)
00495 {
00496 item.lParam = i;
00497
00498 GetHeaderCtrl ()->SetItem (i, &item);
00499 }
00500
00501 RebuildAIndex ();
00502 }
00503
00504 void CListCtrlEx::SetColumnText(int iCol, LPCSTR pszText)
00505 {
00506 m_appszCols [iCol] = pszText;
00507
00508 if (m_aIndex [iCol] == -1)
00509 return;
00510
00511 int aOrder [LISTEX_MAXCOLUMNS];
00512 GetColumnOrderArray ((int*) aOrder, GetHeaderCtrl ()->GetItemCount ());
00513
00514 iCol = aOrder [m_aIndex [iCol]];
00515
00516 HDITEM item;
00517 item.mask = HDI_TEXT;
00518 item.pszText = (LPSTR) pszText;
00519 GetHeaderCtrl ()->SetItem (iCol, &item);
00520 }
00521
00522 void CListCtrlEx::OnShowCol(UINT uCmd)
00523 {
00524 int iCol = uCmd - 1;
00525 ChangeColumnVisibility (iCol);
00526 }
00527
00528 void CListCtrlEx::InsertHdrItem(int iCol)
00529 {
00530 int cCols = GetHeaderCtrl ()->GetItemCount ();
00531 InsertColumn (cCols, m_appszCols [iCol], LVCFMT_LEFT, 80);
00532 HDITEM item;
00533 item.mask = HDI_LPARAM;
00534 item.lParam = iCol;
00535 GetHeaderCtrl ()->SetItem (cCols, &item);
00536 RebuildAIndex ();
00537 OnForceUpdate ();
00538 }
00539
00540 void CListCtrlEx::SetItemText(int iItem, int iSubItem, LPCSTR pszText)
00541 {
00542 if (m_aIndex [iSubItem] != -1)
00543 CListCtrl::SetItemText (iItem, m_aIndex [iSubItem], pszText);
00544 }
00545
00546 BOOL CListCtrlEx::IsColumnShown(int iCol)
00547 {
00548 return m_aIndex [iCol] != -1;
00549 }
00550
00551 void CListCtrlEx::ChangeColumnVisibility(int iColumn)
00552 {
00553 if (m_aIndex [iColumn] == -1)
00554 InsertHdrItem (iColumn);
00555 else
00556 DeleteHdrItem (iColumn);
00557 }
00558
00559 void CListCtrlEx::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
00560 {
00561 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
00562
00563 if (m_sortMode != LCSM_NONE && m_iSortCol == pNMListView->iSubItem)
00564 {
00565 if (m_sortMode == LCSM_ASCENDING)
00566 m_sortMode = LCSM_DESCENDING;
00567 else if (m_sortMode == LCSM_DESCENDING)
00568 m_sortMode = LCSM_ASCENDING;
00569 else
00570 m_sortMode = LCSM_NONE;
00571
00572 if (m_sortMode == LCSM_DESCENDING &&
00573 (m_sortModeSupport & LCSM_DESCENDING_NOTSUPPORTED))
00574 m_sortMode = LCSM_NONE;
00575 }
00576 else
00577 {
00578 m_iSortCol = SubItemToSubItem(pNMListView->iSubItem);
00579 if (m_sortMode == LCSM_NONE)
00580 m_sortMode = m_sortModeSupport & LCSM_ASCENDING_NOTSUPPORTED ? LCSM_DESCENDING : LCSM_ASCENDING;
00581 }
00582
00583 OnSortModeChanged ();
00584
00585 *pResult = 0;
00586 }
00587
00588 void CListCtrlEx::OnSortModeChanged()
00589 {
00590
00591 }
00592
00593 void CListCtrlEx::InitSortImages()
00594 {
00595 m_imgsSort.Create (10, 10, ILC_COLOR24 | ILC_MASK, 3, 1);
00596 CBitmap bmp;
00597 bmp.Attach (SBMP (IDB_SORTIMAGES));
00598 m_imgsSort.Add (&bmp, RGB (255, 0, 255));
00599 GetHeaderCtrl ()->SetImageList (&m_imgsSort);
00600 }
00601
00602 void CListCtrlEx::VirtualView_ItemWillBeAdded(COLORREF clrBg, COLORREF clrText, BOOL bAddToBeginning)
00603 {
00604 ListEx_ItemInfo info;
00605 info.clrBg = clrBg;
00606 info.clrText = clrText;
00607 if (bAddToBeginning)
00608 m_vInfo.insert (m_vInfo.begin (), info);
00609 else
00610 m_vInfo.push_back (info);
00611 }
00612
00613 void CListCtrlEx::VirtualView_ItemWillBeDeleted(int nItem)
00614 {
00615 m_vInfo.erase (m_vInfo.begin () + nItem);
00616 }
00617
00618 void CListCtrlEx::VirtualView_AllItemsWillBeDeleted()
00619 {
00620 m_vInfo.clear ();
00621 }
00622
00623 void CListCtrlEx::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult)
00624 {
00625 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
00626 OnItemChanged (pNMListView);
00627 *pResult = 0;
00628 }
00629
00630 void CListCtrlEx::OnItemChanged(NM_LISTVIEW*)
00631 {
00632
00633 }
00634
00635 int CListCtrlEx::SubItemToSubItem(int nSubItem)
00636 {
00637 for (int i = 0; i < m_cTotalCols; i++)
00638 {
00639 if (m_aIndex [i] == nSubItem)
00640 return i;
00641 }
00642
00643 return -1;
00644 }