home *** CD-ROM | disk | FTP | other *** search
/ C/C++ User's Journal & Wi…eveloper's Journal Tools / C-C__Users_Journal_and_Windows_Developers_Journal_Tools_1997.iso / stingray / gridsvw7.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-27  |  13.9 KB  |  599 lines

  1. // gridsvw7.cpp : implementation of the CGridSample7View class
  2. //
  3.  
  4. // This is a part of the Objective Grid C++ Library.
  5. // Copyright (C) 1995,1996 ClassWorks, Stefan Hoenig.
  6. // All rights reserved.
  7. //
  8. // This source code is only intended as a supplement to
  9. // the Objective Grid Classes Reference and related
  10. // electronic documentation provided with the library.
  11. // See these sources for detailed information regarding
  12. // the Objective Grid product.
  13. //
  14.  
  15. #include "stdafx.h"
  16. #include "gridapp.h"
  17.  
  18. #include "gridsdoc.h"
  19. #include "gridsvw7.h"
  20. #include "dlguser.h"
  21. #include "mainfrm.h"
  22. #include "gridfrms.h"
  23.  
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char BASED_CODE THIS_FILE[] = __FILE__;
  27. #endif
  28.  
  29. //
  30. // CGridSample7View can be used as standalone, splitter or worksheet gridview
  31. // as you have already seen with CGridSampleView
  32. //
  33. // CGridSample7View illustrates how to apply pushbuttons for headers
  34. // and registering this header control (the skeletton for the control
  35. // is simply copied from the CSimpleButton class in CGridSample5View).
  36. //
  37. // CGridSample7View also illustrates how to select cells with the
  38. // SelectRange command and how to override OnLButtonHitRowCol to
  39. // implement owner-written column dragging.
  40. //
  41.  
  42. IMPLEMENT_DYNCREATE(CGridSample7View, CMyGridView)
  43. IMPLEMENT_CONTROL(CHeaderButton, CGXStatic)
  44.  
  45. static TCHAR BASED_CODE szInstruct[] =
  46.         _T("This view shows row and column headers which act like pushbuttons. ")
  47.         _T("When you click on the headers, you can select/deselect the row or column.");
  48.  
  49. #define new DEBUG_NEW
  50.  
  51.  
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CHeaderButton control
  54.  
  55. // This control can be used as header with push button effect
  56. //
  57.  
  58. CHeaderButton::CHeaderButton(CGXGridCore* pGrid)
  59.     : CGXStatic(pGrid)
  60. {
  61.     m_bPressed = FALSE;
  62. }
  63.  
  64. CHeaderButton::~CHeaderButton()
  65. {
  66. }
  67.  
  68. void CHeaderButton::Draw(CDC* pDC, CRect rect, ROWCOL nRow, ROWCOL nCol, const CGXStyle& style, const CGXStyle* pStandardStyle)
  69. {
  70.     WORD w = 0;
  71.  
  72.     // Select font
  73.     CFont* pOldFont = LoadFont(pDC, style, pStandardStyle);
  74.  
  75.     BOOL bActive = (m_nRow == nRow && m_nCol == nCol && !Grid()->IsPrinting()
  76.                 && Grid()->IsActiveFrame());
  77.  
  78.     if (bActive)
  79.     {
  80.         w |= GX_BTNFOCUS;
  81.  
  82.         if (m_bPressed)
  83.             w |= GX_BTNPRESSED;
  84.     }
  85.  
  86.  
  87.     // start of drawing buttons technique 1 ->
  88.  
  89.     CRect rectText = GetCellRect(nRow, nCol, rect);
  90.  
  91.     // Background
  92.     DrawBackground(pDC, rect, style);
  93.  
  94.     // Draw pressed or button look
  95.     if (style.GetIncludeDraw3dFrame() || style.GetDraw3dFrame() == gxFrameNormal)
  96.     {
  97.         CRect r = CGXControl::GetCellRect(nRow, nCol, rect);
  98.  
  99.         if (bActive && m_bPressed)
  100.         {
  101.             // Inset
  102.             GXDrawEdge(pDC, r, BDR_SUNKENOUTER|BDR_SUNKENINNER);
  103.  
  104.             // text will be moved to the bottom-right corner a bit
  105.             rectText += CPoint(1,1);
  106.         }
  107.         else
  108.             // Raised
  109.             GXDrawEdge(pDC, r, BDR_RAISEDOUTER|BDR_RAISEDINNER);
  110.     }
  111.  
  112.     // Draw static text
  113.     pDC->SetBkMode(TRANSPARENT);
  114.  
  115.     DWORD dtAlign = style.GetHorizontalAlignment() | style.GetVerticalAlignment();
  116.  
  117.     if (style.GetWrapText())
  118.         dtAlign |= DT_NOPREFIX | DT_WORDBREAK;
  119.     else
  120.         dtAlign |= DT_NOPREFIX | DT_SINGLELINE;
  121.  
  122.     pDC->SetTextColor(style.GetTextColor());
  123.  
  124.     CString sOutput;
  125.     if (GetControlText(sOutput, nRow, nCol, NULL, style))
  126.     {
  127.         GXDrawTextLikeMultiLineEdit(pDC,
  128.             sOutput,
  129.             -1,
  130.             rectText,
  131.             (UINT) dtAlign);
  132.     }
  133.  
  134.     // <- end of technique 1
  135.  
  136. /*
  137.     // start of drawing buttons technique 2 ->
  138.  
  139.     DrawBackground(pDC, rect, style);
  140.  
  141.     GXDrawPushButton(pDC,
  142.         rect.left, rect.top,
  143.         rect.Width(), rect.Height(),
  144.         w,
  145.         style.GetValueRef());
  146.  
  147.     // <- end of technique 2
  148. */
  149.  
  150.     if (pOldFont)
  151.         pDC->SelectObject(pOldFont);
  152. }
  153.  
  154. void CHeaderButton::InvertBorders(CDC* pDC, const CRect& r)
  155. {
  156.     // I don't want the borders to be inverted
  157.     pDC, r;
  158. }
  159.  
  160. BOOL CHeaderButton::KeyPressed(UINT nMessage, UINT nChar, UINT nRepCnt, UINT flags)
  161. {
  162.     // unused:
  163.     nMessage, nRepCnt, flags;
  164.  
  165.     if (nChar == 32 && nMessage == WM_KEYDOWN)
  166.     {
  167.         // Draw pressed
  168.         m_bPressed = TRUE;
  169.         Refresh();
  170.     }
  171.     else if (nChar == 32 && nMessage == WM_KEYUP && m_bPressed)
  172.     {
  173.         // trigger event
  174.         OnClickedButton(NULL);
  175.  
  176.         // Draw normal
  177.         m_bPressed = FALSE;
  178.         Refresh();
  179.     }
  180.     return TRUE;
  181. }
  182.  
  183. BOOL CHeaderButton::LButtonDown(UINT nFlags, CPoint pt, UINT nHitState)
  184. {
  185.     m_bPressed = TRUE;
  186.     m_bMouseDown = TRUE;
  187.  
  188.     Refresh();
  189.  
  190.     // unreferenced:
  191.     nFlags, pt, nHitState;
  192.  
  193.     return TRUE;
  194. }
  195.  
  196. BOOL CHeaderButton::RButtonDown(UINT nFlags, CPoint pt, UINT nHitState)
  197. {
  198.     m_bPressed = TRUE;
  199.     m_bMouseDown = TRUE;
  200.  
  201.     Refresh();
  202.  
  203.     // unreferenced:
  204.     nFlags, pt, nHitState;
  205.  
  206.     return TRUE;
  207. }
  208.  
  209. BOOL CHeaderButton::LButtonUp(UINT nFlags, CPoint pt, UINT nHitState)
  210. {
  211.     nFlags, pt;
  212.  
  213.     CRect rect = CGXControl::GetCellRect(m_nRow, m_nCol);
  214.  
  215.     if (m_bPressed && rect.PtInRect(pt))
  216.         OnClickedButton(NULL);
  217.  
  218.     m_bPressed = FALSE;
  219.     m_bMouseDown = FALSE;
  220.     Refresh();
  221.  
  222.     // unreferenced:
  223.     nFlags, pt, nHitState;
  224.  
  225.     return TRUE;
  226. }
  227.  
  228. BOOL CHeaderButton::RButtonUp(UINT nFlags, CPoint pt, UINT nHitState)
  229. {
  230.     nFlags, pt;
  231.  
  232.     CRect rect = CGXControl::GetCellRect(m_nRow, m_nCol);
  233.  
  234.     if (m_bPressed && rect.PtInRect(pt))
  235.     {
  236.         TCHAR s[512];
  237.  
  238.         wsprintf(s, _T("Clicked right button on header at cell %d, %d"), m_nRow, m_nCol);
  239.  
  240.         AfxMessageBox(s);
  241.     }
  242.  
  243.     m_bPressed = FALSE;
  244.     m_bMouseDown = FALSE;
  245.     Refresh();
  246.  
  247.     // unreferenced:
  248.     nFlags, pt, nHitState;
  249.  
  250.     return TRUE;
  251. }
  252.  
  253. BOOL CHeaderButton::MouseMove(UINT nFlags, CPoint pt, UINT nHitState)
  254. {
  255.     nFlags, pt;
  256.  
  257.     CRect rect = CGXControl::GetCellRect(m_nRow, m_nCol);
  258.  
  259.     BOOL bState = rect.PtInRect(pt);
  260.  
  261.     if (m_bMouseDown && bState != m_bPressed)
  262.     {
  263.         m_bPressed = bState;
  264.         Refresh();
  265.     }
  266.  
  267.     // unreferenced:
  268.     nFlags, pt, nHitState;
  269.  
  270.     return TRUE;
  271. }
  272.  
  273. BOOL CHeaderButton::LButtonDblClk(UINT nFlags, CPoint point)
  274. {
  275.     // unreferenced:
  276.     nFlags, point;
  277.  
  278.     TCHAR s[512];
  279.  
  280.     wsprintf(s, _T("Double-clicked on header at cell %d, %d"), m_nRow, m_nCol);
  281.  
  282.     AfxMessageBox(s);
  283.  
  284.     return TRUE;
  285. }
  286.  
  287. void CHeaderButton::OnClickedButton(CGXChild* pChild)
  288. {
  289.     // Unreferenced parameters:
  290.     pChild;
  291.  
  292.     // display a message box with the text specified in
  293.     // the user attribut "MessageText" (see the style-sheet)
  294.  
  295.     CGXRangeList* pSelList = Grid()->GetParam()->GetRangeList();
  296.  
  297.     // toggle selection for row
  298.  
  299.     if (m_nRow > 0 && m_nCol == 0)
  300.         Grid()->SelectRange(CGXRange().SetRows(m_nRow, m_nRow), !pSelList->IsCellInList(m_nRow, m_nCol));
  301.     else if (m_nCol > 0 && m_nRow == 0)
  302.         Grid()->SelectRange(CGXRange().SetCols(m_nCol, m_nCol), !pSelList->IsCellInList(m_nRow, m_nCol));
  303.  
  304. }
  305.  
  306.  
  307. /////////////////////////////////////////////////////////////////////////////
  308. // CGridSample7View
  309.  
  310. BEGIN_MESSAGE_MAP(CGridSample7View, CMyGridView)
  311.     //{{AFX_MSG_MAP(CGridSample7View)
  312.     ON_COMMAND(ID_VIEW_USERACTIONS, OnViewUseractions)
  313.     ON_COMMAND(ID_VIEW_SPLITTERVIEW, OnViewSplitterview)
  314.     //}}AFX_MSG_MAP
  315. END_MESSAGE_MAP()
  316.  
  317. /////////////////////////////////////////////////////////////////////////////
  318. // CGridSample7View construction/destruction
  319.  
  320. CGridSample7View::CGridSample7View()
  321. {
  322.     // TODO: add construction code here
  323. }
  324.  
  325. CGridSample7View::~CGridSample7View()
  326. {
  327. }
  328.  
  329. BOOL CGridSample7View::ConnectParam()
  330. {
  331.     // Note: this method is copied from CGridSampleView
  332.     //
  333.  
  334.     BOOL bNew = FALSE;
  335.  
  336.     // Retrive the zero-based worksheet-id if used as worksheet
  337.     if (GetParentTabWnd(this, TRUE))
  338.         m_nViewID = GetParentTabViewID(this);
  339.  
  340.     // check if it is a new pane in a splitter window
  341.     CSplitterWnd* pSplitterWnd = GetParentDynamicSplitter(this, TRUE);
  342.     if (pSplitterWnd != NULL)
  343.     {
  344.         CGXGridView *pView = (CGXGridView *) pSplitterWnd->GetPane(0, 0);
  345.         if (pView != this)
  346.             m_nViewID = pView->GetViewID();
  347.     }
  348.  
  349.     // check if parameter-object exist (in document)
  350.     if (GetDocument()->GetParam(m_nViewID) == NULL)
  351.     {
  352.         // create a parameter-object on the heap
  353.         GetDocument()->SetParam(m_nViewID, new CGXGridParam);
  354.  
  355.         bNew = TRUE;    // this view needs initializing
  356.     }
  357.  
  358.     // connect parameter-object with grid
  359.     SetParam((CGXGridParam*) GetDocument()->GetParam(m_nViewID), FALSE);
  360.  
  361.     return bNew;
  362. }
  363.  
  364. void CGridSample7View::SetupControls()
  365. {
  366.     // Register all controls for the view
  367.  
  368.     // replace the default header control with my CHeaderButton
  369.  
  370.     RegisterControl(GX_IDS_CTRL_HEADER, new CHeaderButton(this));
  371. }
  372.  
  373. /////////////////////////////////////////////////////////////////////////////
  374. // CGridSample7View drawing
  375.  
  376. void CGridSample7View::OnInitialUpdate()
  377. {
  378.     BOOL bNew = ConnectParam();
  379.  
  380.     CMyGridView::OnInitialUpdate(); // Creates all objects and links them to the grid
  381.  
  382.     // Register all controls for the view
  383.     SetupControls();
  384.  
  385.     if (bNew)
  386.     {
  387.         // Don't create undo-information for the following commands
  388.         GetParam()->EnableUndo(FALSE);
  389.         // (at the end of this procedure, I will reenable it)
  390.  
  391.         SetRowCount(10);
  392.         SetColCount(10);
  393.  
  394.         // Instructions
  395.         SetCoveredCellsRowCol(1, 1, 3, 5);
  396.         SetStyleRange(CGXRange(1,1),
  397.             CGXStyle()
  398.                 .SetWrapText(TRUE)
  399.                 .SetEnabled(FALSE)
  400.                 .SetFont(CGXFont().SetFaceName(_T("Times New Roman")))
  401.                 .SetInterior(RGB(255,251,240))   // Off-white
  402.                 .SetHorizontalAlignment(DT_CENTER)
  403.                 .SetVerticalAlignment(DT_VCENTER)
  404.                 .SetControl(GX_IDS_CTRL_STATIC)
  405.                 .SetBorders(gxBorderAll, CGXPen().SetWidth(2))
  406.                 .SetValue(szInstruct));
  407.  
  408.         // Enable creation of undo-information for user interactions
  409.         GetParam()->EnableUndo(TRUE);
  410.  
  411.         // disable selecting cells
  412.         GetParam()->EnableSelection(GX_SELNONE);
  413.         GetParam()->EnableMoveCols(FALSE);
  414.         GetParam()->EnableMoveRows(FALSE);
  415.     }
  416.  
  417.     // Position the current cell
  418.  
  419.     SetCurrentCell(4, 1, FALSE /* avoid immediate updating */);
  420.  
  421.     // Enable Update-Hint-Mechanism
  422.  
  423.     EnableHints();
  424. }
  425.  
  426. /////////////////////////////////////////////////////////////////////////////
  427. // dragging cells
  428.  
  429. BOOL CGridSample7View::OnLButtonHitRowCol(ROWCOL nHitRow, ROWCOL nHitCol, ROWCOL nDragRow, ROWCOL nDragCol, CPoint point, UINT flags, WORD nHitState)
  430. {
  431.     if (!CMyGridView::OnLButtonHitRowCol(nHitRow, nHitCol, nDragRow, nDragCol, point, flags, nHitState))
  432.         return FALSE;
  433.  
  434.     // determine style and control of the cell
  435.     CGXControl* pControl = GetControl(nHitRow, nHitCol);
  436.  
  437.     if (nHitRow == 0 && nHitCol > 0)
  438.     {
  439.         if (nHitState & GX_HITSTART)
  440.         {
  441.             m_nLastDragCol = nHitCol;
  442.         }
  443.         else if (nHitState & GX_HITMOVE && m_nLastDragCol != nDragCol)
  444.         {
  445.             DrawDragLine(m_nLastDragCol, FALSE);
  446.  
  447.             // support for dragging columns
  448.             if (nHitCol != nDragCol && nDragCol > 0)
  449.                 // display drag-cursor
  450.                 SetGridCursor(GX_IDC_SELDRAG);
  451.             else
  452.                 // reset cursor
  453.                 SetGridCursor(0);
  454.  
  455.             DrawDragLine(m_nLastDragCol = nDragCol, TRUE);
  456.         }
  457.         else if (nHitState & GX_HITEND)
  458.         {
  459.             DrawDragLine(m_nLastDragCol, FALSE);
  460.  
  461.             // support for dragging columns
  462.             if (nHitCol != nDragCol && nDragCol > 0)
  463.             {
  464.                 // move the dragged column
  465.                 if (nDragCol < nHitCol)
  466.                     MoveCols(nHitCol, nHitCol, nDragCol);
  467.                 else
  468.                     MoveCols(nHitCol, nHitCol, nDragCol-1);
  469.             }
  470.  
  471.             // reset cursor
  472.             SetGridCursor(0);
  473.         }
  474.     }
  475.  
  476.     return TRUE;
  477. }
  478.  
  479. void CGridSample7View::DrawDragLine(ROWCOL nCol, BOOL bOutline)
  480. {
  481.     // This method calls DrawGridLine to outline the gridline
  482.     // for the specified column. DrawGridLine is an implementation
  483.     // specific method, and is not further documented.
  484.  
  485.     CClientDC dc(m_pGridWnd);
  486.     OnPrepareDC(&dc);
  487.  
  488.     if (!bOutline)
  489.     {
  490.         // Hide mark
  491.         DrawGridLine(&dc, GX_VERTLINE, GetClientCol(nCol),
  492.             !GetParam()->GetProperties()->GetDisplayVertLines() ? GX_INVERT : 0);
  493.     }
  494.     else
  495.     {
  496.         // Show mark
  497.         DrawGridLine(&dc, GX_VERTLINE, GetClientCol(nCol),
  498.             !GetParam()->GetProperties()->GetDisplayVertLines() ? GX_INVERT : GX_SELDRAGLINE);
  499.     }
  500. }
  501.  
  502. BOOL CGridSample7View::OnLButtonDblClkRowCol(ROWCOL nRow, ROWCOL nCol, UINT nFlags, CPoint pt)
  503. {
  504.     TCHAR s[512];
  505.  
  506.     wsprintf(s, _T("Double-click on cell %lu, %lu"), nRow, nCol);
  507.     AfxMessageBox(s);
  508.  
  509.     // unreferenced:
  510.     pt, nFlags;
  511.  
  512.     return TRUE;
  513. }
  514.  
  515.  
  516. /////////////////////////////////////////////////////////////////////////////
  517. // CGridSample7View diagnostics
  518.  
  519. #ifdef _DEBUG
  520. void CGridSample7View::AssertValid() const
  521. {
  522.     CMyGridView::AssertValid();
  523. }
  524.  
  525. void CGridSample7View::Dump(CDumpContext& dc) const
  526. {
  527.     CMyGridView::Dump(dc);
  528. }
  529.  
  530. CGridSampleDoc* CGridSample7View::GetDocument() // non-debug version is inline
  531. {
  532.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGridSampleDoc)));
  533.     return (CGridSampleDoc*) m_pDocument;
  534. }
  535.  
  536. #endif //_DEBUG
  537.  
  538.  
  539. /////////////////////////////////////////////////////////////////////////////
  540. // CGridSample7View message handlers
  541.  
  542. // Menu handler for View->Splitter View
  543.  
  544. void CGridSample7View::OnViewSplitterview()
  545. {
  546.     CDocument* pDoc = GetDocument();
  547.  
  548.     CMyMultiDocTemplate* pTemplate
  549.         = (CMyMultiDocTemplate*) ((CGridSampleApp*) AfxGetApp())->m_pSplitterTemplate;
  550.  
  551.     pTemplate->SetViewClass(GetRuntimeClass());
  552.  
  553.     CMDIChildWnd* pNewFrame
  554.         = (CMDIChildWnd*) pTemplate->CreateNewFrame(GetDocument(), NULL);
  555.  
  556.     if (pNewFrame == NULL)
  557.         return;     // not created
  558.  
  559.     ASSERT(pNewFrame->IsKindOf(RUNTIME_CLASS(CSplitterMDIChildWnd)));
  560.  
  561.     CSplitterWnd& splitter = (CSplitterWnd&)
  562.         ((CSplitterMDIChildWnd *) pNewFrame)->m_wndSplitter;
  563.  
  564.     CGridSample7View* pView = (CGridSample7View*)
  565.         splitter.GetPane(0, 0);
  566.  
  567.     // Set view id to active tab view id
  568.     pView->m_nViewID = m_nViewID;
  569.  
  570.     pTemplate->InitialUpdateFrame(pNewFrame, pDoc);
  571.  
  572.     pNewFrame->GetActiveView();
  573.     ASSERT(pView);
  574. }
  575.  
  576. // Menu handler for View->User Actions...
  577.  
  578. void CGridSample7View::OnViewUseractions()
  579. {
  580.     // Note: this method is copied from CGridSampleView
  581.     //
  582.     // Shows a dialog with some attributes of the parameter-object
  583.     // where you can experiment with some attributes
  584.     // such as allowing the user to track columns, select cells
  585.     // or use the grid as a listbox.
  586.  
  587.     // Transfer Current Cell's Data to grid
  588.     if (!TransferCurrentCell())
  589.         return;
  590.  
  591.     CUserActionsDialog dlg(GetParam());
  592.  
  593.     if (dlg.DoModal() == IDOK)
  594.     {
  595.         // Redraw the grid
  596.         Redraw();
  597.     }
  598. }
  599.