首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SetWindowSubclass正在泄漏用户对象

SetWindowSubclass正在泄漏用户对象
EN

Stack Overflow用户
提问于 2009-07-13 15:55:27
回答 2查看 1.7K关注 0票数 1

我使用Bear来检查用户对象,在RemoveWindowSubclass上WindowProc计数从来不会减少。作为Task Manager中的USER对象的User中的总数也是如此。

我读了Raymond关于在销毁窗口之前删除子类化的Safer subclassing评论,但我的测试是在没有销毁它的情况下完成的。

对于TTF_SUBCLASS‘’ed的工具,comctl的tooltip类在内部使用相同的子类化API,因此如果您使用非协作工具提示,则会发生更多的泄漏。

下面是VB6代码

代码语言:javascript
复制
'--- 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进行密集的子类化,请警告其他任何人。

干杯,

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-07-23 17:40:29

我认为把这称为“泄漏”有点夸张。如果为True,则调用RemoveWindowSubclass时不会恢复user对象,但再次调用SetWindowSubclass时也不会分配另一个user对象。您可以重复设置和删除钩子,同一个user对象似乎会在进程的生命周期中被反复使用。

我又做了几个测试,对您最简单的场景进行了扩展。仅供背景参考,每个具有两个命令按钮且没有窗口挂钩的窗体实例使用六个用户对象。调用SetWindowSubclass确实会为每个窗口类多消耗一个User对象。也就是说,我可以加载该表单的多个实例,并为表单本身和两个包含的命令按钮连接消息流,并总共使用两个User对象。正如您所观察到的,这些都不会在流程的生命周期中被回收。

内部设计能不能更整洁?有可能。话又说回来,可能不是。我一点也不觉得这有什么值得担心的地方。一个更值得关注的原因是,应用程序的设计可能会引起关注。在这种情况下,可能需要对整个UI设计进行根本性的重新考虑。我简直无法想象,什么时候你会在一个进程中继承如此多的窗口类,以至于每个类的这个额外的对象可能会很重要。

票数 2
EN

Stack Overflow用户

发布于 2009-07-14 09:14:27

这是在VB6中进行子类化的一种不寻常的方式。您可能会更幸运地使用SetWindowLong(GWL_WNDPROC) -参见Karl Peterson的this VB6 code

有趣的是,看起来Karl使用与您正在使用的相同的comctl32函数进行experimenting right now。编辑:是的,他是posted an article。编辑:哦,还有an answer to this question :)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1120337

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档