How synchronize two list controls vertically in MFC - visual-c++

I have two list controls and both are vertically scroll-able separately.
However I want to synchronize scroll also I would like to hide the vertical scroll bar in list control-1.
On the other hand if you scroll vertically list control-2, then the list control-1 should scroll down automatically the same amount of items in such way that the options on the both the list boxes should always appear in the same row.
How can I achieve this in MFC?

I do this with a connection between two list views through the document, but the end result is a command to the Scroll member of the slave list control.
So handle the ON_WM_VSCROLL() in the master, I actually have a custom notify but you may want to just shortcut to from the likes of in the master:
if( pS->nSBCode == SB_THUMBTRACK )
GetDocument( )->SetSplitScrollPos( pS->nPos );
How ever you work past to the likes of 'SetSplitScrollPos' it ends up with this at the slave:
void CLCtrl::ScrollToVPosition( long inPos )
{
long scroll= ( inPos - curVScrollPos );
Scroll( scroll << 20 );
curVScrollPos= inPos;
}
The 'Scroll' call is a CListCtrl member, so you could:
mySlaveCtrl.Scroll( ... );
Now, I'm sorry, but I don't recall why the shift of 20 as '<< 16' should move the value to the hi_word, but it needed to be 16 times greater, (20 - 16). I did not write in the required comments.
To wit, it may be as simple for you to handle the master ON_WM_VSCROLL and:
if( pS->nSBCode == SB_THUMBTRACK )
mySlaveCtrl.Scroll( ( ps->pos - curVScrollPos ) << 20 );

Related

How to manage tall menus (lists of languages)?

My application supports over 30 languages:
What is the right way to manage the situation where the menu is too tall for the screen? I will slowly get extra languages added and I do not know how to cater for it.
The standard menu implementation provides the functionality to automatically add scrollbars, should the number of entries exceed the menu's maximum height. By default a popup menu's height is set to 0, instructing the system to use the screen height as the menu's maximum height.
This works for a number of scenarios, and you don't have to do anything to get that behavior. It does fail, though, for multimonitor setups, where the height of the primary display is larger than the height of the display, where the application is displayed.
To work around this, you can set the respective popup menu's maximum height, whenever it is displayed. The appropriate place would be CWnd::OnInitMenuPopup:
void CMainFrame::OnInitMenuPopup( CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu ) {
CFrameWnd::OnInitMenuPopup( pPopupMenu, nIndex, bSysMenu );
if ( !bSysMenu && ( nIndex == 3 ) ) { // Apply appropriate filter
MENUINFO mi = { 0 };
mi.cbSize = sizeof( mi );
mi.fMask = MIM_MAXHEIGHT;
mi.cyMax = 150; // Pick an appropriate value
pPopupMenu->SetMenuInfo( &mi );
}
}
This callback is called, whenever a popup menu is about to be displayed. The height has been arbitrarily set to 150. You can pick any value you see fit in your application (e.g. the minimum height of all displays, a value based on the height of the display, where the menu will be displayed, etc.).
Scrollbars are added automatically, as can be seen in the following screenshot:

How to limit frame resizing based on view's size? MFC doc/view architecture

MFC doc/view architecture, sdi (more precisely multiple top-level windows).
In my view class, I set my "playground" (i.e. logical space) with SetScrollSizes(); Then I want to limit maximum frame window size to that of view's maximum size.
Here is what I'm doing but I think there might be better solution, please advice:
I'm implementing OnGetMinMaxInfo() in my CMainFrame. There I try to get active view's scroll sizes, and set lpMMI->ptMaxTrackSize appropriately. Below is the code:
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Call base version:
CFrameWndEx::OnGetMinMaxInfo(lpMMI);
// Get active view:
CScrollView *pScrollView = (CScrollView *)GetActiveView();
if (pScrollView && pScrollView->IsKindOf(RUNTIME_CLASS(CMyFckinView)))
{
// Get total size of playground:
CSize sizePlayground = pScrollView->GetTotalSize();
// Test if the size is non-zero, i.e. there is at least one node displayed:
if (sizePlayground.cx && sizePlayground.cy/* && !IsPrintPreview()*/)
{
// Set maximum window size to match our playground size:
CRect rectClient, rectWindow;
pScrollView->GetClientRect(&rectClient);
this->GetWindowRect(&rectWindow);
if (rectWindow.top > -5000 && rectWindow.left > -5000) // Avoid when minimized...
{
lpMMI->ptMaxTrackSize.x = sizePlayground.cx + (rectWindow.Width() - rectClient.Width());
lpMMI->ptMaxTrackSize.y = sizePlayground.cy + (rectWindow.Height() - rectClient.Height());
return;
}
}
}
}
This works but has one problem: When print preview is displayed (standard MFC print preview), I obviously want to allow free window resizing, so I use runtime info GetActiveView()->IsKindOf(...) to determine that active view is really my view, and not print-preview's view (which is CPreviewViewEx). But when I close the print preview, OnGetMinMaxInfo is not called, so I'm unable to adjust frame size according to my view again. As soon as I move the window OnGetMinMaxInfo gets called again and correctly adjusts frame size, but without manually moving the window old size (to which the print preview was sized to) is retained and has ugly artifact.
What can I do? Basically if I could trap the moment when print preview is closed, I could use following trick:
// Trigger the WM_MINMAXINFO message:
CFrameWnd *pFrame = GetParentFrame();
RECT rectWindow;
pFrame->GetWindowRect(&rectWindow);
pFrame->MoveWindow(&rectWindow);
But I don't know how to trap print-preview closure.
What I'm trying to accomplish seems quite standard: who would want to have frame window resized bigger than view's logical size (set by SetScrollSizes())? So there should be some more natural solution maybe?
In your CMyFckinView, handle a message that is reliably sent when the print preview is closed and then post a user message to the mainframe which will trigger your "force minmax" code. Perhaps WM_FOCUS or WM_ACTIVATE?

