mrDarker
2025-05-29 863f21995955fb3e9aa471430218967d4e642c27
Merge branch 'liuyang'
已添加30个文件
已修改10个文件
14985 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CEFEM.cpp 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph1.cpp 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/CellRange.h 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCell.cpp 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCell.h 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCellBase.cpp 773 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCellBase.h 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCellButton.cpp 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCellButton.h 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCtrl.cpp 8428 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridCtrl.h 1090 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridDropTarget.cpp 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridDropTarget.h 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridInPlaceEdit.cpp 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridInPlaceEdit.h 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/GridMemDC.h 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCheck.cpp 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCheck.h 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCombo.cpp 510 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCombo.h 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellDateTime.cpp 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellDateTime.h 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellNumeric.cpp 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellNumeric.h 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridURLCell.cpp 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridURLCell.h 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/TitleTip.cpp 341 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/GridControl/TitleTip.h 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRobotCmd.cpp 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PortConfigurationDlg.cpp 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PortConfigurationDlg.h 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.cpp 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.user 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TransferManager.cpp 550 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TransferManager.h 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/stdafx.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEFEM.cpp
@@ -409,7 +409,7 @@
            // eq cim mode change
            CEqCimModeChangeStep* pStep = new CEqCimModeChangeStep();
            pStep->setName(STEP_CIM_MODE_CHANGE);
            pStep->setWriteSignalDev(0x70);
            pStep->setWriteSignalDev(0x60);
            pStep->setCimModeDev(0x15);
            if (addStep(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pStep) != 0) {
                delete pStep;
@@ -420,7 +420,7 @@
            // eq cim message
            CEqCimMessageCmdStep* pStep = new CEqCimMessageCmdStep();
            pStep->setName(STEP_CIM_MESSAGE_CMD);
            pStep->setWriteSignalDev(0x71);
            pStep->setWriteSignalDev(0x61);
            pStep->setCimMessageDev(0x0);
            if (addStep(STEP_ID_CIM_MSG_SET_CMD_REPLY, pStep) != 0) {
                delete pStep;
@@ -432,7 +432,7 @@
            // CIM Message Confirm
            CEqReadIntStep* pStep = new CEqReadIntStep(__INT32, 0x5f80);
            pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM);
            pStep->setWriteSignalDev(0x59);
            pStep->setWriteSignalDev(0x49);
            if (addStep(STEP_ID_CIM_MSG_CONFIRM_REPORT, pStep) != 0) {
                delete pStep;
            }
@@ -460,7 +460,7 @@
            // eq cim message clear
            CEqCimMessageClearStep* pStep = new CEqCimMessageClearStep();
            pStep->setName(STEP_CIM_MESSAGE_CLEAR);
            pStep->setWriteSignalDev(0x72);
            pStep->setWriteSignalDev(0x62);
            pStep->setClearCimMessageDev(0x13);
            if (addStep(STEP_ID_CIM_MSG_CLEAR_CMD_REPLY, pStep) != 0) {
                delete pStep;
@@ -471,7 +471,7 @@
            // datetime set cmd
            CEqDateTimeSetCmdStep* pStep = new CEqDateTimeSetCmdStep();
            pStep->setName(STEP_DATETIME_SET_CMD);
            pStep->setWriteSignalDev(0x73);
            pStep->setWriteSignalDev(0x63);
            pStep->setDateTimeDev(0x16);
            if (addStep(STEP_ID_DATETIME_SET_CMD_REPLY, pStep) != 0) {
                delete pStep;
@@ -482,7 +482,7 @@
            // vcr enable
            CEqVCREnableStep* pStep = new CEqVCREnableStep();
            pStep->setName(STEP_EQ_VCR_ENABLE);
            pStep->setWriteSignalDev(0x74);
            pStep->setWriteSignalDev(0x64);
            pStep->setEqVCRModeDev(0x1F);
            if (addStep(STEP_ID_VCR_ENABLE_CMD_REPLY, pStep) != 0) {
                delete pStep;
@@ -493,7 +493,7 @@
            // eq mode change
            CEqModeChangeStep* pStep = new CEqModeChangeStep();
            pStep->setName(STEP_EQ_MODE_CHANGE);
            pStep->setWriteSignalDev(0x75);
            pStep->setWriteSignalDev(0x65);
            pStep->setEqModeDev(0x1E);
            if (addStep(STEP_ID_EQMODE_CHANGE_CMD_REPLY, pStep) != 0) {
                delete pStep;
SourceCode/Bond/Servo/CPageGraph1.cpp
@@ -83,6 +83,12 @@
                        BOOL bAlive = pEquipment->isAlive();
                        if (EQ_ID_EFEM == nID) {
                            DeviceStatus status = bAlive ? DeviceStatus::ONLINE : DeviceStatus::OFFLINE;
                            UpdateDeviceStatus(INDICATE_FLIPER, status);
                            UpdateDeviceStatus(INDICATE_ALIGNER, status);
                            UpdateDeviceStatus(INDICATE_LPORT1, status);
                            UpdateDeviceStatus(INDICATE_LPORT2, status);
                            UpdateDeviceStatus(INDICATE_LPORT3, status);
                            UpdateDeviceStatus(INDICATE_LPORT4, status);
                            UpdateDeviceStatus(INDICATE_ROBOT_ARM1, status);
                            UpdateDeviceStatus(INDICATE_ROBOT_ARM2, status);
                        }
SourceCode/Bond/Servo/GridControl/CellRange.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,156 @@
///////////////////////////////////////////////////////////////////////
// CellRange.h: header file
//
// MFC Grid Control - interface for the CCellRange class.
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// The code contained in this file is based on the original
// WorldCom Grid control written by Joe Willcoxson,
//      mailto:chinajoe@aol.com
//      http://users.aol.com/chinajoe
#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif
class CCellID
{
// Attributes
public:
    int row, col;
// Operations
public:
    explicit CCellID(int nRow = -1, int nCol = -1) : row(nRow), col(nCol) {}
    int IsValid() const { return (row >= 0 && col >= 0); }
    int operator==(const CCellID& rhs) const { return (row == rhs.row && col == rhs.col); }
    int operator!=(const CCellID& rhs) const { return !operator==(rhs); }
};
class CCellRange
{
public:
    CCellRange(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1)
    {
        Set(nMinRow, nMinCol, nMaxRow, nMaxCol);
    }
    void Set(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1);
    int  IsValid() const;
    int  InRange(int row, int col) const;
    int  InRange(const CCellID& cellID) const;
    int  Count() { return (m_nMaxRow - m_nMinRow + 1) * (m_nMaxCol - m_nMinCol + 1); }
    CCellID  GetTopLeft() const;
    CCellRange  Intersect(const CCellRange& rhs) const;
    int GetMinRow() const {return m_nMinRow;}
    void SetMinRow(int minRow) {m_nMinRow = minRow;}
    int GetMinCol() const {return m_nMinCol;}
    void SetMinCol(int minCol) {m_nMinCol = minCol;}
    int GetMaxRow() const {return m_nMaxRow;}
    void SetMaxRow(int maxRow) {m_nMaxRow = maxRow;}
    int GetMaxCol() const {return m_nMaxCol;}
    void SetMaxCol(int maxCol) {m_nMaxCol = maxCol;}
    int GetRowSpan() const {return m_nMaxRow - m_nMinRow + 1;}
    int GetColSpan() const {return m_nMaxCol - m_nMinCol + 1;}
    void operator=(const CCellRange& rhs);
    int  operator==(const CCellRange& rhs);
    int  operator!=(const CCellRange& rhs);
protected:
    int m_nMinRow;
    int m_nMinCol;
    int m_nMaxRow;
    int m_nMaxCol;
};
inline void CCellRange::Set(int minRow, int minCol, int maxRow, int maxCol)
{
     m_nMinRow = minRow;
     m_nMinCol = minCol;
     m_nMaxRow = maxRow;
     m_nMaxCol = maxCol;
}
inline void CCellRange::operator=(const CCellRange& rhs)
{
    if (this != &rhs) Set(rhs.m_nMinRow, rhs.m_nMinCol, rhs.m_nMaxRow, rhs.m_nMaxCol);
}
inline int CCellRange::operator==(const CCellRange& rhs)
{
     return ((m_nMinRow == rhs.m_nMinRow) && (m_nMinCol == rhs.m_nMinCol) &&
             (m_nMaxRow == rhs.m_nMaxRow) && (m_nMaxCol == rhs.m_nMaxCol));
}
inline int CCellRange::operator!=(const CCellRange& rhs)
{
     return !operator==(rhs);
}
inline int CCellRange::IsValid() const
{
     return (m_nMinRow >= 0 && m_nMinCol >= 0 && m_nMaxRow >= 0 && m_nMaxCol >= 0 &&
             m_nMinRow <= m_nMaxRow && m_nMinCol <= m_nMaxCol);
}
inline int CCellRange::InRange(int row, int col) const
{
     return (row >= m_nMinRow && row <= m_nMaxRow && col >= m_nMinCol && col <= m_nMaxCol);
}
inline int CCellRange::InRange(const CCellID& cellID) const
{
     return InRange(cellID.row, cellID.col);
}
inline CCellID CCellRange::GetTopLeft() const
{
     return CCellID(m_nMinRow, m_nMinCol);
}
inline CCellRange CCellRange::Intersect(const CCellRange& rhs) const
{
     return CCellRange(max(m_nMinRow,rhs.m_nMinRow), max(m_nMinCol,rhs.m_nMinCol),
                       min(m_nMaxRow,rhs.m_nMaxRow), min(m_nMaxCol,rhs.m_nMaxCol));
}
#endif // !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_)
SourceCode/Bond/Servo/GridControl/GridCell.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,294 @@
// GridCell.cpp : implementation file
//
// MFC Grid Control - Main grid cell class
//
// Provides the implementation for the "default" cell type of the
// grid control. Adds in cell editing.
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
// History:
// Eric Woodruff - 20 Feb 2000 - Added PrintCell() plus other minor changes
// Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase
// <kenbertelson@hotmail.com>
// C Maunder     - 17 Jun 2000 - Font handling optimsed, Added CGridDefaultCell
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCell.h"
#include "GridCtrl.h"
#include "GridInPlaceEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CGridCell, CGridCellBase)
IMPLEMENT_DYNCREATE(CGridDefaultCell, CGridCell)
/////////////////////////////////////////////////////////////////////////////
// GridCell
CGridCell::CGridCell()
{
    m_plfFont = NULL;
    CGridCell::Reset();
}
CGridCell::~CGridCell()
{
    if (m_plfFont)
    {
        delete m_plfFont;
        m_plfFont = NULL;
    }
}
/////////////////////////////////////////////////////////////////////////////
// GridCell Attributes
void CGridCell::operator=(const CGridCell& cell)
{
    if (this != &cell) CGridCellBase::operator=(cell);
}
void CGridCell::Reset()
{
    CGridCellBase::Reset();
    m_strText.Empty();
    m_nImage   = -1;
    m_lParam   = NULL;           // BUG FIX J. Bloggs 20/10/03
    m_pGrid    = NULL;
    m_bEditing = FALSE;
    m_pEditWnd = NULL;
    m_nFormat = (DWORD)-1;       // Use default from CGridDefaultCell
    m_crBkClr = CLR_DEFAULT;     // Background colour (or CLR_DEFAULT)
    m_crFgClr = CLR_DEFAULT;     // Forground colour (or CLR_DEFAULT)
    m_nMargin = (UINT)-1;        // Use default from CGridDefaultCell
    if (m_plfFont)
    {
        delete m_plfFont;
        m_plfFont = NULL;
    }
    m_plfFont = NULL;            // Cell font
}
void CGridCell::SetFont(const LOGFONT* plf)
{
    if (plf == NULL)
    {
        if (m_plfFont)
        {
            delete m_plfFont;
            m_plfFont = NULL;
        }
    }
    else
    {
        if (!m_plfFont)
            m_plfFont = new LOGFONT;
        if (m_plfFont)
            memcpy(m_plfFont, plf, sizeof(LOGFONT));
    }
}
LOGFONT* CGridCell::GetFont() const
{
    if (m_plfFont == NULL)
    {
        CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
        if (!pDefaultCell)
            return NULL;
        return pDefaultCell->GetFont();
    }
    return m_plfFont;
}
CFont* CGridCell::GetFontObject() const
{
    // If the default font is specified, use the default cell implementation
    if (m_plfFont == NULL)
    {
        CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
        if (!pDefaultCell)
            return NULL;
        return pDefaultCell->GetFontObject();
    }
    else
    {
        static CFont Font;
        Font.DeleteObject();
        Font.CreateFontIndirect(m_plfFont);
        return &Font;
    }
}
DWORD CGridCell::GetFormat() const
{
    if (m_nFormat == (DWORD)-1)
    {
        CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
        if (!pDefaultCell)
            return 0;
        return pDefaultCell->GetFormat();
    }
    return m_nFormat;
}
UINT CGridCell::GetMargin() const
{
    if (m_nMargin == (UINT)-1)
    {
        CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
        if (!pDefaultCell)
            return 0;
        return pDefaultCell->GetMargin();
    }
    return m_nMargin;
}
/////////////////////////////////////////////////////////////////////////////
// GridCell Operations
BOOL CGridCell::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar)
{
    if ( m_bEditing )
    {
        if (m_pEditWnd)
            m_pEditWnd->SendMessage ( WM_CHAR, nChar );
    }
    else
    {
        DWORD dwStyle = ES_LEFT;
        if (GetFormat() & DT_RIGHT)
            dwStyle = ES_RIGHT;
        else if (GetFormat() & DT_CENTER)
            dwStyle = ES_CENTER;
        m_bEditing = TRUE;
        // InPlaceEdit auto-deletes itself
        CGridCtrl* pGrid = GetGrid();
        m_pEditWnd = new CGridInPlaceEdit(pGrid, rect, dwStyle, nID, nRow, nCol, GetText(), nChar);
    }
    return TRUE;
}
void CGridCell::EndEdit()
{
    if (m_pEditWnd)
        ((CGridInPlaceEdit*)m_pEditWnd)->EndEdit();
}
void CGridCell::OnEndEdit()
{
    m_bEditing = FALSE;
    m_pEditWnd = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CGridDefaultCell
CGridDefaultCell::CGridDefaultCell()
{
#ifdef _WIN32_WCE
    m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX;
#else
    m_nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX | DT_END_ELLIPSIS;
#endif
    m_crFgClr = CLR_DEFAULT;
    m_crBkClr = CLR_DEFAULT;
    m_Size    = CSize(30,10);
    m_dwStyle = 0;
#ifdef _WIN32_WCE
    LOGFONT lf;
    GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &lf);
    SetFont(&lf);
#else // not CE
    NONCLIENTMETRICS ncm;
    memset(&ncm,0,sizeof(NONCLIENTMETRICS));
    ncm.cbSize = sizeof(NONCLIENTMETRICS);
    //VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
    SetFont(&(ncm.lfMessageFont));
#endif
}
CGridDefaultCell::~CGridDefaultCell()
{
    m_Font.DeleteObject();
}
void CGridDefaultCell::SetFont(const LOGFONT* plf)
{
//    ASSERT(plf);
    if (!plf) return;
    m_Font.DeleteObject();
    m_Font.CreateFontIndirect(plf);
    CGridCell::SetFont(plf);
    // Get the font size and hence the default cell size
    CDC* pDC = CDC::FromHandle(::GetDC(NULL));
    if (pDC)
    {
        CFont* pOldFont = pDC->SelectObject(&m_Font);
        SetMargin(pDC->GetTextExtent(_T(" "), 1).cx);
        m_Size = pDC->GetTextExtent(_T(" XXXXXXXXXXXX "), 14);
        m_Size.cy = (m_Size.cy * 3) / 2;
        pDC->SelectObject(pOldFont);
        ReleaseDC(NULL, pDC->GetSafeHdc());
    }
    else
    {
        SetMargin(3);
        m_Size = CSize(40,16);
    }
}
LOGFONT* CGridDefaultCell::GetFont() const
{
//    ASSERT(m_plfFont);  // This is the default - it CAN'T be NULL!
    return m_plfFont;
}
CFont* CGridDefaultCell::GetFontObject() const
{
//    ASSERT(m_Font.GetSafeHandle());
    return (CFont*) &m_Font;
}
SourceCode/Bond/Servo/GridControl/GridCell.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,143 @@
/////////////////////////////////////////////////////////////////////////////
// GridCell.h : header file
//
// MFC Grid Control - Grid cell class header file
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CGridCtrl;
#include "GridCellBase.h"
// Each cell contains one of these. Fields "row" and "column" are not stored since we
// will usually have acces to them in other ways, and they are an extra 8 bytes per
// cell that is probably unnecessary.
class CGridCell : public CGridCellBase
{
    friend class CGridCtrl;
    DECLARE_DYNCREATE(CGridCell)
// Construction/Destruction
public:
    CGridCell();
    virtual ~CGridCell();
// Attributes
public:
    void operator=(const CGridCell& cell);
    virtual void  SetText(LPCTSTR szText)        { m_strText = szText;  }
    virtual void  SetImage(int nImage)           { m_nImage = nImage;   }
    virtual void  SetData(LPARAM lParam)         { m_lParam = lParam;   }
    virtual void  SetGrid(CGridCtrl* pGrid)      { m_pGrid = pGrid;     }
    // virtual void SetState(const DWORD nState);  -  use base class version
    virtual void  SetFormat(DWORD nFormat)       { m_nFormat = nFormat; }
    virtual void  SetTextClr(COLORREF clr)       { m_crFgClr = clr;     }
    virtual void  SetBackClr(COLORREF clr)       { m_crBkClr = clr;     }
    virtual void  SetFont(const LOGFONT* plf);
    virtual void  SetMargin(UINT nMargin)        { m_nMargin = nMargin; }
    virtual CWnd* GetEditWnd() const             { return m_pEditWnd;   }
    virtual void  SetCoords(int /*nRow*/, int /*nCol*/) {}  // don't need to know the row and
                                                            // column for base implementation
    virtual LPCTSTR     GetText() const             { return (m_strText.IsEmpty())? _T("") : LPCTSTR(m_strText); }
    virtual int         GetImage() const            { return m_nImage;  }
    virtual LPARAM      GetData() const             { return m_lParam;  }
    virtual CGridCtrl*  GetGrid() const             { return m_pGrid;   }
    // virtual DWORD    GetState() const - use base class
    virtual DWORD       GetFormat() const;
    virtual COLORREF    GetTextClr() const          { return m_crFgClr; } // TODO: change to use default cell
    virtual COLORREF    GetBackClr() const          { return m_crBkClr; }
    virtual LOGFONT*    GetFont() const;
    virtual CFont*      GetFontObject() const;
    virtual UINT        GetMargin() const;
    virtual BOOL        IsEditing() const           { return m_bEditing; }
    virtual BOOL        IsDefaultFont() const       { return (m_plfFont == NULL); }
    virtual void        Reset();
// editing cells
public:
    virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
    virtual void EndEdit();
protected:
    virtual void OnEndEdit();
protected:
    CString    m_strText;      // Cell text (or binary data if you wish...)
    LPARAM     m_lParam;       // 32-bit value to associate with item
    int        m_nImage;       // Index of the list view item抯 icon
    DWORD      m_nFormat;
    COLORREF   m_crFgClr;
    COLORREF   m_crBkClr;
    LOGFONT*   m_plfFont;
    UINT       m_nMargin;
    BOOL       m_bEditing;     // Cell being edited?
    CGridCtrl* m_pGrid;        // Parent grid control
    CWnd*      m_pEditWnd;
};
// This class is for storing grid default values. It's a little heavy weight, so
// don't use it in bulk
class CGridDefaultCell : public CGridCell
{
    DECLARE_DYNCREATE(CGridDefaultCell)
// Construction/Destruction
public:
    CGridDefaultCell();
    virtual ~CGridDefaultCell();
public:
    virtual DWORD GetStyle() const                      { return m_dwStyle;      }
    virtual void  SetStyle(DWORD dwStyle)               { m_dwStyle = dwStyle;   }
    virtual int   GetWidth() const                      { return m_Size.cx;      }
    virtual int   GetHeight() const                     { return m_Size.cy;      }
    virtual void  SetWidth(int nWidth)                  { m_Size.cx = nWidth;    }
    virtual void  SetHeight(int nHeight)                { m_Size.cy = nHeight;   }
    // Disable these properties
    virtual void     SetData(LPARAM /*lParam*/)             { ASSERT(FALSE);         }
    virtual void     SetState(DWORD /*nState*/)             { ASSERT(FALSE);         }
    virtual DWORD    GetState() const                       { return CGridCell::GetState()|GVIS_READONLY; }
    virtual void     SetCoords( int /*row*/, int /*col*/)   { /*ASSERT(FALSE);*/         }
    virtual void     SetFont(const LOGFONT* /*plf*/);
    virtual LOGFONT* GetFont() const;
    virtual CFont*   GetFontObject() const;
protected:
    CSize m_Size;       // Default Size
    CFont m_Font;       // Cached font
    DWORD m_dwStyle;    // Cell Style - unused
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
SourceCode/Bond/Servo/GridControl/GridCellBase.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,773 @@
// GridCellBase.cpp : implementation file
//
// MFC Grid Control - Main grid cell base class
//
// Provides the implementation for the base cell type of the
// grid control. No data is stored (except for state) but default
// implementations of drawing, printingetc provided. MUST be derived
// from to be used.
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
// History:
// Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase
// C Maunder     - 19 May 2000 - Fixed sort arrow drawing (Ivan Ilinov)
// C Maunder     - 29 Aug 2000 - operator= checks for NULL font before setting (Martin Richter)
// C Maunder     - 15 Oct 2000 - GetTextExtent fixed (Martin Richter)
// C Maunder     -  1 Jan 2001 - Added ValidateEdit
// Yogurt        - 13 Mar 2004 - GetCellExtent fixed
//
// NOTES: Each grid cell should take care of it's own drawing, though the Draw()
//        method takes an "erase background" paramter that is called if the grid
//        decides to draw the entire grid background in on hit. Certain ambient
//        properties such as the default font to use, and hints on how to draw
//        fixed cells should be fetched from the parent grid. The grid trusts the
//        cells will behave in a certain way, and the cells trust the grid will
//        supply accurate information.
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCtrl.h"
#include "GridCellBase.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CGridCellBase, CObject)
/////////////////////////////////////////////////////////////////////////////
// GridCellBase
CGridCellBase::CGridCellBase()
{
    Reset();
}
CGridCellBase::~CGridCellBase()
{
}
/////////////////////////////////////////////////////////////////////////////
// GridCellBase Operations
void CGridCellBase::Reset()
{
    m_nState  = 0;
}
void CGridCellBase::operator=(const CGridCellBase& cell)
{
    if (this == &cell) return;
    SetGrid(cell.GetGrid());    // do first in case of dependencies
    SetText(cell.GetText());
    SetImage(cell.GetImage());
    SetData(cell.GetData());
    SetState(cell.GetState());
    SetFormat(cell.GetFormat());
    SetTextClr(cell.GetTextClr());
    SetBackClr(cell.GetBackClr());
    SetFont(cell.IsDefaultFont()? NULL : cell.GetFont());
    SetMargin(cell.GetMargin());
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Attributes
// Returns a pointer to a cell that holds default values for this particular type of cell
CGridCellBase* CGridCellBase::GetDefaultCell() const
{
    if (GetGrid())
        return GetGrid()->GetDefaultCell(IsFixedRow(), IsFixedCol());
    return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Operations
// EFW - Various changes to make it draw cells better when using alternate
// color schemes.  Also removed printing references as that's now done
// by PrintCell() and fixed the sort marker so that it doesn't draw out
// of bounds.
BOOL CGridCellBase::Draw(CDC* pDC, int nRow, int nCol, CRect rect,  BOOL bEraseBkgnd /*=TRUE*/)
{
    // Note - all through this function we totally brutalise 'rect'. Do not
    // depend on it's value being that which was passed in.
    CGridCtrl* pGrid = GetGrid();
//    ASSERT(pGrid);
    if (!pGrid || !pDC)
        return FALSE;
    if( rect.Width() <= 0 || rect.Height() <= 0)  // prevents imagelist item from drawing even
        return FALSE;                             //  though cell is hidden
    //TRACE3("Drawing %scell %d, %d\n", IsFixed()? _T("Fixed ") : _T(""), nRow, nCol);
    int nSavedDC = pDC->SaveDC();
    pDC->SetBkMode(TRANSPARENT);
    // Get the default cell implementation for this kind of cell. We use it if this cell
    // has anything marked as "default"
    CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
    if (!pDefaultCell)
        return FALSE;
    // Set up text and background colours
    COLORREF TextClr, TextBkClr;
    TextClr = (GetTextClr() == CLR_DEFAULT)? pDefaultCell->GetTextClr() : GetTextClr();
    if (GetBackClr() == CLR_DEFAULT)
        TextBkClr = pDefaultCell->GetBackClr();
    else
    {
        bEraseBkgnd = TRUE;
        TextBkClr = GetBackClr();
    }
    // Draw cell background and highlighting (if necessary)
    if ( IsFocused() || IsDropHighlighted() )
    {
        // Always draw even in list mode so that we can tell where the
        // cursor is at.  Use the highlight colors though.
        if(GetState() & GVIS_SELECTED)
        {
            TextBkClr = ::GetSysColor(COLOR_HIGHLIGHT);
            TextClr = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
            bEraseBkgnd = TRUE;
        }
        rect.right++; rect.bottom++;    // FillRect doesn't draw RHS or bottom
        if (bEraseBkgnd)
        {
            TRY
            {
                CBrush brush(TextBkClr);
                pDC->FillRect(rect, &brush);
            }
            CATCH(CResourceException, e)
            {
                //e->ReportError();
            }
            END_CATCH
        }
        // Don't adjust frame rect if no grid lines so that the
        // whole cell is enclosed.
        if(pGrid->GetGridLines() != GVL_NONE)
        {
            rect.right--;
            rect.bottom--;
        }
        if (pGrid->GetFrameFocusCell())
        {
                // Use same color as text to outline the cell so that it shows
                // up if the background is black.
            TRY
            {
                CBrush brush(TextClr);
                pDC->FrameRect(rect, &brush);
            }
            CATCH(CResourceException, e)
            {
                //e->ReportError();
            }
            END_CATCH
        }
        pDC->SetTextColor(TextClr);
        // Adjust rect after frame draw if no grid lines
        if(pGrid->GetGridLines() == GVL_NONE)
        {
            rect.right--;
            rect.bottom--;
        }
        //rect.DeflateRect(0,1,1,1);  - Removed by Yogurt
    }
    else if ((GetState() & GVIS_SELECTED))
    {
        rect.right++; rect.bottom++;    // FillRect doesn't draw RHS or bottom
        pDC->FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT));
        rect.right--; rect.bottom--;
        pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
    }
    else
    {
        if (bEraseBkgnd)
        {
            rect.right++; rect.bottom++;    // FillRect doesn't draw RHS or bottom
            CBrush brush(TextBkClr);
            pDC->FillRect(rect, &brush);
            rect.right--; rect.bottom--;
        }
        pDC->SetTextColor(TextClr);
    }
    // Draw lines only when wanted
    if (IsFixed() && pGrid->GetGridLines() != GVL_NONE)
    {
        CCellID FocusCell = pGrid->GetFocusCell();
        // As above, always show current location even in list mode so
        // that we know where the cursor is at.
        BOOL bHiliteFixed = pGrid->GetTrackFocusCell() && pGrid->IsValid(FocusCell) &&
                            (FocusCell.row == nRow || FocusCell.col == nCol);
        // If this fixed cell is on the same row/col as the focus cell,
        // highlight it.
        if (bHiliteFixed)
        {
            rect.right++; rect.bottom++;
            pDC->DrawEdge(rect, BDR_SUNKENINNER /*EDGE_RAISED*/, BF_RECT);
            rect.DeflateRect(1,1);
        }
        else
        {
            CPen lightpen(PS_SOLID, 1,  ::GetSysColor(COLOR_3DHIGHLIGHT)),
                darkpen(PS_SOLID,  1, ::GetSysColor(COLOR_3DDKSHADOW)),
                *pOldPen = pDC->GetCurrentPen();
            pDC->SelectObject(&lightpen);
            pDC->MoveTo(rect.right, rect.top);
            pDC->LineTo(rect.left, rect.top);
            pDC->LineTo(rect.left, rect.bottom);
            pDC->SelectObject(&darkpen);
            pDC->MoveTo(rect.right, rect.top);
            pDC->LineTo(rect.right, rect.bottom);
            pDC->LineTo(rect.left, rect.bottom);
            pDC->SelectObject(pOldPen);
            rect.DeflateRect(1,1);
        }
    }
    // Draw Text and image
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
    if (!pDC->m_bPrinting)
#endif
    {
        CFont *pFont = GetFontObject();
//        ASSERT(pFont);
        if (pFont)
            pDC->SelectObject(pFont);
    }
    //rect.DeflateRect(GetMargin(), 0); - changed by Yogurt
    rect.DeflateRect(GetMargin(), GetMargin());
    rect.right++;
    rect.bottom++;
    if (pGrid->GetImageList() && GetImage() >= 0)
    {
        IMAGEINFO Info;
        if (pGrid->GetImageList()->GetImageInfo(GetImage(), &Info))
        {
            //  would like to use a clipping region but seems to have issue
            //  working with CMemDC directly.  Instead, don't display image
            //  if any part of it cut-off
            //
            // CRgn rgn;
            // rgn.CreateRectRgnIndirect(rect);
            // pDC->SelectClipRgn(&rgn);
            // rgn.DeleteObject();
            /*
            // removed by Yogurt
            int nImageWidth = Info.rcImage.right-Info.rcImage.left+1;
            int nImageHeight = Info.rcImage.bottom-Info.rcImage.top+1;
            if( nImageWidth + rect.left <= rect.right + (int)(2*GetMargin())
                && nImageHeight + rect.top <= rect.bottom + (int)(2*GetMargin())  )
            {
                pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
            }
            */
            // Added by Yogurt
            int nImageWidth = Info.rcImage.right-Info.rcImage.left;
            int nImageHeight = Info.rcImage.bottom-Info.rcImage.top;
            if ((nImageWidth + rect.left <= rect.right) && (nImageHeight + rect.top <= rect.bottom))
                pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
            //rect.left += nImageWidth+GetMargin();
        }
    }
    // Draw sort arrow
    if (pGrid->GetSortColumn() == nCol && nRow == 0)
    {
        CSize size = pDC->GetTextExtent(_T("M"));
        int nOffset = 2;
        // Base the size of the triangle on the smaller of the column
        // height or text height with a slight offset top and bottom.
        // Otherwise, it can get drawn outside the bounds of the cell.
        size.cy -= (nOffset * 2);
        if (size.cy >= rect.Height())
            size.cy = rect.Height() - (nOffset * 2);
        size.cx = size.cy;      // Make the dimensions square
        // Kludge for vertical text
        BOOL bVertical = (GetFont()->lfEscapement == 900);
        // Only draw if it'll fit!
        //if (size.cx + rect.left < rect.right + (int)(2*GetMargin())) - changed / Yogurt
        if (size.cx + rect.left < rect.right)
        {
            int nTriangleBase = rect.bottom - nOffset - size.cy;    // Triangle bottom right
            //int nTriangleBase = (rect.top + rect.bottom - size.cy)/2; // Triangle middle right
            //int nTriangleBase = rect.top + nOffset;                 // Triangle top right
            //int nTriangleLeft = rect.right - size.cx;                 // Triangle RHS
            //int nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
            //int nTriangleLeft = rect.left;                            // Triangle LHS
            int nTriangleLeft;
            if (bVertical)
                nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
            else
                nTriangleLeft = rect.right - size.cx;               // Triangle RHS
            CPen penShadow(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
            CPen penLight(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
            if (pGrid->GetSortAscending())
            {
                // Draw triangle pointing upwards
                CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
                pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
                pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + 1 );
                pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + size.cy + 1);
                pDC->LineTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
                pDC->SelectObject(&penShadow);
                pDC->MoveTo( nTriangleLeft, nTriangleBase + size.cy );
                pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase );
                pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase + size.cy );
                pDC->LineTo( nTriangleLeft, nTriangleBase + size.cy );
                pDC->SelectObject(pOldPen);
            }
            else
            {
                // Draw triangle pointing downwards
                CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
                pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + 1 );
                pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + size.cy + 1 );
                pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + 1 );
                pDC->LineTo( nTriangleLeft + 1, nTriangleBase + 1 );
                pDC->SelectObject(&penShadow);
                pDC->MoveTo( nTriangleLeft, nTriangleBase );
                pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase + size.cy );
                pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase );
                pDC->LineTo( nTriangleLeft, nTriangleBase );
                pDC->SelectObject(pOldPen);
            }
            if (!bVertical)
                rect.right -= size.cy;
        }
    }
    // We want to see '&' characters so use DT_NOPREFIX
    GetTextRect(rect);
    rect.right++;
    rect.bottom++;
    DrawText(pDC->m_hDC, GetText(), -1, rect, GetFormat() | DT_NOPREFIX);
    pDC->RestoreDC(nSavedDC);
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Mouse and Cursor events
// Not yet implemented
void CGridCellBase::OnMouseEnter()
{
//    TRACE0("Mouse entered cell\n");
}
void CGridCellBase::OnMouseOver()
{
    //TRACE0("Mouse over cell\n");
}
// Not Yet Implemented
void CGridCellBase::OnMouseLeave()
{
//    TRACE0("Mouse left cell\n");
}
void CGridCellBase::OnClick( CPoint PointCellRelative)
{
    UNUSED_ALWAYS(PointCellRelative);
//    TRACE2("Mouse Left btn up in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
void CGridCellBase::OnClickDown( CPoint PointCellRelative)
{
    UNUSED_ALWAYS(PointCellRelative);
 //   TRACE2("Mouse Left btn down in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
void CGridCellBase::OnRClick( CPoint PointCellRelative)
{
    UNUSED_ALWAYS(PointCellRelative);
 //   TRACE2("Mouse right-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
void CGridCellBase::OnDblClick( CPoint PointCellRelative)
{
    UNUSED_ALWAYS(PointCellRelative);
//    TRACE2("Mouse double-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
// Return TRUE if you set the cursor
BOOL CGridCellBase::OnSetCursor()
{
#ifndef _WIN32_WCE_NO_CURSOR
    SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
#endif
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase editing
void CGridCellBase::OnEndEdit()
{
//    ASSERT( FALSE);
}
BOOL CGridCellBase::ValidateEdit(LPCTSTR str)
{
    UNUSED_ALWAYS(str);
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Sizing
BOOL CGridCellBase::GetTextRect( LPRECT pRect)  // i/o:  i=dims of cell rect; o=dims of text rect
{
    if (GetImage() >= 0)
    {
        IMAGEINFO Info;
        CGridCtrl* pGrid = GetGrid();
        CImageList* pImageList = pGrid->GetImageList();
        if (pImageList && pImageList->GetImageInfo( GetImage(), &Info))
        {
            int nImageWidth = Info.rcImage.right-Info.rcImage.left+1;
            pRect->left += nImageWidth + GetMargin();
        }
    }
    return TRUE;
}
// By default this uses the selected font (which is a bigger font)
CSize CGridCellBase::GetTextExtent(LPCTSTR szText, CDC* pDC /*= NULL*/)
{
    CGridCtrl* pGrid = GetGrid();
//    ASSERT(pGrid);
    BOOL bReleaseDC = FALSE;
    if (pDC == NULL || szText == NULL)
    {
        if (szText)
            pDC = pGrid->GetDC();
        if (pDC == NULL || szText == NULL)
        {
            CGridDefaultCell* pDefCell = (CGridDefaultCell*) GetDefaultCell();
//            ASSERT(pDefCell);
            return CSize(pDefCell->GetWidth(), pDefCell->GetHeight());
        }
        bReleaseDC = TRUE;
    }
    CFont *pOldFont = NULL,
          *pFont = GetFontObject();
    if (pFont)
        pOldFont = pDC->SelectObject(pFont);
    CSize size;
    int nFormat = GetFormat();
    // If the cell is a multiline cell, then use the width of the cell
    // to get the height
    if ((nFormat & DT_WORDBREAK) && !(nFormat & DT_SINGLELINE))
    {
        CString str = szText;
        int nMaxWidth = 0;
        while (TRUE)
        {
            int nPos = str.Find(_T('\n'));
            CString TempStr = (nPos < 0)? str : str.Left(nPos);
            int nTempWidth = pDC->GetTextExtent(TempStr).cx;
            if (nTempWidth > nMaxWidth)
                nMaxWidth = nTempWidth;
            if (nPos < 0)
                break;
            str = str.Mid(nPos + 1);    // Bug fix by Thomas Steinborn
        }
        CRect rect;
        rect.SetRect(0,0, nMaxWidth+1, 0);
        pDC->DrawText(szText, -1, rect, nFormat | DT_CALCRECT);
        size = rect.Size();
    }
    else
        size = pDC->GetTextExtent(szText, (int)_tcslen(szText));
    // Removed by Yogurt
    //TEXTMETRIC tm;
    //pDC->GetTextMetrics(&tm);
    //size.cx += (tm.tmOverhang);
    if (pOldFont)
        pDC->SelectObject(pOldFont);
    size += CSize(2*GetMargin(), 2*GetMargin());
    // Kludge for vertical text
    LOGFONT *pLF = GetFont();
    if (pLF->lfEscapement == 900 || pLF->lfEscapement == -900)
    {
        int nTemp = size.cx;
        size.cx = size.cy;
        size.cy = nTemp;
        size += CSize(0, 4*GetMargin());
    }
    if (bReleaseDC)
        pGrid->ReleaseDC(pDC);
    return size;
}
CSize CGridCellBase::GetCellExtent(CDC* pDC)
{
    CSize size = GetTextExtent(GetText(), pDC);
    CSize ImageSize(0,0);
    int nImage = GetImage();
    if (nImage >= 0)
    {
        CGridCtrl* pGrid = GetGrid();
//        ASSERT(pGrid);
        IMAGEINFO Info;
        if (pGrid->GetImageList() && pGrid->GetImageList()->GetImageInfo(nImage, &Info))
        {
            ImageSize = CSize(Info.rcImage.right-Info.rcImage.left,
                Info.rcImage.bottom-Info.rcImage.top);
            if (size.cx > 2*(int)GetMargin ())
                ImageSize.cx += GetMargin();
            ImageSize.cy += 2*(int)GetMargin ();
        }
    }
    size.cx += ImageSize.cx + 1;
    size.cy = max(size.cy, ImageSize.cy) + 1;
    if (IsFixed())
    {
        size.cx++;
        size.cy++;
    }
    return size;
}
// EFW - Added to print cells so that grids that use different colors are
// printed correctly.
BOOL CGridCellBase::PrintCell(CDC* pDC, int /*nRow*/, int /*nCol*/, CRect rect)
{
#if defined(_WIN32_WCE_NO_PRINTING) || defined(GRIDCONTROL_NO_PRINTING)
    return FALSE;
#else
    COLORREF crFG, crBG;
    GV_ITEM Item;
    CGridCtrl* pGrid = GetGrid();
    if (!pGrid || !pDC)
        return FALSE;
    if( rect.Width() <= 0
        || rect.Height() <= 0)  // prevents imagelist item from drawing even
        return FALSE;           //  though cell is hidden
    int nSavedDC = pDC->SaveDC();
    pDC->SetBkMode(TRANSPARENT);
    if (pGrid->GetShadedPrintOut())
    {
        // Get the default cell implementation for this kind of cell. We use it if this cell
        // has anything marked as "default"
        CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
        if (!pDefaultCell)
            return FALSE;
        // Use custom color if it doesn't match the default color and the
        // default grid background color.  If not, leave it alone.
        if(IsFixed())
            crBG = (GetBackClr() != CLR_DEFAULT) ? GetBackClr() : pDefaultCell->GetBackClr();
        else
            crBG = (GetBackClr() != CLR_DEFAULT && GetBackClr() != pDefaultCell->GetBackClr()) ?
                GetBackClr() : CLR_DEFAULT;
        // Use custom color if the background is different or if it doesn't
        // match the default color and the default grid text color.
        if(IsFixed())
            crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr();
        else
            crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr();
        // If not printing on a color printer, adjust the foreground color
        // to a gray scale if the background color isn't used so that all
        // colors will be visible.  If not, some colors turn to solid black
        // or white when printed and may not show up.  This may be caused by
        // coarse dithering by the printer driver too (see image note below).
        if(pDC->GetDeviceCaps(NUMCOLORS) == 2 && crBG == CLR_DEFAULT)
            crFG = RGB(GetRValue(crFG) * 0.30, GetGValue(crFG) * 0.59,
                GetBValue(crFG) * 0.11);
        // Only erase the background if the color is not the default
        // grid background color.
        if(crBG != CLR_DEFAULT)
        {
            CBrush brush(crBG);
            rect.right++; rect.bottom++;
            pDC->FillRect(rect, &brush);
            rect.right--; rect.bottom--;
        }
    }
    else
    {
        crBG = CLR_DEFAULT;
        crFG = RGB(0, 0, 0);
    }
    pDC->SetTextColor(crFG);
    CFont *pFont = GetFontObject();
    if (pFont)
        pDC->SelectObject(pFont);
    /*
    // ***************************************************
    // Disabled - if you need this functionality then you'll need to rewrite.
    // Create the appropriate font and select into DC.
    CFont Font;
    // Bold the fixed cells if not shading the print out.  Use italic
    // font it it is enabled.
    const LOGFONT* plfFont = GetFont();
    if(IsFixed() && !pGrid->GetShadedPrintOut())
    {
        Font.CreateFont(plfFont->lfHeight, 0, 0, 0, FW_BOLD, plfFont->lfItalic, 0, 0,
            ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
#ifndef _WIN32_WCE
            PROOF_QUALITY,
#else
            DEFAULT_QUALITY,
#endif
            VARIABLE_PITCH | FF_SWISS, plfFont->lfFaceName);
    }
    else
        Font.CreateFontIndirect(plfFont);
    pDC->SelectObject(&Font);
    // ***************************************************
    */
    // Draw lines only when wanted on fixed cells.  Normal cell grid lines
    // are handled in OnPrint.
    if(pGrid->GetGridLines() != GVL_NONE && IsFixed())
    {
        CPen lightpen(PS_SOLID, 1,  ::GetSysColor(COLOR_3DHIGHLIGHT)),
             darkpen(PS_SOLID,  1, ::GetSysColor(COLOR_3DDKSHADOW)),
            *pOldPen = pDC->GetCurrentPen();
        pDC->SelectObject(&lightpen);
        pDC->MoveTo(rect.right, rect.top);
        pDC->LineTo(rect.left, rect.top);
        pDC->LineTo(rect.left, rect.bottom);
        pDC->SelectObject(&darkpen);
        pDC->MoveTo(rect.right, rect.top);
        pDC->LineTo(rect.right, rect.bottom);
        pDC->LineTo(rect.left, rect.bottom);
        rect.DeflateRect(1,1);
        pDC->SelectObject(pOldPen);
    }
    rect.DeflateRect(GetMargin(), 0);
    if(pGrid->GetImageList() && GetImage() >= 0)
    {
        // NOTE: If your printed images look like fuzzy garbage, check the
        //       settings on your printer driver.  If it's using coarse
        //       dithering and/or vector graphics, they may print wrong.
        //       Changing to fine dithering and raster graphics makes them
        //       print properly.  My HP 4L had that problem.
        IMAGEINFO Info;
        if(pGrid->GetImageList()->GetImageInfo(GetImage(), &Info))
        {
            int nImageWidth = Info.rcImage.right-Info.rcImage.left;
            pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
            rect.left += nImageWidth+GetMargin();
        }
    }
    // Draw without clipping so as not to lose text when printed for real
    // DT_NOCLIP removed 01.01.01. Slower, but who cares - we are printing!
    DrawText(pDC->m_hDC, GetText(), -1, rect,
        GetFormat() | /*DT_NOCLIP | */ DT_NOPREFIX);
    pDC->RestoreDC(nSavedDC);
    return TRUE;
#endif
}
/*****************************************************************************
Callable by derived classes, only
*****************************************************************************/
LRESULT CGridCellBase::SendMessageToParent(int nRow, int nCol, int nMessage)
{
    CGridCtrl* pGrid = GetGrid();
    if( pGrid)
        return pGrid->SendMessageToParent(nRow, nCol, nMessage);
    else
        return 0;
}
SourceCode/Bond/Servo/GridControl/GridCellBase.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,172 @@
/////////////////////////////////////////////////////////////////////////////
// GridCellBase.h : header file
//
// MFC Grid Control - Grid cell base class header file
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CGridCtrl;
// Cell states
#define GVIS_FOCUSED            0x0001
#define GVIS_SELECTED           0x0002
#define GVIS_DROPHILITED        0x0004
#define GVIS_READONLY           0x0008
#define GVIS_FIXED              0x0010
#define GVIS_FIXEDROW           0x0020
#define GVIS_FIXEDCOL           0x0040
#define GVIS_MODIFIED           0x0080
// Cell data mask
#define GVIF_TEXT               LVIF_TEXT
#define GVIF_IMAGE              LVIF_IMAGE
#define GVIF_PARAM              LVIF_PARAM
#define GVIF_STATE              LVIF_STATE
#define GVIF_BKCLR              (GVIF_STATE<<1)
#define GVIF_FGCLR              (GVIF_STATE<<2)
#define GVIF_FORMAT             (GVIF_STATE<<3)
#define GVIF_FONT               (GVIF_STATE<<4)
#define GVIF_MARGIN             (GVIF_STATE<<5)
#define GVIF_ALL                (GVIF_TEXT|GVIF_IMAGE|GVIF_PARAM|GVIF_STATE|GVIF_BKCLR|GVIF_FGCLR| \
                                 GVIF_FORMAT|GVIF_FONT|GVIF_MARGIN)
// Used for Get/SetItem calls.
typedef struct _GV_ITEM {
    int      row,col;     // Row and Column of item
    UINT     mask;        // Mask for use in getting/setting cell data
    UINT     nState;      // cell state (focus/hilighted etc)
    DWORD    nFormat;     // Format of cell
    int      iImage;      // index of the list view item抯 icon
    COLORREF crBkClr;     // Background colour (or CLR_DEFAULT)
    COLORREF crFgClr;     // Forground colour (or CLR_DEFAULT)
    LPARAM   lParam;      // 32-bit value to associate with item
    LOGFONT  lfFont;      // Cell font
    UINT     nMargin;     // Internal cell margin
    CString  strText;     // Text in cell
} GV_ITEM;
// Each cell contains one of these. Fields "row" and "column" are not stored since we
// will usually have acces to them in other ways, and they are an extra 8 bytes per
// cell that is probably unnecessary.
class CGridCellBase : public CObject
{
    friend class CGridCtrl;
    DECLARE_DYNAMIC(CGridCellBase)
// Construction/Destruction
public:
    CGridCellBase();
    virtual ~CGridCellBase();
// Attributes
public:
    virtual void SetText(LPCTSTR /* szText */)              = 0 ;
    virtual void SetImage(int /* nImage */)                 = 0 ;
    virtual void SetData(LPARAM /* lParam */)               = 0 ;
    virtual void SetState(DWORD nState)                     { m_nState = nState; }
    virtual void SetFormat(DWORD /* nFormat */)             = 0 ;
    virtual void SetTextClr(COLORREF /* clr */)             = 0 ;
    virtual void SetBackClr(COLORREF /* clr */)             = 0 ;
    virtual void SetFont(const LOGFONT* /* plf */)          = 0 ;
    virtual void SetMargin( UINT /* nMargin */)             = 0 ;
    virtual void SetGrid(CGridCtrl* /* pGrid */)            = 0 ;
    virtual void SetCoords( int /* nRow */, int /* nCol */) = 0 ;
    virtual LPCTSTR    GetText()       const                = 0 ;
    virtual LPCTSTR    GetTipText()    const                { return GetText(); } // may override TitleTip return
    virtual int        GetImage()      const                = 0 ;
    virtual LPARAM     GetData()       const                = 0 ;
    virtual DWORD      GetState()      const                { return m_nState;  }
    virtual DWORD      GetFormat()     const                = 0 ;
    virtual COLORREF   GetTextClr()    const                = 0 ;
    virtual COLORREF   GetBackClr()    const                = 0 ;
    virtual LOGFONT  * GetFont()       const                = 0 ;
    virtual CFont    * GetFontObject() const                = 0 ;
    virtual CGridCtrl* GetGrid()       const                = 0 ;
    virtual CWnd     * GetEditWnd()    const                = 0 ;
    virtual UINT       GetMargin()     const                = 0 ;
    virtual CGridCellBase* GetDefaultCell() const;
    virtual BOOL IsDefaultFont()       const                = 0 ;
    virtual BOOL IsEditing()           const                = 0 ;
    virtual BOOL IsFocused()           const                { return (m_nState & GVIS_FOCUSED);  }
    virtual BOOL IsFixed()             const                { return (m_nState & GVIS_FIXED);    }
    virtual BOOL IsFixedCol()          const                { return (m_nState & GVIS_FIXEDCOL); }
    virtual BOOL IsFixedRow()          const                { return (m_nState & GVIS_FIXEDROW); }
    virtual BOOL IsSelected()          const                { return (m_nState & GVIS_SELECTED); }
    virtual BOOL IsReadOnly()          const                { return (m_nState & GVIS_READONLY); }
    virtual BOOL IsModified()          const                { return (m_nState & GVIS_MODIFIED); }
    virtual BOOL IsDropHighlighted()   const                { return (m_nState & GVIS_DROPHILITED); }
// Operators
public:
    virtual void operator=(const CGridCellBase& cell);
// Operations
public:
    virtual void Reset();
    virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
    virtual BOOL GetTextRect( LPRECT pRect);    // i/o:  i=dims of cell rect; o=dims of text rect
    virtual BOOL GetTipTextRect( LPRECT pRect) { return GetTextRect( pRect); }  // may override for btns, etc.
    virtual CSize GetTextExtent(LPCTSTR str, CDC* pDC = NULL);
    virtual CSize GetCellExtent(CDC* pDC);
    // Editing
    virtual BOOL Edit( int /* nRow */, int /* nCol */, CRect /* rect */, CPoint /* point */,
                       UINT /* nID */, UINT /* nChar */) { return FALSE;}
    virtual BOOL ValidateEdit(LPCTSTR str);
    virtual void EndEdit() {}
    // EFW - Added to print cells properly
    virtual BOOL PrintCell(CDC* pDC, int nRow, int nCol, CRect rect);
    // add additional protected grid members required of cells
    LRESULT SendMessageToParent(int nRow, int nCol, int nMessage);
protected:
    virtual void OnEndEdit();
    virtual void OnMouseEnter();
    virtual void OnMouseOver();
    virtual void OnMouseLeave();
    virtual void OnClick( CPoint PointCellRelative);
    virtual void OnClickDown( CPoint PointCellRelative);
    virtual void OnRClick( CPoint PointCellRelative);
    virtual void OnDblClick( CPoint PointCellRelative);
    virtual BOOL OnSetCursor();
protected:
    DWORD    m_nState;      // Cell state (selected/focus etc)
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
SourceCode/Bond/Servo/GridControl/GridCellButton.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
#include "stdafx.h"
#include "GridCell.h"
#include "GridCtrl.h"
#include "GridCellButton.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CGridCellButton, CGridCell)
    CGridCellButton::CGridCellButton(void)
{
    m_bPushing = FALSE;
}
CGridCellButton::~CGridCellButton(void)
{
}
BOOL CGridCellButton::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /* = TRUE */)
{
    m_rect = rect;
    pDC->SetBkMode(TRANSPARENT);
    rect.DeflateRect(GetMargin(), 0);
    CFont* pOldFont = pDC->SelectObject(GetFontObject());
    pDC->DrawFrameControl(rect, DFC_BUTTON, m_bPushing ? DFCS_BUTTONPUSH | DFCS_PUSHED : DFCS_BUTTONPUSH);
    COLORREF ColorCurrent = pDC->GetTextColor();
    pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
    pDC->DrawText(GetText(), -1, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    pDC->SetTextColor(ColorCurrent);
    return TRUE;
}
void CGridCellButton::OnClick(CPoint PointCellRelative)
{
    m_bPushing = !m_bPushing;
    GetGrid()->InvalidateRect(m_rect);
}
void CGridCellButton::OnMouseLeave()
{
    m_bPushing = FALSE;
    GetGrid()->InvalidateRect(m_rect);
}
SourceCode/Bond/Servo/GridControl/GridCellButton.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
#ifndef __GRID_CELL_BUTTON__
#define __GRID_CELL_BUTTON__
#include "GridCell.h"
class CGridCellButton : public CGridCell
{
    friend class CGridCtrl;
    DECLARE_DYNCREATE(CGridCellButton)
public:
    CGridCellButton(void);
    virtual ~CGridCellButton(void);
    void SetPushing(BOOL bPush) {m_bPushing = bPush;}
public:
    virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
protected:
    virtual void OnClick(CPoint PointCellRelative);
    virtual void OnMouseLeave();
protected:
    CRect m_rect;
    BOOL m_bPushing;
};
#endif
SourceCode/Bond/Servo/GridControl/GridCtrl.cpp
¶Ô±ÈÐÂÎļþ
ÎļþÌ«´ó
SourceCode/Bond/Servo/GridControl/GridCtrl.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1090 @@
/////////////////////////////////////////////////////////////////////////////
// GridCtrl.h : header file
//
// MFC Grid Control - main header
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
//////////////////////////////////////////////////////////////////////
// FEATURES BY Mukit, Ataul (2007-11-17):
// 1. Merge Cell
// 2. Ability to do XL Style Freeze Pane
// 3. The Horizontal Gray Area Removed
// FINDINGS:
// 1. A cell cannot be edited if a tooltip is shown..
// 2. The InplaceEditCtrl is not multiline even if a cell can contain Multiline Text..
// 3. If a cell is too small, the InplaceEditCtrl is almost invisible..
#if !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include "CellRange.h"
#include "GridCell.h"
#include <afxtempl.h>
#include <vector>
using namespace std;
struct CELL_ENABLE
{
    CELL_ENABLE()
    {
        nEnable = -1;
    }
    void SetEnable(BOOL bValue)
    {
        nEnable = bValue;
    }
    BOOL isEnable()
    {
        if (nEnable > 0)
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
    BOOL isActivated()
    {
        if (nEnable < 0)
        {
            return FALSE;
        }
        else
        {
            return TRUE;
        }
    }
    int nEnable;
};
///////////////////////////////////////////////////////////////////////////////////
// Defines - these determine the features (and the final size) of the final code
///////////////////////////////////////////////////////////////////////////////////
//#define GRIDCONTROL_NO_TITLETIPS   // Do not use titletips for cells with large data
//#define GRIDCONTROL_NO_DRAGDROP    // Do not use OLE drag and drop
//#define GRIDCONTROL_NO_CLIPBOARD   // Do not use clipboard routines
#ifdef _WIN32_WCE
#   define GRIDCONTROL_NO_TITLETIPS   // Do not use titletips for cells with large data
#   define GRIDCONTROL_NO_DRAGDROP    // Do not use OLE drag and drop
#   define GRIDCONTROL_NO_CLIPBOARD   // Do not use clipboard routines
#   define GRIDCONTROL_NO_PRINTING    // Do not use printing routines
#   ifdef WCE_NO_PRINTING              // Older versions of CE had different #def's
#       define _WIN32_WCE_NO_PRINTING
#   endif
#   ifdef WCE_NO_CURSOR
#       define _WIN32_WCE_NO_CURSOR
#   endif
#endif  // _WIN32_WCE
// Use this as the classname when inserting this control as a custom control
// in the MSVC++ dialog editor
#define GRIDCTRL_CLASSNAME    _T("MFCGridCtrl")  // Window class name
#define IDC_INPLACE_CONTROL   8                  // ID of inplace edit controls
///////////////////////////////////////////////////////////////////////////////////
// Conditional includes
///////////////////////////////////////////////////////////////////////////////////
#ifndef GRIDCONTROL_NO_TITLETIPS
#   include "TitleTip.h"
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
#   include "GridDropTarget.h"
#   undef GRIDCONTROL_NO_CLIPBOARD     // Force clipboard functions on
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
#   include <afxole.h>
#endif
///////////////////////////////////////////////////////////////////////////////////
// Helper functions
///////////////////////////////////////////////////////////////////////////////////
// Handy functions
#define IsSHIFTpressed() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0   )
#define IsCTRLpressed()  ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 )
// Backwards compatibility for pre 2.20 grid versions
#define DDX_GridControl(pDX, nIDC, rControl)  DDX_Control(pDX, nIDC, rControl)
///////////////////////////////////////////////////////////////////////////////////
// Structures
///////////////////////////////////////////////////////////////////////////////////
// This structure sent to Grid's parent in a WM_NOTIFY message
typedef struct tagNM_GRIDVIEW {
    NMHDR hdr;
    int   iRow;
    int   iColumn;
} NM_GRIDVIEW;
// This is sent to the Grid from child in-place edit controls
typedef struct tagGV_DISPINFO {
    NMHDR   hdr;
    GV_ITEM item;
} GV_DISPINFO;
// This is sent to the Grid from child in-place edit controls
typedef struct tagGV_CACHEHINT {
    NMHDR      hdr;
    CCellRange range;
} GV_CACHEHINT;
// storage typedef for each row in the grid
typedef CTypedPtrArray<CObArray, CGridCellBase*> GRID_ROW;
// For virtual mode callback
typedef BOOL (CALLBACK* GRIDCALLBACK)(GV_DISPINFO *, LPARAM);
///////////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////////
// Grid line/scrollbar selection
#define GVL_NONE                0L      // Neither
#define GVL_HORZ                1L      // Horizontal line or scrollbar
#define GVL_VERT                2L      // Vertical line or scrollbar
#define GVL_BOTH                3L      // Both
// Autosizing option
#define GVS_DEFAULT             0
#define GVS_HEADER              1       // Size using column fixed cells data only
#define GVS_DATA                2       // Size using column non-fixed cells data only
#define GVS_BOTH                3       // Size using column fixed and non-fixed
// Cell Searching options
#define GVNI_FOCUSED            0x0001
#define GVNI_SELECTED           0x0002
#define GVNI_DROPHILITED        0x0004
#define GVNI_READONLY           0x0008
#define GVNI_FIXED              0x0010
#define GVNI_MODIFIED           0x0020
// LUC
#define GVNI_FREEZED            0x0040
#define GVNI_ABOVE              LVNI_ABOVE
#define GVNI_BELOW              LVNI_BELOW
#define GVNI_TOLEFT             LVNI_TOLEFT
#define GVNI_TORIGHT            LVNI_TORIGHT
#define GVNI_ALL                (LVNI_BELOW|LVNI_TORIGHT|LVNI_TOLEFT)
#define GVNI_AREA               (LVNI_BELOW|LVNI_TORIGHT)
// Hit test values (not yet implemented)
#define GVHT_DATA               0x0000
#define GVHT_TOPLEFT            0x0001
#define GVHT_COLHDR             0x0002
#define GVHT_ROWHDR             0x0004
#define GVHT_COLSIZER           0x0008
#define GVHT_ROWSIZER           0x0010
#define GVHT_LEFT               0x0020
#define GVHT_RIGHT              0x0040
#define GVHT_ABOVE              0x0080
#define GVHT_BELOW              0x0100
// Messages sent to the grid's parent (More will be added in future)
#define GVN_BEGINDRAG           LVN_BEGINDRAG        // LVN_FIRST-9
#define GVN_BEGINLABELEDIT      LVN_BEGINLABELEDIT   // LVN_FIRST-5
#define GVN_BEGINRDRAG          LVN_BEGINRDRAG
#define GVN_COLUMNCLICK         LVN_COLUMNCLICK
#define GVN_DELETEITEM          LVN_DELETEITEM
#define GVN_ENDLABELEDIT        LVN_ENDLABELEDIT     // LVN_FIRST-6
#define GVN_SELCHANGING         LVN_ITEMCHANGING
#define GVN_SELCHANGED          LVN_ITEMCHANGED
#define GVN_GETDISPINFO         LVN_GETDISPINFO
#define GVN_ODCACHEHINT         LVN_ODCACHEHINT
#define GVN_COMBOSELCHANGE        LVN_FIRST-10
class CGridCtrl;
/////////////////////////////////////////////////////////////////////////////
// CGridCtrl window
typedef bool (*PVIRTUALCOMPARE)(int, int);
class CGridCtrl : public CWnd
{
    DECLARE_DYNCREATE(CGridCtrl)
    friend class CGridCell;
    friend class CGridCellBase;
// Construction
public:
    CGridCtrl(int nRows = 0, int nCols = 0, int nFixedRows = 0, int nFixedCols = 0);
    BOOL Create(const RECT& rect, CWnd* parent, UINT nID,
                DWORD dwStyle = WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VISIBLE);
///////////////////////////////////////////////////////////////////////////////////
// Attributes
///////////////////////////////////////////////////////////////////////////////////
public:
///// LUC ///////////////////////////////////////////////////////////////////////
    //// LUC : MergeCell////////
    INT_PTR MergeCells(CCellRange& mergedCellRange);
    void SplitCells(INT_PTR nMergeID);
    BOOL IsMergedCell(int row, int col, CCellRange& mergedCellRange);
    BOOL GetMergedCellRect(int row, int col, CRect& rect);
    BOOL GetMergedCellRect(CCellRange& mergedCell, CRect& rect);
    BOOL GetTopLeftMergedCell(int& row, int& col, CRect& mergeRect);
    BOOL GetBottomRightMergedCell(int& row, int& col, CRect& mergeRect);
    virtual BOOL IsFocused(CGridCellBase& cell, int nRow, int nCol);
    virtual BOOL IsSelected(CGridCellBase& cell, int nRow, int nCol);
    BOOL    m_bDrawingMergedCell;
    INT_PTR    m_nCurrentMergeID;
    static CRect rectNull;
    static CCellID cellNull;
    // LUC : Freeze Rows
    BOOL SetFreezedRowCount(int nFreezedRows)
    {
        BOOL bRet = FALSE;
        if( (nFreezedRows >= 0) && ((nFreezedRows + m_nFixedRows) <= m_nRows) )
        {
            m_nFreezedRows = nFreezedRows;
            ResetScrollBars();
            Refresh();
            bRet = TRUE;
        }
        return bRet;
    }
    BOOL SetFreezedColumnCount(int nFreezedCols)
    {
        BOOL bRet = FALSE;
        if( (nFreezedCols >= 0) && ((nFreezedCols + m_nFixedCols) <= m_nCols) )
        {
            m_nFreezedCols = nFreezedCols;
            ResetScrollBars();
            Refresh();
            bRet = TRUE;
        }
        return bRet;
    }
    // To avoid calling ResetScrollBars twice you can use SetFreezedFrame
    BOOL SetFreezedFrame(int nFreezedRows, int nFreezedCols)
    {
        BOOL bRet = FALSE;
        if( (nFreezedRows >= 0) && ((nFreezedRows + m_nFixedRows) <= m_nRows) )
        {
            m_nFreezedRows = nFreezedRows;
            bRet = TRUE;
        }
        if( (nFreezedCols >= 0) && ((nFreezedCols + m_nFixedCols) <= m_nCols) )
        {
            m_nFreezedCols = nFreezedCols;
            bRet = TRUE;
        }
        else
        {
            bRet = FALSE;
        }
        ResetScrollBars();
        return bRet;
    }
    int  GetFreezedRowCount() const                    { return m_nFreezedRows; }
    int  GetFreezedColumnCount() const                 { return m_nFreezedCols; }
    void ShowHorzNonGridArea(BOOL bShow)
    {
        m_bShowHorzNonGridArea = bShow;
    }
    BOOL IsShowingHorzNonGridArea()
    {
        return m_bShowHorzNonGridArea;
    }
///////////////////////////////////////////////////////////////////////////////////////
    int  GetRowCount() const                    { return m_nRows; }
    int  GetColumnCount() const                 { return m_nCols; }
    int  GetFixedRowCount(BOOL bIncludeFreezedRows = FALSE) const
    {
        return (bIncludeFreezedRows) ? (m_nFixedRows + m_nFreezedRows) : m_nFixedRows;
    }
    int  GetFixedColumnCount(BOOL bIncludeFreezedCols = FALSE) const
    {
        return (bIncludeFreezedCols) ? (m_nFixedCols + m_nFreezedCols) : m_nFixedCols;
    }
    BOOL SetRowCount(int nRows = 10);
    BOOL SetColumnCount(int nCols = 10);
    BOOL UpdateCellEditableMask();
    BOOL SetFixedRowCount(int nFixedRows = 1);
    BOOL SetFixedColumnCount(int nFixedCols = 1);
public:
    int  GetRowHeight(int nRow) const;
    BOOL SetRowHeight(int row, int height);
    int  GetColumnWidth(int nCol) const;
    BOOL SetColumnWidth(int col, int width);
    BOOL GetCellOrigin(int nRow, int nCol, LPPOINT p);
    BOOL GetCellOrigin(const CCellID& cell, LPPOINT p);
    BOOL GetCellRect(int nRow, int nCol, LPRECT pRect);
    BOOL GetCellRect(const CCellID& cell, LPRECT pRect);
    BOOL GetTextRect(const CCellID& cell, LPRECT pRect);
    BOOL GetTextRect(int nRow, int nCol, LPRECT pRect);
    BOOL SetCellMaskEditable(int nRow, int nCol, BOOL bEditable);
    BOOL isCellMaskEditable(int nRow, int nCol);
    BOOL isCellMaskActivated(int nRow, int nCol);
    // LUC
    // Change for MergeCell
    CCellID GetCellFromPt(CPoint point, BOOL bAllowFixedCellCheck = TRUE, CCellID& cellOriginal = cellNull);
    // LUC
    //int  GetFixedRowHeight() const;
    //int  GetFixedColumnWidth() const;
    int    GetFixedRowHeight(BOOL bIncludeFreezedRows = FALSE) const;
    int GetFixedColumnWidth(BOOL bIncludeFreezedCols = FALSE) const;
    long GetVirtualWidth() const;
    long GetVirtualHeight() const;
    CSize GetTextExtent(int nRow, int nCol, LPCTSTR str);
    // EFW - Get extent of current text in cell
    inline CSize GetCellTextExtent(int nRow, int nCol)  { return GetTextExtent(nRow, nCol, GetItemText(nRow,nCol)); }
    void     SetGridBkColor(COLORREF clr)         { m_crGridBkColour = clr;           }
    COLORREF GetGridBkColor() const               { return m_crGridBkColour;          }
    void     SetGridLineColor(COLORREF clr)       { m_crGridLineColour = clr;         }
    COLORREF GetGridLineColor() const             { return m_crGridLineColour;        }
    void     SetTitleTipBackClr(COLORREF clr = CLR_DEFAULT) { m_crTTipBackClr = clr;  }
    COLORREF GetTitleTipBackClr()                            { return m_crTTipBackClr; }
    void     SetTitleTipTextClr(COLORREF clr = CLR_DEFAULT) { m_crTTipTextClr = clr;  }
    COLORREF GetTitleTipTextClr()                            { return m_crTTipTextClr; }
    // ***************************************************************************** //
    // These have been deprecated. Use GetDefaultCell and then set the colors
    void     SetTextColor(COLORREF clr)      { m_cellDefault.SetTextClr(clr);        }
    COLORREF GetTextColor()                  { return m_cellDefault.GetTextClr();    }
    void     SetTextBkColor(COLORREF clr)    { m_cellDefault.SetBackClr(clr);        }
    COLORREF GetTextBkColor()                { return m_cellDefault.GetBackClr();    }
    void     SetFixedTextColor(COLORREF clr) { m_cellFixedRowDef.SetTextClr(clr);
                                               m_cellFixedColDef.SetTextClr(clr);
                                               m_cellFixedRowColDef.SetTextClr(clr); }
    COLORREF GetFixedTextColor() const       { return m_cellFixedRowDef.GetTextClr(); }
    void     SetFixedBkColor(COLORREF clr)   { m_cellFixedRowDef.SetBackClr(clr);
                                               m_cellFixedColDef.SetBackClr(clr);
                                               m_cellFixedRowColDef.SetBackClr(clr); }
    COLORREF GetFixedBkColor() const         { return m_cellFixedRowDef.GetBackClr(); }
    void     SetGridColor(COLORREF clr)      { SetGridLineColor(clr);                }
    COLORREF GetGridColor()                  { return GetGridLineColor();            }
    void     SetBkColor(COLORREF clr)        { SetGridBkColor(clr);                  }
    COLORREF GetBkColor()                    { return GetGridBkColor();              }
    void     SetDefCellMargin( int nMargin)  { m_cellDefault.SetMargin(nMargin);
                                               m_cellFixedRowDef.SetMargin(nMargin);
                                               m_cellFixedColDef.SetMargin(nMargin);
                                               m_cellFixedRowColDef.SetMargin(nMargin); }
    int      GetDefCellMargin() const        { return m_cellDefault.GetMargin();     }
    int      GetDefCellHeight() const        { return m_cellDefault.GetHeight();     }
    void     SetDefCellHeight(int nHeight)   { m_cellDefault.SetHeight(nHeight);
                                               m_cellFixedRowDef.SetHeight(nHeight);
                                               m_cellFixedColDef.SetHeight(nHeight);
                                               m_cellFixedRowColDef.SetHeight(nHeight); }
    int      GetDefCellWidth() const         { return m_cellDefault.GetWidth();     }
    void     SetDefCellWidth(int nWidth)     { m_cellDefault.SetWidth(nWidth);
                                               m_cellFixedRowDef.SetWidth(nWidth);
                                               m_cellFixedColDef.SetWidth(nWidth);
                                               m_cellFixedRowColDef.SetWidth(nWidth); }
    // ***************************************************************************** //
    int GetSelectedCount() const                  { return (int)m_SelectedCellMap.GetCount(); }
    CCellID SetFocusCell(CCellID cell);
    CCellID SetFocusCell(int nRow, int nCol);
    CCellID GetFocusCell() const                  { return m_idCurrentCell;           }
    void SetVirtualMode(BOOL bVirtual);
    BOOL GetVirtualMode() const                   { return m_bVirtualMode;            }
    void SetCallbackFunc(GRIDCALLBACK pCallback,
                         LPARAM lParam)           { m_pfnCallback = pCallback; m_lParam = lParam; }
    GRIDCALLBACK GetCallbackFunc()                { return m_pfnCallback;             }
    void SetImageList(CImageList* pList)          { m_pImageList = pList;             }
    CImageList* GetImageList() const              { return m_pImageList;              }
    void SetGridLines(int nWhichLines = GVL_BOTH);
    int  GetGridLines() const                     { return m_nGridLines;              }
    void SetEditable(BOOL bEditable = TRUE)       { m_bEditable = bEditable;          }
    BOOL IsEditable() const                       { return m_bEditable;               }
    void SetListMode(BOOL bEnableListMode = TRUE);
    BOOL GetListMode() const                      { return m_bListMode;               }
    void SetSingleRowSelection(BOOL bSing = TRUE) { m_bSingleRowSelection = bSing;    }
    BOOL GetSingleRowSelection()                  { return m_bSingleRowSelection & m_bListMode; }
    void SetSingleColSelection(BOOL bSing = TRUE) { m_bSingleColSelection = bSing;    }
    BOOL GetSingleColSelection()                  { return m_bSingleColSelection;     }
    void EnableSelection(BOOL bEnable = TRUE)     { ResetSelectedRange(); m_bEnableSelection = bEnable; ResetSelectedRange(); }
    BOOL IsSelectable() const                     { return m_bEnableSelection;        }
    void SetFixedColumnSelection(BOOL bSelect)    { m_bFixedColumnSelection = bSelect;}
    BOOL GetFixedColumnSelection()                { return m_bFixedColumnSelection;   }
    void SetFixedRowSelection(BOOL bSelect)       { m_bFixedRowSelection = bSelect;   }
    BOOL GetFixedRowSelection()                   { return m_bFixedRowSelection;      }
    void EnableDragAndDrop(BOOL bAllow = TRUE)    { m_bAllowDragAndDrop = bAllow;     }
    BOOL GetDragAndDrop() const                   { return m_bAllowDragAndDrop;       }
    void SetRowResize(BOOL bResize = TRUE)        { m_bAllowRowResize = bResize;      }
    BOOL GetRowResize() const                     { return m_bAllowRowResize;         }
    void SetColumnResize(BOOL bResize = TRUE)     { m_bAllowColumnResize = bResize;   }
    BOOL GetColumnResize() const                  { return m_bAllowColumnResize;      }
    void SetHeaderSort(BOOL bSortOnClick = TRUE)  { m_bSortOnClick = bSortOnClick;    }
    BOOL GetHeaderSort() const                    { return m_bSortOnClick;            }
    void SetHandleTabKey(BOOL bHandleTab = TRUE)  { m_bHandleTabKey = bHandleTab;     }
    BOOL GetHandleTabKey() const                  { return m_bHandleTabKey;           }
    void SetDoubleBuffering(BOOL bBuffer = TRUE)  { m_bDoubleBuffer = bBuffer;        }
    BOOL GetDoubleBuffering() const               { return m_bDoubleBuffer;           }
    void EnableTitleTips(BOOL bEnable = TRUE)     { m_bTitleTips = bEnable;           }
    BOOL GetTitleTips()                           { return m_bTitleTips;              }
    void SetSortColumn(int nCol);
    int  GetSortColumn() const                    { return m_nSortColumn;             }
    void SetSortAscending(BOOL bAscending)        { m_bAscending = bAscending;        }
    BOOL GetSortAscending() const                 { return m_bAscending;              }
    void SetTrackFocusCell(BOOL bTrack)           { m_bTrackFocusCell = bTrack;       }
    BOOL GetTrackFocusCell()                      { return m_bTrackFocusCell;         }
    void SetFrameFocusCell(BOOL bFrame)           { m_bFrameFocus = bFrame;           }
    BOOL GetFrameFocusCell()                      { return m_bFrameFocus;             }
    void SetAutoSizeStyle(int nStyle = GVS_BOTH)  { m_nAutoSizeColumnStyle = nStyle;  }
    int  GetAutoSizeStyle()                       { return m_nAutoSizeColumnStyle; }
    void EnableHiddenColUnhide(BOOL bEnable = TRUE){ m_bHiddenColUnhide = bEnable;    }
    BOOL GetHiddenColUnhide()                     { return m_bHiddenColUnhide;        }
    void EnableHiddenRowUnhide(BOOL bEnable = TRUE){ m_bHiddenRowUnhide = bEnable;    }
    BOOL GetHiddenRowUnhide()                     { return m_bHiddenRowUnhide;        }
    void EnableColumnHide(BOOL bEnable = TRUE)    { m_bAllowColHide = bEnable;        }
    BOOL GetColumnHide()                          { return m_bAllowColHide;           }
    void EnableRowHide(BOOL bEnable = TRUE)       { m_bAllowRowHide = bEnable;        }
    BOOL GetRowHide()                             { return m_bAllowRowHide;           }
///////////////////////////////////////////////////////////////////////////////////
// default Grid cells. Use these for setting default values such as colors and fonts
///////////////////////////////////////////////////////////////////////////////////
public:
    CGridCellBase* GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const;
///////////////////////////////////////////////////////////////////////////////////
// Grid cell Attributes
///////////////////////////////////////////////////////////////////////////////////
public:
    CGridCellBase* GetCell(int nRow, int nCol) const;   // Get the actual cell!
    void SetModified(BOOL bModified = TRUE, int nRow = -1, int nCol = -1);
    BOOL GetModified(int nRow = -1, int nCol = -1);
    BOOL IsCellFixed(int nRow, int nCol);
    BOOL   SetItem(const GV_ITEM* pItem);
    BOOL   GetItem(GV_ITEM* pItem);
    BOOL   SetItemText(int nRow, int nCol, LPCTSTR str);
    // The following was virtual. If you want to override, use
    //  CGridCellBase-derived class's GetText() to accomplish same thing
    CString GetItemText(int nRow, int nCol) const;
    // EFW - 06/13/99 - Added to support printf-style formatting codes.
    // Also supports use with a string resource ID
#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 210)
    BOOL   SetItemTextFmt(int nRow, int nCol, LPCTSTR szFmt, ...);
    BOOL   SetItemTextFmtID(int nRow, int nCol, UINT nID, ...);
#endif
    BOOL   SetItemData(int nRow, int nCol, LPARAM lParam);
    LPARAM GetItemData(int nRow, int nCol) const;
    BOOL   SetItemImage(int nRow, int nCol, int iImage);
    int    GetItemImage(int nRow, int nCol) const;
    BOOL   SetItemState(int nRow, int nCol, UINT state);
    UINT   GetItemState(int nRow, int nCol) const;
    BOOL   SetItemFormat(int nRow, int nCol, UINT nFormat);
    UINT   GetItemFormat(int nRow, int nCol) const;
    BOOL   SetItemBkColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT);
    COLORREF GetItemBkColour(int nRow, int nCol) const;
    BOOL   SetItemFgColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT);
    COLORREF GetItemFgColour(int nRow, int nCol) const;
    BOOL SetItemFont(int nRow, int nCol, const LOGFONT* lf);
    const LOGFONT* GetItemFont(int nRow, int nCol);
    BOOL IsItemEditing(int nRow, int nCol);
    BOOL SetCellType(int nRow, int nCol, CRuntimeClass* pRuntimeClass);
    BOOL SetDefaultCellType( CRuntimeClass* pRuntimeClass);
///////////////////////////////////////////////////////////////////////////////////
// Operations
///////////////////////////////////////////////////////////////////////////////////
public:
    int  InsertColumn(LPCTSTR strHeading, UINT nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE,
                      int nColumn = -1);
    int  InsertRow(LPCTSTR strHeading, int nRow = -1);
    BOOL DeleteColumn(int nColumn);
    BOOL DeleteRow(int nRow);
    BOOL DeleteNonFixedRows();
    BOOL DeleteAllItems();
    void ClearCells(CCellRange Selection);
    BOOL AutoSizeRow(int nRow, BOOL bResetScroll = TRUE);
    BOOL AutoSizeColumn(int nCol, UINT nAutoSizeStyle = GVS_DEFAULT, BOOL bResetScroll = TRUE);
    void AutoSizeRows();
    void AutoSizeColumns(UINT nAutoSizeStyle = GVS_DEFAULT);
    void AutoSize(UINT nAutoSizeStyle = GVS_DEFAULT);
    void ExpandColumnsToFit(BOOL bExpandFixed = TRUE);
    void ExpandLastColumn();
    void ExpandRowsToFit(BOOL bExpandFixed = TRUE);
    void ExpandToFit(BOOL bExpandFixed = TRUE);
    void Refresh();
    void AutoFill();   // Fill grid with blank cells
    void EnsureVisible(CCellID &cell)       { EnsureVisible(cell.row, cell.col); }
    void EnsureVisible(int nRow, int nCol);
    BOOL IsCellVisible(int nRow, int nCol);
    BOOL IsCellVisible(CCellID cell);
    BOOL IsCellEditable(int nRow, int nCol) const;
    BOOL IsCellEditable(CCellID &cell) const;
    BOOL IsCellSelected(int nRow, int nCol) const;
    BOOL IsCellSelected(CCellID &cell) const;
    // SetRedraw stops/starts redraws on things like changing the # rows/columns
    // and autosizing, but not for user-intervention such as resizes
    void SetRedraw(BOOL bAllowDraw, BOOL bResetScrollBars = FALSE);
    BOOL RedrawCell(int nRow, int nCol, CDC* pDC = NULL);
    BOOL RedrawCell(const CCellID& cell, CDC* pDC = NULL);
    BOOL RedrawRow(int row);
    BOOL RedrawColumn(int col);
#ifndef _WIN32_WCE
    BOOL Save(LPCTSTR filename, TCHAR chSeparator = _T(','));
    BOOL Load(LPCTSTR filename, TCHAR chSeparator = _T(','));
#endif
///////////////////////////////////////////////////////////////////////////////////
// Cell Ranges
///////////////////////////////////////////////////////////////////////////////////
 public:
    CCellRange GetCellRange() const;
    CCellRange GetSelectedCellRange() const;
    void SetSelectedRange(const CCellRange& Range, BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE);
    void SetSelectedRange(int nMinRow, int nMinCol, int nMaxRow, int nMaxCol,
                          BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE);
    BOOL IsValid(int nRow, int nCol) const;
    BOOL IsValid(const CCellID& cell) const;
    BOOL IsValid(const CCellRange& range) const;
///////////////////////////////////////////////////////////////////////////////////
// Clipboard, drag and drop, and cut n' paste operations
///////////////////////////////////////////////////////////////////////////////////
#ifndef GRIDCONTROL_NO_CLIPBOARD
    virtual void CutSelectedText();
    virtual COleDataSource* CopyTextFromGrid();
    virtual BOOL PasteTextToGrid(CCellID cell, COleDataObject* pDataObject, BOOL bSelectPastedCells=TRUE);
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
 public:
    virtual void OnBeginDrag();
    virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
    virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
    virtual void OnDragLeave();
    virtual BOOL OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
    virtual void OnEditCut();
    virtual void OnEditCopy();
    virtual void OnEditPaste();
#endif
    virtual void OnEditSelectAll();
///////////////////////////////////////////////////////////////////////////////////
// Misc.
///////////////////////////////////////////////////////////////////////////////////
public:
    CCellID GetNextItem(CCellID& cell, int nFlags) const;
    BOOL SortItems(int nCol, BOOL bAscending, LPARAM data = 0);
    BOOL SortTextItems(int nCol, BOOL bAscending, LPARAM data = 0);
    BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data = 0);
    void SetCompareFunction(PFNLVCOMPARE pfnCompare);
    // in-built sort functions
    static int CALLBACK pfnCellTextCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
    static int CALLBACK pfnCellNumericCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
///////////////////////////////////////////////////////////////////////////////////
// Printing
///////////////////////////////////////////////////////////////////////////////////
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
public:
    void Print(CPrintDialog* pPrntDialog = NULL);
    // EFW - New printing support functions
    void EnableWysiwygPrinting(BOOL bEnable = TRUE) { m_bWysiwygPrinting = bEnable;     }
    BOOL GetWysiwygPrinting()                       { return m_bWysiwygPrinting;        }
    void SetShadedPrintOut(BOOL bEnable = TRUE)     {   m_bShadedPrintOut = bEnable;    }
    BOOL GetShadedPrintOut(void)                    {   return m_bShadedPrintOut;       }
    // Use -1 to have it keep the existing value
    void SetPrintMarginInfo(int nHeaderHeight, int nFooterHeight,
        int nLeftMargin, int nRightMargin, int nTopMargin,
        int nBottomMargin, int nGap);
    void GetPrintMarginInfo(int &nHeaderHeight, int &nFooterHeight,
        int &nLeftMargin, int &nRightMargin, int &nTopMargin,
        int &nBottomMargin, int &nGap);
///////////////////////////////////////////////////////////////////////////////////
// Printing overrides for derived classes
///////////////////////////////////////////////////////////////////////////////////
public:
    virtual void OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo);
    virtual void OnPrint(CDC *pDC, CPrintInfo *pInfo);
    virtual void OnEndPrinting(CDC *pDC, CPrintInfo *pInfo);
#endif // #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
// Implementation
public:
    virtual ~CGridCtrl();
protected:
    BOOL RegisterWindowClass();
    BOOL Initialise();
    void SetupDefaultCells();
    LRESULT SendMessageToParent(int nRow, int nCol, int nMessage) const;
    LRESULT SendDisplayRequestToParent(GV_DISPINFO* pDisplayInfo) const;
    LRESULT SendCacheHintToParent(const CCellRange& range) const;
    BOOL InvalidateCellRect(const int row, const int col);
    BOOL InvalidateCellRect(const CCellID& cell);
    BOOL InvalidateCellRect(const CCellRange& cellRange);
    void EraseBkgnd(CDC* pDC);
    BOOL GetCellRangeRect(const CCellRange& cellRange, LPRECT lpRect);
    BOOL SetCell(int nRow, int nCol, CGridCellBase* pCell);
    int  SetMouseMode(int nMode) { int nOldMode = m_MouseMode; m_MouseMode = nMode; return nOldMode; }
    int  GetMouseMode() const    { return m_MouseMode; }
    BOOL MouseOverRowResizeArea(CPoint& point);
    BOOL MouseOverColumnResizeArea(CPoint& point);
    CCellID GetTopleftNonFixedCell(BOOL bForceRecalculation = FALSE);
    CCellRange GetUnobstructedNonFixedCellRange(BOOL bForceRecalculation = FALSE);
    // LUC
    CCellRange GetVisibleNonFixedCellRange(LPRECT pRect = NULL, BOOL bForceRecalculation = FALSE);
    CCellRange GetVisibleFixedCellRange(LPRECT pRect = NULL, BOOL bForceRecalculation = FALSE);
    BOOL IsVisibleVScroll() { return ( (m_nBarState & GVL_VERT) > 0); }
    BOOL IsVisibleHScroll() { return ( (m_nBarState & GVL_HORZ) > 0); }
    void ResetSelectedRange();
    void ResetScrollBars();
    void EnableScrollBars(int nBar, BOOL bEnable = TRUE);
    int  GetScrollPos32(int nBar, BOOL bGetTrackPos = FALSE);
    BOOL SetScrollPos32(int nBar, int nPos, BOOL bRedraw = TRUE);
    BOOL SortTextItems(int nCol, BOOL bAscending, int low, int high);
    BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data,
                   int low, int high);
    CPoint GetPointClicked(int nRow, int nCol, const CPoint& point);
    void ValidateAndModifyCellContents(int nRow, int nCol, LPCTSTR strText);
// Overrrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CGridCtrl)
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL
protected:
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
    // Printing
    virtual void PrintFixedRowCells(int nStartColumn, int nStopColumn, int& row, CRect& rect,
                                    CDC *pDC, BOOL& bFirst);
    virtual void PrintColumnHeadings(CDC *pDC, CPrintInfo *pInfo);
    virtual void PrintHeader(CDC *pDC, CPrintInfo *pInfo);
    virtual void PrintFooter(CDC *pDC, CPrintInfo *pInfo);
    virtual void PrintRowButtons(CDC *pDC, CPrintInfo* /*pInfo*/);
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
    // Drag n' drop
    virtual CImageList* CreateDragImage(CPoint *pHotSpot);    // no longer necessary
#endif
    // Mouse Clicks
    virtual void  OnFixedColumnClick(CCellID& cell);
    virtual void  OnFixedRowClick(CCellID& cell);
    // Editing
    virtual void  OnEditCell(int nRow, int nCol, CPoint point, UINT nChar);
    virtual void  OnEndEditCell(int nRow, int nCol, CString str);
    virtual BOOL  ValidateEdit(int nRow, int nCol, LPCTSTR str);
    virtual void  EndEditing();
    // Drawing
    virtual void  OnDraw(CDC* pDC);
    // CGridCellBase Creation and Cleanup
    virtual CGridCellBase* CreateCell(int nRow, int nCol);
    virtual void DestroyCell(int nRow, int nCol);
// Attributes
protected:
    // General attributes
    COLORREF    m_crFixedTextColour, m_crFixedBkColour;
    COLORREF    m_crGridBkColour, m_crGridLineColour;
    COLORREF    m_crWindowText, m_crWindowColour, m_cr3DFace,     // System colours
                m_crShadow;
    COLORREF    m_crTTipBackClr, m_crTTipTextClr;                 // Titletip colours - FNA
    BOOL        m_bVirtualMode;
    LPARAM      m_lParam;                                           // lParam for callback
    GRIDCALLBACK m_pfnCallback;                                     // The callback function
    int         m_nGridLines;
    BOOL        m_bEditable;
    BOOL        m_bModified;
    BOOL        m_bAllowDragAndDrop;
    BOOL        m_bListMode;
    BOOL        m_bSingleRowSelection;
    BOOL        m_bSingleColSelection;
    BOOL        m_bAllowDraw;
    BOOL        m_bEnableSelection;
    BOOL        m_bFixedRowSelection, m_bFixedColumnSelection;
    BOOL        m_bSortOnClick;
    BOOL        m_bHandleTabKey;
    BOOL        m_bDoubleBuffer;
    BOOL        m_bTitleTips;
    int         m_nBarState;
    BOOL        m_bWysiwygPrinting;
    BOOL        m_bHiddenColUnhide, m_bHiddenRowUnhide;
    BOOL        m_bAllowColHide, m_bAllowRowHide;
    BOOL        m_bAutoSizeSkipColHdr;
    BOOL        m_bTrackFocusCell;
    BOOL        m_bFrameFocus;
    UINT        m_nAutoSizeColumnStyle;
    // Cell enable
    vector<vector<CELL_ENABLE>>    m_pCellEnable;
    // Cell size details
    int         m_nRows, m_nFixedRows, m_nCols, m_nFixedCols;
    // LUC
    int            m_nFreezedRows, m_nFreezedCols;
    BOOL m_bExcludeFreezedRowsFromSelection;
    BOOL m_bExcludeFreezedColsFromSelection;
    // LUC
    CArray<CCellRange, CCellRange&> m_arMergedCells;
    // LUC
    BOOL m_bShowHorzNonGridArea;
    CUIntArray  m_arRowHeights, m_arColWidths;
    int         m_nVScrollMax, m_nHScrollMax;
    // Fonts and images
    CRuntimeClass*   m_pRtcDefault; // determines kind of Grid Cell created by default
    CGridDefaultCell m_cellDefault;  // "default" cell. Contains default colours, font etc.
    CGridDefaultCell m_cellFixedColDef, m_cellFixedRowDef, m_cellFixedRowColDef;
    CFont       m_PrinterFont;  // for the printer
    CImageList* m_pImageList;
    // Cell data
    CTypedPtrArray<CObArray, GRID_ROW*> m_RowData;
    // Mouse operations such as cell selection
    int         m_MouseMode;
    BOOL        m_bLMouseButtonDown, m_bRMouseButtonDown;
    CPoint      m_LeftClickDownPoint, m_LastMousePoint;
    CCellID     m_LeftClickDownCell, m_SelectionStartCell;
    CCellID     m_idCurrentCell, m_idTopLeftCell;
    INT_PTR     m_nTimerID;
    int         m_nTimerInterval;
    int         m_nResizeCaptureRange;
    BOOL        m_bAllowRowResize, m_bAllowColumnResize;
    int         m_nRowsPerWheelNotch;
    CMap<DWORD,DWORD, CCellID, CCellID&> m_SelectedCellMap, m_PrevSelectedCellMap;
#ifndef GRIDCONTROL_NO_TITLETIPS
    CTitleTip   m_TitleTip;             // Title tips for cells
#endif
    // Drag and drop
    CCellID     m_LastDragOverCell;
#ifndef GRIDCONTROL_NO_DRAGDROP
    CGridDropTarget m_DropTarget;       // OLE Drop target for the grid
#endif
    // Printing information
    CSize       m_CharSize;
    int         m_nPageHeight;
    CSize       m_LogicalPageSize,      // Page size in gridctrl units.
                m_PaperSize;            // Page size in device units.
    // additional properties to support Wysiwyg printing
    int         m_nPageWidth;
    int         m_nPrintColumn;
    int         m_nCurrPrintRow;
    int         m_nNumPages;
    int         m_nPageMultiplier;
    // sorting
    int          m_bAscending;
    int          m_nSortColumn;
    PFNLVCOMPARE m_pfnCompare;
    // EFW - Added to support shaded/unshaded printout.  If true, colored
    // cells will print as-is.  If false, all text prints as black on white.
    BOOL        m_bShadedPrintOut;
    // EFW - Added support for user-definable margins.  Top and bottom are in
    // lines.  Left, right, and gap are in characters (avg width is used).
    int         m_nHeaderHeight, m_nFooterHeight, m_nLeftMargin,
                m_nRightMargin, m_nTopMargin, m_nBottomMargin, m_nGap;
protected:
    void SelectAllCells();
    void SelectColumns(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE);
    void SelectRows(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE);
    void SelectCells(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE);
    void OnSelecting(const CCellID& currentCell);
    // Generated message map functions
    //{{AFX_MSG(CGridCtrl)
    afx_msg void OnPaint();
    afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg UINT OnGetDlgCode();
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI);
    //}}AFX_MSG
#ifndef _WIN32_WCE_NO_CURSOR
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
#endif
#ifndef _WIN32_WCE
    afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);    // EFW - Added
    afx_msg void OnSysColorChange();
#endif
#ifndef _WIN32_WCE_NO_CURSOR
    afx_msg void OnCaptureChanged(CWnd *pWnd);
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
    afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI);
    afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI);
    afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI);
