From bbbb84e6c22dbcc332b1cc4edcad8806dbf091f0 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 2 Apr 2015 13:18:19 +0200 Subject: [PATCH] Fix a few minor coverity warnings. Fix minor 3D viewer issues (includling change number of segments and its optimization to draw pad holes.) Fix Bug #1439132 (track and via list on toolbar not always refresh after loading a board). Remove useless tool in Modedit. --- 3d-viewer/3d_draw.cpp | 51 ++++++++++------ 3d-viewer/vrml_aux.cpp | 13 ++-- 3d-viewer/vrml_aux.h | 9 +-- 3d-viewer/vrml_v2_modelparser.cpp | 6 +- common/common_plotPDF_functions.cpp | 17 ++++-- common/geometry/hetriang.cpp | 1 + .../dialog_edit_component_in_schematic.cpp | 3 +- .../dialogs/dialog_lib_edit_pin_table.cpp | 3 + eeschema/find.cpp | 11 ++-- eeschema/sch_text.cpp | 6 +- pcbnew/autorouter/autorout.cpp | 13 ++-- pcbnew/edtxtmod.cpp | 59 +++++++------------ pcbnew/files.cpp | 3 + pcbnew/loadcmp.cpp | 5 +- pcbnew/modedit.cpp | 1 + pcbnew/tool_modedit.cpp | 6 +- 16 files changed, 117 insertions(+), 90 deletions(-) diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index 0b8c4cf1e1..878f8d469a 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -111,7 +111,7 @@ void EDA_3D_CANVAS::create_and_render_shadow_buffer( GLuint *aDst_gl_texture, CIMAGE imgDepthBufferAux( aTexture_size, aTexture_size ); imgDepthBuffer.SetPixelsFromNormalizedFloat( depthbufferFloat ); - + free( depthbufferFloat ); // Debug texture image @@ -168,7 +168,7 @@ void EDA_3D_CANVAS::generateFakeShadowsTextures( wxString* aErrorMessages, bool CreateDrawGL_List( aErrorMessages, aShowWarnings ); DBG( unsigned strtime = GetRunningMicroSecs() ); - + m_shadow_init = true; glClearColor( 0, 0, 0, 1 ); @@ -246,7 +246,7 @@ void EDA_3D_CANVAS::generateFakeShadowsTextures( wxString* aErrorMessages, bool // move the bouding box in order to draw it with its center at 0,0 3D coordinates glTranslatef( -(m_fastAABBox_Shadow.Min().x + v.x / 2.0f), -(m_fastAABBox_Shadow.Min().y + v.y / 2.0f), 0.0f ); - + create_and_render_shadow_buffer( &m_text_fake_shadow_board, 512, true, 10 ); DBG( printf( " generateFakeShadowsTextures total time %f ms\n", (double) (GetRunningMicroSecs() - strtime) / 1000.0 ) ); @@ -404,7 +404,7 @@ void EDA_3D_CANVAS::Redraw() // Set material for the board glEnable( GL_COLOR_MATERIAL ); SetOpenGlDefaultMaterial(); - + // Board Body GLint shininess_value = 32; @@ -569,7 +569,7 @@ void EDA_3D_CANVAS::Redraw() void EDA_3D_CANVAS::buildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList ) -{ +{ // Board shadows are based on board dimension. float xmin = m_boardAABBox.Min().x; @@ -646,14 +646,14 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ); // Number of segments to convert a circle to polygon - // Boost polygon (at least v 1.54, v1.55 and previous) in very rare cases crashes + // Boost polygon (at least v1.57 and previous) in very rare cases crashes // when using 16 segments to approximate a circle. // So using 18 segments is a workaround to try to avoid these crashes // ( We already used this trick in plot_board_layers.cpp, // see PlotSolderMaskLayer() ) const int segcountforcircle = 18; double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2.0) ); - const int segcountLowQuality = 8; // segments to draw a circle with low quality + const int segcountLowQuality = 12; // segments to draw a circle with low quality // to reduce time calculations // for holes and items which do not need // a fine representation @@ -767,13 +767,28 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, for( ; pad; pad = pad->Next() ) { - // Calculate a factor to apply to segcount (bigger pad size -> more segments) - wxSize padSize = pad->GetSize(); - int maxPadSize = glm::max( padSize.x, padSize.y ); - float segFactor = (float)maxPadSize / (float)Millimeter2iu( 0.6 ); + // Calculate a factor to apply to segcount for large holes ( > 1 mm) + // (bigger pad drill size -> more segments) because holes in pads can have + // very different sizes and optimizing this segcount gives a better look + // Mainly mounting holes have a size bigger thon 1 mm + wxSize padHole = pad->GetDrillSize(); - pad->BuildPadDrillShapePolygon( allLayerHoles, 0, - (int)(segcountLowQuality * segFactor) ); + if( ! padHole.x ) // Not drilled pad like SMD pad + continue; + + // we use the hole diameter to calculate the seg count. + // for round holes, padHole.x == padHole.y + // for oblong holes, the diameter is the smaller of (padHole.x, padHole.y) + int diam = std::min( padHole.x, padHole.y ); + double segFactor = (double)diam / Millimeter2iu( 1.0 ); + + int segcount = (int)(segcountLowQuality * segFactor); + + // Clamp segcount between segcountLowQuality and 48. + // 48 segm for a circle is a very good approx. + segcount = Clamp( segcountLowQuality, segcount, 48 ); + + pad->BuildPadDrillShapePolygon( allLayerHoles, 0, segcount ); } } } @@ -1291,7 +1306,7 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni if( ! m_glLists[GL_ID_BOARD] ) { DBG( unsigned strtime = GetRunningMicroSecs() ); - + m_glLists[GL_ID_BOARD] = glGenLists( 1 ); m_glLists[GL_ID_BODY] = glGenLists( 1 ); buildBoard3DView(m_glLists[GL_ID_BOARD], m_glLists[GL_ID_BODY], aErrorMessages, aShowWarnings ); @@ -1366,10 +1381,10 @@ void EDA_3D_CANVAS::CreateDrawGL_List( wxString* aErrorMessages, bool aShowWarni if( !m_glLists[GL_ID_SHADOW_FRONT] ) m_glLists[GL_ID_SHADOW_FRONT] = glGenLists( 1 ); - + if( !m_glLists[GL_ID_SHADOW_BACK] ) m_glLists[GL_ID_SHADOW_BACK] = glGenLists( 1 ); - + if( !m_glLists[GL_ID_SHADOW_BOARD] ) m_glLists[GL_ID_SHADOW_BOARD] = glGenLists( 1 ); @@ -1412,7 +1427,7 @@ void EDA_3D_CANVAS::calcBBox() } // Compute a union bounding box for all the shapes of the model - + S3D_MASTER* shape3D = module->Models(); for( ; shape3D; shape3D = shape3D->Next() ) @@ -1540,7 +1555,7 @@ bool EDA_3D_CANVAS::read3DComponentShape( MODULE* module ) { // Create a new parser S3D_MODEL_PARSER *newParser = S3D_MODEL_PARSER::Create( shape3D, shape3D->GetShape3DExtension() ); - + if( newParser ) { // Read file diff --git a/3d-viewer/vrml_aux.cpp b/3d-viewer/vrml_aux.cpp index 1b2bcefdf1..ace9a5cffe 100644 --- a/3d-viewer/vrml_aux.cpp +++ b/3d-viewer/vrml_aux.cpp @@ -37,7 +37,7 @@ bool GetString( FILE* File, char* aDstString, size_t maxDstLen ) return false; int c; - + while( ( c = fgetc( File ) ) != EOF ) { if( c == '\"' ) @@ -256,12 +256,15 @@ int ParseVertex( FILE* File, glm::vec3& dst_vertex ) } -int ParseFloat( FILE* File, float* dst_float ) +bool ParseFloat( FILE* aFile, float *aDstFloat, float aDefaultValue ) { float value; - int ret = fscanf( File, "%e", &value ); + int ret = fscanf( aFile, "%e", &value ); - *dst_float = value; + if( ret == 1 ) + *aDstFloat = value; + else + *aDstFloat = aDefaultValue; - return ret; + return ret == 1; } diff --git a/3d-viewer/vrml_aux.h b/3d-viewer/vrml_aux.h index e1c9da0584..3ab388063d 100644 --- a/3d-viewer/vrml_aux.h +++ b/3d-viewer/vrml_aux.h @@ -83,11 +83,12 @@ int ParseVertex( FILE* File, glm::vec3 &dst_vertex ); /** * Function ParseFloat * parse a float value - * @param File file to read from - * @param dst_float destination float - * @return int - Return the number of floats readed (0 or 1) + * @param aFile file to read from + * @param aDstFloat destination float + * @param aDefaultValue = the default value, when the actual value cannot be read + * @return bool - Return true if the float was read without error */ -int ParseFloat( FILE* File, float *dst_float ); +bool ParseFloat( FILE* aFile, float *aDstFloat, float aDefaultValue ); /** * Function GetNextTag diff --git a/3d-viewer/vrml_v2_modelparser.cpp b/3d-viewer/vrml_v2_modelparser.cpp index b44c673e4b..8d26130e5b 100644 --- a/3d-viewer/vrml_v2_modelparser.cpp +++ b/3d-viewer/vrml_v2_modelparser.cpp @@ -1283,7 +1283,7 @@ int VRML2_MODEL_PARSER::read_Material() else if( strcmp( text, "ambientIntensity" ) == 0 ) { float ambientIntensity; - ParseFloat( m_file, &ambientIntensity ); + ParseFloat( m_file, &ambientIntensity, 0.8 ); if( m_Master->m_use_modelfile_ambientIntensity == true ) { @@ -1294,7 +1294,7 @@ int VRML2_MODEL_PARSER::read_Material() else if( strcmp( text, "transparency" ) == 0 ) { float transparency; - ParseFloat( m_file, &transparency ); + ParseFloat( m_file, &transparency, 0.0 ); if( m_Master->m_use_modelfile_transparency == true ) { @@ -1304,7 +1304,7 @@ int VRML2_MODEL_PARSER::read_Material() else if( strcmp( text, "shininess" ) == 0 ) { float shininess; - ParseFloat( m_file, &shininess ); + ParseFloat( m_file, &shininess, 1.0 ); // VRML value is normalized and openGL expects a value 0 - 128 if( m_Master->m_use_modelfile_shininess == true ) diff --git a/common/common_plotPDF_functions.cpp b/common/common_plotPDF_functions.cpp index de9c1bf8df..e5f12afc19 100644 --- a/common/common_plotPDF_functions.cpp +++ b/common/common_plotPDF_functions.cpp @@ -455,7 +455,12 @@ void PDF_PLOTTER::closePdfStream() wxASSERT( workFile ); long stream_len = ftell( workFile ); - wxASSERT( stream_len >= 0 ); + + if( stream_len < 0 ) + { + wxASSERT( false ); + return; + } // Rewind the file, read in the page stream and DEFLATE it fseek( workFile, 0, SEEK_SET ); @@ -475,11 +480,11 @@ void PDF_PLOTTER::closePdfStream() { /* Somewhat standard parameters to compress in DEFLATE. The PDF spec is - misleading, it says it wants a DEFLATE stream but it really want a ZLIB - stream! (a DEFLATE stream would be generated with -15 instead of 15) - rc = deflateInit2( &zstrm, Z_BEST_COMPRESSION, Z_DEFLATED, 15, - 8, Z_DEFAULT_STRATEGY ); - */ + * misleading, it says it wants a DEFLATE stream but it really want a ZLIB + * stream! (a DEFLATE stream would be generated with -15 instead of 15) + * rc = deflateInit2( &zstrm, Z_BEST_COMPRESSION, Z_DEFLATED, 15, + * 8, Z_DEFAULT_STRATEGY ); + */ wxZlibOutputStream zos( memos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB ); diff --git a/common/geometry/hetriang.cpp b/common/geometry/hetriang.cpp index d1e7fd0254..323754b5ae 100644 --- a/common/geometry/hetriang.cpp +++ b/common/geometry/hetriang.cpp @@ -170,6 +170,7 @@ TRIANGULATION::TRIANGULATION() TRIANGULATION::TRIANGULATION( const TRIANGULATION& aTriangulation ) { + m_helper = 0; // make coverity and static analysers quiet. // Triangulation: Copy constructor not present assert( false ); } diff --git a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp index fa281a23d5..3fd44f6028 100644 --- a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp +++ b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp @@ -156,7 +156,8 @@ void SCH_EDIT_FRAME::EditComponent( SCH_COMPONENT* aComponent ) // frame. Therefore this dialog as a modal frame parent, MUST be run under // quasimodal mode for the quasimodal frame support to work. So don't use // the QUASIMODAL macros here. - dlg->ShowQuasiModal(); + int ret = dlg->ShowQuasiModal(); + (void) ret; // not used. Make coverity and static analysers quiet. m_canvas->SetIgnoreMouseEvents( false ); m_canvas->MoveCursorToCrossHair(); diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp index d72b447348..7703a050c0 100644 --- a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp +++ b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp @@ -196,6 +196,9 @@ DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::DataViewModel( LIB_PART& aPart ) : m_GroupingColumn( 1 ), m_UnitCount( m_Part.GetUnitCount() ) { +#ifdef REASSOCIATE_HACK + m_Widget = NULL; +#endif aPart.GetPins( m_Backing ); /// @todo C++11 for( LIB_PINS::const_iterator i = m_Backing.begin(); i != m_Backing.end(); ++i ) diff --git a/eeschema/find.cpp b/eeschema/find.cpp index f207a1e853..02d596a915 100644 --- a/eeschema/find.cpp +++ b/eeschema/find.cpp @@ -420,10 +420,13 @@ void SCH_EDIT_FRAME::updateFindReplaceView( wxFindDialogEvent& aEvent ) // Make the item temporarily visible just in case it's hide flag is set. This // has no effect on objects that don't support hiding. If this is a close find // dialog event, clear the temporary visibility flag. - if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE ) - item->SetForceVisible( false ); - else if( item->Type() == SCH_FIELD_T && !( (SCH_FIELD*) item )->IsVisible() ) - item->SetForceVisible( true ); + if( item ) + { + if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE ) + item->SetForceVisible( false ); + else if( item->Type() == SCH_FIELD_T && !( (SCH_FIELD*) item )->IsVisible() ) + item->SetForceVisible( true ); + } if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() ) { diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index 3dc9929687..12a99405ef 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -360,7 +360,7 @@ void SCH_TEXT::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& aOffset, EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR ); EXCHG( linewidth, m_Thickness ); // set initial value - if( m_isDangling ) + if( m_isDangling && panel) DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color ); // Enable these line to draw the bounding box (debug tests purposes only) @@ -1282,7 +1282,7 @@ void SCH_GLOBALLABEL::Draw( EDA_DRAW_PANEL* panel, CreateGraphicShape( Poly, m_Pos + aOffset ); GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color ); - if( m_isDangling ) + if( m_isDangling && panel ) DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color ); // Enable these line to draw the bounding box (debug tests purposes only) @@ -1614,7 +1614,7 @@ void SCH_HIERLABEL::Draw( EDA_DRAW_PANEL* panel, CreateGraphicShape( Poly, m_Pos + offset ); GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color ); - if( m_isDangling ) + if( m_isDangling && panel ) DrawDanglingSymbol( panel, DC, m_Pos + offset, color ); // Enable these line to draw the bounding box (debug tests purposes only) diff --git a/pcbnew/autorouter/autorout.cpp b/pcbnew/autorouter/autorout.cpp index 32112d7c5f..7c53f0e3d3 100644 --- a/pcbnew/autorouter/autorout.cpp +++ b/pcbnew/autorouter/autorout.cpp @@ -221,7 +221,7 @@ void PCB_EDIT_FRAME::Reset_Noroutable( wxDC* DC ) /* DEBUG Function: displays the routing matrix */ void DisplayRoutingMatrix( EDA_DRAW_PANEL* panel, wxDC* DC ) { - int dcell0, dcell1 = 0; + int dcell0; EDA_COLOR_T color; int maxi = 600 / RoutingMatrix.m_Ncols; @@ -242,14 +242,17 @@ void DisplayRoutingMatrix( EDA_DRAW_PANEL* panel, wxDC* DC ) if( dcell0 & HOLE ) color = GREEN; -// if( RoutingMatrix.m_RoutingLayersCount ) -// dcell1 = GetCell( row, col, TOP ); +#if 0 + int dcell1 = 0; + + if( RoutingMatrix.m_RoutingLayersCount ) + dcell1 = GetCell( row, col, TOP ); if( dcell1 & HOLE ) color = RED; -// dcell0 |= dcell1; - + dcell0 |= dcell1; +#endif if( !color && ( dcell0 & VIA_IMPOSSIBLE ) ) color = BLUE; diff --git a/pcbnew/edtxtmod.cpp b/pcbnew/edtxtmod.cpp index 2bd5d51013..733183f96d 100644 --- a/pcbnew/edtxtmod.cpp +++ b/pcbnew/edtxtmod.cpp @@ -303,54 +303,39 @@ void PCB_BASE_FRAME::ResetTextSize( BOARD_ITEM* aItem, wxDC* aDC ) { wxSize newSize; int newThickness; - TEXTE_PCB* pcbText = NULL; - TEXTE_MODULE* moduleText = NULL; - EDA_TEXT* text; - switch( aItem->Type() ) + if( aItem->Type() == PCB_TEXT_T ) { - case PCB_TEXT_T: newSize = GetDesignSettings().m_PcbTextSize; newThickness = GetDesignSettings().m_PcbTextWidth; - pcbText = static_cast( aItem ); - text = static_cast( pcbText ); - break; + TEXTE_PCB* text = static_cast( aItem ); - case PCB_MODULE_TEXT_T: + // Exit if there's nothing to do + if( text->GetSize() == newSize && text->GetThickness() == newThickness ) + return; + + SaveCopyInUndoList( text, UR_CHANGED ); + text->SetSize( newSize ); + text->SetThickness( newThickness ); + } + + else if( aItem->Type() == PCB_MODULE_TEXT_T ) + { newSize = GetDesignSettings().m_ModuleTextSize; newThickness = GetDesignSettings().m_ModuleTextWidth; - moduleText = static_cast( aItem ); - text = static_cast( moduleText ); - break; + TEXTE_MODULE* text = static_cast( aItem ); - default: - // Exit if aItem is not a text field - return; + // Exit if there's nothing to do + if( text->GetSize() == newSize && text->GetThickness() == newThickness ) + return; + + SaveCopyInUndoList( text->GetParent(), UR_CHANGED ); + text->SetSize( newSize ); + text->SetThickness( newThickness ); } - - // Exit if there's nothing to do - if( text->GetSize() == newSize && text->GetThickness() == newThickness ) + else return; - // Push item to undo list - switch( aItem->Type() ) - { - case PCB_TEXT_T: - SaveCopyInUndoList( pcbText, UR_CHANGED ); - break; - - case PCB_MODULE_TEXT_T: - SaveCopyInUndoList( moduleText->GetParent(), UR_CHANGED ); - break; - - default: - break; - } - - // Apply changes - text->SetSize( newSize ); - text->SetThickness( newThickness ); - if( aDC ) m_canvas->Refresh(); diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index c9d7df189d..68e00856f9 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -572,6 +572,9 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in syncLayerWidgetLayer(); syncRenderStates(); + // Update the tracks / vias available sizes list: + ReCreateAuxiliaryToolbar(); + // Update the RATSNEST items, which were not loaded at the time // BOARD::SetVisibleElements() was called from within any PLUGIN. // See case RATSNEST_VISIBLE: in BOARD::SetElementVisibility() diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index d042b72db2..c0b1d65688 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -29,7 +29,7 @@ */ #include - + #include #include #include @@ -146,7 +146,8 @@ wxString PCB_BASE_FRAME::SelectFootprintFromLibBrowser() wxString fpid; - viewer->ShowModal( &fpid, this ); + int ret = viewer->ShowModal( &fpid, this ); + (void) ret; // make static analyser quiet //DBG(printf("%s: fpid:'%s'\n", __func__, TO_UTF8( fpid ) );) diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 4b813f5d98..0012efdfa9 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -581,6 +581,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_MODEDIT_CHECK: + // Currently: not implemented break; case ID_MODEDIT_EDIT_MODULE_PROPERTIES: diff --git a/pcbnew/tool_modedit.cpp b/pcbnew/tool_modedit.cpp index c3819d1bb7..94ca85c075 100644 --- a/pcbnew/tool_modedit.cpp +++ b/pcbnew/tool_modedit.cpp @@ -1,10 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2012 Wayne Stambaugh - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -137,10 +137,12 @@ void FOOTPRINT_EDIT_FRAME::ReCreateHToolbar() m_mainToolBar->AddTool( ID_MODEDIT_PAD_SETTINGS, wxEmptyString, KiBitmap( options_pad_xpm ), _( "Pad settings" ) ); +#if 0 // Currently there is no check footprint function defined, so do not show this tool m_mainToolBar->AddSeparator(); m_mainToolBar->AddTool( ID_MODEDIT_CHECK, wxEmptyString, KiBitmap( module_check_xpm ), _( "Check footprint" ) ); +#endif // after adding the buttons to the toolbar, must call Realize() to reflect the changes m_mainToolBar->Realize();