Changing text color of ribbon button - c++

I'm having an issue in VS2013-15 where my buttons' font colour is a shade of grey rather than black.
Here is what the buttons look like currently:
Some of the text seems to change to the desired colour when hovered over. However, some don't changed even when hovered:
Any help would be greatly appreciated. Thanks.

I managed to fix it using Barmak's answer. The Windows 7 theme is the problem.
To fix, you have 2 options.
Option 1
Change the theme your program uses
This is a lazy work around. Just switch your visual manager from CMFCVisualManagerWindows7 to one of the other visual managers.
Option 2
Override the OnUpdateSystemColors() function
First off you'll need a new class that inherits CMFCVisualManagerWindows7:
class Win7VM : public CMFCVisualManagerWindows7
{
};
Then you'll need to call DECLARE_DYNCREATE as the object is created dynamically at runtime.
class Win7VM : public CMFCVisualManagerWindows7
{
DECLARE_DYNCREATE(Win7VM);
};
Next, you'll need to implement the class.
class Win7VM : public CMFCVisualManagerWindows7
{
DECLARE_DYNCREATE(Win7VM)
virtual void OnUpdateSystemColors()
{
CMFCVisualManagerWindows7::OnUpdateSystemColors();
m_clrRibbonPanelCaptionText = RGB(0, 0, 0);
}
};
After that, you need to call IMPLEMENT_DYNCREATE separate to your class implementation, in global scope.
IMPLEMENT_DYNCREATE(Win7VM, CMFCVisualManagerWindows7);
Finally, we need to change our usage of CMFCVisualManagerWindows7 to that of our new class:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(Win7VM));

Related

Create a window of custom class type in Qt

This is my first question here, so I'm trying to not sound stupid!
EXPLANATION:
I have a main window in Qt that has a button to create (sub-?) windows within the main window. This can be done as many times as the user wants, and each sub-window displays the same set of properties/items. I figured writing a class to hold all these properties would be a smart way to go about it (this would inherit the main window class), as each instance of the child window would automatically get the properties. I am using a slot to create each instance.
QUESTION:
Besides the desired properties, what do I add to the child window class to let Qt know that if I create an object of that type it should open a window?
For example, say I have implemented all the child window properties in a header file that looks something like this:
#include <QObject>
#include <QDialog> //Not sure about this
class ChildWindow : public ParentWindow
{
Q_OBJECT
public:
ChildWindow(QObject* parent);
~ChildWindow();
//Remaining properties like QSpinBox, Radio buttons etc
}
how then would I implement my slot? Like this?
void Parent::Slot()
{
ChildWindow* window;
window = new ChildWindow(this);
window->show()
}
My problem is that I don't see any code that indicates that window is a separate window. I can see that it is of type ChildWindow, but does just including QDialog give it the show() functionality?
EDIT:
I realise the first suggestion would be try and see if this works, but in the unlikely scenario that it works I wouldn't have learnt anything and I still wouldn't know why it worked, and if it didn't I would be back here asking this same question. I hope you guys understand.
EDIT 2:
error C2039: 'show' : is not a member of 'ChildWindow'
So I am guessing including QDialog did not do the trick
EDIT 3:
If I add this to the ChildWindow constructor
QDialog* child;
child = new QDialog;
child->show()
Do I have to do the same in the slot definition as well?

Set CSS in QPushButton's subclass's constructor

I'm creating my custom push button class by subclassing QPushButton. However for some reason setting that class's CSS in its constructor has no effect; I have to do it in for example paintEvent, then everything is fine. I could just have a global .qss file and set it for the entire application, but I want the class to manage its own styles. Why doesn't my approach work?
The code:
custompushbutton.h
class CustomPushButton: public QPushButton
{
Q_OBJECT
public:
explicit CustomPushButton(QWidget *parent = 0);
~CustomPushButton() = default;
};
custompushbutton.cpp
CustomPushButton::CustomPushButton(QWidget *parent)
: QPushButton(parent)
{
setStyleSheet("background-color: black;"); // this does not work
}
EDIT: For future readers, if you're having a similar issue (i.e. Qt seems to ignore your CSS you set in code), see if you haven't edited the object's styleSheet property in Qt Creator - scroll down in the properties list and make sure styleSheet is empty and NOT BOLD - that was the issue in my case. If it is bold, it means Qt is still using that empty field as the object's CSS, thereby overriding your styles. To clear it either hit the little arrow next to the field in Qt Creator or open up the .ui file and delete the <styleSheet> XML property.
Thanks to JMik for pointing me in the right direction.
The performance cost of setting a stylesheet is surprisingly high, especially if you're developing for an embedded system.
I'd suggest, like you said, using a global stylesheet and specify the class name, like this:
CustomPushButton { background-color: black; }
this way all CustomPushButton will have the same style, and the object will take less time to create.
As for the reason why it doesn't work in your case, I'd guess maybe your accidentally changing the stylesheet again after the creation of the CustomPushButton.
I tested your code on my side and it worked, so it probably has something to do with code your not showing

