{"id":107325,"date":"2022-10-26T07:00:00","date_gmt":"2022-10-26T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=107325"},"modified":"2022-10-26T10:54:12","modified_gmt":"2022-10-26T17:54:12","slug":"20221026-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20221026-00\/?p=107325","title":{"rendered":"What can or should I do with the cursor handle returned by <CODE>SetCursor<\/CODE>?"},"content":{"rendered":"<p>A customer was a bit confused by the return value of the <code>Set\u00adCursor<\/code> function. Why does it return the previous cursor? Does the caller own it now? Is the caller responsible for destroying it?<\/p>\n<p>First we&#8217;ll answer the questions: Ownership of the cursor does not change. Whoever was responsible for the cursor before you called <code>Set\u00adCursor<\/code> is still responsible for it.<\/p>\n<p>Okay, with the answers out of the way, let&#8217;s take a step back.<\/p>\n<p>There are two general use cases for <code>Set\u00adCursor<\/code>.<\/p>\n<p>One of them is for setting the cursor in response to a <code>WM_<wbr \/>SET\u00adCURSOR<\/code> message. The system is telling you, &#8220;Okay, you&#8217;re in charge of the cursor. Pick something.&#8221; In this case, you set the cursor, and you don&#8217;t care what the previous cursor was, because you&#8217;re choosing the cursor now. Any old cursors are losers.<\/p>\n<p>The other pattern is where you are temporarily changing the cursor (typically to an hourglass), and you want to change it back when you&#8217;re done.<\/p>\n<pre>void DoLongRunningThingOnTheUIThread()\r\n{\r\n    HCURSOR oldCursor = SetCursor(hourglass);\r\n    \/* Do stuff that DOES NOT PUMP MESSAGES *\/\r\n    SetCursor(oldCursor);\r\n}\r\n<\/pre>\n<p>It is essential that you not pump messages because<\/p>\n<ol>\n<li>If you pump messages and the user moves the mouse, then the <code>WM_<wbr \/>SET\u00adCURSOR<\/code> message will change the cursor, and your hourglass will be lost. Even worse, you will restore the wrong cursor.<\/li>\n<li>If you pump messages, then that creates the opportunity for the cursor owner to destroy the old cursor while you still have a handle to it.<\/li>\n<\/ol>\n<p>The point is that the code that had set the cursor (the cursor you are temporarily replacing) has to keep the cursor handle valid until it gets a chance to change the cursor to something else. And as long as you don&#8217;t pump messages, that code is not going to get another <code>WM_<wbr \/>SET\u00adCURSOR<\/code> message, and therefore won&#8217;t get a chance to change the cursor.<\/p>\n<p>Mind you, locking up the UI thread for a long period of time is not a great idea, so even though it is a common pattern, it&#8217;s a sign that your program should probably be moving the expensive work to a background thread.<\/p>\n<p><b>Bonus reading<\/b>: <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050525-27\/?p=35543\"> The effect of SetCursor lasts only until the next SetCursor<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can put it back, but sometimes you need to make sure you do it before anybody else can see the change.<\/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-107325","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can put it back, but sometimes you need to make sure you do it before anybody else can see the change.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107325","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=107325"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107325\/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=107325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=107325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=107325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}