#endif
#if (_MFC_VER >= 0x0421) || (_WIN32_WCE >= 210)
    afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
#endif
#if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
#endif
    afx_msg LRESULT OnSetFont(WPARAM hFont, LPARAM lParam);
    afx_msg LRESULT OnGetFont(WPARAM hFont, LPARAM lParam);
    afx_msg LRESULT OnImeChar(WPARAM wCharCode, LPARAM lParam);
    afx_msg void OnEndInPlaceEdit(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnComboSelChange(NMHDR* pNMHDR, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
    enum eMouseModes { MOUSE_NOTHING, MOUSE_SELECT_ALL, MOUSE_SELECT_COL, MOUSE_SELECT_ROW,
                       MOUSE_SELECT_CELLS, MOUSE_SCROLLING_CELLS,
                       MOUSE_OVER_ROW_DIVIDE, MOUSE_SIZING_ROW,
                       MOUSE_OVER_COL_DIVIDE, MOUSE_SIZING_COL,
                       MOUSE_PREPARE_EDIT,
#ifndef GRIDCONTROL_NO_DRAGDROP
                       MOUSE_PREPARE_DRAG, MOUSE_DRAGGING
#endif
    };
//      for sort in virtual mode, and column order, save and load layer
public:
    typedef std::vector<int> intlist;
    void Reorder(int From, int To);
    void SetVirtualCompare(PVIRTUALCOMPARE VirtualCompare) { m_pfnVirtualCompare = VirtualCompare;}
    int m_CurCol;
    void AllowReorderColumn(bool b=true) { m_AllowReorderColumn = b;}
    void EnableDragRowMode(bool b=true) { m_bDragRowMode = b; if(b) EnableDragAndDrop(); } // to change row order
    int GetLayer(int** pLayer); //  gives back the number of ints of the area (do not forget to delete *pLayer)
    void SetLayer(int* pLayer); // coming from a previous GetLayer (ignored if not same number of column, or the same revision number)
    void ForceQuitFocusOnTab(bool b=true) { m_QuitFocusOnTab = b;} // use only if GetParent() is a CDialog
    void AllowSelectRowInFixedCol(bool b=true) { m_AllowSelectRowInFixedCol = b;} //
//    allow acces?
    intlist m_arRowOrder, m_arColOrder;
    static CGridCtrl* m_This;
protected:
    virtual void AddSubVirtualRow(int Num, int Nb);
    bool m_bDragRowMode;
    int m_CurRow;
private:
    void ResetVirtualOrder();
    PVIRTUALCOMPARE m_pfnVirtualCompare;
    static bool NotVirtualCompare(int c1, int c2);
    bool m_InDestructor;
    bool m_AllowReorderColumn;
    bool m_QuitFocusOnTab;
    bool m_AllowSelectRowInFixedCol;
};
// Returns the default cell implementation for the given grid region
inline CGridCellBase* CGridCtrl::GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const
{
    if (bFixedRow && bFixedCol) return (CGridCellBase*) &m_cellFixedRowColDef;
    if (bFixedRow)              return (CGridCellBase*) &m_cellFixedRowDef;
    if (bFixedCol)              return (CGridCellBase*) &m_cellFixedColDef;
    return (CGridCellBase*) &m_cellDefault;
}
inline CGridCellBase* CGridCtrl::GetCell(int nRow, int nCol) const
{
    if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols)
        return NULL;
    if (GetVirtualMode())
    {
        CGridCellBase* pCell = GetDefaultCell(nRow < m_nFixedRows, nCol < m_nFixedCols);
        static GV_DISPINFO gvdi;
        gvdi.item.row     = nRow;
        gvdi.item.col     = nCol;
        gvdi.item.mask    = 0xFFFFFFFF;
        gvdi.item.nState  = 0;
        gvdi.item.nFormat = pCell->GetFormat();
        gvdi.item.iImage  = pCell->GetImage();
        gvdi.item.crBkClr = pCell->GetBackClr();
        gvdi.item.crFgClr = pCell->GetTextClr();
        gvdi.item.lParam  = pCell->GetData();
        memcpy(&gvdi.item.lfFont, pCell->GetFont(), sizeof(LOGFONT));
        gvdi.item.nMargin = pCell->GetMargin();
        gvdi.item.strText.Empty();
        // Fix the state bits
        if (IsCellSelected(nRow, nCol))   gvdi.item.nState |= GVIS_SELECTED;
        if (nRow < GetFixedRowCount())    gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDROW);
        if (nCol < GetFixedColumnCount()) gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDCOL);
        if (GetFocusCell() == CCellID(nRow, nCol)) gvdi.item.nState |= GVIS_FOCUSED;
        if(!m_InDestructor)
        {
            gvdi.item.row = m_arRowOrder[nRow];
            gvdi.item.col = m_arColOrder[nCol];
            if (m_pfnCallback)
                m_pfnCallback(&gvdi, m_lParam);
            else
                SendDisplayRequestToParent(&gvdi);
            gvdi.item.row = nRow;
            gvdi.item.col = nCol;
        }
        static CGridCell cell;
        cell.SetState(gvdi.item.nState);
        cell.SetFormat(gvdi.item.nFormat);
        cell.SetImage(gvdi.item.iImage);
        cell.SetBackClr(gvdi.item.crBkClr);
        cell.SetTextClr(gvdi.item.crFgClr);
        cell.SetData(gvdi.item.lParam);
        cell.SetFont(&(gvdi.item.lfFont));
        cell.SetMargin(gvdi.item.nMargin);
        cell.SetText(gvdi.item.strText);
        cell.SetGrid((CGridCtrl*)this);
        return (CGridCellBase*) &cell;
    }
    GRID_ROW* pRow = m_RowData[nRow];
    if (!pRow) return NULL;
    if(pRow->GetData() == NULL)
        return NULL;
    return pRow->GetAt(m_arColOrder[nCol]);
}
inline BOOL CGridCtrl::SetCell(int nRow, int nCol, CGridCellBase* pCell)
{
    if (GetVirtualMode())
        return FALSE;
    if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols)
        return FALSE;
    GRID_ROW* pRow = m_RowData[nRow];
    if (!pRow) return FALSE;
    pCell->SetCoords( nRow, nCol);
    pRow->SetAt(nCol, pCell);
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
SourceCode/Bond/Servo/GridControl/GridDropTarget.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,156 @@
// GridDropTarget.cpp : implementation file
//
// MFC Grid Control - Drag/Drop target implementation
//
// CGridDropTarget is an OLE drop target for CGridCtrl. All it does
// is handle the drag and drop windows messages and pass them
// directly onto the grid control.
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCtrl.h"
#ifndef GRIDCONTROL_NO_DRAGDROP
#include "GridDropTarget.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CGridDropTarget
CGridDropTarget::CGridDropTarget()
{
    m_pGridCtrl = NULL;
    m_bRegistered = FALSE;
}
CGridDropTarget::~CGridDropTarget()
{
}
// Overloaded Register() function performs the normal COleDropTarget::Register
// but also serves to connect this COleDropTarget with the parent grid control,
// where all drop messages will ultimately be forwarded.
BOOL CGridDropTarget::Register(CGridCtrl *pGridCtrl)
{
    if (m_bRegistered)
        return FALSE;
    // Stop re-entry problems
    static BOOL bInProcedure = FALSE;
    if (bInProcedure)
        return FALSE;
    bInProcedure = TRUE;
//    ASSERT(pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl)));
//    ASSERT(pGridCtrl);
    if (!pGridCtrl || !pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl)))
    {
        bInProcedure = FALSE;
        return FALSE;
    }
    m_pGridCtrl = pGridCtrl;
    m_bRegistered = COleDropTarget::Register(pGridCtrl);
    bInProcedure = FALSE;
    return m_bRegistered;
}
void CGridDropTarget::Revoke()
{
    m_bRegistered = FALSE;
    COleDropTarget::Revoke();
}
BEGIN_MESSAGE_MAP(CGridDropTarget, COleDropTarget)
    //{{AFX_MSG_MAP(CGridDropTarget)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGridDropTarget message handlers
