{"id":112045,"date":"2026-02-06T07:00:00","date_gmt":"2026-02-06T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=112045"},"modified":"2026-02-06T10:59:20","modified_gmt":"2026-02-06T18:59:20","slug":"20260206-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260206-00\/?p=112045","title":{"rendered":"How can I prevent the user from changing the widths of ListView columns in version 5 of the common controls?, part 2"},"content":{"rendered":"<p>Last time, we had figured out how to <a title=\"How can I prevent the user from changing the widths of ListView columns in version 5 of the common controls?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260205-00\/?p=112042\"> prevent the version 5 ListView Win32 common control from resizing columns<\/a>, but we noticed that the cursor still changes to a resize cursor that doesn&#8217;t work. How can we avoid misleading the user?<\/p>\n<p>I had a few ideas but decided that the easiest way would be to subclass the header control and override its <code>WM_<wbr \/>SET\u00adCURSOR<\/code> message with one that just sets the arrow cursor.<\/p>\n<pre>LRESULT CALLBACK AlwaysArrowSubclassProc(\r\n    HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,\r\n    [[maybe_unused]] UINT_PTR uIdSubclass,\r\n    [[maybe_unused]] DWORD_PTR dwRefData)\r\n{\r\n    switch (uMsg) {\r\n    case WM_SETCURSOR:\r\n        SetCursor(LoadCursor(nullptr, IDC_ARROW));\r\n        return 1;\r\n    }\r\n    return DefSubclassProc(hWnd, uMsg, wParam, lParam);\r\n}\r\n\r\n    case WM_CREATE: \/\/ or WM_INITDIALOG if this is a dialog procedure\r\n        \u27e6 ... \u27e7\r\n\r\n        SetWindowSubclass(ListView_GetHeader(hwndLV),\r\n                          AlwaysArrowSubclassProc, 1, 0);\r\n\r\n        \u27e6 ... \u27e7\r\n        return 0;\r\n\r\n    case WM_DESTROY:\r\n        RemoveWindowSubclass(ListView_GetHeader(hwndLV),\r\n                             AlwaysArrowSubclassProc, 1);\r\n\r\n        \u27e6 ... \u27e7\r\n        return 0;\r\n<\/pre>\n<p>Alternatively, we could have the subclass procedure be self-destroying.<\/p>\n<pre>LRESULT CALLBACK AlwaysArrowSubclassProc(\r\n    HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,\r\n    UINT_PTR uIdSubclass, [[maybe_unused]] DWORD_PTR dwRefData)\r\n\r\n{\r\n    switch (uMsg) {\r\n    <span style=\"border: solid 1px currentcolor; border-bottom: none;\">case WM_NCDESTROY:                                                   <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">    RemoveWindowSubclass(hWnd, AlwaysArrowSubclassProc, uIdSubclass);<\/span>\r\n    <span style=\"border: solid 1px currentcolor; border-top: none;\">    break;                                                           <\/span>\r\n    case WM_SETCURSOR:\r\n        SetCursor(LoadCursor(nullptr, IDC_ARROW));\r\n        return 1;\r\n    }\r\n    return DefSubclassProc(hWnd, uMsg, wParam, lParam);\r\n}\r\n\r\n    case WM_CREATE: \/\/ or WM_INITDIALOG if this is a dialog procedure\r\n        \u27e6 ... \u27e7\r\n\r\n        SetWindowSubclass(ListView_GetHeader(hwndLV),\r\n                          AlwaysArrowSubclassProc, 1, 0);\r\n\r\n        \u27e6 ... \u27e7\r\n        return 0;\r\n\r\n    case WM_DESTROY:\r\n        \/\/ <span style=\"text-decoration: line-through;\">RemoveWindowSubclass(ListView_GetHeader(hwndLV),<\/span>\r\n        \/\/ <span style=\"text-decoration: line-through;\">                     AlwaysArrowSubclassProc, 1);<\/span>\r\n\r\n        \u27e6 ... \u27e7\r\n        return 0;\r\n<\/pre>\n<p>We could generalize this subclass procedure so it always sets the cursor to one specified in its <code>dwRefData<\/code>.<\/p>\n<pre>LRESULT CALLBACK <span style=\"border: solid 1px currentcolor;\">FixedCursorSubclassProc<\/span>(\r\n    HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,\r\n    UINT_PTR uIdSubclass, [[maybe_unused]] DWORD_PTR dwRefData)\r\n\r\n{\r\n    switch (uMsg) {\r\n    case WM_NCDESTROY:\r\n        RemoveWindowSubclass(hWnd, <span style=\"border: solid 1px currentcolor;\">FixedCursorSubclassProc<\/span>, uIdSubclass);\r\n        break;\r\n    case WM_SETCURSOR:\r\n        SetCursor(<span style=\"border: solid 1px currentcolor;\">(HCURSOR)dwRefData<\/span>);\r\n        return 1;\r\n    }\r\n    return DefSubclassProc(hWnd, uMsg, wParam, lParam);\r\n}\r\n\r\n    case WM_CREATE: \/\/ or WM_INITDIALOG if this is a dialog procedure\r\n        \u27e6 ... \u27e7\r\n\r\n        SetWindowSubclass(ListView_GetHeader(hwndLV),\r\n                          <span style=\"border: solid 1px currentcolor;\">FixedCursorSubclassProc<\/span>, 1,\r\n                          <span style=\"border: solid 1px currentcolor;\">(DWORD_PTR)LoadCursor(nullptr, IDC_ARROW)<\/span>);\r\n\r\n        \u27e6 ... \u27e7\r\n        return 0;\r\n<\/pre>\n<p>And then I realized that I don&#8217;t need to set the cursor at all. The default window procedure sets the cursor to the class cursor. We just have to call it.<\/p>\n<pre>LRESULT CALLBACK <span style=\"border: solid 1px currentcolor;\">ClassCursorSubclassProc<\/span>(\r\n    HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,\r\n    UINT_PTR uIdSubclass, [[maybe_unused]] DWORD_PTR dwRefData)\r\n\r\n{\r\n    switch (uMsg) {\r\n    case WM_NCDESTROY:\r\n        RemoveWindowSubclass(hWnd, <span style=\"border: solid 1px currentcolor;\">ClassCursorSubclassProc<\/span>, uIdSubclass);\r\n        break;\r\n    case WM_SETCURSOR:\r\n        <span style=\"border: solid 1px currentcolor;\">return DefWindowProc(hWnd, uMsg, wParam, lParam);<\/span>\r\n    }\r\n    return DefSubclassProc(hWnd, uMsg, wParam, lParam);\r\n}\r\n\r\n    case WM_CREATE: \/\/ or WM_INITDIALOG if this is a dialog procedure\r\n        \u27e6 ... \u27e7\r\n\r\n        SetWindowSubclass(ListView_GetHeader(hwndLV),\r\n                          <span style=\"border: solid 1px currentcolor;\">ClassCursorSubclassProc<\/span>, 1, <span style=\"border: solid 1px currentcolor;\">0<\/span>);\r\n\r\n        \u27e6 ... \u27e7\r\n        return 0;\r\n<\/pre>\n<p>Recall that all of this work is just to work around the lack of support for the <code>HDS_<wbr \/>NO\u00adSIZING<\/code> style in the version 5 common controls library. If you are using version 6 (and really, you should be), then just set the <code>HDS_<wbr \/>NO\u00adSIZING<\/code> style onto the ListView&#8217;s header control, and you&#8217;re all done.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Preventing the resize cursor from appearing.<\/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-112045","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Preventing the resize cursor from appearing.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112045","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=112045"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112045\/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=112045"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=112045"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=112045"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}