关于WNDCLASS中替换画刷及SetClassLongPtr与DeleteBrush的疑问
关于SetClassLongPtr替换窗口类画刷与DeleteBrush的疑惑解答
嘿,这个点当初我啃Petzold的书时也绕了好一会儿,咱们把逻辑掰碎了说:
首先得明确窗口类画刷的本质:窗口类(比如WNDCLASSEX)里的hbrBackground是类级别的资源句柄——所有基于这个类创建的窗口,都会共用这个画刷来绘制背景。
接下来看SetClassLongPtr的核心行为,这是你困惑的关键:
当你调用SetClassLongPtr(hwnd, GCLP_HBRBACKGROUND, (LONG_PTR)hNewBrush)时,它做了两件事:
- 它会返回窗口类中原来的旧画刷句柄(这个返回值很容易被忽略,但恰恰是删除旧画刷的关键)
- 用你传入的新画刷句柄,替换窗口类里存储的旧句柄
所以正确的操作流程应该是这样的(Petzold的代码里肯定隐含了这个逻辑):
// 先创建新画刷 HBRUSH hNewBrush = CreateSolidBrush(RGB(255, 200, 200)); // 调用SetClassLongPtr替换,同时拿到旧画刷的句柄 HBRUSH hOldBrush = (HBRUSH)SetClassLongPtr(hwnd, GCLP_HBRBACKGROUND, (LONG_PTR)hNewBrush); // 删除旧画刷(注意:这里删的是返回的旧句柄,不是新画刷!) if (hOldBrush != NULL && hOldBrush != (HBRUSH)GetStockObject(WHITE_BRUSH)) { DeleteBrush(hOldBrush); }
你之前的误解可能是没注意到SetClassLongPtr的返回值——DeleteBrush的参数不是你传入的新画刷,而是函数返回的旧画刷句柄。这就实现了“用新画刷替换旧画刷,同时释放旧画刷资源”的目的。
额外补充:如果旧画刷是系统库存对象(比如GetStockObject(WHITE_BRUSH)),其实不需要调用DeleteBrush,因为系统会管理这些库存资源。所以代码里通常会加个判断,避免误删系统对象。
内容的提问来源于stack exchange,提问作者bazoni
相关产品推荐
相关产品推荐

