TreeView_SetExtendedStyle does not apply certain styles, what am I doing wrong? - c++

I wanted to "play around" with new extended styles, especially the ones that manipulate with checkboxes.
The problem is that none of them seem to work.
I can not determine if TVS_EX_DOUBLEBUFFER works or not, because my treeview is small. I haven't tested TVS_EX_RICHTOOLTIP yet. Apart from that, no matter what other style I set, I am unable to see any effect.
Here is the relevant snippet:
HWND hwndTV = CreateWindowEx(...);
// first, add checkboxes
DWORD dwStyle = GetWindowLong(hwndTV, GWL_STYLE);
dwStyle |= TVS_CHECKBOXES;
SetWindowLongPtr(hwndTV, GWL_STYLE, dwStyle);
// now add extended window styles
HRESULT h = TreeView_SetExtendedStyle(hwndTV,
TVS_EX_PARTIALCHECKBOXES, TVS_EX_PARTIALCHECKBOXES);
// insert items...
I have checked the return value of the TreeView_SetExtendedStyle macro and it did not fail, which increases my frustration even more.
QUESTION:
Can you show me how to properly apply extended styles? For example, how to properly set TVS_EX_PARTIALCHECKBOXES or any other?
Thank you.

There's nothing wrong with how you're setting the style - it's when you're setting it that's the problem.
You need to set the TVS_EX_PARTIALCHECKBOXES extended style before you set TVS_CHECKBOXES. This is because setting TVS_CHECKBOXES triggers the creation of a state imagelist for the treeview, and this imagelist only includes the "partial" images if the partial style is set at the time it's created. The imagelist isn't recreated automatically if TVS_EX_PARTIALCHECKBOXES is set later on.
Additionally, you can't specify TVS_CHECKBOXES in the call to CreateWindowEx if you want to use the partial checkboxes style, since there's no way to set TVS_EX_PARTIALCHECKBOXES until the control has been created.

Related

3-state checkbox Win32 runtime

When I add the BS_AUTO3STATE style to a default-styled checkbox on a dialog window like so at runtime;
this->Style |= BS_AUTO3STATE; // wrapper of Get/SetWindowLongPtr, ignore the specifics
.. it turns into a group box rather than a 3-state checkbox. What am I doing wrong?
Have I got the wrong control style?
This problem is caused by the fact that the BS_Xxx values are not actually defined in the headers to work as bit flags. Instead, their values just increase linearly:
#define BS_PUSHBUTTON 0x00000000L
#define BS_DEFPUSHBUTTON 0x00000001L
#define BS_CHECKBOX 0x00000002L
#define BS_AUTOCHECKBOX 0x00000003L
#define BS_RADIOBUTTON 0x00000004L
#define BS_3STATE 0x00000005L
#define BS_AUTO3STATE 0x00000006L
#define BS_GROUPBOX 0x00000007L
#define BS_USERBUTTON 0x00000008L
#define BS_AUTORADIOBUTTON 0x00000009L
// ... and so on
Note that BS_GROUPBOX (which is the style you're getting and don't want) is equal to 0x7. Your control is ending up with that style flag set because you're setting a combination of flags that works out to have a value of 0x7. Unfortunately, you can't just OR the flags together and get the result you desire.
Instead, you'll have to clear out the current button style using the BS_TYPEMASK flag and then set the individual BS_Xxx flag that you desire. For a normal checkbox, that is probably BS_AUTOCHECKBOX; for a 3-state checkbox, that is BS_AUTO3STATE.
Working sample code:
void ToggleCheckboxCtrl(HWND hwndCheckBox)
{
// Retrieve the control's current styles.
LONG_PTR styles = GetWindowLongPtr(hwndCheckBox, GWL_STYLE);
// Remove any button styles that may be set so they don't interfere
// (but maintain any general window styles that are also set).
styles &= ~BS_TYPEMASK;
// Just for example purposes, we're maintain our last state as a static var.
// In the real code, you probably have a better way of determining this!
static bool isRegularCheckBox = true;
if (isRegularCheckBox)
{
// If we're a regular checkbox, toggle us to a 3-state checkbox.
styles |= BS_AUTO3STATE;
}
else
{
// Otherwise, we want to go back to being a regular checkbox.
styles |= BS_AUTOCHECKBOX;
}
isSet = !isSet;
// Update the control's styles.
// (You'll also need to force a repaint to see your changes.)
SetWindowLongPtr(hwndCheckBox, GWL_STYLE, styles);
}
The Spy++ utility (bundled with Visual Studio) is an indispensable little utility for figuring out what is going wrong when toggling window styles. Run your app, and use Spy++ to locate the window and enumerate its current styles. Then change the styles, dump the new styles with Spy++, and see what went wrong.

How to create a bold and italic label in MFC?

Please do not mark it as a dupe of this question just yet:
Bold labels in MFC
That question does not help me; for some reason I do not see the rich edit control. Instead I believe I have to do it in code. here is a sample I found:
http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2006-10/msg00245.html
My problem is that I prefer not to re-invent the wheel and test for errors myself or through QA.
Someone must have implemented this before. Please share your code.
What I would like to do is:
Keep the same font size, family, etc. as in the already created label, but make it bold and italic as well.
Keep the memory footprint reasonably low (do not create any new unnecessary objects), but do not get the app into an inconsistent state either.
I appreciate your help.
You will want to do the following before the static text control is shown on the parent window.
Get a handle to the window: CWnd * pwnd = GetDlgItem(IDC_LABEL);
Get the current font for the static text: CFont * pfont = pwnd->GetFont();
Get the characteristics of the font: LOGFONT lf; pfont->GetLogFont(&lf);
Change the lfWeight and lfItalic fields in lf.
Put a CFont object in your parent window, so it will exist for the entire lifetime of the child window.
Initialize the CFont: m_font.CreateFontIndirect(&lf);
Set the font into the static text window: pwnd->SetFont(&m_font);

