{"id":110715,"date":"2025-01-06T07:00:00","date_gmt":"2025-01-06T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=110715"},"modified":"2025-01-06T07:36:20","modified_gmt":"2025-01-06T15:36:20","slug":"20250106-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250106-00\/?p=110715","title":{"rendered":"How can I tell whether a change to a control was due to the user or due to my program?"},"content":{"rendered":"<p>In many UI frameworks, controls raise an event when the state of the control changes. The Win32 edit control raises the <code>EN_<wbr \/>CHANGED<\/code> notification, for example. This is sometimes desirable. For example, maybe you want the &#8220;Author&#8221; field to match the current Book ID.<\/p>\n<pre>void OnBookIdChanged()\r\n{\r\n    auto id = ReadBookId();\r\n    auto author = LookUpAuthor(id);\r\n    SetAuthorText(author);\r\n}\r\n<\/pre>\n<p>Even if the book ID is set programmatically, you still want the author to be updated.<\/p>\n<p>But often, you want your program to respond to changes in a control if they were initiated by the user, but not if they were triggered by the program itself. For example, you want to update a table with the new author as the user types it, but you don&#8217;t want to trigger an update when the code initializes the author field. How can you tell whether a change notification was due to the user or due to your program?<\/p>\n<p>The simple solution is to set a flag when you are changing the value from your program, and then check that flag in the notification to decide whether to respond to it.<\/p>\n<pre>bool m_authorSetProgrammatically = false;\r\n\r\nvoid SetAuthorProgrammatically(PCWSTR author)\r\n{\r\n    m_authorSetProgrammatically = true;\r\n    SetWindowText(m_authorText, author);\r\n    m_authorSetProgrammatically = false;\r\n}\r\n\r\nvoid OnAuthorChanged()\r\n{\r\n    if (m_authorSetProgrammatically)\r\n    {\r\n        \/\/ Ignore programmatic setting\r\n        return;\r\n    }\r\n\r\n    \u27e6 update the author in the table \u27e7\r\n}\r\n<\/pre>\n<p>This also means that if an external component programmatically changes the author, your code will treat it as if the user had changed it. This is a good thing, because that external component might be an assistive technology that is updating the edit box on behalf of the user.<\/p>\n<p>Note that if there are multiple &#8220;author changed&#8221; handlers, and one of the other ones triggers additional changes that in turn change the author again (say, by applying an autocorrection to the new author), the second change will still be ignored because <code>m_author\u00adSet\u00adProgrammatically<\/code> is still <code>true<\/code>. To avoid that, you could reset the flag on the first notification.<\/p>\n<pre>void OnAuthorChanged()\r\n{\r\n    if (<span style=\"border: solid 1px currentcolor;\">std::exchange(m_authorSetProgrammatically, false)<\/span>)\r\n    {\r\n        \/\/ Ignore programmatic setting\r\n        return;\r\n    }\r\n\r\n    \u27e6 update the author in the table \u27e7\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>You know when it was done by your program because you did it.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-110715","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You know when it was done by your program because you did it.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110715","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=110715"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110715\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=110715"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=110715"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=110715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}