{"id":560,"date":"2011-09-16T19:54:00","date_gmt":"2011-09-16T18:54:00","guid":{"rendered":"http:\/\/shadowcovenant.com\/blog\/2011\/09\/16\/win32-tree-component\/"},"modified":"2011-09-16T19:54:00","modified_gmt":"2011-09-16T18:54:00","slug":"win32-tree-component","status":"publish","type":"post","link":"http:\/\/shadowcovenant.com\/blog\/2011\/09\/16\/win32-tree-component\/","title":{"rendered":"Win32 Tree Component"},"content":{"rendered":"<blockquote>\n<p align=\"justify\">For SurgeED, I\u2019ve had to build some tree views:<\/p>\n<\/blockquote>\n<p align=\"justify\"><a href=\"http:\/\/shadowcovenant.com\/blog\/wp-content\/uploads\/2011\/09\/tree_view.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px\" title=\"tree_view\" border=\"0\" alt=\"tree_view\" src=\"http:\/\/shadowcovenant.com\/blog\/wp-content\/uploads\/2011\/09\/tree_view_thumb.jpg\" width=\"165\" height=\"458\" \/><\/a><\/p>\n<p align=\"justify\">I\u2019m using the Win32 C API to build the GUI, but the TreeView control available didn\u2019t support everything I needed (or supported it in such oblique ways it was too much work). I tried finding a control like this on the Internet, but either they cost money (which I can\u2019t afford), the functionality wasn\u2019t there, or they used MFCs (which I don\u2019t like).<\/p>\n<p align=\"justify\">I decided to build my own, on top of the Windows one, and make the code available.<\/p>\n<p align=\"justify\">My tree view supports:<\/p>\n<ul>\n<li>\n<div align=\"justify\">Multiple selection<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Drag\/drop operation<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Context sensitive pop-up menu<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Callbacks for<\/div>\n<\/li>\n<ul>\n<li>\n<div align=\"justify\">Selection<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Command (WM_COMMAND message)<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Drag operation (start\/finish)<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Popup called<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Sort operation<\/div>\n<\/li>\n<li>\n<div align=\"justify\">Size change<\/div>\n<\/li>\n<\/ul>\n<\/ul>\n<p align=\"justify\">&#160;<\/p>\n<p align=\"justify\">You can download the files <a href=\"http:\/\/www.shadowcovenant.com\/SurgeTreeView.rar\">here<\/a>. They probably don\u2019t work \u201cout of the box\u201d, some helper functions are missing, and probably some includes need to be removed. Anyway, it should be easy enough to extrapolate what\u2019s missing.<\/p>\n<p align=\"justify\">Some usage instructions (check .h file for the public interface):<\/p>\n<ul>\n<li>\n<div align=\"justify\">To initialize (register the window class \u2013 you have to create a define called SURGE_TREE_VIEW with the name you want the class to have internally), you have to call \u201c<font face=\"Courier New\">scc_register_tree_view()<\/font>\u201d. To unregister, call \u201c<font face=\"Courier New\">scc_unregister_tree_view()<\/font>\u201d<\/div>\n<\/li>\n<li>\n<div align=\"justify\">To create a tree view, either use a custom control (with the class set to whatever the name was), or something like:<\/div>\n<\/li>\n<\/ul>\n<p align=\"justify\">&#160;<\/p>\n<blockquote>\n<p align=\"justify\"><font face=\"Courier New\">HWND tree= CreateWindow(SURGE_TREE_VIEW,window_name,window_flags,       <br \/><\/font><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; x,y,width,height,parent_window,NULL,instance,0L);<\/font><\/p>\n<ul>\n<li>\n<div align=\"justify\">To enable\/disable multiple selection, call \u201c<font face=\"Courier New\">scc_set_tree_view_multiselect(tree,true\/false)<\/font>\u201d<\/div>\n<\/li>\n<li>\n<div align=\"justify\">To set a callback function, use \u201c<font face=\"Courier New\">scc_set_tree_view_*_callback<\/font><font face=\"Arial\">\u201d<\/font><\/div>\n<\/li>\n<li>\n<div align=\"justify\">To add nodes, you have to use &quot;<font face=\"Courier New\">scc_add_node<\/font><font face=\"Arial\">\u201d. This takes as a parameter an object of type SurgeTreeNode (more on this later). This will add the node at the top level of the Tree View. To add elements as sub-nodes, use the \u201c<font face=\"Courier New\">add_node<\/font>\u201d function on the SurgeTreeNode you want to be parent of this one.<\/font><\/div>\n<\/li>\n<li>\n<div align=\"justify\">The SurgeTreeNode is the base class of all the nodes in the tree. You should subclass it for \u201ctype of nodes\u201d. For example, on the Component Explorer of SurgeED, I have loads of classes (\u201cProject\u201d, \u201cComponent Group\u201d, \u201cComponent\u201d, \u201cGroup\u201d and \u201cEntity\u201d). All of these can have different options on the pop-up menu, have different behaviors on drag, etc.<\/div>\n<\/li>\n<\/ul>\n<\/blockquote>\n<blockquote><\/blockquote>\n<ul>\n<ul>\n<li><font face=\"Courier New\">add_node<\/font>: Adds a subnode to this node<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">remove<\/font>: Remove a subnode from this node<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">expand<\/font>: Expands\/contracts this node<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">toggle_expand<\/font>: Expands the node if it is contracted, and vice-versa<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">select<\/font>: Selects this node (and the nodes below, if the second parameter is set to \u201ctrue\u201d). Note that for this to work correctly, when you select a node, all the nodes below it are unselected (or else we could have some weird behaviors on the drags), although they are still highlighted (like they are selected because someone up the chain is selected)<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">toggle_select<\/font>: Selects this node if it is unselected, and vice-versa<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">update_label<\/font>: Forces a refresh on the label of the node<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">set_bold<\/font>: Sets the label on this node to bold<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) get_label<\/font>: Returns the label of the node<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) evt_select_change<\/font>: This function is called whenever this node is selected<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) is_draggable<\/font>: Should return true if this node can be dragged. Only if all nodes in the current selection can be dragged can the operation be executed.<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) try_drag<\/font>: Should return true if this node can be dragged to the given target node<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) can_accept<\/font>: Should return true if this node can accept all the given nodes as sub-nodes<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) notify_drag<\/font>: This function gets call for each node that is dragged onto the target node, when the drag operation is completed (don\u2019t have to do anything to change the structure of the tree itself, the nodes will be moved to the correct place)<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) get_menu_options<\/font>: fetches a list of strings with the names of the options to show up on the pop-up menu. Only the options that are shared by all the selected nodes show up.<\/div>\n<\/li>\n<li>\n<div align=\"justify\"><font face=\"Courier New\">(Virtual) handle_menu_option<\/font>: Gets called for all selected nodes when an option is selected.<\/div>\n<\/li>\n<\/ul>\n<\/ul>\n<p align=\"justify\">&#160;<\/p>\n<p align=\"justify\">For the record, you can use this code in any way you want (commercial and non-commercial), a heads-up and thank you would be nice. <\/p>\n<p align=\"justify\">I\u2019m not responsible for any damages and bugs! <img decoding=\"async\" style=\"border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"http:\/\/shadowcovenant.com\/blog\/wp-content\/uploads\/2011\/09\/wlEmoticon-smile2.png\" \/><\/p>\n<p align=\"justify\">Anyway, if you have any questions, just shoot them here or email me\u2026<\/p>\n<p align=\"justify\">Hope this is helpful!<\/p>\n<div id=\"tweetbutton560\" class=\"tw_button\" style=\"\"><a href=\"http:\/\/twitter.com\/share?url=http%3A%2F%2Fshadowcovenant.com%2Fblog%2F2011%2F09%2F16%2Fwin32-tree-component%2F&amp;text=Win32%20Tree%20Component&amp;related=&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fshadowcovenant.com%2Fblog%2F2011%2F09%2F16%2Fwin32-tree-component%2F\" class=\"twitter-share-button\"  style=\"width:55px;height:22px;background:transparent url('http:\/\/shadowcovenant.com\/blog\/wp-content\/plugins\/wp-tweet-button\/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;\">Tweet<\/a><\/div>","protected":false},"excerpt":{"rendered":"<p>For SurgeED, I\u2019ve had to build some tree views: I\u2019m using the Win32 C API to build the GUI, but the TreeView control available didn\u2019t support everything I needed (or supported it in such oblique ways it was too much work). I tried finding a control like this on the Internet, but either they cost [&hellip;]<\/p>\n<div id=\"tweetbutton560\" class=\"tw_button\" style=\"\"><a href=\"http:\/\/twitter.com\/share?url=http%3A%2F%2Fshadowcovenant.com%2Fblog%2F2011%2F09%2F16%2Fwin32-tree-component%2F&amp;text=Win32%20Tree%20Component&amp;related=&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fshadowcovenant.com%2Fblog%2F2011%2F09%2F16%2Fwin32-tree-component%2F\" class=\"twitter-share-button\"  style=\"width:55px;height:22px;background:transparent url('http:\/\/shadowcovenant.com\/blog\/wp-content\/plugins\/wp-tweet-button\/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;\">Tweet<\/a><\/div>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23,59],"tags":[],"class_list":["post-560","post","type-post","status-publish","format-standard","hentry","category-development","category-surgeed-2"],"_links":{"self":[{"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/posts\/560","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/comments?post=560"}],"version-history":[{"count":0,"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/posts\/560\/revisions"}],"wp:attachment":[{"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/media?parent=560"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/categories?post=560"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/shadowcovenant.com\/blog\/wp-json\/wp\/v2\/tags?post=560"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}