{"id":8193,"date":"2012-03-01T07:00:00","date_gmt":"2012-03-01T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/03\/01\/how-do-i-make-it-so-that-users-can-copy-static-text-on-a-dialog-box-to-the-clipboard-easily\/"},"modified":"2012-03-01T07:00:00","modified_gmt":"2012-03-01T07:00:00","slug":"how-do-i-make-it-so-that-users-can-copy-static-text-on-a-dialog-box-to-the-clipboard-easily","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120301-00\/?p=8193","title":{"rendered":"How do I make it so that users can copy static text on a dialog box to the clipboard easily?"},"content":{"rendered":"<p>\nGiven that you have a Win32 dialog box with static\ntext in an <code>LTEXT<\/code> control,\nhow do you make it so that users can easily copy that\ntext to the clipboard?\n<\/p>\n<p>\nThe traditional solution is to create a borderless read-only edit control\n(which draws as static text by default).\nAdd it to the tab order by setting the <code>WS_TABSTOP<\/code>\nstyle, and maybe even\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2008\/06\/02\/8568490.aspx\">\ngive it a keyboard accelerator for accessibility<\/a>.\n<\/p>\n<p>\nStarting in Windows Vista,\nversion&nbsp;6 of the common controls provides an alternative.\n(A less accessible alternative, mind you.)\nStatic text controls automatically copy their contents\nto the clipboard when you double-click them\nif you set the <code>SS_NOTIFY<\/code> style.\n<\/p>\n<p>\nLet&#8217;s try it:\n<\/p>\n<pre>\n#include &lt;windows.h&gt;\n#include &lt;windowsx.h&gt;\n#include &lt;commctrl.h&gt;\n#pragma comment(linker, \\\n \"\\\"<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2007\/05\/31\/2995284.aspx\">\/manifestdependency<\/a>:type='Win32' \"\\\n \"name='Microsoft.Windows.Common-Controls' \"\\\n \"version='6.0.0.0' \"\\\n \"processorArchitecture='*' \"\\\n \"publicKeyToken='6595b64144ccf1df' \"\\\n \"language='*'\\\"\")\nINT_PTR CALLBACK DlgProc(\n    HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n switch (uMsg) {\n case WM_INITDIALOG:\n  return TRUE;\n case WM_COMMAND:\n  switch (GET_WM_COMMAND_ID(wParam, lParam)) {\n  case IDCANCEL:\n   EndDialog(hdlg, 0);\n   break;\n  }\n }\n return FALSE;\n}\nint WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,\n                   LPSTR lpCmdLine, int nShowCmd)\n{\n return DialogBox(hinst, MAKEINTRESOURCE(1), NULL, DlgProc);\n}\n\/\/ resource file\n#include &lt;windows.h&gt;\n1 DIALOG 50, 50, 100, 50\nSTYLE DS_SHELLFONT | WS_SYSMENU\nCAPTION \"Sample\"\nFONT 8, \"MS Shell Dlg\"\nBEGIN\n LTEXT \"Sample text 1\",100,10,10,80,10,SS_NOTIFY\n LTEXT \"Sample text 2\",101,10,20,80,10,SS_NOTIFY\n LTEXT \"Sample text 3\",102,10,30,80,10\nEND\n<\/pre>\n<p>\nRun this program and double-click on the text controls,\nand observe that the text gets copied to the clipboard,\nor at least it does for the first two, since I\nset the <code>SS_NOTIFY<\/code> style on them.\n<\/p>\n<p>\nNow, when the <i>double-click to copy<\/i>\nfeature was added to the static control,\nthere was no way to suppress it.\nThe <code>STN_DBLCLK<\/code> notification is documented\nas ignoring its return code,\nso it would be a compatibility problem if suddenly it started\nstudying its return code so that the parent could respond\n&#8220;No, I handled the click, don&#8217;t do your default action.&#8221;\nInstead, if you want to disable the <i>double-click to copy<\/i>\nfeature on a <code>SS_NOTIFY<\/code> static control,\nyou have to subclass the static control and eat\nthe clicks yourself.\n<\/p>\n<pre>\n<font COLOR=\"blue\">LRESULT CALLBACK SuppressCopyOnClick(\n    HWND hwnd, UINT uMsg, WPARAM wParam,\n    LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)\n{\n switch (uMsg) {\n case WM_LBUTTONDBLCLK: return 0; \/\/ eat the double-click\n case WM_NCDESTROY:\n  RemoveWindowSubclass(hwnd, SuppressCopyOnClick, uIdSubclass);\n  break;\n }\n return DefSubclassProc(hwnd, uMsg, wParam, lParam);\n}<\/font>\nINT_PTR CALLBACK DlgProc(\n    HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n switch (uMsg) {\n case WM_INITDIALOG:\n  <font COLOR=\"blue\">SetWindowSubclass(GetDlgItem(hdlg, 101),\n                    SuppressCopyOnClick, 0, 0);<\/font>\n  return TRUE;\n ...\n<\/pre>\n<p>\n&#8220;Why would you add a style that enabled a feature, and then\ndisable the feature?&#8221;\n<\/p>\n<p>\nMaybe you want some other aspects of the feature but not the\ncopy-on-double-click behavior.\nMaybe somebody else is adding the <code>SS_NOTIFY<\/code>\nstyle behind your back.\nFor example, a UI framework might add it automatically to all\nstatic controls.\n<\/p>\n<p>\nAnd actually, in that UI framework case,\nyou probably want the <code>STN_DBLCLK<\/code> notification\nto be fired when a double-click occurs,\nbecause you added an\n<code>OnDoubleClick<\/code> handler to your class.\nYou just don&#8217;t want the copy-to-clipboard behavior.\nWe can fix that by firing the notification in our subclass\nprocedure.\n<\/p>\n<pre>\n case WM_LBUTTONDBLCLK:\n  <font COLOR=\"blue\">if (GetWindowStyle(hwnd) &amp; SS_NOTIFY) {\n   FORWARD_WM_COMMAND(GetParent(hwnd), GetDlgCtrlID(hwnd), hwnd,\n                      STN_DBLCLK, SendMessage);\n  }\n  return 0; \/\/ message handled<\/font>\n<\/pre>\n<p>\nTo illustrate this change, we&#8217;ll make our dialog box beep\nwhen it gets a double-click notification.\nIn real life, of course, you would do whatever you want\nto happen on the &#8220;double click on a static control&#8221; event.\nActually, in real life, the code that responds to the\n<code>STN_DBLCLK<\/code>\nlives inside your framework, and it turns around and\nraises an <code>OnDoubleClick<\/code> event,\nbut for simplicity, we&#8217;ll just code it inline.<\/p>\n<pre>\n case WM_COMMAND:\n     switch (GET_WM_COMMAND_ID(wParam, lParam)) {\n     case IDCANCEL:\n        EndDialog(hdlg, 0);\n        break;\n     case 100:\n     case 101:\n     case 102:\n      switch (GET_WM_COMMAND_CMD(wParam, lParam)) {\n      \/\/ Obviously we would do something more interesting here\n      case STN_DBLCLK: MessageBeep(MB_OK); break;\n      }\n     }\n<\/pre>\n<p>\nEach of the static controls on the dialog behaves differently.\nThe first one is <code>SS_NOTIFY<\/code> with no subclassing,\nso double-clicking copies the text to the clipboard and also\nbeeps.\nThe second one is\n<code>SS_NOTIFY<\/code> with subclassing to disable\nthe copy-to-clipboard, so\ndouble-clicking merely beeps.\nAnd the third one doesn&#8217;t have the <code>SS_NOTIFY<\/code>\nstyle at all, so it neither copies the next nor responds\nto double-click.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Given that you have a Win32 dialog box with static text in an LTEXT control, how do you make it so that users can easily copy that text to the clipboard? The traditional solution is to create a borderless read-only edit control (which draws as static text by default). Add it to the tab order [&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-8193","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Given that you have a Win32 dialog box with static text in an LTEXT control, how do you make it so that users can easily copy that text to the clipboard? The traditional solution is to create a borderless read-only edit control (which draws as static text by default). Add it to the tab order [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8193","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=8193"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8193\/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=8193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=8193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=8193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}