Changing the style of CMFCMenuButton look like a regular button on my dialog [duplicate] - mfc

This question already has an answer here:
CMFCButton with Vista Style
(1 answer)
Closed 2 years ago.
I have a CMFCMenuButton control on my dialog:
CONTROL "Lookup",IDC_MFCMENUBUTTON_LOOKUP_PUBLISHER,
"MfcMenuButton",WS_TABSTOP,106,254,45,14
I initialize it like this:
m_menuLookupPublisher.LoadMenu(IDR_MENU_LOOKUP_PUBLISHER);
m_btnLookupPublisher.m_hMenu = m_menuLookupPublisher.GetSubMenu(0)->GetSafeHmenu();
It works fine:
Update
I have added some extra code (based on answer provided to me):
m_menuLookupPublisher.LoadMenu(IDR_MENU_LOOKUP_PUBLISHER);
m_btnLookupPublisher.m_hMenu = m_menuLookupPublisher.GetSubMenu(0)->GetSafeHmenu();
m_btnLookupPublisher.m_nFlatStyle = CMFCButton::BUTTONSTYLE_SEMIFLAT;
m_btnLookupPublisher.m_bDrawFocus = FALSE;
This improves the look and feel of the button now, but it is still not 100% the same. Here is what it looks like now when it does not have focus:
It is just the way the border is displayed that is not correct. EnableWindowsThemeing is TRUE by default so I am not sure what else I need to do here.
What's annoying is that in the VS IDE it looks fine:
My question concerns the visual display of the menu button. The border looks different that the other buttons. Can it be made to look the same without too much work?
Update
I stumbled on this question which is now pointing me in the right direction. If I add this code:
m_btnLookupPublisher.ModifyStyle(BS_OWNERDRAW, 0, 0);
Then is draws the border correctly etc. but renders other aspects of the button useless so it is not a viable solution. But the remainder of the answer is what I needed:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

Are you talking about 3D look? Then you need to specify "flat" style BUTTONSTYLE_FLAT:
https://learn.microsoft.com/en-us/cpp/mfc/reference/cmfcbutton-class?view=msvc-160#m_nflatstyle

Related

MSHTML editing - changing the text selection color

I use MSHTML (TWebBrowser control) in Design (edit) mode. I use TEmbeddedWB but slowly moving away from that component and implementing my own interface. When a block of text is selected, so when typing into the editor and then selecting a block of text it is in black color for the background color.
Instead I'd like to use blue.
I know that it has something to do with the selection range but not sure how to modify it in designer mode. The code below is of course when it is not in design mode.
IHTMLSelectionObject currentSelection = document.selection;
IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange;
if (range != null)
{
range.execCommand("BackColor", false, "0000FF");
}
Any ideas? Do I have to use event sinking? Or maybe QueryCommandValue? I tried some things with HiliteColor without success yet (according to Mozilla documentation this is not supported by Internet Explorer).
I use C++ Builder or Delphi, but code example in any language is welcome, I can (probably) translate it.

How can I adjust the size of a QDialog according to its title length?

