I have a need to run different code when a user clicks or double-clicks an item in a VB6 ListBox control. When I click on the control, the Click event handler executes. However, I am finding that when I double-click on the control, both the Click and DblClick event handlers execute.
Anyone have a good solution for getting just the DblClick event handler code to run without the Click code being executed first?
Thanks in advance for any suggestions.
A slight hack, but you could use a Timer control and a boolean variable:
Start the timer on the Click event, set the boolean variable to false
Set the boolean variable to true on the DoubleClick event
When the timer Tick event fires, check the boolean variable to see if the user did a Click or DoubleClick
I'd recommend setting the timer interval to the Windows double click time setting, plus a bit (There should be a Windows API call that will give you this value).
The behavior of the list control in Visual Basic 6 is as follows.
When you click on an item the click event is fired.
When you click on the SAME item the click event is still fired.
When you double click on the item both the click event and double click event are fired.
Note #2. What you need to do is have a current item in the form you working with. Every time the click event is checked you first see if the current item is the same item as what you clicked. If it is NOT the same item you process the click event normally.
If you double click on a NEW Item then the user is doing two things at the same time. Selecting a new item and performing the double click item. In this case the click is fired first then the double click.
This sequence is no different than if the control did what you wanted it to. It is the same as if you clicked on a new item wait X second then double click the same item.
If your click event involves handing off the task to a ActiveX EXE and immediately terminating or setting data to be processed later by a background timer. Then you need to have a semaphore or a flag to indicate when the process spawned by the click event is done. The Double Click event won't be processed until the semaphore is cleared.
If you have additional details my answer can be more specific. The following is some code you can run to see the List Box in actions. Create a Form and add three items to the list. Then add the below code.
Private Sub List1_Click()
Print "Clicked - " & Me.List1.List(Me.List1.ListIndex)
End Sub
Private Sub List1_DblClick()
Print "Double Clicked - " & Me.List1.List(Me.List1.ListIndex)
End Sub
Do the following steps
Click on Item #1
Click on Item #2
Click on Item #2 again
Double Click on Item #2
Double Click on Item #3
You will see the various combination of actions occurring.
Related
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.
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.
By default RadTreeNode becomes editable after (http://www.telerik.com/help/aspnet-ajax/p_telerik_web_ui_radtreeview_allownodeediting.html)
"End-users can edit the text of tree-nodes by pressing F2 when the node is selected or by clicking on a node that is already selected (slow double click)."
This is unconvenient, that whatever was clicked twice start being edited, even if clicks are spearated by far.
How I can change its behaviour so edit happens on normal, fast double-click?
Turns out, you just have to rely on context menu approach, and start editing item from context menu handler. AllowNodeEditing="False" can be set, yet OnNodeEdit="HandleNodeEdit" and the like will still work, when editing is triggered manually using appropritate client API function from context menu handler function.
A GtkComboBoxText consists of a text entry, a dropdown list and a button to show the dropdown list.
I want to populate the contents of the drop down box of a GtkComboBoxText when the user clicks on the dropdown button. This is because the drop down box needs to be repopulated with the data.
I found that pressing alt-down in the text entry generates the "popup" signal and opens the drop down box, but I can't find the right signal which one which matches the even when the dropdown button is pressed.
What would be the right signal I need to connect to?
Or is there another way to repopulate the contents of the dropdown list when it gets displayed?
Thanks in advance, Edwin
The popup signal is a keybinding signal - instead of being emitted when the menu is opened, it is emitted when you press Alt-Down and tells the combo box to open its menu. There is no signal emitted when the menu is opened.
Instead, you could try connecting to key-press-event and button-press-event. This will populate the menu more often than you really need to, but will ensure that it is up-to-date whenever the menu is shown. Don't forget to return FALSE from these signals so that the events are passed through to the signal handlers that normally handle them.
Alternatively, try repopulating the menu whenever the data it is generated from change, instead of every time it is shown. This makes more sense to me.
My test needs to click a link from a rad tools menu that it can only find some of the time. Even when it finds the link ByText it cannot double click it. If I hover the menu item it will always find it. Cannot find a hover in Watin, otherwise I've tried refresh, sleeps, focus, keypress, WaitUntilExists, double clicks, etc. Its using a class rmText from rad tools.
The only thing I've found to work is hovering that drop down while the tests are running...
Wish I could just do that for a few seconds...
//process would be a menu item below the radtool menu item that only shows up when certain conditions exist (but always does with the hover)
if (ie.Link(Find.ByText("process")).Exists) //sometimes I get through here
ie.Link(Find.ByText("process")).Click(); // this works only if I hover
Might be that creating the menu item is taking some time. Calling Exists does check if it exists now, maybe if you wait a few (milli)seconds it will be there. Try calling
ie.Link(Find.ByText("process")).WaitUntilExists()
This will time out if the element never appears, otherwise you can savely call the click.
BTW maybe you can get rid of the exists check, WatiN does call WaitUntilExists by itself too before calling Click().
HTH,
Jeroen