MFC: How to custom draw a dynamically created CListCtrl

I need to customize the head/row height of a CListCtrl. After some googling, I know that I need to subclass CListCtrl, so I wrote my own list class, with the outline as follows:
class CListCtrlCl : public CListCtrl
{
DECLARE_DYNAMIC(CListCtrlCl)
public:
...
BEGIN_MESSAGE_MAP(CListCtrlCl, CListCtrl)
ON_WM_MEASUREITEM()
ON_WM_MEASUREITEM_REFLECT()
END_MESSAGE_MAP()
void CListCtrlCl::PreSubclassWindow()
{
ModifyStyle(0,LVS_OWNERDRAWFIXED);
CListCtrl::PreSubclassWindow();
CHeaderCtrl *pHeader = GetHeaderCtrl();
m_Header.SubclassWindow(pHeader->GetSafeHwnd());
}
void CListCtrlCl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
if (m_nRowHeight>0)
{
lpMeasureItemStruct->itemHeight = 100;
}
}
The problem is that this method worked if I drag a CListCtrl control in dialog template, but if I create this listctrl dynamically, like:
BOOL CListCtrlTestDlg::OnInitDialog()
{
CRect rect(7,7,300,300);
this->m_ListCtrl.Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|LVS_REPORT|LVS_ALIGNLEFT|WS_BORDER | WS_TABSTOP, rect, this,IDC_LIST1 + 1);
SetWindowLong(m_ListCtrl.m_hWnd ,GWL_EXSTYLE,WS_EX_CLIENTEDGE);
m_ListCtrl.SetExtendedStyle(LVS_EX_GRIDLINES);
::SendMessage(m_ListCtrl.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
...
Then the customization code just doesn't take effect. Whatever I did, the result listctrl is the standard one without any customization. But I need to create this listctrl dynamically, so could anyone tell me what I need to do to make dynamically created clistctrl customizable?
Thanks.
You've left off the necessary style for custom drawing when you create the control. Add LVS_OWNERDRAWFIXED. That should fix your problem.
The reason is that, PreSubclassWindow is only called when you subclass a control. When you createthe control you have also control over the style.
Simply overwrite the virtual Create function and just add the style like you are doing it in the PreSubclassWindow function. Than call the base class. You can also overwrite PreCreateWindow.
But much simpler than using the ownerdraw feature is cusum draw.

Changing default sort arrows of CMFCListCtrl

I found a problem. I can't change default sort arrows in header of CMFCListCtrl.
I found post on msdn about CMFCHeaderCtrl::OnDrawSortArrow but it didn't help because no examples there.
I tried simple method how I set arrows to CListCtrl header through the CimageList and HDITEM but those arrow sets only to left side because right side has already arrow default.
Google is empty on solutions how change default arrows on CMFCListCTrl.
Please help me)
Thanks!
PS. Please note that this is CMFCListCtrl not a CListCtrl where I can add arrows very easly.
Because CMFCHeaderCtrl is a member inside CMFCListCtrl you can not overwrite it.
Try to derive yor own CMFCListCtrl class, with your own CMFCHeaderCtrl class, that overwrites OnDrawSortHeader OnDrawSortArrow.
Overwrite CMFCListCtrl::InitHeader and subclass to your header control class.
If you start form scratch with a CListCtrl you can directly subclass the header control. The complete stuff inside CMFCListCtrl isn't so complicated and easy to reimplement. Depends what functionality you need.
The CMFCHeaderCtrl calls the currently active Visual Manager to do the actual drawing of sort arrows. It is easy to implement a customized Visual manager which overrides the arrow drawing method in the base class.
class CMyVisualManager:public CMFCVisualManagerOffice2007
{
virtual void OnDrawHeaderCtrlSortArrow(CMFCHeaderCtrl* pCtrl, CDC* pDC, CRect& rect, BOOL bIsUp);
};
void CMyVisualManager::OnDrawHeaderCtrlSortArrow(CMFCHeaderCtrl* pCtrl, CDC* pDC, CRect& rectArrow, BOOL bIsUp)
{
BOOL bDlgCtrl = pCtrl->IsDialogControl();
CPen penDark(PS_SOLID, 1, bDlgCtrl ? afxGlobalData.clrBtnDkShadow : afxGlobalData.clrBarDkShadow);
CPen* pPenOld = pDC->SelectObject(&penDark);;
ASSERT_VALID(pPenOld);
if (!bIsUp)
{
pDC->MoveTo(rectArrow.CenterPoint().x, rectArrow.bottom);
pDC->LineTo(rectArrow.CenterPoint().x, rectArrow.top);
pDC->MoveTo(rectArrow.CenterPoint().x-2, rectArrow.top+4);
pDC->LineTo(rectArrow.CenterPoint().x+3, rectArrow.top+4);
pDC->MoveTo(rectArrow.CenterPoint().x-1, rectArrow.top+3);
pDC->LineTo(rectArrow.CenterPoint().x+2, rectArrow.top+3);
pDC->MoveTo(rectArrow.CenterPoint().x-1, rectArrow.top+2);
pDC->LineTo(rectArrow.CenterPoint().x+2, rectArrow.top+2);
}
else
{
pDC->MoveTo(rectArrow.CenterPoint().x, rectArrow.top);
pDC->LineTo(rectArrow.CenterPoint().x, rectArrow.bottom);
pDC->MoveTo(rectArrow.CenterPoint().x-2, rectArrow.bottom-4);
pDC->LineTo(rectArrow.CenterPoint().x+3, rectArrow.bottom-4);
pDC->MoveTo(rectArrow.CenterPoint().x-1, rectArrow.bottom-3);
pDC->LineTo(rectArrow.CenterPoint().x+2, rectArrow.bottom-3);
pDC->MoveTo(rectArrow.CenterPoint().x-1, rectArrow.bottom-2);
pDC->LineTo(rectArrow.CenterPoint().x+2, rectArrow.bottom-2);
}
pDC->SelectObject(pPenOld);
}

