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

  1. // gridsvw5.cpp : implementation of the CGridSample5View 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 "gridsvw5.h"
  20. #include "dlguser.h"
  21. #include "mainfrm.h"
  22. #include "gridfrms.h"
  23.  
  24. #include "gxtwnd.h"
  25.  
  26.  
  27. #ifdef _DEBUG
  28. #undef THIS_FILE
  29. static char BASED_CODE THIS_FILE[] = __FILE__;
  30. #endif
  31.  
  32. //
  33. // CGridSample5View can be used as standalone, splitter or worksheet gridview
  34. // as you have already seen with CGridSampleView
  35. //
  36. // CGridSample5View illustrates applying controls to cells or deriving
  37. // and registerφng your own controls. It also illustrates how to
  38. // use comboboxes in column headers.
  39. //
  40. // CSimpleButton provides a button control you can use a prototype
  41. // for creating your own controls.
  42. //
  43. // CBitmapBtnEdit provides a sample how to use small buttons in a control
  44. //
  45. // CArrowRowHeader is a control you can apply to ro headers. It will
  46. // display an arrow if the row owns the current cell.
  47. //
  48.  
  49. IMPLEMENT_DYNCREATE(CGridSample5View, CMyGridView)
  50. IMPLEMENT_CONTROL(CSimpleButton, CGXStatic)
  51. IMPLEMENT_CONTROL(CBitmapBtnEdit, CGXEditControl)
  52. IMPLEMENT_CONTROL(CArrowRowHeader, CGXControl)
  53. IMPLEMENT_CONTROL(COwnerDrawnComboBox, CGXComboBoxWnd)
  54. IMPLEMENT_CONTROL(CMyComboBox, CGXComboBox)
  55.  
  56. static TCHAR BASED_CODE szInstruct[] =
  57.         _T("This view shows standard and user defined controls and special headers. ")
  58.         _T("You can apply controls to cells by calling Format->Cells->Control ")
  59.         _T("or by changing the Control setting of a base style (Format->Styles).");
  60.  
  61. #define new DEBUG_NEW
  62.  
  63. /////////////////////////////////////////////////////////////////////////////
  64. // CSimpleButton control
  65.  
  66. CSimpleButton::CSimpleButton(CGXGridCore* pGrid)
  67.     : CGXStatic(pGrid)
  68. {
  69.     m_bPressed = FALSE;
  70. }
  71.  
  72. CSimpleButton::~CSimpleButton()
  73. {
  74. }
  75.  
  76. void CSimpleButton::Draw(CDC* pDC, CRect rect, ROWCOL nRow, ROWCOL nCol, const CGXStyle& style, const CGXStyle* pStandardStyle)
  77. {
  78.     WORD nState = 0;
  79.  
  80.     // Select font
  81.     CFont* pOldFont = LoadFont(pDC, style, pStandardStyle);
  82.  
  83.     BOOL bActive = (m_nRow == nRow && m_nCol == nCol && !Grid()->IsPrinting()
  84.                 && Grid()->IsActiveFrame());
  85.  
  86.     if (bActive)
  87.     {
  88.         nState |= GX_BTNFOCUS;
  89.  
  90.         if (m_bPressed)
  91.             nState |= GX_BTNPRESSED;
  92.     }
  93.  
  94.  
  95.     // start of drawing buttons technique 1 ->
  96.  
  97.     CRect rectText = GetCellRect(nRow, nCol, rect);
  98.  
  99.     // Background
  100.     DrawBackground(pDC, rect, style);
  101.  
  102.     // Draw pressed or button look
  103.     CRect r = CGXControl::GetCellRect(nRow, nCol, rect);
  104.  
  105.     if (nState & GX_BTNPRESSED)
  106.         GXDrawEdge(pDC, r, BDR_SUNKENOUTER | BDR_SUNKENINNER);
  107.     else
  108.         GXDrawEdge(pDC, r, BDR_RAISEDOUTER | BDR_RAISEDINNER);
  109.  
  110.     // button text
  111.     CRect faceRect(r.left+1, r.top+1, r.right-2, r.bottom-2);
  112.     if (nState & GX_BTNPRESSED)
  113.         faceRect += CPoint(1,1);
  114.  
  115.     // Draw static text
  116.     pDC->SetBkMode(TRANSPARENT);
  117.     pDC->SetTextColor(style.GetTextColor());
  118.  
  119.     CString sOutput;
  120.     if (GetControlText(sOutput, nRow, nCol, NULL, style))
  121.         GXDrawFocusText(pDC, faceRect, nState&GX_BTNFOCUS, sOutput);
  122.  
  123.     // <- end of technique 1
  124.  
  125. /*
  126.     // start of drawing buttons technique 2 ->
  127.  
  128.     DrawBackground(pDC, rect, style);
  129.  
  130.     GXDrawPushButton(pDC,
  131.         rect.left, rect.top,
  132.         rect.Width(), rect.Height(),
  133.         w,
  134.         style.GetValueRef());
  135.  
  136.     // <- end of technique 2
  137. */
  138.  
  139.     if (pOldFont)
  140.         pDC->SelectObject(pOldFont);
  141. }
  142.  
  143. BOOL CSimpleButton::LButtonDown(UINT nFlags, CPoint pt, UINT nHitState)
  144. {
  145.     m_bMouseDown = TRUE;
  146.     m_bPressed = TRUE;
  147.     Refresh();
  148.  
  149.     // unreferenced:
  150.     nFlags, pt, nHitState;
  151.  
  152.     return TRUE;
  153. }
  154.  
  155. BOOL CSimpleButton::RButtonDown(UINT nFlags, CPoint pt, UINT nHitState)
  156. {
  157.     m_bMouseDown = TRUE;
  158.     m_bPressed = TRUE;
  159.     Refresh();
  160.  
  161.     // unreferenced:
  162.     nFlags, pt, nHitState;
  163.  
  164.     return TRUE;
  165. }
  166.  
  167. BOOL CSimpleButton::LButtonUp(UINT nFlags, CPoint pt, UINT nHitState)
  168. {
  169.     nFlags, pt;
  170.  
  171.     CRect rect = CGXControl::GetCellRect(m_nRow, m_nCol);
  172.  
  173.     if (m_bMouseDown && m_bPressed && rect.PtInRect(pt))
  174.         OnClickedButton(NULL);
  175.  
  176.     m_bPressed = FALSE;
  177.     m_bMouseDown = FALSE;
  178.     Refresh();
  179.  
  180.     // unreferenced:
  181.     nFlags, pt, nHitState;
  182.  
  183.     return TRUE;
  184. }
  185.  
  186. BOOL CSimpleButton::RButtonUp(UINT nFlags, CPoint pt, UINT nHitState)
  187. {
  188.     nFlags, pt;
  189.  
  190.     CRect rect = CGXControl::GetCellRect(m_nRow, m_nCol);
  191.  
  192.     if (m_bMouseDown && m_bPressed && rect.PtInRect(pt))
  193.         AfxMessageBox(_T("Right button clicked!\n"));
  194.  
  195.     m_bPressed = FALSE;
  196.     m_bMouseDown = FALSE;
  197.     Refresh();
  198.  
  199.     // unreferenced:
  200.     nFlags, pt, nHitState;
  201.  
  202.     return TRUE;
  203. }
  204.  
  205. BOOL CSimpleButton::MouseMove(UINT nFlags, CPoint pt, UINT nHitState)
  206. {
  207.     nFlags, pt;
  208.  
  209.     CRect rect = CGXControl::GetCellRect(m_nRow, m_nCol);
  210.  
  211.     BOOL bState = rect.PtInRect(pt);
  212.  
  213.     if (m_bMouseDown && bState != m_bPressed)
  214.     {
  215.         m_bPressed = bState;
  216.         Refresh();
  217.     }
  218.  
  219.     // unreferenced:
  220.     nFlags, pt, nHitState;
  221.  
  222.     return TRUE;
  223. }
  224.  
  225. BOOL CSimpleButton::KeyPressed(UINT nMessage, UINT nChar, UINT nRepCnt, UINT flags)
  226. {
  227.     BOOL bRet = CGXControl::KeyPressed(nMessage, nChar, nRepCnt, flags);
  228.  
  229.     if (nChar == 32 && nMessage == WM_KEYDOWN)
  230.     {
  231.         // Draw pressed
  232.         m_bPressed = TRUE;
  233.         Refresh();
  234.         return TRUE;
  235.     }
  236.     else if (nChar == 32 && nMessage == WM_KEYUP && m_bPressed)
  237.     {
  238.         // trigger event
  239.         OnClickedButton(NULL);
  240.  
  241.         // Draw normal
  242.         m_bPressed = FALSE;
  243.         Refresh();
  244.         return TRUE;
  245.     }
  246.  
  247.     return bRet;
  248. }
  249.  
  250. void CSimpleButton::InvertBorders(CDC* pDC, const CRect& r)
  251. {
  252.     // I don't want an inverted frame
  253.  
  254.     // unreferenced:
  255.     pDC, r;
  256. }
  257.  
  258. void CSimpleButton::OnClickedButton(CGXChild* pChild)
  259. {
  260.     // Unreferenced parameters:
  261.     pChild;
  262.  
  263.     // display a message box with the text specified in
  264.     // the user attribut "MessageText" (see the style-sheet)
  265.  
  266.     AfxMessageBox(Grid()->LookupStyleRowCol(m_nRow, m_nCol)
  267.         .GetUserAttribute(IDS_ATTR_MSGTEXT));
  268. }
  269.  
  270. /////////////////////////////////////////////////////////////////////////////
  271. // CBitmapBtnEdit control
  272.  
  273. CBitmapBtnEdit::CBitmapBtnEdit(CGXGridCore* pGrid, UINT nID)
  274.     : CGXEditControl(pGrid, nID)
  275. {
  276.     // Use CGXDIBitmapButton instead of CGXBitmapButton
  277.     AddChild(m_pButton = new CGXDIBitmapButtonChild(this));
  278.     VERIFY(m_pButton->LoadBitmaps(IDB_BITMAP1));
  279.  
  280.     m_sizeBtn = CSize(14,14);
  281. }
  282.  
  283. BEGIN_MESSAGE_MAP(CBitmapBtnEdit, CGXEditControl)
  284.     //{{AFX_MSG_MAP(CBitmapBtnEdit)
  285.     //}}AFX_MSG_MAP
  286. END_MESSAGE_MAP()
  287.  
  288. CRect CBitmapBtnEdit::GetCellRect(ROWCOL nRow, ROWCOL nCol, LPRECT rectItem /* = NULL */, const CGXStyle* pStyle /*= NULL*/)
  289. {
  290.     // compute the interior rectangle for the text
  291.     // without buttons and borders
  292.  
  293.     CRect rect = CGXEditControl::GetCellRect(nRow, nCol, rectItem, pStyle);
  294.  
  295.     rect.left += m_sizeBtn.cx+3;
  296.  
  297.     return rect;
  298. }
  299.  
  300. void CBitmapBtnEdit::OnInitChilds(ROWCOL nRow, ROWCOL nCol, const CRect& rect)
  301. {
  302.     nRow, nCol;
  303.  
  304.     int nTop = (max(0, rect.Height() - m_sizeBtn.cy)) / 2;
  305.  
  306.     // init BitmapBtn button
  307.     CRect rectBtn;
  308.     rectBtn.IntersectRect(rect,
  309.                 CRect(rect.left+3,
  310.                     rect.top + nTop,
  311.                     rect.left+3+m_sizeBtn.cx,
  312.                     rect.top+ nTop + m_sizeBtn.cy)
  313.                 );
  314.  
  315.     m_pButton->SetRect(rectBtn);
  316. }
  317.  
  318. void CBitmapBtnEdit::OnClickedButton(CGXChild* pChild)
  319. {
  320.     pChild;
  321.     AfxMessageBox(_T("You pressed the bitmap"));
  322. };
  323.  
  324. BOOL CBitmapBtnEdit::OnValidate()
  325. {
  326.     CString s;
  327.     GetWindowText(s);
  328.     if (_ttoi(s) > 100)
  329.     {
  330.         Grid()->SetWarningText(_T("Values greater 100 are invalid!"));
  331.         return FALSE;
  332.     }
  333.     return TRUE;
  334. }
  335.  
  336.  
  337. /////////////////////////////////////////////////////////////////////////////
  338. // CArrowRowHeader
  339.  
  340. CArrowRowHeader::CArrowRowHeader(CGXGridCore* pGrid)
  341.     : CGXControl(pGrid)
  342. {
  343. }
  344.  
  345. void CArrowRowHeader::Draw(CDC* pDC, CRect rect, ROWCOL nRow, ROWCOL nCol, const CGXStyle& style, const CGXStyle* pStandardStyle)
  346. {
  347.     // no arrow needed when printing
  348.     if (Grid()->IsPrinting())
  349.         return;
  350.  
  351.     // Cell-Color
  352.     COLORREF rgbText = style.GetTextColor();
  353.     COLORREF rgbCell = style.GetInteriorRef().GetColor();
  354.  
  355.     BOOL bArrow = nRow > 0 && Grid()->IsCurrentCell(nRow);
  356.  
  357.     GXDrawButton(pDC, rect.left, rect.top,
  358.         rect.Width(), rect.Height(), FALSE, rgbCell);
  359.  
  360.     const int nSize = 9;
  361.  
  362.     if (bArrow && rect.Width() > nSize && rect.Height() > nSize)
  363.     {
  364.         int x = rect.left + (rect.Width() - nSize) / 2;
  365.         int y = rect.top + (rect.Height() - nSize) / 2;
  366.  
  367.         GXPatB(pDC, x++, y++, 1, 9, rgbText);
  368.         GXPatB(pDC, x++, y++, 1, 7, rgbText);
  369.         GXPatB(pDC, x++, y++, 1, 5, rgbText);
  370.         GXPatB(pDC, x++, y++, 1, 3, rgbText);
  371.         GXPatB(pDC, x++, y++, 1, 1, rgbText);
  372.     }
  373.  
  374.     CGXControl::Draw(pDC, rect, nRow, nCol, style, pStandardStyle);
  375. }
  376.  
  377. /////////////////////////////////////////////////////////////////////////////
  378. // CMyComboBox control
  379.  
  380. CMyComboBox::CMyComboBox(CGXGridCore* pGrid, UINT nEditID, UINT nListBoxID, UINT nFlags)
  381.     : CGXComboBox(pGrid, nEditID, nListBoxID, nFlags)
  382. {
  383. }
  384.  
  385. void CMyComboBox::Init(ROWCOL nRow, ROWCOL nCol)
  386. {
  387.     CGXComboBox::Init(nRow, nCol);
  388. }
  389.  
  390. BOOL CMyComboBox::OnCommand(WPARAM wParam, LPARAM lParam)
  391. {
  392. #if _MFC_VER < 0x0300
  393.     UINT nNotification = HIWORD(lParam);
  394.     HWND hCtl = (HWND) LOWORD(lParam);
  395. #else
  396.     UINT nNotification = HIWORD(wParam);
  397.     HWND hCtl = (HWND) lParam;
  398. #endif
  399.  
  400.     if (hCtl == m_hWnd)
  401.     {
  402.         // Edit Control changed
  403.     }
  404.     else if (GetDroppedState())
  405.     {
  406.         // Listbox changed
  407.         if (nNotification == LBN_SELCHANGE)
  408.             TRACE0("Listbox changed\n" );
  409.         else
  410.             TRACE1("Listbox notification %d\n", nNotification );
  411.     }
  412.  
  413.     return CGXComboBox::OnCommand(wParam, lParam);
  414. }
  415.  
  416. /////////////////////////////////////////////////////////////////////////////
  417. // COwnerDrawnComboBox
  418.  
  419. static COLORREF VGAColorsArray[20] = {
  420.         RGB(0,0,0),         // Black
  421.         RGB(0,0,255),       // Bright blue
  422.         RGB(0,255,0),       // Bright green
  423.         RGB(0,255,255),     // Cyan
  424.         RGB(255,0,0),       // Bright red
  425.         RGB(255,0,255),     // Magenta
  426.         RGB(255,255,0),     // Bright yellow
  427.         RGB(255,255,255),   // White
  428.         RGB(0,0,128),       // Dark blue
  429.         RGB(0,128,0),       // Dark green
  430.         RGB(0,128,128),     // Blue-green
  431.         RGB(128,0,0),       // Brown
  432.         RGB(128,0,128),     // Dark purple
  433.         RGB(128,128,0),     // Olive
  434.         RGB(128,128,128),   // Dark gray
  435.         RGB(192,192,192),   // Light gray
  436.         RGB(192,220,192),   // Pale green
  437.         RGB(166,202,240),   // Light blue
  438.         RGB(255,251,240),   // Off-white
  439.         RGB(160,160,164),   // Medium gray
  440.     };
  441.  
  442. COwnerDrawnComboBox::COwnerDrawnComboBox(CGXGridCore* pGrid)
  443.     : CGXComboBoxWnd(pGrid)
  444. {
  445.     m_bFillWithChoiceList = FALSE;  // must be FALSE for ownderdrawn combobox
  446.     m_bWantArrowKeys = FALSE;       // pass arrow keys to Grid
  447.     m_nIndexValue = 0;              // 0 = Item 0, 1 = Item 1, ... n = Item N
  448.  
  449.     m_bSizeToContent = TRUE;
  450.     // set m_nIndexValue = 1 if you want to have 1 = Item 0, 2 = Item 1, ... n = Item N+1
  451. }
  452.  
  453. COwnerDrawnComboBox::~COwnerDrawnComboBox()
  454. {
  455. }
  456.  
  457. void COwnerDrawnComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  458. {
  459.     CRect rc = lpDrawItemStruct->rcItem;
  460.     COLORREF rgbColor = lpDrawItemStruct->itemData;
  461.     CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  462.  
  463.     GXPatB(pDC, rc, rgbColor);
  464.  
  465.     if (lpDrawItemStruct->itemState & ODS_SELECTED)
  466.     {
  467.         CBrush br;
  468.         br.CreateStockObject(BLACK_BRUSH);
  469.         pDC->FrameRect(CRect(rc.left, rc.top, rc.right, rc.bottom), &br);
  470.     }
  471. }
  472.  
  473. void COwnerDrawnComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  474. {
  475.     lpMeasureItemStruct->itemHeight = 20;
  476. }
  477.  
  478. BEGIN_MESSAGE_MAP(COwnerDrawnComboBox, CGXComboBoxWnd)
  479.     //{{AFX_MSG_MAP(COwnerDrawnComboBox)
  480.     //}}AFX_MSG_MAP
  481. END_MESSAGE_MAP()
  482.  
  483. BOOL COwnerDrawnComboBox::OnCommand(WPARAM wParam, LPARAM lParam)
  484. {
  485. #if _MFC_VER < 0x0300
  486.     UINT nNotification = HIWORD(lParam);
  487.     HWND hCtl = (HWND) LOWORD(lParam);
  488. #else
  489.     UINT nNotification = HIWORD(wParam);
  490.     HWND hCtl = (HWND) lParam;
  491. #endif
  492.  
  493.     if (hCtl == m_hWnd)     // is it really this wnd?
  494.     {
  495.         if (nNotification == CBN_SELCHANGE
  496.             || nNotification == CBN_EDITCHANGE)
  497.         {
  498.             TRACE0("Combobox changed\n");
  499.         }
  500.     }
  501.  
  502.     return CGXComboBoxWnd::OnCommand(wParam, lParam);
  503. }
  504.  
  505. /////////////////////////////////////////////////////////////////////////////
  506. // CGridSample5View
  507.  
  508. BEGIN_MESSAGE_MAP(CGridSample5View, CMyGridView)
  509.     //{{AFX_MSG_MAP(CGridSample5View)
  510.     ON_COMMAND(ID_VIEW_USERACTIONS, OnViewUseractions)
  511.     ON_COMMAND(ID_VIEW_SPLITTERVIEW, OnViewSplitterview)
  512.     //}}AFX_MSG_MAP
  513. END_MESSAGE_MAP()
  514.  
  515. /////////////////////////////////////////////////////////////////////////////
  516. // CGridSample5View construction/destruction
  517.  
  518. CGridSample5View::CGridSample5View()
  519. {
  520.     // TODO: add construction code here
  521. }
  522.  
  523. CGridSample5View::~CGridSample5View()
  524. {
  525. }
  526.  
  527. BOOL CGridSample5View::ConnectParam()
  528. {
  529.     // Note: this method is copied from CGridSampleView
  530.     //
  531.  
  532.     BOOL bNew = FALSE;
  533.  
  534.     // Retrive the zero-based worksheet-id if used as worksheet
  535.     if (GetParentTabWnd(this, TRUE))
  536.         m_nViewID = GetParentTabViewID(this);
  537.  
  538.     // check if it is a new pane in a splitter window
  539.     CSplitterWnd* pSplitterWnd = GetParentDynamicSplitter(this, TRUE);
  540.     if (pSplitterWnd != NULL)
  541.     {
  542.         CGXGridView *pView = (CGXGridView *) pSplitterWnd->GetPane(0, 0);
  543.         if (pView != this)
  544.             m_nViewID = pView->GetViewID();
  545.     }
  546.  
  547.     // check if parameter-object exist (in document)
  548.     if (GetDocument()->GetParam(m_nViewID) == NULL)
  549.     {
  550.         // create a parameter-object on the heap
  551.         GetDocument()->SetParam(m_nViewID, new CGXGridParam);
  552.  
  553.         bNew = TRUE;    // this view needs initializing
  554.     }
  555.  
  556.     // connect parameter-object with grid
  557.     SetParam((CGXGridParam*) GetDocument()->GetParam(m_nViewID), FALSE);
  558.  
  559.     return bNew;
  560. }
  561.  
  562. void CGridSample5View::SetupControls()
  563. {
  564.     // Register all controls for the view
  565.  
  566.     // First, the simple control
  567.     RegisterControl(IDS_CTRL_SIMPLE, new CSimpleButton(this));
  568.  
  569.     // With its MsgText to display when the button is pressed
  570.     GetParam()->GetStylesMap()->AddUserAttribute(IDS_ATTR_MSGTEXT);
  571.     // the Message Text is specified in OnInitialUpdate!
  572.  
  573.     // In OnInitialUpdate, I do set the default value for this attribute
  574.     // by calling style->SetUserAttribute(IDS_ATTR_MSGTEXT, _T("You pressed the button"));
  575.  
  576.     RegisterControl(IDS_CTRL_EDITBTN, new CBitmapBtnEdit(this, IDS_CTRL_EDITBTN));
  577.  
  578.     RegisterControl(IDS_CTRL_ARROWHEADER, new CArrowRowHeader(this));
  579.  
  580.     RegisterControl(GX_IDS_CTRL_COMBOBOX, new CMyComboBox(this, 2001, 2002, 0));
  581.  
  582.     // CGXWndWrapper allows you to register any CWnd you want.
  583.     CGXTabBeam* pBeam = new CGXTabBeam;
  584.     pBeam->Create(WS_CHILD | WS_CLIPSIBLINGS, CRect(0,0,0,0), this, IDS_CTRL_TABBEAM);
  585.     pBeam->InsertTab(FALSE, _T("Tab 1"));
  586.     pBeam->InsertTab(FALSE, _T("Tab 2"));
  587.     pBeam->InsertTab(FALSE, _T("Tab 3"));
  588.     pBeam->AdjustTabSize(0);
  589.     pBeam->AdjustTabSize(1);
  590.     pBeam->AdjustTabSize(2);
  591.     pBeam->DisplayScrollBtns(FALSE);
  592.     RegisterControl(IDS_CTRL_TABBEAM, new CGXWndWrapper(this, pBeam, TRUE, TRUE, TRUE));
  593.  
  594.     // ownerdrawn CComboBox with CBS_DROPDOWNLIST style
  595.     {
  596.         CGXComboBoxWnd* pWnd = new COwnerDrawnComboBox(this);
  597.         pWnd->Create(WS_VSCROLL | CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED, IDS_CTRL_OWNERDRAWNDROPDOWN);
  598.         RegisterControl(IDS_CTRL_OWNERDRAWNDROPDOWN, pWnd);
  599.  
  600.         for (int n = 0; n < 20; n++)
  601.             pWnd->AddString((LPCTSTR) VGAColorsArray[n]);
  602.     }
  603. }
  604.  
  605. /////////////////////////////////////////////////////////////////////////////
  606. // CGridSample5View drawing
  607.  
  608. void CGridSample5View::OnInitialUpdate()
  609. {
  610.     BOOL bNew = ConnectParam();
  611.  
  612.     CMyGridView::OnInitialUpdate(); // Creates all objects and links them to the grid
  613.  
  614.     // Register all controls for the view
  615.     SetupControls();
  616.  
  617.     if (bNew)
  618.     {
  619.         // Don't create undo-information for the following commands
  620.         GetParam()->EnableUndo(FALSE);
  621.         // (at the end of this procedure, I will reenable it)
  622.  
  623.         // Apply Arrow-Header-Control to Row-Header-Style
  624.         RowHeaderStyle()
  625.             .SetControl(IDS_CTRL_ARROWHEADER)
  626.             .SetEnabled(FALSE);             // disables usage as current cell
  627.  
  628.         // Apply Dropdown-List-Control to Column-Header-Style
  629.         ColHeaderStyle()
  630.             .SetControl(GX_IDS_CTRL_CBS_DROPDOWNLIST)
  631.             .SetInterior(GXSYSCOLOR(COLOR_BTNFACE))
  632.             .SetHorizontalAlignment(DT_CENTER)
  633.             .SetWrapText(FALSE)
  634.             .SetVerticalAlignment(DT_VCENTER)
  635.             .SetFont(CGXFont().SetBold(TRUE))
  636.             .SetChoiceList(_T("Combo Box\none\ntwo\nthree\nfour\nfive\nsix\nseven\neight"))
  637.             .SetValue(_T("Combo Box"))
  638.             .SetDraw3dFrame(gxFrameRaised);
  639.  
  640.         SetRowHeight(0, 0, 30);
  641.  
  642.         // Cell (0,0) is treated like a normal column header
  643.         // So, I do need to reset the style for the cell explicitly.
  644.         SetStyleRange(CGXRange(0,0), CGXStyle()
  645.                 .SetControl(GX_IDS_CTRL_HEADER)
  646.                 .SetEnabled(FALSE)          // disables usage as current cell
  647.                 .SetValue(_T(""))
  648.             );
  649.  
  650.         // Turn off selecting whole columns when clicking on a column header
  651.         GetParam()->EnableSelection((WORD) (GX_SELFULL & ~GX_SELCOL & ~GX_SELTABLE));
  652.  
  653.  
  654.         // Apply default message text for simple control to standard style
  655.         StandardStyle()
  656.             .SetUserAttribute(IDS_ATTR_MSGTEXT, _T("You pressed the button"));
  657.  
  658.         // Number of rows and columns
  659.         SetRowCount(100);
  660.         SetColCount(20);
  661.  
  662.         // Turn off displaying vertical and horizontal lines
  663.         CGXProperties* pProp = GetParam()->GetProperties();
  664.  
  665.         pProp->SetDisplayVertLines(FALSE);
  666.         pProp->SetDisplayHorzLines(FALSE);
  667.  
  668.         pProp->SetPrintRowHeaders(FALSE);   // no row headers when printing
  669.  
  670.         // Setup the table of controls
  671.  
  672.         SetRowHeight(5, 25, Height_LPtoDP(GX_NYHEIGHT)*2);
  673.                     // GX_NYHEIGHT is the logical height of a line
  674.  
  675.         SetColWidth(2, 2, Width_LPtoDP(GX_NXAVGWIDTH)*16);
  676.         SetColWidth(3, 3, Width_LPtoDP(GX_NXAVGWIDTH)*16);
  677.                     // GX_NXAVGWIDTH is the average logical width of a char
  678.  
  679.         // Fill table
  680.  
  681.         // Background and interior borders
  682.  
  683.         SetStyleRange(CGXRange(5,2,24,3), CGXStyle()
  684.                 .SetBorders(gxBorderAll, CGXPen().SetStyle(PS_DOT))
  685.                 .SetInterior(GXSYSCOLOR(COLOR_BTNFACE))
  686.             );
  687.  
  688.         // Alignment
  689.  
  690.         SetStyleRange(CGXRange(5,2,24,2), CGXStyle()
  691.                 .SetVerticalAlignment(DT_VCENTER)
  692.                 .SetHorizontalAlignment(DT_CENTER)
  693.                 .SetFont(CGXFont().SetBold(TRUE))
  694.             );
  695.  
  696.         // Headers
  697.  
  698.         SetStyleRange(CGXRange(5,2,5,3), CGXStyle()
  699.                 .SetBorders(gxBorderBottom, CGXPen().SetWidth(2))
  700.                 .SetBorders(gxBorderTop, CGXPen().SetWidth(2))
  701.                 .SetFont(CGXFont().SetBold(TRUE).SetSize(12))
  702.                 .SetEnabled(FALSE)          // disables usage as current cell
  703.                 .SetInterior(GXSYSCOLOR(COLOR_BTNFACE))
  704.                 .SetHorizontalAlignment(DT_CENTER)
  705.                 .SetVerticalAlignment(DT_VCENTER)
  706.                 );
  707.  
  708.  
  709.         SetStyleRange(CGXRange(5,2), CGXStyle().SetValue(_T("Name")));
  710.         SetStyleRange(CGXRange(5,3), CGXStyle().SetValue(_T("Control")));
  711.         SetStyleRange(CGXRange(5,2,24,2), CGXStyle().SetEnabled(FALSE));
  712.  
  713.         // thick borders
  714.  
  715.         SetStyleRange(CGXRange(5,3,24,3), CGXStyle().SetBorders(gxBorderLeft, CGXPen().SetWidth(2)));
  716.         SetStyleRange(CGXRange(5,2,24,2), CGXStyle().SetBorders(gxBorderLeft, CGXPen().SetWidth(2)));
  717.         SetStyleRange(CGXRange(5,3,24,3), CGXStyle().SetBorders(gxBorderRight, CGXPen().SetWidth(2)));
  718.         SetStyleRange(CGXRange(24,2,24,3), CGXStyle().SetBorders(gxBorderBottom, CGXPen().SetWidth(2)));
  719.  
  720.         // controls
  721.  
  722.         SetStyleRange(CGXRange(6,2), CGXStyle().SetValue(_T("CSimpleButton")));
  723.         SetStyleRange(CGXRange(6,3), CGXStyle()
  724.                 .SetControl(IDS_CTRL_SIMPLE)
  725.                 .SetHorizontalAlignment(DT_CENTER)
  726.                 .SetVerticalAlignment(DT_VCENTER)
  727.                 .SetInterior(GXSYSCOLOR(COLOR_BTNFACE))
  728.                 .SetFont(CGXFont().SetBold(TRUE))
  729.                 .SetValue(_T("Simple"))
  730.             );
  731.  
  732.         SetCoveredCellsRowCol(6, 4, 7, 5);
  733.         SetStyleRange(CGXRange(6,4), _T("<- You can specify the message text with Format->Cells->User"));
  734.  
  735.         SetStyleRange(CGXRange(7,2), CGXStyle().SetValue(_T("CGXEditControl")));
  736.         SetStyleRange(CGXRange(7,3), CGXStyle()
  737.                 .SetControl(GX_IDS_CTRL_EDIT)
  738.                 .SetValue(_T("Editable Text"))
  739.             );
  740.  
  741.         SetStyleRange(CGXRange(8,2), CGXStyle().SetValue(_T("CGXSpinEdit")));
  742.         SetStyleRange(CGXRange(8,3), CGXStyle()
  743.                 .SetControl(GX_IDS_CTRL_SPINEDIT)
  744.                 .SetValue(_T("0"))
  745.             );
  746.  
  747.         SetStyleRange(CGXRange(9,2), CGXStyle().SetValue(_T("CGXHotSpotEdit")));
  748.         SetStyleRange(CGXRange(9,3), CGXStyle()
  749.                 .SetControl(GX_IDS_CTRL_HOTSPOT)
  750.                 .SetValue(_T("Editable Text"))
  751.             );
  752.  
  753.         SetStyleRange(CGXRange(10,2), CGXStyle().SetValue(_T("CGXCheckBox")));
  754.         SetStyleRange(CGXRange(10,3), CGXStyle()
  755.                 .SetControl(GX_IDS_CTRL_CHECKBOX)
  756.                 .SetChoiceList(_T("Click Me!"))
  757.                 .SetVerticalAlignment(DT_VCENTER)
  758.             );
  759.  
  760.         SetStyleRange(CGXRange(11,3), CGXStyle()
  761.                 .SetControl(GX_IDS_CTRL_CHECKBOX3D)
  762.                 .SetChoiceList(_T("Click Me!"))
  763.                 .SetInterior(GXSYSCOLOR(COLOR_BTNFACE))
  764.                 .SetVerticalAlignment(DT_VCENTER)
  765.             );
  766.  
  767.  
  768.         SetStyleRange(CGXRange(12,2), CGXStyle().SetValue(_T("CGXPushbutton")));
  769.         SetStyleRange(CGXRange(12,3), CGXStyle()
  770.                 .SetControl(GX_IDS_CTRL_PUSHBTN)
  771.                 .SetChoiceList(_T("Push Me!"))
  772.             );
  773.  
  774.         SetStyleRange(CGXRange(13,2), CGXStyle().SetValue(_T("CGXStatic")));
  775.         SetStyleRange(CGXRange(13,3), CGXStyle()
  776.                 .SetControl(GX_IDS_CTRL_STATIC)
  777.                 .SetValue(_T("Text"))
  778.             );
  779.  
  780.         SetCoveredCellsRowCol(14,2,15,2);
  781.         SetStyleRange(CGXRange(14,2), CGXStyle().SetValue(_T("CGXRadioButton")));
  782.         SetCoveredCellsRowCol(14,3,15,3);
  783.         SetStyleRange(CGXRange(14,3), CGXStyle()
  784.                 .SetControl(GX_IDS_CTRL_RADIOBTN)
  785.                 .SetChoiceList(_T("one\ntwo\nthree\n"))
  786.             );
  787.         SetCoveredCellsRowCol(16,2,17,2);
  788.         SetCoveredCellsRowCol(16,3,17,3);
  789.         SetStyleRange(CGXRange(16,3), CGXStyle()
  790.                 .SetControl(GX_IDS_CTRL_RADIOBTN3D)
  791.                 .SetChoiceList(_T("one\ntwo\nthree\n"))
  792.                 .SetInterior(GXSYSCOLOR(COLOR_BTNFACE))
  793.             );
  794.  
  795.         SetCoveredCellsRowCol(18,2,19,2);
  796.         SetStyleRange(CGXRange(18,2), CGXStyle().SetValue(_T("CGXListBox")));
  797.         SetCoveredCellsRowCol(18,3,19,3);
  798.         SetStyleRange(CGXRange(18,3), CGXStyle()
  799.                 .SetControl(GX_IDS_CTRL_LISTBOX)
  800.                 .SetChoiceList(_T("one\ntwo\nthree\n"))
  801.             );
  802.  
  803.         SetStyleRange(CGXRange(20,2), CGXStyle().SetValue(_T("CGXComboBox")));
  804.         SetStyleRange(CGXRange(20,3), CGXStyle()
  805.                 .SetControl(GX_IDS_CTRL_COMBOBOX)
  806.                 .SetChoiceList(_T("one\ntwo\nthree\nfour\n"))
  807.                 .SetValue(_T("one"))
  808.             );
  809.  
  810.         SetStyleRange(CGXRange(21,2), CGXStyle().SetValue(_T("CBitmapBtnEdit")));
  811.         SetStyleRange(CGXRange(21,3), CGXStyle()
  812.                 .SetControl(IDS_CTRL_EDITBTN)
  813.                 .SetValue(_T("Editable Text with button"))
  814.             );
  815.  
  816.         SetStyleRange(CGXRange(22,2), CGXStyle().SetValue(_T("CGXWndWrapper")));
  817.         SetStyleRange(CGXRange(22,3), CGXStyle()
  818.                 .SetControl(IDS_CTRL_TABBEAM)
  819.             );
  820.  
  821.         SetStyleRange(CGXRange(23,2), CGXStyle().SetValue(_T("COwnerDrawnComboBox")));
  822.         SetStyleRange(CGXRange(23,3), CGXStyle()
  823.                 .SetControl(IDS_CTRL_OWNERDRAWNDROPDOWN)
  824.             );
  825.  
  826.         // Instructions
  827.  
  828.         SetCoveredCellsRowCol(1, 1, 3, 5);
  829.         SetStyleRange(CGXRange(1,1),
  830.             CGXStyle()
  831.                 .SetWrapText(TRUE)
  832.                 .SetEnabled(FALSE)
  833.                 .SetFont(CGXFont().SetFaceName(_T("Times New Roman")))
  834.                 .SetInterior(RGB(255,251,240))   // Off-white
  835.                 .SetHorizontalAlignment(DT_CENTER)
  836.                 .SetVerticalAlignment(DT_VCENTER)
  837.                 .SetControl(GX_IDS_CTRL_STATIC)
  838.                 .SetBorders(gxBorderAll, CGXPen().SetWidth(2))
  839.                 .SetValue(szInstruct));
  840.  
  841.         // Enable creation of undo-information for user interactions
  842.         GetParam()->EnableUndo(TRUE);
  843.     }
  844.  
  845.     // Position the current cell
  846.  
  847.     SetCurrentCell(4, 1, FALSE /* avoid immediate updating */);
  848.  
  849.     // Enable Update-Hint-Mechanism
  850.  
  851.     EnableHints();
  852. }
  853.  
  854. /////////////////////////////////////////////////////////////////////////////
  855. // CGridSample5View diagnostics
  856.  
  857. #ifdef _DEBUG
  858. void CGridSample5View::AssertValid() const
  859. {
  860.     CMyGridView::AssertValid();
  861. }
  862.  
  863. void CGridSample5View::Dump(CDumpContext& dc) const
  864. {
  865.     CMyGridView::Dump(dc);
  866. }
  867.  
  868. CGridSampleDoc* CGridSample5View::GetDocument() // non-debug version is inline
  869. {
  870.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGridSampleDoc)));
  871.     return (CGridSampleDoc*) m_pDocument;
  872. }
  873.  
  874. #endif //_DEBUG
  875.  
  876.  
  877. /////////////////////////////////////////////////////////////////////////////
  878. // CGridSample5View message handlers
  879.  
  880. // Menu handler for View->Splitter View
  881.  
  882. void CGridSample5View::OnViewSplitterview()
  883. {
  884.     CDocument* pDoc = GetDocument();
  885.  
  886.     CMyMultiDocTemplate* pTemplate
  887.         = (CMyMultiDocTemplate*) ((CGridSampleApp*) AfxGetApp())->m_pSplitterTemplate;
  888.  
  889.     pTemplate->SetViewClass(GetRuntimeClass());
  890.  
  891.     CMDIChildWnd* pNewFrame
  892.         = (CMDIChildWnd*) pTemplate->CreateNewFrame(GetDocument(), NULL);
  893.  
  894.     if (pNewFrame == NULL)
  895.         return;     // not created
  896.  
  897.     ASSERT(pNewFrame->IsKindOf(RUNTIME_CLASS(CSplitterMDIChildWnd)));
  898.  
  899.     CSplitterWnd& splitter = (CSplitterWnd&)
  900.         ((CSplitterMDIChildWnd *) pNewFrame)->m_wndSplitter;
  901.  
  902.     CGridSample5View* pView = (CGridSample5View*)
  903.         splitter.GetPane(0, 0);
  904.  
  905.     // Set view id to active tab view id
  906.     pView->m_nViewID = m_nViewID;
  907.  
  908.     pTemplate->InitialUpdateFrame(pNewFrame, pDoc);
  909.  
  910.     pNewFrame->GetActiveView();
  911.     ASSERT(pView);
  912. }
  913.  
  914. // Menu handler for View->User Actions...
  915.  
  916. void CGridSample5View::OnViewUseractions()
  917. {
  918. /*
  919.     // just some performance checking
  920.     ((CMDIChildWnd*) GetParentFrame())->MDIMaximize();
  921.  
  922.     OnViewZoomin();
  923.     OnViewZoomin();
  924.     OnViewZoomin();
  925.  
  926.     OnViewZoomout();
  927.     OnViewZoomout();
  928.     OnViewZoomout();
  929.     OnViewZoomout();
  930.     OnViewZoomout();
  931.  
  932.     OnViewZoomin();
  933.     OnViewZoomin();
  934.     OnViewZoomin();
  935.     OnViewZoomin();
  936.     OnViewZoomin();
  937.  
  938.     OnViewZoomout();
  939.     OnViewZoomout();
  940.     OnViewZoomout();
  941.  
  942.     ProcessKeys(this, WM_CHAR, 20, 1, 0);
  943. */
  944.  
  945.     // Note: this method is copied from CGridSampleView
  946.     //
  947.     // Shows a dialog with some attributes of the parameter-object
  948.     // where you can experiment with some attributes
  949.     // such as allowing the user to track columns, select cells
  950.     // or use the grid as a listbox.
  951.  
  952.     // Transfer Current Cell's Data to grid
  953.     if (!TransferCurrentCell())
  954.         return;
  955.  
  956.     CUserActionsDialog dlg(GetParam());
  957.  
  958.     if (dlg.DoModal() == IDOK)
  959.     {
  960.         // Redraw the grid
  961.         Redraw();
  962.     }
  963. }
  964.