{"id":27963,"date":"2007-02-19T10:00:00","date_gmt":"2007-02-19T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/02\/19\/what-does-lockwindowupdate-do\/"},"modified":"2007-02-19T10:00:00","modified_gmt":"2007-02-19T10:00:00","slug":"what-does-lockwindowupdate-do","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070219-00\/?p=27963","title":{"rendered":"What does LockWindowUpdate do?"},"content":{"rendered":"<p>\nPoor misunderstood <code>LockWindowUpdate<\/code>.\n<\/p>\n<p>\nThis is the first in a series on\n<code>LockWindowUpdate<\/code>,\nwhat it does, what it&#8217;s for and (perhaps most important) what it&#8217;s not for.\n<\/p>\n<p>\nWhat <code>LockWindowUpdate<\/code> does is pretty simple.\nWhen a window is locked,\nall attempt to draw into it or its children fail.\nInstead of drawing, the window manager remembers which parts of\nthe window the application tried to draw into, and when the\nwindow is unlocked, those areas are invalidated so that the\napplication gets another <code>WM_PAINT<\/code> message,\nthereby bringing the screen contents back in sync with what\nthe application believed to be on the screen.\n<\/p>\n<p>\nThis &#8220;keep track of what the application tried to draw\nwhile Condition&nbsp;X was in effect, and invalidate it when\nCondition&nbsp;X no longer hold&#8221; behavior you&#8217;ve seen already\nin another guise:\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/04\/28\/586018.aspx\">\n<code>CS_SAVEBITS<\/code><\/a>.\nIn this sense, <code>LockWindowUpdate<\/code> does the same bookkeeping\nthat would occur if you had covered the locked window with a\n<code>CS_SAVEBITS<\/code> window, except that it doesn&#8217;t save any bits.\n<\/p>\n<p>\nThe documentation explicitly calls out that only one window\n(per desktop, of course)\ncan be locked at a time, but this is implied by the function prototype.\nIf two windows could be locked at once, it would be impossible\nto use <code>LockWindowUpdate<\/code> reliably.\nWhat would happen if you did this:\n<\/p>\n<pre>\nLockWindowUpdate(hwndA); \/\/ locks window A\nLockWindowUpdate(hwndB); \/\/ also locks window B\nLockWindowUpdate(NULL); \/\/ ???\n<\/pre>\n<p>\nWhat does that third call to <code>LockWindowUpdate<\/code> do?\nDoes it unlock all the windows?\nOr just window&nbsp;A?\nOr just window&nbsp;B?\nWhatever your answer, it would make it impossible for the following\ncode to use <code>LockWindowUpdate<\/code> reliably:\n<\/p>\n<pre>\nvoid BeginOperationA()\n{\n LockWindowUpdate(hwndA);\n ...\n}\nvoid EndOperationA()\n{\n ...\n LockWindowUpdate(NULL);\n}\nvoid BeginOperationB()\n{\n LockWindowUpdate(hwndB);\n ...\n}\nvoid EndOperationB()\n{\n ...\n LockWindowUpdate(NULL);\n}\n<\/pre>\n<p>\nImagine that the <code>BeginOperation<\/code> functions started\nsome operation that was triggered by asynchronous activity.\nFor example, suppose operation&nbsp;A is drawing drag\/drop\nfeedback, so it begins when the mouse goes down and ends when\nthe mouse is released.\n<\/p>\n<p>\nNow suppose operation&nbsp;B finishes while a drag\/drop is\nstill in progress.\nThen <code>EndOperationB<\/code> will clean up operation&nbsp;B\nand call\n<code>LockWindowUpdate(NULL)<\/code>.\nIf you propose that that should unlock all windows,\nthen you&#8217;ve\njust ruined operation&nbsp;A, which expects that <code>hwndA<\/code>\nstill be locked.\nSimilarly, if you argue that it should unlock\nonly <code>hwndA<\/code>, then only only is operation&nbsp;A ruined,\nbut so too is operation&nbsp;B (since <code>hwndB<\/code> is still\nlocked even though the operation is complete).\nOn the other hand, if you propose that <code>LockWindowUpdate(NULL)<\/code>\nshould unlock <code>hwndB<\/code>, then consider the case where\noperation&nbsp;A completes first.\n<\/p>\n<p>\nIf <code>LockWindowUpdate<\/code> were able to lock more than one\nwindow at a time, then the function prototype would have to have\nbeen changed so that the unlock operation knows which window is\nbeing unlocked.\nThere are many ways this could have been done.\nFor example, a new parameter could have been added\nor a separate function created.\n<\/p>\n<pre>\n\/\/ Method A - new parameter\n\/\/ fLock = TRUE to lock, FALSE to unlock\nBOOL LockWindowUpdate(HWND hwnd, BOOL fLock);\n\/\/ Method B - separate function\nBOOL LockWindowUpdate(HWND hwnd);\nBOOL UnlockWindowUpdate(HWND hwnd);\n<\/pre>\n<p>\nBut neither of these is the case.\nThe <code>LockWindowUpdate<\/code> function locks only one window at a time.\nAnd the reason for this will become more clear as we learn\nwhat <code>LockWindowUpdate<\/code> is for.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Poor misunderstood LockWindowUpdate. This is the first in a series on LockWindowUpdate, what it does, what it&#8217;s for and (perhaps most important) what it&#8217;s not for. What LockWindowUpdate does is pretty simple. When a window is locked, all attempt to draw into it or its children fail. Instead of drawing, the window manager remembers which [&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-27963","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Poor misunderstood LockWindowUpdate. This is the first in a series on LockWindowUpdate, what it does, what it&#8217;s for and (perhaps most important) what it&#8217;s not for. What LockWindowUpdate does is pretty simple. When a window is locked, all attempt to draw into it or its children fail. Instead of drawing, the window manager remembers which [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/27963","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=27963"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/27963\/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=27963"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=27963"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=27963"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}