DROPEFFECT CGridDropTarget::OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint /*point*/)
{
//    TRACE("In CGridDropTarget::OnDragScroll\n");
    if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
    {
        if (dwKeyState & MK_CONTROL)
            return DROPEFFECT_COPY;
        else
            return DROPEFFECT_MOVE;
    } else
        return DROPEFFECT_NONE;
}
DROPEFFECT CGridDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject,
                                        DWORD dwKeyState, CPoint point)
{
//    TRACE(_T("In CGridDropTarget::OnDragEnter\n"));
//    ASSERT(m_pGridCtrl);
    if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
        return m_pGridCtrl->OnDragEnter(pDataObject, dwKeyState, point);
    else
        return DROPEFFECT_NONE;
}
void CGridDropTarget::OnDragLeave(CWnd* pWnd)
{
//    TRACE(_T("In CGridDropTarget::OnDragLeave\n"));
//    ASSERT(m_pGridCtrl);
    if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
        m_pGridCtrl->OnDragLeave();
}
DROPEFFECT CGridDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject,
                                       DWORD dwKeyState, CPoint point)
{
///    TRACE("In CGridDropTarget::OnDragOver\n");
//    ASSERT(m_pGridCtrl);
    if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
        return m_pGridCtrl->OnDragOver(pDataObject, dwKeyState, point);
    else
        return DROPEFFECT_NONE;
}
BOOL CGridDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject,
                             DROPEFFECT dropEffect, CPoint point)
{
//    TRACE(_T("In CGridDropTarget::OnDrop\n"));
//    ASSERT(m_pGridCtrl);
    if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
        return m_pGridCtrl->OnDrop(pDataObject, dropEffect, point);
    else
        return FALSE;
}
#endif // GRIDCONTROL_NO_DRAGDROP
SourceCode/Bond/Servo/GridControl/GridDropTarget.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
//////////////////////////////////////////////////////////////////////
// GridDropTarget.h : header file
//
// MFC Grid Control - Drag/Drop target implementation
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_)
#define AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include <afxole.h>
class CGridCtrl;
/////////////////////////////////////////////////////////////////////////////
// CGridDropTarget command target
class CGridDropTarget : public COleDropTarget
{
public:
    CGridDropTarget();
    virtual ~CGridDropTarget();
// Attributes
public:
    CGridCtrl* m_pGridCtrl;
    BOOL       m_bRegistered;
// Operations
public:
    BOOL Register(CGridCtrl *pGridCtrl);
    virtual void Revoke();
    BOOL        OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);
    DROPEFFECT  OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
    void        OnDragLeave(CWnd* pWnd);
    DROPEFFECT  OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
    DROPEFFECT  OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point);
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CGridDropTarget)
    //}}AFX_VIRTUAL
