MFC: CListView: Why SetItemState(-1, 0, LVIS_SELECTED) doesn't work if multiple items were selected with SHIFT + arrow key? - windows

Easy to reproduce problem using default MFC dialog application:
Add listview control and link it to CListCtrl class - m_listCtrl.
Enable "owner data" or LVS_OWNERDATA flag to enable virtual list view mode. Enable multiple selection and "Always show selection".
In OnInitDialog() add at least one column and call m_listCtrl.SetItemCount() to set number of items in the list to more than one.
Link button click with a method that calls m_listCtrl.SetItemState(-1, 0, LVIS_SELECTED); That call should deselect all entries in the list.
Click on item in the list and use SHIFT + arrow key to extend selection to at least two entries. If selection is extended with mouse or CTRL + click or CTRL + SHIFT, then the issue doesn't appear.
Click on a button that triggers SetItemState() call in step (4) and notice that items don't get deselected the first time. They only get deselected the second time.
Is that a bug in listview control or am I doing something wrong?
Calling m_listCtrl.SetItemState(-1, 0, LVIS_SELECTED); should deselect all entries with the first call, but it does so only when called twice.

Related

MFC: How do you get CMFCToolBarComboBoxButton to show on a CMFCToolBar?

Something I thought would be easy I can't get to work. How do I get a ComboBox to show on the CMFCToolBar? Here's what I have done that doesn't work (meaning it just shows the original placeholder button with the circle (grayed out)).
1 - I added a button to the toolbar in resource editor giving it the id ID_EDIT_FIND_COMBO (I also put a circle in it just to know it's in use).
2- in CMainFrame I added ON_REGISTERED_MESSAGE(AFX_WM_RESETTOOLBAR, OnToolbarReset) to message map and the OnToolbarReset() function below:
afx_msg LRESULT CMainFrame::OnToolbarReset(WPARAM wparm, LPARAM )
{
UINT uitoolbarid = (UINT) wparm;
if (uitoolbarid == IDR_MAINFRAME) {
CMFCToolBarComboBoxButton btncombo(ID_EDIT_FIND_COMBO, GetCmdMgr()->GetCmdImage(ID_EDIT_FIND));
m_wndToolBar.ReplaceButton(ID_EDIT_FIND_COMBO, btncombo);
}
return 0;
}
The ReplaceButton() returns 1 saying it replaced it.
What am I missing?
To be clear, here's what MS says to do which is what is done above:
1 - Reserve a dummy resource ID for the button in the parent toolbar resource. For more information about how to create buttons by using the Toolbar Editor in Visual Studio, see the Toolbar Editor article.
2 - Reserve a toolbar image (button icon) for the button in all bitmaps of the parent toolbar.
3 - In the message handler that processes the AFX_WM_RESETTOOLBAR message, do the following steps:
a. Construct the button control by using a CMFCToolbarButton-derived class.
b. Replace the dummy button with the new control by using CMFCToolBar::ReplaceButton. You can construct the button object on the stack, because ReplaceButton copies the button object and maintains the copy.
TIA!!
Here's a sample project where it doesn't work. Just the button on the toolbar, not a combobox. Even took code sample from MS sample.
Sample Project
The answer is that MFC caches the toolbar so if you ever run it without the combo, once you replace the button to use the combo it still doesn't use it. You can make it pick up the change by either going to customize for the toolbars (if you have that option enabled) and choose Reset All, otherwise, you'll find under Computer\HKEY_CURRENT_USER\Software\{NameAsUsedInSetRegistryCall}\{appname}\Workspace all the cache items, of which the various MFCToolBar entries. Delete the key and run app again, then it works. Why they wouldn't make it smart and have a timestamp to know if to automactially update, not sure?

How do I setup the Actions/Outlets for 2 radio buttons, a calculate button, and a graph output in XCode?

The image above is a screenshot of what I've set up in my storyboard. I have 2 radio buttons, 3 static values, and a final calculate button.
The way it works is this:
User selects either radio button #1 or radio button #2. If she selects radio button #2, she must select a file from disk. This file will then be parsed by the function linked to the calculate button.
The user must provide the 3 static values in order for this to work.
After pressing the calculate button, the function will calculate some things and eventually feed some data into the graph to the Container View on the right.
Here's the catch - I am doing this all through VNC viewer, so I cannot ctrl + drag. I need to know how to set this all up using the Connections Inspector menu (which is the alternative for users who cannot ctrl + drag):
Does anyone know how?

How can I make a CMenu TrackPopupMenu SubMenu menu-item clickable?

Normally when you hover over a sub-menu (with the little arrow) on a CMenu menu item it delays briefly then shows the sub-menu items. Also, if you click the item before the delay timeout, it shows the sub menu items. I want the delay behavior, but I want a different behavior for the click. That is, I want the sub-menu itself (the one with the arrow) to be a clickable entity too, i.e. it has an ID and results in a WM_COMMAND and menu dismissal.
The idea is, the main sub-menu menu item is a "default", and the sub-menu items are modified versions, e.g. "print->" (defaulting to default printer), and sub-menu items like "print preview" "print to file" etc. Thanks for thoughts/suggestions.
edit:
IDR_MY_MENU MENUEX
BEGIN
POPUP "menu"
BEGIN
MENUITEM "&Something Else", ID_MENU_SOMETHING_ELSE
POPUP "&Print", ID_MENU_PRINT
BEGIN
MENUITEM "Print Pre&view", ID_MENU_PRINT_PREVIEW
MENUITEM "Print to &File", ID_MENU_PRINT_TO_FILE
END
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM "&Bottom", ID_MENU_BOTTOM
MENUITEM "&Done", ID_MENU_DONE
END
END
I dont know if theres a better way as I last did this 2 years ago, but the way I solved the problem had one constraint: that you own the whole menu. If you do own the whole menu what you can do is create two columns (two columns in the menu/submenu that is, not a new submenu) and use the right column as a submenu and the left column as the default.
For future StackOverflowers, here's what I did...
Added a handler for OnInitMenuPopup and corresponding
ON_WM_INITMENUPOPUP(), although doing this messed up my UPDATE_COMMAND_UI handler but I was able to resolve that by moving that code into the OnInitMenuPopup handler.
In the OnInitMenuPopup handler, set a hook for the mouse SetWindowsHookEx(WH_MOUSE,...) (checking if one isn't already set because sub-menus can cause multiple calls)... and for each menu that initializes during the hook, push the HMENU onto a linked list.
In the mouse hook proc, checking the end of the list and working toward the front, verify each HMENU is still and active menu via IsMenu and remove it if it isn't. If there are no menus left, UnhookWindowsHook.
If there are menus left in the hook proc, check for WM_LBUTTONUP or WM_RBUTTONUP and see if happened over one of your menu items (because of coordinate mapping of screen versus sub-menu that I couldn't figure out I ended up simply cycling through the menu items via GetMenuItemRect and checking PtInRect to determine this).
If there is a click hit, do GetMenuItemInfo on the item, and if there's a hSubMenu for that item and it has an wID (and the wID doesn't match the sub-menu handle), simply post the id as a WM_COMMAND, post a WM_CANCELMODE to dismiss the menu, and disable the hook... Bingo!
So, seems to work fine and everything else functions like normal. The only issue at this point is a keyboard handler for selecting the item instead opening the sub-menu but I suspect the same idea works there as well.
Also, I added the main sub-menu text as the first item in the sub-menu list with a separator which added some clarity to what the menu was doing.

VB6 + how to switch between windows/frame in form by buttons

I am very new beginner with VB6 and I hope I explain the things right
I want to create form with 2 buttons (the buttons are located on the top form position )
So each button will switch to other form/window/frame
For example
The first button will show window 1 (there I can set only parameters)
The second button will show window 2 (there I can set only IP address)
Please advice if we can do that by VB6 ?
And if yes how to do that ( step by step )
Remark - Similar example but with multiple windows in the same form is the system properties ( right click on my computer and properties ) , the we can see each button will view different window
Create a form with 2 buttons, Command1 and Command2.
On this form, create 2 frames, Frame1 and Frame2. hide Frame2 and make sure to line up both framesso that they are of the same size and located right on top of each other (Top, Left, Width and Height properties must be the same)
Now put this code in:
Private Sub Command1_Click()
Frame1.Visible = True
Frame2.Visible = False
End Sub
Private Sub Command2_Click()
Frame1.Visible = False
Frame2.Visible = True
End Sub
Now each the first button shows the first frame while hiding the 2nd. The second button hides the first frame and shows the seconds. I think this is the simplest way to implement your task.
PS: don't forget to name your objects properly, it's not a good idea to have default names like Command1 or Frame2 - should be more descriptive than that.
It sounds like you are asking about the tabbed dialog control. To use a tabbed dialog control in VB6:
Click Project -> Components
Scroll down to "Microsoft Tabbed Dialog Control 6.0" and select it.
Click the Apply button.
You should notice a new control in the component tool box. If you do not see the toolbox, click View -> ToolBox. This is the same area of the IDE where you first click to add a button to a form. The tabbed dialog control looks like the top tab of several file folders. When you hover your mouse over the control in the toolbox, you will see a tool tip text of "SSTab". Click this control and then draw a rectangle on your form.
By default, this will add a tabbed dialog control with 3 tabs, but you can change this in the properties window. You can now create any control on top of a tab of the tabbed dialog control and interact with the control exactly the same way you would if the control was placed on the form itself.
What you want is called an MDI Form. It's a form that contains other forms.
You can find a full tutorial on them here, but here's the gist of what you want to do:
Set the "MDIChild" property of all your subforms you want to use to True. Disable their minimize, maximize, and resize functions as well.
Create an MDIForm. Disable its AutoShowChildren property.
Add a toolbar to the MDIForm. Add buttons to the toolbar corresponding to the forms you'll be switching between.
Implement each button's click event, to create child form as expected (or switch to an existing one).

How do you programmatically change the tab order in a Win32 dialog?

Often time I need to add a control to a dialog after the dialog has been generated via dialog template and CreateDialogIndirect. In these cases the tab order is set by the dialog template and there is no obvious way to change the tab order by including a newly created control.
I recently discovered that you can use SetWindowPos to accomplish this. Determine which control after which you want to insert the new control in the tab order then use SetWindowPos like this:
SetWindowPos(hNewControl, hOldControl, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
This changes the z-order of controls which, in turn, establishes the tab order.
I know this is an old question but here is how to do it at compile time (which is preferable in the vast majority of cases):
http://msdn.microsoft.com/en-us/library/7039hzb0(v=vs.80).aspx
My favourite method:
From the View menu, choose Tab Order.
Choose Assign Interactively.
Double-click the tab order box beside the control you want to be the
first control in the tab order.
Click the tab order box for each of the other controls.
Click anywhere on the form to save your changes and exit Tab Order
mode, or press ESC to exit Tab Order mode without saving your
changes.

Resources