{"id":1713,"date":"2014-02-19T07:00:00","date_gmt":"2014-02-19T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/02\/19\/when-will-the-static-control-automatically-delete-the-image-loaded-into-it-and-when-is-it-the-responsibility-of-the-application\/"},"modified":"2014-02-19T07:00:00","modified_gmt":"2014-02-19T07:00:00","slug":"when-will-the-static-control-automatically-delete-the-image-loaded-into-it-and-when-is-it-the-responsibility-of-the-application","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20140219-00\/?p=1713","title":{"rendered":"When will the static control automatically delete the image loaded into it, and when is it the responsibility of the application?"},"content":{"rendered":"<p>\nIf you create a static control with initial contents\n(for example, by creating a <code>BITMAP<\/code> or\n<code>ICON<\/code> control in a dialog template),\nthen the static control will load the contents upon\ncreation and destroy the contents upon destruction.\nSo at least in the case where you don&#8217;t touch the\nstatic control, things will work automatically.\n<\/p>\n<p>\nBut once you touch it, things get confusing.\n<\/p>\n<p>\nIf you send the <code>STM_SET&shy;IMAGE<\/code>\nmessage to a static control, this does a few things\n(assuming your parameters are all valid):\n<\/p>\n<ul>\n<li>The previous image is replaced by the new image you passed.\n<li>The message returns a handle to the previous image.\n<li>The static control <i>turns off automatic image deletion<\/i>.\n<\/ul>\n<p>\nThe third part is the tricky part.\nIf you ever (successfully) send a static control the\n<code>STM_SET&shy;IMAGE<\/code> message,\nthen it says,\n&#8220;Okay, it&#8217;s all your problem now.&#8221;\nYou are now responsible not only for destroying the\nnew image,\nbut you are also responsible for destroying the old image\nthat was returned.\n<\/p>\n<p>\nIn other words,\nthe following operation is <i>not<\/i> a nop:\n<\/p>\n<pre>\nHBITMAP hbmPrev = SendMessage(hwndStatic, STM_SETIMAGE,\n                              IMAGE_BITMAP, (LPARAM)hbmNew);\nSendMessage(hwndStatic, STM_SETIMAGE,\n            IMAGE_BITMAP, (LPARAM)hbmPrev);\n<\/pre>\n<p>\nThis sounds like a nop,\nsince all you did was change the image,\nand then change it back.\nBut the side effect is also that you made the static\ncontrol go into <i>your problem<\/i> mode,\nand the original image will no longer be automatically\ndestroyed.\nIf you forget to destroy it yourself, then you have a leak.\n<\/p>\n<p>\n<i>Wait, it gets worse.<\/i>\n<\/p>\n<p>\nIf you are using version&nbsp;6 of the common controls,\nthen things get even more confusing if you\nuse the <code>STM_SET&shy;IMAGE<\/code> message\nto change the <code>IMAGE_BITMAP<\/code> of a\n<code>SS_BITMAP<\/code> static control,\nand the bitmap you pass is a 32-bpp bitmap,\nand the image has a nonzero alpha channel,\nthen the static control will make a <i>copy<\/i>\nof the bitmap you passed in and act as if you had passed\nthat copy instead.&sup1;\nThis by itself is no big deal, because the responsibility\nfor destroying the image you passed in still resides with\nyou, the application,\nso the rules haven&#8217;t changed there.\n<\/p>\n<p>\nThe nasty bit is that the application also must assume\nresponsibility for <i>destroying the secret copy<\/i>.\nThat bitmap you didn&#8217;t even know existed and don&#8217;t have\na handle to?\nYeah, you&#8217;re on the hook for that one too.\n<\/p>\n<p>\nHow unfair.\n<\/p>\n<p>\nEven more confusing is that if you send\n<code>STM_SET&shy;IMAGE<\/code> a second time,\nit will replace the bitmap and return a handle to\n<i>the secret copy<\/i> (which is a bitmap you&#8217;ve never\nseen before).\n<\/p>\n<p>\nThis means that the following assertion can fire:\n<\/p>\n<pre>\nHBITMAP hbmPrev = SendMessage(hwndStatic, STM_SETIMAGE,\n                              IMAGE_BITMAP, (LPARAM)hbmNew);\nHBITMAP hbmBack = SendMessage(hwndStatic, STM_SETIMAGE,\n                              IMAGE_BITMAP, (LPARAM)hbmPrev);\nassert(hbmNew == hbmBack); \/\/ ??\n<\/pre>\n<p>\nYou would think that the assertion is safe because all you\ndid was change the bitmap to <code>hbmNew<\/code>, then change\nit back.\nAnd when you change it back, the &#8220;previous value&#8221; is the\nvalue <code>hbmNew<\/code> you set it to on the previous line.\n<\/p>\n<p>\nExcept that if <code>hbmNew<\/code> satisfies the above magic criteria,\nthen the value in <code>hbmBack<\/code> is not <code>hbmNew<\/code>\nbut rather the handle to the <i>secret copy<\/i>.\n<\/p>\n<p>\nWhich you have to remember to destroy.\n<\/p>\n<p>\nYuck.\n<\/p>\n<p>\nThe secret copy is not <i>too<\/i> secret.\nYou can get a handle to it by sending the\n<code>STM_GET&shy;IMAGE<\/code> message.\nWhich you now need to do when you destroy the static control,\njust in case it&#8217;s the <i>secret copy<\/i>.\nYou need to compare the current image against the one that\nyou thought you passed in,\nand if they are different, then you have the <i>secret copy<\/i>\nthat needs to be destroyed as an extra step.\n<\/p>\n<p>\nYes, this sucks.\nI apologize.\n<\/p>\n<p>\n(My recommendation: To detect whether a &#8220;secret copy&#8221; occurred,\ndo a\n<code>STM_GET&shy;IMAGE<\/code> after your\n<code>STM_SET&shy;IMAGE<\/code> and see if the handles match.)\n<\/p>\n<p>\n&sup1; The <i>secret copy<\/i> is not an exact copy.\n(After all, if it were an exact copy, then there would be no need\nto create the copy.\nIt could just use the handle you passed in.)\nInstead, the <i>secret copy<\/i> is a copy of the original,\nfollowed by some\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/shawnhar\/archive\/2009\/11\/06\/premultiplied-alpha.aspx\">\nadditional munging<\/a>\nso that it can be displayed\non the screen while respecting the alpha channel you passed in.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you create a static control with initial contents (for example, by creating a BITMAP or ICON control in a dialog template), then the static control will load the contents upon creation and destroy the contents upon destruction. So at least in the case where you don&#8217;t touch the static control, things will work automatically. [&hellip;]<\/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-1713","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>If you create a static control with initial contents (for example, by creating a BITMAP or ICON control in a dialog template), then the static control will load the contents upon creation and destroy the contents upon destruction. So at least in the case where you don&#8217;t touch the static control, things will work automatically. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/1713","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=1713"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/1713\/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=1713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=1713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=1713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}