]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/common/win32/CellView.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / common / win32 / CellView.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it 
9 // under the terms of the GNU General Public License as published by the Free 
10 // Software Foundation; either version 2 of the License, or (at your option) 
11 // any later version.
12 // 
13 // This program is distributed in the hope that it will be useful, but WITHOUT 
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16 // more details.
17 // 
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc., 
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25 //===========================================================================
26 //#####DESCRIPTIONBEGIN####
27 //
28 // Author(s):   sdf
29 // Contact(s):  sdf
30 // Date:                1998/08/11
31 // Version:             0.01
32 // Purpose:     
33 // Description: Implementation of a the cell window view class
34 // Requires:    
35 // Provides:    
36 // See also:#include    
37 // Known bugs:  
38 // Usage:       
39 //
40 //####DESCRIPTIONEND####
41 //
42 //===========================================================================
43
44 #include "stdafx.h"
45 #include "ConfigTool.h"
46 #include "CellView.h"
47 #include "ControlView.h"
48 #include "ConfigItem.h"
49 #include "IntegerEdit.h"
50 #include "DoubleEdit.h"
51 #include "StringEdit.h"
52 #include "ComboEdit.h"
53
54 #include "CTUtils.h"
55 #include "ConfigToolDoc.h"
56
57 #include "resource.h"
58
59 #ifdef PLUGIN
60   #define INCLUDEFILE "ide.guicommon.h" // for ID_EDIT_FINDAGAIN
61   #include "IncludeSTL.h"
62 #endif
63
64 #ifdef _DEBUG
65 #define new DEBUG_NEW
66 #undef THIS_FILE
67 static char THIS_FILE[] = __FILE__;
68 #endif
69
70 /////////////////////////////////////////////////////////////////////////////
71 // CCellView
72
73 IMPLEMENT_DYNCREATE(CCellView, CView)
74
75 CCellView::CCellView():
76   m_bComboSellPending(false)
77 {
78   m_hInCell=NULL;
79   m_pwndCell=NULL;
80   m_GrayPen.CreatePen(PS_SOLID,1,RGB(192,192,192));     
81   CConfigTool::SetCellView(this);
82 }
83
84 CCellView::~CCellView()
85 {
86     deleteZ(m_pwndCell);
87     CConfigTool::SetCellView(0);
88 }
89
90
91 BEGIN_MESSAGE_MAP(CCellView, CView)
92         //{{AFX_MSG_MAP(CCellView)
93         ON_WM_LBUTTONDOWN()
94         ON_WM_SIZE()
95         ON_WM_CREATE()
96         ON_WM_VSCROLL()
97         ON_WM_MOUSEMOVE()
98         ON_WM_MOUSEWHEEL()
99     ON_COMMAND(ID_EDIT_FIND,OnEditFind)
100     ON_COMMAND(ID_EDIT_FINDAGAIN,OnEditFindAgain)
101         ON_UPDATE_COMMAND_UI(ID_EDIT_FINDAGAIN, OnUpdateEditFindAgain)
102         ON_WM_RBUTTONDOWN()
103         ON_UPDATE_COMMAND_UI(ID_EDIT_FIND, OnUpdateEditFind)
104         ON_WM_ERASEBKGND()
105         ON_COMMAND(ID_EDIT_COPY,   OnEditCopy)
106         ON_COMMAND(ID_EDIT_CUT,    OnEditCut)
107         ON_COMMAND(ID_EDIT_PASTE,  OnEditPaste)
108         ON_COMMAND(ID_EDIT_CLEAR,  OnEditDelete)
109         ON_UPDATE_COMMAND_UI(ID_EDIT_COPY,   OnUpdateEditCopy)
110         ON_UPDATE_COMMAND_UI(ID_EDIT_CUT,    OnUpdateEditCut)
111         ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE,  OnUpdateEditPaste)
112         ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR,  OnUpdateEditDelete)
113         ON_WM_HELPINFO()
114     ON_MESSAGE(WM_CANCEL_EDIT,OnCancelEdit)
115
116         //}}AFX_MSG_MAP
117 END_MESSAGE_MAP()
118
119 /////////////////////////////////////////////////////////////////////////////
120 // CCellView drawing
121
122 void CCellView::OnInitialUpdate()
123 {
124         m_nFirstVisibleItem=0;
125         CView::OnInitialUpdate();
126 }
127
128 void CCellView::OnDraw(CDC* pDC)
129 {
130         CTreeCtrl &Tree=CConfigTool::GetControlView()->GetTreeCtrl();
131
132         CConfigToolDoc* pDoc=CConfigTool::GetConfigToolDoc();
133         if(pDoc->ItemCount()>0)
134         {
135                 CRect rect;
136                 Tree.GetItemRect(Tree.GetRootItem(),rect,TRUE);
137                 m_nFirstVisibleItem=rect.top;
138
139                 CRect rcClient;
140                 GetClientRect(rcClient);
141                 CPen *pOldPen=pDC->SelectObject(&m_GrayPen);
142                 CFont *pOldFont=pDC->SelectObject(CConfigTool::GetControlView()->GetFont());
143                 pDC->SetBkMode(TRANSPARENT);
144
145                 CRect rcClip;
146                 pDC->GetClipBox(rcClip);
147                 
148                 CPtrArray arItems;
149                 int dy=CConfigTool::GetControlView()->GetItemHeight();
150                 int cy=0;
151                 for(HTREEITEM h=Tree.GetFirstVisibleItem();h;h=Tree.GetNextVisibleItem(h))
152                 {
153                         if(cy>rcClip.bottom){
154                                 break;
155                         }
156
157                         CRect rcEdit(0,cy,rcClient.right,cy+dy);
158                         cy+=dy;
159
160                         pDC->MoveTo(rcClient.left,rcEdit.top);
161                         pDC->LineTo(rcClient.right,rcEdit.top);
162
163                         CConfigItem &ti=TI(h);
164                         if(h!=m_hInCell){
165         switch(ti.Type()){
166                       case CConfigItem::Enum:
167                                                 // Using combobox
168                                                 rcEdit.left+=2;
169                                                 rcEdit.top+=2;
170             // fall through
171           case CConfigItem::Integer:
172           case CConfigItem::Double:
173           case CConfigItem::String:
174                                                 // Using editbox
175                                                 rcEdit.top+=2;
176                                                 rcEdit.left+=3;
177             {
178                                       CString str(ti.StringValue());
179                                       // cell contents is greyed if the option is not both active and modifiable
180                                       // or if a booldata item is not enabled
181                                       const CdlValuable valuable = ti.GetCdlValuable();
182                                       // check for a package explicitly because is_modifiable() returns true for a package
183                                       pDC->SetTextColor (GetSysColor ((! valuable) || (valuable->is_modifiable () && valuable->is_active () && ((! ti.HasBool ()) || ti.IsEnabled ()) && ! ti.IsPackage ()) ? COLOR_WINDOWTEXT : COLOR_GRAYTEXT));
184                                       pDC->TextOut(rcEdit.left,rcEdit.top,str);
185             }
186             break;
187           default:
188             break;
189         }
190                         }
191                 }
192                 pDC->MoveTo(rcClient.left,cy);
193                 pDC->LineTo(rcClient.right,cy);
194                 pDC->SelectObject(pOldPen);
195                 pDC->SelectObject(pOldFont);
196         }
197 }
198
199 /////////////////////////////////////////////////////////////////////////////
200 // CCellView diagnostics
201
202 #ifdef _DEBUG
203 void CCellView::AssertValid() const
204 {
205         CView::AssertValid();
206 }
207
208 void CCellView::Dump(CDumpContext&      dc) const
209 {
210         CView::Dump(dc);
211 }
212 #endif //_DEBUG
213
214 /////////////////////////////////////////////////////////////////////////////
215 // CCellView message handlers
216
217 void CCellView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
218 {
219         switch(lHint)
220         {
221                 case CConfigToolDoc::IntFormatChanged:
222       {
223                           for(HTREEITEM h=CConfigTool::GetControlView()->GetFirstVisibleItem();h;h=CConfigTool::GetControlView()->GetNextVisibleItem(h)){
224                                   CConfigItem &ti=TI(h);
225           if(ti.Type()==CConfigItem::Integer) {
226                                           CRect rect;
227                                           GetItemRect(h,rect);
228                                           InvalidateRect(rect);
229                                   }
230                           }
231         if(m_pwndCell && TI(m_hInCell).Type()==CConfigItem::Integer) {
232                                   CString strData;
233                                   m_pwndCell->GetWindowText(strData);
234                                   ItemIntegerType n;
235                                   CUtils::StrToItemIntegerType(strData,n);
236           m_pwndCell->SetWindowText(CUtils::IntToStr(n,CConfigTool::GetConfigToolDoc()->m_bHex));
237                           }
238       }
239                         break;
240                 case CConfigToolDoc::Clear:     
241                         deleteZ(m_pwndCell);
242                         Invalidate();
243                         UpdateWindow(); // This prevents cell view half of config pane still being displayed
244       break;
245                 case CConfigToolDoc::ValueChanged:
246                         {
247                                 CConfigItem *pti=(CConfigItem *)pHint;
248                                 CRect rect;
249                                 GetItemRect(pti->HItem(),rect);
250                                 InvalidateRect(rect);
251                         }
252                         break;
253                 case 0:
254                         Invalidate();
255                         break;
256                 default:
257                         break;
258         }       
259         UNUSED_ALWAYS(pSender);
260 }
261
262 void CCellView::GetItemRect(HTREEITEM h,CRect & rect) const
263 {
264         CRect rcClient;
265         GetClientRect(rcClient);
266
267         CConfigTool::GetControlView()->GetItemRect( h, &rect, FALSE );
268         rect.left=rcClient.left;
269         rect.right=rcClient.right;
270 }
271
272 void CCellView::GetInCellRect(HTREEITEM h, CRect & rect, BOOL bDropped) const
273 {
274         CConfigItem &ti=TI(h);
275         GetItemRect(h,rect);
276   switch(ti.Type()){
277                 case CConfigItem::Enum:
278                         // Using combobox
279       if(bDropped) {
280         CStringArray arEnum;
281         ti.EvalEnumStrings(arEnum);
282         rect.bottom += (2+(int)arEnum.GetSize()-1)*rect.Height();
283       }
284       break;
285     case CConfigItem::Integer:  
286     case CConfigItem::Double:
287     case CConfigItem::String:
288                         // Using editbox
289                         //rect.bottom++;
290                         //rect.DeflateRect(2,2); // To allow room  for the border we draw ourselves
291       //rect.InflateRect(2,2);
292       break;
293     default:
294       return;
295   }
296 }
297
298 ItemIntegerType CCellView::GetCellValue() const
299 {
300   // If the item is being edited in-cell, we'll get the data from the control
301   ItemIntegerType rc=0;
302   switch(TI(m_hInCell).Type()){
303                 case CConfigItem::Integer:
304       {
305         CString strData;
306         m_pwndCell->GetWindowText(strData);
307         if(!CUtils::StrToItemIntegerType(strData,rc)){
308           rc=0;
309         }
310       }
311       break;
312     case CConfigItem::Enum:
313     /*
314     case CConfigItem::Boolean:
315     case CConfigItem::Radio:
316     //rc=((CTreeComboBox *)m_pwndCell)->GetCurSel();
317     rc=((CComboEdit *)m_pwndCell)->GetCurSel();
318     break;
319       */
320     case CConfigItem::String:
321     default:
322       int type=TI(m_hInCell).Type();
323       UNUSED_ALWAYS(type);
324       ASSERT(FALSE);
325       break;
326   }
327   return rc;
328 }
329
330 void CCellView::CancelCellEdit(bool bApplyChanges)
331 {
332   if(m_hInCell){
333     CConfigItem &ti=TI(m_hInCell);
334     if(bApplyChanges){
335       CString strValue;
336       m_pwndCell->GetWindowText(strValue);
337       // Ignore empty strings in integer or floating cells - these are legal as intermediate values but not now
338       if(strValue!=ti.StringValue() && (!strValue.IsEmpty() || (ti.Type()!=CConfigItem::Integer && ti.Type()!=CConfigItem::Double))){
339         CConfigTool::GetConfigToolDoc()->SetValue (ti, strValue);
340       }
341     }
342
343     deleteZ(m_pwndCell);
344     m_hInCell=NULL;
345   }
346 }
347
348 BOOL CCellView::InCell(HTREEITEM h)
349 {
350   CancelCellEdit();
351   if(h && TI(h).IsEnabled()){
352     CConfigItem &ti=TI(h);
353     // edit cell only if option is both active and modifiable
354     const CdlValuable valuable = ti.GetCdlValuable();
355     // check packages explicitly because is_modifiable() returns true for a package
356     if ((! valuable) || (valuable->is_modifiable () && valuable->is_active () && ! ti.IsPackage ())){
357       CRect rcEdit;
358       GetItemRect(h,rcEdit);
359       rcEdit.bottom++;
360       switch(ti.Type()){
361         case CConfigItem::Double:
362           {
363             double d;
364             CUtils::StrToDouble(ti.StringValue(),d);
365             m_pwndCell=new CDoubleEdit(d);
366             m_pwndCell->Create(WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL, rcEdit, this, IDC_CELL);
367           }
368           break;
369         case CConfigItem::Integer:
370           {
371             ItemIntegerType i;
372             CUtils::StrToItemIntegerType(ti.StringValue(),i);
373             m_pwndCell=new CIntegerEdit(i);
374           }
375           m_pwndCell->Create(WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL, rcEdit, this, IDC_CELL);
376           break;
377         case CConfigItem::String:
378           {
379             CStringEdit *pStringEdit=new CStringEdit(ti.StringValue());
380             m_pwndCell=pStringEdit;
381             m_pwndCell->Create(WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL, rcEdit, this, IDC_CELL);
382             pStringEdit->EnableDoubleClickEdit(true,IDC_CT_EDIT);
383           }
384
385           break;
386         case CConfigItem::Enum:
387           {
388             CStringArray arEnum;
389             ti.EvalEnumStrings(arEnum);
390             rcEdit.bottom += (2+(int)arEnum.GetSize()-1)*rcEdit.Height();
391             m_pwndCell=new CComboEdit(ti.StringValue(),arEnum);
392             m_pwndCell->Create(WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST, rcEdit, this, IDC_CELL);
393           }
394           break;
395         default:
396           return 0;
397           break;
398       }
399       m_hInCell=h;
400       m_pwndCell->SetFont(CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT)));
401       m_pwndCell->SetFocus();
402       m_pwndCell->GetWindowText(m_strInitialCell);
403     }
404   }
405   return NULL!=m_hInCell;
406 }
407
408 void CCellView::OnLButtonDown(UINT nFlags, CPoint point) 
409 {
410     UNUSED_ALWAYS(nFlags);
411         CTreeCtrl &Tree=CConfigTool::GetControlView()->GetTreeCtrl();
412         CancelCellEdit();
413         HTREEITEM h=HitTest();
414         if(h){
415                 InCell(h);
416                 Tree.SelectItem(h);
417         }
418
419         // Relay to the splitter
420         ClientToScreen(&point);
421         GetParent()->ScreenToClient(&point);
422         GetParent()->SendMessage(WM_LBUTTONDOWN,(WPARAM)nFlags,MAKELPARAM(point.x,point.y));    
423 }
424
425 void CCellView::OnSize(UINT nType, int cx, int cy) 
426 {
427         CView::OnSize(nType, cx, cy);
428         if(m_hInCell){
429 //sdf1          UpdateWindow();
430                 CRect rect;
431     GetItemRect(m_hInCell,rect);
432                 m_pwndCell->MoveWindow(rect,TRUE);
433         }
434         
435 }
436
437 int CCellView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
438 {
439         if (CView::OnCreate(lpCreateStruct) == -1)
440                 return -1;
441         
442         return 0;
443 }
444
445
446
447 BOOL CCellView::PreCreateWindow(CREATESTRUCT& cs) 
448 {
449         // TODO: Add your specialized code here and/or call the base class
450         cs.style &= (~WS_BORDER);
451         return CView::PreCreateWindow(cs);
452 }
453
454 void CCellView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
455 {
456         CView::OnVScroll(nSBCode, nPos, pScrollBar);
457         Sync();
458 }
459
460 void CCellView::Sync()
461 {
462         CTreeCtrl &t=CConfigTool::GetControlView()->GetTreeCtrl();
463         CRect rect;
464         t.GetItemRect(t.GetRootItem(),rect,TRUE);
465         int pos=rect.top;
466
467         if(pos!=m_nFirstVisibleItem){
468                 ScrollWindow(0,pos-m_nFirstVisibleItem);
469     UpdateWindow();
470         }
471 }
472
473
474 void CCellView::OnMouseMove(UINT nFlags, CPoint point) 
475 {
476         // Relay the mouse event to the splitter
477         ClientToScreen(&point);
478         GetParent()->ScreenToClient(&point);
479         GetParent()->SendMessage(WM_MOUSEMOVE,(WPARAM)nFlags,MAKELPARAM(point.x,point.y));      
480 }
481
482
483 BOOL CCellView::OnMouseWheel(UINT, short zDelta, CPoint) 
484 {
485   UINT nScrollCode=((zDelta<0)?SB_LINEDOWN:SB_LINEUP);
486   LPARAM lParam=(LPARAM)GetScrollBarCtrl(SB_VERT)->GetSafeHwnd();
487   if(lParam){
488     for(int i=0;i<abs(zDelta)/WHEEL_DELTA;i++){
489       CConfigTool::GetControlView()->SendMessage(WM_VSCROLL,MAKEWPARAM(nScrollCode,0),lParam);
490       Sync();
491     }
492   }
493   return TRUE;
494 }
495
496 void CCellView::OnEditFind() 
497 {
498     CConfigTool::GetControlView()->OnEditFind();
499 }
500
501 void CCellView::OnEditFindAgain() 
502 {
503     CConfigTool::GetControlView()->OnEditFindAgain();
504 }
505
506 void CCellView::OnUpdateEditFindAgain(CCmdUI* pCmdUI) 
507 {
508     CConfigTool::GetControlView()->OnUpdateEditFindAgain(pCmdUI);
509 }
510
511 void CCellView::OnRButtonDown(UINT nFlags, CPoint point) 
512 {
513     UNUSED_ALWAYS(nFlags);
514     // Make the r-click have an effect equivalent to that when on the control view part
515     CControlView *pv=CConfigTool::GetControlView();
516         HTREEITEM h=HitTest();
517         if(h){
518                 pv->SelectItem(h);
519     }
520         // point is in client coords
521         ClientToScreen(&point);
522         pv->ShowPopupMenu(h,point);
523 }
524
525 void CCellView::OnUpdateEditFind(CCmdUI* pCmdUI) 
526 {
527     CConfigTool::GetControlView()->OnUpdateEditFind(pCmdUI);
528 }
529
530 BOOL CCellView::OnEraseBkgnd(CDC* pDC) 
531 {
532     /*
533     static int x=3;
534     const MSG *pMsg=GetCurrentMessage();
535         WNDCLASS wndcls;
536     if (::GetClassInfo(NULL, _T("AfxFrameOrView42ud"), &wndcls)){
537         TRACE(_T("proc=%08x hbrBackground=%08x "),wndcls.lpfnWndProc,wndcls.hbrBackground);
538     }
539    
540     TRACE(_T("msg=%d hWnd=%08x wParam=%08x lParam=%08x m_pfnSuper=%08x super=%08x\n"),
541         pMsg->message,pMsg->hwnd, pMsg->lParam,pMsg->wParam,m_pfnSuper, GetSuperWndProcAddr());
542     if(x){
543         return CView::OnEraseBkgnd(pDC);
544     }
545     */
546
547     // Work around bug apparently caused by SlickEdit
548         CRect rcClient;
549         pDC->GetClipBox(rcClient);
550         pDC->FillSolidRect(rcClient,GetSysColor(COLOR_WINDOW));
551                 
552         return TRUE;
553 }
554
555 BOOL CCellView::PreTranslateMessage(MSG* pMsg) 
556 {
557         CTreeCtrl &Tree=CConfigTool::GetControlView()->GetTreeCtrl();
558     if(WM_KEYDOWN==pMsg->message){
559                 switch(pMsg->wParam){
560             case VK_TAB:
561                 {
562                         HTREEITEM h=Tree.GetSelectedItem();
563                     if(h){
564                                     if(0==(::GetKeyState(VK_SHIFT)&0x8000)){
565                                             // Shift key not down
566                             h=Tree.GetNextVisibleItem(h);
567                         }
568                         if(h){
569                             CancelCellEdit();
570                                 Tree.SelectItem(h);
571                             Tree.SetFocus();
572                         } else {
573                             MessageBeep (0xFFFFFFFF);
574                         }
575                         // Always handle this message to keep focus within the tree control
576                         return true;
577                     }
578                 }
579                     }
580     }
581         return CView::PreTranslateMessage(pMsg);
582 }
583
584 HTREEITEM CCellView::HitTest()
585 {
586         // Can use the control view's hittest because all it's interested in is the y coord
587
588         TVHITTESTINFO tvi;
589     DWORD dwPos=GetMessagePos();
590         CTreeCtrl &Tree=CConfigTool::GetControlView()->GetTreeCtrl();
591     tvi.pt.y=GET_Y_LPARAM(dwPos);
592     Tree.ScreenToClient(&tvi.pt);
593     tvi.pt.x=0;
594         return Tree.HitTest(&tvi);
595
596 }
597
598 void CCellView::OnEditCopy() 
599 {
600   if(m_pwndCell){
601     m_pwndCell->OnEditCopy();
602   }
603 }
604
605 void CCellView::OnEditCut() 
606 {
607   if(m_pwndCell){
608     m_pwndCell->OnEditCut();
609   }
610 }
611
612 void CCellView::OnEditPaste() 
613 {
614   if(m_pwndCell){
615     m_pwndCell->OnEditPaste();
616   }
617 }
618
619 void CCellView::OnEditDelete() 
620 {
621   if(m_pwndCell){
622     m_pwndCell->OnEditDelete();
623   }
624 }
625
626 void CCellView::OnUpdateEditCopy(CCmdUI* pCmdUI) 
627 {
628   if(m_pwndCell){
629     m_pwndCell->OnUpdateEditCopy(pCmdUI);
630   } else {
631     pCmdUI->Enable(false);
632   }
633 }
634
635 void CCellView::OnUpdateEditCut(CCmdUI* pCmdUI) 
636 {
637   if(m_pwndCell){
638     m_pwndCell->OnUpdateEditCut(pCmdUI);
639   } else {
640     pCmdUI->Enable(false);
641   }
642 }
643
644 void CCellView::OnUpdateEditPaste(CCmdUI* pCmdUI) 
645 {
646   if(m_pwndCell){
647     m_pwndCell->OnUpdateEditPaste(pCmdUI);
648   } else {
649     pCmdUI->Enable(false);
650   }
651 }
652
653 void CCellView::OnUpdateEditDelete(CCmdUI* pCmdUI) 
654 {
655   if(m_pwndCell){
656     m_pwndCell->OnUpdateEditDelete(pCmdUI);
657   } else {
658     pCmdUI->Enable(false);
659   }
660 }
661
662 BOOL CCellView::OnHelpInfo(HELPINFO* pHelpInfo) 
663 {
664         return CConfigTool::GetControlView()->OnHelpInfo(pHelpInfo);
665 }
666
667 LRESULT CCellView::OnCancelEdit(WPARAM wParam, LPARAM)
668 {
669   CancelCellEdit(wParam);
670   return 0;
671 }