lvlist.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 11k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. // list view (small icons, multiple columns)
  2. #include "ctlspriv.h"
  3. #include "listview.h"
  4. #define COLUMN_VIEW
  5. void NEAR PASCAL ListView_LDrawItem(LV* plv, int i, LISTITEM FAR* pitem, HDC hdc, LPPOINT lpptOrg, RECT FAR* prcClip, UINT fDraw)
  6. {
  7.     RECT rcIcon;
  8.     RECT rcLabel;
  9.     RECT rcBounds;
  10.     RECT rcT;
  11.     ListView_GetRects(plv, i, &rcIcon, &rcLabel, &rcBounds, NULL);
  12.     if (!prcClip || IntersectRect(&rcT, &rcBounds, prcClip))
  13.     {
  14.         LV_ITEM item;
  15.         char ach[CCHLABELMAX];
  16. UINT fText;
  17. if (lpptOrg)
  18. {
  19.     OffsetRect(&rcIcon, lpptOrg->x - rcBounds.left,
  20.      lpptOrg->y - rcBounds.top);
  21.     OffsetRect(&rcLabel, lpptOrg->x - rcBounds.left,
  22.      lpptOrg->y - rcBounds.top);
  23. }
  24.         item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
  25.         item.iItem = i;
  26.         item.iSubItem = 0;
  27.         item.pszText = ach;
  28.         item.cchTextMax = sizeof(ach);
  29.         item.stateMask = LVIS_ALL;
  30.         ListView_OnGetItem(plv, &item);
  31.         fText = ListView_DrawImage(plv, &item, hdc,
  32.             rcIcon.left, rcIcon.top, fDraw) | SHDT_ELLIPSES;
  33.         // Don't draw the label if it is being edited.
  34.         if (plv->iEdit != i)
  35.         {
  36.     if (fDraw & LVDI_TRANSTEXT)
  37.                 fText |= SHDT_TRANSPARENT;
  38.             if (pitem->cxSingleLabel == SRECOMPUTE)
  39.                 ListView_RecomputeLabelSize(plv, pitem, i, hdc);
  40.             if (pitem->cxSingleLabel < rcLabel.right - rcLabel.left)
  41.                 rcLabel.right = rcLabel.left + pitem->cxSingleLabel;
  42.             SHDrawText(hdc, item.pszText, &rcLabel, LVCFMT_LEFT, fText,
  43.                        plv->cyLabelChar, plv->cxEllipses, plv->clrText, 
  44.                        (plv->style & WS_DISABLED ? plv->clrBk : plv->clrTextBk));
  45.             if ((fDraw & LVDI_FOCUS) && (pitem->state & LVIS_FOCUSED))
  46.                 DrawFocusRect(hdc, &rcLabel);
  47.         }
  48.     }
  49. }
  50. int NEAR ListView_LItemHitTest(LV* plv, int x, int y, UINT FAR* pflags)
  51. {
  52.     int iHit;
  53.     int i;
  54.     int iCol;
  55.     int xItem; //where is the x in relation to the item
  56.     UINT flags;
  57.     LISTITEM FAR* pitem;
  58.     HDC hdc;
  59.     flags = LVHT_NOWHERE;
  60.     iHit = -1;
  61. #ifdef COLUMN_VIEW
  62.     i = y / plv->cyItem;
  63.     if (i >= 0 && i < plv->cItemCol)
  64.     {
  65.         iCol = (x + plv->xOrigin) / plv->cxItem;
  66.         i += iCol * plv->cItemCol;
  67.         if (i >= 0 && i < ListView_Count(plv))
  68.         {
  69.             iHit = i;
  70.             xItem = x + plv->xOrigin - iCol * plv->cxItem;
  71.             if (xItem < plv->cxState) {
  72.                 flags = LVHT_ONITEMSTATEICON;
  73.             } else if (xItem < (plv->cxState + plv->cxSmIcon)) {
  74.                     flags = LVHT_ONITEMICON;
  75.             }
  76.             else
  77.             {
  78.                 pitem = ListView_FastGetItemPtr(plv, i);
  79.                 if (pitem->cxSingleLabel == SRECOMPUTE)
  80.                 {
  81.                     hdc = ListView_RecomputeLabelSize(plv, pitem, i, NULL);
  82.                     ReleaseDC(HWND_DESKTOP, hdc);
  83.                 }
  84.                 if (xItem < (plv->cxSmIcon + plv->cxState + pitem->cxSingleLabel))
  85.                     flags = LVHT_ONITEMLABEL;
  86.             }
  87.         }
  88.     }
  89. #else
  90.     i = x / plv->cxItem;
  91.     if (i < plv->cItemCol)
  92.     {
  93.         i += ((y + plv->xOrigin) / plv->cyItem) * plv->cItemCol;
  94.         if (i < ListView_Count(plv))
  95.         {
  96.             iHit = i;
  97.             flags = LVHT_ONITEMICON;
  98.         }
  99.     }
  100. #endif
  101.     *pflags = flags;
  102.     return iHit;
  103. }
  104. void NEAR ListView_LGetRects(LV* plv, int i, RECT FAR* prcIcon,
  105.         RECT FAR* prcLabel, RECT FAR *prcBounds, RECT FAR* prcSelectBounds)
  106. {
  107.     RECT rcIcon;
  108.     RECT rcLabel;
  109.     int x, y;
  110.     int cItemCol = plv->cItemCol;
  111.     if (cItemCol == 0)
  112.     {
  113.         // Called before other data has been initialized so call
  114.         // update scrollbars which should make sure that that
  115.         // we have valid data...
  116.         ListView_UpdateScrollBars(plv);
  117.         
  118.         // but it's possible that updatescrollbars did nothing because of
  119.         // LVS_NOSCROLL or redraw
  120.         if (plv->cItemCol == 0)
  121.             cItemCol = 1;
  122.         else 
  123.             cItemCol = plv->cItemCol;
  124.     }
  125. #ifdef COLUMN_VIEW
  126.     x = (i / cItemCol) * plv->cxItem;
  127.     y = (i % cItemCol) * plv->cyItem;
  128.     rcIcon.left   = x - plv->xOrigin + plv->cxState;
  129.     rcIcon.top    = y;
  130. #else
  131.     x = (i % cItemCol) * plv->cxItem;
  132.     y = (i / cItemCol) * plv->cyItem;
  133.     rcIcon.left   = x;
  134.     rcIcon.top    = y - plv->xOrigin;
  135. #endif
  136.     rcIcon.right  = rcIcon.left + plv->cxSmIcon;
  137.     rcIcon.bottom = rcIcon.top + plv->cyItem;
  138.     if (prcIcon)
  139.         *prcIcon = rcIcon;
  140.     rcLabel.left  = rcIcon.right;
  141.     rcLabel.right = rcIcon.left + plv->cxItem - plv->cxState;
  142.     rcLabel.top   = rcIcon.top;
  143.     rcLabel.bottom = rcIcon.bottom;
  144.     if (prcLabel)
  145.         *prcLabel = rcLabel;
  146.     if (prcBounds)
  147.     {
  148.         *prcBounds = rcLabel;
  149.         prcBounds->left = rcIcon.left - plv->cxState;
  150.     }
  151.     if (prcSelectBounds)
  152.     {
  153.         *prcSelectBounds = rcLabel;
  154.         prcSelectBounds->left = rcIcon.left;
  155.     }
  156. }
  157. void NEAR ListView_LUpdateScrollBars(LV* plv)
  158. {
  159.     RECT rcClient;
  160.     int cItemCol;
  161.     int cCol;
  162.     int cColVis;
  163.     SCROLLINFO si;
  164.     Assert(plv);
  165.     ListView_GetClientRect(plv, &rcClient, FALSE, NULL);
  166. #ifdef COLUMN_VIEW
  167.     cColVis = (rcClient.right - rcClient.left) / plv->cxItem;
  168.     cItemCol = max(1, (rcClient.bottom - rcClient.top) / plv->cyItem);
  169. #else
  170.     cColVis = (rcClient.bottom - rcClient.top) / plv->cyItem;
  171.     cItemCol = max(1, (rcClient.right - rcClient.left) / plv->cxItem);
  172. #endif
  173.     cCol     = (ListView_Count(plv) + cItemCol - 1) / cItemCol;
  174.     // Make the client area smaller as appropriate, and
  175.     // recompute cCol to reflect scroll bar.
  176.     //
  177.     si.cbSize = sizeof(SCROLLINFO);
  178.     si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
  179.     si.nPage = cColVis;
  180.     si.nMin = 0;
  181. #ifdef COLUMN_VIEW
  182.     rcClient.bottom -= g_cyScrollbar;
  183.     cItemCol = max(1, (rcClient.bottom - rcClient.top) / plv->cyItem);
  184.     cCol = (ListView_Count(plv) + cItemCol - 1) / cItemCol;
  185.     si.nPos = plv->xOrigin / plv->cxItem;
  186.     si.nMax = cCol - 1;
  187. #ifdef IEWIN31_25
  188.     plv->cxScrollPage = (int)si.nPage;
  189.     SetScrollRange( plv->hwnd, SB_HORZ, (int) si.nMin,
  190.                        max( (int)(si.nMax-si.nPage+1), 0 ), FALSE );
  191.     SetScrollPos( plv->hwnd, SB_HORZ, (int) si.nPos, TRUE );
  192. #else
  193.     SetScrollInfo(plv->hwnd, SB_HORZ, &si, TRUE);
  194. #endif //IEWIN31_25
  195. #else
  196.     rcClient.right -= cxScrollBar;
  197.     cItemCol = max(1, (rcClient.right - rcClient.left) / plv->cxItem);
  198.     cCol = (ListView_Count(plv) + cItemCol - 1) / cItemCol;
  199.     si.nPos = plv->xOrigin / plv->cyItem;
  200.     si.nMax = cCol - 1;
  201. #ifdef IEWIN31_25
  202.     plv->cyScrollPage = si.nPage;
  203.     SetScrollRange( plv->hwnd, SB_VERT, (int) si.nMin,
  204.                        max( (int) si.nMax-si.nPage+1, 0 ), FALSE );
  205.     SetScrollPos( plv->hwnd, SB_VERT, (int) si.nPos, TRUE );
  206. #else
  207.     SetScrollInfo(plv->hwnd, SB_VERT, &si, TRUE);
  208. #endif //IEWIN31_25
  209. #endif
  210.     // Update number of visible lines...
  211.     //
  212.     if (plv->cItemCol != cItemCol)
  213.     {
  214.         plv->cItemCol = cItemCol;
  215.         InvalidateRect(plv->hwnd, NULL, TRUE);
  216.     }
  217.     // make sure our position and page doesn't hang over max
  218.     if ((si.nPos + (LONG)si.nPage - 1 > si.nMax) && si.nPos > 0) {
  219.         int iNewPos, iDelta;
  220.         iNewPos = (int)si.nMax - (int)si.nPage + 1;
  221.         if (iNewPos < 0) iNewPos = 0;
  222.         if (iNewPos != si.nPos) {
  223.             iDelta = iNewPos - (int)si.nPos;
  224. #ifdef COLUMN_VIEW
  225.             ListView_LScroll2(plv, iDelta, 0);
  226. #else
  227.             ListView_LScroll2(plv, 0, iDelta);
  228. #endif
  229.             ListView_LUpdateScrollBars(plv);
  230.         }
  231.     }
  232.     // never have the other scrollbar
  233. #ifdef COLUMN_VIEW
  234.     SetScrollRange(plv->hwnd, SB_VERT, 0, 0, TRUE);
  235. #else
  236.     SetScrollRange(plv->hwnd, SB_HORZ, 0, 0, TRUE);
  237. #endif
  238. }
  239. void FAR PASCAL ListView_LScroll2(LV* plv, int dx, int dy)
  240. {
  241. #ifdef COLUMN_VIEW
  242.     if (dx)
  243.     {
  244.         dx *= plv->cxItem;
  245.         plv->xOrigin += dx;
  246.         ScrollWindowEx(plv->hwnd, -dx, 0, NULL, NULL, NULL, NULL,
  247.                        SW_INVALIDATE | SW_ERASE);
  248.         UpdateWindow(plv->hwnd);
  249.     }
  250. #else
  251.     if (dy)
  252.     {
  253.         dy *= plv->cyItem;
  254.         plv->xOrigin += dy;
  255.         ScrollWindowEx(plv->hwnd, 0, -dy, NULL, NULL, NULL, NULL,
  256.                 SW_INVALIDATE | SW_ERASE);
  257.         UpdateWindow(plv->hwnd);
  258.     }
  259. #endif
  260. }
  261. void NEAR ListView_LOnScroll(LV* plv, UINT code, int posNew)
  262. {
  263.     RECT rcClient;
  264.     int cPage;
  265.     if (plv->hwndEdit)
  266.         ListView_DismissEdit(plv, FALSE);
  267.     ListView_GetClientRect(plv, &rcClient, TRUE, NULL);
  268. #ifdef COLUMN_VIEW
  269.     cPage = (rcClient.right - rcClient.left) / plv->cxItem;
  270.     ListView_ComOnScroll(plv, code, posNew, SB_HORZ, 1,
  271.                          cPage ? cPage : 1, ListView_LScroll2);
  272. #else
  273.     cPage = (rcClient.bottom - rcClient.top) / plv->cyItem;
  274.     ListView_ComOnScroll(plv, code, posNew, SB_VERT, 1,
  275.                          cPage ? cPage : 1, ListView_LScroll2);
  276. #endif
  277. }
  278. //------------------------------------------------------------------------------
  279. // This function will see if the size of column should be changed for the listview
  280. // It will check to see if the items between first and last exceed the current width
  281. // and if so will see if the columns are currently big enough.  This wont happen
  282. // if we are not currently in listview or if the caller has set an explicit size.
  283. BOOL FAR PASCAL ListView_MaybeResizeListColumns(LV* plv, int iFirst, int iLast)
  284. {
  285.     HDC hdc = NULL;
  286.     int cxMaxLabel = 0;
  287.     if (!ListView_IsListView(plv) || (plv->flags & LVF_COLSIZESET))
  288.         return(FALSE);
  289.     while (iFirst <= iLast)
  290.     {
  291.         LISTITEM FAR* pitem = ListView_FastGetItemPtr(plv, iFirst);
  292.         if (pitem->cxSingleLabel == SRECOMPUTE)
  293.         {
  294.             hdc = ListView_RecomputeLabelSize(plv, pitem, iFirst, hdc);
  295.         }
  296.         if (pitem->cxSingleLabel > cxMaxLabel)
  297.             cxMaxLabel = pitem->cxSingleLabel;
  298.         iFirst++;
  299.     }
  300.     if (hdc)
  301.         ReleaseDC(HWND_DESKTOP, hdc);
  302.     // We have the max label width, see if this plus the rest of the slop will
  303.     // cause us to want to resize.
  304.     //
  305.     cxMaxLabel += plv->cxSmIcon + g_cxIconMargin + plv->cxState;
  306.     if (cxMaxLabel > g_cxScreen)
  307.         cxMaxLabel = g_cxScreen;
  308.     // Now see if we should resize the columns...
  309.     if (cxMaxLabel > plv->cxItem)
  310.     {
  311.         int iScroll = plv->xOrigin / plv->cxItem;
  312.         DebugMsg(DM_TRACE, "LV Resize Columns: %d", cxMaxLabel);
  313.         ListView_ISetColumnWidth(plv, 0, cxMaxLabel, FALSE);
  314.         plv->xOrigin = iScroll * plv->cxItem;
  315.         return(TRUE);
  316.     }
  317.     return(FALSE);
  318. }