Forum
Please
Log In
to post a new message or reply to an existing one. If you are not registered, please
register.
NOTE: Some forums may be read-only if you are not currently subscribed to
our technical support services.
Subject |
Author |
Date |
|
Eric guez
|
Mar 30, 2010 - 4:51 AM
|
Hi,
I changed CExtGridWnd colors by overloading OnSiwGetSysColor. Now, I want to change a CExtGridCellComboBox colors, how can I do that ?
Thanks!
|
|
Technical Support
|
Mar 30, 2010 - 5:54 AM
|
Most of the grid cells are based on the CExtGridCellEx grid cell class, including the CExtGridCellComboBox class. All the CExtGridCellEx -based grid cells support both the text and background color customization. Please use the CExtGridCell::TextColorSet() and CExtGridCell::BackColorSet() methods for colorizing grid cells.
|
|
Eric guez
|
Mar 30, 2010 - 6:30 AM
|
It changes the "in grin" color, but not the drop-down list colors. The dropdown list have the grid custom colors (set by OnSiwGetSysColor), and I want to change them.
|
|
Technical Support
|
Mar 30, 2010 - 7:30 AM
|
You should use the custom drown popup list box items. You can override the CExtGridCell::OnPopupListBoxItemDraw() virtual method in your grid cell class or the CExtGridWnd::OnGridCellPopupListBoxItemDraw() virtual method in your grid control class.
|
|
Eric guez
|
Mar 31, 2010 - 2:49 AM
|
CExtGridWnd::OnGridCellPopupListBoxItemDraw() worked great !
See you soon (I have many more questions :) )
|
|
Krister Goodh
|
Mar 29, 2010 - 2:59 AM
|
Hello! When i remove items from a CExtPropertyStore ther’s normally no problem. After removing the items, using m_SomeCategoryPtr->ItemRemove(); I do m_PGC.PropertyStoreSynchronize(); to show the changes. However if I click on a read-oply property (enables user to copy value to clipboard, from a CExtGridCellString ) and then, while cursor is visible, execute the code above the call to m_PGC.PropertyStoreSynchronize() activates code that fails with the message: ASSERT_VALID fails with illegal vtable pointer.
ASSERT_VALID fails with illegal vtable pointer.
Second Chance Assertion Failed: File C:\Program\FOSS Software Inc\Prof-UIS\Src\ExtPropertyGridWnd.cpp, Line 7194 from CExtPropertyGridWnd::PropertyItemFromTreeItem() (the call is passing CExtGridInplaceEdit::DoEndEdit() ). - Am I removing items in the wrong way?
|
|
Krister Goodh
|
Mar 29, 2010 - 9:59 AM
|
A partial workaround is to do: if (may_delete_or_edit) m_PGC.PropertyStoreSet(NULL);
m_Store.DoSomeChanges();
if (may_delete_or_edit) m_PGC.PropertyStoreSet(&m_Store); This does not work for an edit field that is not disabled for editing. Still asserts. It also has the efect that if I drop down a combo box, and while it:s dropped down delete 2 items moving a checklist into the position previously occupied by the combo, the checklist will be repopulated with the entries from the combo box!!!
|
|
Technical Support
|
Mar 29, 2010 - 12:23 PM
|
Thank you for reporting us this issue. To fix it, please update the source code for the following method: void CExtPropertyGridCtrl::PropertyStoreSynchronize()
{
__EXT_DEBUG_GRID_ASSERT_VALID( this );
_EnsureInitialized();
CExtPropertyGridWnd * pActivePGW = GetActiveGrid();
if( pActivePGW->GetSafeHwnd() != NULL )
{
HWND hWndInpalaceEditor = pActivePGW->GetSafeInplaceActiveHwnd();
if( hWndInplaceEditor != NULL )
{
::SendMessage( hWndInplaceEditor, WM_CANCELMODE, 0L, 0L );
pActivePGW->SendMessage( WM_CANCELMODE );
}
}
CExtPropertyStore * pCurrentPS = PropertyStoreGet();
CExtPropertyItem * pRestoreFocusPI = NULL;
if( pCurrentPS != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pCurrentPS );
if( pActivePGW->GetSafeHwnd() != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
HTREEITEM htiFocus = pActivePGW->ItemFocusGet();
if( htiFocus != NULL )
// pRestoreFocusPI = pActivePGW->PropertyItemFromTreeItem( htiFocus );
pRestoreFocusPI = pActivePGW->_PropertyItemFromTreeItem_Impl( htiFocus );
}
}
CTypedPtrArray < CPtrArray, CExtPropertyGridWnd * > arrGrids;
OnPgcQueryGrids( arrGrids );
INT nGridIdx = 0;
for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
{
CExtPropertyGridWnd * pGrid = arrGrids[ nGridIdx ];
__EXT_DEBUG_GRID_ASSERT_VALID( pGrid );
pGrid->PropertyStoreSynchronizeAll();
} // for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
if( pRestoreFocusPI != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
__EXT_DEBUG_GRID_ASSERT( pActivePGW->GetSafeHwnd() != NULL );
// HTREEITEM htiSetFocus = pActivePGW->PropertyItemToTreeItem( pRestoreFocusPI );
HTREEITEM htiSetFocus = pActivePGW->_PropertyItemToTreeItem_Impl( pRestoreFocusPI );
if( htiSetFocus != NULL )
pActivePGW->ItemFocusSet( htiSetFocus );
}
}
|
|
Krister Goodh
|
Mar 30, 2010 - 3:11 AM
|
Great, this solved the first issue described, which was the most serious. It however does not solve the issue with destroyed value lists. How to reproduce: - Have property tree with two categories, the upper category has two entries, the lower has five entries, the first is a combo box and the 4:th is a drop down check list
- Populate combo with some strings and check list with some strings, make all visible in a
CExtPPVW < CExtPropertyGridCtrlMeterInfo > . - Drop down the combo box and move the mouse over a value
- While the combo is open, let the program remove the upper category and it:s 2 values
- Click on a line in the combo
- Now the values from the combo box will repopulate the drop down check list 3 lines below ??!?
|
|
Technical Support
|
Mar 30, 2010 - 5:54 AM
|
Here is the next improved version of the CExtPropertyGridCtrl::PropertyStoreSynchronize() method which closes any popup windows opened by any property grid cells before updating the property grid control:
void CExtPropertyGridCtrl::PropertyStoreSynchronize()
{
__EXT_DEBUG_GRID_ASSERT_VALID( this );
_EnsureInitialized();
CExtPropertyGridWnd * pActivePGW = GetActiveGrid();
if( pActivePGW->GetSafeHwnd() != NULL )
{
HWND hWndInplaceEditor = pActivePGW->GetSafeInplaceActiveHwnd();
if( hWndInplaceEditor != NULL )
{
::SendMessage( hWndInplaceEditor, WM_CANCELMODE, 0L, 0L );
pActivePGW->SendMessage( WM_CANCELMODE );
}
}
if( CExtGridCell::g_pCellMenuTracking != NULL )
{
CExtGridDataProvider * pDP = CExtGridCell::g_pCellMenuTracking->DataProviderGet();
if( pDP != NULL && pDP->IsKindOf( RUNTIME_CLASS(CExtTreeGridDataProvider) ) )
{
CExtPropertyGridWnd * pActiveGrid = GetActiveGrid();
if( pActiveGrid != NULL )
{
CExtGridDataProvider & _ActiveDP = pActiveGrid->OnGridQueryDataProvider();
if( LPVOID(&_ActiveDP) == LPVOID(pDP) )
CExtPopupMenuWnd::CancelMenuTracking();
}
}
}
CExtPropertyStore * pCurrentPS = PropertyStoreGet();
CExtPropertyItem * pRestoreFocusPI = NULL;
if( pCurrentPS != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pCurrentPS );
if( pActivePGW->GetSafeHwnd() != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
HTREEITEM htiFocus = pActivePGW->ItemFocusGet();
if( htiFocus != NULL )
// pRestoreFocusPI = pActivePGW->PropertyItemFromTreeItem( htiFocus );
pRestoreFocusPI = pActivePGW->_PropertyItemFromTreeItem_Impl( htiFocus );
}
}
CTypedPtrArray < CPtrArray, CExtPropertyGridWnd * > arrGrids;
OnPgcQueryGrids( arrGrids );
INT nGridIdx = 0;
for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
{
CExtPropertyGridWnd * pGrid = arrGrids[ nGridIdx ];
__EXT_DEBUG_GRID_ASSERT_VALID( pGrid );
pGrid->PropertyStoreSynchronizeAll();
} // for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
if( pRestoreFocusPI != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
__EXT_DEBUG_GRID_ASSERT( pActivePGW->GetSafeHwnd() != NULL );
// HTREEITEM htiSetFocus = pActivePGW->PropertyItemToTreeItem( pRestoreFocusPI );
HTREEITEM htiSetFocus = pActivePGW->_PropertyItemToTreeItem_Impl( pRestoreFocusPI );
if( htiSetFocus != NULL )
pActivePGW->ItemFocusSet( htiSetFocus );
}
}
Please also make the CExtGridCell::g_pCellMenuTracking static property public .
|
|
Krister Goodh
|
Mar 30, 2010 - 6:25 AM
|
When I reach this code provided by you: if( CExtGridCell::g_pCellMenuTracking != NULL )
{
CExtGridDataProvider * pDP = CExtGridCell::g_pCellMenuTracking->DataProviderGet();
if( pDP != NULL && pDP->IsKindOf( RUNTIME_CLASS(CExtTreeGridDataProvider) ) ) the variable pDP points to a CExtGridDataProviderMemory and the last if clause in my snip above is not taken -> problem can still be reproduced.
|
|
Technical Support
|
Mar 31, 2010 - 6:41 AM
|
Yes, you are right. The pDP->IsKindOf( RUNTIME_CLASS(CExtTreeGridDataProvider) ) condition is not needed.
|
|
Krister Goodh
|
Apr 12, 2010 - 1:00 AM
|
// Ups’ didn’t see your answer since it was above my question... Well it’s not the runtime class test that is false, but rather _ActiveDP == pDP . That’s why I experimentally replaced the test by the test _ActiveDP = pDP->m_pOuterDataProvider . Could you please verify that this is correct? (See the code posted (i think) below at "Mar 30, 2010 - 6:54 AM".)
|
|
Krister Goodh
|
Apr 28, 2010 - 7:13 AM
|
Have you had time to look at this? The code in profuis289(2010-04-22) seems to be the same (-> i guess not working according to description above). /J
|
|
Krister Goodh
|
Mar 30, 2010 - 6:54 AM
|
Would this work???? (In CExtPropertyGridCtrl::PropertyStoreSynchronize() , slight patch on the code provided by you.) if( CExtGridCell::g_pCellMenuTracking != NULL )
{
CExtGridDataProvider * pDP = CExtGridCell::g_pCellMenuTracking->DataProviderGet();
if( pDP != NULL
&& pDP->IsKindOf( RUNTIME_CLASS(CExtGridDataProviderMemory) )
&& pDP->m_pOuterDataProvider != NULL )
{
CExtPropertyGridWnd * pActiveGrid = GetActiveGrid();
if( pActiveGrid != NULL )
{
CExtGridDataProvider& _ActiveDP = pActiveGrid->OnGridQueryDataProvider(); CExtTreeGridDataProvider * pTreeDP =
DYNAMIC_DOWNCAST( CExtTreeGridDataProvider, pDP->m_pOuterDataProvider ); if( LPVOID(&_ActiveDP) == LPVOID(pTreeDP) )
CExtPopupMenuWnd::CancelMenuTracking();
}
}
}
|
|
Krister Goodh
|
Mar 30, 2010 - 3:30 AM
|
I have a screen shot of the event, and will send this by mail.
|
|
Krister Goodh
|
Mar 29, 2010 - 3:15 AM
|
How to reproduce (using "Win32 Static MBCS Debug", ProfUIS289smd.lib in project "Property Grid Sample": - In
BOOL CMainDlg::OnInitDialog() , add to the end the line SetTimer(134,3000,NULL); - Add function
void CMainDlg::OnTimer(UINT nIDEvent)
{
CExtResizableDialog ::OnTimer(nIDEvent);
if (nIDEvent == 134)
{
m_Btn1.SelectedStateSet( false );
CheckMarkOnButtonChanged();
}
} - Start aplication and quickly click on a property value so that the edit cursor is visible (ex: "RadiusInner")
- Wait for the timer to expire, this will reproduce my problem.
|
|
David Baginski
|
Mar 23, 2010 - 1:27 PM
|
Hello, I have seen two other posts with this question but I still have trouble making the buttons display in the toolbar. I have created a new project using the ProfUIS application wizard. I then turned the Empty controlbar in the sample code into a ExtPropertyGridCtrl. This works fine. I then derived my own class from CExtPropertyGridCtrl and overrode the virtual method OnPgcCreateBars() to add the application about button to the toolbar. However, the button does not display although the separator I added does display. It appears that the button is in the toolbar however because the status bar will update the displayed message when I hover the cursor over the location that I expect the button to be displayed. However, the button does not appear to be painting. Do I need to override the OnCmd method before the button will paint? Here is my code for OnPgcCreateBars(): bool CMyPropertyGridCtrl::OnPgcCreateBars()
{
ASSERT_VALID( this );
if( ! CExtPropertyGridCtrl::OnPgcCreateBars() )
return false;
CWnd * pWnd = GetChildByRTC( RUNTIME_CLASS(CExtPropertyGridToolBar) );
if( pWnd != NULL )
{
ASSERT_VALID( pWnd );
CExtPropertyGridToolBar * pToolBar = STATIC_DOWNCAST( CExtPropertyGridToolBar, pWnd );
pToolBar->m_bForceBalloonGradientInDialogs = false;
VERIFY( pToolBar->InsertButton( -1 ) );
VERIFY( pToolBar->InsertButton( -1, ID_APP_ABOUT ) );
}
return true;
}
I can send you the whole project if that would help.
Thanks, Dave
|
|
David Baginski
|
Mar 25, 2010 - 12:17 PM
|
OK it works now, thank you!
If anybody else is looking at this, here is the source for the other two methods that are required to get user buttons to work on the property grid toolbar. In this case, the button I am using is defined in the IDR_MAINFRAME resource (about). You will need to include the correct resource here for your application. And you will need to replace ID_APP_ABOUT with the correct command as well.
void CMyPropertyGridCtrl :: PreSubclassWindow()
{
CExtPropertyGridCtrl::PreSubclassWindow();
ASSERT( ! m_strCommandProfile.IsEmpty() );
VERIFY(
g_CmdManager->UpdateFromToolBar(
LPCTSTR( m_strCommandProfile ),
IDR_MAINFRAME
)
);
}
BOOL CMyPropertyGridCtrl::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
switch( nID )
{
case ID_APP_ABOUT:
switch( nCode )
{
case CN_COMMAND:
CExtPaintManager::stat_PassPaintMessages();
dynamic_cast<CProfPropGridApp*>(AfxGetApp())->OnAppAbout();
break;
case CN_UPDATE_COMMAND_UI:
//TRACE("CN_UPDATE_COMMAND_UI\n");
ASSERT( pExtra != NULL );
((CCmdUI*)pExtra)->Enable( TRUE );
break;
} // switch( nCode )
return TRUE;
} // switch( nID )
return CExtPropertyGridCtrl::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
|
|
Technical Support
|
Mar 25, 2010 - 2:34 AM
|
There is a ready-to-use example of how to insert custom buttons into a property grid’s toolbar. It’s in the Prof-UIS source code for the CExtPPVW template decorator class which adds printing and print previewing features to other controls. A specialized version of this class (CExtPPVW < CExtPropertyGridCtrl > ) inserts print and print preview toolbar buttons. This is the last class in the ../Prof-UIS/Include/ExtPrint.h and ../Prof-UIS/Src/ExtPrint.cpp files. There are three important methods:
1) The CExtPPVW < CExtPropertyGridCtrl > :: PreSubclassWindow() virtual method updates the property grid’s command profile with the icons from the IDR_EXT_TOOLBAR_PPW toolbar resource. You didn’t do that. This is why you didn’t see the icon on your About toolbar button. The CExtBarButton toolbar button objects inside the CExtToolControlBar toolbar control does not contain icons. The toolbar buttons used the command icons stored in the command manager. Your About toolbar button is not able to find the ID_APP_ABOUT command icon in the command manager.
2) The CExtPPVW < CExtPropertyGridCtrl > :: OnPgcCreateBars() virtual method inserts the toolbar buttons. It’s similar to your method. Your method is OK.
3) The CExtPPVW < CExtPropertyGridCtrl > :: OnCmdMsg() virtual method handles and updates the toolbar button commands. You should add the similar method into your property grid class.
|
|
David Baginski
|
Mar 23, 2010 - 1:32 PM
|
Second question, if I have to override OnCmdMsg, what should I add to route the ID_APP_ABOUT command?
|
|
Claudiu Tanasescu
|
Mar 23, 2010 - 1:06 PM
|
How use CExtGridWnd with MDI ?
You can help me with a easy sample project with how to use grid controls(prof-uis) in the MDI applications(created without prof-uis wizard ) ?
Exist a tutorial with this topic?
|
|
Technical Support
|
Mar 23, 2010 - 2:01 PM
|
If you are not using the MFC’s document/view architecture, then you can create a CExtGridWnd as a child of the MDI child frame window. This grid control will play a role of the view window. If you are using the MFC’s document/view architecture, then you can create a CExtGridWnd as a child of the view window. You will need to resize the grid control and pass the focus from the view window manually in this case. Please take a look at the following test project:
http://www.prof-uis.com/download/forums/MDIGridTest.zip
|
|
Claudiu Tanasescu
|
Mar 25, 2010 - 10:45 AM
|
|
|
Robert Webb
|
Mar 22, 2010 - 1:29 AM
|
Hi, Seems like this should be the simplest thing, but when I call SetTitle() for my CDocument, neither the MDI tab label nor the overall window title are updated. How can I force these things to update? The MDI tab label I can get to redraw with "m_MDITabs.InvalidateRect(NULL)", but I think sometimes if the title is longer than it was, then the size of the tab is not increased to match. As for the overall window title (at the top of the ribbon bar), I don’t really want to redraw the whole ribbon bar just to update the title. What’s the right way to do this? Thanks, Rob.
|
|
Technical Support
|
Mar 22, 2010 - 11:36 AM
|
If the main frame caption or MDI child frame caption has changed, Prof-UIS is able to intercept the standard WM_SETTEXT window message and update ribbon bar caption, MDI tab items, skinned window non client area caption, everything else. But the CDocument object is handle-less. Please override the CDocument::SetTitle() virtual method, invoke the parent class method and then invalidate the ribbon bar and update MDI tabs using the CExtTabWnd::UpdateTabWnd() method.
|
|
Robert Webb
|
Mar 21, 2010 - 8:35 PM
|
Some observations about ribbon bar layouts. These are things that stand out as poor uses of space, and don’t seem to happen with MS Word: It seems as the ribbon bar is reduced in size and groups collapse to single buttons, that it is not possible for a group to collapse to a single button without all subsequent groups doing the same (all groups to the right of it). This is not how MS Word does it. If a large group is collapsed, then subsequent groups may stay expanded if there’s room. Eg the View tab in MS Word. Shrink the window until the "Show/Hide" group collapses into a single button. Subsequent groups all stay full size. MS Word is also able to reduce some buttons from large to small within a group without having to reduce all of them as Prof-UIS does. Eg if there are 5 or 6 buttons, MS Word will first shrink the last 3 to small, leaving the first 2 or 3 large. Prof-UIS always collapses all at once, even when there are separators within the group. MS Word also appears to NEVER collapse a group to a single button if it would not lead to a saving of space. Eg a group with a single button and not-too-long text. Similarly, there is no point reducing buttons from large with text below to small with text at the side unless it will save space. I’ve seen Prof-UIS make that adjustment even though it results in the group being larger! That is, since the text is now beside the icon rather than below it, you may end up with a wider group even though the button icon has shrunk (also because text that was over two lines below a large icon becomes text in a single line, making it longer). This also seems to be avoided in MS Word. I’m pretty sure BCG and CodeJock handle these things correctly. Thanks, Rob.
|
|
Technical Support
|
Apr 5, 2010 - 5:20 AM
|
We can modify the RibbonBar sample application for you. Please choose some ribbon tab page and tell us which buttons should collapse in some specific order. We will modify this sample application for you by coding the button behavior rules you need.
|
|
Robert Webb
|
Apr 6, 2010 - 2:06 AM
|
Thanks. Looks like the Page Layout --> Arrange group would be a good one. It has seven buttons. Let’s number them 1 through 7 from left to right. As the window is made smaller, here’s the order of what should happen: (1) All buttons start off big. (2) Last 3 buttons (5,6,7) are made small with text. (3) Buttons 2,3,4 are also made small with text. (4) Buttons 5,6,7 are made small without text. (5) Buttons 2,3,4 are also made small without text. (6) Whole group is collapsed to a single button. Currently we see steps 1, 3, 4, and 6. That is, all the last six buttons collapse at once from large to small with text (skipping step 2). And the whole group collapses to a single button before buttons 2,3,4 are shrunk from small with text to small without text. I still suggest that the above sequence should happen automatically for any collection of buttons with equal priority rules, and I believe this is how other ribbon bars behave, ie the developer does not have to write special code to make it happen. I will be wanting to automate it for all our controls. Hopefully I will be able to do that based on your changes to the ribbon sample code. Thanks, Rob.
|
|
Robert Webb
|
Apr 13, 2010 - 7:19 PM
|
How’s this going? Let me know if anything wasn’t clear in my explanation. Thanks, Rob.
|
|
Technical Support
|
Apr 15, 2010 - 2:10 PM
|
We are sorry for the delay with this answer. Please update the source code for the CMainFrame::_InitRibbonNode_PageLayout_Arrange() method in the RibbonBar sample application:
CExtRibbonNode * CMainFrame::_InitRibbonNode_PageLayout_Arrange()
{
CExtRibbonNodeGroup * pRibbonGroup =
new CExtRibbonNodeGroup( ID_RIBBON_PAGE_PL_ARRANGE );
pRibbonGroup->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("ZA") ) ), false );
{ // block: coding rules
pRibbonGroup->RibbonILE_SetCollapsed( __EXT_RIBBON_ILE_MIN );
} // block: coding rules
VERIFY( pRibbonGroup->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_LARGE) ) );
pRibbonGroup->m_iconBig.m_bmpNormal.Make32();
pRibbonGroup->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
VERIFY( pRibbonGroup->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_SMALL) ) );
pRibbonGroup->m_iconSmall.m_bmpNormal.Make32();
pRibbonGroup->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->SetTextInToolbar( _T("Arrange") );
CExtRibbonNodeDialogLauncher * pRibbonDLB =
new CExtRibbonNodeDialogLauncher( ID_RIBBON_PAGE_PL_ARRANGE );
pRibbonDLB->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("PA") ) ), false );
pRibbonGroup->InsertNode( NULL, pRibbonDLB );
//////////////////// 1 ////////////////////
CExtRibbonNode * pNodePositionBox =
new CExtRibbonNode( ID_ARRANGE_POSITION_LARGE, 0, NULL, 0, _T("Position") );
pNodePositionBox->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("PO") ) ), false );
pNodePositionBox->RibbonILE_RuleRemoveSmallILV();
pNodePositionBox->RibbonILE_RuleRemoveNormalILV();
VERIFY( pNodePositionBox->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_POSITION_LARGE) ) );
pNodePositionBox->m_iconBig.m_bmpNormal.Make32();
pNodePositionBox->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->InsertNode(
NULL,
pNodePositionBox
);
//////////////////// 2, 3, 4 ////////////////////
CExtRibbonNode * pNodeBringToFront =
new CExtRibbonNode( ID_ARRANGE_BTF_LARGE, 0, NULL, 0, _T("Bring to\nFront") );
pNodeBringToFront->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AF") ) ), false );
// pNodeBringToFront->RibbonILE_RuleRemoveSmallILV();
{ // block: coding rules
CArray < DWORD, DWORD > & arrRules = pNodeBringToFront->RibbonILE_RuleArrayGeta();
arrRules.RemoveAll();
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-2, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-4, __EXT_RIBBON_ILV_SIMPLE_SMALL, false ) );
} // block: coding rules
VERIFY( pNodeBringToFront->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_LARGE) ) );
pNodeBringToFront->m_iconBig.m_bmpNormal.Make32();
pNodeBringToFront->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
VERIFY( pNodeBringToFront->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_SMALL) ) );
pNodeBringToFront->m_iconSmall.m_bmpNormal.Make32();
pNodeBringToFront->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->InsertNode(
NULL,
pNodeBringToFront
);
CExtRibbonNode * pNodeSendToBack =
new CExtRibbonNode( ID_ARRANGE_STB_LARGE, 0, NULL, 0, _T("Send to\nBack") );
pNodeSendToBack->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AE") ) ), false );
// pNodeSendToBack->RibbonILE_RuleRemoveSmallILV();
{ // block: coding rules
CArray < DWORD, DWORD > & arrRules = pNodeSendToBack->RibbonILE_RuleArrayGet();
arrRules.RemoveAll();
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-2, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-4, __EXT_RIBBON_ILV_SIMPLE_SMALL, false ) );
} // block: coding rules
VERIFY( pNodeSendToBack->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_STB_LARGE) ) );
pNodeSendToBack->m_iconBig.m_bmpNormal.Make32();
pNodeSendToBack->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
VERIFY( pNodeSendToBack->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_STB_SMALL) ) );
pNodeSendToBack->m_iconSmall.m_bmpNormal.Make32();
pNodeSendToBack->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->InsertNode(
NULL,
pNodeSendToBack
);
CExtRibbonNode * pNodeTextWrapping =
new CExtRibbonNode( ID_ARRANGE_TW_LARGE, 0, NULL, 0, _T("Text\nWrapping") );
pNodeTextWrapping->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("TW") ) ), false );
// pNodeTextWrapping->RibbonILE_RuleRemoveSmallILV();
{ // block: coding rules
CArray < DWORD, DWORD > & arrRules = pNodeTextWrapping->RibbonILE_RuleArrayGet();
arrRules.RemoveAll();
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-2, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-4, __EXT_RIBBON_ILV_SIMPLE_SMALL, false ) );
} // block: coding rules
VERIFY( pNodeTextWrapping->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_TW_LARGE) ) );
pNodeTextWrapping->m_iconBig.m_bmpNormal.Make32();
pNodeTextWrapping->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
VERIFY( pNodeTextWrapping->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_TW_SMALL) ) );
pNodeTextWrapping->m_iconSmall.m_bmpNormal.Make32();
pNodeTextWrapping->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->InsertNode(
NULL,
pNodeTextWrapping
);
//////////////////// 5, 6, 7 ////////////////////
CExtRibbonNode * pNodeAlign =
new CExtRibbonNode( ID_ARRANGE_ALIGN_LARGE, 0, NULL, 0, _T("Align") );
pNodeAlign->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AA") ) ), false );
{ // block: coding rules
CArray < DWORD, DWORD > & arrRules = pNodeAlign->RibbonILE_RuleArrayGet();
arrRules.RemoveAll();
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-1, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-3, __EXT_RIBBON_ILV_SIMPLE_SMALL, false ) );
} // block: coding rules
VERIFY( pNodeAlign->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ALIGN_LARGE) ) );
pNodeAlign->m_iconBig.m_bmpNormal.Make32();
pNodeAlign->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
VERIFY( pNodeAlign->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ALIGN_SMALL) ) );
pNodeAlign->m_iconSmall.m_bmpNormal.Make32();
pNodeAlign->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->InsertNode(
NULL,
pNodeAlign
);
CExtRibbonNode * pNodeGroup =
new CExtRibbonNode( ID_ARRANGE_GROUP_LARGE, 0, NULL, 0, _T("Group") );
VERIFY( pNodeGroup->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_GROUP_LARGE) ) );
pNodeGroup->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AG") ) ), false );
{ // block: coding rules
CArray < DWORD, DWORD > & arrRules = pNodeGroup->RibbonILE_RuleArrayGet();
arrRules.RemoveAll();
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-1, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-3, __EXT_RIBBON_ILV_SIMPLE_SMALL, false ) );
} // block: coding rules
pNodeGroup->m_iconBig.m_bmpNormal.Make32();
pNodeGroup->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
VERIFY( pNodeGroup->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_GROUP_SMALL) ) );
pNodeGroup->m_iconSmall.m_bmpNormal.Make32();
pNodeGroup->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->InsertNode(
NULL,
pNodeGroup
);
CExtRibbonNode * pNodeRotate =
new CExtRibbonNode( ID_ARRANGE_ROTATE_LARGE, 0, NULL, 0, _T("Rotate") );
pNodeRotate->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AY") ) ), false );
{ // block: coding rules
CArray < DWORD, DWORD > & arrRules = pNodeRotate->RibbonILE_RuleArrayGet();
arrRules.RemoveAll();
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-1, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-3, __EXT_RIBBON_ILV_SIMPLE_SMALL, false ) );
} // block: coding rules
VERIFY( pNodeRotate->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ROTATE_LARGE) ) );
pNodeRotate->m_iconBig.m_bmpNormal.Make32();
pNodeRotate->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
VERIFY( pNodeRotate->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ROTATE_SMALL) ) );
pNodeRotate->m_iconSmall.m_bmpNormal.Make32();
pNodeRotate->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->InsertNode(
NULL,
pNodeRotate
);
return pRibbonGroup;
}
|
|
Robert Webb
|
Apr 15, 2010 - 7:51 PM
|
Ah, thanks, this is very helpful! I should be able to figure out how to automate it from this. I still think this kind of section-by-section collapsing should happen by default, even when two items have the same effective level. One thing I don’t understand. Why is __EXT_RIBBON_ILE_MAX set to 10? That puts a pretty small limit on the number of levels available. It also appears that 5 bits are set aside for this value (__EXT_RIBBON_BIT_COUNT_ILE), so why not allow all 32 levels that could be represented? That is, set __EXT_RIBBON_ILE_MAX to 31. And finally, it seems there are 26 bits used for the visual level, but aren’t there typically less visual levels than effective ones? Just 3 in fact, as far as I know. Why not give more bits to the effective level? Thanks, Rob.
|
|
Robert Webb
|
Apr 21, 2010 - 8:27 PM
|
Any thoughts on this? I’ve written a function to create nice rules for buttons in ribbon groups, but I ran into the foreseen problem of the very limited number of possible effective levels. One of our groups has 16 buttons (9 buttons followed by a separator and then another 7). There are only 11 effective levels available (0 - 10). The minimum one is used to collapse the whole group to a button. The maximum one represents all buttons at full size. This leaves 9 levels (1 - 9). Half are required for dropping from full size to normal, and half are required to drop from normal to small, so really only 4 groupings of buttons can have different levels. Grouping 3 at a time (3 buttons appear in a column and should collapse together), and taking note of the separator, our above ribbon group requires 6 groupings. So I ask again, why is __EXT_RIBBON_ILE_MAX set to 10 when there are enough bits set aside for 32 levels? Why are more bits set aside for visual levels, even though visual levels are accessed via effective levels so there’s never a need for more visual levels than effective levels. Is there a reason not to just change __EXT_RIBBON_BIT_COUNT_ILE from 5 to 16 and __EXT_RIBBON_ILE_MAX from 10 to 65535? (Or better, (1 << __EXT_RIBBON_BIT_COUNT_ILE) - 1). Thanks, Rob.
|
|
Technical Support
|
Mar 22, 2010 - 11:38 AM
|
Sorry but we do not agree. Everything can be coded using ribbon command node rules. You can change visual informativeness (small - small 16x16 icon only, middle - small 16x16 icon and text at right, big - large 32x32 icon and 1 or 2 lines of text at bottom) of any node anytime. It’s possible to change visual informativeness of buttons at left earlier than buttons at right in the same or different ribbon groups. Everything is defined by effective informativeness level to visual informativeness level pair of numbers. Each node supports array of such pairs. If the ribbon bar width is changed, then it tries to find the larges effective informativeness level for all the nodes/buttons when all the buttons are visible and does not intersect with the right side if the ribbon bar. But each effective informativeness level of each node/button has corresponding visual level. If the buttons at the left side still use the big visual level at a smaller effective level, then the buttons at left kept larger then buttons at right. The same rules applied to the button groups. But the button groups also support the collapsed state which is linked to effective informativeness level. This means you can collapse button groups at left later than button groups at right or vice versa. Of course, you can avoid group collapsing at all what is really recommended for button groups containing one always big button or three always small/middle buttons.
|
|
Robert Webb
|
Mar 22, 2010 - 11:40 PM
|
Is there any documentation or sample code related to these ribbon bar rules? I can’t find any. The documentation has a brief page about RibbonILE_RuleArrayGet(), but it really doesn’t explain what it does. It returns an array of integers. By default they seem to be "73, 40, 7". The only way to make any sense of these is to look inside the Prof-UIS code. Seems the bottom 5 bits are used as the effective level. The rest is used for the visible level. I think it ends up meaning that an effective level of 9 makes it large, a level of 8 leads to normal size, and a level of 7 leads to small icons with no text. Is that right? I’m guessing that a single effective level is tried at once for all controls within a group, which is why you can’t shrink some buttons and not others when they have the same rules. To say that the poor uses of space as I described "can" be coded in Prof-UIS may be true, but only by pushing much of the responsibility back onto us the programmers, and require us to use undocumented features. The whole point of the ribbon bar, as I see it, is to AUTOMATICALLY come up with nice layouts. It’s nice if we have the power to tell it that one item is more important than another, and should thus shrink later, but the Prof-UIS solution seems overly convoluted and difficult to use, and doesn’t provide good defaults if the programmer doesn’t want to have to think about how every element should arrange itself. I think all the things I described above should happen by default, as I believe they do when using other ribbon bar toolkits. Rob.
|
|
Robert Webb
|
Apr 1, 2010 - 1:14 AM
|
Thoughts? I still don’t really know how to make buttons within a group shrink three at a time rather than all at once, as seems to happen automatically in other ribbon bar implementations. There may be a convoluted way by playing with the rules, but there’s no explanation anywhere of how to use these rules. Rob.
|
|
Offer Har
|
Mar 21, 2010 - 6:33 AM
|
Dear Support, We have a grid with a CExtGridCellDropListComboBox with long texts. We made the column wide, so the text will be visible, however the drop-list width does not get the same width as the column, and the texts are cut. Even worse, at a certain columns width, the drop-list width get narrower and narrower then the column width... as we make the column wider, the drop-list get narrower.... Please fix. Thanks, Ron.
|
|
Technical Support
|
Mar 23, 2010 - 10:58 AM
|
|
|
Offer Har
|
Mar 23, 2010 - 12:07 PM
|
But there is a bug... read my mail... Please make the column very wide - half a screen.... 1000 pixels wide and you’ll see that the drop list is not 1000 pixels wide!
|
|
Technical Support
|
Mar 23, 2010 - 12:57 PM
|
Yes, you are right. We should extend the maximal available size of popup list boxes to the work area size of the monitor where the popup list box should appear. Please update the source code for the following method: CSize CExtGridCell::OnPopupListBoxQueryMaxSize(
CExtPopupInplaceListBox & wndListBox,
CExtGridCell::TrackCellStateInfo_t & _tcsi
)
{
// returned CSize( 0, 0 ) means no limit in size - what means use monitor limits
__EXT_DEBUG_GRID_ASSERT_VALID( this );
__EXT_DEBUG_GRID_ASSERT( (&_tcsi.m_cell) == this );
__EXT_DEBUG_GRID_ASSERT_VALID( (&_tcsi.m_wndGrid) );
__EXT_DEBUG_GRID_ASSERT( wndListBox.GetSafeHwnd() != NULL );
CSize _size = _tcsi.m_wndGrid.OnGridCellPopupListBoxQueryMaxSize( wndListBox, _tcsi );
if( _size.cx >= 0 && _size.cy >= 0 )
return _size;
CRect rcCellScreen = _tcsi.m_rcCell;
_tcsi.m_wndGrid.ClientToScreen( &rcCellScreen );
CExtPaintManager::monitor_parms_t _mp;
CExtPaintManager::stat_GetMonitorParms( _mp, rcCellScreen );
CRect rcAvailableSpaces(
rcCellScreen.left - _mp.m_rcWorkArea.left - 1,
rcCellScreen.top - _mp.m_rcWorkArea.top - 1,
_mp.m_rcWorkArea.right - rcCellScreen.right - 1,
_mp.m_rcWorkArea.bottom - rcCellScreen.bottom - 1
);
CSize sizeAvailable = rcAvailableSpaces.Size();
return sizeAvailable;
}
|
|
Offer Har
|
Mar 24, 2010 - 9:05 AM
|
Dear Support, Your solution still have some bug. I had a case that the column width was ~700, and the sizeAvailable.cx was only 212.... Please check (I have lots if images showing the bug if you want...) However, I added this line before the return, and I can live with it for now...:
sizeAvailable.cx = max(200, rcCellScreen.Width()); I realy do not understand why you make all the computations there for this simple task. Please fix for the next version. Ron.
|
|
Technical Support
|
Mar 25, 2010 - 2:37 AM
|
Could you please comment the sizeAvailable.cx = max(200, rcCellScreen.Width()); suggested line of code and create a screen shot demonstrating the problem for us?
|
|
Offer Har
|
Mar 25, 2010 - 2:50 AM
|
Dear Support, I’m out of the office for 10 days. The bug is there... very easy to reproduce... the picture will just show you how the width is less then the cell width. I also saw it in the cx variable that the value was not close to the cell width. Ron.
|
|
Offer Har
|
Mar 22, 2010 - 12:52 PM
|
Dear Support, Please try and widen the combo’s column... up to half screen, and you’ll see it. Ron.
|
|
Technical Support
|
Mar 23, 2010 - 9:27 AM
|
|
|
Offer Har
|
Mar 23, 2010 - 9:58 AM
|
Dear Support, I need the drop-list width to be computed as follows: 1. If the cell width is less then X then X 2. If the cell width is more then X, then the cell’s width. If this is too complicated, then I need the drop-list to be exactly the same width as the cell. This is not what i see now when the cell is very wide (half screen for example)
|
|
Technical Support
|
Mar 22, 2010 - 11:39 AM
|
|
|
Jens Oehler
|
Mar 19, 2010 - 2:23 PM
|
Dear Technical Support, in the Version 2.88 the bool CExtControlBar::DockControlBarLTRB(
int nPercentToOccupy, // greater then zero and less then one hundred
CExtControlBar * pBarTarget,
UINT nDockBarID, // = AFX_IDW_DOCKBAR_BOTTOM
bool bRecalcLayout // = true
)
seems not working as decribed. It looks that the nPercentToOccupy parameter doesn´t have effect. All the bars docked with this function are splitted by 50%. You can easiely produce this problem by using your MDI Sample. I have changed the lines 366-392 in Mainfrm.cpp from
if( ! CExtControlBar::ProfileBarStateLoad(
this,
pApp->m_pszRegistryKey,
pApp->m_pszProfileName,
pApp->m_pszProfileName,
&m_dataFrameWP
)
)
{
DockControlBar( &m_wndMenuBar );
DockControlBar( &m_wndToolBar );
DockControlBar( &m_wndToolBarUiLook, AFX_IDW_DOCKBAR_RIGHT );
m_wndResizableBar0.SetInitDesiredSizeVertical( CSize( 120, 120 ) );
m_wndResizableBar1.SetInitDesiredSizeHorizontal( CSize( 120, 120 ) );
m_wndResizableBar2.SetInitDesiredSizeVertical( CSize( 120, 120 ) );
m_wndResizableBar3.SetInitDesiredSizeHorizontal( CSize( 120, 120 ) );
m_wndResizableBar4.SetInitDesiredSizeVertical( CSize( 120, 120 ) );
m_wndResizableBar0.DockControlBar( AFX_IDW_DOCKBAR_LEFT, 1, this, true );
m_wndResizableBar1.DockControlBarLTRB( 50, &m_wndResizableBar0, AFX_IDW_DOCKBAR_BOTTOM, true );
m_wndResizableBar3.DockControlBar( AFX_IDW_DOCKBAR_BOTTOM, 2, this, false );
m_wndResizableBar2.DockControlBarLTRB( 50, &m_wndResizableBar3, AFX_IDW_DOCKBAR_LEFT, true );
m_wndResizableBar4.DockControlBar( AFX_IDW_DOCKBAR_RIGHT, 1, this, false );
m_wndResizableBarTA.DockControlBar( AFX_IDW_DOCKBAR_RIGHT, 3, this, false );
RecalcLayout();
} to /*
if( ! CExtControlBar::ProfileBarStateLoad(
this,
pApp->m_pszRegistryKey,
pApp->m_pszProfileName,
pApp->m_pszProfileName,
&m_dataFrameWP
)
)
*/
{
DockControlBar( &m_wndMenuBar );
DockControlBar( &m_wndToolBar );
DockControlBar( &m_wndToolBarUiLook, AFX_IDW_DOCKBAR_RIGHT );
m_wndResizableBar0.SetInitDesiredSizeVertical( CSize( 120, 120 ) );
m_wndResizableBar1.SetInitDesiredSizeHorizontal( CSize( 120, 120 ) );
m_wndResizableBar2.SetInitDesiredSizeVertical( CSize( 120, 120 ) );
m_wndResizableBar3.SetInitDesiredSizeHorizontal( CSize( 120, 120 ) );
m_wndResizableBar4.SetInitDesiredSizeVertical( CSize( 120, 120 ) );
m_wndResizableBar0.DockControlBar( AFX_IDW_DOCKBAR_LEFT, 1, this, true );
m_wndResizableBar1.DockControlBarLTRB( 10, &m_wndResizableBar0, AFX_IDW_DOCKBAR_BOTTOM, true );
m_wndResizableBar3.DockControlBar( AFX_IDW_DOCKBAR_BOTTOM, 2, this, false );
m_wndResizableBar2.DockControlBarLTRB( 90, &m_wndResizableBar3, AFX_IDW_DOCKBAR_LEFT, true );
m_wndResizableBar4.DockControlBar( AFX_IDW_DOCKBAR_RIGHT, 1, this, false );
m_wndResizableBarTA.DockControlBar( AFX_IDW_DOCKBAR_RIGHT, 3, this, false );
RecalcLayout();
}
Both produce the same layout on the user interface. Playing with the percentage in the function calls doesn’t shows changes. Regards Jens
|
|
Technical Support
|
Mar 22, 2010 - 1:17 PM
|
We successfully reproduced this issue. Thank you. It’s fixed in the latest Prof-UIS 2.89 pre-release version. Please drop us an e-mail to the support mail box at this web site so we will provide you with the source code update.
|
|
Jens Oehler
|
Mar 20, 2010 - 2:15 PM
|
In our software we only use CExtControlBar::DockControlBarInnerOuter() for the first bar to dock. For all other control bars we use CExtControlBar::DockControlBarLTRB(). With Prof-UIS 2.84 the control bars are docked with the given percentage, given in the nPercentToOccupy parameter. With version 2.88 this is broken. Every docked bar splits his parent in equal sizes and the nPercentToOccupy parameter are not working.
|
|
Technical Support
|
Mar 20, 2010 - 11:17 AM
|
The CExtControlBar::DockControlBar() is provided for backward compatibility with very old Prof-UIS versions so you should not use it. Please use the CExtControlBar::DockControlBarInnerOuter() method instead so the CExtControlBar::DockControlBarLTRB() method’s nPercentToOccupy parameter can affect the size of control bars.
|
|
Emmanuel V.
|
Mar 19, 2010 - 9:48 AM
|
Hi, Default behavior to go next next active cell is by pressing UP or DOWN key (__EGWS_BSE_WALK_VERT is set). When I click on ENTER it only validate current cell (not going to next one : in my case the one bellow current one). I want to be able to validate current active cell by pressing TAB key, and go automatically to next cell (in my case the one bellow current one). How can I do this ? On the same way, when pressing ENTER, how going automatically to next cell (in my case the one bellow current one) ? Thanks.
|
|
Technical Support
|
Mar 19, 2010 - 12:15 PM
|
Here is the code which adds the Tab key based in-row navigation in the grid control:
CExtGridWnd & wndGrid = . . .
wndGrid.m_dwSupportedAccelCommands |= __EGSA_IN_ROW_TAB_NEXT | __EGSA_IN_ROW_TAB_PREV;
|
|
Emmanuel V.
|
Mar 22, 2010 - 2:22 AM
|
|
|
Emmanuel V.
|
Mar 19, 2010 - 10:22 AM
|
OK, I had solved one problem : adding __EGWS_BSE_EDIT_RETURN_MOVES_NEXT_ROW style, when pressing ENTER key, next row is automatically selected. How can I have same behavior with TAB key ? Thanks.
|
|
Robert Webb
|
Mar 18, 2010 - 7:24 PM
|
Hi, When a ribbon bar group is small, sometimes the label at the bottom is truncated and can’t be fully read. It would be nice if a tooltip appeared in this situation when the mouse was hovered over the truncated text, showing the full text. Thanks, Rob.
|
|
Technical Support
|
Mar 22, 2010 - 1:29 PM
|
We would be very happy to leave the new behavior of ribbon button group captions because it meets the Microsoft Ribbon UI Design Guidelines document. If the caption text is lengthy, then it must be displayed completely and the ribbon button group content must be centered horizontally. We suspect you have too many ribbon buttons and elements on some/all ribbon tab pages in your application. Not all the elements should be placed directly on tab pages. You can organize some subset of commands into drop down or split buttons. You can have some ribbon galleries never displayed as in-pace gallery controls on ribbon tab pages and have them always displayed as drop-down buttons showing popup gallery menus. This is what you can see in any application from the Microsoft Office 2007 / 2010. The never collapsed ribbon button groups are supported in the latest Prof-UIS 2.89. We added a new CExtRibbonNode::RibbonILE_SetCollapsedNever() method and it’s invoked in the CMainFrame::_InitRibbonNode_Insert_Table() methods of the RibbonBar and RibbonBarMDI sample applications: CExtRibbonNodeGroup * pRibbonGroup =
new CExtRibbonNodeGroup( ID_RIBBON_PAGE_INSERT_TABLE );
pRibbonGroup->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("ZA") ) ), false );
VERIFY( pRibbonGroup->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_INSERT_TABLE_LARGE) ) );
pRibbonGroup->m_iconBig.m_bmpNormal.Make32();
pRibbonGroup->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
pRibbonGroup->SetTextInToolbar( _T("Table") );
pRibbonGroup->RibbonILE_SetCollapsedNever(); If the button groups are collapsed into the text-less buttons, then you didn’t specify the caption text. The code above initializes a button group with the Table caption text.
|
|
Robert Webb
|
Mar 22, 2010 - 10:09 PM
|
The new behaviour ruins our layout. I’m not expecting you to remove the new behaviour, but some way to tell it to use the old behaviour instead would be nice. Till then we will need to keep hacking any new Prof-UIS code back to the old way. We don’t use any ribbon galleries. Mostly just buttons and a few text fields. And yes, some of our controls are hidden under drop-downs etc. We do have a lot of controls though, and our users complain about how many mouse-clicks things take, so we don’t like to hide things too deep where possible. We could always shorten our ribbon group names, but it’s better that they’re descriptive. Wasn’t a problem before. Oh, I wasn’t talking about the group-buttons losing text. I meant that the buttons within the group lose their text when the ribbon bar is made small enough, even though the text would easily fit in now that the group is wider due to the group’s own caption. That is, reducing to no-text doesn’t save any space, so it shouldn’t do it. Thanks, Rob.
|
|
Robert Webb
|
Apr 1, 2010 - 1:10 AM
|
Any answer to this? RibbonILE_SetCollapsedNever() looks useful since ProfUIS can’t automatically recognise which groups shouldn’t be collapsed (the ones that won’t save any space by doing so). But with or without this, our layout is now terrible in a smaller window. It was good before the change you made. We just want an option to use the old method. We like descriptive group labels when there’s room, and like them to be truncated when there isn’t. Currently we will have to patch the ProfUIS code back to how it was whenever we get a new version. Rob.
|
|
Technical Support
|
Apr 15, 2010 - 2:09 PM
|
Most of the ribbon button groups in the RibbonBar sample application have approximately the same length short text in their captions. But this text is typically a bit wider than the minimal possible width of the collapsed ribbon group button. The user can see everything and read every collapsed caption. We can make everything even more thin and you will see a lot if ". . . " ellipsis text lines with a few letters before it. We are not sure this is good. Looking from the other side, the last source code update allows you to assign rich ribbon cool tips to the collapsed ribbon button groups. Why not to start using short captions and display rich tooltips with a lot of text information?
|
|
Technical Support
|
Apr 5, 2010 - 11:28 AM
|
Please re-download the latest Prof-UIS source code and add the following virtual method to your ribbon class:
bool C_YOUR_RibbonBar::OnRibbonQueryGroupCaptionTextCompletlyVisible( CExtRibbonButtonGroup * pTBB ) const
{
ASSERT_VALID( this );
ASSERT_VALID( pTBB );
pTBB;
return false;
}
Now the group buttons use the ellipsis effect for long text captions and display tooltips. You can also assign CExtCustomizeCmdScreenTip ribbon screen tips to the ribbon group nodes as it is demonstrated in the comments inside the CMainFrame::_InitRibbonNode_Insert_Table() method in the RibbonBar sample.
|
|
Robert Webb
|
Apr 7, 2010 - 8:08 PM
|
Great! Thank you. One minor point, why OnRibbonQueryGroupCaptionTextCompletlyVisible() rather than OnRibbonQueryGroupCaptionTextCompletelyVisible()? Seems odd to abbreviate such a long function by name just one letter, removing just one "e" from "Completely". Looks like a typo rather than an abbreviation. I haven’t checked out adding a tooltip to the group label yet, but I presume it will always appear once defined? Is there a way to make it only appear when the label is being truncated? Still seems like sensible automatic behaviour. Thanks, Rob.
|
|
Technical Support
|
Apr 8, 2010 - 12:20 PM
|
Thank you for reporting the typo. We fixed it in the latest Prof-UIS 2.89 source code. You can re-download it. If you define a ribbon super tooltip and assign it to a ribbon group button, the super tooltip is always displayed for the ribbon group. This is the default super tooltip behavior for all ribbon buttons. If you does not define a super tooltip, the ribbon group displays a small tooltip with caption text. Yes, this small tooltip is displayed only if the caption text is painted with the ellipsis text effect.
|
|
Robert Webb
|
Apr 8, 2010 - 9:23 PM
|
Thanks! Yep, the ribbon group tooltips when the label is truncated look great. Just one final thing I noticed. Although the group names are now truncated, when the group is made small enough that it collapses to a single button, suddenly the full length text is back, making the groups wider than they were before they collapsed. Significantly wider in some of our cases. This means that several groups suddenly vanish off the end of the bar, even though all the groups just fit when the window was one pixel wider. May I suggest that the group labels still be truncated when the group is collapsed to a single button? Tooltips should again show the full label when truncated. Thanks, Rob.
|
|
Robert Webb
|
Apr 13, 2010 - 7:14 PM
|
Any answer to this? When using OnRibbonQueryGroupCaptionTextCompletelyVisible(), the group captions should also be truncated when the group is collapsed to a single button, but this does not happen, making the single button considerably wider than the expanded group in many cases. Thanks, Rob.
|
|
Robert Webb
|
Apr 21, 2010 - 7:54 PM
|
Still waiting for a response.
|
|
Technical Support
|
Mar 20, 2010 - 11:20 AM
|
It’s not correct to show a tooltip over the caption of a ribbon button painted with the ellipsis effect. It’s also not correct to use the ellipsis effect there. The ribbon UI recommendations require the caption text to be fully visible and the buttons to be centered if the caption is very lengthy. We fixed this issue. Please update the source code for the following two methods: CSize CExtRibbonButtonGroup::OnRibbonCalcLayout(
CDC & dc,
CPoint & ptCalcLayoutOffset,
bool bSetupRects
)
{
ASSERT_VALID( this );
ASSERT( dc.GetSafeHdc() != NULL );
if( ! IsVisible() )
return CSize( 0, 0 );
if( (GetStyle()&TBBS_HIDDEN) != 0 )
return CSize( 0, 0 );
CExtRibbonPage * pRibbonPage = GetRibbonPage();
ASSERT_VALID( pRibbonPage );
INT nDistanceBefore = OnRibbonGetOuterGroupDistance( true );
INT nDistanceAfter = OnRibbonGetOuterGroupDistance( false );
CRect rcCP = OnRibbonGetContentPadding();
if( pRibbonPage->RibbonLayout_GroupCaptionIsTopAligned( this ) )
rcCP.top += pRibbonPage->RibbonLayout_GroupCaptionGetHeight( this );
else
rcCP.bottom += pRibbonPage->RibbonLayout_GroupCaptionGetHeight( this );
if( TopCollapsedStateGet() )
{
CSize _sizeLayout = OnRibbonCalcCollapsedGroupSize( dc );
if( bSetupRects )
{
CRect rcTBB( ptCalcLayoutOffset, _sizeLayout );
rcTBB.OffsetRect( nDistanceBefore, 0 );
SetLayoutRect( dc, rcTBB );
}
_sizeLayout.cx += nDistanceBefore + nDistanceAfter;
ptCalcLayoutOffset.x += nDistanceBefore + nDistanceAfter;
return _sizeLayout;
} // if( TopCollapsedStateGet() )
CPoint ptGroupLayout = ptCalcLayoutOffset;
ptGroupLayout.x += rcCP.left + nDistanceBefore;
ptGroupLayout.y += rcCP.top;
CSize _sizeLayout( 0, 0 );
INT nIndex, nCount = ChildButtonGetCount();
INT nLineWidth = 0, nLineHeight = 0, nMaxLineHeight = 0, nLineHeightSaved = 0,
nMaxAvailableLineHeight = pRibbonPage->RibbonLayout_GetGroupHeight( this ) - rcCP.top - rcCP.bottom;
INT nSizeMinCaptionArea = 0;
CExtBarButton * pLastVisibleTBB = NULL;
for( nIndex = 0; nIndex < nCount; nIndex ++ )
{
CExtBarButton * pTBB = ChildButtonGetAt( nIndex );
ASSERT_VALID( pTBB );
if( bSetupRects )
pTBB->SetWrap( CExtBarButton::__EVT_FLOAT, false );
if( pTBB->IsKindOf( RUNTIME_CLASS(CExtRibbonButtonDialogLauncher) ) )
{
pTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
CSize _sizeTBB = pTBB->RibbonILV_CalcSize( dc, -1 );
if( bSetupRects )
{
CRect rcTBB( 0, 0, _sizeTBB.cx, _sizeTBB.cy );
pTBB->SetLayoutRect( dc, rcTBB );
pTBB->Show( false );
}
nSizeMinCaptionArea += _sizeTBB.cx + 1;
continue;
} // if( pTBB->IsKindOf( RUNTIME_CLASS(CExtRibbonButtonDialogLauncher) ) )
if( ! pTBB->IsVisible() )
continue;
if( (pTBB->GetStyle()&TBBS_HIDDEN) != 0 )
continue;
if( pTBB->IsSeparator() )
{
INT nSeparatorWidth = pTBB->OnRibbonGetSeparatorExtent( true );
CRect rcCpTBB = pTBB->OnRibbonGetContentPadding();
nMaxLineHeight = max( nMaxLineHeight, nLineHeight );
_sizeLayout.cx += nLineWidth + nSeparatorWidth + rcCpTBB.left + rcCpTBB.right;
ptGroupLayout.x += nLineWidth;
ptGroupLayout.y = ptCalcLayoutOffset.y + rcCP.top;
nLineWidth = nLineHeight = 0;
if( bSetupRects )
{
pTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
if( pLastVisibleTBB != NULL )
pLastVisibleTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
pLastVisibleTBB = pTBB;
CRect rcTBB( ptGroupLayout + rcCpTBB.TopLeft(), CSize( nSeparatorWidth, 100 ) );
rcTBB.OffsetRect( -nDistanceBefore, 0 );
pTBB->SetLayoutRect( dc, rcTBB );
}
ptGroupLayout.x += nSeparatorWidth + rcCpTBB.left + rcCpTBB.right;
continue;
} // if( pTBB->IsSeparator() )
CSize _sizeTBB = pTBB->RibbonILV_CalcSize( dc, -1 );
CRect rcCpTBB = pTBB->OnRibbonGetContentPadding();
nLineHeightSaved = nLineHeight;
nLineHeight += _sizeTBB.cy + rcCpTBB.top + rcCpTBB.bottom;
if( nLineHeight > nMaxAvailableLineHeight )
{
nMaxLineHeight = max( nMaxLineHeight, nLineHeightSaved );
_sizeLayout.cx += nLineWidth;
ptGroupLayout.x += nLineWidth;
ptGroupLayout.y = ptCalcLayoutOffset.y + rcCP.top;
nLineWidth = _sizeTBB.cx + rcCpTBB.left + rcCpTBB.right;
nLineHeight = _sizeTBB.cy + rcCpTBB.top + rcCpTBB.bottom;
if( bSetupRects )
{
if( pLastVisibleTBB != NULL )
pLastVisibleTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
else
pTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
pLastVisibleTBB = pTBB;
CRect rcTBB( ptGroupLayout + rcCpTBB.TopLeft(), _sizeTBB );
rcTBB.OffsetRect( -nDistanceBefore, 0 );
pTBB->SetLayoutRect( dc, rcTBB );
}
ptGroupLayout.y += nLineHeight;
} // if( nLineHeight > nMaxAvailableLineHeight )
else
{
if( bSetupRects )
{
pLastVisibleTBB = pTBB;
CRect rcTBB( ptGroupLayout + rcCpTBB.TopLeft(), _sizeTBB );
rcTBB.OffsetRect( -nDistanceBefore, 0 );
pTBB->SetLayoutRect( dc, rcTBB );
}
INT nWidthTBB = _sizeTBB.cx + rcCpTBB.left + rcCpTBB.right;
nLineWidth = max( nLineWidth, nWidthTBB );
nMaxLineHeight = max( nMaxLineHeight, nLineHeight );
ptGroupLayout.y += _sizeTBB.cy + rcCpTBB.top + rcCpTBB.bottom;
} // else from if( nLineHeight > nMaxAvailableLineHeight )
} // for( nIndex = 0; nIndex < nCount; nIndex ++ )
if( bSetupRects && pLastVisibleTBB != NULL )
pLastVisibleTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
_sizeLayout.cx += nLineWidth;
nMaxLineHeight = max( nMaxLineHeight, nLineHeightSaved );
CExtSafeString strCaptionText = GetText();
if( ! strCaptionText.IsEmpty() )
{
strCaptionText.Replace( _T("\r"), _T("") );
strCaptionText.Replace( _T("\n"), _T(" ") );
CFont * pFont = & ( pRibbonPage->PmBridge_GetPM()->m_FontRibbonGroupCaption );
if( pFont->GetSafeHandle() == NULL )
pFont = pRibbonPage->OnGetToolbarFont( false, true, this );
nSizeMinCaptionArea += CExtPaintManager::stat_CalcTextDimension( dc, *pFont, strCaptionText, DT_SINGLELINE|DT_LEFT|DT_TOP|DT_CALCRECT ).Width() + 6;
}
if( nSizeMinCaptionArea > _sizeLayout.cx )
{
INT nShift = ( nSizeMinCaptionArea - _sizeLayout.cx ) / 2;
_sizeLayout.cx = nSizeMinCaptionArea;
if( nShift > 0 && bSetupRects )
{
for( nIndex = 0; nIndex < nCount; nIndex ++ )
{
CExtBarButton * pTBB = ChildButtonGetAt( nIndex );
ASSERT_VALID( pTBB );
if( ! pTBB->IsVisible() )
continue;
if( (pTBB->GetStyle()&TBBS_HIDDEN) != 0 )
continue;
if( pTBB->IsKindOf( RUNTIME_CLASS(CExtRibbonButtonDialogLauncher) ) )
continue;
CRect rcTBB = *pTBB;
rcTBB.OffsetRect( nShift, 0 );
pTBB->SetLayoutRect( dc, rcTBB );
}
}
}
_sizeLayout.cy += nMaxLineHeight;
_sizeLayout.cx += rcCP.left + rcCP.right;
_sizeLayout.cy += rcCP.top + rcCP.bottom;
_sizeLayout.cy -= 2;
if( ParentButtonGet() == NULL
&& _sizeLayout.cx < 40
)
_sizeLayout.cx = 40;
if( bSetupRects )
{
CRect rcTBB( ptCalcLayoutOffset, _sizeLayout );
rcTBB.OffsetRect( nDistanceBefore, 0 );
SetLayoutRect( dc, rcTBB );
}
_sizeLayout.cx += nDistanceBefore + nDistanceAfter;
return _sizeLayout;
}
CSize CExtRibbonButtonToolGroup::OnRibbonCalcLayout(
CDC & dc,
CPoint & ptCalcLayoutOffset,
bool bSetupRects
)
{
ASSERT_VALID( this );
ASSERT( dc.GetSafeHdc() != NULL );
if( ! IsVisible() )
return CSize( 0, 0 );
if( (GetStyle()&TBBS_HIDDEN) != 0 )
return CSize( 0, 0 );
CExtRibbonPage * pRibbonPage = GetRibbonPage();
ASSERT_VALID( pRibbonPage );
INT nDistanceBefore = OnRibbonGetOuterGroupDistance( true );
INT nDistanceAfter = OnRibbonGetOuterGroupDistance( false );
CRect rcCP = OnRibbonGetContentPadding();
if( pRibbonPage->RibbonLayout_GroupCaptionIsTopAligned( this ) )
rcCP.top += pRibbonPage->RibbonLayout_GroupCaptionGetHeight( this );
if( TopCollapsedStateGet() )
{
CSize _sizeLayout = OnRibbonCalcCollapsedGroupSize( dc );
if( bSetupRects )
{
CRect rcTBB( ptCalcLayoutOffset, _sizeLayout );
rcTBB.OffsetRect( nDistanceBefore, 0 );
SetLayoutRect( dc, rcTBB );
}
_sizeLayout.cx += nDistanceBefore + nDistanceAfter;
ptCalcLayoutOffset.x += nDistanceBefore + nDistanceAfter;
return _sizeLayout;
} // if( TopCollapsedStateGet() )
CPoint ptGroupLayout = ptCalcLayoutOffset;
ptGroupLayout.x += rcCP.left + nDistanceBefore;
ptGroupLayout.y += rcCP.top;
CSize _sizeLayout( 0, 0 );
INT nIndex, nCount = ChildButtonGetCount();
INT nLineWidth = 0, nLineHeight = 0, nMaxLineWidth = 0;
INT nSizeMinCaptionArea = 0;
bool bLastWrapPassed = false;
CExtBarButton * pLastVisibleTBB = NULL;
for( nIndex = 0; nIndex < nCount; nIndex ++ )
{
CExtBarButton * pTBB = ChildButtonGetAt( nIndex );
ASSERT_VALID( pTBB );
if( pTBB->IsKindOf( RUNTIME_CLASS(CExtRibbonButtonDialogLauncher) ) )
{
pTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
CSize _sizeTBB = pTBB->RibbonILV_CalcSize( dc, -1 );
if( bSetupRects )
{
CRect rcTBB( 0, 0, _sizeTBB.cx, _sizeTBB.cy );
pTBB->SetLayoutRect( dc, rcTBB );
pTBB->Show( false );
}
nSizeMinCaptionArea += _sizeTBB.cx + 1;
continue;
} // if( pTBB->IsKindOf( RUNTIME_CLASS(CExtRibbonButtonDialogLauncher) ) )
if( ! pTBB->IsVisible() )
continue;
if( (pTBB->GetStyle()&TBBS_HIDDEN) != 0 )
continue;
if( pTBB->IsSeparator() )
{
INT nSeparatorHeight = pTBB->OnRibbonGetSeparatorExtent( false );
CRect rcCpTBB = pTBB->OnRibbonGetContentPadding();
ptGroupLayout.x = ptCalcLayoutOffset.x + rcCP.left;
ptGroupLayout.y += nLineHeight;
_sizeLayout.cy += nLineHeight;
nLineWidth = nLineHeight = 0;
bLastWrapPassed = true;
if( bSetupRects )
{
pTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
if( pLastVisibleTBB != NULL )
pLastVisibleTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
pLastVisibleTBB = pTBB;
CRect rcTBB( ptGroupLayout + rcCpTBB.TopLeft(), CSize( 100, nSeparatorHeight ) );
rcTBB.OffsetRect( -nDistanceBefore, 0 );
pTBB->SetLayoutRect( dc, rcTBB );
}
ptGroupLayout.y += nSeparatorHeight + rcCpTBB.top + rcCpTBB.bottom;
_sizeLayout.cy += nSeparatorHeight + rcCpTBB.top + rcCpTBB.bottom;
continue;
} // if( pTBB->IsSeparator() )
CSize _sizeTBB = pTBB->RibbonILV_CalcSize( dc, -1 );
bool bRibbonWrap = pTBB->RibbonWrapFromILE( pTBB->RibbonILE_Get() );
CRect rcCpTBB = pTBB->OnRibbonGetContentPadding();
INT nWidthTBB = _sizeTBB.cx + rcCpTBB.left + rcCpTBB.right;
INT nHeightTBB = _sizeTBB.cy + rcCpTBB.top + rcCpTBB.bottom;
nLineWidth += nWidthTBB;
nMaxLineWidth = max( nMaxLineWidth, nLineWidth );
nLineHeight = max( nLineHeight, nHeightTBB );
if( bSetupRects )
{
CRect rcTBB( ptGroupLayout + rcCpTBB.TopLeft(), _sizeTBB );
pTBB->SetLayoutRect( dc, rcTBB );
rcTBB.OffsetRect( -nDistanceBefore, 0 );
pTBB->SetWrap( CExtBarButton::__EVT_FLOAT, bRibbonWrap );
pLastVisibleTBB = pTBB;
}
if( bRibbonWrap )
{
ptGroupLayout.x = ptCalcLayoutOffset.x + rcCP.left;
ptGroupLayout.y += nLineHeight;
_sizeLayout.cy += nLineHeight;
nLineWidth = nLineHeight = 0;
bLastWrapPassed = true;
} // if( bRibbonWrap )
else
{
ptGroupLayout.x += nWidthTBB;
bLastWrapPassed = false;
} // else from if( bRibbonWrap )
} // for( nIndex = 0; nIndex < nCount; nIndex ++ )
if( bSetupRects && pLastVisibleTBB != NULL )
pLastVisibleTBB->SetWrap( CExtBarButton::__EVT_FLOAT, true );
if( ! bLastWrapPassed )
_sizeLayout.cy += nLineHeight;
_sizeLayout.cy --;
_sizeLayout.cx += nMaxLineWidth;
CExtSafeString strCaptionText = GetText();
if( ! strCaptionText.IsEmpty() )
{
strCaptionText.Replace( _T("\r"), _T("") );
strCaptionText.Replace( _T("\n"), _T(" ") );
CFont * pFont = & ( pRibbonPage->PmBridge_GetPM()->m_FontRibbonGroupCaption );
if( pFont->GetSafeHandle() == NULL )
pFont = pRibbonPage->OnGetToolbarFont( false, true, this );
nSizeMinCaptionArea += CExtPaintManager::stat_CalcTextDimension( dc, *pFont, strCaptionText, DT_SINGLELINE|DT_LEFT|DT_TOP|DT_CALCRECT ).Width() + 6;
}
if( nSizeMinCaptionArea > _sizeLayout.cx )
{
INT nShift = ( nSizeMinCaptionArea - _sizeLayout.cx ) / 2;
_sizeLayout.cx = nSizeMinCaptionArea;
if( nShift > 0 && bSetupRects )
{
for( nIndex = 0; nIndex < nCount; nIndex ++ )
{
CExtBarButton * pTBB = ChildButtonGetAt( nIndex );
ASSERT_VALID( pTBB );
if( ! pTBB->IsVisible() )
continue;
if( (pTBB->GetStyle()&TBBS_HIDDEN) != 0 )
continue;
if( pTBB->IsKindOf( RUNTIME_CLASS(CExtRibbonButtonDialogLauncher) ) )
continue;
CRect rcTBB = *pTBB;
rcTBB.OffsetRect( nShift, 0 );
pTBB->SetLayoutRect( dc, rcTBB );
}
}
}
_sizeLayout.cx += rcCP.left + rcCP.right;
_sizeLayout.cy += rcCP.top + rcCP.bottom;
if( ParentButtonGet() == NULL
&& _sizeLayout.cx < 40
)
_sizeLayout.cx = 40;
if( bSetupRects )
{
CRect rcTBB( ptCalcLayoutOffset, _sizeLayout );
rcTBB.OffsetRect( nDistanceBefore, 0 );
SetLayoutRect( dc, rcTBB );
}
_sizeLayout.cx += nDistanceBefore + nDistanceAfter;
return _sizeLayout;
}
|
|
Robert Webb
|
Mar 21, 2010 - 8:22 PM
|
Hmm, that’s an interesting solution, but it creates new (worse) problems. Now less groups fit in, so more of them collapse. We have one ribbon page for example with 8 groups. At a certain window size (first one I tried) all 8 groups now collapse to just a single button, with one of them being completely inaccessible off the edge of the ribbon bar, whereas previously all 8 were expanded with room to spare. In fact, one of the groups contains only a single button, which would easily fit in the non-collapsed group, even with caption, without the group being any larger than it is in collapsed form. Elsewhere I see buttons within groups reduced to small icon without text, even though there is plenty of room for the text now that the whole group is wider due to its own caption. It stands out as an obvious poor use of space. I think I regret asking for this now! Is there a way to choose the old behaviour? The old behaviour with a tooltip for the group name when truncated would be perfect. Even better if the full text is displayed only when it would not cause other contractions within the page (ie apply all normal layout logic first, then if there’s room, make some groups wider to fit their full captions). Thanks, Rob.
|
|
Jeroen Walter
|
Mar 18, 2010 - 6:43 AM
|
using profuis 2.87 CExtSpinWnd only draws correctly of the autobuddy style is set. The method CExtSpinWnd::_IsBuddyToEdit does not take into account that I may have set the buddy via the SetBuddy() method. Please fix this.
|
|
Jeroen Walter
|
Mar 24, 2010 - 9:49 AM
|
Thanks, However the way you use GetClassName is errorprone, as GetClassName truncates the returned class name. For example, if I have a registered window class name "EditableCombobox" then this method will think my combobox is an edit box and _IsBuddyToEdit() will still return true..... Also, I think you can skip the check on UDS_AUTOBUDDY, as UDM_GETBUDDY will return the buddy also if you have the autobuddy style.
|
|
Technical Support
|
Mar 25, 2010 - 2:42 AM
|
We replaced the following line of code:
TCHAR szCompare[ sizeof(szEdit)/sizeof(szEdit[0]) + 1 ];
With the following one: TCHAR szCompare[ 512 ];
We agree you have the right to implement your own editable windows. Here is the entire method’s source code: bool CExtSpinWnd::_IsBuddyToEdit()
{
ASSERT_VALID( this );
if( GetSafeHwnd() == NULL )
return false;
DWORD dwStyle = GetStyle();
bool bSpinAlignRight = ( ( dwStyle & UDS_ALIGNRIGHT ) != 0 ) ? true : false;
bool bSpinAlignLeft = ( ( dwStyle & UDS_ALIGNLEFT ) != 0 ) ? true : false;
if( ! ( bSpinAlignRight || bSpinAlignLeft ) )
return false;
HWND hWndBuddyTest = NULL;
static const TCHAR szEdit[] = _T("EDIT");
TCHAR szCompare[ 512 ];
if( ( dwStyle & UDS_AUTOBUDDY ) != 0 )
{
hWndBuddyTest = ::GetWindow( m_hWnd, GW_HWNDPREV );
if( hWndBuddyTest != NULL )
{
::memset( szCompare, 0, sizeof(szCompare) );
::GetClassName( hWndBuddyTest, szCompare, sizeof(szCompare)/sizeof(szCompare[0]) );
if( ::lstrcmpi( szCompare, szEdit ) != 0 )
hWndBuddyTest = NULL;
}
}
if( hWndBuddyTest == NULL )
{
hWndBuddyTest = (HWND) SendMessage( UDM_GETBUDDY, 0L, 0L );
if( hWndBuddyTest != NULL && ::IsWindow( hWndBuddyTest ) )
{
::memset( szCompare, 0, sizeof(szCompare) );
::GetClassName( hWndBuddyTest, szCompare, sizeof(szCompare)/sizeof(szCompare[0]) );
if( ::lstrcmpi( szCompare, szEdit ) != 0 )
hWndBuddyTest = NULL;
}
else
hWndBuddyTest = NULL;
}
return ( hWndBuddyTest != NULL ) ? true : false;
}
But we would prefer to leave the UDS_AUTOBUDDY style checking code to be exactly 100% sure about the CExtSpinWnd is backward compatible with all the customer projects.
|
|
Jeroen Walter
|
Mar 25, 2010 - 2:56 AM
|
Thanks. Just for my understanding, is it the intention of the CExtSpinWnd to only be a buddy to an edit box? I’m asking this because it is possible (though arguably useless) to buddy a spincontrol to other types of controls as well. In the resource editor of Visual Studio you can test this, just create a checkbox or combobox and create a spincontrol with the autobuddy and set buddy int styles. If your CExtSpinWnd is meant to be a drop-in replacement of CSpinButtonCtrl, then you should not limit the buddying to edit boxes only.
|
|
Technical Support
|
Mar 25, 2010 - 7:52 AM
|
|
|
Jeroen Walter
|
Mar 26, 2010 - 4:09 AM
|
Still, it’s possible  Not that I need it, I was just wondering (not criticizing) in how far the ProfUis controls are supposed to be a drop-in replacement for the default MFC controls, i.e. maintaining the same functionality.
|
|
Technical Support
|
Mar 26, 2010 - 11:14 AM
|
Each control is specific. The CExtEdit class supports a themed border, Prof-UIS context menu and several additional handy methods like changing text/background colors. The CExtButton class supports an icon, a split button mode and a built in-menu. The CExtColorButton class is a CExtButton -based button which displays a color picker popup menu and automatically generates a color icon. The CExtCheckBox and CExtRadioButton and just skinned versions of appropriate common controls. The CExtGroupBox is also just a skinned control, but it supports several optional skinning modes. The CExtListCtrl class supports an improved and themed header control and sorting. The CExtTreeCtrl class is very improved and completely re-painted tree view common control. If you need the classic tree view common control but with Prof-UIS themed scroll bars, then you can simply use the CExtNCSB < CTreeCtrl > template based class type. The CExtThemedTabCtrl is just a themed tab common control which Prof-UIS uses only in themed property sheet windows. The CExtTabWnd class is a tab window written from scratch and Prof-UIS uses everywhere we need the tabs. The CExtMenuControlBar , CExtPanelControlBar , CExtControlBar , CExtRibbonBar bars are bars written from scratch. The grids, of course, also written from scratch. The most complex and big parts of Prof-UIS are not related to Window common controls.
|
|
Technical Support
|
Mar 20, 2010 - 11:25 AM
|
Thank you for reporting this issue. To fix it, please update the source code for the following method:
bool CExtSpinWnd::_IsBuddyToEdit()
{
ASSERT_VALID( this );
if( GetSafeHwnd() == NULL )
return false;
DWORD dwStyle = GetStyle();
bool bSpinAlignRight = ( ( dwStyle & UDS_ALIGNRIGHT ) != 0 ) ? true : false;
bool bSpinAlignLeft = ( ( dwStyle & UDS_ALIGNLEFT ) != 0 ) ? true : false;
if( ! ( bSpinAlignRight || bSpinAlignLeft ) )
return false;
HWND hWndBuddyTest = NULL;
static const TCHAR szEdit[] = _T("EDIT");
TCHAR szCompare[ sizeof(szEdit)/sizeof(szEdit[0]) + 1 ];
if( ( dwStyle & UDS_AUTOBUDDY ) != 0 )
{
hWndBuddyTest = ::GetWindow( m_hWnd, GW_HWNDPREV );
if( hWndBuddyTest != NULL )
{
::memset( szCompare, 0, sizeof(szCompare) );
::GetClassName( hWndBuddyTest, szCompare, sizeof(szCompare)/sizeof(szCompare[0]) );
if( ::lstrcmpi( szCompare, szEdit ) != 0 )
hWndBuddyTest = NULL;
}
}
if( hWndBuddyTest == NULL )
{
hWndBuddyTest = (HWND) SendMessage( UDM_GETBUDDY, 0L, 0L );
if( hWndBuddyTest != NULL && ::IsWindow( hWndBuddyTest ) )
{
::memset( szCompare, 0, sizeof(szCompare) );
::GetClassName( hWndBuddyTest, szCompare, sizeof(szCompare)/sizeof(szCompare[0]) );
if( ::lstrcmpi( szCompare, szEdit ) != 0 )
hWndBuddyTest = NULL;
}
else
hWndBuddyTest = NULL;
}
return ( hWndBuddyTest != NULL ) ? true : false;
}
|
|
Jeroen Walter
|
Mar 18, 2010 - 6:32 AM
|
Could you please provide documentation about skinning? What we want is documentation about the skinning API and the XML format. Also a skin editor would be nice. Right now the only thing we can do when creating our own skin, is using one of the supplied XML skins and through trial and error see what effect each XML tag has on the skin. This time consuming and error prone and could be prevented if you just provide some tools and documentation for building our own skins. Why would you even provide (and promote) the ability to use custom skins via xml/bin files, if you don’t also provide documentation and tools for it?
|
|
Technical Support
|
Mar 25, 2010 - 2:42 AM
|
There are four types of XML nodes in the XML skin file:
1) The Prof-UIS-Skin node as the root element. 2) The SkinItem nodes defining hierarchical tree. This element has only the Name attribute. 3) The Color nodes defining the color values in the Color attribute. The color elements are always leaf elements in the XML. This element also has only the Name attribute which is typically defining normal/hovered/disabled/pressed color names. 4) The Glyph nodes defining bitmap backgrounds of UI elements. The Clp , Crp , Ctp and Cbp attributes defining the content padding of UI element which means how the inner sub elements should be far from this element borders. The Image attribute defines path to BMP or PNG image file. The Lp , Rp , Tp and Bp attributes defining how the bitmap should be split into the nine slice bitmaps before painting. The DrawCenter attribute is the flag which defines whether to draw the central part of bitmap. The DrawMethod attribute defines how to draw all the slices. It can be Hollow , Stretch , Center , TileH , TileV or Tile . These values are similar to the CExtBitmap::e_DrawMethod_t enumeration used by the CExtBitmap::AlphaBlendSkinParts() method. This element also has only the Name attribute which is typically defining background type or state of UI item.
Some skins can be very un-friendly to particular UI elements. For example, the buttons have very big paddings in the Aqua skin and you cannot use this skin with very small push buttons.
|
|
Eric
|
Jul 14, 2010 - 1:26 PM
|
What about To, Ro, Bo and Lo? Thank you!
|
|
Technical Support
|
Jul 15, 2010 - 6:46 AM
|
The skinned UI item layout and position are defined by the following XML parameter names declared near the top of the .../Prof-UIS/ProfSkin/ExtSkinItem.h file:
<>1)</b> The bitmap padding used for splitting bitmap into nine slices before painting it over UI element:
#define __EXT_SKIN_ITEM_GLYPH_TOP_PADDING L"Tp"
#define __EXT_SKIN_ITEM_GLYPH_LEFT_PADDING L"Lp"
#define __EXT_SKIN_ITEM_GLYPH_BOTTOM_PADDING L"Bp"
#define __EXT_SKIN_ITEM_GLYPH_RIGHT_PADDING L"Rp"
<>2)</b> The UI element content padding determines how far the inner UI sub-elements from borders of their parent element (for instance, how far icon and text from button’s border): #define __EXT_SKIN_ITEM_GLYPH_CONTENT_TOP_PADDING L"Ctp"
#define __EXT_SKIN_ITEM_GLYPH_CONTENT_LEFT_PADDING L"Clp"
#define __EXT_SKIN_ITEM_GLYPH_CONTENT_BOTTOM_PADDING L"Cbp"
#define __EXT_SKIN_ITEM_GLYPH_CONTENT_RIGHT_PADDING L"Crp"
<>3)</b> The UI element offset: #define __EXT_SKIN_ITEM_GLYPH_LEFT_OFFSET L"Lo"
#define __EXT_SKIN_ITEM_GLYPH_TOP_OFFSET L"To"
#define __EXT_SKIN_ITEM_GLYPH_RIGHT_OFFSET L"Ro"
#define __EXT_SKIN_ITEM_GLYPH_BOTTOM_OFFSET L"Bo"
The first two types of parameters used by all the skin data items. The most of UI elements in any app have fixed layout and/or position and ProfSkin library just needs to know how to paint UI elements and how to position inner UI sub elements. But some UI items require to be shifted to some distance from their default location or from corners of parent UI elements. This is needed only for elements like window caption buttons or resizable control bar caption buttons. That’s why the third type of XML node parameters were defined. The most of UI elements ignore these parameters.
|
|
Jeroen Walter
|
Mar 25, 2010 - 3:00 AM
|
Thanks for the information. I hope however that you are still working towards a complete documentation for the skins, that will then be integrated in the Profuis helpfiles along with a skin editor.
|
|
Technical Support
|
Mar 20, 2010 - 11:25 AM
|
The XML skin description file works like CSS works with HTML. The XML skin does not have exactly defined skin description for each particular UI item. The XML nodes are inheritable like CSS cascading classes. We can only describe the XML tree branches and corresponding UI elements.
The skin editor is in our TO-DO list. We can visualize XML data in some tree grid control and display what and how can be painted according to the currently focused tree item. We can also provide several test windows containing different Prof-UIS controls. This can be useful for taking look at the entire skinning progress in the skin editor.
|
|
Jeroen Walter
|
Mar 24, 2010 - 9:57 AM
|
A description of each xml tag and its attributes and its effects and correspondence with UI elements would be nice. In addition to that a skin editor is very desirable. For example, I had a small CExtButton, about 12x12 pixels, with 1 letter as caption. This letter would not show up on the button, because apparently the skin element for a CExtButton has some attributes concerning content padding etc, which resulted in a usable client area for the caption of 0,0 pixels..... It took some time to hunt down that this was the problem, becauseI had to debug step it until I found the culprit and then find the corresponding tag in the skin xml file.
|
|
Offer Har
|
Mar 18, 2010 - 4:49 AM
|
Hi, When editing the time from the cell OnInplaceControlDateTimeInputVerify is called, when changing from the drop-list it’s not called. I see that OnValueChanging is called when changing from the drop list, however this function is also called when changing the value of cell from the code (SetDateTime ) which makes it very complicated to handle user input in one place - can you please change it to be more user friendly, or at-least add a flag to OnValueChanging so we’ll know if the change came from the user or from the code? Thanks, Ron.
|
|
Technical Support
|
Mar 22, 2010 - 11:40 AM
|
The CExtGridCellDateTime::OnValueChanging() / CExtGridCellDateTime::OnValueChanged() virtual methods really provide unified notifications. Do you want us to add similar methods into the CExtGridWnd class?
|
|
Offer Har
|
Mar 22, 2010 - 12:54 PM
|
There are two problems: 1. I need it in the grid, not going to derive a cell for every validation 2. I need to know when the user changed the value, and not from elsewhere in the code.
|
|
Technical Support
|
Mar 23, 2010 - 10:57 AM
|
There are only three ways to modify the date-time cell’s value:
1) Editing text in the in-place activated date-time editor window. The CExtGridCellDateTime::OnInplaceControlDateTimeInputComplete() and CExtGridWnd::OnGridCellInplaceControlDateTimeInputComplete() virtual methods allow you to intercept this event.
2) Pressing the date-time grid cell’s built-in up-down button arrows. The CExtGridCell::OnQueryEnabledIncrement() , CExtGridWnd::OnGridHookCellQueryEnabledIncrement() , CExtGridCellDateTime::OnValueIncrement() and CExtGridWnd::OnGridHookCellValueIncrement()</code> virtual methods allow you to intercept this event and even disable up and/or down parts of the built-in cell’s up-down button.
3) Picking the date item in the popup calendar control. The CExtGridCellDateTime::OnPopupDatePickerSelChange() virtual method allows you to intercept this event.
The third case does not have a similar virtual method in the grid control. We added it:
virtual bool OnGridCellPopupDatePickerSelChange( LPVOID pSelectionNotification, CExtGridCell::TrackCellStateInfo_t & _tcsi );
bool CExtGridWnd::OnGridCellPopupDatePickerSelChange( LPVOID pSelectionNotification, CExtGridCell::TrackCellStateInfo_t & _tcsi )
{
__EXT_DEBUG_GRID_ASSERT_VALID( this );
ASSERT( pSelectionNotification != NULL );
pSelectionNotification; _tcsi;
return false;
}
Please also update the source code of the CExtGridCellDateTime::OnPopupDatePickerSelChange() and CExtGridCellDateTime::OnButtonPopupMenuTrack() virtual method: bool CExtGridCellDateTime::OnPopupDatePickerSelChange(
LPVOID pSelectionNotification
)
{
__EXT_DEBUG_GRID_ASSERT_VALID( this );
const CExtDatePickerWnd::SELECTION_NOTIFICATION * pSN = CExtDatePickerWnd::SELECTION_NOTIFICATION::FromWPARAM( (WPARAM)pSelectionNotification );
if( pSN == NULL )
return false;
if( pSN->m_hWndDatePicker != NULL && ::IsWindow( pSN->m_hWndDatePicker ) )
{
CExtDatePickerWnd * pWndDatePicker = DYNAMIC_DOWNCAST( CExtDatePickerWnd, CWnd::FromHandlePermanent( pSN->m_hWndDatePicker ) );
if( pWndDatePicker != NULL )
{
CExtPopupDatePickerMenuWnd * pPopup = DYNAMIC_DOWNCAST( CExtPopupDatePickerMenuWnd, pWndDatePicker->GetParent() );
if( pPopup->GetSafeHwnd() != NULL )
{
CExtGridCell::TrackCellStateInfo_t * p_tcsi = (CExtGridCell::TrackCellStateInfo_t *) pPopup->m_lParamCookie;
if( p_tcsi != NULL && p_tcsi->m_wndGrid.GetSafeHwnd() != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( (&p_tcsi->m_wndGrid) );
__EXT_DEBUG_GRID_ASSERT_KINDOF( CExtGridWnd, (&p_tcsi->m_wndGrid) );
if( p_tcsi->m_wndGrid.OnGridCellPopupDatePickerSelChange( pSelectionNotification, *p_tcsi ) )
return true;
}
}
}
}
if( pSN->m_bFinalSelectionChanging )
{
if( pSN->m_dtBegin.GetStatus() == COleDateTime::valid
&& m_dtDate.GetStatus() == COleDateTime::valid
)
SetDateTime(
pSN->m_dtBegin.GetYear(), pSN->m_dtBegin.GetMonth(), pSN->m_dtBegin.GetDay(),
m_dtDate.GetHour(), m_dtDate.GetMinute(), m_dtDate.GetSecond()
);
else
SetDateTime( pSN->m_dtBegin );
}
return true;
}
bool CExtGridCellDateTime::OnButtonPopupMenuTrack(
CExtGridCell::TrackCellStateInfo_t & _tcsi
)
{
__EXT_DEBUG_GRID_ASSERT_VALID( this );
__EXT_DEBUG_GRID_ASSERT( (&_tcsi.m_cell) == this );
__EXT_DEBUG_GRID_ASSERT_VALID( (&_tcsi.m_wndGrid) );
if( _tcsi.m_nButtonType != INT(__EBTT_DROPDOWN) )
return CExtGridCellEx::OnButtonPopupMenuTrack( _tcsi );
// move focus and selection to the cell
DWORD dwSiwStyles = _tcsi.m_wndGrid.SiwGetStyle();
if( ( dwSiwStyles & __EGBS_SFB_MASK ) != __EGBS_SFB_NONE && _tcsi.m_nColType == 0 && _tcsi.m_nRowType == 0 )
{
CPoint ptFocusOld = _tcsi.m_wndGrid.FocusGet();
CPoint ptFocusDesired( _tcsi.m_nColNo, _tcsi.m_nRowNo );
CRect rcSelectionOld = _tcsi.m_wndGrid.SelectionGet( false, -1 );
CRect rcSelectionDesired( _tcsi.m_nColNo, _tcsi.m_nRowNo, _tcsi.m_nColNo, _tcsi.m_nRowNo );
if( (dwSiwStyles & __EGBS_SFB_MASK) == __EGBS_SFB_FULL_ROWS )
{
LONG nColumnCount = _tcsi.m_wndGrid.ColumnCountGet();
rcSelectionDesired.SetRect( 0, _tcsi.m_nRowNo, nColumnCount - 1, _tcsi.m_nRowNo );
}
if( (dwSiwStyles & __EGBS_SFB_MASK) == __EGBS_SFB_FULL_COLUMNS )
{
LONG nRowCount = _tcsi.m_wndGrid.RowCountGet();
rcSelectionDesired.SetRect( _tcsi.m_nColNo, 0, nRowCount - 1, _tcsi.m_nColNo );
}
if( ptFocusDesired != ptFocusOld
|| rcSelectionOld != rcSelectionDesired
)
{
if( ptFocusDesired != ptFocusOld )
_tcsi.m_wndGrid.FocusSet( ptFocusDesired, true, true, false, false );
if( rcSelectionOld != rcSelectionDesired )
_tcsi.m_wndGrid.SelectionSet( rcSelectionDesired, true, false, false );
_tcsi.m_wndGrid.OnSwDoRedraw();
}
}
_tcsi.m_wndGrid.InvalidateRect( &_tcsi.m_rcCellExtra );
_tcsi.m_wndGrid.OnSwUpdateWindow();
CExtPopupDatePickerMenuWnd * pPopup =
STATIC_DOWNCAST(
CExtPopupDatePickerMenuWnd,
CExtPopupMenuWnd::InstantiatePopupMenu( _tcsi.m_wndGrid.GetSafeHwnd(), RUNTIME_CLASS(CExtPopupDatePickerMenuWnd), this )
);
if( ! pPopup->CreatePopupMenu( _tcsi.m_wndGrid.GetSafeHwnd() ) )
{
delete pPopup;
__EXT_DEBUG_GRID_ASSERT( FALSE );
return true;
}
pPopup->m_dwDatePickerStyle = OnQueryDatePickerStyle();
pPopup->m_pCbDatePickerSelection = (CExtPopupInplaceDatePicker::pCbDatePickerSelection) stat_CbDatePickerSelection;
pPopup->m_pDatePickerSelectionCookie = (LPVOID)this;
pPopup->m_pCbInitDatePickerContent = (CExtPopupInplaceDatePicker::pCbInitDatePickerContent) stat_CbInitDatePickerContent;
pPopup->m_pInitDatePickerCookie = (LPVOID)this;
pPopup->m_lParamCookie = (LPARAM) (LPVOID) (&_tcsi);
CRect wr( _tcsi.m_rcCell );
_tcsi.m_wndGrid.ClientToScreen( &wr );
CPoint ptTrack( wr.BottomRight() );
ptTrack.x += pPopup->OnQueryMenuShadowSize();
CRect rcExclude( ptTrack, ptTrack );
HWND hWndGrid = _tcsi.m_wndGrid.m_hWnd;
g_pCellMenuTracking = this;
if( ! pPopup->TrackPopupMenu(
TPMX_RIGHTALIGN | TPMX_COMBINE_NONE | TPMX_DO_MESSAGE_LOOP,
ptTrack.x, ptTrack.y, &rcExclude, this, NULL, NULL, true
)
)
{
g_pCellMenuTracking = NULL;
//delete pPopup;
__EXT_DEBUG_GRID_ASSERT( FALSE );
return true;
}
if( ! ::IsWindow( hWndGrid ) )
return true;
if( g_pCellMenuTracking == this )
g_pCellMenuTracking = NULL;
else if( g_pCellMenuTracking == NULL )
return true;
_tcsi.m_wndGrid.InvalidateRect( &_tcsi.m_rcCellExtra );
_tcsi.m_wndGrid.OnGridCellInputComplete( *this, _tcsi.m_nColNo, _tcsi.m_nRowNo, _tcsi.m_nColType, _tcsi.m_nRowType );
return OnButtonPopupMenuComplete( _tcsi );
}
The LPVOID pSelectionNotification parameter is the pointer to the CExtDatePickerWnd::SELECTION_NOTIFICATION data structure in both methods. This data structure has the m_bFinalSelectionChanging property which is false when the user just moves mouse over date item. It’s true when the user picked some date item.
|
|
Technical Support
|
Mar 20, 2010 - 11:26 AM
|
The CExtGridCell::OnInplaceControlDateTimeInputVerify() virtual method and the corresponding CExtGridWnd::OnGridCellInplaceControlDateTimeInputVerify virtual method have the InplaceControl text in the method names because these methods are related to the in-palace activated date time editor control looking like validating/masked text editor controls. If you need to handle the date-time cell’s up-down and drop-down buttons, then you should override the CExtGridCellDateTime::OnValueChanging() / CExtGridCellDateTime::OnValueChanged() virtual methods.
|
|
Offer Har
|
Mar 20, 2010 - 1:56 PM
|
Hi, There is a problem with this design: 1) Usually, we need to validate user’s inputs - and according to your answer there is no one place to validate it. 2) When validating user’s inputs, I do not want to check code inputs, it is also calling OnValueChanging. Do you plan of fixing this for the coming versions?
|
|
Noa Naot
|
Mar 18, 2010 - 4:24 AM
|
Hi, When button is pressed on the ellipsis button for the first time, i get a assertion. In Release build, operation takes longer than expected. Assertion origins from the line:
ASSERT(FromHandlePermanent(hImageList) == NULL); in CImageList::Attach
called from g_ilShellSmall.Attach( hSysImageList ); (ExtControlsShell.cpp line 766)
called from CExtShellBase::Shell_Init
called from CExtShellLock _shellLock;
called from CExtGridCellFile::GetFile
What can be the cause of this?
I am using Prof-UIS version 2.85. Problem occurs since i upgraded to 2.85. Before, i did not have such problem.
In addition - the file dialog that is eventually opened if i ignore the assertion has a different style than the normal file open dialog. I tried to remove the flag OFN_EXPLORER but it did not help. Thank you, Noa
|
|
Noa Naot
|
Mar 25, 2010 - 2:00 PM
|
Thank you, I dont have any other code using LVSIL_SMALL anywhere. In addition - my code used to work with Prof-UIS 2.84 and below, and the assertion takes place since 2.85. Could it be sothing else? thanks Noa
|
|
Technical Support
|
Mar 26, 2010 - 6:56 AM
|
You can set a breakpoint at the g_ilShellSmall image list initialization code where the image list handle is attached to it and run your application. You will see where it’s initialized for the first time and why it becomes initialized for the second time. Do you use only one copy of Prof-UIS in the running instance of your application? Do you have any Prof-UIS based regular DLLs? Please also note, Prof-UIS library should be used in the one UI thread only.
|
|
Technical Support
|
Mar 19, 2010 - 12:15 PM
|
Here is the code which gets the shell
if( g_ilShellSmall.GetSafeHandle() == NULL )
{
SHFILEINFO _sfi;
::memset( &_sfi, 0, sizeof(SHFILEINFO) );
HIMAGELIST hSysImageList = (HIMAGELIST)
::SHGetFileInfo(
(LPCTSTR)g_pidlDesktop,
0,
&_sfi,
sizeof(SHFILEINFO),
SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON
);
if( hSysImageList == NULL )
{
ASSERT( FALSE );
Shell_DoneImpl();
if( bEnableThrowExceptions )
::AfxThrowUserException();
return false;
}
g_ilShellSmall.Attach( hSysImageList );
}
If you have similar code in your application, then the g_ilShellSmall.Attach( hSysImageList ); line of code above can really try to attach image list handle which is already attached to other CImageList object. If our guess is correct, then we would like to ask you to switch using the CExtShellBase::g_ilShellSmall and CExtShellBase::g_ilShellBig image lists.
|
|
Noa Naot
|
Mar 18, 2010 - 1:35 PM
|
|
|
Technical Support
|
Mar 18, 2010 - 12:31 PM
|
Did you invoke the AfxOleInit() API in the InitInstance() virtual method of the CWinApp -derived class in your project?
|
|
Robert Webb
|
Mar 15, 2010 - 8:59 PM
|
Hi, Is it possible to set things up so that the MDI tabs only appear when there’s more than one document? Would be great if there was a style for this somewhere. Thanks, Rob.
|
|
Technical Support
|
Mar 22, 2010 - 11:35 AM
|
We think with this version the problem should be gone: void C_YOUR_MdiTabWnd::OnTabWndSyncVisibility()
{
ASSERT_VALID( this );
if( GetSafeHwnd() == NULL )
return;
bool bZeroItemCount = ( ItemGetCount() == 0 ) ? true : false;
if( ( GetStyle() & WS_VISBIBLE ) != 0 )
{
if( ! bZeroItemCount )
return;
}
else
{
if( bZeroItemCount )
return;
}
ShowWindow( ( ! bZeroItemCount ) ? SW_SHOW : SW_HIDE );
}
|
|
Technical Support
|
Mar 17, 2010 - 2:29 AM
|
You can do that by overriding CExtTabWnd::OnTabWndSyncVisibility() in the following way:
void C_YOUR_MdiTabWnd::OnTabWndSyncVisibility()
{
ASSERT_VALID( this );
if( GetSafeHwnd() == NULL )
return;
ShowWindow( ( ItemGetCount() > 0 ) ? SW_SHOW : SW_HIDE );
}
|
|
Robert Webb
|
Mar 21, 2010 - 8:26 PM
|
Thanks, it works! We found that it’s best to return without doing anything though if ItemGetCount() returns zero. If you call ShowWindow with SW_SHOW otherwise (we give the user the option to always show or hide when only one tab) then it leads to endless repaint messages being sent. Don’t know why, but that test avoids it. Thanks, this one’s solved. Rob.
|
|
Robert Webb
|
Mar 15, 2010 - 8:56 PM
|
How do I change the font (or actually just the size of the font) used in the ribbon group label? Thanks, Rob.
|
|
Technical Support
|
Mar 17, 2010 - 2:28 AM
|
The font returned by the CExtRibbonPage::OnGetToolbarFont() virtual method is used for painting ribbon group captions. Unfortunately, this method does not have a parameter identifying who is asking for the font. So, we can regard your question as a feature request. We added a new parameter CObject * pQuerySrc to the following virtual methods:
CFont * CExtRibbonPage::OnGetToolbarFont(
bool bVert,
bool bMeasureFont,
CObject * pQuerySrc
)
CFont * CExtToolControlBar::OnGetToolbarFont(
bool bVert,
bool bMeasureFont,
CObject * pQuerySrc
)
It’s a pointer to the CExtRibbonButtonGroup object when the caption font for the ribbon button groups should be returned. Please drop us an e-mail to the support mail box so we will provide you with the source code update.
|
|
Claudiu Tanasescu
|
Mar 12, 2010 - 8:43 AM
|
Hi Tech Support,
You have a sample project for how to use CExtGridWnd in a dialog?
You have a tutorial how to use prof-uis Data Grids Control ?
|
|
Claudiu Tanasescu
|
Mar 19, 2010 - 7:04 AM
|
|
|
Technical Support
|
Mar 15, 2010 - 5:26 AM
|
|
|
Robert Webb
|
Mar 11, 2010 - 9:12 PM
|
About 8 months ago I asked about changing the ribbon bar height (see http://www.prof-uis.com/prof-uis/tech-support/support-forum/customisable-ribbon-bar-64944.aspx). We would still love to be able to do this, since a number of our customers are complaining about it taking up too much space, so I thought it best to start a new thread. Back then you advised that we override CExtRibbonPage::RibbonLayout_GetGroupHeight(), and indeed this goes part of the way. It does indeed allow us to change the height of the ribbon bar, however Prof-UIS fails to use this height properly. I notice the following problems: - The ribbon groups are simply truncated, not resized, so the border around a group just gets cropped meaning you can no longer see the group name, nor the lower right group button if it has one. - Large icons are still used, although they no longer fit. Once below a certain height, all icons should be forced to small. - Although it does seem to arrange buttons into less rows as it should (ie 1 or 2 instead of 3 depending on height), they are still being positioned vertically based on the original full height. So it may decide to use a single row, but they are "centred" so low that they are mostly clipped by the actual new bottom of the ribbon bar. Maybe this and the previous item would sort themselves out if the groups were resized correctly? Would it be possible to fix these things? Thanks, Rob.
|
|
Technical Support
|
Mar 20, 2010 - 11:24 AM
|
The CExtRibbonButtonGroup::OnRibbonCalcCollapsedGroupSize() virtual method computes the size of a ribbon button representing the collapsed group of buttons. This button is the same group container button but it’s in the top-collapsed state (CExtRibbonButtonGroup::TopCollapsedStateGet() ). You need to code your own CExtRibbonButtonGroup -derived and CExtRibbonButtonToolGroup -derived classes which implement the CExtRibbonButtonGroup::OnRibbonCalcCollapsedGroupSize() virtual method. You will also need to code your own group and tool-group ribbon command nodes which will provide the ribbon bar with your group button class instances. The same can be done for the text/combo field buttons and their ribbon nodes.
The ribbon bar height changing means complete reset of layout rules for all the ribbon elements. We are not sure it’s always possible to find the best looking layout rules for any abstract height of the ribbon bar.
|
|
Robert Webb
|
Mar 22, 2010 - 1:46 AM
|
Sorry, but I’m not sure how to tie all this together from that description. Is there any sample code? I couldn’t find anything that does something similar already. These work-arounds seem like things Prof-UIS should do internally, but I’m happy with any solution I can get working. You’re right that it may not always be possible to find a good layout, depending on the contents, but I only see a few problems which seem like they should be within reach. Also, you didn’t comment on how best to prevent use of large icons. I’m calling RuleRemoveLargeILV() for every node, which then makes it hard to bring the large icons back if the user changes back to a taller ribbon bar. Is there a better way? Thanks, Rob.
|
|
Technical Support
|
Mar 22, 2010 - 11:38 AM
|
We followed the Microsoft’s Ribbon UI Design Guidelines document when we coded all the CExtRibbon*** classes. So, a custom sized ribbon is some kind of advanced, non-standard and custom coded task. But we think this task is really interesting and creative. We would be very happy to code some test project for you and/or similar new sample application for Prof-UIS. Please let us discuss the entire task details. We understand this improved ribbon bar should support any variable height and it should place all the buttons automatically to fit any available space in each ribbon button group. But what is the custom ribbon size in your real application? Should we insert some separator at the bottom of the ribbon and let the user to resize the ribbon bar to any height? Or do we need to support some non-standard ribbon bar size(s) which will make the ribbon bar to place the ribbon elements of the current standard size into layouts which are different than the standard three row layout? In the last case, we can modify the Prof-UIS ribbon source code and let you to specify the count of the standard sized ribbon rows you want to see.
|
|
Robert Webb
|
Mar 23, 2010 - 1:30 AM
|
Sounds great. It’s already close, other than the few things I mentioned. For our purposes, I’d be happy for the user to be able to choose somewhere between 1, 2 or 3 rows of small icons. There’s nothing much to gain by setting the height to intermediate values. It would be a nice addition if the user could interactively grab the bottom of the ribbon bar and drag it up or down, maybe snapping to sensible heights to fit integral numbers of icon rows, but we’re also happy to add our own interface control and use the current programmatic way to set the height. Buttons already arrange themselves into just 1 or 2 rows when the height is reduced. They even arrange into more rows when the height is increased. But they still insist on trying to use large icons when there’s not enough room, and when groups collapse to single buttons it really throws things out. The formula for a good height seems to be: dh = rows * 19 - 67, where dh is the change in height, added to the value returned by the base class versiono of RibbonLayout_GetGroupHeight(). This presumes only small icons are used, which should be true for 1 or 2 rows. For 3 rows this formula gives -10, ie 10 pixels shorter than usual, which fits 3 small rows OK, but doesn’t quite fit one large button with text below. I’m still not sure how to make my ribbon bar text fields shorter too. Currently they are taller than buttons and thus cause problems when using a different ribbon bar height. Rob.
|
|
Robert Webb
|
Apr 1, 2010 - 1:11 AM
|
Any further news on this? (My Outlook isn’t working by the way, in case you’ve tried emailing me). Rob.
|
|
Technical Support
|
Mar 15, 2010 - 5:22 AM
|
If you are using a non-standard height for the ribbon bar, you should not use ribbon button in the large state because large buttons are optimized for the standard ribbon height only. You should remove large button states from all the ribbon command tree nodes. If you decrease the ribbon bar height, there is no vertical space to organize buttons into 3 rows. Of course, you will see 2 or 1 rows of buttons only. Big buttons in some ribbon group make all the groups in the tab page larger. That’s why you see incorrectly clipped layout.
|
|
Robert Webb
|
Mar 15, 2010 - 8:54 PM
|
Wow, using RibbonILE_RuleRemoveLargeILV() on every ribbon bar node almost fixes everything, but not quite. I still notice these limitations: - When a ribbon group runs out of room and switches to a single drop-down button, this button is too big and forces the whole ribbon page to be bigger, again getting truncated at the bottom. This single button has text below, whereas it would fit if the text was put beside it when there isn’t enough vertical room (and maybe the button itself would need to be smaller in those cases). - I want to make the ribbon bar height available to the user. It looks like when they make the bar shorter I will have to call RibbonILE_RuleRemoveLargeILV() for every node. What about when they make it bigger again? How do I bring back that rule for all the nodes that had it originally? Surely Prof-UIS should recognise when the height is too short for large icons and behave as if they had been removed. I imagine this would be much easier on your end than the end-user’s. - I have text/combo fields on some ribbon pages. These it seems are taller than normal buttons, and don’t fit in so well at shorter heights chosen based on button height. Is there a way I can change the height of my text fields? They seem taller than necessary anyway. I create a new CExtRibbonNode, then call ModifyFlags(__ECTN_TBB_TEXT_FIELD | __ECTN_TBB_RESIZABLE), but I don’t see any way to specify a height. The node is not derived from a CWnd. I discovered that making the bar 29 pixels shorter works well for 2 rows of small icons, and 48 shorter for 1 row. Works well except for the above problems. Thanks, Rob.
|
|
Robert Webb
|
Mar 18, 2010 - 6:06 PM
|
Any solutions to the above three issues? The ability to reduce the ribbon bar to one or two rows of (small) buttons is great, but really unusable as it stuffs up when a group is reduced to a single button that’s too big. Thanks, Rob.
|
|
Dominik Braendlin
|
Mar 11, 2010 - 8:48 AM
|
Hi Tech Support, I am translating our software using satellite dll’s. So far everything works fine also using your translated lib resources except! The text of the "Hide" and "Auto Hide" tooltip of the panels can for some reason not be altered. I also tried to directly change the text in the src file "ExtControlBar.cpp" Ln 14693 and Ln 14871 but I still get the same text “Hide” and “Auto Hide”. I am using Prof-UIS v288 Is there some hidden text I am missing? Adrian
|
|
Technical Support
|
Mar 15, 2010 - 5:25 AM
|
Both MFC and Prof-UIS resource manager will be able to find any resources in your resource DLLs only if they are MFC extension DLLs. They can be linked statically or loaded using the AfxLoadLibrary() MFC API. If your resource DLL are just non-MFC-extension DLLs, then you can make Prof-UIS searching them for resources only if you register your resource DLL handle(s) in the Prof-UIS resource manager using the g_ResourceManager->RscInst_Insert( . . . ) code.
|
|
Dominik Braendlin
|
Mar 15, 2010 - 8:23 AM
|
The following situation works well. I first get the English resources and after LoadBestLanguage I get the language I have selected.
CString str30048; CString str30056; // English language g_ResourceManager->LoadString(str30048, /*IDS_CBNCAREA_CLOSE*/30048); g_ResourceManager->LoadString(str30056, /*IDS_EXTTABWND_BTN_AUTOHIDE*/30056); // call of AfxLoadLibrary() m_LanguageSupport.LoadBestLanguage(); // new language g_ResourceManager->LoadString(str30048, /*IDS_CBNCAREA_CLOSE*/30048); g_ResourceManager->LoadString(str30056, /*IDS_EXTTABWND_BTN_AUTOHIDE*/30056);
//dllinit.cpp HINSTANCE AFXAPI AfxFindStringResourceHandle(UINT nID) { HINSTANCE hInst; // first check the main module state AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); if (!pModuleState->m_bSystem) { hInst = AfxGetResourceHandle(); if (AtlGetStringResourceImage(hInst, nID) != NULL) { // found a non-zero string in app return hInst; } } #define IDS_CBNCAREA_CLOSE 30048 #define IDS_EXTTABWND_BTN_AUTOHIDE 30056 #define IDS_CONTENT_EXPAND_TIP 30045
AfxGetResourceHandle in AfxFindStringResourceHandle returns 0x00400000 for ID 30048 and 30056 but 0x03570000 for 30045. 0x03570000 is the handle of the DLL which would be desired also for 30045 and 30056. Any idea?
|
|
Technical Support
|
Mar 15, 2010 - 1:36 PM
|
Unfortunately, we have no idea what is the m_LanguageSupport.LoadBestLanguage(); line of code. Let us assume it’s just AfxLoadLibrary() API invocation and you loaded German resources. Then the next two lines of code will load German strings only if the current thread locale is German. That’s what MFC localization can do. If you use Prof-UIS localization feature, then you can load German strings independently from the Windows/current thread locale setting. Please try to insert the following code immediately after the m_LanguageSupport.LoadBestLanguage(); line of code:
g_ResourceManager->AllowCustomLang( true );
g_ResourceManager->SetLangIdDesired( __EXT_MFC_LANG_ID_GERMAN );
Of course, you can use any other __EXT_MFC_LANG_ID_*** language identifier instead.
|
|
Dominik Braendlin
|
Mar 18, 2010 - 2:21 AM
|
The design of my app is a following. One exe for the app using just English resources for MFC and Prof-UIS. No multilingual Resources such as the design of Prof-UIS if the additional languages are switched on. Additional languages are in a satellite dll. One dll per language. If a dll is loaded with AfxLoadLibrary all the resources must be loaded from that dll. The resources from the exe must not be loaded at any time. As I have mentioned earlier I have moved all the translations per language for the Prof-UIS resources ID 29000 – 32000 Strings, Menu, Dialog and … to the satellite dll. It seems to me as if the Prof-UIS does not get all its internal resources ID 29000 - 32000 form the same handle once I switch from the exe as the only resource source to a satellite resource only dll using AfxLoadLibrary. As I have tried to explain earlier some Prof-UIS resources are loaded from the dll (using handle 0x03570000) and others are still loaded from the exe (using handle 0x00400000). I don’t know why this is happening. I want the Prof-UIS library to load all the resources from the dll once I have switched to the dll and not from the exe. I have tried your lines of code and they work g_ResourceManager->AllowCustomLang( true ); g_ResourceManager->SetLangIdDesired( __EXT_MFC_LANG_ID_GERMAN ); but I cannot use them in my project because as mentioned I do not want to compile all the Prof-UIS languages into the exe. Only English should be in the exe and if I add an additional language all the additional language resources must be in a satellite dll. Is there a bug in the Prof-UIS Lib or is it me?
|
|
Technical Support
|
Mar 18, 2010 - 12:30 PM
|
It’s not important where the Prof-UIS resources are stored. The only important thing is whether they are available for MFC style searching algorithm or not. This algorithm searches for the resources which have the same language as specified in Windows locale setting. It does not load resources of any other languages. So, you will need to invoke these lines of code in any case. It’s not important whether you moved Prof-UIS resources into some DLL or not.
|
|
Dominik Braendlin
|
Mar 19, 2010 - 1:00 AM
|
I have added these two lines of code after doing my language switching.
g_ResourceManager->AllowCustomLang( g_ResourceManager->SetLangIdDesired( m_LanguageSupport.GetCurrentLanguage() ); true );
But the text for "Auto Hide" and "Hide" are still displayed in English when I switch to e.g. German.
My exe has English only resources also the Prof_UIS part is English only. The dll is German only. I still don’t get I why e.g. the Prof-UIS Color dialog is displayed correctly in German also without the above two lines of code and these two "Auto Hide" and "Hide" are not.
Any idea?
|
|
Technical Support
|
Mar 19, 2010 - 12:14 PM
|
We checked the ..\Prof-UIS\Include\Resources\Resource_deu.rc file and it contains correct string:
MENUITEM "A&utomatisch verbergen", ID_EXT_DYN_BAR_AUTO_HIDE
We inserted the following lines of code into the CMainFrame class constructor in the MDIDOCVIEW sample application: g_ResourceManager->AllowCustomLang();
g_ResourceManager->SetLangIdDesired( __EXT_MFC_LANG_ID_GERMAN );
And we saw the Automatisch verbergen text. So, at least, we have this resource string translated and Prof-UIS Resource Manager was able to find and load it. There are couple possible reasons why you didn’t see this text in your application: 1) The m_LanguageSupport.GetCurrentLanguage() returns some language identifier which is not exactly equal to the __EXT_MFC_LANG_ID_GERMAN value that is defined as MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN) where both language and sub-language parts are exactly very important. 2) The German resources are not available for loading because of your resource DLL was not loaded as correct MFC extension DLL. If your resource DLL is MFC extension DLL, then you should load it using AfxLoadLibrary() API. If it’s not an MFC extension DLL, then it should be loaded using the LoadLibrary() and registered in the resource manager using the CExtResourceManager::RscInst_Insert() method. There are no other reasons to fail loading of localized resources of any type. You can insert the following code into the MDIDOCVIEW sample application and into your application: g_ResourceManager->AllowCustomLang();
g_ResourceManager->SetLangIdDesired( ID_EXT_DYN_BAR_AUTO_HIDE );
CExtSafeString sText;
g_ResourceManager->LoadString( sText, nId );
This will allow you to debug step by step the resource manager methods. You can enter the CExtResourceManager::LoadString() method, then CExtResourceManager::LoadStringEx() method, then the CExtResourceManager::LoadResourceBufferEx() method, then the CExtResourceManager::LoadResourceBufferSingleLanguage() method. The last method invokes the CExtResourceManager::CExtResourceMemoryBuffer::FindAndLoad() method many times trying to load the string data of the specified language from all the available locations. This will allow you to see all the available resource locations in the running instance of your application and in the MDIDOCVIEW sample application.
|
|
Dominik Braendlin
|
Mar 22, 2010 - 2:04 AM
|
We came a long way but finally I think I have found the problem. When I switch the language I load the language satellite dll with AfxLoadLibrary and then I set the AfxSetResourceHandle to the handle returned from AfxLoadLibrary. After searching in your source code for AfxSetResourceHandle I have found out that there are two locations where this function is called.<o:p></o:p> It’s in ExtLocalizeation.h Init() LN46 and Free LN 104. I also found a thread in your forum having a customer describing my problem.<o:p></o:p> http://www.prof-uis.com/prof-uis/tech-support/support-forum/prof-uis-resource-problem-56757.aspx<o:p></o:p> In some of your classes the class CExtLocalResourceHelper is used which sets the resource handle back to the default one and restors is after completing some task. During that time I get the wrong transaltions.<o:p></o:p> I have set the CExtLocalResourceHelper::g_bUseResourceHandle = true; and now it works fine.<o:p></o:p> What side effect could this cause? I am not able to change our way of handling language resources.<o:p></o:p> I have read the thread http://www.prof-uis.com/prof-uis/tech-support/support-forum/what-to-do-with-cextlocalresourcehelperg_buseresourcehandle-58745.aspx<o:p></o:p> and it seems as the same situation applies also to our software. <o:p></o:p> <o:p> </o:p>
|
|
Technical Support
|
Mar 22, 2010 - 11:39 AM
|
The CExtLocalResourceHelper class was designed for temporarily resource handle switching. This class is present in Prof-UIS approximately from the first versions release approximately eight years ago. It provides basic localization and resource identifier collision to Prof-UIS source code. There are no side effects with it. The CExtResourceManager class and the g_ResourceManager global smart pointer variable are the much newer features of Prof-UIS. The resource manager provides better and on the fly switchable localization feature. This feature is easy to use and not available in classic MFC and Win32 applications. We simply support both resource handle switching and resource manager.
|
|
Dominik Braendlin
|
Mar 12, 2010 - 7:17 AM
|
We provide out own language resource satellite dll’s. That’s why I have turned off all the languages in the prof-uis „resource.rc“ file. In the satellite dll’s we also translate the Prof-UIS Text “ID: 29000 - 32000” the menus and dialogs. #define __EXT_MFC_NO_RESOURCES_ARABIC_SAUDI_ARABIA #define __EXT_MFC_NO_RESOURCES_BELARUSIAN I have found out that if I turn on all the language resources again in the “resource.rc” file the ID IDS_EXTTABWND_BTN_AUTOHIDE translates correct. I don’t understand why the IDS_EXTTABWND_BTN_AUTOHIDE ID text is not taken from my resource satellite dll but others such as the “Color Dialog” are? Do you call the IDS_EXTTABWND_BTN_AUTOHIDE ID in a different thread other than the main thread? Thanks Adrian
|
|
Technical Support
|
Mar 12, 2010 - 1:24 AM
|
The Auto Hide text is loaded from the IDS_EXTTABWND_BTN_AUTOHIDE string resource. The ..\Prof-UIS\Include\Resources\ folder contains a set of *.rc files which are localized Prof-UIS resources. Please find the translation you need and check how the IDS_EXTTABWND_BTN_AUTOHIDE string resource is translated in it. Please use some simple text editor like the standard NOTEPAD.EXE editor provided with any Windows version. If you want to use Visual Studio resource editor for editing Prof-UIS resources, then you should save a copy of the ..\Prof-UIS\Include\Resources\resource.h file somewhere and restore it after editing localized resources in Visual Studio.
|
|
Rado Manzela
|
Mar 11, 2010 - 7:24 AM
|
I’m using tree grid with sortable columns, but it it seems to be too slow. My tree has abot 3 levels with approx. 1500 items total and sorting takes 5 or more seconds on Athlon XP 3400+ with 100% CPU load. Is it possible to optimize it? Especially when reversing sorting order, items are already sorted, you could just reverse order instead of making full order again. I’ve tried to find another optimizations, in ItemSortChildrenDeep() you call ItemSortChildren() for each parent node which calls OnSwUpdateScrollBars(); each time, maybe also other stuff redundantly. Is it really necessary? I’ve made my own version of deep sort which calls it only once at the end, wich is bit faster, but I’m not sure whether it is 100% safe.
|
|
Technical Support
|
Mar 20, 2010 - 1:06 PM
|
The following small improvement can make sorting 20% faster:bool CExtTreeGridDataProvider::_Tree_SortSwapSeries( LONG nRowNo1, LONG nRowNo2, LONG & nSwapCounter, CExtTreeGridDataProvider::ITreeDataProviderEvents * pDPE, CExtTreeGridCellNode * pNodeParent ) { __EXT_DEBUG_GRID_ASSERT_VALID( this ); __EXT_DEBUG_GRID_ASSERT( nRowNo1 >= 0L ); __EXT_DEBUG_GRID_ASSERT( nRowNo2 >= 0L ); __EXT_DEBUG_GRID_ASSERT( nRowNo1 != nRowNo2 ); __EXT_DEBUG_GRID_ASSERT( nSwapCounter >= 0L ); CExtTreeGridCellNode * pNode1 = pNodeParent->TreeNodeGetChildAt( ULONG(nRowNo1) ); __EXT_DEBUG_GRID_ASSERT_VALID( pNode1 ); CExtTreeGridCellNode * pNode2 = pNodeParent->TreeNodeGetChildAt( ULONG(nRowNo2) ); __EXT_DEBUG_GRID_ASSERT_VALID( pNode2 ); if( pDPE != NULL ) pDPE->OnTreeDataProviderSwapSeries( *pNode1, *pNode2, nSwapCounter ); nSwapCounter ++; CExtTreeGridCellNode * pNodeCopyMove = ( nRowNo2 > nRowNo1 ) ? pNode2 : pNode1; ULONG nIdxInsertBefore = ULONG( ( nRowNo2 > nRowNo1 ) ? nRowNo1 : nRowNo2 ); //CExtTreeGridCellNode * pNode3 = _Tree_NodeCopyMove( pNodeCopyMove, pNodeParent, nIdxInsertBefore, true, false ); // if( pNode3 == NULL ) // return false; __EXT_DEBUG_GRID_VERIFY( _Tree_NodeMoveImpl( pNodeCopyMove, pNodeParent, nIdxInsertBefore, TVE_TOGGLE ) ); return true; }
We just don’t need to check whether the specified tree nodes can really be swapped. I.e. whether one is not child of other one. But this generally does not solve the speed problem. The real source of this problem is that the CExtTreeGridWnd tree grid is the adopted version of the CExtGridWnd plain grid control. This fortunately makes all the grid cells and most other features of the plain grid control available in the tree grid control. But we had to track the linear list of expanded items constantly. This is extremely required by the CExtGridWnd class code and by all of its subsystems, especially by the data provider component. The current version of the tree grid sorting algorithm is some kind of universal algorithm which can work with any sub-branches of rows inside the tree grid. This algorithm cannot be seriously faster. But we can re-code the tree grid sorting for the particular case when the entire tree grid is sorted. It’s possible to make such particular sorting task seriously faster.
|
|
Rado Manzela
|
Mar 22, 2010 - 8:22 AM
|
Thank you, but it seems the speedup is not measurable in my case (definitely not 20% on my computer). I hope you’ll make faster at least reversing of the sort order (when tree is ordered by some column and user just clicks the column again to get reversed order) in next release.
|
|
Technical Support
|
Mar 17, 2010 - 2:32 AM
|
It seems you forgot to include the CellStatNumber.h file into the ZIP archive.
|
|
Rado Manzela
|
Mar 17, 2010 - 3:37 AM
|
I’m sorry, please just delete cellstatnumber.cpp , it is not used in the project, it was just numeric cell with different color.
|
|
Technical Support
|
Mar 15, 2010 - 5:20 AM
|
The tree grid swaps tree rows with/without children during sorting each tree level. The tree grid does not swap rows that do not need to be swapped during sorting. The speed of sorting depends on the number of rows, the number of columns in sorting rules and the type of grid cells. The speed is much faster in release than in debug. To make debug working with the speed that is close to release you should invert the commented state of the following lines of code at the beginning of the ../Prof-UIS/Include/ExtGridWnd.h file:
// #define __EXT_DEBUG_GRID_ASSERT_VALID( __PTR__ ) ;
// #define __EXT_DEBUG_GRID_ASSERT_KINDOF( __CTYPE__, __PTR__ ) ;
// #define __EXT_DEBUG_GRID_ASSERT( __SOME_EXPR__ ) ;
// #define __EXT_DEBUG_GRID_VERIFY( __SOME_EXPR__ ) __SOME_EXPR__ ;
#define __EXT_DEBUG_GRID_ASSERT_VALID( __PTR__ ) ASSERT_VALID( __PTR__ ) ;
#define __EXT_DEBUG_GRID_ASSERT_KINDOF( __CTYPE__, __PTR__ ) ASSERT_KINDOF( __CTYPE__, __PTR__ ) ;
#define __EXT_DEBUG_GRID_ASSERT( __SOME_EXPR__ ) ASSERT( __SOME_EXPR__ ) ;
#define __EXT_DEBUG_GRID_VERIFY( __SOME_EXPR__ ) VERIFY( __SOME_EXPR__ ) ;
Then you should rebuild the required Prof-UIS configurations and your project(s). Please provide us with additional information about the cell data types in your tree grid control.
|
|
Rado Manzela
|
Mar 16, 2010 - 9:17 AM
|
I was talking about release version. I’ve created some sample: http://rrrado.szm.sk/tree_order.zip#@lt;/p>
Compiled in VS 2005, release, (re)ordering takes 4,5 sec on my computer. (time is displayed in dialog after ordering).
|
|