errorbox.cpp

Go to the documentation of this file.
00001 // $Id: errorbox.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // implementation of CInformErrorDialog, used for error reporting
00100 // (taken from errors.cpp 1.27)
00101 
00102 
00103 #include "camtypes.h"
00104 
00105 #include "errorbox.h"
00106 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "andy.h"
00108 //#include "tim.h"
00109 //#include "resource.h"
00110 #include "splash.h"
00111 #include "mainfrm.h"
00112 //#include "richard2.h"
00113 #include "prdlgctl.h"
00114 
00115 #include "helpuser.h"
00116 
00117 
00118 CInformErrorDialog::CInformErrorDialog(CWnd* pParent /*=NULL*/)
00119     : CDialog(CInformErrorDialog::IDD, pParent ? pParent : GetSafeParent() )
00120 {
00121     //{{AFX_DATA_INIT(CInformErrorDialog)
00122         // NOTE: the ClassWizard will add member initialization here
00123     //}}AFX_DATA_INIT
00124 
00125     // remember the HWND to use in case of emergency
00126     ParentHwnd = GetSafeParent()->GetSafeHwnd();
00127   
00128     // Make sure all the string variables are NULL.
00129     m_StaticTextStr = 0;
00130     m_TitleStr      = 0;                    // by default NOT a custom title
00131     m_ErrorBoxType  = ERRORTYPE_ERROR;      // This is an error box by default
00132     m_OwnerModule   = 0L;
00133     m_OK            = 1;
00134     m_Cancel        = 2;
00135     m_Help          = 0;                    // by default there is no help button
00136 
00137     // Set reasonable defaults for the button captions.
00138     m_ButtonStr[0]  = _R(IDS_OK);
00139     for (INT32 i = 1; i < ERRORDLG_MAXBUTTONS; i++) m_ButtonStr[i] = 0;
00140 }
00141 
00142 
00143 
00144 void CInformErrorDialog::DoDataExchange(CDataExchange* pDX)
00145 {
00146     // IF YOU CHANGE THE VALUE OF ERRORDLG_MAXBUTTONS YOU MUST CHANGE THIS AS WELL!
00147     CDialog::DoDataExchange(pDX);
00148     //{{AFX_DATA_MAP(CInformErrorDialog)
00149     DDX_Control(pDX, _R(ID_ERRORBOX_BUTTON5), m_Button[4]);
00150     DDX_Control(pDX, _R(ID_ERRORBOX_BUTTON4), m_Button[3]);
00151     DDX_Control(pDX, _R(ID_ERRORBOX_BUTTON3), m_Button[2]);
00152     DDX_Control(pDX, _R(ID_ERRORBOX_BUTTON2), m_Button[1]);
00153     DDX_Control(pDX, _R(ID_ERRORBOX_BUTTON1), m_Button[0]);
00154     //}}AFX_DATA_MAP
00155 }
00156 
00157 
00158 // IF YOU CHANGE THE VALUE OF ERRORDLG_MAXBUTTONS YOU MUST CHANGE THIS AS WELL!
00159 BEGIN_MESSAGE_MAP(CInformErrorDialog, CDialog)
00160     //{{AFX_MSG_MAP(CInformErrorDialog)
00161     ON_WM_PAINT()
00162     ON_BN_CLICKED(_R(ID_ERRORBOX_BUTTON1), OnClickedButton1)
00163     ON_BN_CLICKED(_R(ID_ERRORBOX_BUTTON2), OnClickedButton2)
00164     ON_BN_CLICKED(_R(ID_ERRORBOX_BUTTON3), OnClickedButton3)
00165     ON_BN_CLICKED(_R(ID_ERRORBOX_BUTTON4), OnClickedButton4)
00166     ON_BN_CLICKED(_R(ID_ERRORBOX_BUTTON5), OnClickedButton5)
00167     ON_COMMAND(IDCANCEL, OnCancelCmd)
00168     //}}AFX_MSG_MAP
00169 END_MESSAGE_MAP()
00170 
00171 
00172 // Static variables used to hold info about the error box template.
00173 SIZE        CInformErrorDialog::DefButtonSize;
00174 INT32           CInformErrorDialog::ButtonSpacing;
00175 SIZE        CInformErrorDialog::DialogSize;
00176 INT32           CInformErrorDialog::EdgeSpacing;
00177 INT32           CInformErrorDialog::DefTopOfButton;
00178 POINT       CInformErrorDialog::DefIconPos;
00179 SIZE        CInformErrorDialog::DefMsgSize;
00180 BOOL        CInformErrorDialog::ValidInfo = FALSE;
00181 String_64   CInformErrorDialog::ButtonText[ERRORDLG_MAXBUTTONS];
00182 
00183 
00184 // The ID's of the error box buttons.
00185 // IF YOU CHANGE THE VALUE OF ERRORDLG_MAXBUTTONS YOU MUST CHANGE THIS AS WELL!
00186 UINT32 CInformErrorDialog::ButtonID[ERRORDLG_MAXBUTTONS] =
00187 {
00188     _R(ID_ERRORBOX_BUTTON1),
00189     _R(ID_ERRORBOX_BUTTON2),
00190     _R(ID_ERRORBOX_BUTTON3),
00191     _R(ID_ERRORBOX_BUTTON4),
00192     _R(ID_ERRORBOX_BUTTON5)
00193 };
00194 
00195 
00196 
00197 /********************************************************************************************
00198 
00199 >   void CInformErrorDialog::GetDialogInfo()
00200 
00201     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00202     Created:    19/05/94
00203     Purpose:    Finds out various properties of the error box dialog.  This is done once
00204                 only - the first time an error box is displayed.
00205                 These properties are used when moving/resizing buttons, the icon, and
00206                 the static control used to display the message.
00207     SeeAlso:    CInformErrorDialog::SetupButtons; CInformErrorDialog::SetupMessage
00208 
00209 ********************************************************************************************/
00210 
00211 void CInformErrorDialog::GetDialogInfo()
00212 {
00213     // Skip this if we've already done it.
00214     if (ValidInfo)
00215         return;
00216 
00217     // Find out how bug the dialog is by default.
00218     CRect DlgRect;
00219     GetClientRect(&DlgRect);
00220     DialogSize.cx = DlgRect.Width();
00221     DialogSize.cy = DlgRect.Height();
00222 
00223     // Find out the button spacing/sizes etc.
00224     CWnd *pCtrl1 = GetDlgItem(ButtonID[0]);
00225     CWnd *pCtrl2 = GetDlgItem(ButtonID[1]);
00226     ENSURE((pCtrl1 != NULL) && (pCtrl2 != NULL), 
00227            "Can't find control in CInformErrorDialog::OnInitDialog()");
00228 
00229     // Safety check.
00230     if ((pCtrl1 == NULL) || (pCtrl2 == NULL))
00231         return;
00232 
00233     // Get width of buttons, and the spacing between the buttons and the edge of the dialog.
00234     WINDOWPLACEMENT Placement;
00235     Placement.length = sizeof(WINDOWPLACEMENT);
00236     pCtrl1->GetWindowPlacement(&Placement);
00237 
00238     DefTopOfButton = Placement.rcNormalPosition.top;
00239     DefButtonSize.cx = Placement.rcNormalPosition.right - Placement.rcNormalPosition.left;
00240     DefButtonSize.cy = Placement.rcNormalPosition.bottom - Placement.rcNormalPosition.top;
00241     EdgeSpacing = Placement.rcNormalPosition.left;
00242 
00243     // Get space between adjacent buttons.
00244     Placement.length = sizeof(WINDOWPLACEMENT);
00245     pCtrl2->GetWindowPlacement(&Placement);
00246 
00247     ButtonSpacing = Placement.rcNormalPosition.left - (EdgeSpacing + DefButtonSize.cx);
00248 
00249     // Find the position of the icon.
00250     CWnd *pIconCtrl = GetDlgItem(_R(IDC_ERRORBOX_ICON));
00251     ENSURE(pIconCtrl != NULL, "Can't find Icon control in CInformErrorDialog::GetDialogInfo()");
00252 
00253     // Safety check.
00254     if (pIconCtrl == NULL)
00255         return;
00256 
00257     Placement.length = sizeof(WINDOWPLACEMENT);
00258     pIconCtrl->GetWindowPlacement(&Placement);
00259     
00260     DefIconPos.x = Placement.rcNormalPosition.left;
00261     DefIconPos.y = Placement.rcNormalPosition.top;
00262 
00263     // Find the position of the message text area.
00264     CWnd *pMsgCtrl = GetDlgItem(_R(IDC_ERRORBOX_TEXT));
00265     ENSURE(pMsgCtrl != NULL, "Can't find Text control in CInformErrorDialog::GetDialogInfo()");
00266 
00267     // Safety check.
00268     if (pMsgCtrl == NULL)
00269         return;
00270 
00271     Placement.length = sizeof(WINDOWPLACEMENT);
00272     pMsgCtrl->GetWindowPlacement(&Placement);
00273 
00274     DefMsgSize.cx = Placement.rcNormalPosition.right - Placement.rcNormalPosition.left;
00275     DefMsgSize.cy = Placement.rcNormalPosition.bottom - Placement.rcNormalPosition.top;
00276 
00277     // The static variables now contain valid information.
00278     ValidInfo = TRUE;
00279 }
00280 
00281 
00282 
00283 /********************************************************************************************
00284 
00285 >   BOOL CInformErrorDialog::SetupButtons(HDC hDC, INT32 NumButtons)
00286 
00287     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00288     Created:    19/05/94
00289     Inputs:     hDC - device context for the dialog (used to access the font).
00290                 NumButtons - how many buttons the caller has asked for.
00291     Returns:    TRUE if the buttons were set up ok;
00292                 FALSE if not, and hence caller should fall back on MessageBox().
00293     Purpose:    Initialises the buttons in the dialog ready to be displayed.
00294                 This includes setting the text, resizing the buttons if the text is too
00295                 big to fit, moveing the buttons so they are always centred no matter how
00296                 big they are or how many there are.
00297                 If the buttons get very wide, then the dialog is made wider to accomadate
00298                 them.
00299     SeeAlso:    CInformErrorDialog::GetDialogInfo; CInformErrorDialog::SetupMessage
00300 
00301 ********************************************************************************************/
00302 
00303 BOOL CInformErrorDialog::SetupButtons(HDC hDC, INT32 NumButtons)
00304 {
00305     // Set the default button in the dialog.
00306     CWnd *pDefCtrl = GetDlgItem(ButtonID[m_OK - 1]);
00307     ENSURE(pDefCtrl != NULL, "Can't get handle to default control in CInformErrorDialog");
00308 
00309     // If we can't get at this button then ooer...bit of a fatal error
00310     if (pDefCtrl == NULL)
00311     {
00312         ENSURE(FALSE, "Can't get default button in error box!");
00313         return FALSE;
00314     }
00315 
00316     // Set the keyboard focus to the default button, and give it a 'default' border.
00317     pDefCtrl->SetFocus();
00318     SendMessage(DM_SETDEFID, ButtonID[m_OK - 1], 0);
00319 
00320     // Read in the button texts, and find which is the widest string.
00321     INT32 ButtonWidth = DefButtonSize.cx;
00322     INT32 i;
00323     for (i = 0; i < NumButtons; i++)
00324     {
00325         // Try to load text for this button
00326         if (!ButtonText[i].Load(m_ButtonStr[i], m_OwnerModule))
00327         {
00328             ENSURE(FALSE, "Unable to load button text for error box!");
00329             return FALSE;
00330         }
00331 
00332         // Try to read the size of this button text.
00333         SIZE TextSize;
00334         if (!GetTextExtentPoint(hDC, (TCHAR *) ButtonText[i], ButtonText[i].Length(),
00335                                 &TextSize))
00336         {
00337             // Error reading text size
00338             ENSURE(FALSE, "Unable to read button text size for error box!");
00339             return FALSE;
00340         }
00341 
00342         if (TextSize.cx > ButtonWidth)
00343             ButtonWidth = TextSize.cx + 8;
00344     }
00345 
00346     // Allow for space on either side in the button
00347     ButtonWidth += 8;
00348 
00349     // Find out how big the buttons can be at the most.
00350     INT32 MaxWidth = DialogSize.cx - 
00351                    (2 * EdgeSpacing) - 
00352                    ((NumButtons - 1) * ButtonSpacing);
00353 
00354     // NumButtons cannot be 0 if we get to here...but just in case :-)
00355     if (NumButtons == 0)
00356     {
00357         ENSURE(FALSE, "NumButtons is zero in error box!");
00358         return FALSE;
00359     }
00360 
00361     // Safe to do a divide now!
00362     MaxWidth /= NumButtons;
00363 
00364     // The width of the dialog may change.
00365     INT32 NewWidth = DialogSize.cx;
00366 
00367     // Find out if we need to make the dialog bigger to accomodate the buttons.
00368     if (ButtonWidth > MaxWidth)
00369     {
00370         // Yes - find out if the buttons actually fit on screen - if not, make them
00371         // smaller and truncate the button text (this shouldn't happen too often!)
00372 
00373         // Get required dialog width
00374         NewWidth = (EdgeSpacing * 2) +
00375                    (NumButtons * ButtonWidth) +
00376                    ((NumButtons - 1) * ButtonSpacing);
00377 
00378         // Does this actually fit on screen?
00379         INT32 ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
00380 
00381         if (ScreenWidth < NewWidth)
00382         {
00383             // They don't fit - downsize the buttons to fit.
00384             ButtonWidth = ScreenWidth - 
00385                           (2 * EdgeSpacing) - 
00386                           ((NumButtons - 1) * ButtonSpacing);
00387             ButtonWidth /= NumButtons;
00388 
00389             NewWidth = ScreenWidth;
00390         }
00391 
00392         // Ok - buttons are now correct size - resize the dialog.
00393         SIZE BorderSize;
00394         BorderSize.cx = 2 * ::GetSystemMetrics(SM_CXDLGFRAME);
00395         BorderSize.cy = ::GetSystemMetrics(SM_CYDLGFRAME) + 
00396                         ::GetSystemMetrics(SM_CYCAPTION);
00397 
00398         if (!SetWindowPos(NULL, 0, 0, 
00399                           NewWidth + BorderSize.cx, DialogSize.cy + BorderSize.cy,
00400                           SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW))
00401         {
00402             ENSURE(FALSE, "Unable to resize the error box!");
00403             return FALSE;
00404         }
00405 
00406         // Resize the error message control so it doesn't look silly.
00407         INT32 Diff = NewWidth - DialogSize.cx;
00408         
00409         CWnd *pMsgCtrl = GetDlgItem(_R(IDC_ERRORBOX_TEXT));
00410         ENSURE(pMsgCtrl != NULL, "Can't get handle to text control in CInformErrorDialog");
00411 
00412         if (pMsgCtrl != NULL)
00413         {
00414             // Ok - resize it.
00415             if (!pMsgCtrl->SetWindowPos(NULL, 0, 0, 
00416                                         DefMsgSize.cx + Diff, DefMsgSize.cy,
00417                                         SWP_NOACTIVATE | SWP_NOZORDER | 
00418                                         SWP_NOMOVE | SWP_NOREDRAW))
00419             {
00420                 ENSURE(FALSE, "Unable to adjust error message control in error box!");
00421                 return FALSE;
00422             }
00423         }
00424     }
00425 
00426     // Position buttons accordingly...
00427 
00428     // How much space is left on either side of the row of buttons?
00429     INT32 SpareSpace = NewWidth - 
00430                      (NumButtons * ButtonWidth) - 
00431                      ((NumButtons - 1) * ButtonSpacing);
00432 
00433     // Work out where the first button should be.
00434     INT32 FarLeft = SpareSpace / 2;
00435 
00436     INT32 ButtonStep = ButtonSpacing + ButtonWidth;
00437 
00438     // For each button:
00439     //  * Set the button text.
00440     //  * Move the button to the correct position.
00441     //  * Show the button.
00442     for (i = 0; i < NumButtons; i++)
00443     {
00444         SetDlgItemText(ButtonID[i], ButtonText[i]);
00445 
00446         if (!m_Button[i].SetWindowPos(NULL, 
00447                                       FarLeft + (i * ButtonStep), DefTopOfButton, 
00448                                       ButtonWidth, DefButtonSize.cy,
00449                                       SWP_NOACTIVATE | SWP_NOZORDER | 
00450                                       SWP_NOREDRAW | SWP_SHOWWINDOW))
00451         {
00452             ENSURE(FALSE, "Unable to move button in the error box!");
00453             return FALSE;
00454         }
00455     }
00456 
00457     // Tell the caller that we managed to do all this successfully!
00458     return TRUE;
00459 }
00460 
00461 
00462 
00463 
00464 /********************************************************************************************
00465 
00466 >   BOOL CInformErrorDialog::SetupMessage(HDC hDC)
00467 
00468     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00469     Created:    19/05/94
00470     Inputs:     hDC - the device context of the dialog (used to access the dialog's font).
00471     Purpose:    Puts the error message into the dialog, and checks to see if this message
00472                 will fit. If it doesn't, the dialog is expanded vertically so that it does
00473                 fit, and the buttons are moved down, and the icon is moved down so it's
00474                 halfway down the message text so it looks all neat and luvverly.
00475     SeeAlso:    CInformErrorDialog::GetDialogInfo; CInformErrorDialog::SetupButtons
00476 
00477 ********************************************************************************************/
00478 
00479 BOOL CInformErrorDialog::SetupMessage(HDC hDC)
00480 {
00481     // Set the error message in the text control, and find out the size of the message.
00482     SIZE TextSize;
00483     RECT TextRect;
00484     INT32 Offset = 0;
00485 
00486     CWnd *pMsgCtrl = GetDlgItem(_R(IDC_ERRORBOX_TEXT));
00487     ENSURE(pMsgCtrl != NULL, "Can't get handle to text control in CInformErrorDialog");
00488 
00489     
00490     if (pMsgCtrl == NULL)
00491     {
00492         // Failed to get at the message control - flag an error
00493         ENSURE(FALSE, "Unable to access error message control");
00494         return FALSE;
00495     }
00496 
00497     // Get rectangle of message control.
00498     RECT MsgCtrlRect;
00499     pMsgCtrl->GetWindowRect(&MsgCtrlRect);
00500     ScreenToClient(&MsgCtrlRect);
00501 
00502     // Use the current control's rectangle as the basis for the formatting rectangle
00503     // of the text (Bottom will extend in preference to Right)
00504     TextRect = MsgCtrlRect;
00505 
00506     if (m_StaticTextStr != 0)
00507     {
00508         String_256 MsgStr(m_StaticTextStr, m_OwnerModule);
00509         SetDlgItemText(_R(IDC_ERRORBOX_TEXT), MsgStr);
00510         DrawText(hDC, (TCHAR *) MsgStr, -1, &TextRect, DT_CALCRECT | DT_TOP | DT_LEFT | DT_WORDBREAK);
00511     }
00512     else
00513     {
00514         TCHAR *pMsg = Error::GetErrorString();
00515         SetDlgItemText(_R(IDC_ERRORBOX_TEXT), pMsg);
00516         DrawText(hDC, pMsg, -1, &TextRect, DT_CALCRECT | DT_TOP | DT_LEFT | DT_WORDBREAK);
00517     }
00518 
00519     TextSize.cx = TextRect.right - TextRect.left;
00520     TextSize.cy = TextRect.bottom - TextRect.top;
00521 
00522     if ((TextSize.cx == 0) || (TextSize.cy == 0))
00523     {
00524         // Failed to get the size of the text - flag an error
00525         ENSURE(FALSE, "Unable to read size of error message");
00526         return FALSE;
00527     }
00528 
00529     // Get dimensions of message control.
00530     SIZE MsgCtrlSize;
00531     MsgCtrlSize.cx = MsgCtrlRect.right - MsgCtrlRect.left;
00532     MsgCtrlSize.cy = MsgCtrlRect.bottom - MsgCtrlRect.top;
00533 
00534     if ((MsgCtrlSize.cx == 0) || (MsgCtrlSize.cy == 0))
00535     {
00536         // Message control has a bad size - flag an error
00537         ENSURE(FALSE, "Bad message control size in error dialog box!");
00538         return FALSE;
00539     }
00540 
00541     // If formatted text is bigger than current control rect
00542     // we need to resize it...
00543     if (MsgCtrlSize.cx < TextSize.cx || MsgCtrlSize.cy < TextSize.cy)
00544     {
00545         if (MsgCtrlSize.cx < TextSize.cx)
00546             MsgCtrlSize.cx = TextSize.cx + 8;
00547 
00548         if (MsgCtrlSize.cy < TextSize.cy)
00549         {
00550             Offset = TextSize.cy - MsgCtrlSize.cy + 8;
00551             MsgCtrlSize.cy = TextSize.cy + 8;
00552         }
00553 
00554         // Resize message.
00555         if (!pMsgCtrl->SetWindowPos(NULL, 0, 0, MsgCtrlSize.cx, MsgCtrlSize.cy,
00556                                     SWP_NOACTIVATE | SWP_NOZORDER | 
00557                                     SWP_NOMOVE | SWP_NOREDRAW))
00558         {
00559             ENSURE(FALSE, "Unable to resize the message control in error box!");
00560             return FALSE;
00561         }
00562 
00563         // Move icon (just change IconPos - we ignore the real icon from now on)
00564         IconPos.y += (Offset / 2);
00565 
00566         // Move buttons
00567         for (INT32 i = 0; i < ERRORDLG_MAXBUTTONS; i++)
00568         {
00569             RECT ButtonRect;
00570             m_Button[i].GetWindowRect(&ButtonRect);
00571             ScreenToClient(&ButtonRect);
00572             if (!m_Button[i].SetWindowPos(NULL, ButtonRect.left, ButtonRect.top + Offset,
00573                                           0, 0,
00574                                           SWP_NOACTIVATE | SWP_NOZORDER | 
00575                                           SWP_NOSIZE | SWP_NOREDRAW))
00576             {
00577                 ENSURE(FALSE, "Unable to resize the button control in error box!");
00578                 return FALSE;
00579             }
00580         }
00581 
00582         // Resize dialog.
00583         RECT DialogRect;
00584         GetWindowRect(&DialogRect);
00585         INT32 DialogWidth  = DialogRect.right  - DialogRect.left;
00586         INT32 DialogHeight = DialogRect.bottom - DialogRect.top;
00587 
00588         if (!SetWindowPos(NULL, 0, 0, DialogWidth, DialogHeight + Offset,
00589                           SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW))
00590         {
00591             ENSURE(FALSE, "Unable to resize the error box dialog!");
00592             return FALSE;
00593         }
00594     }
00595 
00596     // All ok!
00597     return TRUE;
00598 }
00599 
00600 
00602 // CInformErrorDialog message handlers
00603 
00604 
00605 /********************************************************************************************
00606 
00607 >   BOOL CInformErrorDialog::OnInitDialog()
00608 
00609     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00610     Created:    20/7/93
00611     Returns:    TRUE if all went OK, FALSE if the focus was set to a control
00612     Purpose:    This function sets up the dialog accoding to the data supplied by the
00613                 program. First the various fields in the dialog are filled in and the 
00614                 relevant buttons activated, and then the dialog is centred.
00615 
00616 ********************************************************************************************/
00617 
00618 BOOL CInformErrorDialog::OnInitDialog()
00619 {
00620     CDialog::OnInitDialog();
00621     
00622     String_64 BoxTitle;
00623     BoxTitle = _R(IDS_ERROR_BOX_SERIOUS_ERROR); // "Serious error"
00624 
00625     String_256 VerySeriousError;
00626     VerySeriousError = _R(IDS_ERROR_BOX_VERY_SERIOUS_ERROR); // "A very serious error has occured - please consult your technical support."
00627 
00628     // Andy Hills, 22-11-00
00629     // Store the help context.
00630     // We need to do this here, because the global help context variable
00631     // nNextMessageHelpContext may change before the user clicks the 'Help'
00632     // button. This fixes bug 6359.
00633     m_nHelpContext = Error::GetErrorNumber();
00634     if (! m_nHelpContext) m_nHelpContext = GetNextMsgHelpContext();
00635 
00636     // Find out how many buttons there are.
00637     for (INT32 NumButtons = ERRORDLG_MAXBUTTONS; NumButtons > 0; NumButtons--)
00638     {
00639         if (m_ButtonStr[NumButtons - 1] != 0) break;
00640     }
00641 
00642     // Adjust the OK and Cancel fields if necessary
00643     if (m_OK > (UINT32) NumButtons)
00644     {
00645         if (IsUserName("Tim"))
00646         {
00647             TRACE( _T("OK out of range, OK=%u, NumButtons=%d\n"), m_OK, NumButtons);
00648         }
00649         // Default to first button
00650         m_OK = 1;
00651     }
00652 
00653     if (m_Cancel > (UINT32) NumButtons)
00654     {
00655         if (IsUserName("Tim"))
00656         {
00657             TRACE( _T("Cancel out of range, Cancel=%u, NumButtons=%d\n"), m_Cancel, NumButtons);
00658         }
00659 
00660         // Default to be the same as OK (this means a box with a single OK box will
00661         // respond to Enter and Esc without the user having to specify a Cancel ID).
00662         m_Cancel = m_OK;
00663     }
00664 
00665     if (m_Help > (UINT32) NumButtons)
00666     {
00667         TRACEUSER( "JustinF", _T("Help button (%d) out of range (%d)\n"),
00668                                     (INT32) m_Help, (INT32) NumButtons);
00669         
00670         // The only really safe thing we can do is drop the help button.
00671         m_Help = 0;
00672     }
00673         
00674     // Make sure we have correct dialog information
00675     GetDialogInfo();
00676     if (!ValidInfo)
00677     {
00678         // Serious error - fall back to to MessageBox().
00679         goto SevereError;
00680     }
00681 
00682     // Get icon position
00683     IconPos = DefIconPos;
00684 
00685 
00686     // Get a DC for this dialog, so we can find out the size of text strings.
00687     // We'll also need to select in our font or else it'll base the width upon the
00688     // System font rather than the font we're using (MS Sans Serif at last check)
00689     CDC *pDC;
00690     CFont *OldFont;
00691 
00692     pDC = GetDC();
00693     ENSURE(pDC != NULL, "Can't get DC for error box dialog");
00694 
00695     // Check the DC
00696     if (pDC == NULL)
00697         goto SevereError;
00698 
00699     OldFont = pDC->SelectObject(GetFont());
00700 
00701     // Set buttons text and move/resize buttons according to the number of them,
00702     // and their contents.
00703     BOOL Success;
00704     Success = SetupButtons(pDC->m_hDC, NumButtons);
00705 
00706     // Size the error message control, and put the message in it.
00707     Success = Success && SetupMessage(pDC->m_hDC);
00708 
00709     if (OldFont != NULL)
00710         pDC->SelectObject(OldFont);
00711 
00712     // We've finished with this DC now.
00713     ReleaseDC(pDC);
00714 
00715 
00716     // Check for failure in button/message setup.
00717     if (!Success)
00718         goto SevereError;
00719 
00720     // Play the appropriate sound and set the appropriate title bar text ID.
00721     UINT32 TitleID;
00722     TitleID = m_TitleStr;
00723     switch (m_ErrorBoxType)
00724     {
00725         case ERRORTYPE_NORMAL:
00726             // No sound for this one - it's just a message; nothing to shout about.
00727             if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_NORMAL);
00728             break;
00729 
00730         case ERRORTYPE_QUESTION:
00731             MessageBeep(MB_ICONQUESTION);
00732             if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_NORMAL);
00733             break;
00734 
00735         case ERRORTYPE_ERROR:
00736             MessageBeep(MB_ICONEXCLAMATION);
00737             if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_ERROR);
00738             break;
00739 
00740         case ERRORTYPE_WARNING:
00741             MessageBeep(MB_ICONASTERISK);
00742             if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_WARNING);
00743             break;
00744 
00745         case ERRORTYPE_SERIOUS:
00746             MessageBeep(MB_ICONHAND);
00747             if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_SERIOUS);
00748             break;
00749 
00750         case ERRORTYPE_ENSURE:
00751             MessageBeep(MB_ICONHAND);
00752             if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_ENSURE);
00753             break;
00754 
00755         default:
00756             ENSURE(FALSE, "Bad errortype in CInformErrorDialog::OnInitDialog()");
00757             goto SevereError;
00758             break;
00759     }
00760 
00761     // Set the title bar text if necessary.
00762     if (TitleID != 0)
00763     {
00764         String_64 Title(TitleID);
00765         SetWindowText((TCHAR*) Title);
00766     }
00767 
00768     // Centre the dialog on the screen (Code stolen from splash.cpp)    
00769     // Get the size of the screen
00770     INT32 ScreenWidth, ScreenHeight;
00771     ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
00772     ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
00773     
00774     // Get the size of the dialog box
00775     RECT DialogRect;
00776     GetWindowRect(&DialogRect);
00777     INT32 DialogWidth, DialogHeight;
00778     DialogWidth  = DialogRect.right  - DialogRect.left;
00779     DialogHeight = DialogRect.bottom - DialogRect.top;
00780     
00781     // Chicago M7 gives us crap values at this point if we are minimized so try and make them sane
00782     if (DialogWidth<=0)
00783         DialogWidth = ScreenWidth / 2;
00784     else if (DialogWidth > ScreenWidth)
00785         DialogWidth = ScreenWidth;
00786 
00787     if (DialogHeight<=0)
00788         DialogHeight = ScreenHeight / 2;
00789     else if (DialogHeight > ScreenHeight)
00790         DialogHeight = ScreenHeight;
00791 
00792     // Centre the dialog box and give it the 'top' style.
00793     INT32 Left, Top;
00794     Left = (ScreenWidth - DialogWidth) / 2;
00795     Top  = (ScreenHeight - DialogHeight) / 2;
00796     SetWindowPos(&wndTop, Left, Top, DialogWidth, DialogHeight, SWP_SHOWWINDOW);
00797     
00798     // If we got this far, then we changed the keyboard focus, so return FALSE.
00799     return FALSE;
00800 
00801 SevereError:
00802     // Ooer - deeply catastrophic error...report to user and exit.
00803     String_256 Message;
00804 
00805     // First - check that this isn't just because of an empty error message.
00806     if (m_StaticTextStr == 0)
00807     {
00808         // Get the error message
00809         TCHAR *pMsg = Error::GetErrorString();
00810 
00811         if ((pMsg == NULL) || (pMsg[0] == 0))
00812         {
00813             //
00814             // There is no error message!
00815             //
00816 
00817             // In debug builds, give developer a chance to go into debugger to see who is not
00818             // setting an error message.
00819             #ifdef _DEBUG
00820             if (::MessageBox(ParentHwnd, 
00821                              "Somebody reported an error without an error message being set.\r"
00822                              "Click OK to continue, or Cancel to go into debugger",
00823                              "DEBUG Warning from Camelot",
00824                              MB_OKCANCEL| MB_SYSTEMMODAL | MB_ICONHAND) == IDCANCEL)
00825             {
00826                 // User wants to go into debugger
00827                 DebugBreak();
00828             }
00829             #endif
00830 
00831             // Tell the user a spurious error has occured,
00832             if (!Message.Load(_R(IDS_ERRORBOX_SPURIOUS)))
00833                 // Can't load error message - panic.
00834                 goto VerySevereError;
00835 
00836             // Try to get the string that says "Warning from Camelot"
00837             String_64 Title;
00838             if (!Title.Load(_R(IDS_ERRORBOX_WARNING)))
00839                 goto VerySevereError;
00840 
00841             if (::MessageBox(ParentHwnd, (TCHAR *) Message, (TCHAR *) Title,
00842                              MB_OK | MB_SYSTEMMODAL | MB_ICONHAND) == 0)
00843                 // Could not create the message box - try our fallback one (probably won't
00844                 // work but what the hell).
00845                 goto VerySevereError;
00846 
00847             // Simulate user hitting default button.
00848             EndDialog((INT32) m_OK);
00849 
00850             return TRUE; // We haven't set the keyboard focus.
00851         }
00852     }
00853 
00854 
00855     // Inform the user that we've got a bit of a bad karma situation, and that the error
00856     // box might be not be completely accurate.
00857     if (!Message.Load(_R(IDS_ERRORBOX_SEVERE)))
00858         goto VerySevereError;
00859 
00860     if (::MessageBox(ParentHwnd, (TCHAR *) Message, (TCHAR *)BoxTitle, /*"Serious Error", */
00861                      MB_OK | MB_SYSTEMMODAL | MB_ICONHAND) == 0)
00862         // Could not create the message box - try our fallback one (probably won't
00863         // work but what the hell).
00864         goto VerySevereError;
00865 
00866     // Ok - try to report the error as best we can...
00867 
00868     // Work out what buttons to put on the dialog...
00869 
00870     // We use SYSTEMMODAL with ICONHAND because the SDK docs recommend this for low
00871     // memory/severe error situations.
00872     UINT32 MBFlags;
00873     MBFlags = MB_SYSTEMMODAL | MB_ICONHAND;
00874 
00875     // Do we need a cancel icon?
00876     if (m_Cancel != m_OK)
00877         MBFlags |= MB_OKCANCEL;
00878     else
00879         MBFlags |= MB_OK;
00880 
00881     if (m_StaticTextStr != 0)
00882     {
00883         if (Message.Load(m_StaticTextStr, m_OwnerModule))
00884         {
00885             // Error message loaded ok - display it
00886             INT32 Result =  ::MessageBox(ParentHwnd, (TCHAR *) Message, (TCHAR *)BoxTitle, MBFlags);
00887 
00888             if (Result == 0)
00889                 // Could not create the message box - try our fallback one (probably won't
00890                 // work but what the hell).
00891                 goto VerySevereError;
00892 
00893             if (Result == IDCANCEL)
00894             {
00895                 // Simulate user hitting cancel button.
00896                 EndDialog((INT32) m_Cancel);
00897             }
00898             else
00899             {
00900                 // Simulate user hitting default button.
00901                 EndDialog((INT32) m_OK);
00902             }
00903 
00904             return TRUE; // We haven't set the keyboard focus.
00905         }
00906         else
00907         {
00908             // Can't load error message - bail out
00909             goto VerySevereError;
00910         }
00911     }
00912     else
00913     {
00914         // Get the error message
00915         TCHAR *pMsg = Error::GetErrorString();
00916 
00917         if (pMsg == NULL)
00918             // No error message!
00919             goto VerySevereError;
00920 
00921         // Found error message ok - display it
00922         INT32 Result =  ::MessageBox(ParentHwnd, pMsg, (TCHAR *)BoxTitle, MBFlags);
00923 
00924         if (Result == 0)
00925             // Could not create the message box - try our fallback one (probably won't
00926             // work but what the hell).
00927             goto VerySevereError;
00928 
00929         if (Result == IDCANCEL)
00930         {
00931             // Simulate user hitting cancel button.
00932             EndDialog((INT32) m_Cancel);
00933         }
00934         else
00935         {
00936             // Simulate user hitting default button.
00937             EndDialog((INT32) m_OK);
00938         }
00939 
00940         return TRUE; // We haven't set the keyboard focus.
00941     }
00942 
00943 VerySevereError:
00944     // Very bad - we can't even report the error - just let the user that something deeply
00945     // sad has happened, and pretend that the OK button was pressed.
00946     ::MessageBox(ParentHwnd, (TCHAR *)VerySeriousError, (TCHAR *)BoxTitle, MB_OK | MB_SYSTEMMODAL | MB_ICONHAND);
00947 
00948     // Simulate user hitting default button.
00949     EndDialog((INT32) m_OK);
00950 
00951     return TRUE; // We haven't set the keyboard focus.
00952 }
00953 
00954 
00955 
00956 /********************************************************************************************
00957 
00958 >   void CInformErrorDialog::OnPaint()
00959 
00960     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00961     Created:    19/05/94
00962     Purpose:    Special painting of the dialog.  This involves drawing the correct icon
00963                 onto the dialog, according to the type/degree of error.
00964                 The icon position is based on the position of the hidden icon control in
00965                 the dialog, but may be moved down if the message area needs to grow to
00966                 accomodate a long message.
00967     SeeAlso:    CInformErrorDialog::SetupMessage
00968 
00969 ********************************************************************************************/
00970 
00971 void CInformErrorDialog::OnPaint()
00972 {
00973     CPaintDC dc(this); // device context for painting
00974     
00975     HICON hIcon;
00976     CWinApp *pApp = AfxGetApp();
00977 
00978     ENSURE(pApp != NULL, "Could not get application object in CInformErrorDialog::OnPaint()");
00979     if (pApp == NULL)
00980         return;
00981 
00982     switch (m_ErrorBoxType)
00983     {
00984         case ERRORTYPE_NORMAL:
00985             hIcon = pApp->LoadIcon(_R(IDR_MAINFRAME));
00986             break;
00987 
00988         case ERRORTYPE_QUESTION:
00989 // The line below is commented out (by Phil, 12/8/96) because the latest UI guidelines
00990 // advise against using this icon.
00991 // See "The Windows Interface Guidelines for Software Design" P.211.
00992 //          hIcon = pApp->LoadStandardIcon(_R(IDI_QUESTION));
00993             hIcon = pApp->LoadStandardIcon(_R(IDI_EXCLAMATION));
00994             break;
00995 
00996         case ERRORTYPE_ERROR:
00997             hIcon = pApp->LoadStandardIcon(_R(IDI_EXCLAMATION));
00998             break;
00999 
01000         case ERRORTYPE_WARNING:
01001             hIcon = pApp->LoadStandardIcon(_R(IDI_ASTERISK));
01002             break;
01003 
01004         case ERRORTYPE_SERIOUS:
01005         case ERRORTYPE_ENSURE:
01006             hIcon = pApp->LoadStandardIcon(_R(IDI_HAND));
01007             break;
01008 
01009         default:
01010             ENSURE(FALSE, "Bad errortype in CInformErrorDialog::OnPaint()");
01011             return;
01012     }
01013 
01014 
01015     ENSURE(hIcon != NULL, "Could not load icon in CInformErrorDialog::OnPaint()");
01016     if (hIcon != NULL)
01017     {
01018         // Got an icon - let's draw it on the dialog.
01019         dc.DrawIcon(IconPos.x, IconPos.y, hIcon);
01020     }
01021 
01022     // Do not call CWnd::OnPaint() for painting messages
01023 }
01024 
01025 
01026 
01027 /********************************************************************************************
01028 >   void CInformErrorDialog::OnClickedButton1()
01029     void CInformErrorDialog::OnClickedButton2()
01030     void CInformErrorDialog::OnClickedButton3()
01031     void CInformErrorDialog::OnClickedButton4()
01032     void CInformErrorDialog::OnClickedButton5()
01033 
01034     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01035     Created:    20/7/93
01036     Purpose:    Responds to the five buttons at the bottom of the dialog.  Calls the
01037                 HandleButton function in each case, passing the ID of the button.
01038     SeeAlso:    CInformErrorDialog::HandleButton
01039 ********************************************************************************************/
01040 
01041 void CInformErrorDialog::OnClickedButton1()
01042 {
01043     HandleButton(1);
01044 }
01045 
01046 
01047 void CInformErrorDialog::OnClickedButton2()
01048 {
01049     HandleButton(2);
01050 }
01051 
01052 
01053 void CInformErrorDialog::OnClickedButton3()
01054 {
01055     HandleButton(3);
01056 }
01057 
01058 
01059 void CInformErrorDialog::OnClickedButton4()
01060 {
01061     HandleButton(4);
01062 }
01063 
01064 
01065 void CInformErrorDialog::OnClickedButton5()
01066 {
01067     HandleButton(5);
01068 }
01069 
01070 
01071 
01072 /********************************************************************************************
01073 >   virtual void CInformErrorDialog::HandleButton(UINT32 idButton)
01074 
01075     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01076     Created:    11/5/95
01077     Inputs:     idButton            which button was clicked, ie. 1-5
01078     Purpose:    Handles a button being clicked in a Inform... dialog box.  If the button
01079                 is the "help" button it runs help for the dialog, otherwise it ends the
01080                 dialog and returns which button was clicked.
01081     SeeAlso:    CInformErrorDialog::OnClickedButton1
01082 ********************************************************************************************/
01083 
01084 void CInformErrorDialog::HandleButton(UINT32 idButton)
01085 {
01086     // Check if the clicked button is a "Help" button.
01087     if (idButton == m_Help)
01088     {
01089 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
01090         // It is, so run the help topic associated with the message ID.
01091         HelpUser(m_nHelpContext);
01092 #endif
01093     }
01094     else
01095     {
01096         // It isn't, so end the dialog, returning which button was clicked.
01097         EndDialog((INT32) idButton);
01098     }
01099 }
01100 
01101 
01102 
01103 /********************************************************************************************
01104 >   void CInformErrorDialog::OnCancelCmd()
01105 
01106     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01107     Created:    19/05/94
01108     Purpose:    Responds to an Esc keypress from the user - it simulates pressing the
01109                 button defined to be the 'cancel' button in the dialog (although the
01110                 button may not actually be labelled 'cancel' - it may say 'No' or
01111                 whatever).
01112 ********************************************************************************************/
01113 
01114 void CInformErrorDialog::OnCancelCmd()
01115 {
01116     // User has hit Esc - return with the ID of the 'Cancel' button.
01117     EndDialog((INT32) m_Cancel);
01118 }
01119 
01120 
01121 
01122 /********************************************************************************************
01123 
01124 >   CWnd* CInformErrorDialog::GetSafeParent()
01125 
01126     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01127     Created:    2/11/94
01128     Returns:    Pointer to a CWnd for use as a parent window in error dialogs, or NULL
01129                 if we don't have one.
01130     Purpose:    Used by the error reporter and ensure handler to get a suitable parent
01131                 window.
01132 
01133 ********************************************************************************************/
01134 
01135 CWnd* CInformErrorDialog::GetSafeParent()
01136 {
01137     CWnd *Parent = NULL;
01138 
01139 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
01140     // if the splash box is up, use that as the parent
01141     Parent = CSplashDialog::GetpWnd();
01142 
01143     if (Parent)
01144         return Parent;
01145 #endif
01146 
01147 //  WEBSTER-ranbirr-12/11/96
01148 #ifndef WEBSTER
01149 #ifndef STANDALONE
01150     // If there is a print-related dlg up, use it as the parent
01151     Parent = CCPrintDialog::GetPrintCWnd();
01152     if (Parent)
01153         return Parent;
01154 #endif
01155 #endif //webster
01156 
01157     // see if mainframe is up - use it if visible
01158     Parent = GetMainFrame();
01159     if (Parent && Parent->IsWindowVisible())
01160         return Parent;
01161     return NULL;
01162 }

Generated on Sat Nov 10 03:48:26 2007 for Camelot by  doxygen 1.4.4