Promoting code reuse for this situation

This is a bit tricky to explain but I will try my best to explain it.
I'm making a Gui API for games and it has Themes.
First I'll explain how Widgets work.
A Button for example, inherits from Widget.
Themes work similarly.
ButtonTheme inherits from WidgetTheme.
Inside each widget class, there is an instance of its corrosponding Theme.
Widget class has:
private:
static WidgetTheme widgetTheme;
public:
static WidgetTheme& getWidgetTheme();
button class has:
private:
static ButtonTheme buttonTheme;
public:
static ButtonTheme& getButtonTheme();
the Widget constructor, builds itself from its theme ex:
Widget()
{
setFont(getWidgetTheme().getFont());
}
the Button, inheriting from WidgetTheme, has to do the same ones because the internal widget will not know to construct from ButtonTheme, so my button ends up having to do:
Button()
{
setFont(getButtonTheme().getFont());
setButtonPadding(getButtonTheme().getButtonPadding());
}
This is where my problem is. It really feels wrong that I have to reprovide all the WidgetTheme ones and redirect them to ButtonTheme's parameters for Widget. If I do not do this, a SuperButton would inherit the styles of Button which would also inherit the styles of Widget, but what I want is for SuperButton to use its version of ButtonTheme and WidgetTheme because SuperButtonTheme would inherit from ButtonTheme and WidgetTheme.
Is there a way I could redesign this so that the constructor only has to set parts of the theme that it brings, and not have to set those of its parents?
Thanks
A virtual getTheme() (as drewish suggests) but using covariant return types ought to solve your problem without requiring casts.
The Widget constructor can accept a WidgetTheme and use that.
Widget(const WidgetTheme& theme)
{
setFont(theme.getFont());
}
Button() : Widget(getButtonTheme())
{
setButtonPadding(getButtonTheme().getButtonPadding());
}
I'm not quite clear on where getButtonTheme() and getWidgetTheme() live in your object hierarchy but it seems like it should be up to the class to know what its theme is so why not have a getTheme() method on your class? Maybe I'm too used to scripting languages and not appreciating some issues with strict typing.