How to put 4 button in row use lwuit? At the same distance

how to put 4 button in row, as in the picture:
The distance between the elements should be changed at different resolutions
There are allot of ways to do everything in LWUIT. Its unclear from your image what your exact constraints are, I'm guessing you want the left most button to be left aligned and the right most to be right aligned. You probably also want the two other buttons to be centered.
I would implement this using a GridLayout with nested FlowLayout elements. As such:
Container c = new Container(new GridLayout(1, 4));
addButton(c, new Button("b1"), Component.LEFT);
addButton(c, new Button("b2"), Component.CENTER);
addButton(c, new Button("b3"), Component.CENTER);
addButton(c, new Button("b4"), Component.RIGHT);
private void addButton(Container c, Button b, int align) {
Container flow = new Container(new FlowLayout(align));
flow.addComponent(b);
c.addComponent(flow);
}
Play with setMargin(Component.RIGHT,x) for the first three Buttons. Set the value of x such that the Buttons are equi-partitioned in the row : you must take into account the preferredWidth of the Buttons for that. For the first Button set its margin-left to 0 ( setMargin(Component.LEFT,0) ) , and for the last Button set its right-margin to 0 ( setMargin(Component.RIGHT,0) ).
You should use use BorderLayout and add the container (described in this answer inside south)

How to avoid CListCtrl items to be partially visible?

I have a resizeable CListCtrl and I want to avoid any item being displayed partially, ever.
For example:
I want Item 9 to not be displayed in this case. Is there a flag or method for this? How would you go about solving this issue?
I tried the following and it was no good:
void CMyCListCtrl::OnEndScrolling()
{
int iCount = this->GetCountPerPage();
EnsureVisible(iCount - 1, FALSE);
}
after catching
...
ON_NOTIFY( LVN_ENDSCROLL, IDC_LIST1, OnEndScroll )
...
void CWheelTestDlg::OnEndScroll(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLVSCROLL pnmLVScroll = (LPNMLVSCROLL) pNMHDR;
m_MyListCtrl.OnEndScrolling();
*pResult = 0;
}
In the CListCtrl parent dialog. (which I don't want to do, I want to do everything in my CListCtrl derived class only, if possible).
All I accomplish is showing item 9 completely, but item 10 is partially visible below it. If I have 30 items I don't want to scroll the list to show item 30, I want to show up to item 8 with no partially visible item below it.
CListCtrl doesn't appear to support Integral Height.
Here's a solution that accomplishes what you desire by forcefully changing the control height [with commented conditions] (http://www.codeproject.com/Messages/418084/Socket-accept-call.aspx):
/////////////////////////////////////////////////////////////////////////////////
// This assumes a REPORT-style CListCtrl.
//
// Resize the control. This works correctly only if scrolling is disabled. If
// there is scrolling, then setting to the size from ApproximateViewRect() will
// always give scroll bars showing. Which is irritating.
//
// We need to adjust the vertical size from what ApproximateViewRect() returns
// by one row minus border width
//////////////////////////////////////////////////////////////////////////////////
CSize sz = m_list.ApproximateViewRect(); // always adds room for a new row
CRect itRect; // Get the height of a single row (there had better *be* a row!)
m_list.GetItemRect(0, &itRect, LVIR_BOUNDS);
int vOffset = itRect.Height() - 3; // leave a little 'cuz it looks better
m_list.SetWindowPos(NULL, 0, 0, sz.cx, sz.cy - vOffset,
SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
I have the similar problem in wince, and find a solution accidentally. No direct solution in internet, so i decide to re-position scroll bar after receive some message, and the only message i can used in wince is WM_LBUTTONDOWN, other messages such as OnEndScroll are not called, maybe something wrong in my code.
Whatever, i use Timer(ON_WM_TIMER) to re-position scroll bar when receive WM_LBUTTONDOWN message, then find that list control doesn't scroll automatically! then i remain a empty OnTimer function and remove everything else. It works, and i guess list control use Timer to scroll partial row.
Hope useful to you.

Deletion of multiple items in a collection bound to a datagridview takes forever

This is not a question, cause I already answerd it. But it may be helpful to others, too.
Here's what happens:
Create a WinForm with a Datagridview and bind a Subsonic ...Collection with more then 500 objects loaded to it
Add some columns to the datagrid and make at least one autosizemode = fill
Add logic to delete all selected columns (i.e. on keypress -> delete)
Mark all records and delete them
This should take about 30 sec. on a high end pc (and scales up: 1 min for 1000 ...)
Cause:
Everytime you delete a row the collections ListChanged event is fired which causes the datagridview to recalculate the space needed for the autosized column (if someone is interested in the "internals" I attached a call graph.
Solution:
While deleting, disable the ListChangedEvent:
mycollection.RaiseListChangedEvents = false;
// Delete multiple rows
foreach(DataGridViewRow row In dataGridView.SelectedRows) {
dataGridView.Rows.Remove(row);
}
// After that you can re-enable the event:
mycollection.RaiseListChangedEvents = true;
// But you have to call
mycollection.ResetBindings();
//to let the datagridview perform at least one redraw.
The same task now takes only the blink of an eye

Resources