// Implementation
protected:
    // Generated message map functions
    //{{AFX_MSG(CGridDropTarget)
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_)
SourceCode/Bond/Servo/GridControl/GridInPlaceEdit.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,262 @@
// InPlaceEdit.cpp : implementation file
//
// Adapted by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// The code contained in this file is based on the original
// CGridInPlaceEdit from http://www.codeguru.com/listview/edit_subitems.shtml
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
// History:
//         10 May 1998  Uses GVN_ notifications instead of LVN_,
//                      Sends notification messages to the parent,
//                      instead of the parent's parent.
//         15 May 1998  There was a problem when editing with the in-place editor,
//                      there arises a general protection fault in user.exe, with a
//                      few qualifications:
//                         (1) This only happens with owner-drawn buttons;
//                         (2) This only happens in Win95
//                         (3) This only happens if the handler for the button does not
//                             create a new window (even an AfxMessageBox will avoid the
//                             crash)
//                         (4) This will not happen if Spy++ is running.
//                      PreTranslateMessage was added to route messages correctly.
//                      (Matt Weagle found and fixed this problem)
//         26 Jul 1998  Removed the ES_MULTILINE style - that fixed a few probs!
//          6 Aug 1998  Added nID to the constructor param list
//          6 Sep 1998  Space no longer clears selection when starting edit (Franco Bez)
//         10 Apr 1999  Enter, Tab and Esc key prob fixed (Koay Kah Hoe)
//                      Workaround for bizzare "shrinking window" problem in CE
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TCHAR.h"
#include "GridCtrl.h"
#include "GridInPlaceEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CGridInPlaceEdit
CGridInPlaceEdit::CGridInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
                           int nRow, int nColumn, CString sInitText,
                           UINT nFirstChar)
{
    m_sInitText     = sInitText;
    m_nRow          = nRow;
    m_nColumn       = nColumn;
    m_nLastChar     = 0;
    m_bExitOnArrows = (nFirstChar != VK_LBUTTON);    // If mouse click brought us here,
                                                     // then no exit on arrows
    m_Rect = rect;  // For bizarre CE bug.
    DWORD dwEditStyle = WS_BORDER|WS_CHILD|WS_VISIBLE| ES_AUTOHSCROLL //|ES_MULTILINE
        | dwStyle;
    if (!Create(dwEditStyle, rect, pParent, nID)) return;
    SetFont(pParent->GetFont());
    SetWindowText(sInitText);
    SetFocus();
    switch (nFirstChar){
        case VK_LBUTTON:
        case VK_RETURN:   SetSel((int)_tcslen(m_sInitText), -1); return;
        case VK_BACK:     SetSel((int)_tcslen(m_sInitText), -1); break;
        case VK_TAB:
        case VK_DOWN:
        case VK_UP:
        case VK_RIGHT:
        case VK_LEFT:
        case VK_NEXT:
        case VK_PRIOR:
        case VK_HOME:
        case VK_SPACE:
        case VK_END:      SetSel(0,-1); return;
        default:          SetSel(0,-1);
    }
    // Added by KiteFly. When entering DBCS chars into cells the first char was being lost
    // SenMessage changed to PostMessage (John Lagerquist)
    if( nFirstChar < 0x80)
        PostMessage(WM_CHAR, nFirstChar);
    else
        PostMessage(WM_IME_CHAR, nFirstChar);
}
CGridInPlaceEdit::~CGridInPlaceEdit()
{
}
BEGIN_MESSAGE_MAP(CGridInPlaceEdit, CEdit)
    //{{AFX_MSG_MAP(CGridInPlaceEdit)
    ON_WM_KILLFOCUS()
    ON_WM_CHAR()
    ON_WM_KEYDOWN()
    ON_WM_GETDLGCODE()
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////
// CGridInPlaceEdit message handlers
// If an arrow key (or associated) is pressed, then exit if
//  a) The Ctrl key was down, or
//  b) m_bExitOnArrows == TRUE
void CGridInPlaceEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if ((nChar == VK_PRIOR || nChar == VK_NEXT ||
        nChar == VK_DOWN  || nChar == VK_UP   ||
        nChar == VK_RIGHT || nChar == VK_LEFT) &&
        (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0))
    {
        m_nLastChar = nChar;
        GetParent()->SetFocus();
        return;
    }
    CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
