Horizontal scroll not coming for listbox? - mfc

I am having a listbox where I set both the properties i.e, vertical and horizontal scroll to true.I am able to get vertical scroll bar but not able to get horizontal scroll bar when added a lengthy string.
Can anyone please let me know how get horizontal scroll bar for a listbox.

Adding this piece of code in OnInitDialog resolved my issue.
BOOL OnInitDialog()
{
CString str;
CSize sz;
int dx = 0;
CDC* pDC = m_listbox.GetDC();
for(int i=0; i < m_listbox.GetCount();i++)
{
m_listbox.GetText(i,str);
sz = pDC->GetTextExtent(str);
if(sz.cx > dx)
dx = sz.cx;
}
m_listbox.ReleaseDC(pDC);
if(m_listbox.GetHorizontalExtent() < dx )
{
m_listbox.SetHorizontalExtent(dx);
ASSERT(m_listbox.GetHorizontalExtent() == dx);
}
return TRUE;
}

You have to specify the horizontal scroll extent (max width in pixels). Do that by calling CListBox::SetHorizontalExtent.

In MFC, I had a listbox that was too big and extended past the right border of the window containing it. Once I made the listbox x dimension fit inside the window, the scrollbar started working properly again.
For some reason if the listbox is too big, Windows did not handle the scrollbar visibility properly as a side-effect of the sizing.

Related

How to stop the bottom scrollbar from a CListCtrl from displaying?

I have a CListCtrl which is dynamically resized with the dialogue. I used a WM_SIZE message handler in the derived CListCtrl to resize the columns such that the total is the width of the control - 4, where the - 4 is to indicate the width of the border.
When I make the dialogue bigger, the control resizes correctly and I don't get the bottom scrollbar. However when I shrink the control, I sometimes get the horizontal scrollbar showing up.
void CMyListCtrl::OnSize(UINT nType, int cx, int cy)
{
CListCtrl::OnSize(nType, cx, cy);
ResizeLastColumn();
}
void CMyListCtrl::ResizeLastColumn()
{
LVCOLUMN column;
column.mask = LVCF_WIDTH;
LONG maxWidth = 0;
for (int i = 0; i < lastColumnIndex; ++i)
{
GetColumn(i, &column);
maxWidth += column.cx;
}
CRect wndRect;
GetWindowRect(&wndRect);
SetColumnWidth(lastColumnIndex, wndRect.Width() - maxWidth - 4);
}
It is like the WM_SIZE message is getting to the control before the control is finally resized.
This is related to How to determine if a scrollbar for a CListCtrl is displaying?. However, this question is not dealing with the right scrollbar, and is assuming that it is not being displayed.
Resizing the window generates a message to test for horizontal scroll. SetColumnWidth will also generate the same message. It depends how ListView handles this internally, but a vertical scroll could also come in and go, this will change the client area, so the code may have to make recursive calls to figure out if the scroll should be visible or not. You can see this can easily run in to problems.
Try resizing the columns in WM_WINDOWPOSCHANGED, before calling the default procedure. Use SetRedraw to stop redundant paint messages.
ON_WM_WINDOWPOSCHANGED()
...
void CMyListCtrl::OnWindowPosChanged(WINDOWPOS *wpos)
{
SetRedraw(FALSE);
ResizeLastColumn();
SetRedraw(TRUE);
CListCtrl::OnWindowPosChanged(wpos);
}
You can use GetClientRect for the client area, then you don't need to subtract the border thickness (which is not always 4).
void ResizeLastColumn()
{
int maxwidth = 0;
int index = GetHeaderCtrl()->GetItemCount() - 1;
for(int i = 0; i < index; ++i)
maxwidth += GetColumnWidth(i);
CRect rc;
GetClientRect(&rc);
SetColumnWidth(index, rc.Width() - maxwidth);
}
Also GetHeaderCtrl()->GetItemCount() returns the number of columns.
I'm facing the exact same issue, with the exact same Use Case.
To disable the horizontal scroll bar altogether, you add a message handler for WM_NCCALCSIZE
Using the Class Wizard this adds the following to your message map:
ON_WM_NCCALCSIZE()
In the implementation of this handler, you modify the style to disable the horizontal scroll bar.
void CMyListCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
ModifyStyle(WS_HSCROLL, 0); // disable the horizontal scroll bar
__super::OnNcCalcSize(bCalcValidRects, lpncsp);
}
In my own implementation of ResizeLastColumn(), which is similar to yours, I subtract ::GetSystemMetrics(SM_CXVSCROLL) from the width to account for the vertical scroll bar.
I realise this reply is rather late, but hopefully it will help someone.
(Edited to remove mentions of some problems I am having because a) they are off-topic and b) because I think they stem from me not using the Doc-View architecture and things not being wired up correctly as a result. I'm going to re-think my approach.)

Wrapping text in GTK3 treeview

