BOOL ClsPanel::OnGetMinSize( ClsSize& szMinSize ) { // Use the minimum button size. szMinSize.CX() = szMinSize.CY() = 0; m_pPanelCaption->OnGetMinSize( szMinSize ); // Store the button height. m_nCaptionHeight = szMinSize.CY(); return TRUE; }
LRESULT ClsPanel::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) { // What's up? switch ( uMsg ) { case WM_SETFONT: // Pass to the client and the caption // button. if ( m_pPanelCaption ) m_pPanelCaption->SendMessage( WM_SETFONT, wParam, lParam ); if ( m_pClient ) m_pClient->SendMessage( WM_SETFONT, wParam, lParam ); m_hFont = ( HFONT )wParam; // Do we have a panel caption? if ( m_pPanelCaption ) { // Get the minimum size of the // panel caption. ClsSize sz; ClsRect rc = GetClientRect(); m_pPanelCaption->OnGetMinSize( sz ); // Save the new value. m_nCaptionHeight = sz.CY(); // Simulate a resize of the control. This will // re-evaluate the caption and client positions. OnSize( 0, rc.Width(), rc.Height()); // Make sure our parent, which _MUST_ // be a ClsPanelBar or drived object, // relayouts it's panels. ClsPanelBar *pParent = reinterpret_cast<ClsPanelBar *>( GetParent()); if ( pParent ) pParent->LayoutPanels(); } break; case WM_GETFONT: // Return the stored font. return ( LRESULT )m_hFont; } // Pass to the base class. return ClsWindow::WindowProc( uMsg, wParam, lParam ); }
// For the layout engine. BOOL ClsFlatButton::OnGetMinSize( ClsSize& szMinSize ) { // Add room for the frame. szMinSize.CX() += ::GetSystemMetrics( SM_CXFRAME ) * 3; // For vista and up we use different numbers. if ( ClsGetApp()->GetMajorVersion() >= 6 ) { szMinSize.CY() += ::GetSystemMetrics( SM_CYFRAME ) * 1 + 4; } else { szMinSize.CY() += ::GetSystemMetrics( SM_CYFRAME ) * 3; } // Images? int cxi = 0, cyi = 0; if ( m_hImages && ImageList_GetImageCount( m_hImages )) { // Get the image size. ImageList_GetIconSize( m_hImages, &cxi, &cyi ); // Make room. cxi += 4; // Add sizes. szMinSize.CX() += cxi; szMinSize.CY() += cyi; } // Do we have a caption? ClsString str( GetSafeHWND()); if ( str.GetStringLength()) { // Setup the DC. ClsGetDC dc( this ); ClsFont font; GetFont( font ); ClsSelector sel( &dc, font ); // Measure the caption. ClsRect rc; dc.DrawText( str, rc, DT_CALCRECT ); // Add the width of the caption. szMinSize.CX() += rc.Width() + 4; // Adjust the height if necessary. if ( rc.Height() > cyi ) szMinSize.CY() += rc.Height() - cyi; } return TRUE; }
// Get the minimum size. BOOL ClsLTab::OnGetMinSize( ClsSize& szMinSize ) { // Adjust an empty rectangle to include the // tab and frame sizes. ClsRect rc( 0, 0, 0, 0 ); AdjustRect( TRUE, rc ); // We need two pixels of extra room on the tab-side. We need // this because the TCM_ADJUSTRECT message creates a rectangle // which is two pixels closer to the tabs than to the other // rectangle sides. DWORD dwStyle = GetStyle(); if (( dwStyle & TCS_BUTTONS ) != TCS_BUTTONS ) { // When we are vertical we grow two pixels // wider. Otherwise we grow two pixels higher. if ( dwStyle & TCS_VERTICAL ) rc.Right() += 2; else rc.Bottom() += 2; } // The size of the resulting rectangle is the // total size of the tabs including frames etc. szMinSize = rc.Size(); // Iterate the members. ClsTMember *pMember; int cx = 0, cy = 0; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // Initialize structure. ClsSize sz( 0, 0 ); // Get dimensions. if ( pMember->m_pMember->OnGetMinSize( sz )) { // Any larger values? if ( sz.CX() > cx ) cx = sz.CX(); if ( sz.CY() > cy ) cy = sz.CY(); } } // Store values. szMinSize.Add( cx, cy ); return TRUE; }
// For the layout engine. BOOL ClsSplitter::OnGetMinSize( ClsSize& szMinSize ) { // Setup values. szMinSize.CX() = szMinSize.CY() = SPLITTER_SIZE; return TRUE; }
// Calculate the minimum size of a // vertical group. BOOL ClsLayoutEngine::GroupVMinSize( ClsSize& szMinSize ) { // Reset values. m_nFixedSize = m_nFullWeight = 0; // Query minimum sizes. if ( MaxMinSize() == FALSE ) return FALSE; // Iterate members. ClsMember *pMember; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // Is it a spacing member? if (( pMember->m_dwFlags & ClsMember::MF_SPACING ) != ClsMember::MF_SPACING ) { // Is it a equal height group? if ( m_dwFlags & LF_EQUALHEIGHT ) // Make the group it's minimum height the // member it's minimum height. pMember->m_nMinHeight = m_nMaxMinHeight; } } // Iterate members. UINT nWidth = 0, nHeight = 0; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // Does the member have fixed minimum dimensions? if (( pMember->m_dwFlags & ClsMember::MF_ASKMIN ) != ClsMember::MF_ASKMIN) { // Is it a fixed height member? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDHEIGHT ) // Increase the group it's fixed height. m_nFixedSize += pMember->m_nFixedHeight; else { // Increase the group height and total weight. nHeight += pMember->m_nMinHeight; m_nFullWeight += pMember->m_nWeight; } } else { // Is it a fixed height member? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDHEIGHT ) { // Make the fixed height the minimum height. m_nFixedSize += pMember->m_nMinHeight; pMember->m_nFixedHeight = pMember->m_nMinHeight; } else { // Increase the group height and total weight. nHeight += pMember->m_nMinHeight; m_nFullWeight += pMember->m_nWeight; } } // Does the member have fixed minimum dimensions? if (( pMember->m_dwFlags & ClsMember::MF_ASKMIN ) != ClsMember::MF_ASKMIN ) { // Does it have a fixed width? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDWIDTH ) { // Store the width when it is larger than // the width sofar. if ( pMember->m_nFixedWidth > nWidth ) nWidth = pMember->m_nFixedWidth; } else { // Store the width when it is larger than // the width sofar. if ( pMember->m_nMinWidth > nWidth ) nWidth = pMember->m_nMinWidth; } } else { // Does it have a fixed width? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDWIDTH ) // Make the fixed width the minimum width. pMember->m_nFixedWidth = pMember->m_nMinWidth; // Store the width when it is larger than the width // sofar. if ( pMember->m_nMinWidth > nWidth ) nWidth = pMember->m_nMinWidth; } } // Add the offsets etc. to the sizes. The result will be the total // group minimum dimensions. nHeight += m_nFixedSize + ( m_rcOffsets.Top() + m_rcOffsets.Bottom() + (( m_Members.GetSize() - 1 ) * m_nSpacing )); nWidth += ( m_rcOffsets.Left() + m_rcOffsets.Right()); // Adjust for the frame. if ( m_bFrameGroup && m_Frame.GetSafeHWND()) { nWidth += ( ::GetSystemMetrics( SM_CXEDGE )) * 2 + ( m_nSpacing * 2 ); nHeight += ::GetSystemMetrics( SM_CYEDGE ) + ( m_nFontHeight + ( m_nSpacing * 2 )); } // Store the values. szMinSize.CX() = max( 1, nWidth ); szMinSize.CY() = max( 1, nHeight ); // Success... return TRUE; }
// Calculate the minumum size of a // horizontal group. BOOL ClsLayoutEngine::GroupHMinSize( ClsSize& szMinSize ) { // Reset values. m_nFullWeight = m_nFixedSize = 0; // Query minimum sizes. if ( MaxMinSize() == FALSE ) return FALSE; // Scan through the members. ClsMember *pMember; UINT nWidth = 0, nHeight = 0; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // Is this a spacing member? if (( pMember->m_dwFlags & ClsMember::MF_SPACING ) != ClsMember::MF_SPACING ) { // No. If this group has equal widths we set the // witdth of the member to the group width. if ( m_dwFlags & LF_EQUALWIDTH ) pMember->m_nMinWidth = m_nMaxMinWidth; } // Does the member have fixed minimum dimensions? if (( pMember->m_dwFlags & ClsMember::MF_ASKMIN ) != ClsMember::MF_ASKMIN ) { // No. Is it a fixed width object? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDWIDTH ) // Increase the group it's total fixed width. m_nFixedSize += pMember->m_nFixedWidth; else { // Increase the groups width and the total // weight. nWidth += pMember->m_nMinWidth; m_nFullWeight += pMember->m_nWeight; } } else { // Is it a fixed width member? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDWIDTH ) { // Increase the total fixed width by the member // it's minimum width. m_nFixedSize += pMember->m_nMinWidth; pMember->m_nFixedWidth = pMember->m_nMinWidth; } else { // Increase the group width and the total weight. nWidth += pMember->m_nMinWidth; m_nFullWeight += pMember->m_nWeight; } } // Does the member have fixed minimum dimensions? if (( pMember->m_dwFlags & ClsMember::MF_ASKMIN ) != ClsMember::MF_ASKMIN ) { // Is it a fixed height object? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDHEIGHT ) { // Store the member height when it is larger than // the height sofar. if ( pMember->m_nFixedHeight > nHeight ) nHeight = pMember->m_nFixedHeight; } else { // Store the member minimum height when it is larger // than the height sofar. if ( pMember->m_nMinHeight > nHeight ) nHeight = pMember->m_nMinHeight; } } else { // Is it a fixed height object? if ( pMember->m_dwFlags & ClsMember::MF_FIXEDHEIGHT ) // Store the minimum height as the fixed height. pMember->m_nFixedHeight = pMember->m_nMinHeight; // Store the height when it is larger than // the height sofar. if ( pMember->m_nMinHeight > nHeight ) nHeight = pMember->m_nMinHeight; } } // Add the offsets etc. to the sizes. The result will be the total // group minimum dimensions. nWidth += m_nFixedSize + ( m_rcOffsets.Left() + m_rcOffsets.Right() + (( m_Members.GetSize() - 1 ) * m_nSpacing )); nHeight += ( m_rcOffsets.Top() + m_rcOffsets.Bottom()); // Adjust for the frame. if ( m_bFrameGroup && m_Frame.GetSafeHWND()) { nWidth += ( ::GetSystemMetrics( SM_CXEDGE ) * 2 ) + ( m_nSpacing * 2 ); nHeight += ::GetSystemMetrics( SM_CYEDGE ) + ( m_nFontHeight + ( m_nSpacing * 2 )); } // Store the values. szMinSize.CX() = max( 1, nWidth ); szMinSize.CY() = max( 1, nHeight ); // Success... return TRUE; }
// Scale a vertical group. void ClsLayoutEngine::ScaleVGroup() { // Find out the group domain. ClsRect rc = GetWindowRect(); // Calculate offsets. UINT nLeftOff = rc.Left() + m_rcOffsets.Left(); UINT nTopOff = rc.Top() + m_rcOffsets.Top(); // Calculate the effective height // in which the objects are scaled. UINT nEffHeight = ( rc.Height() - ((( m_Members.GetSize() - 1 ) * m_nSpacing ) + m_rcOffsets.Top() + m_rcOffsets.Bottom())); UINT nEffWidth = ( rc.Width() - ( m_rcOffsets.Left() + m_rcOffsets.Right())); // Decrease the effective height with // the total fixed height. nEffHeight -= m_nFixedSize; // Any framing? if ( m_bFrameGroup && m_Frame.GetSafeHWND()) { // Reposition and resize the // frame object. ResizeGroupFrame(); // Adjust offsets. nLeftOff += ::GetSystemMetrics( SM_CXEDGE ) + m_nSpacing; nTopOff += m_nFontHeight + m_nSpacing; // And sizes. nEffWidth -= ( ::GetSystemMetrics( SM_CXEDGE ) * 2 ) + ( m_nSpacing * 2 ); nEffHeight -= ::GetSystemMetrics( SM_CYEDGE ) + m_nFontHeight + ( m_nSpacing * 2 ); } // Scale the objects. ScaleGroup( nEffHeight ); // Iterate members. ClsMember *pMember; UINT nMemberWidth, nMemberHeight, nTotal = 0; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // Calculate object dimensions. nMemberWidth = ( pMember->m_dwFlags & ClsMember::MF_FIXEDWIDTH ) ? pMember->m_nFixedWidth : nEffWidth; if ( pMember->m_dwFlags & ClsMember::MF_FIXEDHEIGHT ) nMemberHeight = pMember->m_nFixedHeight; else { nMemberHeight = pMember->m_nScaledSize; nTotal += nMemberHeight; } // Adjust when necessary. This may get a somewhat ugly // result in some cases. if ( pMember == m_Members.GetLast()) { // Was the member scaled to large? if ( nTotal > nEffHeight ) nMemberHeight -= ( nTotal - nEffHeight ); else { // If the member does not have a fixed height we stretch // it to fill the area. if ( ! ( pMember->m_dwFlags & ClsMember::MF_FIXEDHEIGHT )) { if ( nTotal < nEffHeight ) nMemberHeight += ( nEffHeight - nTotal ); } } } // Align (if necessary). UINT nLeftAdjust; if ( pMember->m_dwFlags & ClsMember::MF_ALIGN ) nLeftAdjust = max( nEffWidth - nMemberWidth, 0 ); else nLeftAdjust = 0; // Spacing member? if (( pMember->m_dwFlags & ClsMember::MF_SPACING ) != ClsMember::MF_SPACING ) { // Setup object. ClsRect points( nLeftOff + nLeftAdjust, nTopOff, nLeftOff + nLeftAdjust + nMemberWidth, nTopOff + nMemberHeight ); // Extra lines? if ( pMember->m_nExtraLines ) { if ( pMember->m_nLineSize == 0 ) { // Compute the line size. ClsGetDC dc( pMember->m_pMember ); ClsSelector sel( &dc, ( HFONT )pMember->m_pMember->SendMessage( WM_GETFONT )); ClsSize sz = dc.GetTextExtent( _T( "W" ), 1 ); pMember->m_nLineSize = sz.CY(); } // OK? if ( pMember->m_nLineSize ) // Add extra height. points.Bottom() += ( pMember->m_nExtraLines * pMember->m_nLineSize ) + 4; } // Convert the screen coordinates // to the target client. GetParent()->ScreenToClient( points ); // Layout the member. pMember->m_pMember->MoveWindow( points, FALSE ); // If this member is a layout engine force // it to re-layout it's members. if ( pMember->m_pMember->SendMessage( WM_ISLAYOUTENGINE )) pMember->m_pMember->SendMessage( WM_RELAYOUT ); } // Increase top offset. nTopOff += ( nMemberHeight + m_nSpacing ); } }
// Window procedure override. Handles layout engine private messages. LRESULT ClsLayoutEngine::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) { // Interpred message. switch ( uMsg ) { case WM_CREATE: { // Get the default font height used // by the layout control. This information // is needed if the control font is not // set. ClsGetDC dc( this ); ClsSize sz = dc.GetTextExtent( _T( "W" ), 1 ); m_nFontHeight = sz.CY(); break; } case WM_GETFONT: // Valid font? return ( LRESULT )( m_Font.IsValid() ? ( HFONT )m_Font : NULL ); case WM_SETFONT: { // Detach old font. m_Font.Detach(); // Valid? if ( wParam ) { // Attach the new font. m_Font.Attach(( HFONT )wParam, FALSE ); // Set the font to the frame // if it exists. if ( m_Frame.GetSafeHWND()) m_Frame.SetFont( &m_Font, FALSE ); // Pass this message to all our members // when they do not have a font set. ClsMember *pMember; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // Skip spacing members. if (( pMember->m_dwFlags & ClsMember::MF_SPACING ) != ClsMember::MF_SPACING ) { // Does it have a font? if ( pMember->m_pMember->SendMessage( WM_GETFONT ) == NULL ) // No. Set it. pMember->m_pMember->SendMessage( WM_SETFONT, wParam, MAKELPARAM( FALSE, 0 )); } } // Pickup the font height. ClsGetDC dc(this); ClsSelector sel( &dc, ( HFONT )wParam ); ClsSize sz = dc.GetTextExtent( _T( "W" ), 1 ); // Store the height. m_nFontHeight = sz.CY(); m_dwFlags &= ~LF_DIMENSIONED; } break; } case WM_ISLAYOUTENGINE: // Yes, we really are a layout engine... return TRUE; case WM_ORGANIZE: // Organize the members. m_dwFlags &= ~LF_ORGANIZED; OrganizeMembers(); return TRUE; case WM_GETCONTROLS: // Add members to the passed list. GetControls(( ClsLinkedList<ClsCNode> * )lParam ); return TRUE; case WM_ERRORS: // Return error bool. return ( LRESULT )(( BOOL )( m_dwFlags & LF_ADDERROR )); //case WM_SIZE: // Resize the frame. // if ( m_bFrameGroup && m_Frame.GetSafeHWND()) // { // ClsRect rc; // GetClientRect( rc ); // m_Frame.MoveWindow( rc, FALSE ); // } // return 0; case WM_RELAYOUT: // Group dimensioned? When ever a group contents // has changed we need to call the OnGetMinSize() // method before we re-layout. This is to make sure // the layout engine always works with the latest // information. if (( m_dwFlags & LF_DIMENSIONED ) != LF_DIMENSIONED ) { ClsSize szMinSize( 0, 0 ); // OK? if ( OnGetMinSize( szMinSize ) == FALSE ) return FALSE; } // Is this the master group? if ( m_dwFlags & LF_MASTER ) { // Organized? if (( m_dwFlags & LF_ORGANIZED ) != LF_ORGANIZED ) OrganizeMembers(); // Get the parent it's client rectangle. ClsRect rc = GetParent()->GetClientRect(); // Re-size the group. MoveWindow( rc, FALSE ); } // Scale the group members. if ( m_bIsHorizontal ) ScaleHGroup(); else ScaleVGroup(); // Master group? if ((( m_dwFlags & LF_MASTER ) == LF_MASTER ) && GetParent()->IsWindowVisible()) // Force the parent to redraw. GetParent()->RedrawWindow( NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); return TRUE; case WM_SHOWMEMBERS: { // Show/Hide members. ClsMember *pMember; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // A spacing member? if (( pMember->m_dwFlags & ClsMember::MF_SPACING ) != ClsMember::MF_SPACING ) { if ( pMember->m_pMember->SendMessage( WM_ISLAYOUTENGINE )) pMember->m_pMember->SendMessage( WM_SHOWMEMBERS, wParam ); else { pMember->m_pMember->ShowWindow( wParam ? SW_SHOW : SW_HIDE ); if ( wParam ) pMember->m_pMember->UpdateWindow(); } } } // Show/Hide the frame. if ( m_bFrameGroup && m_Frame.GetSafeHWND()) { m_Frame.ShowWindow( wParam ? SW_SHOW : SW_HIDE ); if ( wParam ) m_Frame.UpdateWindow(); } return TRUE; } case WM_REFRESH: { // Do longer dimensioned or organized... m_dwFlags &= ~( LF_ORGANIZED | LF_DIMENSIONED ); // Refresh layout engine members. ClsMember *pMember; for ( pMember = m_Members.GetFirst(); pMember; pMember = m_Members.GetNext( pMember )) { // A spacing member? if (( pMember->m_dwFlags & ClsMember::MF_SPACING ) != ClsMember::MF_SPACING ) { // Is it a layout engine? if ( pMember->m_pMember->SendMessage( WM_ISLAYOUTENGINE )) pMember->m_pMember->SendMessage( WM_REFRESH ); } } // Are we the master? if ( m_dwFlags & LF_MASTER ) // Layout the group. SendMessage( WM_RELAYOUT ); return TRUE; } } // Call the base class. return ClsWindow::WindowProc( uMsg, wParam, lParam ); }
// Called after ClsDialog has distributed the dialog // font to it's children. virtual void OnFontDistributed() { // Setup static controls. Attach them to the objects and // add them to the layout engine controls. for ( int i = 0; i < 5; i++ ) { m_Statics[ i ].Attach( GetDlgItemHandle( IDC_STATIC_1 + i )); m_Left.AddSpacingMember(); m_Left.AddMember( &m_Statics[ i ], NULL, ATTR_FixMinSize, TRUE, ATTR_RightAlign, TRUE, TAG_END ); m_Left.AddSpacingMember(); } // Add the controls to the layout engine controls. m_Right.AddMember( &m_Find, NULL, TAG_END ); m_Right.AddMember( &m_Type, NULL, TAG_END ); m_Right.AddMember( &m_Folder, NULL, TAG_END ); m_Right.AddMember( &m_Proc, NULL, ATTR_UseControlSize, TRUE, TAG_END ); m_StatBut.AddMember( &m_Occ, NULL, TAG_END ); m_StatBut.AddMember( &m_About, NULL, ATTR_UseControlSize, TRUE, ATTR_FixMinWidth, TRUE, TAG_END ); m_StatBut.AddMember( &m_Go, NULL, ATTR_UseControlSize, TRUE, ATTR_FixMinWidth, TRUE, TAG_END ); m_Right.AddMember( &m_StatBut, NULL, TAG_END ); // Get the minimum size of the "m_Right" layout-engine without // the checkboxes. ClsSize szRight; m_Right.OnGetMinSize( szRight ); // Add the checkboxes. m_Right.AddMember( &m_Recur, NULL, ATTR_FixMinWidth, TRUE, TAG_END ); m_Right.AddMember( &m_Case, NULL, ATTR_FixMinWidth, TRUE, TAG_END ); // Combine left and right layout-engine controls. m_LeftRight.AddMember( &m_Left, NULL, ATTR_FixMinWidth, TRUE, ATTR_FixHeight, szRight.CY(), TAG_END ); m_LeftRight.AddMember( &m_Right, NULL, TAG_END ); // Setup the master layout engine. m_Master.AddMember( &m_LeftRight, NULL, ATTR_FixMinHeight, TRUE, TAG_END ); m_Master.AddMember( &m_List, NULL, TAG_END ); // Any errors? if ( m_Master.Error()) { // Bye... EndDialog( TRUE ); return; } // Compute the minimum size of the master group. if ( m_Master.OnGetMinSize( m_MinSize ) == FALSE ) { // Bye... EndDialog( 0 ); return; } // Add frame and caption sizes so that we know the minimum // size of the dialog. m_MinSize.CY() += ( ::GetSystemMetrics( SM_CYFRAME ) * 2 ) + ::GetSystemMetrics( SM_CYCAPTION ); m_MinSize.CX() += ::GetSystemMetrics( SM_CXFRAME ) * 2; // Relayout the master layout engine control. m_Master.Relayout(); // No thread running. m_bSearchInProgress = FALSE; // Call the base class. ClsSizeDialog::OnFontDistributed(); }