{"id":35323,"date":"2005-06-14T09:02:18","date_gmt":"2005-06-14T09:02:18","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/06\/14\/displaying-the-dictionary-part-2-using-text-callbacks\/"},"modified":"2005-06-14T09:02:18","modified_gmt":"2005-06-14T09:02:18","slug":"displaying-the-dictionary-part-2-using-text-callbacks","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050614-18\/?p=35323","title":{"rendered":"Displaying the dictionary, part 2:  Using text callbacks"},"content":{"rendered":"<p>\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2005\/06\/13\/428534.aspx\">\nAs we noted last time<\/a>,\nadding items to the listview takes an absurd amount of time.\nToday, we&#8217;ll make a failed attempt at improving this\nbecause it lets me illustrate a listview technique\nand it lays the groundwork for the real fix next time.\n<\/p>\n<p>\nInstead of creating the items in their entirety,\nlet&#8217;s set their text to <code>LPSTR_TEXTCALLBACK<\/code>.\nThis is a placeholder value which indicates\n&#8220;I&#8217;m not going to tell you what the string is.\nIf you need it, call me back.&#8221;\n<\/p>\n<pre>\nclass RootWindow : public Window\n{\n ...\n LRESULT OnCreate();\n <font COLOR=\"blue\">LRESULT OnNotify(NMHDR* pnm);\n void OnGetDispInfo(NMLVDISPINFO* pnmv);<\/font>\n ...\n};\nLRESULT RootWindow::OnCreate()\n{\n ...\n <font COLOR=\"blue\"><strike>\/\/ item.pszText = const_cast&lt;LPWSTR&gt;(de.m_pszTrad);<\/strike>\n item.pszText = LPSTR_TEXTCALLBACK;<\/font>\n ...\n   <font COLOR=\"blue\"><strike>\/\/ item.pszText = const_cast&lt;LPWSTR&gt;(de.m_pszPinyin);<\/strike>\n   item.pszText = LPSTR_TEXTCALLBACK;<\/font>\n ...\n   <font COLOR=\"blue\"><strike>\/\/ item.pszText = const_cast&lt;LPWSTR&gt;(de.m_pszEnglish);<\/strike>\n   item.pszText = LPSTR_TEXTCALLBACK;<\/font>\n ...\n}\n<font COLOR=\"blue\">LRESULT RootWindow::OnNotify(NMHDR *pnm)\n{\n switch (pnm-&gt;code) {\n case LVN_GETDISPINFO:\n  OnGetDispInfo(CONTAINING_RECORD(pnm, NMLVDISPINFO, hdr));\n  break;\n }\n return 0;\n}\nvoid RootWindow::OnGetDispInfo(NMLVDISPINFO* pnmv)\n{\n if (pnmv-&gt;item.iItem &lt; 0 || \/\/ typo fixed 11am\n     pnmv-&gt;item.iItem &gt;= Length()) {\n  return;         \/\/ requesting invalid item\n }\n if (pnmv-&gt;item.mask &amp; LVIF_TEXT) {\n  const DictionaryEntry&amp; de = Item(pnmv-&gt;item.iItem);\n  LPCWSTR pszResult = L\"\";\n  switch (pnmv-&gt;item.iSubItem) {\n   case COL_TRAD:    pszResult = de.m_pszTrad;    break;\n   case COL_PINYIN:  pszResult = de.m_pszPinyin;  break;\n   case COL_ENGLISH: pszResult = de.m_pszEnglish; break;\n  }\n  pnmv-&gt;item.pszText = const_cast&lt;LPWSTR&gt;(pszResult);\n }\n if (pnmv-&gt;item.mask &amp; LVIF_IMAGE) {\n  pnmv-&gt;item.iImage = -1;\n }\n if (pnmv-&gt;item.mask &amp; LVIF_STATE) {\n     pnmv-&gt;item.state = 0;\n }\n}<\/font>\nLRESULT RootWindow::HandleMessage(\n                          UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n ...\n  <font COLOR=\"blue\">case WM_NOTIFY:\n   return OnNotify(reinterpret_cast&lt;NMHDR*&gt;(lParam));<\/font>\n ...\n}\n<\/pre>\n<p>\nInstead of setting the strings when we create the listview items,\nwe set their texts to <code>LPSTR_TEXTCALLBACK<\/code>.\nWhen the listview needs the text, it sends us a\n<code>LVN_GETDISPINFO<\/code> notification, which we handle\nby returning the data that the listview requested.\n<\/p>\n<p>\n<strong>Sidebar<\/strong>:\nIn our case, obtaining the missing data is very fast.\nIf it were slow, we could have optimized the function further by\nadding the line<\/p>\n<pre>\n pnmv-&gt;item.mask |= LVIF_DI_SETITEM;\n<\/pre>\n<p>to the end.  This tells the listview, &#8220;Please cache these results\nand don&#8217;t ask me for them again.&#8221;\nThat way, we do the slow computation only once.\n<\/p>\n<p>\nAfter making these changes (though not the <code>LVIF_DI_SETITEM<\/code>\nchange; that was just a sidebar),\nnotice that the it didn&#8217;t really help much.\nOn my machine, the startup time dropped from eleven to ten seconds,\nbut ten seconds is still way too long.\nThis optimization turns out to have been a washout.\n<\/p>\n<p>\n(Note also that our program is now relying heavily on the fact\nthat a vector is a fast random-access data structure.)\n<\/p>\n<p>\nWe&#8217;ll do better next time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As we noted last time, adding items to the listview takes an absurd amount of time. Today, we&#8217;ll make a failed attempt at improving this because it lets me illustrate a listview technique and it lays the groundwork for the real fix next time. Instead of creating the items in their entirety, let&#8217;s set their [&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-35323","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>As we noted last time, adding items to the listview takes an absurd amount of time. Today, we&#8217;ll make a failed attempt at improving this because it lets me illustrate a listview technique and it lays the groundwork for the real fix next time. Instead of creating the items in their entirety, let&#8217;s set their [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/35323","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=35323"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/35323\/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=35323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=35323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=35323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}