Fix setting icon for wxProgressDialog (wxMSW)

Icon for wxProgressDialog cannot be changed directly because the dialog is created in another thread and may not yet exist when SetIcon() is called. We have to store new icon(s) in the data structure used to share data between the main thread and the task dialog runner and wait for a cyclic update.

Closes #17967.
This commit is contained in:
Artur Wieczorek
2017-10-04 16:06:33 +02:00
parent 718c916c93
commit bff8421ed7
2 changed files with 45 additions and 0 deletions

View File

@@ -41,6 +41,8 @@ public:
virtual void SetTitle(const wxString& title) wxOVERRIDE;
virtual wxString GetTitle() const wxOVERRIDE;
virtual void SetIcons(const wxIconBundle& icons) wxOVERRIDE;
virtual bool Show( bool show = true ) wxOVERRIDE;
// Must provide overload to avoid hiding it (and warnings about it)

View File

@@ -60,6 +60,7 @@ const int wxSPDD_DISABLE_SKIP = 0x0100;
const int wxSPDD_DISABLE_ABORT = 0x0200;
const int wxSPDD_FINISHED = 0x0400;
const int wxSPDD_DESTROYED = 0x0800;
const int wxSPDD_ICON_CHANGED = 0x1000;
const int Id_SkipBtn = wxID_HIGHEST + 1;
@@ -95,6 +96,8 @@ public:
wxString m_expandedInformation;
wxString m_labelCancel; // Privately used by callback.
unsigned long m_timeStop;
wxIcon m_iconSmall;
wxIcon m_iconBig;
wxProgressDialog::State m_state;
bool m_progressBarMarquee;
@@ -213,6 +216,12 @@ void PerformNotificationUpdates(HWND hwnd,
if ( sharedData->m_notifications & wxSPDD_TITLE_CHANGED )
::SetWindowText( hwnd, sharedData->m_title.t_str() );
if ( sharedData->m_notifications & wxSPDD_ICON_CHANGED )
{
::SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)GetHiconOf(sharedData->m_iconSmall));
::SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)GetHiconOf(sharedData->m_iconBig));
}
if ( sharedData->m_notifications & wxSPDD_MESSAGE_CHANGED )
{
// Split the message in the title string and the rest if it has
@@ -644,6 +653,40 @@ wxString wxProgressDialog::GetTitle() const
return wxGenericProgressDialog::GetTitle();
}
void wxProgressDialog::SetIcons(const wxIconBundle& icons)
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeTaskDialog() )
{
m_icons = icons; // We can't just call to parent's SetIcons()
// (wxGenericProgressDialog::SetIcons == wxTopLevelWindowMSW::SetIcons)
// because it does too many things.
wxIcon iconSmall;
wxIcon iconBig;
if (!icons.IsEmpty())
{
const wxSize sizeSmall(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
iconSmall = icons.GetIcon(sizeSmall, wxIconBundle::FALLBACK_NEAREST_LARGER);
const wxSize sizeBig(::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
iconBig = icons.GetIcon(sizeBig, wxIconBundle::FALLBACK_NEAREST_LARGER);
}
if (m_sharedData)
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
m_sharedData->m_iconSmall = iconSmall;
m_sharedData->m_iconBig = iconBig;
m_sharedData->m_notifications |= wxSPDD_ICON_CHANGED;
}
return;
}
#endif // wxHAS_MSW_TASKDIALOG
wxGenericProgressDialog::SetIcons(icons);
}
bool wxProgressDialog::Show(bool show)
{
#ifdef wxHAS_MSW_TASKDIALOG