WTL 介面設計篇(CSkinListCtrl)
標頭檔案宣告(CSkinListCtrl.h):
#pragma once
#include <vector>
#include "SkinManager.h"
#include "SkinScrollBar.h"
class CLVColumn
{
public:
CLVColumn(void);
~CLVColumn(void);
public:
CString m_strText;
CImageEx * m_lpImage;
DWORD m_dwFmt;
int m_nWidth;
};
class CLVItem
{
public:
CLVItem(void);
~CLVItem(void);
public:
CString m_strText;
Gdiplus::Bitmap * m_lpImage;
DWORD m_dwFmt;
LPARAM m_lParam;
};
class CLVRow
{
public:
CLVRow(int nCols);
~CLVRow(void);
public:
BOOL AddItem();
BOOL InsertItem(int nCol);
BOOL DeleteItem(int nCol);
BOOL SetItem(int nCol, LPCTSTR lpszText, LPCTSTR lpszImage,
int cx, int cy, BOOL bGray, DWORD dwFmt, LPARAM lParam);
BOOL SetItemText(int nCol, LPCTSTR lpszText);
BOOL SetItemImage(int nCol, LPCTSTR lpszImage, int cx, int cy, BOOL bGray = FALSE);
BOOL SetItemFormat(int nCol, DWORD dwFmt);
BOOL SetItemData(int nCol, LPARAM lParam);
CString GetItemText(int nCol);
Gdiplus::Bitmap * GetItemImage(int nCol);
DWORD GetItemFormat(int nCol);
LPARAM GetItemData(int nCol);
int GetItemCount();
BOOL DeleteAllItems();
private:
CLVItem * GetItem(int nCol);
private:
std::vector<CLVItem *> m_arrItems;
};
class CSkinListCtrl : public CWindowImpl<CSkinListCtrl, CWindow>
{
public:
CSkinListCtrl(void);
~CSkinListCtrl(void);
BEGIN_MSG_MAP_EX(CSkinListCtrl)
MSG_WM_CREATE(OnCreate)
MSG_WM_ERASEBKGND(OnEraseBkgnd)
MSG_WM_PAINT(OnPaint)
MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
MSG_WM_LBUTTONUP(OnLButtonUp)
MSG_WM_RBUTTONDOWN(OnRButtonDown)
MSG_WM_MOUSEMOVE(OnMouseMove)
MSG_WM_MOUSELEAVE(OnMouseLeave)
MSG_WM_TIMER(OnTimer)
MSG_WM_HSCROLL(OnHScroll)
MSG_WM_VSCROLL(OnVScroll)
MSG_WM_MOUSEWHEEL(OnMouseWheel)
MSG_WM_KEYDOWN(OnKeyDown)
MSG_WM_SIZE(OnSize)
MSG_WM_GETDLGCODE(OnGetDlgCode)
//MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
MSG_WM_DESTROY(OnDestroy)
END_MSG_MAP()
public:
BOOL SetBgPic(LPCTSTR lpszFileName); // 設定列表背景圖片
BOOL SetHeadSeparatedPic(LPCTSTR lpszFileName); // 設定表頭分隔符圖片
BOOL SetHeadNormalPic(LPCTSTR lpszFileName); // 設定表頭背景圖片(普通狀態)
BOOL SetHeadHotPic(LPCTSTR lpszFileName); // 設定表頭背景圖片(高亮狀態)
BOOL SetHeadPushedPic(LPCTSTR lpszFileName); // 設定表頭背景圖片(按下狀態)
BOOL SetOddItemBgPic(LPCTSTR lpszFileName); // 設定奇行背景圖片(普通狀態)
BOOL SetEvenItemBgPic(LPCTSTR lpszFileName); // 設定雙行背景圖片(普通狀態)
BOOL SetItemHotBgPic(LPCTSTR lpszFileName); // 設定行背景圖片(高亮狀態)
BOOL SetItemSelBgPic(LPCTSTR lpszFileName); // 設定行背景圖片(選中狀態)
void SetTransparent(BOOL bTransparent, HDC hBgDC); // 設定列表背景是否透明
void SetHeadVisible(BOOL bVisible); // 設定表頭是否可見
BOOL IsHeadVisible(); // 判斷表頭是否可見
void SetHeadHeight(int nHeight); // 設定表頭高度
void SetItemHeight(int nHeight); // 設定行高度
void SetItemImageSize(int cx, int cy); // 設定行影像大小
int AddColumn(LPCTSTR lpszText, // 新增列
LPCTSTR lpszImage, DWORD dwFmt, int nWidth);
int InsertColumn(int nCol, LPCTSTR lpszText, // 插入列
LPCTSTR lpszImage, DWORD dwFmt, int nWidth);
BOOL DeleteColumn(int nCol); // 刪除列
int AddItem(LPCTSTR lpszText, // 新增行
LPCTSTR lpszImage, BOOL bGray, DWORD dwFmt, LPARAM lParam);
int InsertItem(int nItem, LPCTSTR lpszText, // 插入行
LPCTSTR lpszImage, BOOL bGray, DWORD dwFmt, LPARAM lParam);
BOOL DeleteItem(int nItem); // 刪除行
int GetColumnCount(); // 獲取總列數
BOOL DeleteAllColumns(); // 刪除所有列
int GetItemCount(); // 獲取總行數
BOOL DeleteAllItems(); // 刪除所有行
BOOL SetColumnText(int nCol, LPCTSTR lpszText); // 設定列文字
BOOL SetColumnImage(int nCol, LPCTSTR lpszImage); // 設定列影像
BOOL SetColumnFormat(int nCol, DWORD dwFmt); // 設定列格式
BOOL SetColumnWidth(int nCol, int nWidth); // 設定列寬度
CString GetColumnText(int nCol); // 獲取列文字
DWORD GetColumnFormat(int nCol); // 獲取列格式
int GetColumnWidth(int nCol); // 獲取列寬度
BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText); // 設定行文字
BOOL SetItemImage(int nItem, int nSubItem, // 設定行影像
LPCTSTR lpszImage, BOOL bGray = FALSE);
BOOL SetItemFormat(int nItem, int nSubItem, DWORD dwFmt); // 設定行格式
BOOL SetItemData(int nItem, int nSubItem, LPARAM lParam); // 設定行資料
CString GetItemText(int nItem, int nSubItem); // 獲取行文字
DWORD GetItemFormat(int nItem, int nSubItem); // 獲取行格式
LPARAM GetItemData(int nItem, int nSubItem); // 獲取行資料
int GetCurSelItemIndex(); // 獲取當前選中行索引
void SetItemTextColor(COLORREF clr); // 設定行文字顏色(普通狀態)
void SetSelItemTextColor(COLORREF clr); // 行文字顏色(選中狀態)
private:
int OnCreate(LPCREATESTRUCT lpCreateStruct);
BOOL OnEraseBkgnd(CDCHandle dc);
void OnPaint(CDCHandle dc);
void OnLButtonDblClk(UINT nFlags, CPoint point);
void OnLButtonDown(UINT nFlags, CPoint point);
void OnLButtonUp(UINT nFlags, CPoint point);
void OnRButtonDown(UINT nFlags, CPoint point);
void OnMouseMove(UINT nFlags, CPoint point);
void OnMouseLeave();
void OnTimer(UINT_PTR nIDEvent);
void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar);
void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar);
BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
void OnSize(UINT nType, CSize size);
UINT OnGetDlgCode(LPMSG lpMsg);
//LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnDestroy();
CLVColumn * GetColumn(int nCol);
CLVRow * GetItem(int nItem);
void DrawParentWndBg(HDC hDC);
void DrawHeadPart(HDC hDC);
void DrawItemPart(HDC hDC);
BOOL GetHeadPartRect(CRect& rect);
BOOL GetItemPartRect(CRect& rect);
BOOL GetItemRect(int nIndex, CRect& rect);
int HeadHitTest(POINT pt);
int ItemHitTest(POINT pt);
BOOL StartTrackMouseLeave();
void AdjustScrollBarSize();
void CheckScrollBarStatus();
void Scroll(int cx, int cy);
void EnsureVisible(int nIndex);
int GetColumnsWidth();
BOOL Init();
void UnInit();
private:
//CToolTipCtrl m_ToolTipCtrl;
CSkinScrollBar m_HScrollBar;
CSkinScrollBar m_VScrollBar;
std::vector<CLVColumn *> m_arrCols;
std::vector<CLVRow *> m_arrRows;
CImageEx * m_lpBgImg; // 列表背景圖片
CImageEx * m_lpHeadSeparatedImg; // 表頭分隔符圖片
CImageEx * m_lpHeadImgN; // 表頭背景圖片(普通狀態)
CImageEx * m_lpHeadImgH; // 表頭背景圖片(高亮狀態)
CImageEx * m_lpHeadImgP; // 表頭背景圖片(按下狀態)
CImageEx * m_lpOddItemBgImgN; // 奇行背景圖片(普通狀態)
CImageEx * m_lpEvenItemBgImgN; // 雙行背景圖片(普通狀態)
CImageEx * m_lpItemBgImgH; // 行背景圖片(高亮狀態)
CImageEx * m_lpItemBgImgS; // 行背景圖片(選中狀態)
BOOL m_bTransparent; // 列表背景是否透明標誌
HDC m_hBgDC; // 父視窗背景DC
BOOL m_bMouseTracking; // 滑鼠跟蹤標誌
BOOL m_bHeadVisible; // 表頭是否可見標誌
int m_nHeadHeight; // 表頭高度
int m_nItemHeight; // 行高度
CSize m_szItemImage; // 行影像大小
int m_nPressHeadIndex; // 滑鼠按下表頭項索引
int m_nHoverHeadIndex; // 滑鼠懸停表頭項索引
int m_nPressItemIndex; // 滑鼠按下行項索引
int m_nHoverItemIndex; // 滑鼠懸停行項索引
int m_nSelItemIndex; // 滑鼠選中行項索引
int m_nLeft, m_nTop; // 檢視原點座標
COLORREF m_clrItemText; // 行文字顏色(普通狀態)
COLORREF m_clrSelItemText; // 行文字顏色(選中狀態)
};
原始碼定義(CSkinListCtrl.cpp):
#include "StdAfx.h"
#include "SkinListCtrl.h"
void Gray(Gdiplus::Bitmap * lpSrcBmp)
{
UINT nWidth = lpSrcBmp->GetWidth();
UINT nHeight = lpSrcBmp->GetHeight();
Gdiplus::BitmapData bmpData;
Gdiplus::Rect rect(0, 0, nWidth, nHeight);
lpSrcBmp->LockBits(&rect, Gdiplus::ImageLockModeRead|Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &bmpData);
int nValue = 0;
BYTE * pArray = (BYTE *)bmpData.Scan0;
UINT nBytes = (UINT)((nWidth * nHeight) << 2);
for (UINT i = 0; i < nBytes; i += 4)
{
nValue = (int)(pArray[i] * 0.1 + pArray[i+1] * 0.2 + pArray[i+2] * 0.7);
pArray[i] = nValue;
pArray[i+1] = nValue;
pArray[i+2] = nValue;
}
lpSrcBmp->UnlockBits(&bmpData);
}
CLVColumn::CLVColumn(void)
{
m_lpImage = NULL;
m_dwFmt = 0;
m_nWidth = 0;
}
CLVColumn::~CLVColumn(void)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpImage);
}
CLVItem::CLVItem(void)
{
m_lpImage = NULL;
m_dwFmt = 0;
m_lParam = 0;
}
CLVItem::~CLVItem(void)
{
if (m_lpImage != NULL)
{
delete m_lpImage;
m_lpImage = NULL;
}
}
CLVRow::CLVRow(int nCols)
{
for (int i = 0; i < nCols; i++)
{
AddItem();
}
}
CLVRow::~CLVRow(void)
{
DeleteAllItems();
}
BOOL CLVRow::AddItem()
{
CLVItem * lpItem = new CLVItem;
if (NULL == lpItem)
return FALSE;
m_arrItems.push_back(lpItem);
return TRUE;
}
BOOL CLVRow::InsertItem(int nCol)
{
CLVItem * lpItem = new CLVItem;
if (NULL == lpItem)
return FALSE;
m_arrItems.insert(m_arrItems.begin() + nCol, lpItem);
return TRUE;
}
BOOL CLVRow::DeleteItem(int nCol)
{
if (nCol < 0 || nCol >= (int)m_arrItems.size())
return FALSE;
CLVItem * lpItem = m_arrItems[nCol];
if (lpItem != NULL)
{
delete lpItem;
lpItem = NULL;
}
m_arrItems.erase(m_arrItems.begin() + nCol);
return TRUE;
}
BOOL CLVRow::SetItem(int nCol, LPCTSTR lpszText, LPCTSTR lpszImage,
int cx, int cy, BOOL bGray, DWORD dwFmt, LPARAM lParam)
{
if (nCol < 0 || nCol >= (int)m_arrItems.size())
return FALSE;
CLVItem * lpItem = m_arrItems[nCol];
if (NULL == lpItem)
return FALSE;
lpItem->m_strText = lpszText;
SetItemImage(nCol, lpszImage, cx, cy, bGray);
lpItem->m_dwFmt = dwFmt;
lpItem->m_lParam = lParam;
return TRUE;
}
BOOL CLVRow::SetItemText(int nCol, LPCTSTR lpszText)
{
CLVItem * lpItem = GetItem(nCol);
if (NULL == lpItem)
return FALSE;
lpItem->m_strText = lpszText;
return TRUE;
}
BOOL CLVRow::SetItemImage(int nCol, LPCTSTR lpszImage, int cx, int cy, BOOL bGray/* = FALSE*/)
{
CLVItem * lpItem = GetItem(nCol);
if (NULL == lpItem)
return FALSE;
if (lpItem->m_lpImage != NULL)
delete lpItem->m_lpImage;
lpItem->m_lpImage = new Gdiplus::Bitmap(lpszImage);
if (NULL == lpItem->m_lpImage || lpItem->m_lpImage->GetLastStatus() != Gdiplus::Ok)
{
delete lpItem->m_lpImage;
lpItem->m_lpImage = NULL;
return FALSE;
}
if (lpItem->m_lpImage->GetWidth() != cx || lpItem->m_lpImage->GetHeight() != cy)
{
Gdiplus::Bitmap* pThumbnail = (Gdiplus::Bitmap*)lpItem->m_lpImage->GetThumbnailImage(cx, cy);
if (NULL == pThumbnail)
{
delete lpItem->m_lpImage;
lpItem->m_lpImage = NULL;
return FALSE;
}
delete lpItem->m_lpImage;
lpItem->m_lpImage = pThumbnail;
}
if (bGray)
Gray(lpItem->m_lpImage);
return TRUE;
}
BOOL CLVRow::SetItemFormat(int nCol, DWORD dwFmt)
{
CLVItem * lpItem = GetItem(nCol);
if (NULL == lpItem)
return FALSE;
lpItem->m_dwFmt = dwFmt;
return TRUE;
}
BOOL CLVRow::SetItemData(int nCol, LPARAM lParam)
{
CLVItem * lpItem = GetItem(nCol);
if (NULL == lpItem)
return FALSE;
lpItem->m_lParam = lParam;
return TRUE;
}
CString CLVRow::GetItemText(int nCol)
{
CLVItem * lpItem = GetItem(nCol);
return (NULL == lpItem) ? _T("") : lpItem->m_strText;
}
Gdiplus::Bitmap * CLVRow::GetItemImage(int nCol)
{
CLVItem * lpItem = GetItem(nCol);
return (NULL == lpItem) ? NULL : lpItem->m_lpImage;
}
DWORD CLVRow::GetItemFormat(int nCol)
{
CLVItem * lpItem = GetItem(nCol);
return (NULL == lpItem) ? 0 : lpItem->m_dwFmt;
}
LPARAM CLVRow::GetItemData(int nCol)
{
CLVItem * lpItem = GetItem(nCol);
return (NULL == lpItem) ? 0 : lpItem->m_lParam;
}
int CLVRow::GetItemCount()
{
return (int)m_arrItems.size();
}
BOOL CLVRow::DeleteAllItems()
{
for (int i = 0; i < (int)m_arrItems.size(); i++)
{
CLVItem * lpItem = m_arrItems[i];
if (lpItem != NULL)
{
delete lpItem;
lpItem = NULL;
}
}
m_arrItems.clear();
return TRUE;
}
CLVItem * CLVRow::GetItem(int nCol)
{
if (nCol < 0 || nCol >= (int)m_arrItems.size())
return NULL;
else
return m_arrItems[nCol];
}
CSkinListCtrl::CSkinListCtrl(void)
{
m_lpBgImg = NULL;
m_lpHeadSeparatedImg = NULL;
m_lpHeadImgN = NULL;
m_lpHeadImgH = NULL;
m_lpHeadImgP = NULL;
m_lpOddItemBgImgN = NULL;
m_lpEvenItemBgImgN = NULL;
m_lpItemBgImgH = NULL;
m_lpItemBgImgS = NULL;
m_bTransparent = FALSE;
m_hBgDC = NULL;
m_bMouseTracking = FALSE;
m_bHeadVisible = TRUE;
m_nHeadHeight = 20;
m_nItemHeight = 20;
m_szItemImage.cx = 16;
m_szItemImage.cy = 16;
m_nPressHeadIndex = -1;
m_nHoverHeadIndex = -1;
m_nPressItemIndex = -1;
m_nHoverItemIndex = -1;
m_nSelItemIndex = -1;
m_nLeft = m_nTop = 0;
m_clrItemText = RGB(0,0,0);
m_clrSelItemText = RGB(255,255,255);
}
CSkinListCtrl::~CSkinListCtrl(void)
{
DeleteAllItems();
DeleteAllColumns();
}
// 設定列表背景圖片
BOOL CSkinListCtrl::SetBgPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpBgImg);
m_lpBgImg = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpBgImg != NULL) ? TRUE : FALSE;
}
// 設定表頭分隔符圖片
BOOL CSkinListCtrl::SetHeadSeparatedPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadSeparatedImg);
m_lpHeadSeparatedImg = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpHeadSeparatedImg != NULL) ? TRUE : FALSE;
}
// 設定表頭背景圖片(普通狀態)
BOOL CSkinListCtrl::SetHeadNormalPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadImgN);
m_lpHeadImgN = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpHeadImgN != NULL) ? TRUE : FALSE;
}
// 設定表頭背景圖片(高亮狀態)
BOOL CSkinListCtrl::SetHeadHotPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadImgH);
m_lpHeadImgH = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpHeadImgH != NULL) ? TRUE : FALSE;
}
// 設定表頭背景圖片(按下狀態)
BOOL CSkinListCtrl::SetHeadPushedPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadImgP);
m_lpHeadImgP = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpHeadImgP != NULL) ? TRUE : FALSE;
}
// 設定奇行背景圖片(普通狀態)
BOOL CSkinListCtrl::SetOddItemBgPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpOddItemBgImgN);
m_lpOddItemBgImgN = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpOddItemBgImgN != NULL) ? TRUE : FALSE;
}
// 設定雙行背景圖片(普通狀態)
BOOL CSkinListCtrl::SetEvenItemBgPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpEvenItemBgImgN);
m_lpEvenItemBgImgN = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpEvenItemBgImgN != NULL) ? TRUE : FALSE;
}
// 設定行背景圖片(高亮狀態)
BOOL CSkinListCtrl::SetItemHotBgPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpItemBgImgH);
m_lpItemBgImgH = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpItemBgImgH != NULL) ? TRUE : FALSE;
}
// 設定行背景圖片(選中狀態)
BOOL CSkinListCtrl::SetItemSelBgPic(LPCTSTR lpszFileName)
{
CSkinManager::GetInstance()->ReleaseImage(m_lpItemBgImgS);
m_lpItemBgImgS = CSkinManager::GetInstance()->GetImage(lpszFileName);
return (m_lpItemBgImgS != NULL) ? TRUE : FALSE;
}
// 設定列表背景是否透明
void CSkinListCtrl::SetTransparent(BOOL bTransparent, HDC hBgDC)
{
m_bTransparent = bTransparent;
m_hBgDC = hBgDC;
}
// 設定表頭是否可見
void CSkinListCtrl::SetHeadVisible(BOOL bVisible)
{
m_bHeadVisible = bVisible;
}
// 判斷表頭是否可見
BOOL CSkinListCtrl::IsHeadVisible()
{
return m_bHeadVisible;
}
// 設定表頭高度
void CSkinListCtrl::SetHeadHeight(int nHeight)
{
m_nHeadHeight = nHeight;
}
// 設定行高度
void CSkinListCtrl::SetItemHeight(int nHeight)
{
m_nItemHeight = nHeight;
}
// 設定行影像大小
void CSkinListCtrl::SetItemImageSize(int cx, int cy)
{
m_szItemImage.cx = cx;
m_szItemImage.cy = cy;
}
// 新增列
int CSkinListCtrl::AddColumn(LPCTSTR lpszText, LPCTSTR lpszImage, DWORD dwFmt, int nWidth)
{
CLVColumn * lpCol = new CLVColumn;
if (NULL == lpCol)
return -1;
lpCol->m_strText = lpszText;
lpCol->m_lpImage = CSkinManager::GetInstance()->GetImage(lpszImage);
lpCol->m_dwFmt = dwFmt;
lpCol->m_nWidth = nWidth;
m_arrCols.push_back(lpCol);
for (int i = 0; i < (int)m_arrRows.size(); i++)
{
CLVRow * lpRow = m_arrRows[i];
if (lpRow != NULL)
lpRow->AddItem();
}
return m_arrCols.size() - 1;
}
// 插入列
int CSkinListCtrl::InsertColumn(int nCol, LPCTSTR lpszText, LPCTSTR lpszImage, DWORD dwFmt, int nWidth)
{
if (nCol < 0)
return -1;
CLVColumn * lpCol = new CLVColumn;
if (NULL == lpCol)
return -1;
lpCol->m_strText = lpszText;
lpCol->m_lpImage = CSkinManager::GetInstance()->GetImage(lpszImage);
lpCol->m_dwFmt = dwFmt;
lpCol->m_nWidth = nWidth;
m_arrCols.insert(m_arrCols.begin() + nCol, lpCol);
for (int i = 0; i < (int)m_arrRows.size(); i++)
{
CLVRow * lpRow = m_arrRows[i];
if (lpRow != NULL)
lpRow->InsertItem(nCol);
}
return nCol;
}
// 刪除列
BOOL CSkinListCtrl::DeleteColumn(int nCol)
{
if (nCol < 0 || nCol >= (int)m_arrCols.size())
return FALSE;
CLVColumn * lpCol = m_arrCols[nCol];
if (lpCol != NULL)
{
delete lpCol;
lpCol = NULL;
}
m_arrCols.erase(m_arrCols.begin() + nCol);
for (int i = 0; i < (int)m_arrRows.size(); i++)
{
CLVRow * lpRow = m_arrRows[i];
if (lpRow != NULL)
lpRow->DeleteItem(nCol);
}
return TRUE;
}
// 新增行
int CSkinListCtrl::AddItem(LPCTSTR lpszText, LPCTSTR lpszImage, BOOL bGray, DWORD dwFmt, LPARAM lParam)
{
int nItemCnt = GetItemCount();
return InsertItem(nItemCnt, lpszText, lpszImage, bGray, dwFmt, lParam);
}
// 插入行
int CSkinListCtrl::InsertItem(int nItem, LPCTSTR lpszText, LPCTSTR lpszImage,
BOOL bGray,DWORD dwFmt, LPARAM lParam)
{
int nCols = GetColumnCount();
if (nCols <= 0)
return -1;
CLVRow * lpRow = new CLVRow(nCols);
if (NULL == lpRow)
return -1;
BOOL bRet = lpRow->SetItem(0, lpszText, lpszImage,
m_szItemImage.cx, m_szItemImage.cy, bGray, dwFmt, lParam);
if (!bRet)
{
delete lpRow;
return -1;
}
m_arrRows.insert(m_arrRows.begin() + nItem, lpRow);
if (IsWindowVisible())
Invalidate();
return nItem;
}
// 刪除行
BOOL CSkinListCtrl::DeleteItem(int nItem)
{
if (nItem < 0 || nItem >= (int)m_arrRows.size())
return FALSE;
CLVRow * lpRow = m_arrRows[nItem];
if (lpRow != NULL)
{
delete lpRow;
lpRow = NULL;
}
m_arrRows.erase(m_arrRows.begin() + nItem);
if (nItem == m_nSelItemIndex)
m_nSelItemIndex = -1;
else if (m_nSelItemIndex > nItem)
m_nSelItemIndex--;
//m_nHoverItemIndex = -1;
if (::IsWindowVisible(m_hWnd))
Invalidate();
return TRUE;
}
// 獲取總列數
int CSkinListCtrl::GetColumnCount()
{
return (int)m_arrCols.size();
}
// 刪除所有列
BOOL CSkinListCtrl::DeleteAllColumns()
{
DeleteAllItems();
for (int i = 0; i < (int)m_arrCols.size(); i++)
{
CLVColumn * lpCol = m_arrCols[i];
if (lpCol != NULL)
{
delete lpCol;
lpCol = NULL;
}
}
m_arrCols.clear();
return TRUE;
}
// 獲取總行數
int CSkinListCtrl::GetItemCount()
{
return (int)m_arrRows.size();
}
// 刪除所有行
BOOL CSkinListCtrl::DeleteAllItems()
{
for (int i = 0; i < (int)m_arrRows.size(); i++)
{
CLVRow * lpRow = m_arrRows[i];
if (lpRow != NULL)
{
delete lpRow;
lpRow = NULL;
}
}
m_arrRows.clear();
return TRUE;
}
// 設定列文字
BOOL CSkinListCtrl::SetColumnText(int nCol, LPCTSTR lpszText)
{
CLVColumn * lpCol = GetColumn(nCol);
if (NULL == lpCol)
return FALSE;
lpCol->m_strText = lpszText;
if (IsWindowVisible())
Invalidate();
return TRUE;
}
// 設定列影像
BOOL CSkinListCtrl::SetColumnImage(int nCol, LPCTSTR lpszImage)
{
CLVColumn * lpCol = GetColumn(nCol);
if (NULL == lpCol)
return FALSE;
CSkinManager::GetInstance()->ReleaseImage(lpCol->m_lpImage);
lpCol->m_lpImage = CSkinManager::GetInstance()->GetImage(lpszImage);
if (IsWindowVisible())
Invalidate();
return TRUE;
}
// 設定列格式
BOOL CSkinListCtrl::SetColumnFormat(int nCol, DWORD dwFmt)
{
CLVColumn * lpCol = GetColumn(nCol);
if (NULL == lpCol)
return FALSE;
lpCol->m_dwFmt = dwFmt;
if (IsWindowVisible())
Invalidate();
return TRUE;
}
// 設定列寬度
BOOL CSkinListCtrl::SetColumnWidth(int nCol, int nWidth)
{
CLVColumn * lpCol = GetColumn(nCol);
if (NULL == lpCol)
return FALSE;
lpCol->m_nWidth = nWidth;
if (IsWindowVisible())
Invalidate();
return TRUE;
}
// 獲取列文字
CString CSkinListCtrl::GetColumnText(int nCol)
{
CLVColumn * lpCol = GetColumn(nCol);
return (NULL == lpCol) ? _T("") : lpCol->m_strText;
}
// 獲取列格式
DWORD CSkinListCtrl::GetColumnFormat(int nCol)
{
CLVColumn * lpCol = GetColumn(nCol);
return (NULL == lpCol) ? 0 : lpCol->m_dwFmt;
}
// 獲取列寬度
int CSkinListCtrl::GetColumnWidth(int nCol)
{
CLVColumn * lpCol = GetColumn(nCol);
return (NULL == lpCol) ? 0 : lpCol->m_nWidth;
}
// 設定行文字
BOOL CSkinListCtrl::SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
{
CLVRow * lpRow = GetItem(nItem);
if (NULL == lpRow)
return FALSE;
BOOL bRet = lpRow->SetItemText(nSubItem, lpszText);
if (bRet)
{
if (IsWindowVisible())
Invalidate();
}
return bRet;
}
// 設定行影像
BOOL CSkinListCtrl::SetItemImage(int nItem, int nSubItem, LPCTSTR lpszImage, BOOL bGray/* = FALSE*/)
{
CLVRow * lpRow = GetItem(nItem);
if (NULL == lpRow)
return FALSE;
BOOL bRet = lpRow->SetItemImage(nSubItem, lpszImage, m_szItemImage.cx, m_szItemImage.cy, bGray);
if (bRet)
{
if (IsWindowVisible())
Invalidate();
}
return bRet;
}
// 設定行格式
BOOL CSkinListCtrl::SetItemFormat(int nItem, int nSubItem, DWORD dwFmt)
{
CLVRow * lpRow = GetItem(nItem);
if (NULL == lpRow)
return FALSE;
BOOL bRet = lpRow->SetItemFormat(nSubItem, dwFmt);
if (bRet)
{
if (IsWindowVisible())
Invalidate();
}
return bRet;
}
// 設定行資料
BOOL CSkinListCtrl::SetItemData(int nItem, int nSubItem, LPARAM lParam)
{
CLVRow * lpRow = GetItem(nItem);
if (NULL == lpRow)
return FALSE;
return lpRow->SetItemData(nSubItem, lParam);
}
// 獲取行文字
CString CSkinListCtrl::GetItemText(int nItem, int nSubItem)
{
CLVRow * lpRow = GetItem(nItem);
return (NULL == lpRow) ? _T("") : lpRow->GetItemText(nSubItem);
}
// 獲取行格式
DWORD CSkinListCtrl::GetItemFormat(int nItem, int nSubItem)
{
CLVRow * lpRow = GetItem(nItem);
return (NULL == lpRow) ? 0 : lpRow->GetItemFormat(nSubItem);
}
// 獲取行資料
LPARAM CSkinListCtrl::GetItemData(int nItem, int nSubItem)
{
CLVRow * lpRow = GetItem(nItem);
return (NULL == lpRow) ? 0 : lpRow->GetItemData(nSubItem);
}
// 獲取當前選中行索引
int CSkinListCtrl::GetCurSelItemIndex()
{
return m_nSelItemIndex;
}
// 設定行文字顏色(普通狀態)
void CSkinListCtrl::SetItemTextColor(COLORREF clr)
{
m_clrItemText = clr;
}
// 行文字顏色(選中狀態)
void CSkinListCtrl::SetSelItemTextColor(COLORREF clr)
{
m_clrSelItemText = clr;
}
int CSkinListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CRect rcClient;
GetClientRect(&rcClient);
CRect rc = CRect(rcClient.Width()-14, 0, rcClient.Width(), rcClient.Height());
m_VScrollBar.Create(m_hWnd, 1, &rc, 1, FALSE, FALSE);
m_VScrollBar.SetBgNormalPic(_T("ScrollBar\\scrollbar_bkg.png"));
m_VScrollBar.SetBgHotPic(_T("ScrollBar\\scrollbar_bkg.png"));
m_VScrollBar.SetBgPushedPic(_T("ScrollBar\\scrollbar_bkg.png"));
m_VScrollBar.SetBgDisabledPic(_T("ScrollBar\\scrollbar_bkg.png"));
m_VScrollBar.SetShowLeftUpBtn(TRUE);
m_VScrollBar.SetLeftUpBtnNormalPic(_T("ScrollBar\\scrollbar_arrowup_normal.png"));
m_VScrollBar.SetLeftUpBtnHotPic(_T("ScrollBar\\scrollbar_arrowup_highlight.png"));
m_VScrollBar.SetLeftUpBtnPushedPic(_T("ScrollBar\\scrollbar_arrowup_down.png"));
m_VScrollBar.SetLeftUpBtnDisabledPic(_T("ScrollBar\\scrollbar_arrowup_normal.png"));
m_VScrollBar.SetShowRightDownBtn(TRUE);
m_VScrollBar.SetRightDownBtnNormalPic(_T("ScrollBar\\scrollbar_arrowdown_normal.png"));
m_VScrollBar.SetRightDownBtnHotPic(_T("ScrollBar\\scrollbar_arrowdown_highlight.png"));
m_VScrollBar.SetRightDownBtnPushedPic(_T("ScrollBar\\scrollbar_arrowdown_down.png"));
m_VScrollBar.SetRightDownBtnDisabledPic(_T("ScrollBar\\scrollbar_arrowdown_normal.png"));
m_VScrollBar.SetThumbNormalPic(_T("ScrollBar\\scrollbar_bar_normal.png"), CRect(0,1,0,1));
m_VScrollBar.SetThumbHotPic(_T("ScrollBar\\scrollbar_bar_highlight.png"), CRect(0,1,0,1));
m_VScrollBar.SetThumbPushedPic(_T("ScrollBar\\scrollbar_bar_down.png"), CRect(0,1,0,1));
m_VScrollBar.SetThumbDisabledPic(_T("ScrollBar\\scrollbar_bar_normal.png"), CRect(0,1,0,1));
rc = CRect(0, rcClient.Height() - 14, rcClient.Width(), rcClient.Height());
m_HScrollBar.Create(m_hWnd, 2, &rc, 2, TRUE, FALSE);
m_HScrollBar.SetBgNormalPic(_T("ScrollBar\\scrollbar_horz_bkg.png"));
m_HScrollBar.SetBgHotPic(_T("ScrollBar\\scrollbar_horz_bkg.png"));
m_HScrollBar.SetBgPushedPic(_T("ScrollBar\\scrollbar_horz_bkg.png"));
m_HScrollBar.SetBgDisabledPic(_T("ScrollBar\\scrollbar_horz_bkg.png"));
m_HScrollBar.SetShowLeftUpBtn(TRUE);
m_HScrollBar.SetLeftUpBtnNormalPic(_T("ScrollBar\\scrollbar_arrowleft_normal.png"));
m_HScrollBar.SetLeftUpBtnHotPic(_T("ScrollBar\\scrollbar_arrowleft_highlight.png"));
m_HScrollBar.SetLeftUpBtnPushedPic(_T("ScrollBar\\scrollbar_arrowleft_down.png"));
m_HScrollBar.SetLeftUpBtnDisabledPic(_T("ScrollBar\\scrollbar_arrowleft_normal.png"));
m_HScrollBar.SetShowRightDownBtn(TRUE);
m_HScrollBar.SetRightDownBtnNormalPic(_T("ScrollBar\\scrollbar_arrowright_normal.png"));
m_HScrollBar.SetRightDownBtnHotPic(_T("ScrollBar\\scrollbar_arrowright_highlight.png"));
m_HScrollBar.SetRightDownBtnPushedPic(_T("ScrollBar\\scrollbar_arrowright_down.png"));
m_HScrollBar.SetRightDownBtnDisabledPic(_T("ScrollBar\\scrollbar_arrowright_normal.png"));
m_HScrollBar.SetThumbNormalPic(_T("ScrollBar\\scrollbar_horzbar_normal.png"), CRect(1,0,1,0));
m_HScrollBar.SetThumbHotPic(_T("ScrollBar\\scrollbar_horzbar_highlight.png"), CRect(1,0,1,0));
m_HScrollBar.SetThumbPushedPic(_T("ScrollBar\\scrollbar_horzbar_down.png"), CRect(1,0,1,0));
m_HScrollBar.SetThumbDisabledPic(_T("ScrollBar\\scrollbar_horzbar_normal.png"), CRect(1,0,1,0));
m_bMouseTracking = FALSE;
m_nPressHeadIndex = -1;
m_nHoverHeadIndex = -1;
m_nPressItemIndex = -1;
m_nHoverItemIndex = -1;
m_nSelItemIndex = -1;
m_nLeft = m_nTop = 0;
return 0;
}
BOOL CSkinListCtrl::OnEraseBkgnd(CDCHandle dc)
{
return TRUE;
}
void CSkinListCtrl::OnPaint(CDCHandle dc)
{
CRect rcClient;
GetClientRect(&rcClient);
CPaintDC PaintDC(m_hWnd);
CMemoryDC MemDC(PaintDC.m_hDC, rcClient);
CheckScrollBarStatus();
if (m_bTransparent)
DrawParentWndBg(MemDC.m_hDC);
if (m_lpBgImg != NULL && !m_lpBgImg->IsNull())
m_lpBgImg->Draw2(MemDC.m_hDC, rcClient);
DrawHeadPart(MemDC.m_hDC);
DrawItemPart(MemDC.m_hDC);
m_HScrollBar.OnPaint(MemDC.m_hDC);
m_VScrollBar.OnPaint(MemDC.m_hDC);
}
void CSkinListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
CRect rcItemPart;
GetItemPartRect(rcItemPart);
if (rcItemPart.PtInRect(point))
{
m_nSelItemIndex = ItemHitTest(point);
EnsureVisible(m_nSelItemIndex);
Invalidate();
NMHDR stNmhdr = {m_hWnd, GetDlgCtrlID(), NM_DBLCLK}; // 滑鼠左鍵雙擊事件
::SendMessage(::GetParent(m_hWnd), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&stNmhdr);
}
}
void CSkinListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
SetFocus();
::SetCapture(m_hWnd);
CRect rcItemPart;
GetItemPartRect(rcItemPart);
if (rcItemPart.PtInRect(point))
{
int nOldSelItemIndex = m_nSelItemIndex;
m_nSelItemIndex = ItemHitTest(point);
m_nPressItemIndex = m_nSelItemIndex;
m_nPressHeadIndex = -1;
EnsureVisible(m_nSelItemIndex);
Invalidate();
if (m_nSelItemIndex != nOldSelItemIndex)
{
NMHDR stNmhdr = {m_hWnd, GetDlgCtrlID(), LVN_ITEMCHANGED}; // 行選擇改變事件
::SendMessage(::GetParent(m_hWnd), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&stNmhdr);
}
}
else
{
if (IsHeadVisible())
{
CRect rcHeadPart;
GetHeadPartRect(rcHeadPart);
if (rcHeadPart.PtInRect(point))
{
m_nPressHeadIndex = HeadHitTest(point);
m_nPressItemIndex = -1;
Invalidate();
}
}
}
m_VScrollBar.OnLButtonDown(nFlags, point);
m_HScrollBar.OnLButtonDown(nFlags, point);
}
void CSkinListCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
HWND hWnd = ::GetCapture();
if (m_hWnd == hWnd)
::ReleaseCapture();
if (m_nPressHeadIndex != -1)
{
if (HeadHitTest(point) == m_nPressHeadIndex)
{
// 表頭點選事件
}
m_nPressHeadIndex = -1;
Invalidate();
}
else if (m_nPressItemIndex != -1)
{
if (ItemHitTest(point) == m_nPressItemIndex)
{
// 行點選事件
}
m_nPressItemIndex = -1;
Invalidate();
}
m_VScrollBar.OnLButtonUp(nFlags, point);
m_HScrollBar.OnLButtonUp(nFlags, point);
}
void CSkinListCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
SetFocus();
CRect rcItemPart;
GetItemPartRect(rcItemPart);
if (rcItemPart.PtInRect(point))
{
int nOldSelItemIndex = m_nSelItemIndex;
m_nSelItemIndex = ItemHitTest(point);
m_nPressItemIndex = m_nSelItemIndex;
m_nPressHeadIndex = -1;
EnsureVisible(m_nSelItemIndex);
Invalidate();
NMHDR stNmhdr = {m_hWnd, GetDlgCtrlID(), NM_RCLICK}; // 滑鼠右鍵單擊事件
::SendMessage(::GetParent(m_hWnd), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&stNmhdr);
}
}
void CSkinListCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
if (!m_bMouseTracking)
{
StartTrackMouseLeave();
m_bMouseTracking = TRUE;
}
CRect rcItemPart;
GetItemPartRect(rcItemPart);
if (rcItemPart.PtInRect(point))
{
int nHoverItemIndex = ItemHitTest(point);
if (nHoverItemIndex != m_nHoverItemIndex)
{
m_nHoverItemIndex = nHoverItemIndex;
Invalidate();
}
if (m_nHoverHeadIndex != -1)
{
m_nHoverHeadIndex = -1;
Invalidate();
}
}
else
{
if (IsHeadVisible())
{
CRect rcHeadPart;
GetHeadPartRect(rcHeadPart);
if (rcHeadPart.PtInRect(point) && -1 == m_nPressHeadIndex)
{
int nHoverHeadIndex = HeadHitTest(point);
if (nHoverHeadIndex != m_nHoverHeadIndex)
{
m_nHoverHeadIndex = nHoverHeadIndex;
Invalidate();
}
if (m_nHoverItemIndex != -1)
{
m_nHoverItemIndex = -1;
Invalidate();
}
}
}
}
m_VScrollBar.OnMouseMove(nFlags, point);
m_HScrollBar.OnMouseMove(nFlags, point);
}
void CSkinListCtrl::OnMouseLeave()
{
SetMsgHandled(FALSE);
m_bMouseTracking = FALSE;
if (-1 != m_nHoverHeadIndex || -1 != m_nHoverItemIndex)
{
m_nHoverHeadIndex = -1;
m_nHoverItemIndex = -1;
Invalidate();
}
m_VScrollBar.OnMouseLeave();
m_HScrollBar.OnMouseLeave();
}
void CSkinListCtrl::OnTimer(UINT_PTR nIDEvent)
{
m_VScrollBar.OnTimer(nIDEvent);
m_HScrollBar.OnTimer(nIDEvent);
}
void CSkinListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
{
CRect rcItemPart;
GetItemPartRect(rcItemPart);
int nLineSize = 20;
int nPageSize = rcItemPart.Width();
switch (nSBCode)
{
case SB_LINELEFT:
Scroll(-nLineSize, 0);
break;
case SB_LINERIGHT:
Scroll(nLineSize, 0);
break;
case SB_PAGELEFT:
Scroll(-nPageSize, 0);
break;
case SB_PAGERIGHT:
Scroll(nPageSize, 0);
break;
case SB_THUMBTRACK:
Scroll(0, 0);
break;
default:
return;
}
Invalidate();
}
void CSkinListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
{
CRect rcItemPart;
GetItemPartRect(rcItemPart);
int nLineSize = 20;
int nPageSize = rcItemPart.Height();
switch (nSBCode)
{
case SB_LINEUP:
Scroll(0, -nLineSize);
break;
case SB_LINEDOWN:
Scroll(0, nLineSize);
break;
case SB_PAGEUP:
Scroll(0, -nPageSize);
break;
case SB_PAGEDOWN:
Scroll(0, nPageSize);
break;
case SB_THUMBTRACK:
Scroll(0, 0);
break;
default:
return;
}
Invalidate();
}
BOOL CSkinListCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if (!m_VScrollBar.IsVisible())
return TRUE;
int nLineSize = 20;
if (zDelta < 0) // SB_LINEDOWN
Scroll(0, nLineSize);
else // SB_LINEUP
Scroll(0, -nLineSize);
Invalidate();
return TRUE;
}
void CSkinListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (GetItemCount() <= 0)
return;
switch (nChar)
{
case VK_UP: // 向上游標鍵
{
if (0 == m_nSelItemIndex)
return;
m_nSelItemIndex--;
}
break;
case VK_DOWN: // 向下游標鍵
{
if (GetItemCount() - 1 == m_nSelItemIndex)
return;
m_nSelItemIndex++;
}
break;
case VK_LEFT: // 向左游標鍵
{
}
break;
case VK_RIGHT: // 向右游標鍵
{
}
break;
case VK_PRIOR: // PgUp鍵
{
}
return;
case VK_NEXT: // PgDn鍵
{
}
return;
case VK_HOME: // Home鍵
{
}
break;
case VK_END: // End鍵
{
}
break;
case VK_RETURN: // Enter鍵
{
}
return;
default:
return;
}
EnsureVisible(m_nSelItemIndex);
Invalidate();
}
void CSkinListCtrl::OnSize(UINT nType, CSize size)
{
SetMsgHandled(FALSE);
AdjustScrollBarSize();
Invalidate();
}
UINT CSkinListCtrl::OnGetDlgCode(LPMSG lpMsg)
{
return DLGC_HASSETSEL | DLGC_WANTARROWS | DLGC_WANTCHARS | DLGC_WANTTAB;
}
// LRESULT CSkinListCtrl::OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
// {
// SetMsgHandled(FALSE);
// MSG msg = { m_hWnd, uMsg, wParam, lParam };
// if (m_ToolTipCtrl.IsWindow())
// m_ToolTipCtrl.RelayEvent(&msg);
// return 1;
// }
void CSkinListCtrl::OnDestroy()
{
m_VScrollBar.Destroy();
m_HScrollBar.Destroy();
CSkinManager::GetInstance()->ReleaseImage(m_lpBgImg);
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadSeparatedImg);
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadImgN);
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadImgH);
CSkinManager::GetInstance()->ReleaseImage(m_lpHeadImgP);
CSkinManager::GetInstance()->ReleaseImage(m_lpOddItemBgImgN);
CSkinManager::GetInstance()->ReleaseImage(m_lpEvenItemBgImgN);
CSkinManager::GetInstance()->ReleaseImage(m_lpItemBgImgH);
CSkinManager::GetInstance()->ReleaseImage(m_lpItemBgImgS);
DeleteAllItems();
DeleteAllColumns();
}
CLVColumn * CSkinListCtrl::GetColumn(int nCol)
{
if (nCol < 0 || nCol >= (int)m_arrCols.size())
return NULL;
else
return m_arrCols[nCol];
}
CLVRow * CSkinListCtrl::GetItem(int nItem)
{
if (nItem < 0 || nItem >= (int)m_arrRows.size())
return NULL;
else
return m_arrRows[nItem];
}
void CSkinListCtrl::DrawParentWndBg(HDC hDC)
{
HWND hParentWnd = ::GetParent(m_hWnd);
CRect rcWindow;
GetWindowRect(&rcWindow);
::ScreenToClient(hParentWnd, (LPPOINT)&rcWindow);
::ScreenToClient(hParentWnd, ((LPPOINT)&rcWindow)+1);
::BitBlt(hDC, 0, 0, rcWindow.Width(), rcWindow.Height(), m_hBgDC, rcWindow.left, rcWindow.top, SRCCOPY);
}
void CSkinListCtrl::DrawHeadPart(HDC hDC)
{
if (!IsHeadVisible())
return;
CRect rect;
GetHeadPartRect(rect);
if (m_lpHeadImgN != NULL)
m_lpHeadImgN->Draw2(hDC, rect);
int cxSeparated = 0, cySeparated = 0;
if (m_lpHeadSeparatedImg != NULL)
{
cxSeparated = m_lpHeadSeparatedImg->GetWidth();
cySeparated = m_lpHeadSeparatedImg->GetHeight();
}
CRect rcCol, rcSeparated, rcText;
int nLeft = m_nLeft, nTop = 0;
for (int i = 0; i < (int)m_arrCols.size(); i++)
{
CLVColumn * lpCol = m_arrCols[i];
if (lpCol != NULL)
{
rcCol = CRect(nLeft, nTop, nLeft + lpCol->m_nWidth, nTop + m_nHeadHeight);
if (i == m_nPressHeadIndex)
{
if (m_lpHeadImgP != NULL)
m_lpHeadImgP->Draw2(hDC, rcCol);
}
else if (i == m_nHoverHeadIndex)
{
if (m_lpHeadImgH != NULL)
m_lpHeadImgH->Draw2(hDC, rcCol);
}
if (m_lpHeadSeparatedImg != NULL)
{
if (cySeparated >= m_nHeadHeight)
rcSeparated = CRect(rcCol.right-cxSeparated, rcCol.top, rcCol.right, rcCol.bottom);
else
{
int x = (m_nHeadHeight - cySeparated + 1) / 2;
rcSeparated = CRect(rcCol.right-cxSeparated, rcCol.top+x, rcCol.right, rcCol.top+x+cySeparated);
}
m_lpHeadSeparatedImg->Draw2(hDC, rcSeparated);
}
rcText = CRect(rcCol.left+4, rcCol.top, rcCol.right-4, rcCol.bottom);
UINT nFormat = lpCol->m_dwFmt | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS;
::SetTextColor(hDC, RGB(0, 0, 0));
int nMode = ::SetBkMode(hDC, TRANSPARENT);
HFONT hFont = (HFONT)SendMessage(WM_GETFONT, 0, 0);
if (NULL == hFont)
hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
::DrawText(hDC, lpCol->m_strText, -1, &rcText, nFormat);
::SelectObject(hDC, hOldFont);
::SetBkMode(hDC, nMode);
nLeft += lpCol->m_nWidth;
}
}
}
void CSkinListCtrl::DrawItemPart(HDC hDC)
{
CRect rcItemPart;
GetItemPartRect(rcItemPart);
RECT rcClip = {0};
::GetClipBox(hDC, &rcClip);
HRGN hOldRgn = ::CreateRectRgnIndirect(&rcClip);
HRGN hRgn = ::CreateRectRgnIndirect(&rcItemPart);
::ExtSelectClipRgn(hDC, hRgn, RGN_AND);
int nLeft, nTop = m_nTop + rcItemPart.top;
CRect rcClient;
GetClientRect(&rcClient);
int nItemWidth = rcClient.Width();
int nStart = ::abs(m_nTop) / m_nItemHeight;
nTop = (m_nTop + nStart * m_nItemHeight) + rcItemPart.top;
for (int i = nStart; i < (int)m_arrRows.size(); i++)
{
CLVRow * lpRow = m_arrRows[i];
if (lpRow != NULL)
{
nLeft = 0;
CRect rcItem = CRect(nLeft, nTop, nLeft+nItemWidth, nTop+m_nItemHeight);
if (!::RectVisible(hDC, &rcItem))
break;
//if (::RectVisible(hDC, &rcItem))
{
if (i == m_nSelItemIndex)
{
if (m_lpItemBgImgS != NULL)
m_lpItemBgImgS->Draw2(hDC, rcItem);
}
else if (i == m_nHoverItemIndex)
{
if (m_lpItemBgImgH != NULL)
m_lpItemBgImgH->Draw2(hDC, rcItem);
}
else
{
if (i % 2 == 0)
{
if (m_lpOddItemBgImgN != NULL)
m_lpOddItemBgImgN->Draw2(hDC, rcItem);
}
else
{
if (m_lpEvenItemBgImgN != NULL)
m_lpEvenItemBgImgN->Draw2(hDC, rcItem);
}
}
nLeft = m_nLeft;
for (int j = 0; j < (int)lpRow->GetItemCount(); j++)
{
CLVColumn * lpCol = m_arrCols[j];
if (lpCol != NULL)
{
CRect rcCell, rcImage, rcText;
rcCell = CRect(nLeft, nTop, nLeft+lpCol->m_nWidth, nTop+m_nItemHeight);
Gdiplus::Bitmap * lpImage = lpRow->GetItemImage(j);
if (lpImage != NULL)
{
rcImage = rcCell;
rcImage.left += 8;
rcImage.right = rcImage.left + m_szItemImage.cx;
int x = (rcImage.Height() - m_szItemImage.cy + 1) / 2;
rcImage.top += x;
rcImage.bottom = rcImage.top + m_szItemImage.cy;
Gdiplus::Graphics graphics(hDC);
graphics.DrawImage(lpImage, rcImage.left, rcImage.top, rcImage.Width(), rcImage.Height());
}
rcText = rcCell;
if (lpImage != NULL)
rcText.left += rcImage.right+2;
rcText.right -= 4;
UINT nFormat = lpRow->GetItemFormat(j) | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS;
if (i == m_nSelItemIndex)
::SetTextColor(hDC, m_clrSelItemText);
else
::SetTextColor(hDC, m_clrItemText);
int nMode = ::SetBkMode(hDC, TRANSPARENT);
HFONT hFont = (HFONT)SendMessage(WM_GETFONT, 0, 0);
if (NULL == hFont)
hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
::DrawText(hDC, lpRow->GetItemText(j), -1, &rcText, nFormat);
::SelectObject(hDC, hOldFont);
::SetBkMode(hDC, nMode);
nLeft += lpCol->m_nWidth;
}
}
}
nTop += m_nItemHeight;
}
}
::SelectClipRgn(hDC, hOldRgn);
::DeleteObject(hOldRgn);
::DeleteObject(hRgn);
}
BOOL CSkinListCtrl::GetHeadPartRect(CRect& rect)
{
if (!IsHeadVisible())
{
rect = CRect(0, 0, 0, 0);
}
else
{
CRect rcClient;
GetClientRect(&rcClient);
rect = CRect(0, 0, rcClient.Width(), m_nHeadHeight);
if (m_VScrollBar.IsVisible())
{
CRect rcVScrollBar;
m_VScrollBar.GetRect(&rcVScrollBar);
rect.right -= rcVScrollBar.Width();
}
}
return TRUE;
}
BOOL CSkinListCtrl::GetItemPartRect(CRect& rect)
{
CRect rcClient;
GetClientRect(&rcClient);
if (!IsHeadVisible())
rect = CRect(0, 0, rcClient.Width(), rcClient.Height());
else
rect = CRect(0, m_nHeadHeight, rcClient.Width(), rcClient.Height());
if (m_VScrollBar.IsVisible())
{
CRect rcVScrollBar;
m_VScrollBar.GetRect(&rcVScrollBar);
rect.right -= rcVScrollBar.Width();
}
if (m_HScrollBar.IsVisible())
{
CRect rcHScrollBar;
m_HScrollBar.GetRect(&rcHScrollBar);
rect.bottom -= rcHScrollBar.Height();
}
return TRUE;
}
BOOL CSkinListCtrl::GetItemRect(int nIndex, CRect& rect)
{
rect = CRect(0,0,0,0);
if (nIndex < 0 || nIndex >= GetItemCount())
return FALSE;
CRect rcItemPart;
GetItemPartRect(rcItemPart);
int nLeft = 0, nTop = m_nTop + rcItemPart.top;
CRect rcClient;
GetClientRect(rcClient);
int nItemWidth = rcClient.Width();
nTop = m_nTop + rcItemPart.top + nIndex*m_nItemHeight;
rect = CRect(nLeft, nTop, nLeft+nItemWidth, nTop+m_nItemHeight);
return TRUE;
// for (int i = 0; i < (int)m_arrRows.size(); i++)
// {
// if (i == nIndex)
// {
// rect = CRect(nLeft, nTop, nLeft+nItemWidth, nTop+m_nItemHeight);
// return TRUE;
// }
// nTop += m_nItemHeight;
// }
//
// return FALSE;
}
int CSkinListCtrl::HeadHitTest(POINT pt)
{
if (!IsHeadVisible())
return -1;
CRect rcHeadPart;
GetHeadPartRect(rcHeadPart);
if (!rcHeadPart.PtInRect(pt))
return -1;
CRect rcCol;
int nLeft = 0, nTop = 0;
for (int i = 0; i < (int)m_arrCols.size(); i++)
{
CLVColumn * lpCol = m_arrCols[i];
if (lpCol != NULL)
{
rcCol = CRect(nLeft, nTop, nLeft + lpCol->m_nWidth, nTop + m_nHeadHeight);
if (rcCol.PtInRect(pt))
return i;
nLeft += lpCol->m_nWidth;
}
}
return -1;
}
int CSkinListCtrl::ItemHitTest(POINT pt)
{
CRect rcItemPart;
GetItemPartRect(rcItemPart);
if (!rcItemPart.PtInRect(pt))
return -1;
int nLeft = 0, nTop = m_nTop + rcItemPart.top;
CRect rcClient;
GetClientRect(&rcClient);
int nItemWidth = rcClient.Width();
int nStart = ::abs(m_nTop) / m_nItemHeight;
nTop = (m_nTop + nStart * m_nItemHeight) + rcItemPart.top;
for (int i = nStart; i < (int)m_arrRows.size(); i++)
{
CRect rcItem = CRect(nLeft, nTop, nLeft+nItemWidth, nTop+m_nItemHeight);
if (rcItem.PtInRect(pt))
return i;
nTop += m_nItemHeight;
if (nTop > rcClient.bottom)
break;
}
return -1;
}
BOOL CSkinListCtrl::StartTrackMouseLeave()
{
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
return _TrackMouseEvent(&tme);
}
void CSkinListCtrl::AdjustScrollBarSize()
{
CRect rcClient;
GetClientRect(&rcClient);
if (m_VScrollBar.IsVisible() && m_HScrollBar.IsVisible())
{
CRect rc = CRect(rcClient.Width()-14, 0, rcClient.Width(), rcClient.Height()-14);
m_VScrollBar.SetRect(&rc);
rc = CRect(0, rcClient.Height()-14, rcClient.Width()-14, rcClient.Height());
m_HScrollBar.SetRect(&rc);
}
else if (m_VScrollBar.IsVisible())
{
CRect rc = CRect(rcClient.Width()-14, 0, rcClient.Width(), rcClient.Height());
m_VScrollBar.SetRect(&rc);
}
else if (m_HScrollBar.IsVisible())
{
CRect rc = CRect(0, rcClient.Height()-14, rcClient.Width(), rcClient.Height());
m_HScrollBar.SetRect(&rc);
}
}
void CSkinListCtrl::CheckScrollBarStatus()
{
if (!IsWindow())
return;
CRect rcItemPart; // 獲取顯示檢視寬高
GetItemPartRect(rcItemPart);
int cxDisplayView = rcItemPart.Width();
int cyDisplayView = rcItemPart.Height();
int cxContentView = GetColumnsWidth(); // 獲取內容檢視寬高
int cyContentView = GetItemCount() * m_nItemHeight;
CRect rcVScrollBar;
m_VScrollBar.GetRect(&rcVScrollBar);
int cxVScrollBar = rcVScrollBar.Width();
CRect rcHScrollBar;
m_HScrollBar.GetRect(&rcHScrollBar);
int cyHScrollBar = rcHScrollBar.Height();
BOOL bVisibleH = m_HScrollBar.IsVisible();
BOOL bVisibleV = m_VScrollBar.IsVisible();
BOOL bChange2;
int nnn = 0;
do
{
nnn++;
bChange2 = FALSE;
if (cxContentView > cxDisplayView)
{
if (!bVisibleH)
{
bVisibleH = TRUE;
cyDisplayView -= cyHScrollBar;
}
}
else
{
if (bVisibleH)
{
bVisibleH = FALSE;
cyDisplayView += cyHScrollBar;
}
}
if (cyContentView > cyDisplayView)
{
if (!bVisibleV)
{
bVisibleV = TRUE;
bChange2 = TRUE;
cxDisplayView -= cxVScrollBar;
}
}
else
{
if (bVisibleV)
{
bVisibleV = FALSE;
bChange2 = TRUE;
cxDisplayView += cxVScrollBar;
}
}
if (bChange2)
continue;
} while (0);
if (cxContentView > cxDisplayView)
{
m_HScrollBar.SetScrollRange(cxContentView - cxDisplayView);
Scroll(0, 0);
m_HScrollBar.SetVisible(TRUE);
}
else
{
m_nLeft = 0;
m_HScrollBar.SetScrollPos(0);
m_HScrollBar.SetVisible(FALSE);
}
if (cyContentView > cyDisplayView)
{
m_VScrollBar.SetScrollRange(cyContentView - cyDisplayView);
Scroll(0, 0);
m_VScrollBar.SetVisible(TRUE);
}
else
{
m_nTop = 0;
m_VScrollBar.SetScrollPos(0);
m_VScrollBar.SetVisible(FALSE);
}
AdjustScrollBarSize();
}
void CSkinListCtrl::Scroll(int cx, int cy)
{
if (m_HScrollBar.IsVisible() &&
m_HScrollBar.IsEnabled())
{
int nPos = m_HScrollBar.GetScrollPos();
m_HScrollBar.SetScrollPos(nPos + cx);
nPos = m_HScrollBar.GetScrollPos();
m_nLeft = 0 - nPos;
}
if (m_VScrollBar.IsVisible() &&
m_VScrollBar.IsEnabled())
{
int nPos = m_VScrollBar.GetScrollPos();
m_VScrollBar.SetScrollPos(nPos + cy);
nPos = m_VScrollBar.GetScrollPos();
m_nTop = 0 - nPos;
}
}
void CSkinListCtrl::EnsureVisible(int nIndex)
{
CRect rcItemPart;
GetItemPartRect(rcItemPart);
CRect rcItem;
GetItemRect(nIndex, rcItem);
if (rcItem.top < rcItemPart.top || rcItem.bottom >= rcItemPart.bottom)
{
int cy = 0;
if (rcItem.top < rcItemPart.top)
cy = rcItem.top - rcItemPart.top;
if (rcItem.bottom > rcItemPart.bottom)
cy = rcItem.bottom - rcItemPart.bottom;
Scroll(0, cy);
}
}
int CSkinListCtrl::GetColumnsWidth()
{
int nWidth = 0;
for (int i = 0; i < (int)m_arrCols.size(); i++)
{
CLVColumn * lpCol = m_arrCols[i];
if (lpCol != NULL)
{
nWidth += lpCol->m_nWidth;
}
}
return nWidth;
}
BOOL CSkinListCtrl::Init()
{
return TRUE;
}
void CSkinListCtrl::UnInit()
{
}
相關文章
- WTL 介面設計篇(CSkinEdit)
- Thrift RPC 系列教程(5)—— 介面設計篇:struct & enum設計RPCStruct
- 一篇帶你入門面向介面程式設計程式設計
- 【介面功能設計】TopThink介面功能設計建議
- 介面設計分析
- API介面設計API
- 【設計模式】第六篇:來康康介面卡模式設計模式
- 《最佳化介面設計的思路》系列:第四篇—介面的許可權控制
- 後臺介面設計之表格設計
- RPC呼叫介面設計RPC
- 面向介面程式設計程式設計
- 轉賬介面設計
- 介面設計標準
- 《JavaScript設計模式與開發實踐》模式篇(14)—— 介面卡模式JavaScript設計模式
- API 介面設計規範API
- 微信模板介面設計
- QT硬體介面設計QT
- 介面卡設計模式設計模式
- 自適應介面設計
- 介面設計的那些事
- Angular Public API 介面設計AngularAPI
- (03)Flink 程式設計介面程式設計
- 《最佳化介面設計的思路》系列:第三篇—留下使用者呼叫介面的痕跡
- Java設計模式之介面卡設計模式Java設計模式
- 【乾貨】遊戲介面設計 (一)核心設計遊戲
- 介面設計方法 — 3. 字典功能的設計
- 如何設計出“好看”的UI介面(二):4個步驟,搞定介面設計UI
- Java進階篇設計模式之四 -----介面卡模式和橋接模式Java設計模式橋接
- java 介面,介面的特性,介面實現多型,面向介面程式設計Java多型程式設計
- 【乾貨】遊戲介面設計 (五)表現設計遊戲
- 【乾貨】遊戲介面設計 (四)體驗設計遊戲
- 【乾貨】遊戲介面設計 (二)結構設計遊戲
- 【乾貨】遊戲介面設計 (三)資訊設計遊戲
- 如何設計高併發介面?
- 以太坊的程式設計介面程式設計
- 我所理解的介面設計
- 設計模式:介面卡模式設計模式
- PHP 設計模式之流介面模式PHP設計模式