CheckerCtrl.cpp
资源名称:OSDemo [点击查看]
上传用户:tianjwyx
上传日期:2007-01-13
资源大小:813k
文件大小:11k
源码类别:
操作系统开发
开发平台:
Visual C++
- //Author: Mehdi Mousavi
- //Data of release: 8th of September, 2000
- //Email: Webmaster@modemmania.com
- // CheckerCtrl.cpp : implementation file
- //
- #include "stdafx.h"
- #include "CheckerCtrl.h"
- #include "Resource.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CCheckerCtrl
- #define BLANKED_BLOCKS_COLOR RGB(252, 252, 252)
- CCheckerCtrl::CCheckerCtrl()
- {
- //Sets the background brush of the client area
- m_backgroundBrush.CreateSolidBrush(GetSysColor(COLOR_WINDOW));
- //Resets m_nyPos for scrolling purposes
- m_nyPos = 0;
- //Resets m_nBlockStartPos so that when the WM_PAINT message
- //is triggered, the control starts to show blocks
- //from m_nBlockStartPos position
- m_nBlockStartPos = 0;
- //Sets the starting index of blocks
- m_nStartIndex = 0;
- //Total number of blocks
- m_nNumberofBlocks = 0;
- //Offset for scrolling purposes
- m_nOffset = 0;
- m_nTotalVisibleBlocks = 0;
- m_nBlocksPerRow = 0;
- }
- CCheckerCtrl::~CCheckerCtrl()
- {
- }
- BOOL CCheckerCtrl::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID)
- {
- //Postcondition:
- // Creates a window after being registered, as well as
- // setting all the required variables used hereinafter.
- static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
- BOOL bRet = CWnd::CreateEx(WS_EX_CLIENTEDGE,
- className,
- NULL,
- dwStyle,
- rect.left,
- rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top,
- pParentWnd->GetSafeHwnd(),
- (HMENU) nID);
- m_nID = nID;
- m_pParentWnd = pParentWnd;
- SetCursor(LoadCursor(NULL, IDC_ARROW));
- return bRet;
- }
- BEGIN_MESSAGE_MAP(CCheckerCtrl, CWnd)
- //{{AFX_MSG_MAP(CCheckerCtrl)
- ON_WM_PAINT()
- ON_WM_VSCROLL()
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONUP()
- ON_WM_MOUSEMOVE()
- ON_WM_RBUTTONDOWN()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CCheckerCtrl message handlers
- void CCheckerCtrl::OnPaint()
- {
- CPaintDC dc(this); // device context for painting
- // TODO: Add your message handler code here
- //Fill the background color of the client area
- dc.FillRect(m_rcClient, &m_backgroundBrush);
- UINT nColumn = 0, nRow = 0;
- //Calculate the index of the last visible block
- //within the client area
- UINT nBlockEndPos = m_nBlockStartPos + m_nTotalVisibleBlocks + m_nBlocksPerRow;
- if(nBlockEndPos > m_nNumberofBlocks)
- nBlockEndPos = m_nNumberofBlocks;
- for(UINT i = m_nBlockStartPos; i < nBlockEndPos; i++)
- {
- CBrush brush(m_crColor.GetAt(i));
- SetBlock(nRow, nColumn, brush, dc);
- if((i + 1 - m_nBlockStartPos) % m_nBlocksPerRow == 0)
- {
- nRow++;
- nColumn = 0;
- }
- else
- nColumn++;
- }
- }
- void CCheckerCtrl::SetTotalBlocks(const UINT nNumberofBlocks, const UINT nStartIndex)
- {
- //Postcondition:
- // Sets the member variable m_nNumberofBlocks to the specified
- // number of blocks. Then creates an array of COLORREF, sized
- // nNumberofBlocks, and initialize it with white color.
- // Thereafter, it computes m_nOffset for scrolling purposes.
- m_nNumberofBlocks = nNumberofBlocks;
- m_crColor.SetSize(m_nNumberofBlocks);
- for(UINT i = 0; i < m_nNumberofBlocks; i++)
- m_crColor.SetAt(i, BLANKED_BLOCKS_COLOR);
- GetClientRect(m_rcClient);
- m_nBlocksPerRow = m_rcClient.Width() / 9;
- m_nBlocksPerColumn = m_rcClient.Height() / 11;
- m_nTotalVisibleBlocks = m_nBlocksPerRow * m_nBlocksPerColumn;
- //Calculate the vertical scroll bar's range
- int nOffset = (m_nNumberofBlocks / m_nBlocksPerRow);
- if(m_nNumberofBlocks % m_nBlocksPerRow != 0)
- nOffset++;
- m_nOffset = nOffset - m_nBlocksPerColumn;
- if(m_nOffset > 0)
- SetScrollRange(SB_VERT, 0, m_nOffset);
- // Sets the starting index of blocks
- m_nStartIndex = nStartIndex;
- }
- void CCheckerCtrl::SetBlock(int nRow, int nColumn, CBrush &brush, CDC &dc)
- {
- //Postcondition:
- // Places a block on nRow, nColumn ordered pair,
- // and paints it with brush color
- CRect rect = GetRect(nRow, nColumn);
- dc.Rectangle(&rect);
- rect.left++;
- rect.top++;
- rect.bottom--;
- rect.right--;
- dc.FillRect(rect, &brush);
- }
- void CCheckerCtrl::SetBlock(const UINT nBlockNumber, const COLORREF crColor)
- {
- //Postcondition:
- // Sets the color of a specified block number to crColor
- ASSERT(nBlockNumber - m_nStartIndex < m_nNumberofBlocks);
- m_crColor.SetAt(nBlockNumber - m_nStartIndex, crColor);
- }
- void CCheckerCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
- {
- // TODO: Add your message handler code here and/or call default
- int nyOffset;
- switch(nSBCode)
- {
- case SB_PAGEDOWN:
- if(m_nyPos < m_nOffset)
- {
- if(m_nyPos + 2 < m_nOffset)
- nyOffset = 2;
- else
- nyOffset = m_nOffset - m_nyPos;
- m_nyPos += nyOffset;
- m_nBlockStartPos += m_nBlocksPerRow * nyOffset;
- SetScrollPos(SB_VERT, m_nyPos);
- ScrollWindow(0, -nyOffset * 11);
- }
- break;
- case SB_PAGEUP:
- if(m_nyPos > 0)
- {
- if(m_nyPos - 2 > 0)
- nyOffset = 2;
- else
- nyOffset = m_nyPos;
- m_nBlockStartPos -= m_nBlocksPerRow * nyOffset;
- m_nyPos -= nyOffset;
- SetScrollPos(SB_VERT, m_nyPos);
- ScrollWindow(0, nyOffset * 11);
- }
- break;
- case SB_LINEUP:
- if(m_nyPos > 0)
- {
- m_nBlockStartPos -= m_nBlocksPerRow;
- m_nyPos--;
- SetScrollPos(SB_VERT, m_nyPos);
- ScrollWindow(0, 11);
- }
- break;
- case SB_LINEDOWN:
- if(m_nyPos < m_nOffset)
- {
- m_nBlockStartPos += m_nBlocksPerRow;
- m_nyPos++;
- SetScrollPos(SB_VERT, m_nyPos);
- ScrollWindow(0, -11);
- }
- break;
- }
- CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
- }
- void CCheckerCtrl::Refresh()
- {
- //Postcondition:
- // Refreshes the client area of the control
- Invalidate();
- }
- COLORREF CCheckerCtrl::GetBlock(const UINT nBlockNumber) const
- {
- //Precondition:
- // nBlockNumber must be in the range of the defined blocks
- //Postcondition:
- // Takes the color of the specified index
- ASSERT(nBlockNumber >= m_nStartIndex && nBlockNumber - m_nStartIndex <= m_nNumberofBlocks);
- return m_crColor.GetAt(nBlockNumber - m_nStartIndex);
- }
- void CCheckerCtrl::OnLButtonDown(UINT nFlags, CPoint point)
- {
- // TODO: Add your message handler code here and/or call default
- SetFocus();
- DWORD dwPos = GetMessagePos();
- CPoint clickedPoint((int)(short)LOWORD(dwPos), (int)(short)HIWORD(dwPos));
- ScreenToClient(&clickedPoint);
- if(clickedPoint.x % 9 == 0 || clickedPoint.y % 11 == 0)
- m_bShouldUpdated = FALSE;
- else
- {
- UINT nY = clickedPoint.y / 11;
- UINT nX = clickedPoint.x / 9;
- UINT nIndex = nY * m_nBlocksPerRow + nX + m_nyPos * m_nBlocksPerRow;
- if(nIndex < m_nNumberofBlocks && nX < m_nBlocksPerRow)
- {
- SetCapture();
- CString strNumber;
- strNumber.Format("%d", nIndex + m_nStartIndex);
- CreateSafeTooltipRect(clickedPoint.x, clickedPoint.y, strNumber);
- CClientDC dc(this);
- CBrush brush;
- brush.CreateSolidBrush(GetSysColor(COLOR_INFOBK));
- dc.Rectangle(tooltipRect);
- tooltipRect.left++;
- tooltipRect.top++;
- tooltipRect.bottom--;
- tooltipRect.right--;
- dc.FillRect(tooltipRect, &brush);
- CFont font;
- LOGFONT logFont;
- strcpy(logFont.lfFaceName, "Verdana");
- logFont.lfHeight = -MulDiv(12, GetDeviceCaps(dc.m_hDC, LOGPIXELSY), 72);
- logFont.lfWidth = 0;
- logFont.lfEscapement = 0;
- logFont.lfItalic = FALSE;
- logFont.lfStrikeOut = FALSE;
- logFont.lfUnderline = FALSE;
- logFont.lfWeight = FW_BOLD;
- font.CreateFontIndirect(&logFont);
- dc.SelectObject(font);
- dc.SetTextColor(GetSysColor(COLOR_INFOTEXT));
- dc.SetBkColor(GetSysColor(COLOR_INFOBK));
- dc.DrawText(strNumber, tooltipRect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
- tooltipRect.left--;
- tooltipRect.top--;
- tooltipRect.bottom++;
- tooltipRect.right++;
- m_bShouldUpdated = TRUE;
- }
- }
- CWnd::OnLButtonDown(nFlags, point);
- }
- void CCheckerCtrl::OnLButtonUp(UINT nFlags, CPoint point)
- {
- // TODO: Add your message handler code here and/or call default
- if(m_bShouldUpdated)
- {
- CClientDC dc(this);
- InvalidateRect(&tooltipRect, FALSE);
- ReleaseCapture();
- m_bShouldUpdated = FALSE;
- }
- CWnd::OnLButtonUp(nFlags, point);
- }
- void CCheckerCtrl::CreateSafeTooltipRect(int x, int y, LPCTSTR lpszText)
- {
- int nTextLength = strlen(lpszText);
- int nTextWidth = nTextLength;
- if(nTextWidth < 5)
- nTextWidth = 5;
- if(x + 12 * nTextWidth <= m_rcClient.right)
- tooltipRect.right = x + 12 * nTextWidth;
- else
- tooltipRect.right = x - 12 * nTextWidth;
- if(y + 25 <= m_rcClient.bottom)
- tooltipRect.bottom = y + 25;
- else
- tooltipRect.bottom = y - 25;
- tooltipRect.left = x;
- tooltipRect.top = y;
- if(tooltipRect.left > tooltipRect.right)
- {
- int nTemp = tooltipRect.left;
- tooltipRect.left = tooltipRect.right;
- tooltipRect.right = nTemp;
- }
- if(tooltipRect.top > tooltipRect.bottom)
- {
- int nTemp = tooltipRect.bottom;
- tooltipRect.bottom = tooltipRect.top;
- tooltipRect.top = nTemp;
- }
- }
- void CCheckerCtrl::OnMouseMove(UINT nFlags, CPoint point)
- {
- // TODO: Add your message handler code here and/or call default
- SetCursor(LoadCursor(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_CURSOR_HAND)));
- CWnd::OnMouseMove(nFlags, point);
- }
- void CCheckerCtrl::Reset()
- {
- for(UINT i = 0; i < m_nNumberofBlocks; i++)
- m_crColor.SetAt(i, BLANKED_BLOCKS_COLOR);
- }
- void CCheckerCtrl::Update(const UINT nBlockNumber)
- {
- //Precondition:
- // nBlockNumber must be in the range of the defined blocks
- //Postcondition:
- // Updates the color of a specified index on CRT, if and only
- // if it's already visible
- ASSERT(nBlockNumber >= m_nStartIndex && nBlockNumber - m_nStartIndex <= m_nNumberofBlocks);
- if(IsVisible(nBlockNumber))
- {
- UINT nRow = (nBlockNumber - m_nStartIndex) / m_nBlocksPerRow - m_nyPos;
- UINT nColumn = (nBlockNumber - m_nStartIndex) % m_nBlocksPerRow;
- CClientDC dc(this);
- CRect rect = GetRect(nRow, nColumn);
- rect.left++;
- rect.top++;
- rect.bottom--;
- rect.right--;
- CBrush brush;
- brush.CreateSolidBrush(m_crColor.GetAt(nBlockNumber - m_nStartIndex));
- dc.FillRect(rect, &brush);
- }
- }
- CRect CCheckerCtrl::GetRect(const UINT nRow, const UINT nColumn)
- {
- //Postcondition:
- // Returns the rectangular area of a specified block
- // placed in nRow(th) row and nColumn(th) column.
- CRect rect;
- rect.left = nColumn * 9 + 1;
- rect.top = nRow * 11 + 1;
- rect.right = rect.left + 7;
- rect.bottom = rect.top + 9;
- return rect;
- }
- BOOL CCheckerCtrl::IsVisible(const UINT nBlockNumber)
- {
- //Calculate the index of the last visible block
- //within the client area
- UINT nBlockEndPos = m_nBlockStartPos + m_nTotalVisibleBlocks + m_nBlocksPerRow;
- if(nBlockEndPos > m_nNumberofBlocks)
- nBlockEndPos = m_nNumberofBlocks;
- if(nBlockNumber >= m_nBlockStartPos && nBlockNumber <= nBlockEndPos)
- return TRUE;
- else
- return FALSE;
- }
- void CCheckerCtrl::OnRButtonDown(UINT nFlags, CPoint point)
- {
- // TODO: Add your message handler code here and/or call default
- SetFocus();
- if(!(point.x % 9 == 0 || point.y % 11 == 0))
- {
- UINT nY = point.y / 11;
- UINT nX = point.x / 9;
- UINT nIndex = nY * m_nBlocksPerRow + nX + m_nyPos * m_nBlocksPerRow;
- if(nIndex < m_nNumberofBlocks && nX < m_nBlocksPerRow)
- m_pParentWnd->PostMessage(WM_CHECKERCTRL_RBUTTONDOWN, m_nID, nIndex + m_nStartIndex);
- }
- CWnd::OnRButtonDown(nFlags, point);
- }