Use task dialog for wxProgressDialog implementation in wxMSW.

If available, the task dialog is now used for the wxProgressDialog under
Windows. This provides a much more native looking dialog which doesn't look
out of place under modern Windows versions, unlike the generic implementation.

The internals of the code had to be significantly changed as the task dialog
can only be shown modally so, to emulate wxProgressDialog modeless nature, a
separate thread is used for the progress dialog management.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65352 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-08-18 22:49:02 +00:00
parent c0938d8506
commit c31d9c7f60
18 changed files with 1606 additions and 290 deletions

View File

@@ -2965,6 +2965,7 @@ COND_TOOLKIT_MSW_GUI_HDR = \
wx/msw/pen.h \
wx/msw/printdlg.h \
wx/msw/printwin.h \
wx/msw/progdlg.h \
wx/msw/radiobox.h \
wx/msw/radiobut.h \
wx/msw/region.h \
@@ -3488,6 +3489,7 @@ COND_TOOLKIT_WINCE_GUI_HDR = \
wx/msw/pen.h \
wx/msw/printdlg.h \
wx/msw/printwin.h \
wx/msw/progdlg.h \
wx/msw/radiobox.h \
wx/msw/radiobut.h \
wx/msw/region.h \
@@ -5377,6 +5379,7 @@ COND_TOOLKIT_MSW___GUI_SRC_OBJECTS = \
monodll_msw_notebook.o \
monodll_access.o \
monodll_msw_ownerdrw.o \
monodll_progdlg.o \
monodll_msw_radiobox.o \
monodll_msw_radiobut.o \
monodll_richmsgdlg.o \
@@ -5613,6 +5616,7 @@ COND_TOOLKIT_WINCE___GUI_SRC_OBJECTS = \
monodll_msw_notebook.o \
monodll_access.o \
monodll_msw_ownerdrw.o \
monodll_progdlg.o \
monodll_msw_radiobox.o \
monodll_msw_radiobut.o \
monodll_richmsgdlg.o \
@@ -7249,6 +7253,7 @@ COND_TOOLKIT_MSW___GUI_SRC_OBJECTS_1 = \
monolib_msw_notebook.o \
monolib_access.o \
monolib_msw_ownerdrw.o \
monolib_progdlg.o \
monolib_msw_radiobox.o \
monolib_msw_radiobut.o \
monolib_richmsgdlg.o \
@@ -7485,6 +7490,7 @@ COND_TOOLKIT_WINCE___GUI_SRC_OBJECTS_1 = \
monolib_msw_notebook.o \
monolib_access.o \
monolib_msw_ownerdrw.o \
monolib_progdlg.o \
monolib_msw_radiobox.o \
monolib_msw_radiobut.o \
monolib_richmsgdlg.o \
@@ -9308,6 +9314,7 @@ COND_TOOLKIT_MSW___GUI_SRC_OBJECTS_2 = \
coredll_msw_notebook.o \
coredll_access.o \
coredll_msw_ownerdrw.o \
coredll_progdlg.o \
coredll_msw_radiobox.o \
coredll_msw_radiobut.o \
coredll_richmsgdlg.o \
@@ -9544,6 +9551,7 @@ COND_TOOLKIT_WINCE___GUI_SRC_OBJECTS_2 = \
coredll_msw_notebook.o \
coredll_access.o \
coredll_msw_ownerdrw.o \
coredll_progdlg.o \
coredll_msw_radiobox.o \
coredll_msw_radiobut.o \
coredll_richmsgdlg.o \
@@ -10851,6 +10859,7 @@ COND_TOOLKIT_MSW___GUI_SRC_OBJECTS_3 = \
corelib_msw_notebook.o \
corelib_access.o \
corelib_msw_ownerdrw.o \
corelib_progdlg.o \
corelib_msw_radiobox.o \
corelib_msw_radiobut.o \
corelib_richmsgdlg.o \
@@ -11087,6 +11096,7 @@ COND_TOOLKIT_WINCE___GUI_SRC_OBJECTS_3 = \
corelib_msw_notebook.o \
corelib_access.o \
corelib_msw_ownerdrw.o \
corelib_progdlg.o \
corelib_msw_radiobox.o \
corelib_msw_radiobut.o \
corelib_richmsgdlg.o \
@@ -18888,6 +18898,12 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@monodll_msw_ownerdrw.o: $(srcdir)/src/msw/ownerdrw.cpp $(MONODLL_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/ownerdrw.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@monodll_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(MONODLL_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@monodll_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(MONODLL_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@monodll_msw_radiobox.o: $(srcdir)/src/msw/radiobox.cpp $(MONODLL_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/radiobox.cpp
@@ -24105,6 +24121,12 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@monolib_msw_ownerdrw.o: $(srcdir)/src/msw/ownerdrw.cpp $(MONOLIB_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/ownerdrw.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@monolib_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(MONOLIB_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@monolib_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(MONOLIB_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@monolib_msw_radiobox.o: $(srcdir)/src/msw/radiobox.cpp $(MONOLIB_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/radiobox.cpp
@@ -29508,6 +29530,12 @@ coredll_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(COREDLL_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@coredll_msw_ownerdrw.o: $(srcdir)/src/msw/ownerdrw.cpp $(COREDLL_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/msw/ownerdrw.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@coredll_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(COREDLL_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@coredll_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(COREDLL_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@coredll_msw_radiobox.o: $(srcdir)/src/msw/radiobox.cpp $(COREDLL_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/msw/radiobox.cpp
@@ -33426,6 +33454,12 @@ corelib_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(CORELIB_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@corelib_msw_ownerdrw.o: $(srcdir)/src/msw/ownerdrw.cpp $(CORELIB_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/msw/ownerdrw.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@corelib_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(CORELIB_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@corelib_progdlg.o: $(srcdir)/src/msw/progdlg.cpp $(CORELIB_ODEP)
@COND_TOOLKIT_WINCE_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/msw/progdlg.cpp
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@corelib_msw_radiobox.o: $(srcdir)/src/msw/radiobox.cpp $(CORELIB_ODEP)
@COND_TOOLKIT_MSW_USE_GUI_1_WXUNIV_0@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/msw/radiobox.cpp

View File

@@ -1718,6 +1718,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/msw/notebook.cpp
src/msw/ole/access.cpp
src/msw/ownerdrw.cpp
src/msw/progdlg.cpp
src/msw/radiobox.cpp
src/msw/radiobut.cpp
src/msw/richmsgdlg.cpp
@@ -1802,6 +1803,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/msw/pen.h
wx/msw/printdlg.h
wx/msw/printwin.h
wx/msw/progdlg.h
wx/msw/radiobox.h
wx/msw/radiobut.h
wx/msw/region.h

View File

@@ -1753,6 +1753,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \
$(OBJS)\monodll_msw_notebook.obj \
$(OBJS)\monodll_access.obj \
$(OBJS)\monodll_ownerdrw.obj \
$(OBJS)\monodll_progdlg.obj \
$(OBJS)\monodll_msw_radiobox.obj \
$(OBJS)\monodll_msw_radiobut.obj \
$(OBJS)\monodll_richmsgdlg.obj \
@@ -2472,6 +2473,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \
$(OBJS)\monolib_msw_notebook.obj \
$(OBJS)\monolib_access.obj \
$(OBJS)\monolib_ownerdrw.obj \
$(OBJS)\monolib_progdlg.obj \
$(OBJS)\monolib_msw_radiobox.obj \
$(OBJS)\monolib_msw_radiobut.obj \
$(OBJS)\monolib_richmsgdlg.obj \
@@ -3082,6 +3084,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \
$(OBJS)\coredll_msw_notebook.obj \
$(OBJS)\coredll_access.obj \
$(OBJS)\coredll_ownerdrw.obj \
$(OBJS)\coredll_progdlg.obj \
$(OBJS)\coredll_msw_radiobox.obj \
$(OBJS)\coredll_msw_radiobut.obj \
$(OBJS)\coredll_richmsgdlg.obj \
@@ -3584,6 +3587,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \
$(OBJS)\corelib_msw_notebook.obj \
$(OBJS)\corelib_access.obj \
$(OBJS)\corelib_ownerdrw.obj \
$(OBJS)\corelib_progdlg.obj \
$(OBJS)\corelib_msw_radiobox.obj \
$(OBJS)\corelib_msw_radiobut.obj \
$(OBJS)\corelib_richmsgdlg.obj \
@@ -6188,6 +6192,9 @@ $(OBJS)\monodll_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\monodll_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\monodll_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\monodll_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\radiobox.cpp
@@ -8420,6 +8427,9 @@ $(OBJS)\monolib_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\monolib_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\monolib_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\monolib_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\radiobox.cpp
@@ -11060,6 +11070,9 @@ $(OBJS)\coredll_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\coredll_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\coredll_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\coredll_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\radiobox.cpp
@@ -12367,6 +12380,9 @@ $(OBJS)\corelib_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\corelib_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\corelib_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\corelib_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\radiobox.cpp

View File

@@ -1764,6 +1764,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \
$(OBJS)\monodll_msw_notebook.o \
$(OBJS)\monodll_access.o \
$(OBJS)\monodll_ownerdrw.o \
$(OBJS)\monodll_progdlg.o \
$(OBJS)\monodll_msw_radiobox.o \
$(OBJS)\monodll_msw_radiobut.o \
$(OBJS)\monodll_richmsgdlg.o \
@@ -2489,6 +2490,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \
$(OBJS)\monolib_msw_notebook.o \
$(OBJS)\monolib_access.o \
$(OBJS)\monolib_ownerdrw.o \
$(OBJS)\monolib_progdlg.o \
$(OBJS)\monolib_msw_radiobox.o \
$(OBJS)\monolib_msw_radiobut.o \
$(OBJS)\monolib_richmsgdlg.o \
@@ -3115,6 +3117,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \
$(OBJS)\coredll_msw_notebook.o \
$(OBJS)\coredll_access.o \
$(OBJS)\coredll_ownerdrw.o \
$(OBJS)\coredll_progdlg.o \
$(OBJS)\coredll_msw_radiobox.o \
$(OBJS)\coredll_msw_radiobut.o \
$(OBJS)\coredll_richmsgdlg.o \
@@ -3625,6 +3628,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \
$(OBJS)\corelib_msw_notebook.o \
$(OBJS)\corelib_access.o \
$(OBJS)\corelib_ownerdrw.o \
$(OBJS)\corelib_progdlg.o \
$(OBJS)\corelib_msw_radiobox.o \
$(OBJS)\corelib_msw_radiobut.o \
$(OBJS)\corelib_richmsgdlg.o \
@@ -6338,6 +6342,9 @@ $(OBJS)\monodll_access.o: ../../src/msw/ole/access.cpp
$(OBJS)\monodll_ownerdrw.o: ../../src/msw/ownerdrw.cpp
$(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\monodll_progdlg.o: ../../src/msw/progdlg.cpp
$(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\monodll_msw_radiobox.o: ../../src/msw/radiobox.cpp
$(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
@@ -8570,6 +8577,9 @@ $(OBJS)\monolib_access.o: ../../src/msw/ole/access.cpp
$(OBJS)\monolib_ownerdrw.o: ../../src/msw/ownerdrw.cpp
$(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\monolib_progdlg.o: ../../src/msw/progdlg.cpp
$(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\monolib_msw_radiobox.o: ../../src/msw/radiobox.cpp
$(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
@@ -11210,6 +11220,9 @@ $(OBJS)\coredll_access.o: ../../src/msw/ole/access.cpp
$(OBJS)\coredll_ownerdrw.o: ../../src/msw/ownerdrw.cpp
$(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\coredll_progdlg.o: ../../src/msw/progdlg.cpp
$(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\coredll_msw_radiobox.o: ../../src/msw/radiobox.cpp
$(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $<
@@ -12517,6 +12530,9 @@ $(OBJS)\corelib_access.o: ../../src/msw/ole/access.cpp
$(OBJS)\corelib_ownerdrw.o: ../../src/msw/ownerdrw.cpp
$(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\corelib_progdlg.o: ../../src/msw/progdlg.cpp
$(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\corelib_msw_radiobox.o: ../../src/msw/radiobox.cpp
$(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $<

View File

@@ -1961,6 +1961,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \
$(OBJS)\monodll_msw_notebook.obj \
$(OBJS)\monodll_access.obj \
$(OBJS)\monodll_ownerdrw.obj \
$(OBJS)\monodll_progdlg.obj \
$(OBJS)\monodll_msw_radiobox.obj \
$(OBJS)\monodll_msw_radiobut.obj \
$(OBJS)\monodll_richmsgdlg.obj \
@@ -2686,6 +2687,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \
$(OBJS)\monolib_msw_notebook.obj \
$(OBJS)\monolib_access.obj \
$(OBJS)\monolib_ownerdrw.obj \
$(OBJS)\monolib_progdlg.obj \
$(OBJS)\monolib_msw_radiobox.obj \
$(OBJS)\monolib_msw_radiobut.obj \
$(OBJS)\monolib_richmsgdlg.obj \
@@ -3362,6 +3364,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \
$(OBJS)\coredll_msw_notebook.obj \
$(OBJS)\coredll_access.obj \
$(OBJS)\coredll_ownerdrw.obj \
$(OBJS)\coredll_progdlg.obj \
$(OBJS)\coredll_msw_radiobox.obj \
$(OBJS)\coredll_msw_radiobut.obj \
$(OBJS)\coredll_richmsgdlg.obj \
@@ -3870,6 +3873,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \
$(OBJS)\corelib_msw_notebook.obj \
$(OBJS)\corelib_access.obj \
$(OBJS)\corelib_ownerdrw.obj \
$(OBJS)\corelib_progdlg.obj \
$(OBJS)\corelib_msw_radiobox.obj \
$(OBJS)\corelib_msw_radiobut.obj \
$(OBJS)\corelib_richmsgdlg.obj \
@@ -6768,6 +6772,9 @@ $(OBJS)\monodll_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\monodll_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\monodll_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\monodll_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\radiobox.cpp
@@ -9000,6 +9007,9 @@ $(OBJS)\monolib_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\monolib_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\monolib_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\monolib_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\radiobox.cpp
@@ -11640,6 +11650,9 @@ $(OBJS)\coredll_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\coredll_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\coredll_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\coredll_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\radiobox.cpp
@@ -12947,6 +12960,9 @@ $(OBJS)\corelib_access.obj: ..\..\src\msw\ole\access.cpp
$(OBJS)\corelib_ownerdrw.obj: ..\..\src\msw\ownerdrw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\ownerdrw.cpp
$(OBJS)\corelib_progdlg.obj: ..\..\src\msw\progdlg.cpp
$(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\progdlg.cpp
$(OBJS)\corelib_msw_radiobox.obj: ..\..\src\msw\radiobox.cpp
$(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\radiobox.cpp

View File

@@ -324,6 +324,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = &
$(OBJS)\monodll_msw_notebook.obj &
$(OBJS)\monodll_access.obj &
$(OBJS)\monodll_ownerdrw.obj &
$(OBJS)\monodll_progdlg.obj &
$(OBJS)\monodll_msw_radiobox.obj &
$(OBJS)\monodll_msw_radiobut.obj &
$(OBJS)\monodll_richmsgdlg.obj &
@@ -1054,6 +1055,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = &
$(OBJS)\monolib_msw_notebook.obj &
$(OBJS)\monolib_access.obj &
$(OBJS)\monolib_ownerdrw.obj &
$(OBJS)\monolib_progdlg.obj &
$(OBJS)\monolib_msw_radiobox.obj &
$(OBJS)\monolib_msw_radiobut.obj &
$(OBJS)\monolib_richmsgdlg.obj &
@@ -1691,6 +1693,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = &
$(OBJS)\coredll_msw_notebook.obj &
$(OBJS)\coredll_access.obj &
$(OBJS)\coredll_ownerdrw.obj &
$(OBJS)\coredll_progdlg.obj &
$(OBJS)\coredll_msw_radiobox.obj &
$(OBJS)\coredll_msw_radiobut.obj &
$(OBJS)\coredll_richmsgdlg.obj &
@@ -2203,6 +2206,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = &
$(OBJS)\corelib_msw_notebook.obj &
$(OBJS)\corelib_access.obj &
$(OBJS)\corelib_ownerdrw.obj &
$(OBJS)\corelib_progdlg.obj &
$(OBJS)\corelib_msw_radiobox.obj &
$(OBJS)\corelib_msw_radiobut.obj &
$(OBJS)\corelib_richmsgdlg.obj &
@@ -6597,6 +6601,9 @@ $(OBJS)\monodll_access.obj : .AUTODEPEND ..\..\src\msw\ole\access.cpp
$(OBJS)\monodll_ownerdrw.obj : .AUTODEPEND ..\..\src\msw\ownerdrw.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $<
$(OBJS)\monodll_progdlg.obj : .AUTODEPEND ..\..\src\msw\progdlg.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $<
$(OBJS)\monodll_msw_radiobox.obj : .AUTODEPEND ..\..\src\msw\radiobox.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $<
@@ -8829,6 +8836,9 @@ $(OBJS)\monolib_access.obj : .AUTODEPEND ..\..\src\msw\ole\access.cpp
$(OBJS)\monolib_ownerdrw.obj : .AUTODEPEND ..\..\src\msw\ownerdrw.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $<
$(OBJS)\monolib_progdlg.obj : .AUTODEPEND ..\..\src\msw\progdlg.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $<
$(OBJS)\monolib_msw_radiobox.obj : .AUTODEPEND ..\..\src\msw\radiobox.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $<
@@ -11469,6 +11479,9 @@ $(OBJS)\coredll_access.obj : .AUTODEPEND ..\..\src\msw\ole\access.cpp
$(OBJS)\coredll_ownerdrw.obj : .AUTODEPEND ..\..\src\msw\ownerdrw.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $<
$(OBJS)\coredll_progdlg.obj : .AUTODEPEND ..\..\src\msw\progdlg.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $<
$(OBJS)\coredll_msw_radiobox.obj : .AUTODEPEND ..\..\src\msw\radiobox.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $<
@@ -12776,6 +12789,9 @@ $(OBJS)\corelib_access.obj : .AUTODEPEND ..\..\src\msw\ole\access.cpp
$(OBJS)\corelib_ownerdrw.obj : .AUTODEPEND ..\..\src\msw\ownerdrw.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $<
$(OBJS)\corelib_progdlg.obj : .AUTODEPEND ..\..\src\msw\progdlg.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $<
$(OBJS)\corelib_msw_radiobox.obj : .AUTODEPEND ..\..\src\msw\radiobox.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $<

View File

@@ -2025,6 +2025,41 @@ SOURCE=..\..\src\msw\printwin.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\msw\progdlg.cpp
!IF "$(CFG)" == "core - Win32 DLL Universal Release"
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "core - Win32 DLL Universal Debug"
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "core - Win32 DLL Release"
!ELSEIF "$(CFG)" == "core - Win32 DLL Debug"
!ELSEIF "$(CFG)" == "core - Win32 Universal Release"
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "core - Win32 Universal Debug"
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "core - Win32 Release"
!ELSEIF "$(CFG)" == "core - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\src\msw\radiobox.cpp
!IF "$(CFG)" == "core - Win32 DLL Universal Release"
@@ -5162,6 +5197,10 @@ SOURCE=..\..\include\wx\msw\printwin.h
# End Source File
# Begin Source File
SOURCE=..\..\include\wx\msw\progdlg.h
# End Source File
# Begin Source File
SOURCE=..\..\include\wx\msw\radiobox.h
# End Source File
# Begin Source File

View File

@@ -1900,6 +1900,21 @@
<File
RelativePath="..\..\src\msw\printwin.cpp">
</File>
<File
RelativePath="..\..\src\msw\progdlg.cpp">
<FileConfiguration
Name="Universal Debug|Win32"
ExcludedFromBuild="TRUE"/>
<FileConfiguration
Name="Universal Release|Win32"
ExcludedFromBuild="TRUE"/>
<FileConfiguration
Name="DLL Universal Debug|Win32"
ExcludedFromBuild="TRUE"/>
<FileConfiguration
Name="DLL Universal Release|Win32"
ExcludedFromBuild="TRUE"/>
</File>
<File
RelativePath="..\..\src\msw\radiobox.cpp">
<FileConfiguration
@@ -4473,6 +4488,9 @@
<File
RelativePath="..\..\include\wx\msw\printwin.h">
</File>
<File
RelativePath="..\..\include\wx\msw\progdlg.h">
</File>
<File
RelativePath="..\..\include\wx\msw\radiobox.h">
</File>

View File

@@ -2567,6 +2567,26 @@
RelativePath="..\..\src\msw\printwin.cpp"
>
</File>
<File
RelativePath="..\..\src\msw\progdlg.cpp"
>
<FileConfiguration
Name="Universal Debug|Win32"
ExcludedFromBuild="true"
/>
<FileConfiguration
Name="Universal Release|Win32"
ExcludedFromBuild="true"
/>
<FileConfiguration
Name="DLL Universal Debug|Win32"
ExcludedFromBuild="true"
/>
<FileConfiguration
Name="DLL Universal Release|Win32"
ExcludedFromBuild="true"
/>
</File>
<File
RelativePath="..\..\src\msw\radiobox.cpp"
>
@@ -5983,6 +6003,10 @@
RelativePath="..\..\include\wx\msw\printwin.h"
>
</File>
<File
RelativePath="..\..\include\wx\msw\progdlg.h"
>
</File>
<File
RelativePath="..\..\include\wx\msw\radiobox.h"
>

View File

@@ -2563,6 +2563,26 @@
RelativePath="..\..\src\msw\printwin.cpp"
>
</File>
<File
RelativePath="..\..\src\msw\progdlg.cpp"
>
<FileConfiguration
Name="Universal Debug|Win32"
ExcludedFromBuild="true"
/>
<FileConfiguration
Name="Universal Release|Win32"
ExcludedFromBuild="true"
/>
<FileConfiguration
Name="DLL Universal Debug|Win32"
ExcludedFromBuild="true"
/>
<FileConfiguration
Name="DLL Universal Release|Win32"
ExcludedFromBuild="true"
/>
</File>
<File
RelativePath="..\..\src\msw\radiobox.cpp"
>
@@ -5979,6 +5999,10 @@
RelativePath="..\..\include\wx\msw\printwin.h"
>
</File>
<File
RelativePath="..\..\include\wx\msw\progdlg.h"
>
</File>
<File
RelativePath="..\..\include\wx\msw\radiobox.h"
>

View File

@@ -403,13 +403,6 @@ Major new features in this release
2.9.2:
------
MSW:
- Fix Cygwin 1.7 build (David Gangola).
- Native wxHyperlinkCtrl implementation (Rickard Westerlund, GSoC 2010 project).
- Allow using wxDC::DrawText() with multiline texts.
- Fix wxBitmapButton best size determination broken in 2.9.1.
All (GUI):
- Added wxRichMessageDialog (Rickard Westerlund, GSoC 2010 project).
@@ -420,6 +413,15 @@ All (GUI):
- wxRibbon: added EVT_RIBBONGALLERY_CLICKED event (John Roberts).
- Add support for CP-866 encoding to wxEncodingConverter (madnut).
MSW:
- Native implementation of wxHyperlinkCtrl and wxProgressDialog under modern
Windows versions (Rickard Westerlund, GSoC 2010 project).
- Fix Cygwin 1.7 build (David Gangola).
- Allow using wxDC::DrawText() with multiline texts.
- Fix wxBitmapButton best size determination broken in 2.9.1.
2.9.1:
------

View File

@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
// Name: progdlgg.h
// Purpose: wxProgressDialog class
// Purpose: wxGenericProgressDialog class
// Author: Karsten Ballueder
// Modified by: Francesco Montorsi
// Created: 09.05.1999
@@ -12,11 +12,6 @@
#ifndef __PROGDLGH_G__
#define __PROGDLGH_G__
#include "wx/defs.h"
#include "wx/progdlg.h"
#if wxUSE_PROGRESSDLG
#include "wx/dialog.h"
class WXDLLIMPEXP_FWD_CORE wxButton;
@@ -27,15 +22,15 @@ class WXDLLIMPEXP_FWD_CORE wxStaticText;
Progress dialog which shows a moving progress bar.
Taken from the Mahogany project.
*/
class WXDLLIMPEXP_CORE wxProgressDialog : public wxDialog
class WXDLLIMPEXP_CORE wxGenericProgressDialog : public wxDialog
{
public:
wxProgressDialog(const wxString& title, const wxString& message,
wxGenericProgressDialog(const wxString& title, const wxString& message,
int maximum = 100,
wxWindow *parent = NULL,
int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE);
virtual ~wxProgressDialog();
virtual ~wxGenericProgressDialog();
virtual bool Update(int value, const wxString& newmsg = wxEmptyString, bool *skip = NULL);
virtual bool Pulse(const wxString& newmsg = wxEmptyString, bool *skip = NULL);
@@ -58,7 +53,43 @@ public:
virtual bool Show( bool show = true );
// This enum is an implementation detail and should not be used
// by user code.
enum ProgressDialogState
{
Uncancelable = -1, // dialog can't be canceled
Canceled, // can be cancelled and, in fact, was
Continue, // can be cancelled but wasn't
Finished // finished, waiting to be removed from screen
};
protected:
// This ctor is used by the native MSW implementation only.
wxGenericProgressDialog(wxWindow *parent, int maximum, int style);
void Create(const wxString& title,
const wxString& message,
int maximum,
wxWindow *parent,
int style);
// Return the labels to use for showing the elapsed/estimated/remaining
// times respectively.
static wxString GetElapsedLabel() { return _("Elapsed time:"); }
static wxString GetEstimatedLabel() { return _("Estimated time:"); }
static wxString GetRemainingLabel() { return _("Remaining time:"); }
// Updates estimated times from a given progress bar value and stores the
// results in provided arguments.
void UpdateTimeEstimates(int value,
unsigned long &elapsedTime,
unsigned long &estimatedTime,
unsigned long &remainingTime);
// Converts seconds to HH:mm:ss format.
static wxString GetFormattedTime(unsigned long timeInSec);
// callback for optional abort button
void OnCancel(wxCommandEvent&);
@@ -68,11 +99,43 @@ protected:
// callback to disable "hard" window closing
void OnClose(wxCloseEvent&);
// called to disable the other windows while this dialog is shown
void DisableOtherWindows();
// must be called to reenable the other windows temporarily disabled while
// the dialog was shown
void ReenableOtherWindows();
// return the top level parent window of this dialog (may be NULL)
wxWindow *GetTopParent() const { return m_parentTop; }
// continue processing or not (return value for Update())
ProgressDialogState m_state;
// the maximum value
int m_maximum;
#if defined(__WXMSW__ ) || defined(__WXPM__)
// the factor we use to always keep the value in 16 bit range as the native
// control only supports ranges from 0 to 65,535
size_t m_factor;
#endif // __WXMSW__
// time when the dialog was created
unsigned long m_timeStart;
// time when the dialog was closed or cancelled
unsigned long m_timeStop;
// time between the moment the dialog was closed/cancelled and resume
unsigned long m_break;
private:
// update the label to show the given time (in seconds)
static void SetTimeLabel(unsigned long val, wxStaticText *label);
// common part of all ctors
void Init(wxWindow *parent, int maximum, int style);
// create the label with given text and another one to show the time nearby
// as the next windows in the sizer, returns the created control
wxStaticText *CreateLabel(const wxString& text, wxSizer *sizer);
@@ -101,25 +164,10 @@ private:
wxStaticText *m_elapsed,
*m_estimated,
*m_remaining;
// time when the dialog was created
unsigned long m_timeStart;
// time when the dialog was closed or cancelled
unsigned long m_timeStop;
// time between the moment the dialog was closed/cancelled and resume
unsigned long m_break;
// parent top level window (may be NULL)
wxWindow *m_parentTop;
// continue processing or not (return value for Update())
enum
{
Uncancelable = -1, // dialog can't be canceled
Canceled, // can be cancelled and, in fact, was
Continue, // can be cancelled but wasn't
Finished // finished, waiting to be removed from screen
} m_state;
// skip some portion
bool m_skip;
@@ -129,16 +177,15 @@ private:
wxButton *m_btnSkip;
#endif
// the maximum value
int m_maximum;
// saves the time when elapsed time was updated so there is only one
// update per second
unsigned long m_last_timeupdate;
// tells how often a change of the estimated time has to be confirmed
// before it is actually displayed - this reduces the frequence of updates
// before it is actually displayed - this reduces the frequency of updates
// of estimated and remaining time
const int m_delay;
int m_delay;
// counts the confirmations
int m_ctdelay;
unsigned long m_display_estimated;
@@ -146,20 +193,11 @@ private:
bool m_hasAbortButton,
m_hasSkipButton;
#if defined(__WXMSW__ ) || defined(__WXPM__)
// the factor we use to always keep the value in 16 bit range as the native
// control only supports ranges from 0 to 65,535
size_t m_factor;
#endif // __WXMSW__
// for wxPD_APP_MODAL case
class WXDLLIMPEXP_FWD_CORE wxWindowDisabler *m_winDisabler;
DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS(wxProgressDialog)
wxDECLARE_NO_COPY_CLASS(wxProgressDialog);
wxDECLARE_NO_COPY_CLASS(wxGenericProgressDialog);
};
#endif // wxUSE_PROGRESSDLG
#endif // __PROGDLGH_G__

76
include/wx/msw/progdlg.h Normal file
View File

@@ -0,0 +1,76 @@
/////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/progdlg.h
// Purpose: wxProgressDialog
// Author: Rickard Westerlund
// Created: 2010-07-22
// RCS-ID: $Id$
// Copyright: (c) 2010 wxWidgets team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_PROGDLG_H_
#define _WX_PROGDLG_H_
class wxProgressDialogTaskRunner;
class wxProgressDialogSharedData;
class WXDLLIMPEXP_CORE wxProgressDialog : public wxGenericProgressDialog
{
public:
wxProgressDialog(const wxString& title, const wxString& message,
int maximum = 100,
wxWindow *parent = NULL,
int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE);
virtual ~wxProgressDialog();
virtual bool Update(int value, const wxString& newmsg = wxEmptyString, bool *skip = NULL);
virtual bool Pulse(const wxString& newmsg = wxEmptyString, bool *skip = NULL);
void Resume();
int GetValue() const;
wxString GetMessage() const;
void SetRange(int maximum);
// Return whether "Cancel" or "Skip" button was pressed, always return
// false if the corresponding button is not shown.
bool WasSkipped() const;
bool WasCancelled() const;
virtual void SetTitle(const wxString& title);
virtual wxString GetTitle() const;
virtual bool Show( bool show = true );
// Must provide overload to avoid hiding it (and warnings about it)
virtual void Update() { wxGenericProgressDialog::Update(); }
private:
// Returns true if the task dialog is available. If not, all the methods of
// this class simply fall back to wxGenericProgressDialog versions.
bool HasNativeProgressDialog() const;
// Performs common routines to Update() and Pulse(). Requires the
// shared object to have been entered.
bool DoNativeBeforeUpdate(bool *skip);
// Updates the various timing informations for both determinate
// and indeterminate modes. Requires the shared object to have
// been entered.
void UpdateExpandedInformation(int value);
wxProgressDialogTaskRunner *m_taskDialogRunner;
wxProgressDialogSharedData *m_sharedData;
// Store the message and title we currently use to be able to return it
// from Get{Message,Title}()
wxString m_message,
m_title;
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxProgressDialog);
};
#endif // _WX_PROGDLG_H_

View File

@@ -14,6 +14,8 @@
#include "wx/defs.h"
#if wxUSE_PROGRESSDLG
/*
* wxProgressDialog flags
*/
@@ -31,6 +33,28 @@
#include "wx/palmos/progdlg.h"
#else
#include "wx/generic/progdlgg.h"
#endif
#if defined(__WXMSW__) && wxUSE_THREADS
#include "wx/msw/progdlg.h"
#else
class WXDLLIMPEXP_CORE wxProgressDialog
: public wxGenericProgressDialog
{
public:
wxProgressDialog( const wxString& title, const wxString& message,
int maximum = 100,
wxWindow *parent = NULL,
int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE )
: wxGenericProgressDialog( title, message, maximum,
parent, style )
{ }
private:
wxDECLARE_DYNAMIC_CLASS_NO_COPY( wxProgressDialog );
};
#endif // defined(__WXMSW__) && wxUSE_THREADS
#endif // __WXPALMOS__
#endif // wxUSE_PROGRESSDLG
#endif // _WX_PROGDLG_H_BASE_

View File

@@ -1756,25 +1756,26 @@ void MyFrame::ShowProgress( wxCommandEvent& WXUNUSED(event) )
{
static const int max = 100;
wxProgressDialog dialog(wxT("Progress dialog example"),
wxT("An informative message"),
wxProgressDialog dialog("Progress dialog example",
// "Reserve" enough space for the multiline
// messages below, we'll change it anyhow
// immediately in the loop below
wxString(' ', 100) + "\n\n\n\n",
max, // range
this, // parent
wxPD_CAN_ABORT |
wxPD_CAN_SKIP |
wxPD_APP_MODAL |
// wxPD_AUTO_HIDE | -- try this as well
//wxPD_AUTO_HIDE | // -- try this as well
wxPD_ELAPSED_TIME |
wxPD_ESTIMATED_TIME |
wxPD_REMAINING_TIME
| wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
wxPD_REMAINING_TIME |
wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
);
bool cont = true;
for ( int i = 0; i <= max; i++ )
{
wxMilliSleep(200);
wxString msg;
// test both modes of wxProgressDialog behaviour: start in
@@ -1783,15 +1784,25 @@ void MyFrame::ShowProgress( wxCommandEvent& WXUNUSED(event) )
if ( i == max )
{
msg = wxT("That's all, folks!");
msg = "That's all, folks!\n"
"\n"
"Nothing to see here any more.";
}
else if ( !determinate )
{
msg = wxT("Testing indeterminate mode");
msg = "Testing indeterminate mode\n"
"\n"
"This mode allows you to show to the user\n"
"that something is going on even if you don't know\n"
"when exactly will you finish.";
}
else if ( determinate )
{
msg = wxT("Now in standard determinate mode");
msg = "Now in standard determinate mode\n"
"\n"
"This is the standard usage mode in which you\n"
"update the dialog after performing each new step of work.\n"
"It requires knowing the total number of steps in advance.";
}
// will be set to true if "Skip" button was pressed
@@ -1807,8 +1818,13 @@ void MyFrame::ShowProgress( wxCommandEvent& WXUNUSED(event) )
// each skip will move progress about quarter forward
if ( skip )
{
i += max/4;
if ( i >= 100 )
i = 99;
}
if ( !cont )
{
if ( wxMessageBox(wxT("Do you really want to cancel?"),
@@ -1819,6 +1835,8 @@ void MyFrame::ShowProgress( wxCommandEvent& WXUNUSED(event) )
cont = true;
dialog.Resume();
}
wxMilliSleep(200);
}
if ( !cont )

View File

@@ -40,7 +40,7 @@
#include "wx/generic/printps.h"
#include "wx/printdlg.h"
#include "wx/generic/prntdlgg.h"
#include "wx/generic/progdlgg.h"
#include "wx/progdlg.h"
#include "wx/paper.h"
#include <stdlib.h>

View File

@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/generic/progdlgg.cpp
// Purpose: wxProgressDialog class
// Purpose: wxGenericProgressDialog class
// Author: Karsten Ballueder
// Modified by:
// Created: 09.05.1999
@@ -66,48 +66,97 @@
static const int wxID_SKIP = 32000; // whatever
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
// update the label to show the given time (in seconds)
static void SetTimeLabel(unsigned long val, wxStaticText *label);
// ----------------------------------------------------------------------------
// event tables
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxProgressDialog, wxDialog)
EVT_BUTTON(wxID_CANCEL, wxProgressDialog::OnCancel)
EVT_BUTTON(wxID_SKIP, wxProgressDialog::OnSkip)
BEGIN_EVENT_TABLE(wxGenericProgressDialog, wxDialog)
EVT_BUTTON(wxID_CANCEL, wxGenericProgressDialog::OnCancel)
EVT_BUTTON(wxID_SKIP, wxGenericProgressDialog::OnSkip)
EVT_CLOSE(wxProgressDialog::OnClose)
EVT_CLOSE(wxGenericProgressDialog::OnClose)
END_EVENT_TABLE()
IMPLEMENT_CLASS(wxProgressDialog, wxDialog)
// ============================================================================
// wxProgressDialog implementation
// wxGenericProgressDialog implementation
// ============================================================================
wxIMPLEMENT_CLASS(wxProgressDialog, wxDialog)
// ----------------------------------------------------------------------------
// wxProgressDialog creation
// wxGenericProgressDialog creation
// ----------------------------------------------------------------------------
wxProgressDialog::wxProgressDialog(const wxString& title,
void wxGenericProgressDialog::Init(wxWindow *parent, int maximum, int style)
{
// Initialize the inherited members that we always use (even when we don't
// create a valid window here).
// we may disappear at any moment, let the others know about it
SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT);
m_windowStyle |= style;
m_parentTop = wxGetTopLevelParent(parent);
// Initialize our own members.
m_state = Uncancelable;
m_maximum = maximum;
#if defined(__WXMSW__) || defined(__WXPM__)
// we can't have values > 65,536 in the progress control under Windows, so
// scale everything down
m_factor = m_maximum / 65536 + 1;
m_maximum /= m_factor;
#endif // __WXMSW__
m_timeStart = wxGetCurrentTime();
m_timeStop = (unsigned long)-1;
m_break = 0;
m_skip = false;
m_display_estimated =
m_last_timeupdate =
m_ctdelay = 0;
m_delay = 3;
m_hasAbortButton =
m_hasSkipButton = false;
}
wxGenericProgressDialog::wxGenericProgressDialog(wxWindow *parent,
int maximum,
int style)
: wxDialog()
{
Init(parent, maximum, style);
}
wxGenericProgressDialog::wxGenericProgressDialog(const wxString& title,
const wxString& message,
int maximum,
wxWindow *parent,
int style)
: wxDialog(GetParentForModalDialog(parent, style), wxID_ANY, title),
m_skip(false),
m_delay(3),
m_hasAbortButton(false),
m_hasSkipButton(false)
: wxDialog()
{
// we may disappear at any moment, let the others know about it
SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT);
m_windowStyle |= style;
Init(parent, maximum, style);
Create( title, message, maximum, parent, style );
}
void wxGenericProgressDialog::Create( const wxString& title,
const wxString& message,
int maximum,
wxWindow *parent,
int style )
{
wxDialog::Create(GetParentForModalDialog(parent, style), wxID_ANY, title);
SetParent( GetParentForModalDialog(parent, style) );
SetTitle( title );
m_hasAbortButton = (style & wxPD_CAN_ABORT) != 0;
m_hasSkipButton = (style & wxPD_CAN_SKIP) != 0;
@@ -128,16 +177,6 @@ wxProgressDialog::wxProgressDialog(const wxString& title,
#endif
m_state = m_hasAbortButton ? Continue : Uncancelable;
m_maximum = maximum;
#if defined(__WXMSW__) || defined(__WXPM__)
// we can't have values > 65,536 in the progress control under Windows, so
// scale everything down
m_factor = m_maximum / 65536 + 1;
m_maximum /= m_factor;
#endif // __WXMSW__
m_parentTop = wxGetTopLevelParent(parent);
// top-level sizerTop
wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
@@ -173,10 +212,6 @@ wxProgressDialog::wxProgressDialog(const wxString& title,
m_elapsed =
m_estimated =
m_remaining = NULL;
m_display_estimated =
m_last_timeupdate =
m_break = 0;
m_ctdelay = 0;
// also count how many labels we really have
size_t nTimeLabels = 0;
@@ -187,30 +222,24 @@ wxProgressDialog::wxProgressDialog(const wxString& title,
{
nTimeLabels++;
m_elapsed = CreateLabel(_("Elapsed time:"), sizerLabels);
m_elapsed = CreateLabel(GetElapsedLabel(), sizerLabels);
}
if ( style & wxPD_ESTIMATED_TIME )
{
nTimeLabels++;
m_estimated = CreateLabel(_("Estimated time:"), sizerLabels);
m_estimated = CreateLabel(GetEstimatedLabel(), sizerLabels);
}
if ( style & wxPD_REMAINING_TIME )
{
nTimeLabels++;
m_remaining = CreateLabel(_("Remaining time:"), sizerLabels);
m_remaining = CreateLabel(GetRemainingLabel(), sizerLabels);
}
sizerTop->Add(sizerLabels, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, LAYOUT_MARGIN);
if ( nTimeLabels > 0 )
{
// set it to the current time
m_timeStart = wxGetCurrentTime();
}
#if defined(__SMARTPHONE__)
if ( m_hasSkipButton )
SetRightMenu(wxID_SKIP, _("Skip"));
@@ -255,16 +284,7 @@ wxProgressDialog::wxProgressDialog(const wxString& title,
Centre(wxCENTER_FRAME | wxBOTH);
if ( style & wxPD_APP_MODAL )
{
m_winDisabler = new wxWindowDisabler(this);
}
else
{
if ( m_parentTop )
m_parentTop->Disable();
m_winDisabler = NULL;
}
DisableOtherWindows();
Show();
Enable();
@@ -280,59 +300,13 @@ wxProgressDialog::wxProgressDialog(const wxString& title,
Update();
}
wxStaticText *
wxProgressDialog::CreateLabel(const wxString& text, wxSizer *sizer)
{
wxStaticText *label = new wxStaticText(this, wxID_ANY, text);
wxStaticText *value = new wxStaticText(this, wxID_ANY, _("unknown"));
// select placement most native or nice on target GUI
#if defined(__SMARTPHONE__)
// value and time to the left in two rows
sizer->Add(label, 1, wxALIGN_LEFT);
sizer->Add(value, 1, wxALIGN_LEFT);
#elif defined(__WXMSW__) || defined(__WXPM__) || defined(__WXMAC__) || defined(__WXGTK20__)
// value and time centered in one row
sizer->Add(label, 1, wxLARGESMALL(wxALIGN_RIGHT,wxALIGN_LEFT) | wxTOP | wxRIGHT, LAYOUT_MARGIN);
sizer->Add(value, 1, wxALIGN_LEFT | wxTOP, LAYOUT_MARGIN);
#else
// value and time to the right in one row
sizer->Add(label);
sizer->Add(value, 0, wxLEFT, LAYOUT_MARGIN);
#endif
return value;
}
// ----------------------------------------------------------------------------
// wxProgressDialog operations
// ----------------------------------------------------------------------------
bool
wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
{
if ( !DoBeforeUpdate(skip) )
return false;
wxASSERT_MSG( value == -1 || m_gauge, wxT("cannot update non existent dialog") );
#ifdef __WXMSW__
value /= m_factor;
#endif // __WXMSW__
wxASSERT_MSG( value <= m_maximum, wxT("invalid progress value") );
if ( m_gauge )
m_gauge->SetValue(value);
UpdateMessage(newmsg);
if ( (m_elapsed || m_remaining || m_estimated) && (value != 0) )
void wxGenericProgressDialog::UpdateTimeEstimates(int value,
unsigned long &elapsedTime,
unsigned long &estimatedTime,
unsigned long &remainingTime)
{
unsigned long elapsed = wxGetCurrentTime() - m_timeStart;
if ( m_last_timeupdate < elapsed
|| value == m_maximum
)
if ( value != 0 && (m_last_timeupdate < elapsed || value == m_maximum) )
{
m_last_timeupdate = elapsed;
unsigned long estimated = m_break +
@@ -365,12 +339,98 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
}
}
if ( value != 0 )
{
long display_remaining = m_display_estimated - elapsed;
if ( display_remaining < 0 )
{
display_remaining = 0;
}
estimatedTime = m_display_estimated;
remainingTime = display_remaining;
}
elapsedTime = elapsed;
}
// static
wxString wxGenericProgressDialog::GetFormattedTime(unsigned long timeInSec)
{
wxString timeAsHMS;
if ( timeInSec == (unsigned long)-1 )
{
timeAsHMS = _("Unknown");
}
else
{
unsigned hours = timeInSec / 3600;
unsigned minutes = (timeInSec % 3600) / 60;
unsigned seconds = timeInSec % 60;
timeAsHMS.Printf("%u:%02u:%02u", hours, minutes, seconds);
}
return timeAsHMS;
}
wxStaticText *
wxGenericProgressDialog::CreateLabel(const wxString& text, wxSizer *sizer)
{
wxStaticText *label = new wxStaticText(this, wxID_ANY, text);
wxStaticText *value = new wxStaticText(this, wxID_ANY, _("unknown"));
// select placement most native or nice on target GUI
#if defined(__SMARTPHONE__)
// value and time to the left in two rows
sizer->Add(label, 1, wxALIGN_LEFT);
sizer->Add(value, 1, wxALIGN_LEFT);
#elif defined(__WXMSW__) || defined(__WXPM__) || defined(__WXMAC__) || defined(__WXGTK20__)
// value and time centered in one row
sizer->Add(label, 1, wxLARGESMALL(wxALIGN_RIGHT,wxALIGN_LEFT) | wxTOP | wxRIGHT, LAYOUT_MARGIN);
sizer->Add(value, 1, wxALIGN_LEFT | wxTOP, LAYOUT_MARGIN);
#else
// value and time to the right in one row
sizer->Add(label);
sizer->Add(value, 0, wxLEFT, LAYOUT_MARGIN);
#endif
return value;
}
// ----------------------------------------------------------------------------
// wxGenericProgressDialog operations
// ----------------------------------------------------------------------------
bool
wxGenericProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
{
if ( !DoBeforeUpdate(skip) )
return false;
wxASSERT_MSG( value == -1 || m_gauge, wxT("cannot update non existent dialog") );
#ifdef __WXMSW__
value /= m_factor;
#endif // __WXMSW__
wxASSERT_MSG( value <= m_maximum, wxT("invalid progress value") );
if ( m_gauge )
m_gauge->SetValue(value);
UpdateMessage(newmsg);
if ( (m_elapsed || m_remaining || m_estimated) && (value != 0) )
{
unsigned long elapsed;
unsigned long display_remaining;
UpdateTimeEstimates( value,
elapsed,
m_display_estimated,
display_remaining );
SetTimeLabel(elapsed, m_elapsed);
SetTimeLabel(m_display_estimated, m_estimated);
SetTimeLabel(display_remaining, m_remaining);
@@ -405,7 +465,7 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
}
wxCHECK_MSG(wxEventLoopBase::GetActive(), false,
"wxProgressDialog::Update needs a running event loop");
"wxGenericProgressDialog::Update needs a running event loop");
// allow the window to repaint:
// NOTE: since we yield only for UI events with this call, there
@@ -438,7 +498,7 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
return m_state != Canceled;
}
bool wxProgressDialog::Pulse(const wxString& newmsg, bool *skip)
bool wxGenericProgressDialog::Pulse(const wxString& newmsg, bool *skip)
{
if ( !DoBeforeUpdate(skip) )
return false;
@@ -464,10 +524,10 @@ bool wxProgressDialog::Pulse(const wxString& newmsg, bool *skip)
return m_state != Canceled;
}
bool wxProgressDialog::DoBeforeUpdate(bool *skip)
bool wxGenericProgressDialog::DoBeforeUpdate(bool *skip)
{
wxCHECK_MSG(wxEventLoopBase::GetActive(), false,
"wxProgressDialog::DoBeforeUpdate needs a running event loop");
"wxGenericProgressDialog::DoBeforeUpdate needs a running event loop");
// we have to yield because not only we want to update the display but
// also to process the clicks on the cancel and skip buttons
@@ -487,10 +547,10 @@ bool wxProgressDialog::DoBeforeUpdate(bool *skip)
return m_state != Canceled;
}
void wxProgressDialog::DoAfterUpdate()
void wxGenericProgressDialog::DoAfterUpdate()
{
wxCHECK_RET(wxEventLoopBase::GetActive(),
"wxProgressDialog::DoAfterUpdate needs a running event loop");
"wxGenericProgressDialog::DoAfterUpdate needs a running event loop");
// allow the window to repaint:
// NOTE: since we yield only for UI events with this call, there
@@ -498,7 +558,7 @@ void wxProgressDialog::DoAfterUpdate()
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
}
void wxProgressDialog::Resume()
void wxGenericProgressDialog::Resume()
{
m_state = Continue;
m_ctdelay = m_delay; // force an update of the elapsed/estimated/remaining time
@@ -509,7 +569,7 @@ void wxProgressDialog::Resume()
m_skip = false;
}
bool wxProgressDialog::Show( bool show )
bool wxGenericProgressDialog::Show( bool show )
{
// reenable other windows before hiding this one because otherwise
// Windows wouldn't give the focus back to the window which had
@@ -520,26 +580,26 @@ bool wxProgressDialog::Show( bool show )
return wxDialog::Show(show);
}
int wxProgressDialog::GetValue() const
int wxGenericProgressDialog::GetValue() const
{
if (m_gauge)
return m_gauge->GetValue();
return wxNOT_FOUND;
}
int wxProgressDialog::GetRange() const
int wxGenericProgressDialog::GetRange() const
{
if (m_gauge)
return m_gauge->GetRange();
return wxNOT_FOUND;
}
wxString wxProgressDialog::GetMessage() const
wxString wxGenericProgressDialog::GetMessage() const
{
return m_msg->GetLabel();
}
void wxProgressDialog::SetRange(int maximum)
void wxGenericProgressDialog::SetRange(int maximum)
{
wxASSERT_MSG(m_gauge, "The dialog should have been constructed with a range > 0");
wxASSERT_MSG(maximum > 0, "Invalid range");
@@ -556,22 +616,43 @@ void wxProgressDialog::SetRange(int maximum)
}
bool wxProgressDialog::WasCancelled() const
bool wxGenericProgressDialog::WasCancelled() const
{
return m_hasAbortButton && m_state == Canceled;
}
bool wxProgressDialog::WasSkipped() const
bool wxGenericProgressDialog::WasSkipped() const
{
return m_hasSkipButton && m_skip;
}
// static
void wxGenericProgressDialog::SetTimeLabel(unsigned long val,
wxStaticText *label)
{
if ( label )
{
wxString s;
if (val != (unsigned long)-1)
{
s = GetFormattedTime(val);
}
else
{
s = _("Unknown");
}
if ( s != label->GetLabel() )
label->SetLabel(s);
}
}
// ----------------------------------------------------------------------------
// event handlers
// ----------------------------------------------------------------------------
void wxProgressDialog::OnCancel(wxCommandEvent& event)
void wxGenericProgressDialog::OnCancel(wxCommandEvent& event)
{
if ( m_state == Finished )
{
@@ -595,13 +676,13 @@ void wxProgressDialog::OnCancel(wxCommandEvent& event)
}
}
void wxProgressDialog::OnSkip(wxCommandEvent& WXUNUSED(event))
void wxGenericProgressDialog::OnSkip(wxCommandEvent& WXUNUSED(event))
{
DisableSkip();
m_skip = true;
}
void wxProgressDialog::OnClose(wxCloseEvent& event)
void wxGenericProgressDialog::OnClose(wxCloseEvent& event)
{
if ( m_state == Uncancelable )
{
@@ -628,13 +709,27 @@ void wxProgressDialog::OnClose(wxCloseEvent& event)
// destruction
// ----------------------------------------------------------------------------
wxProgressDialog::~wxProgressDialog()
wxGenericProgressDialog::~wxGenericProgressDialog()
{
// normally this should have been already done, but just in case
ReenableOtherWindows();
}
void wxProgressDialog::ReenableOtherWindows()
void wxGenericProgressDialog::DisableOtherWindows()
{
if ( HasFlag(wxPD_APP_MODAL) )
{
m_winDisabler = new wxWindowDisabler(this);
}
else
{
if ( m_parentTop )
m_parentTop->Disable();
m_winDisabler = NULL;
}
}
void wxGenericProgressDialog::ReenableOtherWindows()
{
if ( HasFlag(wxPD_APP_MODAL) )
{
@@ -651,30 +746,7 @@ void wxProgressDialog::ReenableOtherWindows()
// private functions
// ----------------------------------------------------------------------------
static void SetTimeLabel(unsigned long val, wxStaticText *label)
{
if ( label )
{
wxString s;
if (val != (unsigned long)-1)
{
unsigned long hours = val / 3600;
unsigned long minutes = (val % 3600) / 60;
unsigned long seconds = val % 60;
s.Printf(wxT("%lu:%02lu:%02lu"), hours, minutes, seconds);
}
else
{
s = _("Unknown");
}
if ( s != label->GetLabel() )
label->SetLabel(s);
}
}
void wxProgressDialog::EnableSkip(bool enable)
void wxGenericProgressDialog::EnableSkip(bool enable)
{
if(m_hasSkipButton)
{
@@ -690,7 +762,7 @@ void wxProgressDialog::EnableSkip(bool enable)
}
}
void wxProgressDialog::EnableAbort(bool enable)
void wxGenericProgressDialog::EnableAbort(bool enable)
{
if(m_hasAbortButton)
{
@@ -706,7 +778,7 @@ void wxProgressDialog::EnableAbort(bool enable)
}
}
void wxProgressDialog::EnableClose()
void wxGenericProgressDialog::EnableClose()
{
if(m_hasAbortButton)
{
@@ -722,10 +794,10 @@ void wxProgressDialog::EnableClose()
}
}
void wxProgressDialog::UpdateMessage(const wxString &newmsg)
void wxGenericProgressDialog::UpdateMessage(const wxString &newmsg)
{
wxCHECK_RET(wxEventLoopBase::GetActive(),
"wxProgressDialog::UpdateMessage needs a running event loop");
"wxGenericProgressDialog::UpdateMessage needs a running event loop");
if ( !newmsg.empty() && newmsg != m_msg->GetLabel() )
{

881
src/msw/progdlg.cpp Normal file
View File

@@ -0,0 +1,881 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/msw/progdlg.cpp
// Purpose: wxProgressDialog
// Author: Rickard Westerlund
// Created: 2010-07-22
// RCS-ID: $Id$
// Copyright: (c) 2010 wxWidgets team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// Declarations
// ============================================================================
// ----------------------------------------------------------------------------
// Headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_PROGRESSDLG && wxUSE_THREADS
#include "wx/msw/private/msgdlg.h"
#include "wx/progdlg.h"
using namespace wxMSWMessageDialog;
#ifdef wxHAS_MSW_TASKDIALOG
// ----------------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------------
namespace
{
// Notification values of wxProgressDialogSharedData::m_notifications
const int wxSPDD_VALUE_CHANGED = 0x0001;
const int wxSPDD_RANGE_CHANGED = 0x0002;
const int wxSPDD_PBMARQUEE_CHANGED = 0x0004;
const int wxSPDD_TITLE_CHANGED = 0x0008;
const int wxSPDD_MESSAGE_CHANGED = 0x0010;
const int wxSPDD_EXPINFO_CHANGED = 0x0020;
const int wxSPDD_ENABLE_SKIP = 0x0040;
const int wxSPDD_ENABLE_ABORT = 0x0080;
const int wxSPDD_DISABLE_SKIP = 0x0100;
const int wxSPDD_DISABLE_ABORT = 0x0200;
const int wxSPDD_FINISHED = 0x0400;
const int wxSPDD_DESTROYED = 0x0800;
const int Id_SkipBtn = wxID_HIGHEST + 1;
} // anonymous namespace
// ============================================================================
// Helper classes
// ============================================================================
// Class used to share data between the main thread and the task dialog runner.
class wxProgressDialogSharedData
{
public:
wxProgressDialogSharedData()
{
m_hwnd = 0;
m_value = 0;
m_progressBarMarquee = false;
m_skipped = false;
m_notifications = 0;
}
wxCriticalSection m_cs;
HWND m_hwnd; // Task dialog handler
long m_style; // wxProgressDialog style
int m_value;
int m_range;
wxString m_title;
wxString m_message;
wxString m_expandedInformation;
wxString m_labelCancel; // Privately used by callback.
unsigned long m_timeStop;
wxGenericProgressDialog::ProgressDialogState m_state;
bool m_progressBarMarquee;
bool m_skipped;
// Bit field that indicates fields that have been modified by the
// main thread so the task dialog runner knows what to update.
int m_notifications;
};
// Runner thread that takes care of displaying and updating the
// task dialog.
class wxProgressDialogTaskRunner : public wxThread
{
public:
wxProgressDialogTaskRunner(wxWindow* parent)
: wxThread(wxTHREAD_JOINABLE),
m_parent(parent)
{ }
wxProgressDialogSharedData* GetSharedDataObject()
{ return &m_sharedData; }
private:
wxWindow* m_parent;
wxProgressDialogSharedData m_sharedData;
virtual void* Entry();
static HRESULT CALLBACK TaskDialogCallbackProc(HWND hwnd,
UINT uNotification,
WPARAM wParam,
LPARAM lParam,
LONG_PTR dwRefData);
};
// ============================================================================
// Helper functions
// ============================================================================
namespace
{
bool UsesCloseButtonOnly(long style)
{
return !((style & wxPD_CAN_ABORT) || (style & wxPD_AUTO_HIDE));
}
BOOL CALLBACK DisplayCloseButton(HWND hwnd, LPARAM lParam)
{
wxProgressDialogSharedData *sharedData =
(wxProgressDialogSharedData *) lParam;
if ( wxGetWindowText( hwnd ) == sharedData->m_labelCancel )
{
sharedData->m_labelCancel = _("Close");
SendMessage( hwnd, WM_SETTEXT, 0,
(LPARAM) sharedData->m_labelCancel.wx_str() );
return FALSE;
}
return TRUE;
}
void PerformNotificationUpdates(HWND hwnd,
wxProgressDialogSharedData *sharedData)
{
// Update the appropriate dialog fields.
if ( sharedData->m_notifications & wxSPDD_RANGE_CHANGED )
{
::SendMessage( hwnd,
TDM_SET_PROGRESS_BAR_RANGE,
0,
MAKELPARAM(0, sharedData->m_range) );
}
if ( sharedData->m_notifications & wxSPDD_VALUE_CHANGED )
{
::SendMessage( hwnd,
TDM_SET_PROGRESS_BAR_POS,
sharedData->m_value,
0 );
}
if ( sharedData->m_notifications & wxSPDD_PBMARQUEE_CHANGED )
{
BOOL val = sharedData->m_progressBarMarquee ? TRUE : FALSE;
::SendMessage( hwnd,
TDM_SET_MARQUEE_PROGRESS_BAR,
val,
0 );
::SendMessage( hwnd,
TDM_SET_PROGRESS_BAR_MARQUEE,
val,
0 );
}
if ( sharedData->m_notifications & wxSPDD_TITLE_CHANGED )
::SetWindowText( hwnd, sharedData->m_title.wx_str() );
if ( sharedData->m_notifications & wxSPDD_MESSAGE_CHANGED )
{
// Split the message in the title string and the rest if it has
// multiple lines.
wxString
title = sharedData->m_message,
body;
const size_t posNL = title.find('\n');
if ( posNL != wxString::npos )
{
// There can an extra new line between the first and subsequent
// lines to separate them as it looks better with the generic
// version -- but in this one, they're already separated by the use
// of different dialog elements, so suppress the extra new line.
int numNLs = 1;
if ( posNL < title.length() - 1 && title[posNL + 1] == '\n' )
numNLs++;
body.assign(title, posNL + numNLs, wxString::npos);
title.erase(posNL);
}
::SendMessage( hwnd,
TDM_SET_ELEMENT_TEXT,
TDE_MAIN_INSTRUCTION,
(LPARAM) title.wx_str() );
::SendMessage( hwnd,
TDM_SET_ELEMENT_TEXT,
TDE_CONTENT,
(LPARAM) body.wx_str() );
}
if ( sharedData->m_notifications & wxSPDD_EXPINFO_CHANGED )
{
const wxString& expandedInformation =
sharedData->m_expandedInformation;
if ( !expandedInformation.empty() )
{
::SendMessage( hwnd,
TDM_SET_ELEMENT_TEXT,
TDE_EXPANDED_INFORMATION,
(LPARAM) expandedInformation.wx_str() );
}
}
if ( sharedData->m_notifications & wxSPDD_ENABLE_SKIP )
::SendMessage( hwnd, TDM_ENABLE_BUTTON, Id_SkipBtn, TRUE );
if ( sharedData->m_notifications & wxSPDD_ENABLE_ABORT )
::SendMessage( hwnd, TDM_ENABLE_BUTTON, IDCANCEL, TRUE );
if ( sharedData->m_notifications & wxSPDD_DISABLE_SKIP )
::SendMessage( hwnd, TDM_ENABLE_BUTTON, Id_SkipBtn, FALSE );
if ( sharedData->m_notifications & wxSPDD_DISABLE_ABORT )
::SendMessage( hwnd, TDM_ENABLE_BUTTON, IDCANCEL, FALSE );
// Is the progress finished?
if ( sharedData->m_notifications & wxSPDD_FINISHED )
{
sharedData->m_state = wxGenericProgressDialog::Finished;
if ( !(sharedData->m_style & wxPD_AUTO_HIDE) )
{
// Change Cancel into Close and activate the button.
::SendMessage( hwnd, TDM_ENABLE_BUTTON, Id_SkipBtn, FALSE );
::SendMessage( hwnd, TDM_ENABLE_BUTTON, IDCANCEL, TRUE );
::EnumChildWindows( hwnd, DisplayCloseButton,
(LPARAM) sharedData );
}
}
}
} // anonymous namespace
#endif // wxHAS_MSW_TASKDIALOG
// ============================================================================
// wxProgressDialog implementation
// ============================================================================
wxProgressDialog::wxProgressDialog( const wxString& title,
const wxString& message,
int maximum,
wxWindow *parent,
int style )
: wxGenericProgressDialog(parent, maximum, style),
m_taskDialogRunner(NULL),
m_sharedData(NULL),
m_message(message),
m_title(title)
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
Show();
DisableOtherWindows();
return;
}
#endif // wxHAS_MSW_TASKDIALOG
Create(title, message, maximum, parent, style);
}
wxProgressDialog::~wxProgressDialog()
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( !m_taskDialogRunner )
return;
if ( m_sharedData )
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
m_sharedData->m_notifications |= wxSPDD_DESTROYED;
}
m_taskDialogRunner->Wait();
delete m_taskDialogRunner;
ReenableOtherWindows();
if ( GetTopParent() )
GetTopParent()->Raise();
#endif // wxHAS_MSW_TASKDIALOG
}
bool wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
// Do nothing in canceled state.
if ( !DoNativeBeforeUpdate(skip) )
return false;
value /= m_factor;
wxASSERT_MSG( value <= m_maximum, wxT("invalid progress value") );
m_sharedData->m_value = value;
m_sharedData->m_notifications |= wxSPDD_VALUE_CHANGED;
if ( !newmsg.empty() )
{
m_message = newmsg;
m_sharedData->m_message = newmsg;
m_sharedData->m_notifications |= wxSPDD_MESSAGE_CHANGED;
}
if ( m_sharedData->m_progressBarMarquee )
{
m_sharedData->m_progressBarMarquee = false;
m_sharedData->m_notifications |= wxSPDD_PBMARQUEE_CHANGED;
}
UpdateExpandedInformation( value );
// Has the progress bar finished?
if ( value == m_maximum )
{
if ( m_state == Finished )
return true;
m_state = Finished;
m_sharedData->m_state = Finished;
m_sharedData->m_notifications |= wxSPDD_FINISHED;
if( !HasFlag(wxPD_AUTO_HIDE) && newmsg.empty() )
{
// Provide the finishing message if the application didn't.
m_message = _("Done.");
m_sharedData->m_message = m_message;
m_sharedData->m_notifications |= wxSPDD_MESSAGE_CHANGED;
}
}
return m_sharedData->m_state != Canceled;
}
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::Update( value, newmsg, skip );
}
bool wxProgressDialog::Pulse(const wxString& newmsg, bool *skip)
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
// Do nothing in canceled state.
if ( !DoNativeBeforeUpdate(skip) )
return false;
if ( !m_sharedData->m_progressBarMarquee )
{
m_sharedData->m_progressBarMarquee = true;
m_sharedData->m_notifications |= wxSPDD_PBMARQUEE_CHANGED;
}
if ( !newmsg.empty() )
{
m_message = newmsg;
m_sharedData->m_message = newmsg;
m_sharedData->m_notifications |= wxSPDD_MESSAGE_CHANGED;
}
// The value passed here doesn't matter, only elapsed time makes sense
// in indeterminate mode anyhow.
UpdateExpandedInformation(0);
return m_sharedData->m_state != Canceled;
}
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::Pulse( newmsg, skip );
}
bool wxProgressDialog::DoNativeBeforeUpdate(bool *skip)
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
if ( m_sharedData->m_skipped )
{
if ( skip && !*skip )
{
*skip = true;
m_sharedData->m_skipped = false;
m_sharedData->m_notifications |= wxSPDD_ENABLE_SKIP;
}
}
if ( m_sharedData->m_state == Canceled )
m_timeStop = m_sharedData->m_timeStop;
return m_sharedData->m_state != Canceled;
}
#endif // wxHAS_MSW_TASKDIALOG
wxUnusedVar(skip);
wxFAIL_MSG( "unreachable" );
return false;
}
void wxProgressDialog::Resume()
{
wxGenericProgressDialog::Resume();
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
HWND hwnd;
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
m_sharedData->m_state = m_state;
// "Skip" was disabled when "Cancel" had been clicked, so re-enable
// it now.
m_sharedData->m_notifications |= wxSPDD_ENABLE_SKIP;
if ( !UsesCloseButtonOnly(m_windowStyle) )
m_sharedData->m_notifications |= wxSPDD_ENABLE_ABORT;
hwnd = m_sharedData->m_hwnd;
} // Unlock m_cs, we can't call any function operating on a dialog with
// it locked as it can result in a deadlock if the dialog callback is
// called by Windows.
// After resuming we need to bring the window on top of the Z-order as
// it could be hidden by another window shown from the main thread,
// e.g. a confirmation dialog asking whether the user really wants to
// abort.
//
// Notice that this must be done from the main thread as it owns the
// currently active window and attempts to do this from the task dialog
// thread would simply fail.
::BringWindowToTop(hwnd);
}
#endif // wxHAS_MSW_TASKDIALOG
}
int wxProgressDialog::GetValue() const
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
return m_sharedData->m_value;
}
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::GetValue();
}
wxString wxProgressDialog::GetMessage() const
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
return m_message;
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::GetMessage();
}
void wxProgressDialog::SetRange(int maximum)
{
wxGenericProgressDialog::SetRange( maximum );
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
m_sharedData->m_range = maximum;
m_sharedData->m_notifications |= wxSPDD_RANGE_CHANGED;
}
#endif // wxHAS_MSW_TASKDIALOG
}
bool wxProgressDialog::WasSkipped() const
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
if ( !m_sharedData )
{
// Couldn't be skipped before being shown.
return false;
}
wxCriticalSectionLocker locker(m_sharedData->m_cs);
return m_sharedData->m_skipped;
}
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::WasSkipped();
}
bool wxProgressDialog::WasCancelled() const
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
return m_sharedData->m_state == Canceled;
}
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::WasCancelled();
}
void wxProgressDialog::SetTitle(const wxString& title)
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
m_title = title;
if ( m_sharedData )
{
wxCriticalSectionLocker locker(m_sharedData->m_cs);
m_sharedData->m_title = title;
m_sharedData->m_notifications = wxSPDD_TITLE_CHANGED;
}
}
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::SetTitle(title);
}
wxString wxProgressDialog::GetTitle() const
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
return m_title;
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::GetTitle();
}
bool wxProgressDialog::Show(bool show)
{
#ifdef wxHAS_MSW_TASKDIALOG
if ( HasNativeProgressDialog() )
{
// The dialog can't be hidden at all and showing it again after it had
// been shown before doesn't do anything.
if ( !show || m_taskDialogRunner )
return false;
// We're showing the dialog for the first time, create the thread that
// will manage it.
m_taskDialogRunner = new wxProgressDialogTaskRunner(GetParent());
m_sharedData = m_taskDialogRunner->GetSharedDataObject();
// Initialize shared data.
m_sharedData->m_title = m_title;
m_sharedData->m_message = m_message;
m_sharedData->m_range = m_maximum;
m_sharedData->m_state = Uncancelable;
m_sharedData->m_style = m_windowStyle;
if ( HasFlag(wxPD_CAN_ABORT) )
{
m_sharedData->m_state = Continue;
m_sharedData->m_labelCancel = _("Cancel");
}
else if ( !HasFlag(wxPD_AUTO_HIDE) )
{
m_sharedData->m_labelCancel = _("Close");
}
if ( m_windowStyle & (wxPD_ELAPSED_TIME
| wxPD_ESTIMATED_TIME
| wxPD_REMAINING_TIME) )
{
// Use a non-empty string just to have the collapsible pane shown.
m_sharedData->m_expandedInformation = " ";
}
// Do launch the thread.
if ( m_taskDialogRunner->Create() != wxTHREAD_NO_ERROR )
{
wxLogError( "Unable to create thread!" );
return false;
}
if ( m_taskDialogRunner->Run() != wxTHREAD_NO_ERROR )
{
wxLogError( "Unable to start thread!" );
return false;
}
if ( !HasFlag(wxPD_APP_MODAL) )
GetParent()->Disable();
//else: otherwise all windows will be disabled by m_taskDialogRunner
// Do not show the underlying dialog.
return false;
}
#endif // wxHAS_MSW_TASKDIALOG
return wxGenericProgressDialog::Show( show );
}
bool wxProgressDialog::HasNativeProgressDialog() const
{
#ifdef wxHAS_MSW_TASKDIALOG
// For a native implementation task dialogs are required, which
// also require at least one button to be present so the flags needs
// to be checked as well to see if this is the case.
return HasNativeTaskDialog()
&& ((m_windowStyle & (wxPD_CAN_SKIP | wxPD_CAN_ABORT))
|| !(m_windowStyle & wxPD_AUTO_HIDE));
#else // !wxHAS_MSW_TASKDIALOG
// This shouldn't be even called in !wxHAS_MSW_TASKDIALOG case but as we
// still must define the function as returning something, return false.
return false;
#endif // wxHAS_MSW_TASKDIALOG/!wxHAS_MSW_TASKDIALOG
}
void wxProgressDialog::UpdateExpandedInformation(int value)
{
#ifdef wxHAS_MSW_TASKDIALOG
unsigned long elapsedTime;
unsigned long estimatedTime;
unsigned long remainingTime;
UpdateTimeEstimates(value, elapsedTime, estimatedTime, remainingTime);
int realEstimatedTime = estimatedTime,
realRemainingTime = remainingTime;
if ( m_sharedData->m_progressBarMarquee )
{
// In indeterminate mode we don't have any estimation neither for the
// remaining nor for estimated time.
realEstimatedTime =
realRemainingTime = -1;
}
wxString expandedInformation;
// Calculate the three different timing values.
if ( m_windowStyle & wxPD_ELAPSED_TIME )
{
expandedInformation << GetElapsedLabel()
<< " "
<< GetFormattedTime(elapsedTime);
}
if ( m_windowStyle & wxPD_ESTIMATED_TIME )
{
if ( !expandedInformation.empty() )
expandedInformation += "\n";
expandedInformation << GetEstimatedLabel()
<< " "
<< GetFormattedTime(realEstimatedTime);
}
if ( m_windowStyle & wxPD_REMAINING_TIME )
{
if ( !expandedInformation.empty() )
expandedInformation += "\n";
expandedInformation << GetRemainingLabel()
<< " "
<< GetFormattedTime(realRemainingTime);
}
// Update with new timing information.
if ( expandedInformation != m_sharedData->m_expandedInformation )
{
m_sharedData->m_expandedInformation = expandedInformation;
m_sharedData->m_notifications |= wxSPDD_EXPINFO_CHANGED;
}
#else // !wxHAS_MSW_TASKDIALOG
wxUnusedVar(value);
#endif // wxHAS_MSW_TASKDIALOG/!wxHAS_MSW_TASKDIALOG
}
// ----------------------------------------------------------------------------
// wxProgressDialogTaskRunner and related methods
// ----------------------------------------------------------------------------
#ifdef wxHAS_MSW_TASKDIALOG
void* wxProgressDialogTaskRunner::Entry()
{
WinStruct<TASKDIALOGCONFIG> tdc;
wxMSWTaskDialogConfig wxTdc;
{
wxCriticalSectionLocker locker(m_sharedData.m_cs);
wxTdc.caption = m_sharedData.m_title.wx_str();
wxTdc.message = m_sharedData.m_message.wx_str();
wxTdc.MSWCommonTaskDialogInit( tdc );
tdc.pfCallback = TaskDialogCallbackProc;
tdc.lpCallbackData = (LONG_PTR) &m_sharedData;
// Undo some of the effects of MSWCommonTaskDialogInit().
tdc.dwFlags &= ~TDF_EXPAND_FOOTER_AREA; // Expand in content area.
tdc.dwCommonButtons = 0; // Don't use common buttons.
wxTdc.useCustomLabels = true;
if ( m_sharedData.m_style & wxPD_CAN_SKIP )
wxTdc.AddTaskDialogButton( tdc, Id_SkipBtn, 0, _("Skip") );
// Use a Cancel button when requested or use a Close button when
// the dialog does not automatically hide.
if ( (m_sharedData.m_style & wxPD_CAN_ABORT)
|| !(m_sharedData.m_style & wxPD_AUTO_HIDE) )
{
wxTdc.AddTaskDialogButton( tdc, IDCANCEL, 0,
m_sharedData.m_labelCancel );
}
tdc.dwFlags |= TDF_CALLBACK_TIMER
| TDF_SHOW_PROGRESS_BAR
| TDF_SHOW_MARQUEE_PROGRESS_BAR;
if ( !m_sharedData.m_expandedInformation.empty() )
{
tdc.pszExpandedInformation =
m_sharedData.m_expandedInformation.wx_str();
}
}
TaskDialogIndirect_t taskDialogIndirect = GetTaskDialogIndirectFunc();
if ( !taskDialogIndirect )
return NULL;
int msAns;
HRESULT hr = taskDialogIndirect(&tdc, &msAns, NULL, NULL);
if ( FAILED(hr) )
wxLogApiError( "TaskDialogIndirect", hr );
return NULL;
}
// static
HRESULT CALLBACK
wxProgressDialogTaskRunner::TaskDialogCallbackProc
(
HWND hwnd,
UINT uNotification,
WPARAM wParam,
LPARAM WXUNUSED(lParam),
LONG_PTR dwRefData
)
{
wxProgressDialogSharedData * const sharedData =
(wxProgressDialogSharedData *) dwRefData;
wxCriticalSectionLocker locker(sharedData->m_cs);
switch ( uNotification )
{
case TDN_CREATED:
// Store the HWND for the main thread use.
sharedData->m_hwnd = hwnd;
// Set the maximum value and disable Close button.
::SendMessage( hwnd,
TDM_SET_PROGRESS_BAR_RANGE,
0,
MAKELPARAM(0, sharedData->m_range) );
if ( UsesCloseButtonOnly(sharedData->m_style) )
::SendMessage( hwnd, TDM_ENABLE_BUTTON, IDCANCEL, FALSE );
break;
case TDN_BUTTON_CLICKED:
switch ( wParam )
{
case Id_SkipBtn:
::SendMessage(hwnd, TDM_ENABLE_BUTTON, Id_SkipBtn, FALSE);
sharedData->m_skipped = true;
return TRUE;
case IDCANCEL:
if ( sharedData->m_state
== wxGenericProgressDialog::Finished )
{
return FALSE;
}
// Close button on the window triggers an IDCANCEL press,
// don't allow it when it should only be possible to close
// a finished dialog.
if ( !UsesCloseButtonOnly(sharedData->m_style) )
{
wxCHECK_MSG( sharedData->m_state ==
wxGenericProgressDialog::Continue,
TRUE,
"Dialog not in a cancelable state!");
::SendMessage(hwnd, TDM_ENABLE_BUTTON, Id_SkipBtn, FALSE);
::SendMessage(hwnd, TDM_ENABLE_BUTTON, IDCANCEL, FALSE);
sharedData->m_timeStop = wxGetCurrentTime();
sharedData->m_state = wxGenericProgressDialog::Canceled;
}
return TRUE;
}
break;
case TDN_TIMER:
PerformNotificationUpdates(hwnd, sharedData);
// End dialog in three different cases:
// 1. Progress finished and dialog should automatically hide.
// 2. The wxProgressDialog object was destructed and should
// automatically hide.
// 3. The dialog was canceled and wxProgressDialog object
// was destroyed.
bool isCanceled =
sharedData->m_state == wxGenericProgressDialog::Canceled;
bool isFinished =
sharedData->m_state == wxGenericProgressDialog::Finished;
bool wasDestroyed =
(sharedData->m_notifications & wxSPDD_DESTROYED) != 0;
bool shouldAutoHide = (sharedData->m_style & wxPD_AUTO_HIDE) != 0;
if ( (shouldAutoHide && (isFinished || wasDestroyed))
|| (wasDestroyed && isCanceled) )
{
::EndDialog( hwnd, IDCLOSE );
}
sharedData->m_notifications = 0;
return TRUE;
}
// Return anything.
return 0;
}
#endif // wxHAS_MSW_TASKDIALOG
#endif // wxUSE_PROGRESSDLG && wxUSE_THREADS