// As soon as this edit loses focus, kill it.
void CGridInPlaceEdit::OnKillFocus(CWnd* pNewWnd)
{
    CEdit::OnKillFocus(pNewWnd);
    EndEdit();
}
void CGridInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (nChar == VK_TAB || nChar == VK_RETURN)
    {
        m_nLastChar = nChar;
        GetParent()->SetFocus();    // This will destroy this window
        return;
    }
    if (nChar == VK_ESCAPE)
    {
        SetWindowText(m_sInitText);    // restore previous text
        m_nLastChar = nChar;
        GetParent()->SetFocus();
        return;
    }
    CEdit::OnChar(nChar, nRepCnt, nFlags);
    // Resize edit control if needed
    // Get text extent
    CString str;
    GetWindowText( str );
    // add some extra buffer
    str += _T("  ");
    CWindowDC dc(this);
    CFont *pFontDC = dc.SelectObject(GetFont());
    CSize size = dc.GetTextExtent( str );
    dc.SelectObject( pFontDC );
    // Get client rect
    CRect ParentRect;
    GetParent()->GetClientRect( &ParentRect );
    // Check whether control needs to be resized
    // and whether there is space to grow
    if (size.cx > m_Rect.Width())
    {
        if( size.cx + m_Rect.left < ParentRect.right )
            m_Rect.right = m_Rect.left + size.cx;
        else
            m_Rect.right = ParentRect.right;
        MoveWindow( &m_Rect );
    }
}
UINT CGridInPlaceEdit::OnGetDlgCode()
{
    return DLGC_WANTALLKEYS;
}
////////////////////////////////////////////////////////////////////////////
// CGridInPlaceEdit overrides
// Stoopid win95 accelerator key problem workaround - Matt Weagle.
BOOL CGridInPlaceEdit::PreTranslateMessage(MSG* pMsg)
{
    // Catch the Alt key so we don't choke if focus is going to an owner drawn button
    if (pMsg->message == WM_SYSCHAR)
        return TRUE;
    return CWnd::PreTranslateMessage(pMsg);
}
// Auto delete
void CGridInPlaceEdit::PostNcDestroy()
{
    CEdit::PostNcDestroy();
    delete this;
}
////////////////////////////////////////////////////////////////////////////
// CGridInPlaceEdit implementation
void CGridInPlaceEdit::EndEdit()
{
    CString str;
    // EFW - BUG FIX - Clicking on a grid scroll bar in a derived class
    // that validates input can cause this to get called multiple times
    // causing assertions because the edit control goes away the first time.
    static BOOL bAlreadyEnding = FALSE;
    if(bAlreadyEnding)
        return;
    bAlreadyEnding = TRUE;
    GetWindowText(str);
    // Send Notification to parent
    GV_DISPINFO dispinfo;
    dispinfo.hdr.hwndFrom = GetSafeHwnd();
    dispinfo.hdr.idFrom   = GetDlgCtrlID();
    dispinfo.hdr.code     = GVN_ENDLABELEDIT;
    dispinfo.item.mask    = LVIF_TEXT|LVIF_PARAM;
    dispinfo.item.row     = m_nRow;
    dispinfo.item.col     = m_nColumn;
    dispinfo.item.strText  = str;
    dispinfo.item.lParam  = (LPARAM) m_nLastChar;
    CWnd* pOwner = GetOwner();
    if (pOwner)
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo );
    // Close this window (PostNcDestroy will delete this)
    if (IsWindow(GetSafeHwnd()))
        SendMessage(WM_CLOSE, 0, 0);
    bAlreadyEnding = FALSE;
}
SourceCode/Bond/Servo/GridControl/GridInPlaceEdit.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
//////////////////////////////////////////////////////////////////////
// InPlaceEdit.h : header file
//
// MFC Grid Control - inplace editing class
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CGridInPlaceEdit : public CEdit
{
// Construction
public:
    CGridInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
                 int nRow, int nColumn, CString sInitText, UINT nFirstChar);
// Attributes
public:
// Operations
public:
     void EndEdit();
// Overrides
     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CGridInPlaceEdit)
    public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    protected:
    virtual void PostNcDestroy();
    //}}AFX_VIRTUAL
// Implementation
public:
     virtual ~CGridInPlaceEdit();
// Generated message map functions
protected:
    //{{AFX_MSG(CGridInPlaceEdit)
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg UINT OnGetDlgCode();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
private:
    int     m_nRow;
    int     m_nColumn;
    CString m_sInitText;
    UINT    m_nLastChar;
    BOOL    m_bExitOnArrows;
    CRect   m_Rect;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_)
SourceCode/Bond/Servo/GridControl/GridMemDC.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,106 @@
#if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// MemDC.h : header file
//
//////////////////////////////////////////////////
// CGridMemDC - memory DC
//
// Author: Keith Rule
// Email:  keithr@europa.com
// Copyright 1996-1997, Keith Rule
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
// History - 10/3/97 Fixed scrolling bug.
//                   Added print support.
//           25 feb 98 - fixed minor assertion bug
//
// This class implements a memory Device Context
class CGridMemDC : public CDC
{
public:
    // constructor sets up the memory DC
    CGridMemDC(CDC* pDC) : CDC()
    {
//        ASSERT(pDC != NULL);
        m_pDC = pDC;
        m_pOldBitmap = NULL;
#ifndef _WIN32_WCE_NO_PRINTING
        m_bMemDC = !pDC->IsPrinting();
#else
        m_bMemDC = FALSE;
#endif
        if (m_bMemDC)    // Create a Memory DC
        {
            pDC->GetClipBox(&m_rect);
            CreateCompatibleDC(pDC);
            m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
            m_pOldBitmap = SelectObject(&m_bitmap);
#ifndef _WIN32_WCE
            SetWindowOrg(m_rect.left, m_rect.top);
#endif
            // EFW - Bug fix - Fill background in case the user has overridden
            // WM_ERASEBKGND.  We end up with garbage otherwise.
            // CJM - moved to fix a bug in the fix.
            FillSolidRect(m_rect, pDC->GetBkColor());
        }
        else        // Make a copy of the relevent parts of the current DC for printing
        {
#if !defined(_WIN32_WCE) || ((_WIN32_WCE > 201) && !defined(_WIN32_WCE_NO_PRINTING))
            m_bPrinting = pDC->m_bPrinting;
#endif
            m_hDC       = pDC->m_hDC;
            m_hAttribDC = pDC->m_hAttribDC;
        }
    }
    // Destructor copies the contents of the mem DC to the original DC
    ~CGridMemDC()
    {
        if (m_bMemDC)
        {
            // Copy the offscreen bitmap onto the screen.
            m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
                          this, m_rect.left, m_rect.top, SRCCOPY);
            //Swap back the original bitmap.
            SelectObject(m_pOldBitmap);
        } else {
            // All we need to do is replace the DC with an illegal value,
            // this keeps us from accidently deleting the handles associated with
            // the CDC that was passed to the constructor.
            m_hDC = m_hAttribDC = NULL;
        }
    }
    // Allow usage as a pointer
    CGridMemDC* operator->() {return this;}
    // Allow usage as a pointer
    operator CGridMemDC*() {return this;}
private:
    CBitmap  m_bitmap;      // Offscreen bitmap
    CBitmap* m_pOldBitmap;  // bitmap originally found in CGridMemDC
    CDC*     m_pDC;         // Saves CDC passed in constructor
    CRect    m_rect;        // Rectangle of drawing area.
    BOOL     m_bMemDC;      // TRUE if CDC really is a Memory DC.
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCheck.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,185 @@
// GridCellCheck.cpp : implementation file
//
// MFC Grid Control - Main grid cell class
//
// Provides the implementation for a combobox cell type of the
// grid control.
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// Parts of the code contained in this file are based on the original
// CInPlaceList from http://www.codeguru.com/listview
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
// History:
// 23 Jul 2001 - Complete rewrite
// 13 Mar 2004 - GetCellExtent and GetCheckPlacement fixed by Yogurt
//             - Read-only now honoured - Yogurt
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCell.h"
#include "GridCtrl.h"
#include "GridCellCheck.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CGridCellCheck, CGridCell)
CGridCellCheck::CGridCellCheck() : CGridCell()
{
    m_bChecked = FALSE;
    //m_Rect.IsRectNull();
}
CSize CGridCellCheck::GetCellExtent(CDC* pDC)
{
    // Using SM_CXHSCROLL as a guide to the size of the checkbox
    int nWidth = GetSystemMetrics(SM_CXHSCROLL) + 2*GetMargin();
    CSize    cellSize = CGridCell::GetCellExtent(pDC);
    cellSize.cx += nWidth;
    cellSize.cy = max (cellSize.cy, nWidth);
    return  cellSize;
}
// i/o:  i=dims of cell rect; o=dims of text rect
BOOL CGridCellCheck::GetTextRect( LPRECT pRect)
{
    BOOL bResult = CGridCell::GetTextRect(pRect);
    if (bResult)
    {
        int nWidth = GetSystemMetrics(SM_CXHSCROLL) + 2*GetMargin();
        pRect->left += nWidth;
        if (pRect->left > pRect->right)
            pRect->left = pRect->right;
    }
    return bResult;
}
// Override draw so that when the cell is selected, a drop arrow is shown in the RHS.
BOOL CGridCellCheck::Draw(CDC* pDC, int nRow, int nCol, CRect rect,  BOOL bEraseBkgnd /*=TRUE*/)
{
    BOOL bResult = CGridCell::Draw(pDC, nRow, nCol, rect,  bEraseBkgnd);
#ifndef _WIN32_WCE
    // Store the cell's dimensions for later
    m_Rect = rect;
    CRect CheckRect = GetCheckPlacement();
    rect.left = CheckRect.right;
    // enough room to draw?
    // if (CheckRect.Width() < rect.Width() && CheckRect.Height() < rect.Height()) {
    // Do the draw
    pDC->DrawFrameControl(GetCheckPlacement(), DFC_BUTTON,
        (m_bChecked)? DFCS_BUTTONCHECK | DFCS_CHECKED : DFCS_BUTTONCHECK);
    // }
#endif
    return bResult;
}
void CGridCellCheck::OnClick(CPoint PointCellRelative)
{
    // PointCellRelative is relative to the topleft of the cell. Convert to client coords
    PointCellRelative += m_Rect.TopLeft();
    // Bail if cell is read-only
    CCellID cell = GetGrid()->GetCellFromPt(PointCellRelative);
    if (GetGrid()->isCellMaskActivated(cell.row, cell.col))
    {
        if (!GetGrid()->isCellMaskEditable(cell.row, cell.col))
        {
            return;
        }
    }
    else
    {
        if (!GetGrid()->IsCellEditable(cell))
            return;
    }
    // GetCheckPlacement returns the checkbox dimensions in client coords. Only check/
    // uncheck if the user clicked in the box
    if (GetCheckPlacement().PtInRect(PointCellRelative))
    {
        m_bChecked = !m_bChecked;
        GetGrid()->InvalidateRect(m_Rect);
    }
}
//////////////////////////////////////////////////////////////////////
// Operations
//////////////////////////////////////////////////////////////////////
BOOL CGridCellCheck::SetCheck(BOOL bChecked /*=TRUE*/)
{
    BOOL bTemp = m_bChecked;
    m_bChecked = bChecked;
    if (!m_Rect.IsRectEmpty())
        GetGrid()->InvalidateRect(m_Rect);
    return bTemp;
}
BOOL CGridCellCheck::GetCheck()
{
    return m_bChecked;
}
//////////////////////////////////////////////////////////////////////
// Protected implementation
//////////////////////////////////////////////////////////////////////
// Returns the dimensions and placement of the checkbox in client coords.
CRect CGridCellCheck::GetCheckPlacement()
{
    int nWidth = GetSystemMetrics(SM_CXHSCROLL);
    CRect place = m_Rect + CSize(GetMargin(), GetMargin());
    place.right = place.left + nWidth;
    place.bottom = place.top + nWidth;
    /* for centering
    int nDiff = (place.Width() - nWidth)/2;
    if (nDiff > 0)
    {
        place.left += nDiff;
        place.right = place.left + nWidth;
    }
    nDiff = (place.Height() - nWidth)/2;
    if (nDiff > 0)
    {
        place.top += nDiff;
        place.bottom = place.top + nWidth;
    }
    */
    if (m_Rect.Height() < nWidth + 2 * static_cast<int> (GetMargin()))
    {
        place.top = m_Rect.top + (m_Rect.Height() - nWidth) / 2;
        place.bottom = place.top + nWidth;
    }
    return place;
}
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCheck.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
#if !defined(AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
/////////////////////////////////////////////////////////////////////////////
// GridCellCheck.h : header file
//
// MFC Grid Control - Grid combo cell class header file
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
//////////////////////////////////////////////////////////////////////
#include "GridCell.h"
class CGridCellCheck : public CGridCell
{
    friend class CGridCtrl;
    DECLARE_DYNCREATE(CGridCellCheck)
public:
    CGridCellCheck();
public:
    BOOL SetCheck(BOOL bChecked = TRUE);
    BOOL GetCheck();
// Operations
    virtual CSize GetCellExtent(CDC* pDC);
    virtual void OnClick( CPoint PointCellRelative);
    virtual BOOL GetTextRect( LPRECT pRect);
protected:
    CRect GetCheckPlacement();
    virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
protected:
    BOOL  m_bChecked;
    CRect m_Rect;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCombo.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,510 @@
// GridCellCombo.cpp : implementation file
//
// MFC Grid Control - Main grid cell class
//
// Provides the implementation for a combobox cell type of the
// grid control.
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// Parts of the code contained in this file are based on the original
// CInPlaceList from http://www.codeguru.com/listview
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
// History:
// 6 Aug 1998 - Added CComboEdit to subclass the edit control - code
//              provided by Roelf Werkman <rdw@inn.nl>. Added nID to
//              the constructor param list.
// 29 Nov 1998 - bug fix in onkeydown (Markus Irtenkauf)
// 13 Mar 2004 - GetCellExtent fixed by Yogurt
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCell.h"
#include "GridCtrl.h"
#include "GridCellCombo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CComboEdit
CComboEdit::CComboEdit()
{
}
CComboEdit::~CComboEdit()
{
}
// Stoopid win95 accelerator key problem workaround - Matt Weagle.
BOOL CComboEdit::PreTranslateMessage(MSG* pMsg)
{
    // Make sure that the keystrokes continue to the appropriate handlers
    if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP)
    {
        ::TranslateMessage(pMsg);
        ::DispatchMessage(pMsg);
        return TRUE;
    }
    // Catch the Alt key so we don't choke if focus is going to an owner drawn button
    if (pMsg->message == WM_SYSCHAR)
        return TRUE;
    return CEdit::PreTranslateMessage(pMsg);
}
BEGIN_MESSAGE_MAP(CComboEdit, CEdit)
    //{{AFX_MSG_MAP(CComboEdit)
    ON_WM_KILLFOCUS()
    ON_WM_KEYDOWN()
    ON_WM_KEYUP()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CComboEdit message handlers
void CComboEdit::OnKillFocus(CWnd* pNewWnd)
{
    CEdit::OnKillFocus(pNewWnd);
    CInPlaceList* pOwner = (CInPlaceList*) GetOwner();  // This MUST be a CInPlaceList
    if (pOwner)
        pOwner->EndEdit();
}
void CComboEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if ((nChar == VK_PRIOR || nChar == VK_NEXT ||
         nChar == VK_DOWN  || nChar == VK_UP   ||
         nChar == VK_RIGHT || nChar == VK_LEFT) &&
        (GetKeyState(VK_CONTROL) < 0 && GetDlgCtrlID() == IDC_COMBOEDIT))
    {
        CWnd* pOwner = GetOwner();
        if (pOwner)
            pOwner->SendMessage(WM_KEYDOWN, nChar, nRepCnt+ (((DWORD)nFlags)<<16));
        return;
    }
    CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CComboEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (nChar == VK_ESCAPE)
    {
        CWnd* pOwner = GetOwner();
        if (pOwner)
            pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16));
        return;
    }
    if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
    {
        CWnd* pOwner = GetOwner();
        if (pOwner)
            pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16));
        return;
    }
    CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
}
/////////////////////////////////////////////////////////////////////////////
// CInPlaceList
CInPlaceList::CInPlaceList(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
                           int nRow, int nColumn,
                           COLORREF crFore, COLORREF crBack,
                           CStringArray& Items, CString sInitText,
                           UINT nFirstChar)
{
    m_crForeClr = crFore;
    m_crBackClr = crBack;
    m_nNumLines = 4;
    m_sInitText = sInitText;
     m_nRow        = nRow;
     m_nCol      = nColumn;
     m_nLastChar = 0;
    m_bExitOnArrows = FALSE; //(nFirstChar != VK_LBUTTON);    // If mouse click brought us here,
    // Create the combobox
     DWORD dwComboStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL|
                          CBS_AUTOHSCROLL | dwStyle;
    int nHeight = rect.Height();
    rect.bottom = rect.bottom + m_nNumLines*nHeight + ::GetSystemMetrics(SM_CYHSCROLL);
    if (!Create(dwComboStyle, rect, pParent, nID)) return;
    // Add the strings
    for (int i = 0; i < Items.GetSize(); i++)
        AddString(Items[i]);
    SetFont(pParent->GetFont());
    SetItemHeight(-1, nHeight);
    int nMaxLength = GetCorrectDropWidth();
    /*
    if (nMaxLength > rect.Width())
        rect.right = rect.left + nMaxLength;
    // Resize the edit window and the drop down window
    MoveWindow(rect);
    */
    SetDroppedWidth(nMaxLength);
    SetHorizontalExtent(0); // no horz scrolling
    // Set the initial text to m_sInitText
    if (::IsWindow(m_hWnd) && SelectString(-1, m_sInitText) == CB_ERR)
        SetWindowText(m_sInitText);        // No text selected, so restore what was there before
    ShowDropDown();
    // Subclass the combobox edit control if style includes CBS_DROPDOWN
    if ((dwStyle & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST)
    {
        m_edit.SubclassDlgItem(IDC_COMBOEDIT, this);
         SetFocus();
        switch (nFirstChar)
        {
            case VK_LBUTTON:
            case VK_RETURN:   m_edit.SetSel((int)_tcslen(m_sInitText), -1); return;
            case VK_BACK:     m_edit.SetSel((int)_tcslen(m_sInitText), -1); break;
            case VK_DOWN:
            case VK_UP:
            case VK_RIGHT:
            case VK_LEFT:
            case VK_NEXT:
            case VK_PRIOR:
            case VK_HOME:
            case VK_END:      m_edit.SetSel(0,-1); return;
            default:          m_edit.SetSel(0,-1);
        }
        SendMessage(WM_CHAR, nFirstChar);
    }
    else
         SetFocus();
}
CInPlaceList::~CInPlaceList()
{
}
void CInPlaceList::EndEdit()
{
    CString str;
    if (::IsWindow(m_hWnd))
        GetWindowText(str);
    // Send Notification to parent
    GV_DISPINFO dispinfo;
    dispinfo.hdr.hwndFrom = GetSafeHwnd();
    dispinfo.hdr.idFrom   = GetDlgCtrlID();
    dispinfo.hdr.code     = GVN_ENDLABELEDIT;
    dispinfo.item.mask    = LVIF_TEXT|LVIF_PARAM;
    dispinfo.item.row     = m_nRow;
    dispinfo.item.col     = m_nCol;
    dispinfo.item.strText = str;
    dispinfo.item.lParam  = (LPARAM) m_nLastChar;
    CWnd* pOwner = GetOwner();
    if (IsWindow(pOwner->GetSafeHwnd()))
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo );
    // Close this window (PostNcDestroy will delete this)
    if (::IsWindow(m_hWnd))
        PostMessage(WM_CLOSE, 0, 0);
}
int CInPlaceList::GetCorrectDropWidth()
{
    const int nMaxWidth = 200;  // don't let the box be bigger than this
    // Reset the dropped width
    int nNumEntries = GetCount();
    int nWidth = 0;
    CString str;
    CClientDC dc(this);
    int nSave = dc.SaveDC();
    dc.SelectObject(GetFont());
    int nScrollWidth = ::GetSystemMetrics(SM_CXVSCROLL);
    for (int i = 0; i < nNumEntries; i++)
    {
        GetLBText(i, str);
        int nLength = dc.GetTextExtent(str).cx + nScrollWidth;
        nWidth = max(nWidth, nLength);
    }
    // Add margin space to the calculations
    nWidth += dc.GetTextExtent(_T("0")).cx;
    dc.RestoreDC(nSave);
    nWidth = min(nWidth, nMaxWidth);
    return nWidth;
    //SetDroppedWidth(nWidth);
}
/*
// Fix by Ray (raybie@Exabyte.COM)
void CInPlaceList::OnSelendOK()
{
    int iIndex = GetCurSel();
    if( iIndex != CB_ERR)
    {
        CString strLbText;
        GetLBText( iIndex, strLbText);
        if (!((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST))
           m_edit.SetWindowText( strLbText);
    }
    GetParent()->SetFocus();
}
*/
void CInPlaceList::PostNcDestroy()
{
    CComboBox::PostNcDestroy();
    delete this;
}
BEGIN_MESSAGE_MAP(CInPlaceList, CComboBox)
    //{{AFX_MSG_MAP(CInPlaceList)
    ON_WM_KILLFOCUS()
    ON_WM_KEYDOWN()
    ON_WM_KEYUP()
    ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown)
    ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelChange)
    ON_WM_GETDLGCODE()
    ON_WM_CTLCOLOR_REFLECT()
    //}}AFX_MSG_MAP
    //ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendOK)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CInPlaceList message handlers
