Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win32API: How to determine if EN_CHANGE was because of user action, not software action?

I find this situation comes up from time to time, and I never seem to have a really robust generic solution to it.

I have a control - in this example an EDIT control on a dialog. I want to take certain actions in response to the user - and only the user - modifying the contents of the edit control.

The edit control can be set programmatically - e.g. when the dialog is being setup, there may be an initial value placed into the edit field. Or when the user selects an item from a listview, that selection's text may well be what's placed into the edit field.

But when the user modifies the contents of the edit field, I need to know that, and respond (in this scenario, I want to clear the selection from the corresponding listview).

I am currently looking at what control has focus, and only considering EN_CHANGE's to be "from the user" if the edit control has focus.

This works beautifully under Windows 7. This fails under XP (I haven't tested Vista yet).

In XP, if the edit field has the focus, but the user clicks on the list view, and the list view tells the edit control to set its contents, then I get a notification from the edit control which claims to still have focus (::GetFocus() == HWND of edit control). But this incorrect state doesn't occur in Win7.

This is a layered interface, so I cannot modify the list-view notification handler. It gets a selection change, and updates the edit field without my involvement or ability to really intervene other than to get notifications from both of them.

Any thoughts on how to generically, permanently solve the "Is this control notification really from the user" conundrum?

like image 396
Mordachai Avatar asked Nov 06 '22 16:11

Mordachai


2 Answers

You can always track LVM_ITEMCHANGING, LVM_ITEMCHANGED, and EN_MSGFILTER messages. If the edit box is modified between LVM_ITEMCHANGING and LVM_ITEMCHANGED without an EN_MSGFILTER in between then you can probably assume the user did not modify the item. Or just check to see if there are any items selected when EN_CHANGE fires and if not or the text doesn't match the selected item, assume it is a user edit.

Or use ES_MULTILINE (from EN_CHANGE documentation):

The EN_CHANGE notification is not sent when the ES_MULTILINE style is used and the text is sent through WM_SETTEXT.

like image 59
MSN Avatar answered Nov 12 '22 20:11

MSN


I'd suggest using the right message. EN_CHANGE is too generic, you want to know if the user typed or pasted text. So why not subclass the control and watch for WM_KEYPRESS messages?

Alternatively, you can set a flag in your other code that sets the edit control content. You might be able to assume that anything that makes your wndproc re-entrant represents a programmatic change.

You aren't looking for something actually secure, are you? If you just want to exclude set content calls that's fairly straightforward. If you want to differentiate between user action and programmatic simulation of user keypresses, that's a much harder problem.

like image 27
Ben Voigt Avatar answered Nov 12 '22 19:11

Ben Voigt