I have trouble getting TreeView in GTK3 to wrap text correctly.
I set it up to wrap in this way:
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_mode().set_value(Pango::WRAP_WORD_CHAR);
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_width().set_value(200);
This works, text is wrapped, but when I resize the window and make it bigger, there is a lot of ugly white-space above and below cell with long text. It seems, that GTK reserves height for cell based on wrap width. Which makes no sense to me.
I tried to get around with setting needed in signal_check_resize with calculating needed width like this:
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
auto width = this->get_allocated_width()
- mTreeView.get_column(0)->get_width()
- mTreeView.get_column(1)->get_width();
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_width().set_value(width-100);
this->forceRecreateModel = true; //Needed to work
But this lets me only make window bigger. It cannot be shrinked, after it was resized.
The question is, how this is properly done?
I am using gtk3.20.3-1 and gtkmm3.20.1-1 on Arch linux.
EDIT: fixed typo in the title...
In the end I found how to do it.
In the setup of the window (for me constructor of the window derived class) it was necessary to set column to be AUTOSIZE in order to allow shrinking of the width.
//Last Column setup
{
mTreeView.append_column("Translation", mColumns.mEnglish);
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
pColumn->set_sizing(Gtk::TreeViewColumnSizing::TREE_VIEW_COLUMN_AUTOSIZE);
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_mode().set_value(Pango::WRAP_WORD_CHAR);
}
Also there is needed to set correct wrap width on every resize. Without this, height of the row was as big as it would be necessary for currently set wrap_width with no regard on current width (resulting in big padding on the top, when stretched more and prohibiting to make window smaller).
This code was also in the constructor.
this->signal_check_resize().connect([this]()
{
//calculate remaining size
Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
auto width = this->get_allocated_width()
- mTreeView.get_column(0)->get_width()
- mTreeView.get_column(1)->get_width()-30;
//minimum reasonable size for column
if(width < 150)
width = 150;
static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
->property_wrap_width().set_value(width);
//debounce
static auto oldsize = 0;
{
oldsize = width;
//trigger redraw of mTreeView (by clearing and refilling Model,
//it is done in 100ms pulse)
this->mRedrawNeeded = true;
}
});
And maybe it is worth noting, that I have mTreeView encapsulated in Gtk::ScrolledWindow. So this is a chunk which comes before column setup. :)
//in class is: Gtk::ScrolledWindow mScrollForResults;
//scrolling area
mGrid.attach(mScrollForResults, 0,2,10,1);
mScrollForResults.set_hexpand();
mScrollForResults.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC,
Gtk::PolicyType::POLICY_ALWAYS);
mScrollForResults.set_margin_top(10);
mScrollForResults.set_min_content_width(400);
mScrollForResults.set_min_content_height(200);
mScrollForResults.add(mTreeView);
//results treeView
mRefListStore = Gtk::ListStore::create(mColumns);
mTreeView.set_model(mRefListStore);
mTreeView.set_hexpand();
mTreeView.set_vexpand();

How to center QDialog?

I'm trying to center my QDialog.
Here's a code I used:
QRect screenGeometry = QApplication::desktop()->screenGeometry();
int x = (screenGeometry.width() - this->width()) / 2;
int y = (screenGeometry.height() - this->height()) / 2;
this->move(x, y);
But I didn't get my dialog at an appropriate posistion. When I printed values of a dialog's width and height I noticed that they were much smaller than a real ones. To check if something was working in a wrong way I changed it's geometry:
this->setGeometry(100,100,this->width(),this->height());
And my dialog shrank...
Can someone tell me what's going on?
QRect screenGeometry = QApplication::desktop()->screenGeometry();
QRect windowRect = rect();
First get a copy of your own window rect.
windowRect.moveCenter(screenGeometry.center());
Move the copy to the center of the screen's rect.
move(windowRect.topLeft());
Perform the actual move: set your windows top left point to the calculated top left point. No resize is necessary.

How to get the minimum size of a treeview control that avoids scroll bars?

I have a dialog with a tree view inside it, and would like to have the dialog re-size itself automatically when the tree is expanded or collapsed to avoid scroll bars or excessive space.
In order to do so I need some way of finding the "desired" size of the tree view, i.e., the smallest size large enough to avoid displaying scroll bars.
Any suggestions?
Edit: So, I'm halfway there. I can determine the height by counting the number of visible items and multiplying by TreeView_GetItemHeight. I still have no idea how to find the width, however...
It's not quite perfect (it doesn't seem possible to have TreeView_GetItemRect horizontally include the whole line up to the end of text), but the following works great for my use case with disabled horizontal scrolling.
void Dialog::getDimensionTreeView(unsigned int id,
unsigned int &width, unsigned int &height) {
HWND item = GetDlgItem((HWND)_hwnd, id);
if(!item) {
width = 0;
height = 0;
return;
}
RECT area = { };
HTREEITEM node = TreeView_GetRoot(item);
do {
RECT rc;
LPRECT prc = &rc;
// Ideally this would use `fItemRect`=FALSE, but that seems
// to just return the current width of the treeview control.
TreeView_GetItemRect(item, node, prc, TRUE);
if(rc.left < area.left) area.left = rc.left;
if(rc.right > area.right) area.right = rc.right;
if(rc.top < area.top) area.top = rc.top;
if(rc.bottom > area.bottom) area.bottom = rc.bottom;
} while((node = TreeView_GetNextVisible(item, node)));
width = area.right - area.left;
height = area.bottom - area.top;
}
Thanks to Hans Passant for putting me on the right track.

Usage of CScrollView in MFC application

I am using CSCrollView window for our Application in which i have table drawn in View.
I have derived the CMYclass from CSCrollView, But whenevr i am scrolling the window up and down whatever i have drwan is getting erased. How i can acheive it this... i need to perform same actvity like a Word Pad is doing with images and Text. I want to keep scroll the View Vertically. Till the page ends.
Here is the code snippet:-
void CMyView::OnInitialUpdate()
{
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = 450;
sizeTotal.cy = 700;
SetScrollSizes(MM_TEXT, sizeTotal);
}
void CMyView::OnDraw(CDC* pDC)
{
for(int i = 1;i<50;++i)
{
AddRow(pDC);
TopPos = Height+TopPos;// ![Outpu Window Image][1]
nCountRow++;
}
}
it is only drawing 18 rows, but when iam scrolling down above drawn content is no more and also there is nothing coming up in scrolled area.
Is there anything more need to add?
Thanking for help
Regards,
Mukesh
Long time I have used CScrollView. Here is my hint: Try mapping modes other than MM_TEXT. Also look up other functions in CScrollView. I suggest to draw simple stuff first than some complicated rows.