UINT CInPlaceList::OnGetDlgCode()
{
    return DLGC_WANTALLKEYS;
}
void CInPlaceList::OnDropdown()
{
    SetDroppedWidth(GetCorrectDropWidth());
}
void CInPlaceList::OnSelChange()
{
    CString str;
    GetLBText(GetCurSel(), str);
    // Send Notification to parent
    GV_DISPINFO dispinfo;
    dispinfo.hdr.hwndFrom = GetSafeHwnd();
    dispinfo.hdr.idFrom   = GetDlgCtrlID();
    dispinfo.hdr.code     = GVN_COMBOSELCHANGE;
    dispinfo.item.mask    = LVIF_TEXT|LVIF_PARAM;
    dispinfo.item.row     = m_nRow;
    dispinfo.item.col     = m_nCol;
    dispinfo.item.strText = str;
    dispinfo.item.lParam  = (LPARAM) m_nLastChar;
    CWnd* pOwner = GetOwner();
    if (IsWindow(pOwner->GetSafeHwnd()))
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo);
}
void CInPlaceList::OnKillFocus(CWnd* pNewWnd)
{
    CComboBox::OnKillFocus(pNewWnd);
    if (GetSafeHwnd() == pNewWnd->GetSafeHwnd())
        return;
    // Only end editing on change of focus if we're using the CBS_DROPDOWNLIST style
    if ((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST)
        EndEdit();
}
// If an arrow key (or associated) is pressed, then exit if
//  a) The Ctrl key was down, or
//  b) m_bExitOnArrows == TRUE
void CInPlaceList::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if ((nChar == VK_PRIOR || nChar == VK_NEXT ||
         nChar == VK_DOWN  || nChar == VK_UP   ||
         nChar == VK_RIGHT || nChar == VK_LEFT) &&
        (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0))
    {
        m_nLastChar = nChar;
        GetParent()->SetFocus();
        return;
    }
    CComboBox::OnKeyDown(nChar, nRepCnt, nFlags);
}
// Need to keep a lookout for Tabs, Esc and Returns.
void CInPlaceList::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (nChar == VK_ESCAPE)
        SetWindowText(m_sInitText);    // restore previous text
    if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
    {
        m_nLastChar = nChar;
        GetParent()->SetFocus();    // This will destroy this window
        return;
    }
    CComboBox::OnKeyUp(nChar, nRepCnt, nFlags);
}
HBRUSH CInPlaceList::CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/)
{
    /*
    static CBrush brush(m_crBackClr);
    pDC->SetTextColor(m_crForeClr);
    pDC->SetBkMode(TRANSPARENT);
    return (HBRUSH) brush.GetSafeHandle();
    */
    // TODO: Return a non-NULL brush if the parent's handler should not be called
    return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellCombo
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CGridCellCombo, CGridCell)
CGridCellCombo::CGridCellCombo() : CGridCell()
{
    SetStyle(CBS_DROPDOWN);  // CBS_DROPDOWN, CBS_DROPDOWNLIST, CBS_SIMPLE, CBS_SORT
}
// Create a control to do the editing
BOOL CGridCellCombo::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar)
{
    m_bEditing = TRUE;
    // CInPlaceList auto-deletes itself
    m_pEditWnd = new CInPlaceList(GetGrid(), rect, GetStyle(), nID, nRow, nCol,
                                  GetTextClr(), GetBackClr(), m_Strings, GetText(), nChar);
    return TRUE;
}
CWnd* CGridCellCombo::GetEditWnd() const
{
    if (m_pEditWnd && (m_pEditWnd->GetStyle() & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST )
        return &(((CInPlaceList*)m_pEditWnd)->m_edit);
    return NULL;
}
CSize CGridCellCombo::GetCellExtent(CDC* pDC)
{
    CSize sizeScroll (GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL));
    CSize sizeCell (CGridCell::GetCellExtent(pDC));
    sizeCell.cx += sizeScroll.cx;
    sizeCell.cy = max(sizeCell.cy,sizeScroll.cy);
    return sizeCell;
}
// Cancel the editing.
void CGridCellCombo::EndEdit()
{
    if (m_pEditWnd)
        ((CInPlaceList*)m_pEditWnd)->EndEdit();
}
// Override draw so that when the cell is selected, a drop arrow is shown in the RHS.
BOOL CGridCellCombo::Draw(CDC* pDC, int nRow, int nCol, CRect rect,  BOOL bEraseBkgnd /*=TRUE*/)
{
#ifdef _WIN32_WCE
    return CGridCell::Draw(pDC, nRow, nCol, rect,  bEraseBkgnd);
#else
    // Cell selected?
    //if ( !IsFixed() && IsFocused())
    if (GetGrid()->IsCellEditable(nRow, nCol) && !IsEditing())
    {
        // Get the size of the scroll box
        CSize sizeScroll(GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL));
        // enough room to draw?
        if (sizeScroll.cy < rect.Width() && sizeScroll.cy < rect.Height())
        {
            // Draw control at RHS of cell
            CRect ScrollRect = rect;
            ScrollRect.left   = rect.right - sizeScroll.cx;
            ScrollRect.bottom = rect.top + sizeScroll.cy;
            // Do the draw
            pDC->DrawFrameControl(ScrollRect, DFC_SCROLL, DFCS_SCROLLDOWN);
            // Adjust the remaining space in the cell
            rect.right = ScrollRect.left;
        }
    }
    CString strTempText = GetText();
    if (IsEditing())
        SetText(_T(""));
    // drop through and complete the cell drawing using the base class' method
    BOOL bResult = CGridCell::Draw(pDC, nRow, nCol, rect,  bEraseBkgnd);
    if (IsEditing())
        SetText(strTempText);
    return bResult;
#endif
}
// For setting the strings that will be displayed in the drop list
void CGridCellCombo::SetOptions(const CStringArray& ar)
{
    m_Strings.RemoveAll();
    for (int i = 0; i < ar.GetSize(); i++)
        m_Strings.Add(ar[i]);
}
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellCombo.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,178 @@
#if !defined(AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
/////////////////////////////////////////////////////////////////////////////
// GridCellCombo.h : header file
//
// MFC Grid Control - Grid combo cell class header file
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10
//
//////////////////////////////////////////////////////////////////////
#include "GridCell.h"
class CGridCellCombo : public CGridCell
{
    friend class CGridCtrl;
    DECLARE_DYNCREATE(CGridCellCombo)
public:
    CGridCellCombo();
// editing cells
public:
    virtual BOOL  Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
    virtual CWnd* GetEditWnd() const;
    virtual void  EndEdit();
// Operations
public:
    virtual CSize GetCellExtent(CDC* pDC);
// CGridCellCombo specific calls
public:
    void  SetOptions(const CStringArray& ar);
    void  SetStyle(DWORD dwStyle)           { m_dwStyle = dwStyle; }
    DWORD GetStyle()                        { return m_dwStyle;    }
protected:
    virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
    CStringArray m_Strings;
    DWORD        m_dwStyle;
};
/////////////////////////////////////////////////////////////////////////////
// CComboEdit window
#define IDC_COMBOEDIT 1001
class CComboEdit : public CEdit
{
// Construction
public:
    CComboEdit();
// Attributes
public:
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CComboEdit)
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CComboEdit();
    // Generated message map functions
protected:
    //{{AFX_MSG(CComboEdit)
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
// CInPlaceList window
class CInPlaceList : public CComboBox
{
    friend class CComboEdit;
// Construction
public:
    CInPlaceList(CWnd* pParent,         // parent
                 CRect& rect,           // dimensions & location
                 DWORD dwStyle,         // window/combobox style
                 UINT nID,              // control ID
                 int nRow, int nColumn, // row and column
                 COLORREF crFore, COLORREF crBack,  // Foreground, background colour
                 CStringArray& Items,   // Items in list
                 CString sInitText,     // initial selection
                 UINT nFirstChar);      // first character to pass to control
// Attributes
public:
   CComboEdit m_edit;  // subclassed edit control
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CInPlaceList)
    protected:
    virtual void PostNcDestroy();
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CInPlaceList();
    void EndEdit();
protected:
    int GetCorrectDropWidth();
// Generated message map functions
protected:
    //{{AFX_MSG(CInPlaceList)
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnDropdown();
    afx_msg void OnSelChange();
    afx_msg UINT OnGetDlgCode();
    afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
    //}}AFX_MSG
    //afx_msg void OnSelendOK();
    DECLARE_MESSAGE_MAP()
private:
    int         m_nNumLines;
    CString  m_sInitText;
    int         m_nRow;
    int         m_nCol;
     UINT     m_nLastChar;
    BOOL     m_bExitOnArrows;
    COLORREF m_crForeClr, m_crBackClr;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellDateTime.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,268 @@
///////////////////////////////////////////////////////////////////////////
//
// GridCellDateTime.cpp: implementation of the CGridCellDateTime class.
//
// Provides the implementation for a datetime picker cell type of the
// grid control.
//
// Written by Podsypalnikov Eugen 15 Mar 2001
// Modified:
//    31 May 2001  Fixed m_cTime bug (Chris Maunder)
//
// For use with CGridCtrl v2.22+
//
///////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCtrl.h"
#include "GridCellDateTime.h"
#ifdef _DEBUG
#undef THIS_FILE
static const char* THIS_FILE=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// CGridCellDateTime
IMPLEMENT_DYNCREATE(CGridCellDateTime, CGridCell)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGridCellDateTime::CGridCellDateTime() : CGridCell()
{
    m_dwStyle = 0;
    m_cTime   = CTime::GetCurrentTime();
}
CGridCellDateTime::CGridCellDateTime(DWORD dwStyle) : CGridCell()
{
    Init(dwStyle);
}
CGridCellDateTime::~CGridCellDateTime()
{
}
CSize CGridCellDateTime::GetCellExtent(CDC* pDC)
{
    CSize sizeScroll (GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL));
    CSize sizeCell (CGridCell::GetCellExtent(pDC));
    sizeCell.cx += sizeScroll.cx;
    sizeCell.cy = max(sizeCell.cy,sizeScroll.cy);
    return sizeCell;
}
BOOL CGridCellDateTime::Edit(int nRow, int nCol, CRect rect, CPoint /* point */,
                             UINT nID, UINT nChar)
{
    m_bEditing = TRUE;
    // CInPlaceDateTime auto-deletes itself
    m_pEditWnd = new CInPlaceDateTime(GetGrid(), rect,
        m_dwStyle|DTS_UPDOWN, nID, nRow, nCol,
        GetTextClr(), GetBackClr(), GetTime(), nChar);
    return TRUE;
}
CWnd* CGridCellDateTime::GetEditWnd() const
{
    return m_pEditWnd;
}
void CGridCellDateTime::EndEdit()
{
    if (m_pEditWnd) ((CInPlaceDateTime*)m_pEditWnd)->EndEdit();
}
void CGridCellDateTime::Init(DWORD dwStyle)
{
    m_dwStyle = dwStyle;
    SetTime(CTime::GetCurrentTime());
    SetFormat(DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX
#ifndef _WIN32_WCE
        |DT_END_ELLIPSIS
#endif
        );
}
// Should be changed to use locale settings
void CGridCellDateTime::SetTime(CTime time)
{
    m_cTime = time;
    if (DTS_TIMEFORMAT == m_dwStyle)
    {
#ifdef _WIN32_WCE
        CString strTemp;
        strTemp.Format(_T("%02d:%02d:%02d"),
                       m_cTime.GetHour(), m_cTime.GetMinute(), m_cTime.GetSecond());
        SetText(strTemp);
#else
//        SetText(m_cTime.Format(_T("%H:%M:%S")));
        SetText(m_cTime.Format(_T("%X")));
#endif
    }
    else if (DTS_SHORTDATEFORMAT == m_dwStyle)
    {
#ifdef _WIN32_WCE
        CString strTemp;
        strTemp.Format(_T("%02d/%02d/%02d"),
                       m_cTime.GetMonth(), m_cTime.GetDay(), m_cTime.GetYear());
        SetText(strTemp);
#else
//        SetText(m_cTime.Format(("%d/%m/%Y")));
        SetText(m_cTime.Format(("%x")));
#endif
    }
}
/////////////////////////////////////////////////////////////////////////////
// CInPlaceDateTime
CInPlaceDateTime::CInPlaceDateTime(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
                                   int nRow, int nColumn,
                                   COLORREF crFore, COLORREF crBack,
                                   CTime* pcTime,
                                   UINT nFirstChar)
{
    m_crForeClr     = crFore;
    m_crBackClr     = crBack;
    m_nRow          = nRow;
    m_nCol          = nColumn;
    m_nLastChar     = 0;
    m_bExitOnArrows = FALSE;
    m_pcTime        = pcTime;
    DWORD dwStl = WS_BORDER|WS_VISIBLE|WS_CHILD|dwStyle;
    if (!Create(dwStl, rect, pParent, nID)) {
        return;
    }
    SetTime(m_pcTime);
    SetFont(pParent->GetFont());
    SetFocus();
    switch (nFirstChar)
    {
        case VK_LBUTTON:
        case VK_RETURN: return;
        case VK_BACK:   break;
        case VK_DOWN:
        case VK_UP:
        case VK_RIGHT:
        case VK_LEFT:
        case VK_NEXT:
        case VK_PRIOR:
        case VK_HOME:
        case VK_END:    return;
        default:        break;
    }
    SendMessage(WM_CHAR, nFirstChar);
}
CInPlaceDateTime::~CInPlaceDateTime()
{
}
void CInPlaceDateTime::EndEdit()
{
    CString str;
    if (::IsWindow(m_hWnd))
    {
        GetWindowText(str);
        GetTime(*m_pcTime);
    }
    // Send Notification to parent
    GV_DISPINFO dispinfo;
    dispinfo.hdr.hwndFrom = GetSafeHwnd();
    dispinfo.hdr.idFrom   = GetDlgCtrlID();
    dispinfo.hdr.code     = GVN_ENDLABELEDIT;
    dispinfo.item.mask    = LVIF_TEXT|LVIF_PARAM;
    dispinfo.item.row     = m_nRow;
    dispinfo.item.col     = m_nCol;
    dispinfo.item.strText = str;
    dispinfo.item.lParam  = (LPARAM) m_nLastChar;
    CWnd* pOwner = GetOwner();
    if (IsWindow(pOwner->GetSafeHwnd())) {
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo);
    }
    // Close this window (PostNcDestroy will delete this)
    if (::IsWindow(m_hWnd)) {
        PostMessage(WM_CLOSE, 0, 0);
    }
}
void CInPlaceDateTime::PostNcDestroy()
{
    CDateTimeCtrl::PostNcDestroy();
    delete this;
}
BEGIN_MESSAGE_MAP(CInPlaceDateTime, CDateTimeCtrl)
    //{{AFX_MSG_MAP(CInPlaceDateTime)
    ON_WM_KILLFOCUS()
    ON_WM_KEYDOWN()
    ON_WM_KEYUP()
    ON_WM_GETDLGCODE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CInPlaceDateTime message handlers
void CInPlaceDateTime::OnKillFocus(CWnd* pNewWnd)
{
    CDateTimeCtrl::OnKillFocus(pNewWnd);
    if (GetSafeHwnd() == pNewWnd->GetSafeHwnd()) {
        return;
    }
    EndEdit();
}
UINT CInPlaceDateTime::OnGetDlgCode()
{
    return DLGC_WANTALLKEYS;
}
void CInPlaceDateTime::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (( nChar == VK_PRIOR || nChar == VK_NEXT ||
        nChar == VK_DOWN  || nChar == VK_UP   ||
        nChar == VK_RIGHT || nChar == VK_LEFT) &&
        (m_bExitOnArrows  || GetKeyState(VK_CONTROL) < 0))
    {
        m_nLastChar = nChar;
        GetParent()->SetFocus();
        return;
    }
    CDateTimeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CInPlaceDateTime::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
    {
        m_nLastChar = nChar;
        GetParent()->SetFocus();    // This will destroy this window
        return;
    }
    CDateTimeCtrl::OnKeyUp(nChar, nRepCnt, nFlags);
}
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellDateTime.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
// GridCellDateTime.h: interface for the CGridCellDateTime class.
//
// Provides the implementation for a datetime picker cell type of the
// grid control.
//
// For use with CGridCtrl v2.22+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_)
#define AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "GridCell.h"
#include "afxdtctl.h"    // for CDateTimeCtrl
class CGridCellDateTime : public CGridCell
{
  friend class CGridCtrl;
  DECLARE_DYNCREATE(CGridCellDateTime)
  CTime m_cTime;
  DWORD m_dwStyle;
public:
    CGridCellDateTime();
    CGridCellDateTime(DWORD dwStyle);
    virtual ~CGridCellDateTime();
    virtual CSize GetCellExtent(CDC* pDC);
  // editing cells
public:
    void Init(DWORD dwStyle);
    virtual BOOL  Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
    virtual CWnd* GetEditWnd() const;
    virtual void  EndEdit();
    CTime* GetTime() {return &m_cTime;};
    void   SetTime(CTime time);
};
class CInPlaceDateTime : public CDateTimeCtrl
{
// Construction
public:
    CInPlaceDateTime(CWnd* pParent,         // parent
                   CRect& rect,           // dimensions & location
                   DWORD dwStyle,         // window/combobox style
                   UINT nID,              // control ID
                   int nRow, int nColumn, // row and column
                   COLORREF crFore, COLORREF crBack,  // Foreground, background colour
                   CTime* pcTime,
                     UINT nFirstChar);      // first character to pass to control
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CInPlaceList)
    protected:
    virtual void PostNcDestroy();
    //}}AFX_VIRTUAL
// Implementation
public:
    virtual ~CInPlaceDateTime();
    void EndEdit();
// Generated message map functions
protected:
    //{{AFX_MSG(CInPlaceList)
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg UINT OnGetDlgCode();
    //}}AFX_MSG
    //afx_msg void OnSelendOK();
    DECLARE_MESSAGE_MAP()
