最近遇到了一个非常奇怪的问题,反复思量就是想不通,请大家集思广益,给点思路
我做的视频控件(mfc的),在测试中需要进行创建窗口(cwnd->create) 和 销毁敞口(cwnd->destroywindow)操作。
由于视频格式要求,我要创建的窗口背景为黑色,我重载了CWnd::PreCreateWindow 在里边调用了AfxRegisterWndClass
AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
::LoadCursor( NULL, IDC_ARROW ),
(HBRUSH) ::GetStockObject(BLACK_BRUSH),
NULL
);
利用第三个参数,在注册窗口的时候将背景弄黑,这样不会有问题。
但是如果我第三个参数用了 m_hBrush = CreateSolidBrush( VIDEOWND_COLOUR )这样创建的画刷对象,反复创建,销毁窗口100次左右,create创建窗口函数便返回0,即创建窗口失败。我每次都销毁的时候也会 DeleteObject(m_hBrush);因此资源泄漏可以排除,资源管理器的内存基本没涨。
那问题是用GetStockObject获得的GDI对象,放在AfxRegisterWndClass的第三个参数处做参数就不会出上述问题(如代码中所示),CreateSolidBrush创建的就会,而且我试着每次创建窗口之后调用CreateSolidBrush函数,但不使用他返回的参数在AfxRegisterWndClass的第三个参数处,便也不会出错,这说明这样创建画刷没有错,但将返回的画刷句柄做参数就有问题了。
GetStockObject在msdn上说不用进行任何释放,为什么?StockObject是什么样的对象?什么样的叫stock“对象”。这样返回的画刷对象和我每次创建画刷再销毁画刷的做法有什么本质上的区别吗?为什么前者可以通过反复创建窗口测试,后者却不能?
我做的视频控件(mfc的),在测试中需要进行创建窗口(cwnd->create) 和 销毁敞口(cwnd->destroywindow)操作。
由于视频格式要求,我要创建的窗口背景为黑色,我重载了CWnd::PreCreateWindow 在里边调用了AfxRegisterWndClass
AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
::LoadCursor( NULL, IDC_ARROW ),
(HBRUSH) ::GetStockObject(BLACK_BRUSH),
NULL
);
利用第三个参数,在注册窗口的时候将背景弄黑,这样不会有问题。
但是如果我第三个参数用了 m_hBrush = CreateSolidBrush( VIDEOWND_COLOUR )这样创建的画刷对象,反复创建,销毁窗口100次左右,create创建窗口函数便返回0,即创建窗口失败。我每次都销毁的时候也会 DeleteObject(m_hBrush);因此资源泄漏可以排除,资源管理器的内存基本没涨。
那问题是用GetStockObject获得的GDI对象,放在AfxRegisterWndClass的第三个参数处做参数就不会出上述问题(如代码中所示),CreateSolidBrush创建的就会,而且我试着每次创建窗口之后调用CreateSolidBrush函数,但不使用他返回的参数在AfxRegisterWndClass的第三个参数处,便也不会出错,这说明这样创建画刷没有错,但将返回的画刷句柄做参数就有问题了。
GetStockObject在msdn上说不用进行任何释放,为什么?StockObject是什么样的对象?什么样的叫stock“对象”。这样返回的画刷对象和我每次创建画刷再销毁画刷的做法有什么本质上的区别吗?为什么前者可以通过反复创建窗口测试,后者却不能?
AfxRegisterWndClass只要调用一次即可,不需要每次创建窗口都调用。
另外,可以用UnregisterClass取消已注册的类,然后再DeleteObject。
以后直接用类名就行了。
AfxRegisterWndClass是注册一个WNDCLASS,注册之后这个WNDCLASS就是一直存在的,直到取消注册为止,所以只需要注册一次,CreateWindow可以无限次使用该WNDCLASS。
Stock Object 是由系统创建和维护的,因此不会出现资源泄露的问题。注意因为大家谁都可以使用,不应该用 DeleteObject 等函数删除。
CImport::CImport(){
m_hBrush = CreateSolidBrush( VIDEOWND_COLOUR );}CImport::~CImport()
{
// this->DestroyWindow();
DeleteObject(m_hBrush);
}
/*
//视频接收及显示线程开始static CWnd* WndRecvVideoScreen;
CImport* pVideoImport;
bool bVideoRecv = false;int CImport::MutiVideoRecvStart(CString ip,HWND hWnd,int port)
{
if(true == bVideoRecv)
return -1;
pVideoImport = new CImport();
// WndRecvVideoScreen->Attach(hWnd);
WndRecvVideoScreen = (CWnd*) CWnd::FromHandle(hWnd);
CRect rectWnd;
if(NULL == pVideoImport)
return -1; if ( !pVideoImport->Create(
NULL,
NULL,
WS_CHILD|WS_EX_NOPARENTNOTIFY ,
CRect( 0, 0, 0, 0 ),
WndRecvVideoScreen,//this,
0,
NULL
) )
{ // ShowErrMsg() ;
AfxMessageBox("error");
return 0;
} // pVideoImport->SelectThisPane(TRUE);
WndRecvVideoScreen->GetWindowRect(&rectWnd);
pVideoImport->SetWindowPos NULL,
0,
0, rectWnd.Width()-2,
rectWnd.Height()-2,
SWP_SHOWWINDOW
);
// pVideoImport->ShowWindow(SW_SHOW);
bVideoRecv = true;
return 1;
}
//视频接收及显示线程结束
int CImport::MutiVideoRecvStop()
{
if(false == bVideoRecv)
return -1;
if(NULL != pVideoImport)
{
// pVideoImport->VideoRecvStop();
}
//::PostMessage(pVideoImport->GetSafeHwnd(),WM_QUIT,0,0);
//pVideoImport->
:: DestroyWindow( pVideoImport->GetSafeHwnd() );
// pVideoImport->Detach();
// pVideoImport->DestroyWindow();
// WndRecvVideoScreen->DestroyWindow();
// SAFE_DELETE(WndRecvVideoScreen);
pVideoImport->ReleaseDC(pVideoImport->GetDC());
if(NULL!=pVideoImport){
delete pVideoImport;
pVideoImport=NULL; }
WndRecvVideoScreen->DeleteTempMap();
bVideoRecv = false;
return 1;
}BOOL CImport::PreCreateWindow(CREATESTRUCT &cs)
{
if ( !CWnd::PreCreateWindow( cs ) )
{
return FALSE;
}
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, ::LoadCursor( NULL, IDC_ARROW ),
(HBRUSH) ::GetStockObject(BLACK_BRUSH),
NULL
);
return TRUE;
}