Win32API: Как определить, был ли EN_CHANGE из-за действий пользователя, а не программного обеспечения? - PullRequest
4 голосов
/ 05 февраля 2010

Я нахожу, что эта ситуация возникает время от времени, и у меня никогда не было действительно надежного общего решения.

У меня есть элемент управления - в этом примере элемент управления EDIT в диалоговом окне. Я хочу предпринять определенные действия в ответ на изменение пользователем - и только пользователем - содержимого элемента редактирования.

Управление редактированием может быть установлено программно - например, во время настройки диалогового окна может быть начальное значение, помещенное в поле редактирования. Или когда пользователь выбирает элемент из списка, текст этого выбора вполне может быть тем, что помещено в поле редактирования.

Но когда пользователь изменяет содержимое поля редактирования, мне нужно знать это и отвечать (в этом сценарии я хочу очистить выбор из соответствующего списка ).

В настоящее время я смотрю на то, какой элемент управления имеет фокус, и только EN_CHANGE считаются «от пользователя», если элемент управления имеет фокус.

Это прекрасно работает под Windows 7. Это не работает под XP (я еще не тестировал Vista).

В XP, если поле редактирования имеет фокус, но пользователь нажимает на представление списка, и представление списка сообщает элементу управления редактирования об установке его содержимого, тогда я получаю уведомление от элемента управления редактирования, который утверждает, что все еще имеет focus (:: GetFocus () == HWND контроля редактирования). Но это неправильное состояние не возникает в Win7.

Это многоуровневый интерфейс, поэтому я не могу изменить обработчик уведомлений в виде списка. Он получает изменение выбора и обновляет поле редактирования без моего участия или возможности действительно вмешиваться, кроме как получать уведомления от них обоих.

Есть мысли о том, как в общем и целом навсегда решить головоломку "Действительно ли это уведомление от пользователя"?

Ответы [ 2 ]

1 голос
/ 06 февраля 2010

Я бы предложил использовать правильное сообщение. EN_CHANGE слишком общий, вы хотите знать, набрал ли пользователь текст или вставил его. Так почему бы не создать подкласс управления и следить за сообщениями WM_KEYPRESS?

В качестве альтернативы, вы можете установить флаг в другом коде, который устанавливает содержимое элемента управления для редактирования. Возможно, вы сможете предположить, что все, что делает ваш wndproc реентрантом, представляет собой программное изменение.

Вы не ищете что-то действительно безопасное, не так ли? Если вы просто хотите исключить вызовы с заданным содержимым, это довольно просто. Если вы хотите провести различие между действиями пользователя и программным моделированием нажатий клавиш пользователя, это гораздо более сложная проблема.

1 голос
/ 05 февраля 2010

Вы всегда можете отслеживать сообщения LVM_ITEMCHANGING, LVM_ITEMCHANGED и EN_MSGFILTER. Если поле редактирования изменяется между LVM_ITEMCHANGING и LVM_ITEMCHANGED без EN_MSGFILTER между ними, вы можете предположить, что пользователь не изменил элемент. Или просто проверьте, есть ли какие-либо элементы, выбранные, когда срабатывает EN_CHANGE, и если нет, или текст не соответствует выбранному элементу, предположите, что это пользовательское редактирование.

Или используйте ES_MULTILINE (из EN_CHANGE документации):

Уведомление EN_CHANGE не отправлено когда используется стиль ES_MULTILINE и текст отправляется через WM_SETTEXT.

...