private:
    CTime*   m_pcTime;
    int         m_nRow;
    int         m_nCol;
     UINT     m_nLastChar;
    BOOL     m_bExitOnArrows;
    COLORREF m_crForeClr, m_crBackClr;
};
#endif // !defined(AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_)
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellNumeric.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
// GridCellNumeric.cpp: implementation of the CGridCellNumeric class.
//
// Written by Andrew Truckle [ajtruckle@wsatkins.co.uk]
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCtrl.h"
#include "GridCellNumeric.h"
#include "Gridinplaceedit.h"
IMPLEMENT_DYNCREATE(CGridCellNumeric, CGridCell)
#ifdef _DEBUG
#undef THIS_FILE
static const char* THIS_FILE=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// Create a control to do the editing
BOOL CGridCellNumeric::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar)
{
    m_bEditing = TRUE;
    // CGridInPlaceEdit auto-deletes itself
    m_pEditWnd = new CGridInPlaceEdit(GetGrid(), rect, /*GetStyle() |*/ ES_NUMBER, nID, nRow, nCol,
        GetText(), nChar);
    return TRUE;
}
// Cancel the editing.
void CGridCellNumeric::EndEdit()
{
    if (m_pEditWnd)
        ((CGridInPlaceEdit*)m_pEditWnd)->EndEdit();
}
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridCellNumeric.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
// GridCellNumeric.h: interface for the CGridCellNumeric class.
//
// Written by Andrew Truckle [ajtruckle@wsatkins.co.uk]
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_)
#define AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "GridCell.h"
class CGridCellNumeric : public CGridCell
{
    DECLARE_DYNCREATE(CGridCellNumeric)
public:
    virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
    virtual void EndEdit();
};
#endif // !defined(AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_)
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridURLCell.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,212 @@
// GridURLCell.cpp: implementation of the CGridURLCell class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCtrl.h"
#include "GridURLCell.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CGridURLCell, CGridCell)
#ifndef _WIN32_WCE
HCURSOR CGridURLCell::g_hLinkCursor = NULL;
#endif
// Possible prefixes that indicate a hyperlink
URLStruct CGridURLCell::g_szURIprefixes[] = {
    { _T("www."),    _tcslen(_T("www."))    },
    { _T("http:"),   _tcslen(_T("http:"))   },
    { _T("mailto:"), _tcslen(_T("mailto:")) },
    { _T("ftp:"),    _tcslen(_T("ftp:"))    },
    { _T("https:"),  _tcslen(_T("https:"))  },
    { _T("news:"),   _tcslen(_T("news:"))   },
    { _T("gopher:"), _tcslen(_T("gopher:")) },
    { _T("telnet:"), _tcslen(_T("telnet:")) },
    { _T("url:"),    _tcslen(_T("url:"))    },
    { _T("file:"),   _tcslen(_T("file:"))   },
    { _T("ftp."),    _tcslen(_T("ftp."))    }
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGridURLCell::CGridURLCell()
{
#ifndef _WIN32_WCE
    g_hLinkCursor = GetHandCursor();
#endif
    m_bLaunchUrl = TRUE;
    m_clrUrl = GetSysColor(COLOR_HIGHLIGHT);
}
CGridURLCell::~CGridURLCell()
{
}
BOOL CGridURLCell::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd)
{
    // If url is present then change text color
    if (HasUrl(GetText()))
        SetTextClr(m_clrUrl);
    // Good a place as any to store the bounds of the rect
    m_Rect = rect;
    return CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd);
}
#pragma warning(disable:4100)
BOOL CGridURLCell::Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar)
{
    return FALSE;
}
#pragma warning(default:4100)
void CGridURLCell::OnClick(CPoint PointCellRelative)
{
#ifndef _WIN32_WCE
    CString strURL;
    if (GetAutoLaunchUrl() && OverURL(PointCellRelative, strURL))
        ShellExecute(NULL, _T("open"), strURL, NULL,NULL, SW_SHOW);
#endif
}
// Return TRUE if you set the cursor
BOOL CGridURLCell::OnSetCursor()
{
#ifndef _WIN32_WCE
    CString strURL;
    CPoint pt(GetMessagePos());
    GetGrid()->ScreenToClient(&pt);
    pt = pt - m_Rect.TopLeft();
    if (OverURL(pt, strURL))
    {
        SetCursor(g_hLinkCursor);
        return TRUE;
    }
    else
#endif
        return CGridCell::OnSetCursor();
}
#ifndef _WIN32_WCE
HCURSOR CGridURLCell::GetHandCursor()
{
    if (g_hLinkCursor == NULL)        // No cursor handle - load our own
    {
        // Get the windows directory
        CString strWndDir;
        GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
        strWndDir.ReleaseBuffer();
        strWndDir += _T("\\winhlp32.exe");
        // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
        HMODULE hModule = LoadLibrary(strWndDir);
        if( hModule )
        {
            HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
            if( hHandCursor )
            {
                g_hLinkCursor = CopyCursor(hHandCursor);
            }
        }
        FreeLibrary(hModule);
    }
    return g_hLinkCursor;
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Helper functions
BOOL CGridURLCell::HasUrl(CString str)
{
    int nNumPrefixes = sizeof(g_szURIprefixes) / sizeof(g_szURIprefixes[0]);
    for (int i = 0; i < nNumPrefixes; i++)
        //if (str.Left(g_szURIprefixes[i].nLength) == g_szURIprefixes[i].szURLPrefix)
        if (str.Find(g_szURIprefixes[i].szURLPrefix) >= 0)
            return TRUE;
    return FALSE;
}
// here we figure out if we are over a URL or not
BOOL CGridURLCell::OverURL(CPoint& pt, CString& strURL)
{
    //TRACE2("Checking point %d,%d\n",pt.x,pt.y);
    BOOL bOverURL = FALSE;
    CSize size = GetTextExtent(GetText());
    // Add left of cell so we know if we clicked on text or not
    pt.x += m_Rect.left;
    CPoint center = m_Rect.CenterPoint();
    if ((m_nFormat & DT_RIGHT) && pt.x >= (m_Rect.right - size.cx))
    {
        bOverURL = TRUE;
    }
    else if ((m_nFormat & DT_CENTER) &&
             ((center.x - (size.cx/2)) <= pt.x) && (pt.x <= (center.x + (size.cx/2))) )
    {
        bOverURL = TRUE;
    }
    else if (pt.x <= (size.cx + m_Rect.left))
    {
        bOverURL = TRUE;
    }
    if (!bOverURL)
        return FALSE;
    // We are over text - but are we over a URL?
    bOverURL = FALSE;
    strURL = GetText();
    // Use float, otherwise we get an incorrect letter from the point
    float width = (float)size.cx/(float)strURL.GetLength();
    // remove left of cell so we have original point again
    pt.x -= m_Rect.left;
    if (m_nFormat & DT_RIGHT)
    {
        int wide = m_Rect.Width() - size.cx;
        pt.x -= wide;
        if (pt.x <= 0)
            return FALSE;
    }
    if (m_nFormat & DT_CENTER)
    {
        int wide = m_Rect.Width() - size.cx;
        pt.x -= (wide/2);
        if (pt.x <= 0 || pt.x > (size.cx + (wide/2)))
            return FALSE;
    }
    // Turn point into a letter
    int ltrs = (int)((float)pt.x/width);
#if  !defined(_WIN32_WCE) || (_WIN32_WCE > 210)
    // Find spaces before and after letter, process text between
    int endSpace = strURL.Find(_T(' '), ltrs);
    if (endSpace != -1)
        strURL.Delete(endSpace, strURL.GetLength()-endSpace);
    int beginSpace = strURL.ReverseFind(_T(' '));
    if (beginSpace != -1)
        strURL.Delete(0, ++beginSpace);
#endif
    // Does text have url
    return HasUrl(strURL);
}
SourceCode/Bond/Servo/GridControl/NewCellTypes/GridURLCell.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
// GridURLCell.h: interface for the CGridURLCell class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDURLCELL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_)
#define AFX_GRIDURLCELL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "GridCell.h"
typedef struct {
    LPCTSTR szURLPrefix;
    size_t  nLength;
} URLStruct;
class CGridURLCell : public CGridCell
{
    DECLARE_DYNCREATE(CGridURLCell)
public:
    CGridURLCell();
    virtual ~CGridURLCell();
    virtual BOOL     Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
    virtual BOOL     Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
    virtual LPCTSTR  GetTipText() { return NULL; }
    void SetAutoLaunchUrl(BOOL bLaunch = TRUE) { m_bLaunchUrl = bLaunch;    }
    BOOL GetAutoLaunchUrl() { return m_bLaunchUrl;    }
protected:
    virtual BOOL OnSetCursor();
    virtual void OnClick(CPoint PointCellRelative);
    BOOL HasUrl(CString str);
    BOOL OverURL(CPoint& pt, CString& strURL);
protected:
#ifndef _WIN32_WCE
    static HCURSOR g_hLinkCursor;        // Hyperlink mouse cursor
    HCURSOR GetHandCursor();
#endif
    static URLStruct g_szURIprefixes[];
protected:
    COLORREF m_clrUrl;
    BOOL     m_bLaunchUrl;
    CRect    m_Rect;
};
#endif // !defined(AFX_GRIDURLCELL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_)
SourceCode/Bond/Servo/GridControl/TitleTip.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,341 @@
////////////////////////////////////////////////////////////////////////////
// TitleTip.cpp : implementation file
//
// Based on code by Zafir Anjum
//
// Adapted by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
// History
//         10 Apr 1999  Now accepts a LOGFONT pointer and
//                      a tracking rect in Show(...)  (Chris Maunder)
//         18 Apr 1999  Resource leak in Show fixed by Daniel Gehriger
//          8 Mar 2000  Added double-click fix found on codeguru
//                      web site but forgot / can't find who contributed it
//         28 Mar 2000  Aqiruse (marked with //FNA)
//                      Titletips now use cell color
//         18 Jun 2000  Delayed window creation added
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "gridctrl.h"
#ifndef GRIDCONTROL_NO_TITLETIPS
#include "TitleTip.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char* THIS_FILE = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTitleTip
CTitleTip::CTitleTip()
{
    // Register the window class if it has not already been registered.
    WNDCLASS wndcls;
    HINSTANCE hInst = AfxGetInstanceHandle();
    if(!(::GetClassInfo(hInst, TITLETIP_CLASSNAME, &wndcls)))
    {
        // otherwise we need to register a new class
        wndcls.style            = CS_SAVEBITS;
        wndcls.lpfnWndProc        = ::DefWindowProc;
        wndcls.cbClsExtra        = wndcls.cbWndExtra = 0;
        wndcls.hInstance        = hInst;
        wndcls.hIcon            = NULL;
        wndcls.hCursor            = LoadCursor( hInst, IDC_ARROW );
        wndcls.hbrBackground    = (HBRUSH)(COLOR_INFOBK +1);
        wndcls.lpszMenuName        = NULL;
        wndcls.lpszClassName    = TITLETIP_CLASSNAME;
        if (!AfxRegisterClass(&wndcls))
            AfxThrowResourceException();
    }
    m_dwLastLButtonDown = ULONG_MAX;
    m_dwDblClickMsecs   = GetDoubleClickTime();
    m_bCreated          = FALSE;
    m_pParentWnd        = NULL;
}
CTitleTip::~CTitleTip()
{
}
BEGIN_MESSAGE_MAP(CTitleTip, CWnd)
    //{{AFX_MSG_MAP(CTitleTip)
    ON_WM_MOUSEMOVE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTitleTip message handlers
BOOL CTitleTip::Create(CWnd * pParentWnd)
{
//    ASSERT_VALID(pParentWnd);
    // Already created?
    if (m_bCreated)
        return TRUE;
    DWORD dwStyle = WS_BORDER | WS_POPUP;
    DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
    m_pParentWnd = pParentWnd;
    m_bCreated = CreateEx(dwExStyle, TITLETIP_CLASSNAME, NULL, dwStyle,
                          CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, NULL );
    return m_bCreated;
}
BOOL CTitleTip::DestroyWindow()
{
    m_bCreated = FALSE;
    return CWnd::DestroyWindow();
}
// Show          - Show the titletip if needed
// rectTitle     - The rectangle within which the original
//                    title is constrained - in client coordinates
// lpszTitleText - The text to be displayed
// xoffset         - Number of pixel that the text is offset from
//                   left border of the cell
void CTitleTip::Show(CRect rectTitle, LPCTSTR lpszTitleText, int xoffset /*=0*/,
                     LPRECT lpHoverRect /*=NULL*/,
                     const LOGFONT* lpLogFont /*=NULL*/,
                     COLORREF crTextClr /* CLR_DEFAULT */,
                     COLORREF crBackClr /* CLR_DEFAULT */)
{
    if (!IsWindow(m_hWnd))
        Create(m_pParentWnd);
//    ASSERT( ::IsWindow( GetSafeHwnd() ) );
    if (rectTitle.IsRectEmpty())
        return;
    // If titletip is already displayed, don't do anything.
    if( IsWindowVisible() )
        return;
    m_rectHover = (lpHoverRect != NULL)? lpHoverRect : rectTitle;
    m_rectHover.right++; m_rectHover.bottom++;
    m_pParentWnd->ClientToScreen( m_rectHover );
    ScreenToClient( m_rectHover );
    // Do not display the titletip is app does not have focus
    if( GetFocus() == NULL )
        return;
    // Define the rectangle outside which the titletip will be hidden.
    // We add a buffer of one pixel around the rectangle
    m_rectTitle.top    = -1;
    m_rectTitle.left   = -xoffset-1;
    m_rectTitle.right  = rectTitle.Width()-xoffset;
    m_rectTitle.bottom = rectTitle.Height()+1;
    // Determine the width of the text
    m_pParentWnd->ClientToScreen( rectTitle );
    CClientDC dc(this);
    CString strTitle = _T("");
    strTitle += _T(" ");
    strTitle += lpszTitleText;
    strTitle += _T(" ");
    CFont font, *pOldFont = NULL;
    if (lpLogFont)
    {
        font.CreateFontIndirect(lpLogFont);
        pOldFont = dc.SelectObject( &font );
    }
    else
    {
        // use same font as ctrl
        pOldFont = dc.SelectObject( m_pParentWnd->GetFont() );
    }
    CSize size = dc.GetTextExtent( strTitle );
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    size.cx += tm.tmOverhang;
    CRect rectDisplay = rectTitle;
    rectDisplay.left += xoffset;
    rectDisplay.right = rectDisplay.left + size.cx + xoffset;
    // Do not display if the text fits within available space
    if ( rectDisplay.right > rectTitle.right-xoffset )
    {
        // Show the titletip
        SetWindowPos( &wndTop, rectDisplay.left, rectDisplay.top,
            rectDisplay.Width(), rectDisplay.Height(),
            SWP_SHOWWINDOW|SWP_NOACTIVATE );
        // FNA - handle colors correctly
        if (crBackClr != CLR_DEFAULT)
        {
            CBrush backBrush(crBackClr);
            CBrush* pOldBrush = dc.SelectObject(&backBrush);
            CRect rect;
            dc.GetClipBox(&rect);     // Erase the area needed
            dc.PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),  PATCOPY);
            dc.SelectObject(pOldBrush);
        }
        // Set color
        if (crTextClr != CLR_DEFAULT)//FNA
            dc.SetTextColor(crTextClr);//FA
        dc.SetBkMode( TRANSPARENT );
        dc.TextOut( 0, 0, strTitle );
        SetCapture();
    }
    dc.SelectObject( pOldFont );
}
void CTitleTip::Hide()
{
      if (!::IsWindow(GetSafeHwnd()))
        return;
    if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
        ReleaseCapture();
    ShowWindow( SW_HIDE );
}
void CTitleTip::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!m_rectHover.PtInRect(point))
    {
        Hide();
        // Forward the message
        ClientToScreen( &point );
        CWnd *pWnd = WindowFromPoint( point );
        if ( pWnd == this )
            pWnd = m_pParentWnd;
        int hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y));
        if (hittest == HTCLIENT) {
            pWnd->ScreenToClient( &point );
            pWnd->PostMessage( WM_MOUSEMOVE, nFlags, MAKELONG(point.x,point.y) );
        } else {
            pWnd->PostMessage( WM_NCMOUSEMOVE, hittest, MAKELONG(point.x,point.y) );
        }
    }
}
BOOL CTitleTip::PreTranslateMessage(MSG* pMsg)
{
    // Used to qualify WM_LBUTTONDOWN messages as double-clicks
    DWORD dwTick=0;
    BOOL bDoubleClick=FALSE;
    CWnd *pWnd;
    int hittest;
    switch (pMsg->message)
    {
    case WM_LBUTTONDOWN:
       // Get tick count since last LButtonDown
        dwTick = GetTickCount();
        bDoubleClick = ((dwTick - m_dwLastLButtonDown) <= m_dwDblClickMsecs);
        m_dwLastLButtonDown = dwTick;
        // NOTE: DO NOT ADD break; STATEMENT HERE! Let code fall through
    case WM_RBUTTONDOWN:
    case WM_MBUTTONDOWN:
        {
        POINTS pts = MAKEPOINTS( pMsg->lParam );
        POINT  point;
        point.x = pts.x;
        point.y = pts.y;
        ClientToScreen( &point );
        Hide();
        pWnd = WindowFromPoint( point );
        if (!pWnd)
            return CWnd::PreTranslateMessage(pMsg);
        if( pWnd->GetSafeHwnd() == GetSafeHwnd())
            pWnd = m_pParentWnd;
        hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y));
        if (hittest == HTCLIENT)
        {
            pWnd->ScreenToClient( &point );
            pMsg->lParam = MAKELONG(point.x,point.y);
        }
        else
        {
            switch (pMsg->message) {
            case WM_LBUTTONDOWN:
                pMsg->message = WM_NCLBUTTONDOWN;
                break;
            case WM_RBUTTONDOWN:
                pMsg->message = WM_NCRBUTTONDOWN;
                break;
            case WM_MBUTTONDOWN:
                pMsg->message = WM_NCMBUTTONDOWN;
                break;
            }
            pMsg->wParam = hittest;
            pMsg->lParam = MAKELONG(point.x,point.y);
        }
        // If this is the 2nd WM_LBUTTONDOWN in x milliseconds,
        // post a WM_LBUTTONDBLCLK message instead of a single click.
        pWnd->PostMessage(  bDoubleClick ? WM_LBUTTONDBLCLK : pMsg->message,
                            pMsg->wParam,
                            pMsg->lParam);
        return TRUE;
        }
    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
        Hide();
        m_pParentWnd->PostMessage( pMsg->message, pMsg->wParam, pMsg->lParam );
        return TRUE;
    }
    if( GetFocus() == NULL )
    {
        Hide();
        return TRUE;
    }
    return CWnd::PreTranslateMessage(pMsg);
}
#endif // GRIDCONTROL_NO_TITLETIPS
SourceCode/Bond/Servo/GridControl/TitleTip.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
/////////////////////////////////////////////////////////////////////////////
// Titletip.h : header file
//
// MFC Grid Control - cell titletips
//
// Written by Chris Maunder <chris@codeproject.com>
// Copyright (c) 1998-2005. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#define TITLETIP_CLASSNAME _T("ZTitleTip")
/////////////////////////////////////////////////////////////////////////////
// CTitleTip window
class CTitleTip : public CWnd
{
// Construction
public:
    CTitleTip();
    virtual ~CTitleTip();
    virtual BOOL Create( CWnd *pParentWnd);
// Attributes
public:
    void SetParentWnd(CWnd* pParentWnd)  { m_pParentWnd = pParentWnd; }
    CWnd* GetParentWnd()                 { return m_pParentWnd;       }
// Operations
public:
    void Show(CRect rectTitle, LPCTSTR lpszTitleText,
              int xoffset = 0, LPRECT lpHoverRect = NULL,
              const LOGFONT* lpLogFont = NULL,
              COLORREF crTextClr = CLR_DEFAULT, COLORREF crBackClr = CLR_DEFAULT);
    void Hide();
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CTitleTip)
    public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    virtual BOOL DestroyWindow();
    //}}AFX_VIRTUAL
// Implementation
protected:
    CWnd  *m_pParentWnd;
    CRect  m_rectTitle;
    CRect  m_rectHover;
    DWORD  m_dwLastLButtonDown;
    DWORD  m_dwDblClickMsecs;
    BOOL   m_bCreated;
    // Generated message map functions
protected:
    //{{AFX_MSG(CTitleTip)
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_)
SourceCode/Bond/Servo/PageRobotCmd.cpp
@@ -10,18 +10,18 @@
// CPageRobotCmd å¯¹è¯æ¡†
std::map<CString, int> g_deviceSlotCount = {
    {_T("PORT 1"), 1},
    {_T("PORT 2"), 1},
    {_T("PORT 3"), 1},
    {_T("PORT 4"), 1},
    {_T("PORT 1"), 8},
    {_T("PORT 2"), 8},
    {_T("PORT 3"), 8},
    {_T("PORT 4"), 8},
    {_T("RB1"), 1},
    {_T("RB2"), 1},
    {_T("ALIGN"), 1},
    {_T("FLIP"), 1},
    {_T("VAC BAKE"), 2},
    {_T("VAC BAKE"), 4},
    {_T("BONDER1"), 2},
    {_T("BONDER2"), 2},
    {_T("POST BAKE(COOLING)"), 4},
    {_T("POST BAKE(COOLING)"), 2},
    {_T("MEASUREMENT"), 1}
};
SourceCode/Bond/Servo/PortConfigurationDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,146 @@
// PortConfigurationDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "afxdialogex.h"
#include "PortConfigurationDlg.h"
#include "NewCellTypes/GridCellCheck.h"
#include "NewCellTypes/GridCellCombo.h"
#include "NewCellTypes/GridCellNumeric.h"
// CPortConfigurationDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CPortConfigurationDlg, CDialogEx)
CPortConfigurationDlg::CPortConfigurationDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_PORT_CONFIGURATION, pParent)
{
}
CPortConfigurationDlg::~CPortConfigurationDlg()
{
}
void CPortConfigurationDlg::InitGrid()
{
    if (m_wndGrid.GetSafeHwnd() == NULL) {
        return;
    }
    const int nCols = 3;
    const int nFixRows = 1;
    const int nRows = 9;
    int nColIdx = 0;
    m_wndGrid.DeleteAllItems();
    m_wndGrid.SetVirtualMode(FALSE);
    // è®¾ç½®æ ·å¼é¢œè‰²
    m_wndGrid.GetDefaultCell(TRUE, FALSE)->SetBackClr(g_nGridFixCellColor);
    m_wndGrid.GetDefaultCell(FALSE, TRUE)->SetBackClr(g_nGridFixCellColor);
    m_wndGrid.GetDefaultCell(FALSE, FALSE)->SetBackClr(g_nGridCellColor);
    m_wndGrid.SetFixedTextColor(g_nGridFixFontColor);
    // è¡Œåˆ—数量
    m_wndGrid.SetRowCount(nRows);
    m_wndGrid.SetColumnCount(nCols);
    m_wndGrid.SetFixedRowCount(nFixRows);
    m_wndGrid.SetFixedColumnCount(0);
    // è®¾ç½®åˆ—宽
    m_wndGrid.SetColumnWidth(nColIdx, 50);
    m_wndGrid.SetItemText(0, nColIdx++, _T("Slot ID"));
    m_wndGrid.SetColumnWidth(nColIdx, 150);
    m_wndGrid.SetItemText(0, nColIdx++, _T("EQ Recipe"));
    m_wndGrid.SetColumnWidth(nColIdx, 150);
    m_wndGrid.SetItemText(0, nColIdx++, _T("Panel ID"));
    m_wndGrid.SetColumnWidth(nColIdx, 60);
    m_wndGrid.SetItemText(0, nColIdx++, _T("启用"));
    // è®¾ç½®è¡Œä¸ºæ ·å¼
    m_wndGrid.SetFixedRowSelection(FALSE);
    m_wndGrid.SetFixedColumnSelection(FALSE);
    m_wndGrid.SetEditable(TRUE);
    m_wndGrid.SetRowResize(FALSE);
    m_wndGrid.SetColumnResize(TRUE);
    m_wndGrid.SetListMode(TRUE);
    m_wndGrid.EnableSelection(TRUE);
    m_wndGrid.SetSingleRowSelection(TRUE);
    m_wndGrid.ExpandColumnsToFit(TRUE);
    m_wndGrid.ExpandLastColumn();
    // è‡ªåŠ¨è®¡ç®—å¹¶è®¾ç½®æ¯è¡Œé«˜åº¦
    CRect rcClient;
    m_wndGrid.GetClientRect(&rcClient);
    int nAvailableHeight = rcClient.Height();
    int nEachRowHeight = max(24, nAvailableHeight / nRows);
    for (int i = 0; i < nRows; ++i) {
        m_wndGrid.SetRowHeight(i, nEachRowHeight);
    }
    FillGrid();
}
void CPortConfigurationDlg::FillGrid()
{
    //CStringArray recipeOptions;
    //recipeOptions.Add(_T("Recipe A"));
    //recipeOptions.Add(_T("Recipe B"));
    //recipeOptions.Add(_T("Recipe C"));
    for (int i = 1; i < 9; ++i) {
        CString strIndex;
        strIndex.Format(_T("%d"), i);
        m_wndGrid.SetItemText(i, 0, strIndex);
        m_wndGrid.SetItemState(i, 0, GVIS_READONLY);
        // EQ Recipe - ComboBox
        //if (m_wndGrid.SetCellType(i, 1, RUNTIME_CLASS(CGridCellCombo))) {
        //    CGridCellCombo* pCell = static_cast<CGridCellCombo*>(m_wndGrid.GetCell(i, 1));
        //    pCell->SetOptions(recipeOptions);
        //    pCell->SetStyle(CBS_DROPDOWNLIST);
        //}
        //m_wndGrid.SetItemText(i, 1, recipeOptions[0]);
        // Panel ID - å¯ç¼–辑
        m_wndGrid.SetItemText(i, 1, _T(""));
        // Checkbox
        m_wndGrid.SetCellType(i, 2, RUNTIME_CLASS(CGridCellCheck));
        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 2));
        if (pCheck) {
            pCheck->SetCheck(FALSE);
        }
    }
    m_wndGrid.Invalidate();
    m_wndGrid.UpdateWindow();
}
void CPortConfigurationDlg::DoDataExchange(CDataExchange* pDX)
{
    DDX_Control(pDX, IDC_GRID_PANEL_RECIPE, m_wndGrid);
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPortConfigurationDlg, CDialogEx)
END_MESSAGE_MAP()
// CPortConfigurationDlg æ¶ˆæ¯å¤„理程序
BOOL CPortConfigurationDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    InitGrid();
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
SourceCode/Bond/Servo/PortConfigurationDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
#pragma once
#include "afxdialogex.h"
#include "GridCtrl.h"
// CPortConfigurationDlg å¯¹è¯æ¡†
class CPortConfigurationDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CPortConfigurationDlg)
public:
    CPortConfigurationDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CPortConfigurationDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_PORT_CONFIGURATION };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    DECLARE_MESSAGE_MAP()
