<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Memory oder Handle leak bei TreeView Drag&amp;amp;Drop]]></title><description><![CDATA[<p>Hi Coders,</p>
<p>in meinem Programm vermute ich ein Memory- oder Handle-Leak bei den Bitmap-Objekten in einem TreeView-Control.<br />
(Visual Studio 6, kein MFC o.ä.)</p>
<p>Mit Tools wie z.B. GDIOBj <a href="http://www.fengyuan.com/bin/gdiobj.zip" rel="nofollow">http://www.fengyuan.com/bin/gdiobj.zip</a> oder Bear <a href="http://www.geocities.com/the_real_sz/misc/bear_.htm" rel="nofollow">http://www.geocities.com/the_real_sz/misc/bear_.htm</a> kann man Handle-Leaks (z.B. GDI-Leaks) bequem aufspüren.</p>
<p>Angenommen, bei Programmstart werden 7 Bitmaps (d.h. 7 Bitmap-Handles in GDI) angelegt.<br />
Während eines Drag&amp;Drops in einem TreeView-Control steigt der Verbrauch auf 14 Bitmaps an, soweit ok.<br />
Nach Beendigung des Drag&amp;Drops geht die Anzahl der Bitmap-Handles jedoch nur noch auf 10 zurück, statt wie erwartet auf den Anfangswert 7.<br />
Wiederhole ich die gleiche Drag&amp;Drop-Aktion, so steigt der Wert wieder auf den alten Spitzenwert 14 an.<br />
Danach fällt der Verbrauch erneut auf 10 zurück (und driftet also auch nicht periodisch weg).<br />
Und das Phänomen ist beliebig oft reproduzierbar.</p>
<p>Könnt Ihr dieses Phänomen auch bei Euch beobachten?</p>
<p>Im Grunde genommen sind die &quot;mysteriösen&quot; verbleibenden Leaks von den 3 Bitmap-Handles vernachlässigbar.<br />
Dennoch würde es mich schon sehr interessieren, warum diese nicht freigegeben werden. Alleine schon um den Lerneffekt zu erhöhen.</p>
<p>Ich verwende den gleichen Konstrukt, wie er in vielen Codebeispielen im Internet zu finden ist. Lediglich Subclassing wurde noch angewendet.</p>
<p>Das (stark abgespeckte) Skeleton meines TreeView Drag&amp;Drop in meinem Programm sieht wie folgt aus:<br />
(Alle Codeteile werden von Proc_Window_Frame() des Parent-Fensters hwnd_frame aus aufgerufen)</p>
<pre><code class="language-cpp">case WM_CREATE:
hwnd_tree = CreateWindowEx( WS_CHILD... );    //TreeView-Fenster als Child-Fenster generieren.
pProc_TreeView_original = SetWindowLongPtr( hwnd_tree, GWLP_WNDPROC, (LONG_PTR)Proc_Window_TreeView );
                                              //Subclassing TreeView WndProc
himl_tree = ImageList_Create();
hbitmap = LoadBitmap();
ImageList_AddMasked( himl_tree, hbitmap );
DeleteObject( hbitmap );
b_tree_mousedrag_aktiv = 0;
</code></pre>
<pre><code class="language-cpp">case WM_NOTIFY:

/* dann -&gt; */ case TVN_BEGINDRAG:
himl_tree_drag = TreeView_CreateDragImage( pstruct_nmtv-&gt;hdr.hwndFrom );
ImageList_BeginDrag( himl_tree_drag );
ImageList_DragEnter( pstruct_nmtv-&gt;hdr.hwndFrom );
SetCapture( hwnd_frame );
b_tree_mousedrag_aktiv = 1;
</code></pre>
<pre><code class="language-cpp">case WM_MOUSEMOVE:
if ( b_tree_mousedrag_aktiv != 0 )
{
  ImageList_DragMove();
  ImageList_DragShowNolock( FALSE );
  TreeView_Select( hwnd_tree, htreeitem, TVGN_DROPHILITE );   //Beim Draggen das darunterliegende Item selektieren.
  ImageList_DragShowNolock( TRUE );
}
</code></pre>
<pre><code class="language-cpp">case WM_LBUTTONUP:      //Drag&amp;Drop erfolgreich umsetzen.
case WM_CAPTURECHANGED: //Drag&amp;Drop abbrechen.
case WM_RBUTTONDOWN:    //Drag&amp;Drop abbrechen.
if ( b_tree_mousedrag_aktiv != 0 )
{
  ImageList_DragLeave( hwnd_tree );
  ImageList_EndDrag();
  //ImageList_RemoveAll( himl_tree_drag );  // &lt;-- habe ich in keinem Sample gesehen, hat aber leider keine Auswirkung.
  ImageList_Destroy( himl_tree_drag );
  b_tree_mousedrag_aktiv = 0;
  ReleaseCapture(); //Calling ReleaseCapture() causes the window that is losing
                    //the mouse capture to receive a WM_CAPTURECHANGED message.
  ShowCursor( TRUE );
}
</code></pre>
<p>Ich hoffe, ich habe nicht zuviel von meinem Code wegkopiert?<br />
(Damit die Lesbarkeit nicht unnötig erschwert wird, sind auch die notwendigen Fehlerabfragen bereits entfernt)</p>
<p>Bin auf Eure Hinweise dankbar,<br />
Martin</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/223883/memory-oder-handle-leak-bei-treeview-drag-amp-drop</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 23:04:29 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/223883.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 02 Oct 2008 08:32:04 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Memory oder Handle leak bei TreeView Drag&amp;amp;Drop on Thu, 02 Oct 2008 08:32:04 GMT]]></title><description><![CDATA[<p>Hi Coders,</p>
<p>in meinem Programm vermute ich ein Memory- oder Handle-Leak bei den Bitmap-Objekten in einem TreeView-Control.<br />
(Visual Studio 6, kein MFC o.ä.)</p>
<p>Mit Tools wie z.B. GDIOBj <a href="http://www.fengyuan.com/bin/gdiobj.zip" rel="nofollow">http://www.fengyuan.com/bin/gdiobj.zip</a> oder Bear <a href="http://www.geocities.com/the_real_sz/misc/bear_.htm" rel="nofollow">http://www.geocities.com/the_real_sz/misc/bear_.htm</a> kann man Handle-Leaks (z.B. GDI-Leaks) bequem aufspüren.</p>
<p>Angenommen, bei Programmstart werden 7 Bitmaps (d.h. 7 Bitmap-Handles in GDI) angelegt.<br />
Während eines Drag&amp;Drops in einem TreeView-Control steigt der Verbrauch auf 14 Bitmaps an, soweit ok.<br />
Nach Beendigung des Drag&amp;Drops geht die Anzahl der Bitmap-Handles jedoch nur noch auf 10 zurück, statt wie erwartet auf den Anfangswert 7.<br />
Wiederhole ich die gleiche Drag&amp;Drop-Aktion, so steigt der Wert wieder auf den alten Spitzenwert 14 an.<br />
Danach fällt der Verbrauch erneut auf 10 zurück (und driftet also auch nicht periodisch weg).<br />
Und das Phänomen ist beliebig oft reproduzierbar.</p>
<p>Könnt Ihr dieses Phänomen auch bei Euch beobachten?</p>
<p>Im Grunde genommen sind die &quot;mysteriösen&quot; verbleibenden Leaks von den 3 Bitmap-Handles vernachlässigbar.<br />
Dennoch würde es mich schon sehr interessieren, warum diese nicht freigegeben werden. Alleine schon um den Lerneffekt zu erhöhen.</p>
<p>Ich verwende den gleichen Konstrukt, wie er in vielen Codebeispielen im Internet zu finden ist. Lediglich Subclassing wurde noch angewendet.</p>
<p>Das (stark abgespeckte) Skeleton meines TreeView Drag&amp;Drop in meinem Programm sieht wie folgt aus:<br />
(Alle Codeteile werden von Proc_Window_Frame() des Parent-Fensters hwnd_frame aus aufgerufen)</p>
<pre><code class="language-cpp">case WM_CREATE:
hwnd_tree = CreateWindowEx( WS_CHILD... );    //TreeView-Fenster als Child-Fenster generieren.
pProc_TreeView_original = SetWindowLongPtr( hwnd_tree, GWLP_WNDPROC, (LONG_PTR)Proc_Window_TreeView );
                                              //Subclassing TreeView WndProc
himl_tree = ImageList_Create();
hbitmap = LoadBitmap();
ImageList_AddMasked( himl_tree, hbitmap );
DeleteObject( hbitmap );
b_tree_mousedrag_aktiv = 0;
</code></pre>
<pre><code class="language-cpp">case WM_NOTIFY:

/* dann -&gt; */ case TVN_BEGINDRAG:
himl_tree_drag = TreeView_CreateDragImage( pstruct_nmtv-&gt;hdr.hwndFrom );
ImageList_BeginDrag( himl_tree_drag );
ImageList_DragEnter( pstruct_nmtv-&gt;hdr.hwndFrom );
SetCapture( hwnd_frame );
b_tree_mousedrag_aktiv = 1;
</code></pre>
<pre><code class="language-cpp">case WM_MOUSEMOVE:
if ( b_tree_mousedrag_aktiv != 0 )
{
  ImageList_DragMove();
  ImageList_DragShowNolock( FALSE );
  TreeView_Select( hwnd_tree, htreeitem, TVGN_DROPHILITE );   //Beim Draggen das darunterliegende Item selektieren.
  ImageList_DragShowNolock( TRUE );
}
</code></pre>
<pre><code class="language-cpp">case WM_LBUTTONUP:      //Drag&amp;Drop erfolgreich umsetzen.
case WM_CAPTURECHANGED: //Drag&amp;Drop abbrechen.
case WM_RBUTTONDOWN:    //Drag&amp;Drop abbrechen.
if ( b_tree_mousedrag_aktiv != 0 )
{
  ImageList_DragLeave( hwnd_tree );
  ImageList_EndDrag();
  //ImageList_RemoveAll( himl_tree_drag );  // &lt;-- habe ich in keinem Sample gesehen, hat aber leider keine Auswirkung.
  ImageList_Destroy( himl_tree_drag );
  b_tree_mousedrag_aktiv = 0;
  ReleaseCapture(); //Calling ReleaseCapture() causes the window that is losing
                    //the mouse capture to receive a WM_CAPTURECHANGED message.
  ShowCursor( TRUE );
}
</code></pre>
<p>Ich hoffe, ich habe nicht zuviel von meinem Code wegkopiert?<br />
(Damit die Lesbarkeit nicht unnötig erschwert wird, sind auch die notwendigen Fehlerabfragen bereits entfernt)</p>
<p>Bin auf Eure Hinweise dankbar,<br />
Martin</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1591921</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1591921</guid><dc:creator><![CDATA[Mmacher]]></dc:creator><pubDate>Thu, 02 Oct 2008 08:32:04 GMT</pubDate></item><item><title><![CDATA[Reply to Memory oder Handle leak bei TreeView Drag&amp;amp;Drop on Thu, 02 Oct 2008 08:50:09 GMT]]></title><description><![CDATA[<p>So wie ich das sehe ist das kein Leak. Die Anzahl der Handles steigt ja nicht weiter.</p>
<p>1. ImageList_BeginDrag erzegt eine interne Kopie der Imagelist, Du kannst Deine Kopie sofort entsorgen, nachdem Du ImageList_BeginDrag aufgerufen hast!<br />
2. ImageList_EndDrag entsorgt IMHO einige ImageLists aber nicht alle. Einige werden einfach weiterhin im Speicher gehalten und wiederverwendet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1591940</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1591940</guid><dc:creator><![CDATA[Martin Richter]]></dc:creator><pubDate>Thu, 02 Oct 2008 08:50:09 GMT</pubDate></item><item><title><![CDATA[Reply to Memory oder Handle leak bei TreeView Drag&amp;amp;Drop on Thu, 02 Oct 2008 15:05:03 GMT]]></title><description><![CDATA[<p>Hi Martin,<br />
das ist aber eine fixe Antwort <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
<p>Danke für das Hintergrundinfo!<br />
Martin</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1592270</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1592270</guid><dc:creator><![CDATA[Mmacher]]></dc:creator><pubDate>Thu, 02 Oct 2008 15:05:03 GMT</pubDate></item></channel></rss>