One of my dialog window's title is shortened (like "My Dialogt..."). If the dialog was slightly wider, the whole title would be completely displayed, which would look nicer.
It seems as if there is no setting in Qt to do that. I have found a hack for a QMessageBox here: Can QMessageBox::about adjust size to title length?, but it is not general. For example it would have to take also the sizes of the icons to the left and to the right of the window title into account to compute a really good minimal size where still the title is completely shown.
Is there a general way to accomplish that? Is there also a simple way to do that? Or is this overengineering?
Not only this goal is questionable (see vahanco comment) but it is hard to achieve, because the window title bar is not Qt territory at all: apart from being able to set its text and manage to show or hide close/min/max button using window flags, there is little else in control, there.
By the way, a very raw way to set a dialog minimum width which could (could) make room to the whole text is the following:
const QString text = "Very very very very very very very very very very very very very long window title";
setWindowTitle(text);
QFontMetrics metrics(font(), this);
setMinimumWidth( metrics.horizontalAdvance(text));
This won't work out of the box, and it's very likely that the text stay cut, because the font used is supposed to be the same used in the title bar (which usually isn't) and we're not taking into account the frame width, the icon width, the title bar buttons width, and everything else which is owned by the window manager and is totally unknown to Qt.
So, you can figure out how much extra space is needed by all these stuff, and adjust the width with a totally arbitrary extra padding like
setMinimumWidth( metrics.horizontalAdvance(text) + 256);
and maybe get what you wanted in the first place (if you still really want it).
The accepted answer did not work for me.
The below code works in QT 5.15. According to the documentation after you call setMinumumWidth() you must call updateGeometry() update geometry docs. Setting minimumWidth should update the sizeHint. That was not happening for me. Also QFontMetrics::horizontalAdvance was not returning the width of the text. I had to use QFontMetrics::boundingRect({title_string}).width().
Calling resize on the dialog is what finally got it working for me. If the accepted answer doesn't work for you give this a try.
QString message = "Message for the user";
QInputDialog dialog = QInputDialog(this);
dialog.setLabelText(message);
QString longTitle = QString("Super long test title for making sure the widget will show all of the stupid long title.");
dialog.setWindowTitle(longTitle);
dialog.setInputMode(QInputDialog::TextInput);
auto fontMetrics = dialog.fontMetrics();
auto width = fontMetrics.boundingRect(longTitle).width();
dialog.resize(width + 200, dialog.rect().height());
const int ret = dialog.exec();

Reordering MFC control IDs automatically

I've got a pretty old MFC application that's been touched by many people over the years (most of them probably not even CS guys) and it follows, what I like to call the "anarchy design pattern."
Anyway, one of the dialogs has a series of 56 vertical sliders and check boxes. However, there are additional sliders and checkboxes on the dialog as shown below.
Now, the problem is that the additional sliders and checkboxes take on IDs that are in sequence with the slider/checkbox series of the dialog. My task is to add more sliders and checkboxes to the series (in the blank space in the Slider Control group box) Unfortunately, since IDC_SLIDER57 through IDC_SLIDER61 are already in the dialog (same goes for the checkboxes), existing code, such as the snippet below will break:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
Is there a better way to modify the resource file without doing it manually? I've seen a third party tool called ResOrg that looks like it'll help do what I want, but the software is a bit pricey, especially since I'll only use it once. I guess I can give the demo a try, but the limitations might restrict me.
FYI, I'm using Visual C++ 6.0 (yes...I know, don't laugh, it's being forced upon me).
Instead of writing:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
you could write:
pVSlider = (CSliderCtrl *)GetDlgItem(GetSliderID(i));
where GetSlider is a function that returns the id of slider number i.
GetSlider function
int GetSliderID(int nslider)
{
static int sliderids[] = {IDC_SLIDER1, IDC_SLIDER2, IDC_SLIDER3, .... IDC_SLIDERn};
ASSERT(nslider < _countof(sliderids));
return sliderids[nslider];
}
With this method the IDC_SLIDERn symbols dont need to have sequential values.

Why can't I add a string to a combo box?

This seems trivial, but with MFC I always end up with some stupid trivial problem that puts a stop to my workflow.
I am getting a "Debug Assertion Failed" error pointing to afxcmn2.inl line 352:
_AFXCMN_INLINE int CComboBoxEx::AddString(LPCTSTR lpszString)
{ UNUSED_ALWAYS(lpszString); ASSERT(FALSE); return CB_ERR;}
I am attempting to just add some strings to a combo box on initialization like so:
BOOL myDialog::OnInitDialog()
{
CDHtmlDialog::OnInitDialog();
cb_direction.AddString(CString("North"));
}
Most of the answers on Google seem to suggest that the AddString is happening before OnInitDialog, which doesn't seem to be the case here. Another series of answers on Google suggests the data exchange isn't happening or it's wrong, but it's not:
void myDialog::DoDataExchange(CDataExchange* pDX)
{
CDHtmlDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_WHEDIT_DIR, cb_direction);
}
Another suggestion was that the combo box hasn't been created yet, but if I disable the combobox using the following code, not only do I NOT get an error, but it actually works and disables the box!
BOOL myDialog::OnInitDialog()
{
CDHtmlDialog::OnInitDialog();
cb_direction.EnableWindow(FALSE);
}
I've cleaned the solution and rebuilt it. I'm not sure what else I am missing. And all I want to do is to add a string to a combo box, which would take 2 seconds in .Net (this program that was written years ago by someone else which is why it's in MFC rather than .Net, but I digress).
Entering the game a little late but, who knows, this might help someone someday:
COMBOBOXEXITEM item;
ZeroMemory(&item, sizeof(item));
item.mask = CBEIF_TEXT;
item.iItem = 0;
item.pszText = _T("Hello");
m_ComboEx.InsertItem(&item);
FWIW, AddString() functionality is removed from CComboEx because the purpose of the control is to display advanced items (with images, identation, whatever...), not straight regular text items.
Well if you look at what the method is doing they have an ASSERT(FALSE) in there, so no wonder. It doesn't actually do anything that would indicate it adds an item to the ComboBoxEx control. Per the docs
This function is not supported by the Windows ComboBoxEx control. For more information on this control, see ComboBoxEx Controls in the Platform SDK.
The documentation is your friend :)

