こんどはProgressDialogを実装しているsrc/generic/progdlgg.cpp
まずは::Updateの中でbarがいっぱいになるようなvalueを渡したときの処理が行われる部分。
if ( value == m_maximum )
{
if ( m_state == Finished )
{
// ignore multiple calls to Update(m_maximum): it may sometimes be
// troublesome to ensure that Update() is not called twice with the
// same value (e.g. because of the rounding errors) and if we don't
// return now we're going to generate asserts below
return true;
}
// so that we return true below and that out [Cancel] handler knew what
// to do
m_state = Finished;
if( !(GetWindowStyle() & wxPD_AUTO_HIDE) )
{
EnableClose();
DisableSkip();
#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
EnableCloseButton();
#endif // __WXMSW__
if ( newmsg.empty() )
{
// also provide the finishing message if the application didn't
m_msg->SetLabel(_("Done."));
}
wxYieldIfNeeded() ;
(void)ShowModal();
}
else // auto hide
{
// reenable other windows before hiding this one because otherwise
// Windows wouldn't give the focus back to the window which had
// been previously focused because it would still be disabled
ReenableOtherWindows();
Hide();
}
}
else // not at maximum yet if ( value == m_maximum )
デストラクタとReenableOtherWindows
// ----------------------------------------------------------------------------
// destruction
// ----------------------------------------------------------------------------
wxProgressDialog::~wxProgressDialog()
{
// normally this should have been already done, but just in case
ReenableOtherWindows();
}
void wxProgressDialog::ReenableOtherWindows()
{
if ( GetWindowStyle() & wxPD_APP_MODAL )
{
delete m_winDisabler;
m_winDisabler = (wxWindowDisabler *)NULL;
}
else
{
if ( m_parentTop )
m_parentTop->Enable();
}
}
でいくつか気になるメンバ変数があるが、m_parentTopはコンストラクタの中で
m_parentTop = wxGetTopLevelParent(parent);
となっている。
wxGetTopLevelParentの実装は、src/common/wincmn.cpp
// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------
wxWindow* wxGetTopLevelParent(wxWindow *win)
{
while ( win && !win->IsTopLevel() )
win = win->GetParent();
return win;
}
関連は不明だがなにかあるのかもしれない。一応よんでみた。
要点:wxTopLevelWindowはDestroyの過程でwxWindowに成り下がった後、自分の子をDestroyし、最後になくなる。なので、Destroyされる子の側でよぶとNULL返すことになる
wxWindowDisablerも気になる。実装はsrc/common/utilscmn.cppにある。
概要としてはwxTopLevelWindows.GetFirstでTopWindowのリストにあるwindowにたいしてdisableを呼んでいる。
// ----------------------------------------------------------------------------
// wxSafeYield and supporting functions
// ----------------------------------------------------------------------------
void wxEnableTopLevelWindows(bool enable)
{
wxWindowList::compatibility_iterator node;
for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
node->GetData()->Enable(enable);
}
wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
{
// remember the top level windows which were already disabled, so that we
// don't reenable them later
m_winDisabled = NULL;
wxWindowList::compatibility_iterator node;
for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
{
wxWindow *winTop = node->GetData();
if ( winTop == winToSkip )
continue;
// we don't need to disable the hidden or already disabled windows
if ( winTop->IsEnabled() && winTop->IsShown() )
{
winTop->Disable();
}
else
{
if ( !m_winDisabled )
{
m_winDisabled = new wxWindowList;
}
m_winDisabled->Append(winTop);
}
}
}
wxWindowDisabler::~wxWindowDisabler()
{
wxWindowList::compatibility_iterator node;
for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
{
wxWindow *winTop = node->GetData();
if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
{
winTop->Enable();
}
//else: had been already disabled, don't reenable
}
delete m_winDisabled;
}
0 件のコメント:
コメントを投稿