Select full row using check box in MFC - mfc

I have list control including check box for each row. I want to select the entair row when selecting the check box. How can I do this ? What is the code sinnipt for that ?
Thanks.

Inside the dialog (best in OnInitDialog) use following code:
DWORD dwStyle = m_list.GetExtendedStyle();
dwStyle |= LVS_EX_FULLROWSELECT;
m_list.SetExtendedStyle(dwStyle);

Related

Adding a string into CEdit Text box instead of CCombobox

I currently have a combobox which displays a list of numbers which are retrieved elsewhere and stored into the variable "test". Every time another number is set for "test", that number will be added into the combobox list.
Is there a way where I can use a CEdit text box instead of a CComboBox to display my numbers?
This is how I have coded the combobox.
CComboBox *pCombobox = (CComboBox *) (GetDlgItem(IDC_ComboBox));
strNumber.Format(_T("%d"),test);
pCombobox->AddString(strNumber);
Any help would be appreciated. Thank you.
Presuming you have an appropriate edit control placed on your dialog with ID IDC_Edit for example, then get the existing string, append the new value to it, replace with new string.
CString text;
GetDlgItemText(IDC_Text, text);
if (text.IsEmpty())
text.Format(_T("%d"), test);
else
text.AppendFormat(_T(",%d"), test);
SetDlgItemText(IDC_Text, text);

List Control Find ItemText MFC

I have a List Control in MFC.
With that code:
m_Eintrag3 = m_List.InsertItem(0, _T ("Schaller"));
m_List.SetItemText (m_Eintrag3, 1, _T ("Benedikt"));
m_List.SetItemText (m_Eintrag3, 2, _T ("05.08.1996"));
I can insert an Item and Text in my List Control.
With that code:
if ((m_List.FindItem(&Finde)) != -1)
I can find an Item. But I want to find ItemText. Not just the Item.
Is there any solution? FindItemText doesnt exist.
You have to write your own loop, that checks the Subitems too... FindItem only works on the Item entry. Never on subitems.

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];

EM_EXGETSEL does not relate to text selection order. How do I do determine the caret position in a piece of selected text?

When I do:
SendMessage(editControlHWND, EM_EXGETSEL, 0, (LPARAM)&charRange);
I get the selected range of text. However, I want to know where the caret is in this selection, ie at the end, OR at the beginning.
ie, has the user selected the text 'backwards', as in something like dragging from right to left.
EM_EXGETSEL will always have the smaller number in cpMin, so clearly does not relate to the selection order.
I obviously can't get the caret position with EM_EXGETSEL for comparison in this situation because a chunk of stuff is already selected.
Is there any way to get the caret's current individual position (so that I can compare it to cpMin/cpMax)? Or alternatively, is there any way of determining where the caret is in a block of selected text?
EDIT:
My explanation for why I want to do this:
I insert text programmatically into a read-only RichEdit control which the user can select text from. However, when text is added at the end, it has to move the caret to the end and insert the text, and this can happen when text has been selected/the user is currently selecting text.
It's this last one that is the bother. I use EM_EXGETSEL and EM_EXSETSEL to get and set the selected text before and after text is programmatically entered. By default, EM_EXGETSEL will always put the smaller number in cpMin, meaning that if the user is currently selecting text backwards (ie right to left), and text is added to the control, the position of the caret in the selection area changes from the beginning to the end, because I feed these numbers directly into EM_EXSETSEL. I know that EM_EXSETSEL is capable of backwards selection (I have tested this with the larger number in cpMin and the smaller one in cpMax), but EM_EXGETSEL does not give any indication that the user has selected text backwards.
Therefore I need to know the caret position to compare it to cpMin or cpMax to check if it is at the beginning of the selection or the end, and act accordingly.
Just came across this post while looking into the same problem.
I was able to resolve by tracking changes to the selection notified by EN_SELCHANGE and comparing the results at WM_LBUTTONUP.
There's no easy way to do this. EM_GETSEL and EM_EXGETSEL return the range of the current selection. Only if there is no selection do they return the position of the caret.
Note that the caret can't be in a block of selected text - it is always at the end or beginning.
You could probably implement a solution fairly easily by sub-classing the control, and using EM_GETSEL to query and store the position of the caret after any key or mouse input. E.g.
LRESULT WINAPI EditControlSubclassProc(...)
{
LRESULT lRes = CallWindowProc(...); // call original window procedure
if ((uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST)
|| (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST))
{
DWORD dwStart, dwEnd;
SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
if (dwStart == dwEnd)
{
// no current selection, so simply store the position of the caret
g_dwCaretPos = dwStart;
}
}
return lRes;
}
This way you will always know where the caret was the last time there was input that didn't result in a selection. You can then compare it to the range of the selection to determine which end the selection was anchored at, and therefore know the caret is at the other end.
It seems that EM_LINEFROMCHAR and EM_LINEINDEX with (WPARAM == -1) can be used.
I've managed to do this, although it was a little complicated to get there due to my lack of understanding on the concept of sub-classing. ><
I used Spy++ to look at what messages were being sent when I was selecting text.
This was apparently exclusively EM_GETPASSWORDCHAR messages.
So I did:
case EM_GETPASSWORDCHAR:
{
if(hwnd == editControlHwnd)
{
CHARRANGE tempCharRange;
SendMessage(editControlHwnd, EM_EXGETSEL, 0, (LPARAM)&tempCharRange);
SetSelectionDirection(tempCharRange.cpMin, tempCharRange.cpMax);
return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
}
}
With:
void SubWindow::SetSelectionDirection(int newCpMin, int newCpMax) //Set selectionDirection to false if selecting backwards, true if selecting forwards
{
if((newCpMin != prevCpMin) && (newCpMax == prevCpMax))
selectionDirection = false;
else if((newCpMin == prevCpMin) && (newCpMax != prevCpMax))
selectionDirection = true;
prevCpMin = newCpMin;
prevCpMax = newCpMax;
}
Where bool selectionDirection;, int prevCpMin; and int prevCpMax; are private class member variables.
This way I compare the new selected area with the previously selected area to see which end has changed, and which one hasn't.
I don't know if what I'm doing here is a bad way of actually working this out, but if there's a better way to do this, I haven't found it. That's why I'm posting this as the answer in the event that it helps someone else in my position.

MFC: CCheckListBox items overlap

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);
}
};