colorbtn.cpp
上传用户:dengyong
上传日期:2007-01-01
资源大小:40k
文件大小:18k
源码类别:

组合框控件

开发平台:

Visual C++

  1. // ColorBtn.cpp : implementation file
  2. #include "stdafx.h"
  3. #include "ColorBtn.h"
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static char THIS_FILE[] = __FILE__;
  8. #endif
  9. /////////////////////////////////////////////////////////////////////////////
  10. // CColorBtn
  11. CColorBtn::CColorBtn()
  12. {
  13.     m_CurrentColor = RGB(255,255,255);
  14.     m_ColorDlg.m_Parent = this;   // This will allow the dialog to position itself
  15.     // Create the pens and brushes that we'll need to draw the button
  16.     m_NullPen.CreateStockObject(NULL_PEN);
  17.     m_BlackPen.CreateStockObject(BLACK_PEN);
  18.     m_WhitePen.CreateStockObject(WHITE_PEN);
  19.     m_NullBrush.CreateStockObject(NULL_BRUSH);
  20.     m_BackBrush.CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  21.     m_DkGrayPen.CreatePen(PS_SOLID,1,RGB(128,128,128)); 
  22.     m_ColorWellShape = RECTANGLE;
  23. }
  24. CColorBtn::~CColorBtn()
  25. {
  26. }
  27. BEGIN_MESSAGE_MAP(CColorBtn, CButton)
  28. //{{AFX_MSG_MAP(CColorBtn)
  29. ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
  30. ON_WM_CREATE()
  31. //}}AFX_MSG_MAP
  32. END_MESSAGE_MAP()
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CColorBtn message handlers
  35. void CColorBtn::DrawItem(LPDRAWITEMSTRUCT lpd)
  36. {
  37.     // Draw the button
  38.     CBrush colorbrush;
  39.     CDC DC;
  40.     DC.Attach(lpd->hDC);
  41.     int top,left,bottom,right;
  42.     // Store this for convenience
  43.     top    = lpd->rcItem.top;
  44.     left   = lpd->rcItem.left;
  45.     bottom = lpd->rcItem.bottom;
  46.     right  = lpd->rcItem.right;
  47.                 
  48.     colorbrush.CreateSolidBrush(m_CurrentColor);
  49.     
  50.     m_OldPen   = DC.SelectObject(&m_NullPen);
  51.     m_OldBrush = DC.SelectObject(&m_BackBrush);
  52.     // Clear the background using the 3DFACE color.
  53.     DC.Rectangle(&lpd->rcItem);
  54.     // Draw the border
  55.     if (!(lpd->itemState & ODS_SELECTED))
  56.     {
  57.         // Button is up
  58.         DC.SelectObject(&m_BlackPen);
  59.         DC.MoveTo(left,bottom-1);
  60.         DC.LineTo(right-1,bottom-1);
  61.         DC.LineTo(right-1,top);
  62.         DC.SelectObject(&m_DkGrayPen);
  63.         DC.MoveTo(left+1,bottom-2);
  64.         DC.LineTo(right-2,bottom-2);
  65.         DC.LineTo(right-2,top+1);
  66.         DC.SelectObject(&m_WhitePen);
  67.         DC.LineTo(left+1,top+1);
  68.         DC.LineTo(left+1,bottom-2);    
  69.     }
  70.     else
  71.     {
  72.         // Button is down
  73.         DC.SelectObject(&m_DkGrayPen);            
  74.         DC.MoveTo(left,bottom-1);
  75.         DC.LineTo(left,top);
  76.         DC.LineTo(right-1,top);
  77.         DC.SelectObject(&m_WhitePen);
  78.         DC.MoveTo(right-1,top-1);
  79.         DC.LineTo(right-1,bottom-1);
  80.         DC.LineTo(left+1,bottom-1);
  81.         DC.SelectObject(&m_BlackPen);
  82.         DC.MoveTo(left+1,bottom-2);
  83.         DC.LineTo(left+1,top+1);
  84.         DC.LineTo(right-2,top+1);
  85.         // by moving this, we get the things inside the button
  86.         // to draw themselves one pixel down and one to the right.
  87.         // This completes the "pushed" effect
  88.         left++;
  89.         right++;
  90.         bottom++;
  91.         top++;
  92.     }
  93.     // The division
  94.     DC.SelectObject(&m_WhitePen); 
  95.     DC.MoveTo(right-10,top+4);
  96.     DC.LineTo(right-10,bottom-4);
  97.     DC.SelectObject(m_DkGrayPen);
  98.     DC.MoveTo(right-11,top+4);
  99.     DC.LineTo(right-11,bottom-4);
  100.     // The triangle
  101.     if (lpd->itemState & ODS_DISABLED)
  102.         DC.SelectObject(m_DkGrayPen);
  103.     else
  104.         DC.SelectObject(m_BlackPen);
  105.     
  106.     DC.MoveTo(right-4,(bottom/2)-1);
  107.     DC.LineTo(right-9,(bottom/2)-1);
  108.     DC.MoveTo(right-5,(bottom/2));
  109.     DC.LineTo(right-8,(bottom/2));
  110.     if (lpd->itemState & ODS_DISABLED)    
  111.     {
  112.         DC.SetPixel(right-4,(bottom/2)-1,RGB(255,255,255));
  113.         DC.SetPixel(right-5,(bottom/2),RGB(255,255,255));
  114.         DC.SetPixel(right-6,(bottom/2)+1,RGB(255,255,255));
  115.     }
  116.     else
  117.     {
  118.         DC.SetPixel(right-6,(bottom/2)+1,RGB(0,0,0));
  119.     }
  120.     if (!(lpd->itemState & ODS_DISABLED))
  121.     {
  122.         // The color rectangle, only if enabled
  123.         DC.SelectObject(&colorbrush);
  124.         DC.Rectangle(left+5,top+4,right-15,bottom-4);    
  125.     }
  126.     if (lpd->itemState & ODS_FOCUS)
  127.     {
  128.         // Draw the focus
  129.         // It would have been nice just to
  130.         // draw a rectangle using a pen created
  131.         // with the PS_ALTERNATE style, but
  132.         // this is not supported by WIN95
  133.         int i;
  134.         for (i=left+3;i<right-4;i+=2)
  135.         {
  136.             DC.SetPixel(i,top+3,RGB(0,0,0));
  137.             DC.SetPixel(i,bottom-4,RGB(0,0,0));
  138.         }
  139.         for (i=top+3;i<bottom-4;i+=2)
  140.         {
  141.             DC.SetPixel(left+3,i,RGB(0,0,0));
  142.             DC.SetPixel(right-4,i,RGB(0,0,0));
  143.         }       
  144.     }
  145.     DC.SelectObject(m_OldPen);
  146.     DC.SelectObject(m_OldBrush);
  147.     DC.Detach();    
  148. }
  149. void CColorBtn::OnClicked() 
  150. {
  151.     // When the button is clicked, show the dialog.
  152. if (m_ColorDlg.DoModal() == IDOK)
  153.     {
  154.         m_CurrentColor = m_ColorDlg.m_SelectedColor;
  155.         InvalidateRect(NULL);
  156.     }
  157. }
  158. void CColorBtn::Serialize( CArchive& ar )
  159. {
  160. }
  161. void CColorBtn::SetSelectedColor(COLORREF Color)
  162. {
  163.    m_CurrentColor = Color;
  164.    InvalidateRect(NULL);
  165. }
  166. COLORREF CColorBtn::GetColor()
  167. {
  168.    return m_CurrentColor;
  169. }
  170. void CColorBtn::ClearColorWells()
  171. {
  172.    if(m_ColorDlg.m_Colors.GetSize() > 0)
  173.       m_ColorDlg.m_Colors.RemoveAll();
  174. }
  175. void CColorBtn::AddColorWell(COLORREF Color)
  176. {
  177.    m_ColorDlg.m_Colors.Add(Color);
  178. }
  179. void CColorBtn::SetColorsFromArray(CArray<COLORREF, COLORREF&>* ColorArray)
  180. {
  181.    short array_size = ColorArray->GetSize();
  182.    COLORREF local_color;
  183.    m_ColorDlg.m_Colors.SetSize(array_size);
  184.    for(short loop = 0; loop < array_size; loop++)
  185.       {
  186.       local_color = ColorArray->GetAt(loop);
  187.       m_ColorDlg.m_Colors.SetAt(loop, local_color);
  188.       }
  189. }
  190. void CColorBtn::SetBorderThickness(short Outer, short Inner)
  191. {
  192.    m_ColorDlg.m_OuterBorderThickness = Outer;
  193.    m_ColorDlg.m_InnerBorderThickness = Inner;
  194. }
  195. void CColorBtn::SetDialogWidth(short Width)
  196. {
  197.    m_ColorDlg.m_DialogWidth = Width;
  198. }
  199. void CColorBtn::SetNumColorWellColumns(short NumCols)
  200. {
  201.    m_ColorDlg.m_NumColorWellColumns = NumCols;
  202. }
  203. void CColorBtn::SetColorWellHeight(short Height)
  204. {
  205.    m_ColorDlg.m_ColorWellHeight = Height;
  206. }
  207. void CColorBtn::MakeColorWellsIsotropic(BOOL Yes)
  208. {
  209.    if(Yes)
  210.       m_ColorDlg.m_IsotropicWells = TRUE;
  211.    else
  212.       m_ColorDlg.m_IsotropicWells = FALSE;
  213. }
  214. void CColorBtn::SetColorWellShape(short Shape)
  215. {
  216.    switch(Shape)
  217.       {
  218.       case RECTANGLE:
  219.       case ELLIPSE:
  220.          m_ColorWellShape = Shape;
  221.          break;
  222.       default:
  223.          m_ColorWellShape = RECTANGLE;
  224.          break;
  225.       }
  226. }
  227.    
  228. short CColorBtn::GetColorWellShape()
  229. {
  230.    return m_ColorWellShape;
  231. }
  232. /////////////////////////////////////////////////////////////////////////////
  233. // CColorBtnDlg dialog
  234. CColorBtnDlg::CColorBtnDlg(CWnd* pParent /*=NULL*/)
  235. {
  236. //{{AFX_DATA_INIT(CColorBtnDlg)
  237. // NOTE: the ClassWizard will add member initialization here
  238. //}}AFX_DATA_INIT
  239.    m_SelectedColor = RGB(255,255,255);
  240.    m_DialogWidth = 41;
  241.    m_NumColorWellColumns = 4;
  242.    m_ColorWellHeight = 9;
  243.    m_OuterBorderThickness = 1;
  244.    m_InnerBorderThickness = 1;
  245.    m_StartingButtonID = 5000;
  246.    m_IsotropicWells = TRUE;
  247.    CreateDialogFromTemplate();
  248.    
  249. }
  250. CColorBtnDlg::~CColorBtnDlg()
  251. {
  252.    GlobalUnlock(m_GlobalLock);
  253. GlobalFree(m_GlobalLock);
  254.    
  255. }
  256. void CColorBtnDlg::DoDataExchange(CDataExchange* pDX)
  257. {
  258. CDialog::DoDataExchange(pDX);
  259. //{{AFX_DATA_MAP(CColorBtnDlg)
  260. // NOTE: the ClassWizard will add DDX and DDV calls here
  261. //}}AFX_DATA_MAP
  262. }
  263. BEGIN_MESSAGE_MAP(CColorBtnDlg, CDialog)
  264. //{{AFX_MSG_MAP(CColorBtnDlg)
  265. ON_WM_LBUTTONDOWN()
  266. ON_WM_LBUTTONUP()
  267.     ON_WM_DRAWITEM()
  268. //}}AFX_MSG_MAP
  269.    // ON_COMMAND_RANGE(IDC_COLOR_WELL1,IDC_COLOR_WELL16,OnColor)
  270. END_MESSAGE_MAP()
  271. /////////////////////////////////////////////////////////////////////////////
  272. // CColorBtnDlg message handlers
  273. BOOL CColorBtnDlg::OnInitDialog() 
  274. {
  275.    CDialog::OnInitDialog();
  276.    CRect dialog_rect, color_well_rect, parent_button_rect;
  277.    short dialog_height, color_well_width;
  278.    short num_buttons, num_rows;
  279.    int tempx, tempy;
  280.    // If no colors have been added, close
  281.    if(m_Colors.GetSize() == 0)
  282.       EndDialog(IDCANCEL);
  283.    
  284.    // Set the dialog size and add the controls
  285.    // The width cannot be less than the number of columns * MIN_WIDTH
  286.    // plus the inside and outside borders
  287.    
  288.    // Validate Border sizes
  289.    if(m_OuterBorderThickness < MIN_OUTER_BORDER)
  290.       m_OuterBorderThickness = MIN_OUTER_BORDER;
  291.    if(m_OuterBorderThickness > MAX_OUTER_BORDER)
  292.       m_OuterBorderThickness = MAX_OUTER_BORDER;
  293.    if(m_InnerBorderThickness < MIN_INNER_BORDER)
  294.       m_InnerBorderThickness = MIN_INNER_BORDER;
  295.    if(m_InnerBorderThickness > MAX_INNER_BORDER)
  296.       m_InnerBorderThickness = MAX_INNER_BORDER;
  297.    if(m_NumColorWellColumns < MIN_NUMCOLORWELLCOLS)
  298.       m_NumColorWellColumns = MIN_NUMCOLORWELLCOLS;
  299.    if(m_NumColorWellColumns > MAX_NUMCOLORWELLCOLS)
  300.       m_NumColorWellColumns = MAX_NUMCOLORWELLCOLS;
  301.    
  302.    // allow for the dialog border
  303.    tempx = GetSystemMetrics(SM_CXDLGFRAME);
  304.    // Calculate color width to ensure min sizes are met
  305.    color_well_width = (m_DialogWidth -
  306.                        (2*tempx) -
  307.                        (2*m_OuterBorderThickness) -
  308.                        ((m_NumColorWellColumns-1) * m_InnerBorderThickness)) /
  309.                        m_NumColorWellColumns;
  310.    
  311.    if(color_well_width < MIN_WELL_WIDTH)
  312.       {
  313.       color_well_width = MIN_WELL_WIDTH;
  314.       }
  315.    
  316.    // Calculate width from whole number color well width to avoid calculation losses
  317.    m_DialogWidth = ((2*m_OuterBorderThickness) +
  318.                         (2*tempx) +
  319.                         (m_NumColorWellColumns * color_well_width) +
  320.                         ((m_NumColorWellColumns-1)* m_InnerBorderThickness));
  321.    
  322.    // calculate # rows, checking for partial rows
  323.    num_buttons = m_Colors.GetSize();
  324.    num_rows = num_buttons/m_NumColorWellColumns;
  325.    if( (num_rows * m_NumColorWellColumns) < num_buttons)
  326.       {
  327.       num_rows++;
  328.       }
  329.    // allow for the dialog border
  330.    tempy = GetSystemMetrics(SM_CYDLGFRAME);
  331.    if(m_ColorWellHeight < MIN_WELL_HEIGHT)
  332.       m_ColorWellHeight = MIN_WELL_HEIGHT;
  333.    // ignore custom well height if isotropic wells are selected
  334.    if(m_IsotropicWells)
  335.       m_ColorWellHeight = color_well_width;
  336.    dialog_height = (2*m_OuterBorderThickness) +
  337.                      (2*tempy) +
  338.                      (m_ColorWellHeight*num_rows) +
  339.                      (m_InnerBorderThickness *(num_rows-1));
  340.    
  341.     
  342.  m_Parent->GetWindowRect(&parent_button_rect);
  343.     
  344.     // Move the dialog to be below the button
  345.     // Note: we are sizing the rectangle
  346.     SetWindowPos(NULL,
  347.                parent_button_rect.left,
  348.                parent_button_rect.bottom,
  349.                m_DialogWidth,
  350.                dialog_height,
  351.                SWP_NOZORDER | SWP_DRAWFRAME);
  352.     GetWindowRect(&dialog_rect);
  353.     // Check to see if the dialog has a portion outside the
  354.     // screen, if so, adjust.
  355.     
  356.     if (dialog_rect.bottom > GetSystemMetrics(SM_CYSCREEN))
  357.     {   
  358.         dialog_rect.top = parent_button_rect.top-(dialog_rect.bottom-dialog_rect.top);        
  359.     }
  360.     if (dialog_rect.right > GetSystemMetrics(SM_CXSCREEN))
  361.     {
  362.         dialog_rect.left = GetSystemMetrics(SM_CXSCREEN) - 
  363.            (dialog_rect.right-dialog_rect.left);
  364.     }
  365.     SetWindowPos(NULL,dialog_rect.left,dialog_rect.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
  366.     // Add the button controls to the dialog
  367.     CButton *temp_button;
  368.     short column = 1, row = 1;
  369.     short upperleft_x, upperleft_y;
  370.     
  371.     for(short loop = 0; loop < num_buttons; loop++)
  372.        {
  373.        if(column > m_NumColorWellColumns)
  374.           {
  375.           row++;
  376.           column = 1;
  377.           }
  378.        upperleft_x = m_OuterBorderThickness +
  379.                   (column-1)*(color_well_width + m_InnerBorderThickness);
  380.        upperleft_y = m_OuterBorderThickness +
  381.                   (row-1)*(m_ColorWellHeight + m_InnerBorderThickness);
  382.        color_well_rect.SetRect(upperleft_x, 
  383.                      upperleft_y, 
  384.                      upperleft_x + color_well_width, 
  385.                      upperleft_y + m_ColorWellHeight);
  386.        temp_button = new CButton;
  387.        temp_button->Create( "", BS_OWNERDRAW | BS_PUSHBUTTON| WS_TABSTOP | WS_CHILD | 
  388.           WS_VISIBLE | WS_EX_CLIENTEDGE, 
  389.           color_well_rect, this, m_StartingButtonID + loop );
  390.        
  391.        column++;
  392.        }
  393.    
  394.     // Capture the mouse, this allows the dialog to close when
  395.     // the user clicks outside.
  396.     // Remember that the dialog has no "close" button.
  397.     SetCapture();
  398. return TRUE; 
  399. }
  400. void CColorBtnDlg::EndDialog( int nResult ) {
  401.     ReleaseCapture();
  402.     CDialog::EndDialog(nResult);
  403.    
  404.    // delete child buttons
  405.    CWnd *child = (CWnd*) GetTopWindow();
  406.    while(child != NULL)
  407.       {
  408.       delete child;
  409.       child = (CWnd*) GetTopWindow();
  410.       }
  411. }
  412. void CColorBtnDlg::OnLButtonDown(UINT nFlags, CPoint point) 
  413. {
  414.     RECT r;
  415.     POINT p;
  416.     p.x = point.x;
  417.     p.y = point.y;
  418.     ClientToScreen(&p);
  419.     GetWindowRect(&r);
  420.     // The user clicked...
  421.     if (!PtInRect(&r,p))
  422.     {
  423.         //  ...outside the dialog, close.
  424.         EndDialog(IDCANCEL);
  425.     }
  426.     else
  427.     {
  428.         //  ...inside the dialog. Since this window
  429.         //     has the mouse captured, its children
  430.         //     get no messages. So, check to see
  431.         //     if the click was in one of its children
  432.         //     and tell him.
  433.         //     If the user clicks inside the dialog
  434.         //     but not on any of the controls,
  435.         //     ChildWindowFromPoint returns a
  436.         //     pointer to the dialog. In this
  437.         //     case we do not resend the message
  438.         //     (obviously) because it would cause
  439.         //     a stack overflow.
  440.         
  441.         CWnd *child = ChildWindowFromPoint(point);
  442.          
  443.         if (child && child != this)
  444.            {
  445.            OnColor(child->GetDlgCtrlID()); 
  446.            }
  447.     }
  448. CDialog::OnLButtonDown(nFlags, point);
  449. }
  450. void CColorBtnDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpd) 
  451. {
  452. CDC dc;
  453.    CPen m_NullPen;
  454.    CBrush brush;
  455.    CPen *oldpen;
  456.    CBrush *oldbrush;
  457.    short shape;
  458.    // Draw the wells using the current color table
  459.    m_NullPen.CreateStockObject(NULL_PEN);
  460.    brush.CreateSolidBrush(m_Colors.GetAt(nIDCtl-m_StartingButtonID));
  461.    dc.Attach(lpd->hDC);
  462.    oldpen = dc.SelectObject(&m_NullPen);
  463.    oldbrush = dc.SelectObject(&brush);
  464.    
  465.    // Draw the correct shape
  466.    shape = ((CColorBtn*)m_Parent)->GetColorWellShape();
  467.    switch(shape)
  468.       {
  469.       case CColorBtn::RECTANGLE:
  470.          lpd->rcItem.right++;
  471.          lpd->rcItem.bottom++;
  472.          dc.Rectangle(&lpd->rcItem);
  473.          break;
  474.       case CColorBtn::ELLIPSE:
  475.          lpd->rcItem.right++;
  476.          lpd->rcItem.bottom++;
  477.          dc.Ellipse(&lpd->rcItem);
  478.          break;
  479.       default:
  480.          ASSERT(FALSE);
  481.          break;
  482.       }
  483.    dc.SelectObject(oldpen);
  484.    dc.SelectObject(oldbrush);
  485.    dc.Detach();
  486. }
  487. void CColorBtnDlg::OnColor(UINT id) {
  488.     m_SelectedColor = m_Colors.GetAt(id-m_StartingButtonID);
  489.     EndDialog(IDOK); }
  490. void CColorBtnDlg::OnLButtonUp(UINT nFlags, CPoint point) 
  491. {
  492.     // See notes for OnLButtonDown.   
  493.     CWnd *child = ChildWindowFromPoint(point,CWP_ALL);
  494.     
  495.     if (child && child != this)
  496.        {
  497.        OnColor(child->GetDlgCtrlID());
  498.        }
  499. CDialog::OnLButtonUp(nFlags, point);
  500. }
  501. void CColorBtnDlg::CreateDialogFromTemplate()
  502. {
  503.    // Dialog Template info
  504.    // now initialize the DLGTEMPLATE structure
  505. m_dlgTempl.cx = 40;  // 4 horizontal units are the width of one character
  506. m_dlgTempl.cy = 80;  // 8 vertical units are the height of one character
  507. m_dlgTempl.style = DS_MODALFRAME | WS_POPUP;
  508. m_dlgTempl.dwExtendedStyle = 0;
  509. m_dlgTempl.x = 0;
  510. m_dlgTempl.y = 0;
  511. m_dlgTempl.cdit = 0;  // start with 0 dialog items in the dialog
  512. // The first step is to allocate memory to define the dialog.  The information to be 
  513. // stored in the allocated buffer is the following:
  514. // 
  515. // 1.  DLGTEMPLATE structure
  516. // 2.    0x0000 (Word) indicating the dialog has no menu
  517. // 3.    0x0000 (Word) Let windows assign default class to the dialog
  518. // 4.    (Caption)  Null terminated unicode string
  519. // will first convert the control captions to UNICODE
  520. int total_length = 0;  
  521. try  
  522. {
  523. int buffer_size =  sizeof(DLGTEMPLATE) + (3 * sizeof(WORD))/*menu and class and no caption*/;
  524. buffer_size = (buffer_size + 3) & ~3;  // adjust size to make first control DWORD aligned
  525. m_GlobalLock = GlobalAlloc(LHND, buffer_size);
  526. if (m_GlobalLock == NULL)
  527. AfxThrowMemoryException();
  528. BYTE* buffer_ptr = (BYTE*)GlobalLock(m_GlobalLock);
  529. if (buffer_ptr == NULL)
  530. {
  531. GlobalFree(m_GlobalLock);
  532. AfxThrowMemoryException();
  533. }
  534. BYTE* destination_ptr = buffer_ptr;
  535. // transfer DLGTEMPLATE structure to the buffer
  536. memcpy(destination_ptr, &m_dlgTempl, sizeof(DLGTEMPLATE));
  537. destination_ptr += sizeof(DLGTEMPLATE);
  538. *(WORD*)destination_ptr = 0; // no menu
  539. *(WORD*)(destination_ptr + 1) = 0;  // use default window class
  540.       *(WORD*)(destination_ptr + 2) = 0;  // no caption
  541. destination_ptr += 3 * sizeof(WORD);
  542. ASSERT(destination_ptr - buffer_ptr == buffer_size); // just make sure we did not overrun the heap
  543. InitModalIndirect((DLGTEMPLATE*)buffer_ptr);
  544. }
  545. catch(CException *e)
  546. {
  547.    AfxMessageBox("System Out of Memory.", MB_ICONEXCLAMATION | MB_OK);
  548.       delete e;
  549.       throw;
  550. }
  551. }