How to create a multicolumn Listbox?

I'm working on a program, which should list all files and it's size(for now...). I created a simple application, which should write the data to a listbox. I'm trying to write the data in two columns(the first should be the name, and next to it, in an other column, it's size), but i can't figure out, how should i do this.
Can someone help me?
Thanks in advance!
kampi
Update:
I try to use ListControl., but unfortunately i can't. I can succesfully compile my App, but i can only see, the empty rectangle. Does someone know what i am doing wrong?
BOOL CGetFileListDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
LVITEM lvItem;
LVCOLUMN lvColumn;
int nCol;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_CENTER;
lvColumn.cx = 10;
lvColumn.pszText = _T("Filename");
ListView_InsertColumn( m_List, 0, &lvColumn );
ListView_SetItemText( m_List, 0, 0, _T("TEST") );
return TRUE; // return TRUE unless you set the focus to a control
}
The list box control does support multiple columns, but it only supports a single series of entries; the multiple column support just makes the items continue onto the next columns so that vertical scrolling is not necessary.
As Kornel has suggested, a list view control may be more appropriate. After creating a list view control, use ListView_InsertColumn to create the columns. Then use ListView_SetItemText to insert items.
EDIT:
My apoligies; you should use ListView_InsertItem to insert an item (a row) and then use ListView_SetItemText to alter the subitems (columns). If the list view is still just a blank box without any headings, have you initialised common controls? This can be done using InitCommonControlsEx, specifying the ICC_LISTVIEW_CLASSES constant. This should be done before creating the control.
See Microsoft's documentation on list view controls.
Don't use a List Box, use a List Control with LVS_REPORT style.
Maybe to use DataGridView with object as data source.
Three important parameters to be checked are
List Box or the List Control (List Control is to be used)
View parameter must be Report mode
Owner Data must be set to False
The screenshot shows these
The programming flow to add data to list control are Change the list Control to extended list view(ListView_SetExtendedListViewStyle), Create the layout(By adding columns), Add Item data (for each row needed) & add finally add sub-item to each column (for each item data added previously).

Motif main window w/o system menu, minimize and maximize boxes how? (C++)

How do I create a Motif main window that doesn't have a system menu, minimize and maximize boxes? I just cannot find out how by googling and reading docs and tutorials. I believe that it should be possible with some additional parameters for XtVaCreateManagedWindow, but which?
I have tried several variants of XtVaSetValues (topWid, XmNmwmDecorations, ...) but none worked. Instead I get an error message that I need to use a vendor shell for this. Most widget types aren't derived from vendor shells however, and when I e.g. try to use a dialog shell and put a scrollable text widget inside of it, then then text widget seems to control the dialog.
Apparently it's not (easily) possible to get rid of the window (system) menu, but it seems to be possible to disable window menu items with some code like this:
int i;
XtVaGetValues (widget, XmNmwmFunctions, &i);
i &= ~(MWM_FUNC_ALL | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE);
XtVaSetValues (widget, XmNmwmFunctions, i);
which removes the related window decoration too and apparently even works for non vendor shell widgets.
There should also be the possibility to remove the decorations (i.e. make them invisible). However, please note that these "system menu" decorations belong to the Window Manager, not your Motif program itself. It is up to the Window Manager to handle your requests or disregard them--you might get vendor-specific behavior with any MWM resources.
Anyway, here's the code sample to try out:
int decors; //bit-mask of flags defining the decorations, from Xm/MwmUtil.h
XtVaGetValues(dlg, XmNmwmDecorations, &decors, NULL);
decors &= ~MWM_DECOR_MENU;
decors &= ~MWM_DECOR_MAXIMIZE;
decors &= ~MWM_DECOR_MINIMIZE;
XtVaSetValues(dlg, XmNmwmDecorations, decors, NULL);
If you intend to run your application from Mwm, you can achieve the desired behavior by setting (e.g. via XtVaAppInitialize()) the following X11 resources:
! Title bar buttons
Mwm*YourApplicationClassHere.clientDecoration: -minimize -maximize
! Window menu functions
Mwm*YourApplicationClassHere.clientFunctions: -minimize -maximize
These resources are explained in more detail here and here.
Speaking of window menu, this one depends on a specific window manager in use. Mwm, for instance, allows the client to set the menu name using Mwm*YourApplicationClassHere.windowMenu resource, the menu itself must be defined in either ${HOME}/.mwmrc or global mwmrc, or XmNmwmMenu resource of VendorShell. The resulting custom window menu is exposed as a _MOTIF_WM_MENU atom, which seems to be ignored by modern window managers.
Sample mwmrc menu definitions may look like this
Menu CustomMenu0
{
Restore _R Alt<Key>F5 f.restore
Move _M Alt<Key>F7 f.move
Size _S Alt<Key>F8 f.resize
Minimize _n Alt<Key>F9 f.minimize
Maximize _x Alt<Key>F10 f.maximize
Lower _L Alt<Key>F3 f.lower
no-label f.separator
Pass\ Keys _K f.pass_keys
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
Menu CustomMenu1
{
Your\ Application\ Name\ Here f.title
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
(see the function descriptions). Custom menu items can be added using f.send_msg (examples here and here).
I'm pretty sure all of the above also applies to Dtwm (CDE).

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.