Don't assert if HWND is invalid in wxWindow::DissociateHandle()
There was no safe way to prevent wxWindow from trying to destroy the HWND again if it had been already destroyed, for whatever reason, as UnsubclassWin() asserted if it was called and calling SetHWND(0) before calling it as some (but not all) existing code did, resulted in not removing the association using the old HWND as key. Allow to use DissociateHandle() for safely detaching HWND from the window, without assuming that it is valid.
This commit is contained in:
parent
13ebaee247
commit
82729cb93a
2 changed files with 33 additions and 7 deletions
|
|
@ -749,6 +749,9 @@ private:
|
|||
// common part of all ctors
|
||||
void Init();
|
||||
|
||||
// common part of UnsubclassWin() and DissociateHandle()
|
||||
WXHWND DoDetachHWND();
|
||||
|
||||
// the (non-virtual) handlers for the events
|
||||
bool HandleMove(int x, int y);
|
||||
bool HandleMoving(wxRect& rect);
|
||||
|
|
|
|||
|
|
@ -1364,14 +1364,10 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd)
|
|||
|
||||
void wxWindowMSW::UnsubclassWin()
|
||||
{
|
||||
wxRemoveHandleAssociation(this);
|
||||
HWND hwnd = DoDetachHWND();
|
||||
|
||||
// Restore old Window proc
|
||||
HWND hwnd = GetHwnd();
|
||||
if ( hwnd )
|
||||
{
|
||||
SetHWND(0);
|
||||
|
||||
wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
|
||||
|
||||
if ( m_oldWndProc )
|
||||
|
|
@ -1386,6 +1382,20 @@ void wxWindowMSW::UnsubclassWin()
|
|||
}
|
||||
}
|
||||
|
||||
WXHWND wxWindowMSW::DoDetachHWND()
|
||||
{
|
||||
wxRemoveHandleAssociation(this);
|
||||
|
||||
// Restore old Window proc
|
||||
HWND hwnd = GetHwnd();
|
||||
if ( hwnd )
|
||||
{
|
||||
SetHWND(0);
|
||||
}
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
void wxWindowMSW::AssociateHandle(WXWidget handle)
|
||||
{
|
||||
if ( m_hWnd )
|
||||
|
|
@ -1404,8 +1414,21 @@ void wxWindowMSW::AssociateHandle(WXWidget handle)
|
|||
|
||||
void wxWindowMSW::DissociateHandle()
|
||||
{
|
||||
// this also calls SetHWND(0) for us
|
||||
UnsubclassWin();
|
||||
// Unlike in UnsubclassWin() we don't assume that the old HWND was valid,
|
||||
// it could have been already destroyed, but if it is valid, we can just
|
||||
// forward to it.
|
||||
if ( ::IsWindow(GetHwnd()) )
|
||||
{
|
||||
UnsubclassWin();
|
||||
}
|
||||
else // Otherwise just forget about the old HWND.
|
||||
{
|
||||
DoDetachHWND();
|
||||
|
||||
// We shouldn't try to restore it later as it corresponded to a HWND
|
||||
// which doesn't exist any longer.
|
||||
m_oldWndProc = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue