MFC: CCheckListBox items overlap - mfc

In a dialog template I placed a ListBox, since checked list box is not shown in the visual layout options. I set it to owner-draw and set it up with DDX, changing the associated class variable from type CListBox to CCheckListBox - in other words the only changes I make from what the wizard does for me are set owner-draw, and chnage the member variable type.
in my dialog's OnInitDialog method I then test with:
m_List.AddString(_T("One"));
m_List.AddString(_T("Two"));
m_List.AddString(_T("Three"));
m_List.AddString(_T("Four"));
m_List.SetCheck(1,1);
When I run the list is there, with 4 items and one checked, with the right strings. But, the item heights are wrong. It seems like the height of the checkbox is used to determine the item height, leading to the text overlapping the item below.
Shouldn't the default behavior of the class be to figure this out, without me having to individually set each item's height?

From MSDN:
If your checklist box is a default
checklist box (a list of strings with
the default-sized checkboxes to the
left of each), you can use the default
CCheckListBox::DrawItem to draw the
checklist box. Otherwise, you must
override the CListBox::CompareItem
function and the
CCheckListBox::DrawItem and
CCheckListBox::MeasureItem functions.
Looks like you either need to call the default implementation or implement your own MesaureItem/DrawItem. That's probably why the items seem to overlap.

In a check box, string case the following may be sufficient to prevent overlap:
class CCheckListBoxEx : public CCheckListBox
{
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// set item height once:
if ((GetStyle() & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS)) ==
(LBS_OWNERDRAWFIXED | LBS_HASSTRINGS) && m_cyText == 0)
{
SetItemHeight(0, CalcMinimumItemHeight() + 2);
}
// add some space between box and string:
lpDrawItemStruct->rcItem.left += 2;
CCheckListBox::DrawItem(lpDrawItemStruct);
}
};

Related

Qt trying to enable scrolling slightly beyond last element in QTableView

I'm making a sort of an Excel-type application in which I can load a tab-delimited text file and I am able to edit cells... etc
It's useable but I have an issue related to me allowing the user to "freeze" a number of columns/rows. ("Frozen" rows/columns can only be one of the first ones and are then "frozen", i.e. always displayed even when scrolling)
The whole frozen Col/Row is working but I would like the user to be able to scroll slightly past the last Col/Row in order to be able to only ever display full cells.
Right now when reaching the end of the scrollbar I end up with a partial leftmost column and topmost row because it's only displaying up to the last full col/row and not going a wee bit further for all content to be displayed fully.
I've tried doing adding some space to the maximum scrollbar value once everything is loaded in the table but it seems to have no effect :
table->horizontalScrollBar()->setMaximum(table->horizontalScrollBar()->maximum() + t->horizontalScrollBar()->singleStep()*2);
I tried multiple values too.
(Edit) There may be some Qt code that "snaps" the QTableView viewport back to the edge of the last cell automatically...
(Edit2) I connected verticalScrollbar's rangeChanged() signal to a custom slot with the following code:
void MyTableView::onRangeChanged(int min, int max) {
QScrollBar *sender = verticalScrollBar();
int newVMax = max + 20;
sender->blockSignals(true);
sender->setRange(min, newVMax);
sender->blockSignals(false);
}
Sadly there is definitely a snapback mechanic when scrolling to the end of verticalScrollbar...
Gif of snap back issue
(Edit3) The snap back may be related to:
void QHeaderViewPrivate::setScrollOffset(const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode)
{
Q_Q(QHeaderView);
if (scrollMode == QAbstractItemView::ScrollPerItem) {
if (scrollBar->maximum() > 0 && scrollBar->value() == scrollBar->maximum())
q->setOffsetToLastSection();
else
q->setOffsetToSectionPosition(scrollBar->value());
} else {
q->setOffset(scrollBar->value());
}
}
mainly:
if (scrollBar->maximum() > 0 && scrollBar->value() == scrollBar->maximum())
q->setOffsetToLastSection();