private:
    CGridCtrl m_wndGrid;
    void InitGrid();
    void FillGrid();
};
SourceCode/Bond/Servo/Servo.cpp
@@ -8,7 +8,7 @@
#include "ServoGraph.h"
#include "AlarmManager.h"
#include "SECSRuntimeManager.h"
#include "ProductionLogManager.h"
#include "TransferManager.h"
#include "VerticalLine.h"
#include "EqsGraphWnd.h"
#include "MapPosWnd.h"
@@ -132,22 +132,6 @@
    }
    AlarmManager::getInstance().insertMockData();
    // åˆå§‹åŒ–生产履历管理器
    //try {
    //    if (!ProductionLogManager::getInstance().initProductionTable()) {
    //        AfxMessageBox("初始化生产履历管理器失败!");
    //        return FALSE;
    //    }
    //}
    //catch (const std::exception& ex) {
    //    CString errorMsg;
    //    errorMsg.Format(_T("初始化生产履历管理器失败:%s"), CString(ex.what()));
    //    AfxMessageBox(errorMsg, MB_ICONERROR);
    //    return FALSE;
    //}
    // åˆå§‹åŒ–SECS运行设置管理库
    try {
        if (!SECSRuntimeManager::getInstance().initRuntimeSetting()) {
@@ -158,6 +142,20 @@
    catch (const std::exception& ex) {
        CString errorMsg;
        errorMsg.Format(_T("初始化SECS运行设置失败:%s"), CString(ex.what()));
        AfxMessageBox(errorMsg, MB_ICONERROR);
        return FALSE;
    }
    // åˆå§‹åŒ–搬运记录管理库
    try {
        if (!TransferManager::getInstance().initTransferTable()) {
            AfxMessageBox("初始化搬运记录管理库设置失败!");
            return FALSE;
        }
    }
    catch (const std::exception& ex) {
        CString errorMsg;
        errorMsg.Format(_T("初始化搬运记录管理库设置失败:%s"), CString(ex.what()));
        AfxMessageBox(errorMsg, MB_ICONERROR);
        return FALSE;
    }
@@ -205,12 +203,12 @@
    // é”€æ¯æŠ¥è­¦è¡¨
    AlarmManager::getInstance().termAlarmTable();
    // é”€æ¯ç”Ÿäº§è¡¨
    ProductionLogManager::getInstance().termProductionTable();
    // é”€æ¯SECS运行设置管理库
    SECSRuntimeManager::getInstance().termRuntimeSetting();
    // é”€æ¯æ¬è¿è®°å½•管理库
    TransferManager::getInstance().termTransferTable();
    return CWinApp::ExitInstance();
}
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -115,7 +115,7 @@
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
      <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;..\MELSECSDK\include;.\CCLinkPerformance;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;..\MELSECSDK\include;.\CCLinkPerformance;.\GridControl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
@@ -204,6 +204,20 @@
    <ClInclude Include="CRobotCmdTestDlg.h" />
    <ClInclude Include="CPagePortStatus.h" />
    <ClInclude Include="CPortStatusReport.h" />
    <ClInclude Include="GridControl\CellRange.h" />
    <ClInclude Include="GridControl\GridCell.h" />
    <ClInclude Include="GridControl\GridCellBase.h" />
    <ClInclude Include="GridControl\GridCellButton.h" />
    <ClInclude Include="GridControl\GridCtrl.h" />
    <ClInclude Include="GridControl\GridDropTarget.h" />
    <ClInclude Include="GridControl\GridInPlaceEdit.h" />
    <ClInclude Include="GridControl\GridMemDC.h" />
    <ClInclude Include="GridControl\NewCellTypes\GridCellCheck.h" />
    <ClInclude Include="GridControl\NewCellTypes\GridCellCombo.h" />
    <ClInclude Include="GridControl\NewCellTypes\GridCellDateTime.h" />
    <ClInclude Include="GridControl\NewCellTypes\GridCellNumeric.h" />
    <ClInclude Include="GridControl\NewCellTypes\GridURLCell.h" />
    <ClInclude Include="GridControl\TitleTip.h" />
    <ClInclude Include="JobSlotGrid.h" />
    <ClInclude Include="MsgDlg.h" />
    <ClInclude Include="PageRecipe.h" />
@@ -290,6 +304,7 @@
    <ClInclude Include="MapPosWnd.h" />
    <ClInclude Include="Model.h" />
    <ClInclude Include="PageRobotCmd.h" />
    <ClInclude Include="PortConfigurationDlg.h" />
    <ClInclude Include="ProductionLogManager.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SECSRuntimeManager.h" />
@@ -302,6 +317,7 @@
    <ClInclude Include="targetver.h" />
    <ClInclude Include="TerminalDisplayDlg.h" />
    <ClInclude Include="ToolUnits.h" />
    <ClInclude Include="TransferManager.h" />
    <ClInclude Include="VerticalLine.h" />
  </ItemGroup>
  <ItemGroup>
@@ -311,6 +327,18 @@
    <ClCompile Include="CRobotCmdTestDlg.cpp" />
    <ClCompile Include="CPagePortStatus.cpp" />
    <ClCompile Include="CPortStatusReport.cpp" />
    <ClCompile Include="GridControl\GridCell.cpp" />
    <ClCompile Include="GridControl\GridCellBase.cpp" />
    <ClCompile Include="GridControl\GridCellButton.cpp" />
    <ClCompile Include="GridControl\GridCtrl.cpp" />
    <ClCompile Include="GridControl\GridDropTarget.cpp" />
    <ClCompile Include="GridControl\GridInPlaceEdit.cpp" />
    <ClCompile Include="GridControl\NewCellTypes\GridCellCheck.cpp" />
    <ClCompile Include="GridControl\NewCellTypes\GridCellCombo.cpp" />
    <ClCompile Include="GridControl\NewCellTypes\GridCellDateTime.cpp" />
    <ClCompile Include="GridControl\NewCellTypes\GridCellNumeric.cpp" />
    <ClCompile Include="GridControl\NewCellTypes\GridURLCell.cpp" />
    <ClCompile Include="GridControl\TitleTip.cpp" />
    <ClCompile Include="JobSlotGrid.cpp" />
    <ClCompile Include="MsgDlg.cpp" />
    <ClCompile Include="PageRecipe.cpp" />
@@ -396,6 +424,7 @@
    <ClCompile Include="MapPosWnd.cpp" />
    <ClCompile Include="Model.cpp" />
    <ClCompile Include="PageRobotCmd.cpp" />
    <ClCompile Include="PortConfigurationDlg.cpp" />
    <ClCompile Include="ProductionLogManager.cpp" />
    <ClCompile Include="SECSRuntimeManager.cpp" />
    <ClCompile Include="SecsTestDlg.cpp" />
@@ -410,6 +439,7 @@
    </ClCompile>
    <ClCompile Include="TerminalDisplayDlg.cpp" />
    <ClCompile Include="ToolUnits.cpp" />
    <ClCompile Include="TransferManager.cpp" />
    <ClCompile Include="VerticalLine.cpp" />
  </ItemGroup>
  <ItemGroup>
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -112,6 +112,44 @@
    <ClCompile Include="MsgDlg.cpp" />
    <ClCompile Include="CPagePortStatus.cpp" />
    <ClCompile Include="JobSlotGrid.cpp" />
    <ClCompile Include="GridControl\GridCell.cpp">
      <Filter>GridControl</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\GridCellBase.cpp">
      <Filter>GridControl</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\GridCellButton.cpp">
      <Filter>GridControl</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\GridCtrl.cpp">
      <Filter>GridControl</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\GridDropTarget.cpp">
      <Filter>GridControl</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\GridInPlaceEdit.cpp">
      <Filter>GridControl</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\TitleTip.cpp">
      <Filter>GridControl</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\NewCellTypes\GridCellCheck.cpp">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\NewCellTypes\GridCellCombo.cpp">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\NewCellTypes\GridCellDateTime.cpp">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\NewCellTypes\GridCellNumeric.cpp">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClCompile>
    <ClCompile Include="GridControl\NewCellTypes\GridURLCell.cpp">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClCompile>
    <ClCompile Include="PortConfigurationDlg.cpp" />
    <ClCompile Include="TransferManager.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -223,6 +261,50 @@
    <ClInclude Include="CPagePortStatus.h" />
    <ClInclude Include="ServoCommo.h" />
    <ClInclude Include="JobSlotGrid.h" />
    <ClInclude Include="GridControl\CellRange.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\GridCell.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\GridCellBase.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\GridCellButton.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\GridCtrl.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\GridDropTarget.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\GridInPlaceEdit.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\GridMemDC.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\TitleTip.h">
      <Filter>GridControl</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\NewCellTypes\GridCellCheck.h">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\NewCellTypes\GridCellCombo.h">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\NewCellTypes\GridCellDateTime.h">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\NewCellTypes\GridCellNumeric.h">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClInclude>
    <ClInclude Include="GridControl\NewCellTypes\GridURLCell.h">
      <Filter>GridControl\NewCellTypes</Filter>
    </ClInclude>
    <ClInclude Include="PortConfigurationDlg.h" />
    <ClInclude Include="TransferManager.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
@@ -241,5 +323,11 @@
    <Filter Include="CCLinkPerformance">
      <UniqueIdentifier>{77338295-9841-4706-8816-a958b1b5c465}</UniqueIdentifier>
    </Filter>
    <Filter Include="GridControl">
      <UniqueIdentifier>{1206b229-6054-40f2-8d8a-5848582a3896}</UniqueIdentifier>
    </Filter>
    <Filter Include="GridControl\NewCellTypes">
      <UniqueIdentifier>{52ebd40d-fb71-4a53-93ab-5b93670c706d}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
</Project>
SourceCode/Bond/Servo/Servo.vcxproj.user
@@ -4,8 +4,8 @@
    <RESOURCE_FILE>Servo.rc</RESOURCE_FILE>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <RemoteDebuggerCommand>D:\Servo\Debug\Servo.exe</RemoteDebuggerCommand>
    <RemoteDebuggerWorkingDirectory>D:\Servo\Debug\</RemoteDebuggerWorkingDirectory>
    <RemoteDebuggerCommand>\\DESKTOP-IODBVIQ\Servo\Debug\Servo.exe</RemoteDebuggerCommand>
    <RemoteDebuggerWorkingDirectory>\\DESKTOP-IODBVIQ\Servo\Debug\</RemoteDebuggerWorkingDirectory>
    <RemoteDebuggerServerName>DESKTOP-IODBVIQ</RemoteDebuggerServerName>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
SourceCode/Bond/Servo/TransferManager.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,550 @@
#include "stdafx.h"
#include "TransferManager.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <ctime>
#include <stdexcept>
// é™æ€äº’斥锁初始化
std::mutex TransferManager::m_mutex;
// èŽ·å– TransferManager å•例
TransferManager& TransferManager::getInstance() {
    static TransferManager instance;
    return instance;
}
// æž„造函数
TransferManager::TransferManager() {
    m_pDB = new BL::SQLiteDatabase();
}
// æžæž„函数
TransferManager::~TransferManager() {
    if (m_pDB) {
        delete m_pDB;
        m_pDB = nullptr;
    }
}
// ä»»åŠ¡çŠ¶æ€è½¬æ¢æˆ int ç±»åž‹
int TransferManager::statusToInt(TransferStatus status) {
    return static_cast<int>(status);
}
// int ç±»åž‹è½¬æ¢æˆä»»åŠ¡çŠ¶æ€
TransferStatus TransferManager::intToStatus(int value) {
    switch (value) {
        case 0: return TransferStatus::Ready;
        case 1: return TransferStatus::Running;
        case 2: return TransferStatus::Error;
        case 3: return TransferStatus::Abort;
        case 4: return TransferStatus::Completed;
        default: return TransferStatus::Error;
    }
}
// ä»»åŠ¡çŠ¶æ€è½¬æ¢æˆå­—ç¬¦ä¸²
std::string TransferManager::statusToString(TransferStatus status) {
    switch (status) {
        case TransferStatus::Ready:     return "Ready";
        case TransferStatus::Running:   return "Running";
        case TransferStatus::Error:     return "Error";
        case TransferStatus::Abort:     return "Abort";
        case TransferStatus::Completed: return "Completed";
        default:                        return "Unknown";
    }
}
// å­—符串转换成任务状态
TransferStatus TransferManager::stringToStatus(const std::string& str) {
    if (str == "Ready")     return TransferStatus::Ready;
    if (str == "Running")   return TransferStatus::Running;
    if (str == "Error")     return TransferStatus::Error;
    if (str == "Abort")     return TransferStatus::Abort;
    if (str == "Completed") return TransferStatus::Completed;
    return TransferStatus::Error;
}
// æœ¬åœ°ç¼–码转为 UTF-8
std::string TransferManager::ansiToUtf8(const std::string& ansiStr) {
    // 1. ANSI â†’ UTF-16
    int wideLen = MultiByteToWideChar(CP_ACP, 0, ansiStr.c_str(), -1, nullptr, 0);
    std::wstring wideStr(wideLen, 0);
    MultiByteToWideChar(CP_ACP, 0, ansiStr.c_str(), -1, &wideStr[0], wideLen);
    // 2. UTF-16 â†’ UTF-8
    int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, nullptr, 0, nullptr, nullptr);
    std::string utf8Str(utf8Len, 0);
    WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, &utf8Str[0], utf8Len, nullptr, nullptr);
    utf8Str.pop_back(); // åŽ»æŽ‰æœ€åŽçš„ '\0'
    return utf8Str;
}
// UTF-8 è½¬ä¸ºæœ¬åœ°ç¼–码
std::string TransferManager::utf8ToAnsi(const std::string& utf8Str) {
    // 1. UTF-8 â†’ UTF-16
    int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0);
    std::wstring wideStr(wideLen, 0);
    MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wideStr[0], wideLen);
    // 2. UTF-16 â†’ ANSI
    int ansiLen = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, NULL, 0, NULL, NULL);
    std::string ansiStr(ansiLen, 0);
    WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, &ansiStr[0], ansiLen, NULL, NULL);
    ansiStr.pop_back(); // åŽ»æŽ‰æœ€åŽçš„ '\0'
    return ansiStr;
}
// åˆå§‹åŒ–搬运记录表
bool TransferManager::initTransferTable() {
    char szPath[MAX_PATH];
    GetModuleFileName(NULL, szPath, MAX_PATH);
    std::string exePath(szPath);
    std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
    if (!CreateDirectory(dbDir.c_str(), NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
        throw std::runtime_error("创建数据库目录失败");
    }
    std::string dbPath = dbDir + "\\TransferManager.db";
    if (!m_pDB->connect(dbPath, true)) {
        throw std::runtime_error("连接数据库失败");
    }
    const std::string createTableSQL = R"(
        CREATE TABLE IF NOT EXISTS transfers (
            record_id    INTEGER PRIMARY KEY AUTOINCREMENT,
            class_id     TEXT NOT NULL,
            status       TEXT NOT NULL,
            create_time  TEXT,
            pick_time    TEXT,
            place_time   TEXT,
            end_time     TEXT,
            description  TEXT
        );
    )";
    return m_pDB->executeQuery(createTableSQL);
}
// æ’入测试搬运记录
void TransferManager::insertTestTransferRecord() {
    TransferData data;
    data.strClassID = "Task-20240529-001";
    data.strStatus = "Running";
    data.strCreateTime = "2024-05-29 10:30:00";
    data.strPickTime = "2024-05-29 10:31:00";
    data.strPlaceTime = "2024-05-29 10:32:00";
    data.strEndTime = "2024-05-29 10:33:00";
    data.strDescription = "搬运动作:从 Port1 å–片 â†’ Port2 æ”¾ç‰‡";
    int nRecordId = -1;
    if (TransferManager::getInstance().addTransferRecord(data, nRecordId)) {
        std::cout << "插入成功,记录 ID = " << nRecordId << std::endl;
    }
    else {
        std::cerr << "插入失败!" << std::endl;
    }
}
// æ–­å¼€æ•°æ®åº“连接
void TransferManager::termTransferTable() {
    if (m_pDB) {
        m_pDB->disconnect();
    }
}
// åˆ é™¤æ¬è¿è®°å½•表
bool TransferManager::destroyTransferTable() {
    if (!m_pDB) return false;
    const std::string dropTableSQL = "DROP TABLE IF EXISTS transfers;";
    return m_pDB->executeQuery(dropTableSQL);
}
// æ’入搬运记录
bool TransferManager::addTransferRecord(const TransferData& data, int& outRecordId) {
    if (!m_pDB) {
        return false;
    }
    std::ostringstream oss;
    oss << "INSERT INTO transfers (class_id, status, create_time, pick_time, place_time, end_time, description) "
        << "VALUES ('"
        << ansiToUtf8(data.strClassID) << "', '"
        << ansiToUtf8(data.strStatus) << "', '"
        << data.strCreateTime << "', '"
        << data.strPickTime << "', '"
        << data.strPlaceTime << "', '"
        << data.strEndTime << "', '"
        << ansiToUtf8(data.strDescription) << "') RETURNING record_id;";
    std::lock_guard<std::mutex> lock(m_mutex);
    auto results = m_pDB->fetchResults(oss.str());
    if (!results.empty() && !results[0].empty()) {
        try {
            outRecordId = std::stoi(results[0][0]);
            return true;
        }
        catch (const std::exception& e) {
            std::cerr << "解析 record_id å‡ºé”™: " << e.what() << std::endl;
        }
    }
    return false;
}
// æŸ¥è¯¢æ‰€æœ‰æ¬è¿è®°å½•
std::vector<TransferData> TransferManager::getAllTransfers() {
    std::vector<TransferData> records;
    if (!m_pDB) {
        return records;
    }
    const std::string query = R"(
        SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description
        FROM transfers
        ORDER BY record_id DESC
    )";
    auto results = m_pDB->fetchResults(query);
    for (const auto& row : results) {
        if (row.size() != 8) continue;
        TransferData data;
        data.nRecordId = std::stoi(row[0]);
        data.strClassID = row[1];
        data.strStatus = row[2];
        data.strCreateTime = row[3];
        data.strPickTime = row[4];
        data.strPlaceTime = row[5];
        data.strEndTime = row[6];
        data.strDescription = row[7];
        records.push_back(data);
    }
    return records;
}
// æ ¹æ® ID æŸ¥è¯¢æ¬è¿è®°å½•
TransferData TransferManager::getTransferById(int id) {
    TransferData data;
    if (!m_pDB) {
        return data;
    }
    std::ostringstream oss;
    oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
        << "FROM transfers WHERE record_id = " << id;
    auto results = m_pDB->fetchResults(oss.str());
    if (!results.empty() && results[0].size() == 8) {
        data.nRecordId = std::stoi(results[0][0]);
        data.strClassID = results[0][1];
        data.strStatus = results[0][2];
        data.strCreateTime = results[0][3];
        data.strPickTime = results[0][4];
        data.strPlaceTime = results[0][5];
        data.strEndTime = results[0][6];
        data.strDescription = results[0][7];
    }
    return data;
}
// æ ¹æ®æ—¶é—´èŒƒå›´æŸ¥è¯¢æ¬è¿è®°å½•
std::vector<TransferData> TransferManager::getTransfersByTimeRange(const std::string& startTime, const std::string& endTime) {
    std::vector<TransferData> records;
    if (!m_pDB) {
        return records;
    }
    std::ostringstream oss;
    oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
        << "FROM transfers WHERE 1=1";
    if (!startTime.empty()) {
        oss << " AND create_time >= '" << startTime << "'";
    }
    if (!endTime.empty()) {
        oss << " AND end_time <= '" << endTime << "'";
    }
    auto results = m_pDB->fetchResults(oss.str());
    for (const auto& row : results) {
        if (row.size() != 8) continue;
        TransferData data;
        data.nRecordId = std::stoi(row[0]);
        data.strClassID = row[1];
        data.strStatus = row[2];
        data.strCreateTime = row[3];
        data.strPickTime = row[4];
        data.strPlaceTime = row[5];
        data.strEndTime = row[6];
        data.strDescription = row[7];
        records.push_back(data);
    }
    return records;
}
// æŸ¥è¯¢æŒ‡å®šçŠ¶æ€çš„æ¬è¿è®°å½•
std::vector<TransferData> TransferManager::getTransfersByStatus(const std::string& status) {
    std::vector<TransferData> records;
    if (!m_pDB) {
        return records;
    }
    std::ostringstream oss;
    oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
        << "FROM transfers WHERE status = '" << status << "' "
        << "ORDER BY create_time DESC";
    auto results = m_pDB->fetchResults(oss.str());
    for (const auto& row : results) {
        if (row.size() != 8) continue;
        TransferData data;
        data.nRecordId = std::stoi(row[0]);
        data.strClassID = row[1];
        data.strStatus = row[2];
        data.strCreateTime = row[3];
        data.strPickTime = row[4];
        data.strPlaceTime = row[5];
        data.strEndTime = row[6];
        data.strDescription = row[7];
        records.push_back(data);
    }
    return records;
}
// åˆ†é¡µèŽ·å–æ¬è¿è®°å½•
//std::vector<TransferData> TransferManager::getTransfers(int startPosition, int count) {
//    std::vector<TransferData> records;
//    if (!m_pDB) {
//        return records;
//    }
//    std::ostringstream oss;
//    oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
//        << "FROM transfers ORDER BY create_time DESC LIMIT " << count << " OFFSET " << startPosition;
//    auto results = m_pDB->fetchResults(oss.str());
//    for (const auto& row : results) {
//        if (row.size() != 8) continue;
//        TransferData data;
//        data.nRecordId = std::stoi(row[0]);
//        data.strClassID = row[1];
//        data.strStatus = row[2];
//        data.strCreateTime = row[3];
//        data.strPickTime = row[4];
//        data.strPlaceTime = row[5];
//        data.strEndTime = row[6];
//        data.strDescription = row[7];
//        records.push_back(data);
//    }
//    return records;
//}
// èŽ·å–ç¬¦åˆæ¡ä»¶çš„è®°å½•æ€»æ•°
int TransferManager::getTotalTransferCount() {
    if (!m_pDB) {
        return 0;
    }
    const std::string query = "SELECT COUNT(*) FROM transfers;";
    auto results = m_pDB->fetchResults(query);
    if (!results.empty() && !results[0].empty()) {
        try {
            return std::stoi(results[0][0]);
        }
        catch (const std::exception& e) {
            std::cerr << "Error parsing total count: " << e.what() << std::endl;
        }
    }
    return 0;
}
// èŽ·å–ç¬¦åˆæ¡ä»¶çš„è®°å½•æ€»æ•°
int TransferManager::getTotalTransferCount(const TransferData& filter) {
    if (!m_pDB) {
        return 0;
    }
    std::ostringstream oss;
    oss << "SELECT COUNT(*) FROM transfers WHERE 1=1";
    // çŠ¶æ€ç­›é€‰ï¼ˆå®Œå…¨åŒ¹é…ï¼‰
    if (!filter.strStatus.empty()) {
        oss << " AND status = '" << filter.strStatus << "'";
    }
    // æè¿°å…³é”®å­—模糊匹配
    if (!filter.strDescription.empty()) {
        oss << " AND description LIKE '%" << filter.strDescription << "%'";
    }
    // æ—¶é—´èŒƒå›´ç­›é€‰
    if (!filter.strCreateTime.empty()) {
        oss << " AND create_time >= '" << filter.strCreateTime << "'";
    }
    if (!filter.strEndTime.empty()) {
        oss << " AND end_time <= '" << filter.strEndTime << "'";
    }
    auto results = m_pDB->fetchResults(oss.str());
    if (!results.empty() && !results[0].empty()) {
        try {
            return std::stoi(results[0][0]);
        }
        catch (const std::exception& e) {
            std::cerr << "Error parsing total count: " << e.what() << std::endl;
        }
    }
    return 0;
}
std::vector<TransferData> TransferManager::getTransfers(const TransferData& filter, int pageNum, int pageSize) {
    std::vector<TransferData> records;
    if (!m_pDB) {
        return records;
    }
    std::ostringstream oss;
    oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
        << "FROM transfers WHERE 1=1";
    // æ¡ä»¶æ‹¼æŽ¥ï¼ˆä¸Ž getTotalTransferCount ä¿æŒä¸€è‡´ï¼‰
    if (!filter.strStatus.empty()) {
        oss << " AND status = '" << filter.strStatus << "'";
    }
    if (!filter.strDescription.empty()) {
        oss << " AND description LIKE '%" << filter.strDescription << "%'";
    }
    if (!filter.strCreateTime.empty()) {
        oss << " AND create_time >= '" << filter.strCreateTime << "'";
    }
    if (!filter.strEndTime.empty()) {
        oss << " AND end_time <= '" << filter.strEndTime << "'";
    }
    // åˆ†é¡µæŽ§åˆ¶
    int offset = (pageNum - 1) * pageSize;
    oss << " ORDER BY create_time DESC";
    oss << " LIMIT " << pageSize << " OFFSET " << offset;
    // æŸ¥è¯¢
    auto results = m_pDB->fetchResults(oss.str());
    for (const auto& row : results) {
        if (row.size() != 8) continue;
        TransferData data;
        data.nRecordId = std::stoi(row[0]);
        data.strClassID = row[1];
        data.strStatus = row[2];
        data.strCreateTime = row[3];
        data.strPickTime = row[4];
        data.strPlaceTime = row[5];
        data.strEndTime = row[6];
        data.strDescription = row[7];
        records.push_back(data);
    }
    return records;
}
// æ¸…理早于某一时间的搬运记录
void TransferManager::cleanOldTransfers(int daysToKeep) {
    if (!m_pDB) {
        return;
    }
    std::ostringstream oss;
    oss << "DELETE FROM transfers WHERE create_time < datetime('now', '-" << daysToKeep << " days')";
    m_pDB->executeQuery(oss.str());
}
// è¯»å–搬运记录 CSV æ–‡ä»¶
bool TransferManager::readTransferFile(const std::string& filename) {
    std::ifstream file(filename);
    if (!file.is_open()) {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return false;
    }
    std::string line;
    bool firstLine = true;
    int insertedCount = 0;
    while (std::getline(file, line)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        std::stringstream ss(line);
        std::string cell;
        TransferData data;
        try {
            std::getline(ss, cell, ',');
            data.nRecordId = std::stoi(cell);
            std::getline(ss, data.strClassID, ',');
            std::getline(ss, data.strStatus, ',');
            std::getline(ss, data.strCreateTime, ',');
            std::getline(ss, data.strPickTime, ',');
            std::getline(ss, data.strPlaceTime, ',');
            std::getline(ss, data.strEndTime, ',');
            std::getline(ss, data.strDescription, ',');
            int newId = -1;
            if (addTransferRecord(data, newId)) {
                ++insertedCount;
            }
        }
        catch (const std::exception& e) {
            std::cerr << "读取错误行: " << line << ",错误: " << e.what() << std::endl;
            continue;
        }
    }
    file.close();
    std::cout << "成功导入记录数: " << insertedCount << std::endl;
    return true;
}
// ä¿å­˜æ¬è¿è®°å½•到 CSV æ–‡ä»¶
bool TransferManager::saveTransferFile(const std::string& filename) {
    std::ofstream file(filename);
    if (!file.is_open()) {
        std::cerr << "无法写入文件: " << filename << std::endl;
        return false;
    }
    // å†™å…¥æ ‡é¢˜
    file << "RecordID,ClassID,Status,CreateTime,PickTime,PlaceTime,EndTime,Description\n";
    auto records = getAllTransfers();
    for (const auto& data : records) {
        file << data.nRecordId << ","
            << data.strClassID << ","
            << data.strStatus << ","
            << data.strCreateTime << ","
            << data.strPickTime << ","
            << data.strPlaceTime << ","
            << data.strEndTime << ","
            << data.strDescription << "\n";
    }
    file.close();
    std::cout << "已导出 " << records.size() << " æ¡è®°å½•到: " << filename << std::endl;
    return true;
}
SourceCode/Bond/Servo/TransferManager.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,171 @@
#ifndef TRANSFER_MANAGER_H
#define TRANSFER_MANAGER_H
#include <string>
#include <vector>
#include <mutex>
#include <unordered_map>
#include "Database.h"
/**
 * ä»»åŠ¡çŠ¶æ€æžšä¸¾ç±»åž‹
 */
enum class TransferStatus {
    Ready = 0,
    Running,
    Error,
    Abort,
    Completed
};
/**
 * æ¬è¿è®°å½•结构体
 */
struct TransferData {
    int nRecordId;                  // ä¸»é”®
    std::string strClassID;         // æ¬è¿ä»»åŠ¡ ClassID
    std::string strStatus;          // ä»»åŠ¡çŠ¶æ€ï¼ˆå­—ç¬¦ä¸²ï¼šReady、Running...)
    std::string strCreateTime;      // åˆ›å»ºæ—¶é—´
    std::string strPickTime;        // å–片时间
    std::string strPlaceTime;       // æ”¾ç‰‡æ—¶é—´
    std::string strEndTime;         // ç»“束时间
    std::string strDescription;     // ä»»åŠ¡è¯´æ˜Ž
};
using TransferDataMap = std::unordered_map<int, TransferData>;
class TransferManager {
public:
    /**
     * èŽ·å– TransferManager å•例
     * @return TransferManager å®žä¾‹
     */
    static TransferManager& getInstance();
    /**
     * åˆå§‹åŒ–搬运记录表
     * @return æˆåŠŸè¿”å›ž true,失败返回 false
     */
    bool initTransferTable();
    /**
     * æ’入测试搬运记录
     */
    void insertTestTransferRecord();
    /**
     * ç»ˆæ­¢æ•°æ®åº“连接
     */
    void termTransferTable();
    /**
     * åˆ é™¤æ¬è¿è®°å½•表
     * @return æˆåŠŸè¿”å›ž true,失败返回 false
     */
    bool destroyTransferTable();
    /**
     * æ’入搬运记录
     * @param data æ¬è¿è®°å½•结构体
     * @param outRecordId æ’入后的记录主键 ID
     * @return æˆåŠŸè¿”å›ž true,失败返回 false
     */
    bool addTransferRecord(const TransferData& data, int& outRecordId);
    /**
     * æŸ¥è¯¢æ‰€æœ‰æ¬è¿è®°å½•
     * @return æ‰€æœ‰è®°å½•数据
     */
    std::vector<TransferData> getAllTransfers();
    /**
     * æ ¹æ®è®°å½• ID æŸ¥è¯¢æ¬è¿è®°å½•
     * @param id è®°å½•主键 ID
     * @return æ¬è¿è®°å½•数据
     */
    TransferData getTransferById(int id);
    /**
     * æ ¹æ®æ—¶é—´èŒƒå›´æŸ¥è¯¢æ¬è¿è®°å½•
     * @param startTime èµ·å§‹æ—¶é—´
     * @param endTime ç»“束时间
     * @return æ¬è¿è®°å½•数据
     */
    std::vector<TransferData> getTransfersByTimeRange(const std::string& startTime, const std::string& endTime);
    /**
     * æ ¹æ®çŠ¶æ€æŸ¥è¯¢æ¬è¿è®°å½•
     * @param status ä»»åŠ¡çŠ¶æ€
     * @return æ¬è¿è®°å½•数据
     */
    std::vector<TransferData> TransferManager::getTransfersByStatus(const std::string& status);
    /**
     * åˆ†é¡µèŽ·å–æ¬è¿è®°å½•
     * @param startPosition èµ·å§‹è®°å½•位置
     * @param count èŽ·å–çš„è®°å½•æ•°é‡
     * @return æ¬è¿è®°å½•数据
     */
    //std::vector<TransferData> getTransfers(int startPosition, int count);
    /**
     * èŽ·å–ç¬¦åˆæ¡ä»¶çš„è®°å½•æ€»æ•°
     */
    int getTotalTransferCount();
    /**
     * åˆ†é¡µèŽ·å–ç¬¦åˆæ¡ä»¶çš„æ¬è¿è®°å½•
     * @param filter è¿‡æ»¤æ¡ä»¶
     * @param pageNum é¡µç 
     * @param pageSize æ¯é¡µè®°å½•æ•°
     */
    std::vector<TransferData> getTransfers(const TransferData& filter, int pageNum, int pageSize);
    /**
     * èŽ·å–ç¬¦åˆæ¡ä»¶çš„è®°å½•æ€»æ•°
     * @param filter è¿‡æ»¤æ¡ä»¶
     * @return ç¬¦åˆæ¡ä»¶çš„记录总数
     */
    int getTotalTransferCount(const TransferData& filter);;
    /**
     * æ¸…理早于某一时间的搬运记录
     * @param daysToKeep ä¿ç•™çš„天数
     */
    void cleanOldTransfers(int daysToKeep = 30);
    /**
     * è¯»å–搬运记录 CSV æ–‡ä»¶
     * @param filename æ–‡ä»¶å
     * @return æˆåŠŸè¿”å›ž true,失败返回 false
     */
    bool readTransferFile(const std::string& filename);
    /**
     * ä¿å­˜æ¬è¿è®°å½•到 CSV æ–‡ä»¶
     * @param filename æ–‡ä»¶å
     * @return æˆåŠŸè¿”å›ž true,失败返回 false
     */
    bool saveTransferFile(const std::string& filename);
private:
    TransferManager();
    ~TransferManager();
    // ç¦æ­¢æ‹·è´å’Œèµ‹å€¼
    TransferManager(const TransferManager&) = delete;
    TransferManager& operator=(const TransferManager&) = delete;
    // å†…联函数
    inline int statusToInt(TransferStatus status);
    inline TransferStatus intToStatus(int value);
    inline std::string statusToString(TransferStatus status);
    inline TransferStatus stringToStatus(const std::string& str);
    inline std::string ansiToUtf8(const std::string& ansiStr);
    inline std::string utf8ToAnsi(const std::string& utf8Str);
    BL::Database* m_pDB;
    static std::mutex m_mutex;
};
#endif // TRANSFER_MANAGER_H
SourceCode/Bond/Servo/resource.h
Binary files differ
SourceCode/Bond/Servo/stdafx.h
@@ -34,6 +34,17 @@
#include <afxcontrolbars.h>     // åŠŸèƒ½åŒºå’ŒæŽ§ä»¶æ¡çš„ MFC æ”¯æŒ
// æŽ§ä»¶æ ·å¼
static UINT g_nGridFixCellColor = RGB(144, 200, 246);
static UINT g_nGridFixFontColor = RGB(0, 0, 0);
static UINT g_nGridCellColor = RGB(255, 255, 224);
static UINT g_nGridCellColor_NonSelect = RGB(150, 150, 150);
static UINT g_nGridCellReadyColor = RGB(255, 255, 0);
static UINT g_nGridCellOnColor = RGB(255, 69, 0);
static UINT g_nGridCellOffColor = RGB(128, 191, 255);
static UINT g_nPropertyGridFixCellColor = RGB(150, 150, 150);
static UINT g_nPropertyGridFixFontColor = RGB(0, 0, 0);
// GDI+
#include <gdiplus.h>
using namespace Gdiplus;