How do I display a tooltip for a CMFCRibbonButton in the status bar?

I have a CMFCRibbonStatusBar in my mainframe to which I add a CMFCRibbonButtonsGroup which again has a CMFCRibbonButton. This button has the same ID as a menu entry.
Creating the button is done as follows:
CMFCRibbonButtonsGroup* pBGroup = new CMFCRibbonButtonsGroup();
CMFCToolBarImages images;
images.SetImageSize(CSize(32, 16)); // Non-square bitmaps
if(images.Load(IDB_STATUSBAR_IMAGES))
{
pBGroup->SetImages(&images, NULL, NULL);
}
m_pStatusButton = new CMFCRibbonButton(ID_STATUS_SHOWSTATUS,
_T(""),
IMAGEINDEX_DEFAULTSTATUS);
pBGroup->AddButton(m_pStatusButton);
m_wndStatusBar.AddExtendedElement(pBGroup, _T(""));
I want to use this button as a status indicator.
I want to display a tool tip in the following two cases:
when the status changes and
when the user moves the mouse over the button.
I have no idea how to start in the first place. I have looked at the ToolTipDemo and DlgToolTips sample projects but couldn't figure out how to do it since all they do is display tooltips for the toolbar items or dialog buttons (CWnd-derived instead of CMFCRibbonButton).
If you are familiar with the ToolTipDemo sample project: Since there seem to be several ways of doing things, I would prefer the tooltip to look like the "Extended Visual Manager-based" tool tip as shown in this screenshot.
Thanks!
I don't think it's possible to show the tooltip without the mouse cursor being over the control. That's all done automatically.
However if you want to have a nice looking tooltip like in your screenshot, you need to call SetToolTipText and SetDescription, like this:
CMFCRibbonButton* pBtn = new CMFCRibbonButton(12345, _T(""), 1);
pBtn->SetToolTipText("This is the bold Title");
pBtn->SetDescription("This is the not-so-bold Description");
pGroup->AddButton(pBtn);
I am using CMFCRibbonButton controls within a CMFCRibbonButtonGroup, which is added to the CMFCRibbonStatusBar. Take note of the 4th parameter in the CMFCRibbonButton() constructor, bAlwaysShowDescription, as this seems to affect the behavior depending upon whether SetDescription() has been called.
Specifically, if SetDescription() has not been called, it doesn't matter whether bAlwaysShowDescription is TRUE or FALSE - the tool tip is displayed (as I would expect). If SetDescription() is set and bAlwaysShowDescription is FALSE, when hovering over the button the tool tip is displayed with the description below it.
What seems counterintuitive given the name of this bAlwaysShowDescription parameter, is that when this is TRUE and SetDescription() is set, NEITHER the tool tip nor the description appear. I wonder if this is related to this post:
https://connect.microsoft.com/VisualStudio/feedback/details/399646/cmfcribbonbutton-wont-show-tooltip-if-balwaysshowdescription-1
Hope this helps and you can achieve what you need with the different combinations of bAlwaysShowDescription parameter and whether SetDescription() is set.