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 / gridsvw6.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-27  |  14.7 KB  |  572 lines

  1. // gridsvw6.cpp : implementation of the CGridSample6View 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 "gridsvw6.h"
  20. #include "dlguser.h"
  21. #include "mainfrm.h"
  22. #include "gridfrms.h"
  23.  
  24. #ifndef _GXWND_H_
  25. #include "gxwnd.h"
  26. #endif
  27.  
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char BASED_CODE THIS_FILE[] = __FILE__;
  31. #endif
  32.  
  33. //
  34. // CGridSample6View can be used as standalone, splitter or worksheet gridview
  35. // as you have already seen with CGridSampleView
  36. //
  37. // CGridSample6View illustrates using a grid control as cell
  38. // or dropdown grid
  39. //
  40.  
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CDropDownGridWnd control
  43.  
  44. CDropDownGridWnd::CDropDownGridWnd()
  45. {
  46. }
  47.  
  48. BOOL CDropDownGridWnd::Create(CRect rect, CWnd* pParent)
  49. {
  50.     if (!CreateEx(
  51.         0, CGXGridCombo::GetClassName(), NULL, WS_POPUP | WS_BORDER | WS_VSCROLL,
  52.         rect.left-1, rect.top, rect.Width()+1, rect.Height(),
  53.         pParent->GetSafeHwnd(), NULL))
  54.     {
  55.         TRACE0("Failed to create popup window in CDropDownGridWnd\n");
  56.         ASSERT(0);
  57.         // ASSERTION-> Failed to create popup window
  58.         // Did you register the windowclass with CGXGridCombo::RegisterClass? ->END
  59.     }
  60.  
  61.     m_pMsgWnd = pParent;
  62.  
  63.     return TRUE;
  64. }
  65.  
  66. void CDropDownGridWnd::OnInitialUpdate()
  67. {
  68.     BOOL bNeedInit = (GetParam() == NULL);
  69.  
  70.     CGXGridWnd::OnInitialUpdate();
  71.  
  72.     if (bNeedInit)
  73.     {
  74.         // typical listbox initialization
  75.         GetParam()->SetSpecialMode(GX_MODELBOX_SS);
  76.         GetParam()->SetHideCurrentCell(TRUE);
  77.         GetParam()->EnableTrackColWidth(FALSE);
  78.         GetParam()->EnableTrackRowHeight(FALSE);
  79.         GetParam()->EnableMoveRows(FALSE);
  80.         GetParam()->EnableMoveCols(FALSE);
  81.  
  82.         // column widths and row/column count
  83.         SetRowCount(20);
  84.         SetColCount(3);
  85.         SetColWidth(0,0,0);
  86.         SetColWidth(1,1,38);
  87.         SetColWidth(2,3,72);
  88.  
  89.         // select first row
  90.         SetCurrentCell(1,0);
  91.         SelectRange(CGXRange().SetTable(), FALSE);
  92.         SelectRange(CGXRange().SetRows(1), TRUE);
  93.     }
  94. }
  95.  
  96. BOOL CDropDownGridWnd::OnLButtonHitRowCol(ROWCOL nHitRow, ROWCOL nHitCol, ROWCOL nDragRow, ROWCOL nDragCol, CPoint point, UINT flags, WORD nHitState)
  97. {
  98.     BOOL b = CGXGridWnd::OnLButtonHitRowCol(nHitRow, nHitCol, nDragRow, nDragCol, point, flags, nHitState);
  99.  
  100.     if (nHitState & GX_HITEND)
  101.         m_pMsgWnd->PostMessage(WM_GX_LBOXEND, 0, 0);
  102.  
  103.     return b;
  104. }
  105.  
  106. BOOL CDropDownGridWnd::ProcessKeys(CWnd *pSender, UINT nMessage, UINT nChar, UINT nRepCnt, UINT flags)
  107. {
  108.     if (nChar == 13 || nChar == 10)
  109.     {
  110.         m_pMsgWnd->PostMessage(WM_GX_LBOXEND, 0, 0);
  111.         return TRUE;
  112.     }
  113.  
  114.     return CGXGridWnd::ProcessKeys(pSender, nMessage, nChar, nRepCnt, flags);
  115. }
  116.  
  117. BOOL CDropDownGridWnd::OnActivateGrid( BOOL bActivate )
  118. {
  119.     if (GetLastActivePopup() != m_pGridWnd)
  120.         return TRUE;
  121.  
  122.     if (!bActivate)
  123.     {
  124.         m_pMsgWnd->PostMessage(WM_GX_LBOXCANCEL, 0, 0);
  125.         return TRUE;
  126.     }
  127.  
  128.     return CGXGridWnd::OnActivateGrid(bActivate);
  129. }
  130.  
  131.  
  132. BEGIN_MESSAGE_MAP(CDropDownGridWnd, CGXGridWnd)
  133.     //{{AFX_MSG_MAP(CDropDownGridWnd)
  134.     //}}AFX_MSG_MAP
  135. END_MESSAGE_MAP()
  136.  
  137. #ifdef _DEBUG
  138. void CDropDownGridWnd::AssertValid() const
  139. {
  140.     CGXGridWnd::AssertValid();
  141. }
  142.  
  143. void CDropDownGridWnd::Dump(CDumpContext& dc) const
  144. {
  145.     CGXGridWnd::Dump(dc);
  146. }
  147.  
  148. #endif //_DEBUG
  149.  
  150. /////////////////////////////////////////////////////////////////////////////
  151. // CDropGridControl control
  152.  
  153. const int nComboBtnWidth = 15;
  154. const int nComboBtnHeight = 18;
  155.  
  156. CDropGridControl::CDropGridControl(CGXGridCore* pGrid, UINT nEditID, UINT nDropGridID)
  157.     : CGXEditControl(pGrid, nEditID)
  158. {
  159.     AddChild(m_pButton = new CGXComboBoxButton(this));
  160.     m_nDropGridID = nDropGridID;
  161.     m_pDropDownWnd = NULL;
  162. }
  163.  
  164. CDropGridControl::~CDropGridControl()
  165. {
  166.     if (m_pDropDownWnd)
  167.     {
  168.         m_pDropDownWnd->DestroyWindow();
  169.         m_pDropDownWnd  = NULL;
  170.     }
  171. }
  172.  
  173. BEGIN_MESSAGE_MAP(CDropGridControl, CGXEditControl)
  174.     //{{AFX_MSG_MAP(CDropGridControl)
  175.     ON_MESSAGE(WM_GX_LBOXEND, OnListBoxEnd)
  176.     ON_MESSAGE(WM_GX_LBOXCANCEL, OnListBoxCancel)
  177.     ON_MESSAGE(WM_GX_LBOXCHANGED, OnListBoxChanged)
  178.     //}}AFX_MSG_MAP
  179. END_MESSAGE_MAP()
  180.  
  181. CRect CDropGridControl::GetCellRect(ROWCOL nRow, ROWCOL nCol, LPRECT rectItem /* = NULL */, const CGXStyle* pStyle /*= NULL*/)
  182. {
  183.     // compute the interior rectangle for the text
  184.     // without buttons and borders
  185.  
  186.     CRect rect = CGXEditControl::GetCellRect(nRow, nCol, rectItem, pStyle);
  187.  
  188.     rect.right -= nComboBtnWidth;
  189.  
  190.     return rect;
  191. }
  192.  
  193. void CDropGridControl::Init(ROWCOL nRow, ROWCOL nCol)
  194. {
  195.     CGXEditControl::Init(nRow, nCol);
  196.  
  197.     // Force drawing of button for current cell
  198.     GridWnd()->InvalidateRect(m_pButton->GetRect());
  199. }
  200.  
  201. void CDropGridControl::OnInitChilds(ROWCOL nRow, ROWCOL nCol, const CRect& rect)
  202. {
  203.     nRow, nCol;
  204.  
  205.     // initialize combobox button
  206.     CRect rectBtn(
  207.             max(rect.left+1, rect.right-1-nComboBtnWidth),
  208.             rect.top+1,
  209.             rect.right-1,
  210.             min(rect.top+nComboBtnHeight, rect.bottom-1));
  211.  
  212.     m_pButton->SetRect(rectBtn);
  213. }
  214.  
  215. void CDropGridControl::OnClickedButton(CGXChild* pChild)
  216. {
  217.     pChild;
  218.  
  219.     if (m_pDropDownWnd)
  220.         SendMessage(WM_GX_LBOXEND, 0, TRUE);
  221.  
  222.     // Style
  223.     const CGXStyle& style = Grid()->LookupStyleRowCol(m_nRow, m_nCol);
  224.  
  225.     CRect rect = CGXControl::GetCellRect(m_nRow, m_nCol, NULL, &style);
  226.  
  227.     // calculate rectangle for popup window
  228.     CWnd* desktopWnd = CWnd::GetDesktopWindow();
  229.  
  230.     CRect desktopRect;
  231.     desktopWnd->GetClientRect(&desktopRect);
  232.  
  233.     CRect listBoxRect(rect.left, rect.bottom, rect.left+200, rect.bottom+200);
  234.     GridWnd()->ClientToScreen(listBoxRect);
  235.  
  236.     CGXGridCombo::SetComboBoxDropDown(TRUE);
  237.  
  238.     // show popup window with embedded listbox
  239.     // if (m_pDropDownWnd == NULL)
  240.     m_pDropDownWnd = &m_GridWnd;
  241.     m_pDropDownWnd->Create(listBoxRect, this);
  242.  
  243.     m_pDropDownWnd->Initialize();
  244.     m_pDropDownWnd->ShowWindow(SW_SHOW);
  245.     m_pDropDownWnd->SetFocus();
  246.     m_pDropDownWnd->UpdateWindow();
  247.  
  248.     CGXGridCombo::SetComboBoxDropDown(FALSE);
  249. }
  250.  
  251. // WM_MOUSEACTIVATE message
  252. BOOL CDropGridControl::MouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message, int& retval)
  253. {
  254.     if (m_pDropDownWnd)
  255.     {
  256.         retval = MA_ACTIVATEANDEAT;
  257.         SendMessage(WM_GX_LBOXEND, 0, TRUE);
  258.         return TRUE;
  259.     }
  260.  
  261.     return CGXEditControl::MouseActivate(pDesktopWnd, nHitTest, message, retval);
  262. }
  263.  
  264. LRESULT CDropGridControl::OnListBoxEnd(WPARAM, LPARAM )
  265. {
  266.     ASSERT(m_pStyle);
  267.  
  268.     // User has selected an item
  269.     if (m_pDropDownWnd)
  270.     {
  271.         m_pDropDownWnd->TransferCurrentCell(TRUE, FALSE);
  272.  
  273.         CGXGridCombo::SetComboBoxDropDown(TRUE);
  274.         // I need to set m_pDropDownWnd = NULL before I destroy the window
  275.         // This avoids problems when killing the focus results in a call to ListBoxCancel
  276.         CWnd* pDropDownWnd = m_pDropDownWnd;
  277.         m_pDropDownWnd  = NULL;
  278.  
  279.         pDropDownWnd->DestroyWindow();
  280.         // delete pDropDownWnd;
  281.  
  282.         CGXGridCombo::SetComboBoxDropDown(TRUE);
  283.     }
  284.  
  285.     return 0;
  286. }
  287.  
  288. LRESULT CDropGridControl::OnListBoxCancel(WPARAM, LPARAM)
  289. {
  290.     // User has canceled listbox selection
  291.     if (m_pDropDownWnd)
  292.     {
  293.         CGXGridCombo::SetComboBoxDropDown(TRUE);
  294.         // I need to set m_pDropDownWnd = NULL before I destroy the window
  295.         // This avoids problems when killing the focus results in a further call to ListBoxCancel
  296.         CWnd* pDropDownWnd = m_pDropDownWnd;
  297.         m_pDropDownWnd  = NULL;
  298.  
  299.         pDropDownWnd->DestroyWindow();
  300.         // delete pDropDownWnd;
  301.         CGXGridCombo::SetComboBoxDropDown(FALSE);
  302.     }
  303.     return 0;
  304. }
  305.  
  306. LRESULT CDropGridControl::OnListBoxChanged(WPARAM, LPARAM)
  307. {
  308.     // User has changed selection
  309.     return 0;
  310. }
  311.  
  312. IMPLEMENT_DYNCREATE(CGridSample6View, CMyGridView)
  313. IMPLEMENT_DYNAMIC(CDropDownGridWnd, CGXGridWnd)
  314. IMPLEMENT_CONTROL(CDropGridControl, CGXEditControl)
  315.  
  316. static TCHAR BASED_CODE szInstruct[] =
  317.         _T("This view illustrates using a grid control as cell ")
  318.         _T("or dropdown grid.");
  319.  
  320. #define new DEBUG_NEW
  321.  
  322.  
  323.  
  324. /////////////////////////////////////////////////////////////////////////////
  325. // CGridSample6View
  326.  
  327. BEGIN_MESSAGE_MAP(CGridSample6View, CMyGridView)
  328.     //{{AFX_MSG_MAP(CGridSample6View)
  329.     ON_COMMAND(ID_VIEW_USERACTIONS, OnViewUseractions)
  330.     ON_COMMAND(ID_VIEW_SPLITTERVIEW, OnViewSplitterview)
  331.     //}}AFX_MSG_MAP
  332. END_MESSAGE_MAP()
  333.  
  334. /////////////////////////////////////////////////////////////////////////////
  335. // CGridSample6View construction/destruction
  336.  
  337. CGridSample6View::CGridSample6View()
  338. {
  339.     // SetDrawingTechnique(gxDrawDirectToDC);
  340. }
  341.  
  342. CGridSample6View::~CGridSample6View()
  343. {
  344. }
  345.  
  346. BOOL CGridSample6View::ConnectParam()
  347. {
  348.     // Note: this method is copied from CGridSampleView
  349.     //
  350.  
  351.     BOOL bNew = FALSE;
  352.  
  353.     // Retrive the zero-based worksheet-id if used as worksheet
  354.     if (GetParentTabWnd(this, TRUE))
  355.         m_nViewID = GetParentTabViewID(this);
  356.  
  357.     // check if it is a new pane in a splitter window
  358.     CSplitterWnd* pSplitterWnd = GetParentDynamicSplitter(this, TRUE);
  359.     if (pSplitterWnd != NULL)
  360.     {
  361.         CGXGridView *pView = (CGXGridView *) pSplitterWnd->GetPane(0, 0);
  362.         if (pView != this)
  363.             m_nViewID = pView->GetViewID();
  364.     }
  365.  
  366.     // check if parameter-object exist (in document)
  367.     if (GetDocument()->GetParam(m_nViewID) == NULL)
  368.     {
  369.         // create a parameter-object on the heap
  370.         GetDocument()->SetParam(m_nViewID, new CGXGridParam);
  371.  
  372.         bNew = TRUE;    // this view needs initializing
  373.     }
  374.  
  375.     // connect parameter-object with grid
  376.     SetParam((CGXGridParam*) GetDocument()->GetParam(m_nViewID), FALSE);
  377.  
  378.     return bNew;
  379. }
  380.  
  381. void CGridSample6View::SetupControls()
  382. {
  383.     // Register all controls for the view
  384.  
  385.     RegisterControl(IDS_CTRL_DROPGRID, new CDropGridControl(this, IDS_CTRL_GRIDCHILD, IDS_CTRL_GRIDCHILD+1));
  386.  
  387.     // ... This is a cool demonstration of the CGXWndWrapper class
  388.  
  389.     CGXGridWnd* pGridWnd = new CGXGridWnd();
  390.     VERIFY(pGridWnd->Create(WS_BORDER | WS_VSCROLL | WS_HSCROLL, CRect(0,0,1,1), this, IDS_CTRL_GRIDCHILD));
  391.     pGridWnd->Initialize();
  392.     pGridWnd->SetRowCount(32);
  393.     pGridWnd->SetColCount(16);
  394.  
  395.     RegisterControl(IDS_CTRL_GRIDCHILD,
  396.         new CGXWndWrapper(this,
  397.                 pGridWnd,
  398.                 TRUE, // must delete
  399.                 TRUE, // can activate
  400.                 FALSE // no invert borders
  401.             ));
  402.     //
  403.     // Please note that deriving with multiple inheritance would be
  404.     // the better solution (see the note in the CGXWndWrapper class definition)
  405.     //
  406.     // Normally, a control is shared among the cells. (see CGXSpinEdit, CGXComboBox, ...)
  407.     // The CGXWndWrapper class allows you to connect every window you want.
  408.     // The window is responsible for drawing its area.
  409.     //
  410.     // Attention!
  411.     // You have to consider if it makes sense to share a CGXWndWrapper-object
  412.     // among several cells. Each cell would have a pointer to the same window.
  413.     // e.g. sharing sharing the grid control (see above) does not make sense.
  414.  
  415. }
  416.  
  417. /////////////////////////////////////////////////////////////////////////////
  418. // CGridSample6View drawing
  419.  
  420. void CGridSample6View::OnInitialUpdate()
  421. {
  422.     BOOL bNew = ConnectParam();
  423.  
  424.     CMyGridView::OnInitialUpdate(); // Creates all objects and links them to the grid
  425.  
  426.     // Register all controls for the view
  427.     SetupControls();
  428.  
  429.     if (bNew)
  430.     {
  431.         // Don't create undo-information for the following commands
  432.         GetParam()->EnableUndo(FALSE);
  433.         // (at the end of this procedure, I will reenable it)
  434.  
  435.         // Number of rows and columns
  436.         SetRowCount(100);
  437.         SetColCount(20);
  438.  
  439.         GetParam()->GetProperties()->SetDisplayVertLines(FALSE);
  440.         GetParam()->GetProperties()->SetDisplayHorzLines(FALSE);
  441.  
  442.         SetRowHeight(5, 20, Height_LPtoDP(GX_NYHEIGHT)*2);
  443.                     // GX_NYHEIGHT is the logical height of a line
  444.  
  445.         SetCoveredCellsRowCol(5, 1, 10, 5);
  446.         SetStyleRange(CGXRange(5,1), CGXStyle()
  447.                 .SetControl(IDS_CTRL_GRIDCHILD)
  448.             );
  449.  
  450.  
  451.         SetStyleRange(CGXRange(12,2), CGXStyle().SetValue(_T("Dropdown Grid -> ")));
  452.         SetStyleRange(CGXRange(12,3), CGXStyle()
  453.                 .SetControl(IDS_CTRL_DROPGRID)
  454.                 .SetInterior(RGB(192,192,192))
  455.                 .SetBorders(gxBorderAll, CGXPen().SetWidth(3).SetColor(RGB(0,0,128)))
  456.             );
  457.  
  458.  
  459.         // Instructions
  460.         SetCoveredCellsRowCol(1, 1, 3, 5);
  461.         SetStyleRange(CGXRange(1,1),
  462.             CGXStyle()
  463.                 .SetWrapText(TRUE)
  464.                 .SetEnabled(FALSE)
  465.                 .SetFont(CGXFont().SetFaceName(_T("Times New Roman")))
  466.                 .SetInterior(RGB(255,251,240))   // Off-white
  467.                 .SetHorizontalAlignment(DT_CENTER)
  468.                 .SetVerticalAlignment(DT_VCENTER)
  469.                 .SetControl(GX_IDS_CTRL_STATIC)
  470.                 .SetBorders(gxBorderAll, CGXPen().SetWidth(2))
  471.                 .SetValue(szInstruct));
  472.  
  473.  
  474.  
  475.         // Enable creation of undo-information for user interactions
  476.         GetParam()->EnableUndo(TRUE);
  477.     }
  478.  
  479.     // Position the current cell
  480.  
  481.     SetCurrentCell(4, 1, FALSE /* avoid immediate updating */);
  482.  
  483.     // Enable Update-Hint-Mechanism
  484.  
  485.     EnableHints();
  486. }
  487.  
  488. /////////////////////////////////////////////////////////////////////////////
  489. // CGridSample6View diagnostics
  490.  
  491. #ifdef _DEBUG
  492. void CGridSample6View::AssertValid() const
  493. {
  494.     CMyGridView::AssertValid();
  495. }
  496.  
  497. void CGridSample6View::Dump(CDumpContext& dc) const
  498. {
  499.     CMyGridView::Dump(dc);
  500. }
  501.  
  502. CGridSampleDoc* CGridSample6View::GetDocument() // non-debug version is inline
  503. {
  504.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGridSampleDoc)));
  505.     return (CGridSampleDoc*) m_pDocument;
  506. }
  507.  
  508. #endif //_DEBUG
  509.  
  510.  
  511. /////////////////////////////////////////////////////////////////////////////
  512. // CGridSample6View message handlers
  513.  
  514. // Menu handler for View->Splitter View
  515.  
  516. void CGridSample6View::OnViewSplitterview()
  517. {
  518.     CDocument* pDoc = GetDocument();
  519.  
  520.     CMyMultiDocTemplate* pTemplate
  521.         = (CMyMultiDocTemplate*) ((CGridSampleApp*) AfxGetApp())->m_pSplitterTemplate;
  522.  
  523.     pTemplate->SetViewClass(GetRuntimeClass());
  524.  
  525.     CMDIChildWnd* pNewFrame
  526.         = (CMDIChildWnd*) pTemplate->CreateNewFrame(GetDocument(), NULL);
  527.  
  528.     if (pNewFrame == NULL)
  529.         return;     // not created
  530.  
  531.     ASSERT(pNewFrame->IsKindOf(RUNTIME_CLASS(CSplitterMDIChildWnd)));
  532.  
  533.     CSplitterWnd& splitter = (CSplitterWnd&)
  534.         ((CSplitterMDIChildWnd *) pNewFrame)->m_wndSplitter;
  535.  
  536.     CGridSample6View* pView = (CGridSample6View*)
  537.         splitter.GetPane(0, 0);
  538.  
  539.     // Set view id to active tab view id
  540.     pView->m_nViewID = m_nViewID;
  541.  
  542.     pTemplate->InitialUpdateFrame(pNewFrame, pDoc);
  543.  
  544.     pNewFrame->GetActiveView();
  545.     ASSERT(pView);
  546. }
  547.  
  548. // Menu handler for View->User Actions...
  549.  
  550. void CGridSample6View::OnViewUseractions()
  551. {
  552.     // Note: this method is copied from CGridSampleView
  553.     //
  554.     // Shows a dialog with some attributes of the parameter-object
  555.     // where you can experiment with some attributes
  556.     // such as allowing the user to track columns, select cells
  557.     // or use the grid as a listbox.
  558.  
  559.     // Transfer Current Cell's Data to grid
  560.     if (!TransferCurrentCell())
  561.         return;
  562.  
  563.     CUserActionsDialog dlg(GetParam());
  564.  
  565.     if (dlg.DoModal() == IDOK)
  566.     {
  567.         // Redraw the grid
  568.         Redraw();
  569.     }
  570. }
  571.  
  572.