#include "stdafx.h"
|
#include "JobSlotGrid.h"
|
|
#ifdef _DEBUG
|
#define new DEBUG_NEW
|
#endif
|
|
IMPLEMENT_DYNAMIC(CJobSlotGrid, CWnd)
|
|
BEGIN_MESSAGE_MAP(CJobSlotGrid, CWnd)
|
ON_WM_PAINT()
|
ON_WM_ERASEBKGND()
|
ON_WM_MOUSEMOVE()
|
ON_WM_MOUSELEAVE()
|
ON_WM_LBUTTONDOWN()
|
ON_WM_LBUTTONUP()
|
END_MESSAGE_MAP()
|
|
CJobSlotGrid::CJobSlotGrid() {
|
// 初始化默认行列数
|
int m_nRows = 12;
|
int m_nCols = 16;
|
|
// 初始化默认字体
|
m_fontText.CreatePointFont(60, _T("Arial"));
|
|
// 初始化默认颜色
|
COLORREF m_colorHasJob = RGB(0, 200, 0); // 默认绿色
|
COLORREF m_colorNoJob = RGB(220, 220, 220); // 默认灰色
|
|
// 初始化默认画刷
|
m_brushHasJob.CreateSolidBrush(m_colorHasJob);
|
m_brushNoJob.CreateSolidBrush(m_colorNoJob);
|
}
|
|
CJobSlotGrid::~CJobSlotGrid() {
|
if (m_fontText.GetSafeHandle()) {
|
m_fontText.DeleteObject();
|
}
|
|
if (m_brushHasJob.GetSafeHandle()) {
|
m_brushHasJob.DeleteObject();
|
}
|
|
if (m_brushNoJob.GetSafeHandle()) {
|
m_brushNoJob.DeleteObject();
|
}
|
}
|
|
void CJobSlotGrid::SetGridSize(int nRows, int nCols)
|
{
|
m_nRows = nRows;
|
m_nCols = nCols;
|
m_vSlotStatus.assign(nRows, std::vector<bool>(nCols, false));
|
m_vSlotClickable.assign(nRows, std::vector<bool>(nCols, false));
|
|
// 初始化文本数组
|
m_vSlotText.assign(nRows, std::vector<CString>(nCols));
|
for (int i = 0; i < nRows; ++i) {
|
for (int j = 0; j < nCols; ++j) {
|
if (i == 0) {
|
m_vSlotText[i][j].Format(_T("%d"), j + 1);
|
}
|
else if (j == 0) {
|
m_vSlotText[i][j].Format(_T("%d"), i + 1);
|
}
|
}
|
}
|
|
Invalidate();
|
}
|
|
void CJobSlotGrid::SetColors(COLORREF colorHasJob, COLORREF colorNoJob)
|
{
|
m_colorHasJob = colorHasJob;
|
m_colorNoJob = colorNoJob;
|
|
if (m_brushHasJob.GetSafeHandle()) {
|
m_brushHasJob.DeleteObject();
|
}
|
|
if (m_brushNoJob.GetSafeHandle()) {
|
m_brushNoJob.DeleteObject();
|
}
|
|
m_brushHasJob.CreateSolidBrush(m_colorHasJob);
|
m_brushNoJob.CreateSolidBrush(m_colorNoJob);
|
|
|
Invalidate();
|
}
|
|
void CJobSlotGrid::SetSlotStatus(int nRow, int nCol, bool bHasJob, BOOL bInvalidate/* = TRUE*/)
|
{
|
if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
|
m_vSlotStatus[nRow][nCol] = bHasJob;
|
if (bInvalidate) {
|
Invalidate();
|
}
|
}
|
}
|
|
void CJobSlotGrid::SetSlotText(int nRow, int nCol, const CString& strText)
|
{
|
if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
|
m_vSlotText[nRow][nCol] = strText;
|
Invalidate();
|
}
|
}
|
|
void CJobSlotGrid::SetTextFont(const CString& strFontName, int nPointSize)
|
{
|
// 删除旧字体
|
if (m_fontText.GetSafeHandle()) {
|
m_fontText.DeleteObject();
|
}
|
|
// CreatePointFont expects size in 1/10 pt
|
m_fontText.CreatePointFont(nPointSize * 10, strFontName);
|
|
Invalidate();
|
}
|
|
void CJobSlotGrid::ClearAll()
|
{
|
if (m_vSlotStatus.empty()) {
|
return;
|
}
|
|
for (int i = 0; i < m_nRows; ++i) {
|
if (i < (int)m_vSlotStatus.size()) {
|
std::fill(m_vSlotStatus[i].begin(), m_vSlotStatus[i].end(), false);
|
}
|
}
|
Invalidate();
|
}
|
|
void CJobSlotGrid::SetSlotClickable(int nRow, int nCol, bool bClickable)
|
{
|
if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
|
m_vSlotClickable[nRow][nCol] = bClickable;
|
}
|
}
|
|
bool CJobSlotGrid::IsSlotClickable(int nRow, int nCol) const
|
{
|
if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
|
return m_vSlotClickable[nRow][nCol];
|
}
|
return false;
|
}
|
|
void CJobSlotGrid::SetSlotClickCallback(SlotClickCallback fnCallback)
|
{
|
m_fnSlotClickCallback = fnCallback;
|
}
|
|
BOOL CJobSlotGrid::OnEraseBkgnd(CDC* pDC) {
|
return TRUE;
|
}
|
|
void CJobSlotGrid::OnMouseMove(UINT nFlags, CPoint point)
|
{
|
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd };
|
::TrackMouseEvent(&tme);
|
|
CRect rect;
|
GetClientRect(&rect);
|
int nCellWidth = rect.Width() / m_nCols;
|
int nCellHeight = rect.Height() / m_nRows;
|
|
int nCol = point.x / nCellWidth;
|
int nRow = point.y / nCellHeight;
|
|
if (nRow != m_ptHover.y || nCol != m_ptHover.x) {
|
m_ptHover = CPoint(nCol, nRow);
|
Invalidate();
|
}
|
|
CWnd::OnMouseMove(nFlags, point);
|
}
|
|
void CJobSlotGrid::OnMouseLeave()
|
{
|
m_ptHover = CPoint(-1, -1);
|
Invalidate();
|
|
CWnd::OnMouseLeave();
|
}
|
|
void CJobSlotGrid::OnLButtonDown(UINT nFlags, CPoint point)
|
{
|
m_bLButtonDown = true;
|
Invalidate();
|
|
CWnd::OnLButtonDown(nFlags, point);
|
}
|
|
void CJobSlotGrid::OnLButtonUp(UINT nFlags, CPoint point)
|
{
|
m_bLButtonDown = false;
|
Invalidate();
|
|
// 保持原有逻辑不变
|
CRect rect;
|
GetClientRect(&rect);
|
int nCellWidth = rect.Width() / m_nCols;
|
int nCellHeight = rect.Height() / m_nRows;
|
|
int nCol = point.x / nCellWidth;
|
int nRow = point.y / nCellHeight;
|
|
if (IsSlotClickable(nRow, nCol)) {
|
if (m_fnSlotClickCallback) {
|
m_fnSlotClickCallback(nRow, nCol);
|
}
|
}
|
|
CWnd::OnLButtonUp(nFlags, point);
|
}
|
|
void CJobSlotGrid::OnPaint() {
|
CPaintDC dc(this);
|
DrawGrid(&dc);
|
}
|
|
void CJobSlotGrid::DrawGrid(CDC* pDC)
|
{
|
CRect rect;
|
GetClientRect(&rect);
|
|
if (m_nCols == 0 || m_nRows == 0) {
|
return;
|
}
|
|
// 计算格子尺寸
|
int nCellWidth = rect.Width() / m_nCols;
|
int nCellHeight = rect.Height() / m_nRows;
|
|
// 字体设置
|
CFont* pOldFont = pDC->SelectObject(&m_fontText);
|
pDC->SetBkMode(TRANSPARENT);
|
pDC->SetTextColor(RGB(0, 0, 0));
|
|
// 定义颜色常量
|
constexpr COLORREF COLOR_HOVER = RGB(200, 230, 255);
|
constexpr COLORREF COLOR_CLICK = RGB(0, 120, 215);
|
|
for (int i = 0; i < m_nRows; ++i) {
|
for (int j = 0; j < m_nCols; ++j) {
|
CRect cellRect(j * nCellWidth, i * nCellHeight, (j + 1) * nCellWidth, (i + 1) * nCellHeight);
|
|
// 判断状态:悬停 / 按下
|
bool bIsHover = (m_ptHover.x == j && m_ptHover.y == i);
|
bool bIsClicking = bIsHover && m_bLButtonDown;
|
|
// 选择填充颜色
|
COLORREF fillColor = m_vSlotStatus[i][j] ? m_colorHasJob : m_colorNoJob;
|
if (IsSlotClickable(i, j)) {
|
if (bIsClicking)
|
fillColor = COLOR_CLICK;
|
else if (bIsHover)
|
fillColor = COLOR_HOVER;
|
}
|
|
// 绘制背景(高效替代 CBrush)
|
pDC->FillSolidRect(&cellRect, fillColor);
|
|
// 绘制边框
|
pDC->DrawEdge(&cellRect, EDGE_SUNKEN, BF_RECT);
|
|
// 获取文字(安全)
|
CString strText;
|
if (i < m_vSlotText.size() && j < m_vSlotText[i].size()) {
|
strText = m_vSlotText[i][j];
|
}
|
|
if (!strText.IsEmpty()) {
|
// 先计算文字高度(支持换行)
|
CRect calcRect = cellRect;
|
pDC->DrawText(strText, &calcRect, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_CALCRECT);
|
|
// 重新设定居中绘制区域
|
CRect textRect = cellRect;
|
textRect.top += (cellRect.Height() - calcRect.Height()) / 2;
|
|
// 实际绘制文字
|
pDC->DrawText(strText, &textRect, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
|
}
|
}
|
}
|
|
pDC->SelectObject(pOldFont);
|
}
|