1

Bearを使用してユーザーオブジェクトを検査していますが、RemoveWindowSubclassでWindowProcカウントが減少することはありません。タスクマネージャのユーザーオブジェクトであるUSERの合計も同様です。

ウィンドウを破棄する前にサブクラスを削除することについてのレイモンドのより安全なサブクラス化のコメントを読みましたが、私のテストはウィンドウを破棄せずに行われました。

同じサブクラス化APIが、TTF_SUBCLASSされたツールのcomctlのツールチップクラスによって内部的に使用されるため、非協調的なツールチップを使用している場合は、より多くのリークが発生します。

これがVB6コードです

'--- Form1.frm '
Option Explicit

Private Declare Function SetWindowSubclass Lib "comctl32" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
Private Declare Function DefSubclassProc Lib "comctl32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function RemoveWindowSubclass Lib "comctl32" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long

Private Sub Command1_Click()
    Call SetWindowSubclass(hwnd, AddressOf RedirectTabPaneEditWndProc, 10, ObjPtr(Me))
End Sub

Private Sub Command2_Click()
    Call RemoveWindowSubclass(hwnd, AddressOf RedirectTabPaneEditWndProc, 10)
End Sub

Friend Function frWndProc(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    frWndProc = DefSubclassProc(hwnd, wMsg, wParam, lParam)
End Function

'--- Module1.bas '
Option Explicit

Public Function RedirectTabPaneEditWndProc( _
            ByVal hwnd As Long, _
            ByVal wMsg As Long, _
            ByVal wParam As Long, _
            ByVal lParam As Long, _
            ByVal uIdSubclass As Long, _
            ByVal This As Form1) As Long
    #If uIdSubclass Then '--- touch args
    #End If
    RedirectTabPaneEditWndProc = This.frWndProc(hwnd, wMsg, wParam, lParam)
End Function

誰かがコメントを残すことができれば、何が起こっているのか、そしてリークを解決する方法は素晴らしいでしょう。

SetWindowSubclass APIを使用して集中的なサブクラス化を行っている場合は、他の人に警告が表示されます。

乾杯、
</ wqw>

4

2 に答える 2

2

これを「リーク」と呼ぶのは少し双曲的だと思います。確かに、RemoveWindowSubclassが呼び出されたときにユーザーオブジェクトは復元されませんが、SetWindowSubclassを再度呼び出したときに別のオブジェクトが割り当てられることもありません。フックの設定と削除を繰り返し行うことができ、その同じユーザーオブジェクトは、プロセスの存続期間中、何度も再利用されているように見えます。

私はあなたの最も単純なシナリオを拡張したいくつかのテストを行いました。背景を参照するために、2つのコマンドボタンがあり、ウィンドウフックがないフォームの各インスタンスは、6つのUserオブジェクトを消費します。SetWindowSubclassを呼び出すと、実際にはウィンドウクラスごとにもう1つのUserオブジェクトが消費されます。つまり、そのフォームの複数のインスタンスをロードし、フォーム自体とそれに含まれる両方のコマンドボタンのメッセージストリームをフックして、合計2つのユーザーオブジェクトを使用できます。ご存知のように、これらはプロセスの存続期間中はリサイクルされません。

内部のデザインはもっときれいにできますか?おそらく。それからまた、おそらくそうではありません。私はこれが心配するほどの原因ではないと思います。より大きな懸念の原因は、これが懸念されるように設計されたアプリケーションです。その場合、UIデザイン全体の根本的な再検討が必要になる場合があります。1つのプロセスで非常に多くのウィンドウクラスをサブクラス化して、各クラスのこの余分なオブジェクトが問題になる可能性があるのはいつか想像できません。

于 2009-07-23T17:40:29.140 に答える
1

これは、VB6でサブクラス化を行うための珍しい方法です。SetWindowLong(GWL_WNDPROC)を使用すると、さらに運が良くなる可能性があります。KarlPetersonのこのVB6コードを参照してください。

興味深いことに、Karlは現在、使用しているのと同じcomctl32関数を試しているようです。編集:はい、彼は記事を投稿しました。編集:ああ、そしてこの質問への答え:)

于 2009-07-14T09:14:27.210 に答える