1-indexed Model in QCombobox

I have a 1-indexed (readonly-)model and want to use it for a combobox.
I parse the data (comes from a file-parser) and have for example:
1: Variable Number 1 and that will be my first item, next
2: Variable Number 2 and so on.
When I click on an item the currentIndex()-method from QCombobox will give me a 0-indexed int, so my problem is:
I don't want to write everytime I parse a file +1 respectively -1 when writing back to the file (although the model is readonly, I can alter the data in the file). (I have nearly 30 UIs where I need the model, and for every UI I have to parse other data)
I currently use something like:
virtual int currentIndex() const { return QComboBox::currentIndex() + 1; }
virtual void setCurrentIndex(int index) { QComboBox::setCurrentIndex(index-1); }
I know that this is not ideal, because (set-)currentIndex is not virtual. But to avoid +/-1 I used this for now.
Does anybode have a good suggestion for this problem?
If you have a custom model you could add a role that returns the "real" index value.
If you just use strings to fill the combobox, you could use the setItemData() and itemData() methods to associated your reference value.
E.g.
comboBox->addItem("Number 1", 1);
and
int refValue = comboBox->itemData(comboIndex).toInt();
The associated data can be anything that can be stored in a QVariant.

How can I set the color of a specific line in a libgdx list?

I am developing a list and I want to highlight certain lines by showing the font color in red. Is this possible?
EDIT:
Ok, here a simplified version of my code:
Skin defListSkin = new Skin(Gdx.files.internal("data/uiskin.json"));
List listHistory = new List<String>(defSkin);
// Here I set the general font color for the list
List.ListStyle listStyle = listHistory.getStyle();
listStyle.font = fontList;
listStyle.fontColorUnselected = Color.LIGHT_GRAY;
listHistory.setStyle(listStyle);
String[] items = new String[20];
// Example of item[]
// item[0]: "John 12"
// item[1]: "Amy -3" <-- I want certain lines to appear in red (e.g. those with negative numbers)
// Populate the list
listHistory.setItems(items);
// Drawing the list (actual draw happens in render() of course)
Table myTable = new Table();
myTable.add(listHistory);
stage.addActor(myTable);
Use the Color Markup Language that Libgdx supports.
The markup syntax is really simple but still versatile:
[name] Sets the color by name. There are a few predefined colors, see the Colors.reset() method for an exhaustive list. Users can define their own colors through the methods of the Colors class.
[#xxxxxxxx] Sets the color specified by the hex value xxxxxxxx in the form RRGGBBAA where AA is optional and defaults to 0xFF.
[] Sets the color to the previous color (kind of optional end tag)
[[ Escapes the left bracket.
Markup is disabled by default. Use the public member font.getData().markupEnabled to turn it on/off.
Reference: https://github.com/libgdx/libgdx/wiki/Color-Markup-Language
If you want a more complex html like markup you can use those templates: https://github.com/czyzby/gdx-lml, live tests: http://czyzby.github.io/gdx-lml-tests/
I know what you mean, and I don't think it is possible. The list items are all linked to the same listStyle, and the only way to change the color of the list items is to make a new style for listHistory and change the font color of this style, however if you do this, it changes every item in the list to that new font color. My suggestion would be to create two separate lists and two separate ListStyles and the lines you want red be in one list and have one style and the lines you don't want to be red be in another list and have a different style. Hope this helps

COM IContextMenu::InvokeCommand - matching LPCMINVOKECOMMANDINFO::lpVerb to item

I have created a shell extension for windows with COM, however I seem to fail to properly match the ids of items I add in the overload of IContextMenu::QueryContextMenu with what I receive in the overload of IContextMenu::InvokeCommand. In my code I use InsertMenu and InsertMenuItem (as far as I understood they do the same, but the latter has some more features?). However I'm not sure which arguments passed to InsertMenu/InsertMenuItem correspond to what I must be looking for in LPCMINVOKECOMMANDINFO::lpVerb. I need some way to easily know that when I add items x, y, z to a context menu, I can then know exactly which one of x, y or z has been clicked.
EDIT: It seems that the verb equals the number from top to bottom of the item in the current menu/submenu. However I have two sub-menus each with x amount of items, so they have the same IDs of 1,2,3. How do I set custom IDs or something?
Firstly you should define an enum that holds the command IDs for your menu items, e.g.
enum {
CMDID_FIRST = 0,
CMDID_DOSOMETHING = CMDID_FIRST,
CMDID_DOSOMETHINGELSE,
CMDID_LAST,
};
These ID values need to start from 0.
In your IContextMenu::QueryContextMenu implementation:
when you add your menu items you need to give each of them an ID by setting the MIIM_ID flag in the MENUITEMINFO.fMask field, and setting the MENUITEMINFO.wID value.
give each of your menu items an ID derived from its command ID as defined above, plus the value of idCmdFirst which is passed into QueryContextMenu. E.g. the "Do Something" menu item would have MENUITEMINFO.wID set to idCmdFirst + CMDID_DOSOMETHING, and "Do Something Else" would have MENUITEMINFO.wID set to idCmdFirst + CMDID_DOSOMETHINGELSE.
the return value from QueryContextMenu needs to be MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, x) where x is the ID of the highest-numbered item you added plus 1 (alternatively, if all items were sequentially numbered, the total number of items). Basically, you're telling the host which menu item ID values are now in use so that no other context menu extensions add items that clash with yours. In the above example, you'd return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, CMDID_LAST).
In IContextMenu::InvokeCommand:
test if lpVerb (or lpVerbW) is an integer value using the IS_INTRESOURCE macro.
if so, the command ID can be found in the low word. E.g, if the user selected "Do Something Else", you would find that LOWORD(lpVerb) == CMDID_DOSOMETHINGELSE.

Get data from selected row of gtk treeview - gtkmm, c++

I have a GTK application that has a window with a treeview and a button. When the button is clicked I need to get the data from the first (and only) column of the selected row in the treeview.
This is the class for the columns:
class ModelColumns:
public Gtk::TreeModel::ColumnRecord{
public:
ModelColumns(){ add(m_port_name); }
Gtk::TreeModelColumn<Glib::ustring> m_port_name;
};
This is like in the example here but with only one column: http://www.lugod.org/presentations/gtkmm/treeview.html
This is the button click signal handler at the moment:
tvPorts is the treeview widget
tvPortsList is the listStore for the treeview
static
void on_btnPortSelectOK_clicked (){
Glib::RefPtr<Gtk::TreeSelection> selection = tvPorts->get_selection();
Gtk::TreeModel::iterator selectedRow = selection->get_selected();
//Now what?
//Need to get data from selected row to display it.
}
I have searched the documentation and many examples to try and find out what to do next but can't find any examples for gtkmm, I can only find examples for c or python implementations.
As far as I can tell, I need to get a TreeRow object from my iterator (selectedRow) how do I do this?
Thanks.
Update:
I am now using this code and it almost works.
The only problem is that it prints the previous selection.
The first time I select something and then press the button it prints only a new line. The second time it prints what was selected the first time, the third prints the second, etc.
Glib::RefPtr<Gtk::TreeSelection> selection = tvPorts->get_selection();
Gtk::TreeModel::iterator selectedRow = selection->get_selected();
Gtk::TreeModel::Row row = *selectedRow;
Glib::ustring port = row.get_value(m_Columns.m_port_name);
printf("\nselected port: %s", port.data());
This seems odd.
(m_Columns is an instance of the ModelColumns class)
Update 2:
Fixed the problem by adding fflush(stdout);
It all works now, thanks.
The docs say to simply dereference the iter to get the TreeRow:
Gtk::TreeModel::Row row = *iter; // 'iter' being your 'selectedRow'
std::cout<<row[0];