CMFCRibbonSlider bug?
-
Sunday, August 12, 2012 4:02 AM
I use VS2010 to write a MFC APP with ribbon interface.
Then I found problem on slide control.
The slide control doesn't work while minimize the ribbon.
slid the position of the slider is OK but always get the old value while invoke GetPos。
While toggle ribbon hiding to showing, the slide locate at old position.
I guess there is a bug in CMFCRibbonSlider class.
Is any one can help to solve the problem.Sunyear
All Replies
-
Monday, August 13, 2012 8:43 AMModerator
Hi Sunyear,
Welcome to the MSDN forum.
I have not try your issue, and would you mind tell me what ‘slid the position of the slider is OK but always get the old value while invoke GetPos.’ means?
Do you mind when you slid the slider and then press button to get position, you will only get the old value or old position?
Have a nice day.
Regards,
Elegentin Xie [MSFT]
MSDN Community Support | Feedback to us
-
Monday, August 13, 2012 12:26 PM
Hi Sunyear,
Welcome to the MSDN forum.
I have not try your issue, and would you mind tell me what ‘slid the position of the slider is OK but always get the old value while invoke GetPos.’ means?
Do you mind when you slid the slider and then press button to get position, you will only get the old value or old position?
Have a nice day.
Regards,
Elegentin Xie [MSFT]
MSDN Community Support | Feedback to us
When I move the slider, the slider can been slid to the new location on the screen.
But OnCommand of the slid control had not been called.
If I try to call GetPos to the slid control then I got a old position "value".
The sild will go back to the old positon(on the screen) when the ribbon bar toggle from hiding to visible again.
I tried to write an inherited CMFCRibbonSlider class and replace the original CMFCRibbonSlider object by the new class object.
It did not work,even OnLButtonUp had not been invoked.
It makes me feel helpless.
The problem only happend while ribbon bar on minimize mode.
I guess Ribbon bar use CMFCRibbonSlider object copy on minimize mode,and miss to notify the
orginal slide object.Sunyear
-
Monday, August 13, 2012 2:26 PM
>But OnCommand of the slid control had not been called.
Sorry OnCommand of the slid control had been called but got old position value by GetPos method. ,Sunyear
-
Wednesday, August 15, 2012 7:12 AMSo strange, i have not reproduced your problem...
Please not forget mark your answer, and unmark your disagreed point.
-
Thursday, August 16, 2012 6:47 AM
So strange, i have not reproduced your problem...
Please not forget mark your answer, and unmark your disagreed point.
Dear i1freien,
It is easy to reproduce the problem.
Here is the simple project to show the problem :
https://docs.google.com/open?id=0B5ThNWuz5zJaaE56clRIamdodWc
The project is generated using the VS2010(with SP1) Wizard and default almost whole options.
I just add a slide control in the Home panel and wrote a event handle for the control:
CMainFrame::OnSlidertest()
This function display the current position of the slider when the slider event occurs.
Please test it on minimize mode of the ribbon bar.Sunyear
-
Friday, August 17, 2012 12:35 AM
The project is generated using the VS2010(with SP1) Wizard and default almost whole options.
Sunyear
Unfortunately, the link you posted does not work. It is redirected to the Google drive for free registration.
I have done exactly as you described and everything works as expected. You have mentioned:
"The project is generated using the VS2010(with SP1) Wizard and default almost whole options."I did it without "almost", adding slider using ribbon editor. What specifically did you change/add?
Did you try creating test project without changing anything?
Could you post a code snippet showing how did you declare your slider handler (CMainFrame::OnSlidertest)?
You can try posting your project using http://www.mediafire.com/
JohnCz
-
Friday, August 17, 2012 2:47 AM
The project is generated using the VS2010(with SP1) Wizard and default almost whole options.
Sunyear
Unfortunately, the link you posted does not work. It is redirected to the Google drive for free registration.
I have done exactly as you described and everything works as expected. You have mentioned:
"The project is generated using the VS2010(with SP1) Wizard and default almost whole options."I did it without "almost", adding slider using ribbon editor. What specifically did you change/add?
Did you try creating test project without changing anything?
Could you post a code snippet showing how did you declare your slider handler (CMainFrame::OnSlidertest)?
You can try posting your project using http://www.mediafire.com/
JohnCz
Hi John,
Sorry, I did not take into account the download log.
I upload the test roject to SkyDrive:
http://sdrv.ms/R5K3Ez
About "what did I change/Add to th project".
I used resource editor add a slid control to the ribbon.
Set the slide control range from 0 to 100.
The add the command handle as:void CMainFrame::OnSlidertest()
{
// TODO: Add your command handler code here
static int iTraceCount=0;
CMFCRibbonSlider *pSliderTest=DYNAMIC_DOWNCAST(CMFCRibbonSlider, m_wndRibbonBar.FindByID(ID_SLIDERTEST));
TRACE(_T("(%d)The Slide position is %d\n"), ++iTraceCount, pSliderTest->GetPos());
}By the way, you mentioned "everything works as expected" in your test.
Did you also using VS2010 to test it?Sunyear
-
Friday, August 17, 2012 1:01 PM
OK downloaded.
To answer your question: yes, I am using VS 2010 SP1 on Windows 7 64-bit.
After building your application as is, I was not able to reproduce the problem you described. As in my case all works as expected:- Slider position is reported to the Output window.
- Minimizing the ribbon does not affect the slider position.
- Restoring the ribbon does not affect the slider position.
I have tested it on Windows 7 SP1 and XP SP3, both 64-bit machines and in both cases VS 2010.
I even changed SDK from VS2010 to SDK 7.1 - the same results.
I really do not know what else I can do...
By the way, you do not have to incluse .suo and .sdf files when posting projects. This will reduce compressed file size.
JohnCz
- Edited by JohnCz Friday, August 17, 2012 1:04 PM
-
Saturday, August 18, 2012 5:52 PM
OK downloaded.
To answer your question: yes, I am using VS 2010 SP1 on Windows 7 64-bit.
After building your application as is, I was not able to reproduce the problem you described. As in my case all works as expected:- Slider position is reported to the Output window.
- Minimizing the ribbon does not affect the slider position.
- Restoring the ribbon does not affect the slider position.
I have tested it on Windows 7 SP1 and XP SP3, both 64-bit machines and in both cases VS 2010.
I even changed SDK from VS2010 to SDK 7.1 - the same results.
I really do not know what else I can do...
By the way, you do not have to incluse .suo and .sdf files when posting projects. This will reduce compressed file size.
JohnCz
I tried the test project under WIN7 x64 system.
The problem still exists.
Let we make sure no misunderstanding about "ribbon minimize mode".
Press Ctrl key with F1 then we can toggle Minimize/Maximize mode to ribbon bar.
The problem is while switch ribbon as Minimize mode.
OK, I rewrite the test project to show message to the view window.
Please download it :http://sdrv.ms/R8SIGv
There is an execution file in the release folder.
Please run it 1st and to see what happen on your computer.Sunyear
-
Sunday, August 19, 2012 10:53 AM
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
As in my case all works as expected:- Slider position is reported to the Output window.
- Minimizing the ribbon does not affect the slider position.
- Restoring the ribbon does not affect the slider position.
JohnCzHi John,
Sorry,I did not notice the details of your reply.
while the ribbon minimized, user still can hit "Home" of the Category,right?
Then the ribbon will shows on the screen again(like as maximize state but still in minimized mode).
So even the ribbon under minimize mode, user still can move the position of the slider.
I mean at this time, the ribbon does not report correct position while user move the the slider to a new position.
Sunyear
-
Sunday, August 19, 2012 1:45 PM
Hi Sunyear,
Same results: works as expexted.
Is the project you posted the same as the project you have experienced this problem or did you create another project just as a test app?
JohnCz
-
Sunday, August 19, 2012 5:59 PM
Hi Sunyear,
Same results: works as expexted.
Is the project you posted the same as the project you have experienced this problem or did you create another project just as a test app?
JohnCz
This problem occurred in an application is written.
I test it in different projects and different Windows version.
They all have the same problem.
It is incredible for you tested without any problems.
OK, I just run the test program and recorded the process to a AVI file.
Please download and play it, you can see what happened by my side:
http://sdrv.ms/SEKQd5Sunyear
-
Monday, August 20, 2012 4:10 AM
Hi all,
void CMFCRibbonSlider::OnLButtonUp(CPoint point)
I traced the code about CMFCRibbonSlider class today and found clue.
This may be the point of the problem.
Ribbon bar use copied object for all controls under minimize state.
The ribbon call CopyFrom method of copied object to get original data.
The point is the copied object got OnLButtonUp notification not original object!
Let take a look at what CMFCRibbonSlider::OnLButtonUp has done:
{
ASSERT_VALID(this);
CMFCRibbonBaseElement::OnLButtonUp(point);
if (m_nPressed == m_nHighlighted && !IsDisabled())
{
switch(m_nPressed)
{
case nZoomInIndex:
SetPos(m_nPos + m_nZoomIncrement);
break;
case nZoomOutIndex:
SetPos(m_nPos - m_nZoomIncrement);
break;
default:
SetPos(GetPosFromPoint(point.x));
break;
}
NotifyCommand();
}
}
OnLButtonUp update the new position( to the copied object) then notify to the event handle
(it is CMainFrame::OnSlidertest() on my test project).
Please note OnLButtonUp does not update new position to the original object.
So when I try get the slide position in CMainFrame::OnSlidertest().
CMFCRibbonSlider *pSliderTest=DYNAMIC_DOWNCAST(CMFCRibbonSlider, m_wndRibbonBar.FindByID(ID_SLIDERTEST));
//pSliderTest is the original object not the copied object so...
pSliderTest->GetPos() always got old value of the slider
The copied object will be destroyed while ribbon has been hide again.
Every thing in the copied object is gone :(CMFCRibbonSlider::OnLButtonUp is a virtual member.
It rekindled a ray of hope!
I wrote a CMyMFCRibbonSlider class that inherit from CMFCRibbonSlider。
Then I update new position to the original object(If it is exists)in CMyMFCRibbonSlider::OnLButtonUp
The test slider was replaced by my CMyMFCRibbonSlider object.
Unfortunately it doesnt work, because ribbon make CMFCRibbonSlider object under minimize mode.
It is not my CMyMFCRibbonSlider.
Is any one has idea for the problem?Sunyear
-
Tuesday, August 21, 2012 2:29 PMI have seen a video and now I have full understanding of your problem. It is not related to the fact that ribbon is minimized (hidden) or shown.
Ribbon bar use copied object for all controls under minimize state.
The ribbon call CopyFrom method of copied object to get original data.
Sunyear
The real scenario:
Ribbon hosts the set of categories and each category owns a tab, which is not a windows control but just an image drawn as a tab.
When ribbon is hidden and you click on the category (Tab), the ribbon calls tab’s object to set active category.
Tab, in turn calls ribbon to set active category passing its parent (category).
Now the ribbon makes a decision how to activate a category and depending on the value of the m_dwHideFlags it calls category to show as floating if the flag is set to AFX_RIBBONBAR_HIDE_ELEMENTS. The framework creates floating ribbon bar, hosted by the CMFCRibbonPanelMenu object derived from CMFCPopupMenu derived in turn from old good CMiniFrameWnd.
CMFCRibbonPanelMenu object instantiates CMFCRibbonPanelMenuBar object that in turn creates new category object and copies all panels and controls from original category object.
Now you are not dealing with ribbon object but with dealing with CMFCRibbonPanelMenu object hosting a copy of the category.
You are right; this copying is the source of the problem. While in the popup state, the copy of the slider receives mouse clicks and updated own position. When switched to shown state, CMFCRibbonPanelMenu object is destroyed but the slider position of the original slider is not updated.
I checked this behavior for edit control with spinner button and the spin value is the same in both ribbon states. The difference could be that edit control is the real windows control, not the mere shape as the slider is.
In order to change this behavior you would have to access CMFCRibbonPanelMenu that is a member of the tab base class: m_pPopupMenu. Unfortunately this is a private member and neither CMFCRibbonTab nor CMFCRibbonBaseElement provide access to it.
Overriding category class would require deriving class from CMFCRibbonPanelMenu, since copy is initiated in CMFCRibbonPanelMenu when new instance of the CMFCRibbonCategory type is created. Hence you would have to also derive class from CMFCRibbonPanelMenu.
Another words, it creates ripple cascading effect.
I have already spent several hours trying to figure out how to fix it an easy way but so far no prevail. I will keep trying but I am not sure if I have enough patience.
I think you have just discovered another MS blunder; in my opinion serious bug that may affect other ribbon elements.
Consider reporting this issue.
JohnCz
-
Tuesday, August 21, 2012 5:20 PM
I saw a post saying to modify CopyFrom() of CMFCRibbonSlider, CMFCRibbonBaseElement &s is our primary CMFCRibbonSlider,
http://blog.csdn.net/cmaxpath/article/details/7256228 (sorry it's in Chinese)
I overwrited CMFCRibbonSlider, CMFCRibbonConstructor, CMFCRibbonBar to fix loading ribbon elements from resource,
here is the fixed example : http://sdrv.ms/NCBIJj
in the post it says m_nZoomIncrement was not copied in CopyFrom(), i forgot to patch in my example
- Proposed As Answer by JohnCz Tuesday, August 21, 2012 8:31 PM
- Marked As Answer by Sunyear Huang Wednesday, August 22, 2012 8:02 AM
-
Tuesday, August 21, 2012 8:31 PM
I have spent another several hours and I was getting closer but after reading your post I stopped trying having everything given on the plate.
Yes, the key issue is to assign pointer to the source of the copy to m_pSrcSlider member.
On the top of it overriding ribbon class and ribbon construction class allowed to use slider derived class.
It was a very good work researching this. It is always better to find out that somebody else already resolved a problem and understand the solution than reinventing the wheel.
Thanks for sharing.
JohnCz
-
Wednesday, August 22, 2012 9:05 AM
I saw a post saying to modify CopyFrom() of CMFCRibbonSlider, CMFCRibbonBaseElement &s is our primary CMFCRibbonSlider,
http://blog.csdn.net/cmaxpath/article/details/7256228 (sorry it's in Chinese)
I overwrited CMFCRibbonSlider, CMFCRibbonConstructor, CMFCRibbonBar to fix loading ribbon elements from resource,
here is the fixed example : http://sdrv.ms/NCBIJj
in the post it says m_nZoomIncrement was not copied in CopyFrom(), i forgot to patch in my example
Hello Chih-Ching,
Thanks for your replay.
I test your fixed example and It is workable.
There are some additional information as following provided to the people in need.
1.
Save source pointer in CopyFrom and use it in OnLButtonUp is not save.
Event on our testing is OK but it can not guarantee that the source will not be destroyed.
I modified your CMFCRibbonSliderUG::OnLButtonUp
void CMFCRibbonSliderUG::OnLButtonUp(CPoint point)
{
ASSERT_VALID(this);
CMFCRibbonBaseElement::OnLButtonUp(point);
if (m_nPressed == m_nHighlighted && !IsDisabled())
{
switch(m_nPressed)
{
case nZoomInIndex:
SetPos(m_nPos + m_nZoomIncrement);
break;
case nZoomOutIndex:
SetPos(m_nPos - m_nZoomIncrement);
break;
default:
SetPos(GetPosFromPoint(point.x));
break;
}
//Sunyear: Find out all buttons has same ID in the top level ribbon bar
CMFCRibbonBar* pRibbonBar = GetTopLevelRibbonBar();
if (pRibbonBar != NULL)
{
ASSERT_VALID(pRibbonBar);
CArray<CMFCRibbonBaseElement*, CMFCRibbonBaseElement*> arButtons;
pRibbonBar->GetElementsByID(m_nID, arButtons);
for (int i = 0; i < arButtons.GetSize(); i++)
{
CMFCRibbonSliderUG* pOther = DYNAMIC_DOWNCAST(CMFCRibbonSliderUG, arButtons [i]);
if (pOther != NULL && pOther != this)
{
ASSERT_VALID(pOther);
pOther->SetPos(GetPos());
}
}
}
//
NotifyCommand();}
}2.
Because 1. find source object by itself so storage the source pointer have been unnecessary.
3.
Not only need to modify OnLButtonUp.
All calls to the NotifyCommand of the members need to do similar modifications.
They are such as OnMouseMove, OnAutoRepeat
For this reason, write a separate member function for "Find out all buttons has same ID in the top level ribbon bar"
may bea good idea.
4.
About m_nZoomIncrement you mentioned, I think it is not a important member.
If you are concerned about it then you should also consider writing back to the source as slide position.
Sunyear
- Edited by Sunyear Huang Wednesday, August 22, 2012 9:07 AM
- Edited by Sunyear Huang Wednesday, August 22, 2012 9:11 AM
- Edited by Sunyear Huang Wednesday, August 22, 2012 9:13 AM
- Edited by Sunyear Huang Wednesday, August 22, 2012 9:14 AM
-
Thursday, August 23, 2012 5:01 AM
Hello JohnCz & Chih-Ching,,
My nightmare is not over yet :(
I added a edit control intended to synchronize the slider.
It work well under maximize mode, but will not be able to work in the minimize mode(can also be said on category floating).
The reason is the same as before, but can not be solved using the same method.
I can update original edit object while got slider button's event, but I can not modified the copied edit object.
This is the first time I used VS2010 with ribbon interface to develop a project.
The feeling of MS ribbon was awful!
Here's example demonstrates the error : http://sdrv.ms/OV6Vlv
Sunyear
-
Friday, August 24, 2012 4:07 AM
I think you have to do what JohnCz mentioned, deriving class to access CMFCRibbonPanelMenuBar or CMFCRibbonPanelMenu

