From c31d9c7f601e767cc3210b63a989434af76fef61 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 18 Aug 2010 22:49:02 +0000 Subject: [PATCH] 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 --- Makefile.in | 34 ++ build/bakefiles/files.bkl | 2 + build/msw/makefile.bcc | 56 ++- build/msw/makefile.gcc | 56 ++- build/msw/makefile.vc | 56 ++- build/msw/makefile.wat | 56 ++- build/msw/wx_core.dsp | 39 ++ build/msw/wx_vc7_core.vcproj | 18 + build/msw/wx_vc8_core.vcproj | 24 + build/msw/wx_vc9_core.vcproj | 24 + docs/changes.txt | 16 +- include/wx/generic/progdlgg.h | 122 +++-- include/wx/msw/progdlg.h | 76 +++ include/wx/progdlg.h | 26 +- samples/dialogs/dialogs.cpp | 38 +- src/generic/printps.cpp | 2 +- src/generic/progdlgg.cpp | 370 ++++++++------ src/msw/progdlg.cpp | 881 ++++++++++++++++++++++++++++++++++ 18 files changed, 1606 insertions(+), 290 deletions(-) create mode 100644 include/wx/msw/progdlg.h create mode 100644 src/msw/progdlg.cpp diff --git a/Makefile.in b/Makefile.in index d76dad451a..c845a955ea 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 57af655284..0739188eea 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -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 diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index b97cf98576..04e102042f 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -1750,11 +1750,12 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_msgdlg.obj \ $(OBJS)\monodll_nativdlg.obj \ $(OBJS)\monodll_nativewin.obj \ - $(OBJS)\monodll_msw_notebook.obj \ - $(OBJS)\monodll_access.obj \ - $(OBJS)\monodll_ownerdrw.obj \ - $(OBJS)\monodll_msw_radiobox.obj \ - $(OBJS)\monodll_msw_radiobut.obj \ + $(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 \ $(OBJS)\monodll_msw_scrolbar.obj \ $(OBJS)\monodll_msw_slider.obj \ @@ -2469,11 +2470,12 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_msgdlg.obj \ $(OBJS)\monolib_nativdlg.obj \ $(OBJS)\monolib_nativewin.obj \ - $(OBJS)\monolib_msw_notebook.obj \ - $(OBJS)\monolib_access.obj \ - $(OBJS)\monolib_ownerdrw.obj \ - $(OBJS)\monolib_msw_radiobox.obj \ - $(OBJS)\monolib_msw_radiobut.obj \ + $(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 \ $(OBJS)\monolib_msw_scrolbar.obj \ $(OBJS)\monolib_msw_slider.obj \ @@ -3079,11 +3081,12 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_msgdlg.obj \ $(OBJS)\coredll_nativdlg.obj \ $(OBJS)\coredll_nativewin.obj \ - $(OBJS)\coredll_msw_notebook.obj \ - $(OBJS)\coredll_access.obj \ - $(OBJS)\coredll_ownerdrw.obj \ - $(OBJS)\coredll_msw_radiobox.obj \ - $(OBJS)\coredll_msw_radiobut.obj \ + $(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 \ $(OBJS)\coredll_msw_scrolbar.obj \ $(OBJS)\coredll_msw_slider.obj \ @@ -3581,11 +3584,12 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_msgdlg.obj \ $(OBJS)\corelib_nativdlg.obj \ $(OBJS)\corelib_nativewin.obj \ - $(OBJS)\corelib_msw_notebook.obj \ - $(OBJS)\corelib_access.obj \ - $(OBJS)\corelib_ownerdrw.obj \ - $(OBJS)\corelib_msw_radiobox.obj \ - $(OBJS)\corelib_msw_radiobut.obj \ + $(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 \ $(OBJS)\corelib_msw_scrolbar.obj \ $(OBJS)\corelib_msw_slider.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 diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index 17486f80eb..9458aadbd9 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -1761,11 +1761,12 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_msgdlg.o \ $(OBJS)\monodll_nativdlg.o \ $(OBJS)\monodll_nativewin.o \ - $(OBJS)\monodll_msw_notebook.o \ - $(OBJS)\monodll_access.o \ - $(OBJS)\monodll_ownerdrw.o \ - $(OBJS)\monodll_msw_radiobox.o \ - $(OBJS)\monodll_msw_radiobut.o \ + $(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 \ $(OBJS)\monodll_msw_scrolbar.o \ $(OBJS)\monodll_msw_slider.o \ @@ -2486,11 +2487,12 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_msgdlg.o \ $(OBJS)\monolib_nativdlg.o \ $(OBJS)\monolib_nativewin.o \ - $(OBJS)\monolib_msw_notebook.o \ - $(OBJS)\monolib_access.o \ - $(OBJS)\monolib_ownerdrw.o \ - $(OBJS)\monolib_msw_radiobox.o \ - $(OBJS)\monolib_msw_radiobut.o \ + $(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 \ $(OBJS)\monolib_msw_scrolbar.o \ $(OBJS)\monolib_msw_slider.o \ @@ -3112,11 +3114,12 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_msgdlg.o \ $(OBJS)\coredll_nativdlg.o \ $(OBJS)\coredll_nativewin.o \ - $(OBJS)\coredll_msw_notebook.o \ - $(OBJS)\coredll_access.o \ - $(OBJS)\coredll_ownerdrw.o \ - $(OBJS)\coredll_msw_radiobox.o \ - $(OBJS)\coredll_msw_radiobut.o \ + $(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 \ $(OBJS)\coredll_msw_scrolbar.o \ $(OBJS)\coredll_msw_slider.o \ @@ -3622,11 +3625,12 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_msgdlg.o \ $(OBJS)\corelib_nativdlg.o \ $(OBJS)\corelib_nativewin.o \ - $(OBJS)\corelib_msw_notebook.o \ - $(OBJS)\corelib_access.o \ - $(OBJS)\corelib_ownerdrw.o \ - $(OBJS)\corelib_msw_radiobox.o \ - $(OBJS)\corelib_msw_radiobut.o \ + $(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 \ $(OBJS)\corelib_msw_scrolbar.o \ $(OBJS)\corelib_msw_slider.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) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index bf7554dc41..7c49f77c47 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -1958,11 +1958,12 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_msgdlg.obj \ $(OBJS)\monodll_nativdlg.obj \ $(OBJS)\monodll_nativewin.obj \ - $(OBJS)\monodll_msw_notebook.obj \ - $(OBJS)\monodll_access.obj \ - $(OBJS)\monodll_ownerdrw.obj \ - $(OBJS)\monodll_msw_radiobox.obj \ - $(OBJS)\monodll_msw_radiobut.obj \ + $(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 \ $(OBJS)\monodll_msw_scrolbar.obj \ $(OBJS)\monodll_msw_slider.obj \ @@ -2683,11 +2684,12 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_msgdlg.obj \ $(OBJS)\monolib_nativdlg.obj \ $(OBJS)\monolib_nativewin.obj \ - $(OBJS)\monolib_msw_notebook.obj \ - $(OBJS)\monolib_access.obj \ - $(OBJS)\monolib_ownerdrw.obj \ - $(OBJS)\monolib_msw_radiobox.obj \ - $(OBJS)\monolib_msw_radiobut.obj \ + $(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 \ $(OBJS)\monolib_msw_scrolbar.obj \ $(OBJS)\monolib_msw_slider.obj \ @@ -3359,11 +3361,12 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_msgdlg.obj \ $(OBJS)\coredll_nativdlg.obj \ $(OBJS)\coredll_nativewin.obj \ - $(OBJS)\coredll_msw_notebook.obj \ - $(OBJS)\coredll_access.obj \ - $(OBJS)\coredll_ownerdrw.obj \ - $(OBJS)\coredll_msw_radiobox.obj \ - $(OBJS)\coredll_msw_radiobut.obj \ + $(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 \ $(OBJS)\coredll_msw_scrolbar.obj \ $(OBJS)\coredll_msw_slider.obj \ @@ -3867,11 +3870,12 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_msgdlg.obj \ $(OBJS)\corelib_nativdlg.obj \ $(OBJS)\corelib_nativewin.obj \ - $(OBJS)\corelib_msw_notebook.obj \ - $(OBJS)\corelib_access.obj \ - $(OBJS)\corelib_ownerdrw.obj \ - $(OBJS)\corelib_msw_radiobox.obj \ - $(OBJS)\corelib_msw_radiobut.obj \ + $(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 \ $(OBJS)\corelib_msw_scrolbar.obj \ $(OBJS)\corelib_msw_slider.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 diff --git a/build/msw/makefile.wat b/build/msw/makefile.wat index 5e9414833e..b20f5dc887 100644 --- a/build/msw/makefile.wat +++ b/build/msw/makefile.wat @@ -321,11 +321,12 @@ ____CORE_SRC_FILENAMES_OBJECTS = & $(OBJS)\monodll_msgdlg.obj & $(OBJS)\monodll_nativdlg.obj & $(OBJS)\monodll_nativewin.obj & - $(OBJS)\monodll_msw_notebook.obj & - $(OBJS)\monodll_access.obj & - $(OBJS)\monodll_ownerdrw.obj & - $(OBJS)\monodll_msw_radiobox.obj & - $(OBJS)\monodll_msw_radiobut.obj & + $(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 & $(OBJS)\monodll_msw_scrolbar.obj & $(OBJS)\monodll_msw_slider.obj & @@ -1051,11 +1052,12 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = & $(OBJS)\monolib_msgdlg.obj & $(OBJS)\monolib_nativdlg.obj & $(OBJS)\monolib_nativewin.obj & - $(OBJS)\monolib_msw_notebook.obj & - $(OBJS)\monolib_access.obj & - $(OBJS)\monolib_ownerdrw.obj & - $(OBJS)\monolib_msw_radiobox.obj & - $(OBJS)\monolib_msw_radiobut.obj & + $(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 & $(OBJS)\monolib_msw_scrolbar.obj & $(OBJS)\monolib_msw_slider.obj & @@ -1688,11 +1690,12 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = & $(OBJS)\coredll_msgdlg.obj & $(OBJS)\coredll_nativdlg.obj & $(OBJS)\coredll_nativewin.obj & - $(OBJS)\coredll_msw_notebook.obj & - $(OBJS)\coredll_access.obj & - $(OBJS)\coredll_ownerdrw.obj & - $(OBJS)\coredll_msw_radiobox.obj & - $(OBJS)\coredll_msw_radiobut.obj & + $(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 & $(OBJS)\coredll_msw_scrolbar.obj & $(OBJS)\coredll_msw_slider.obj & @@ -2200,11 +2203,12 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = & $(OBJS)\corelib_msgdlg.obj & $(OBJS)\corelib_nativdlg.obj & $(OBJS)\corelib_nativewin.obj & - $(OBJS)\corelib_msw_notebook.obj & - $(OBJS)\corelib_access.obj & - $(OBJS)\corelib_ownerdrw.obj & - $(OBJS)\corelib_msw_radiobox.obj & - $(OBJS)\corelib_msw_radiobut.obj & + $(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 & $(OBJS)\corelib_msw_scrolbar.obj & $(OBJS)\corelib_msw_slider.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) $< diff --git a/build/msw/wx_core.dsp b/build/msw/wx_core.dsp index 8bff982d6c..ccd8920a42 100644 --- a/build/msw/wx_core.dsp +++ b/build/msw/wx_core.dsp @@ -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 diff --git a/build/msw/wx_vc7_core.vcproj b/build/msw/wx_vc7_core.vcproj index 033941da73..450f6adb30 100644 --- a/build/msw/wx_vc7_core.vcproj +++ b/build/msw/wx_vc7_core.vcproj @@ -1901,6 +1901,21 @@ RelativePath="..\..\src\msw\printwin.cpp"> + + + + + + @@ -4474,6 +4489,9 @@ RelativePath="..\..\include\wx\msw\printwin.h"> + + + + + + + + + + diff --git a/build/msw/wx_vc9_core.vcproj b/build/msw/wx_vc9_core.vcproj index 7511147f48..5efe4dd593 100644 --- a/build/msw/wx_vc9_core.vcproj +++ b/build/msw/wx_vc9_core.vcproj @@ -2564,6 +2564,26 @@ > + + + + + + + + diff --git a/docs/changes.txt b/docs/changes.txt index 8d94d5c37c..7e831c5ba7 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -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: ------ diff --git a/include/wx/generic/progdlgg.h b/include/wx/generic/progdlgg.h index ce05dd40f8..cca4526f6c 100644 --- a/include/wx/generic/progdlgg.h +++ b/include/wx/generic/progdlgg.h @@ -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, - int maximum = 100, - wxWindow *parent = NULL, - int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE); + 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__ diff --git a/include/wx/msw/progdlg.h b/include/wx/msw/progdlg.h new file mode 100644 index 0000000000..cd576dc8e9 --- /dev/null +++ b/include/wx/msw/progdlg.h @@ -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_ diff --git a/include/wx/progdlg.h b/include/wx/progdlg.h index dbce6e7275..48c708af02 100644 --- a/include/wx/progdlg.h +++ b/include/wx/progdlg.h @@ -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_ diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index 2a0a1b95e2..3abb136139 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -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 ) diff --git a/src/generic/printps.cpp b/src/generic/printps.cpp index c23f21a9f8..855b65a7a6 100644 --- a/src/generic/printps.cpp +++ b/src/generic/printps.cpp @@ -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 diff --git a/src/generic/progdlgg.cpp b/src/generic/progdlgg.cpp index 7e0e373f09..9cb3d3451f 100644 --- a/src/generic/progdlgg.cpp +++ b/src/generic/progdlgg.cpp @@ -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,49 +66,98 @@ 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, - 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) +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() +{ + 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,8 +300,82 @@ wxProgressDialog::wxProgressDialog(const wxString& title, Update(); } +void wxGenericProgressDialog::UpdateTimeEstimates(int value, + unsigned long &elapsedTime, + unsigned long &estimatedTime, + unsigned long &remainingTime) +{ + unsigned long elapsed = wxGetCurrentTime() - m_timeStart; + if ( value != 0 && (m_last_timeupdate < elapsed || value == m_maximum) ) + { + m_last_timeupdate = elapsed; + unsigned long estimated = m_break + + (unsigned long)(( (double) (elapsed-m_break) * m_maximum ) / ((double)value)) ; + if ( estimated > m_display_estimated + && m_ctdelay >= 0 + ) + { + ++m_ctdelay; + } + else if ( estimated < m_display_estimated + && m_ctdelay <= 0 + ) + { + --m_ctdelay; + } + else + { + m_ctdelay = 0; + } + if ( m_ctdelay >= m_delay // enough confirmations for a higher value + || m_ctdelay <= (m_delay*-1) // enough confirmations for a lower value + || value == m_maximum // to stay consistent + || elapsed > m_display_estimated // to stay consistent + || ( elapsed > 0 && elapsed < 4 ) // additional updates in the beginning + ) + { + m_display_estimated = estimated; + m_ctdelay = 0; + } + } + + 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 * -wxProgressDialog::CreateLabel(const wxString& text, wxSizer *sizer) +wxGenericProgressDialog::CreateLabel(const wxString& text, wxSizer *sizer) { wxStaticText *label = new wxStaticText(this, wxID_ANY, text); wxStaticText *value = new wxStaticText(this, wxID_ANY, _("unknown")); @@ -305,11 +399,11 @@ wxProgressDialog::CreateLabel(const wxString& text, wxSizer *sizer) } // ---------------------------------------------------------------------------- -// wxProgressDialog operations +// wxGenericProgressDialog operations // ---------------------------------------------------------------------------- bool -wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip) +wxGenericProgressDialog::Update(int value, const wxString& newmsg, bool *skip) { if ( !DoBeforeUpdate(skip) ) return false; @@ -329,47 +423,13 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip) if ( (m_elapsed || m_remaining || m_estimated) && (value != 0) ) { - unsigned long elapsed = wxGetCurrentTime() - m_timeStart; - if ( m_last_timeupdate < elapsed - || value == m_maximum - ) - { - m_last_timeupdate = elapsed; - unsigned long estimated = m_break + - (unsigned long)(( (double) (elapsed-m_break) * m_maximum ) / ((double)value)) ; - if ( estimated > m_display_estimated - && m_ctdelay >= 0 - ) - { - ++m_ctdelay; - } - else if ( estimated < m_display_estimated - && m_ctdelay <= 0 - ) - { - --m_ctdelay; - } - else - { - m_ctdelay = 0; - } - if ( m_ctdelay >= m_delay // enough confirmations for a higher value - || m_ctdelay <= (m_delay*-1) // enough confirmations for a lower value - || value == m_maximum // to stay consistent - || elapsed > m_display_estimated // to stay consistent - || ( elapsed > 0 && elapsed < 4 ) // additional updates in the beginning - ) - { - m_display_estimated = estimated; - m_ctdelay = 0; - } - } + unsigned long elapsed; + unsigned long display_remaining; - long display_remaining = m_display_estimated - elapsed; - if ( display_remaining < 0 ) - { - display_remaining = 0; - } + UpdateTimeEstimates( value, + elapsed, + m_display_estimated, + display_remaining ); SetTimeLabel(elapsed, m_elapsed); SetTimeLabel(m_display_estimated, m_estimated); @@ -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() ) { diff --git a/src/msw/progdlg.cpp b/src/msw/progdlg.cpp new file mode 100644 index 0000000000..b86f98986b --- /dev/null +++ b/src/msw/progdlg.cpp @@ -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 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 -- 2.45.2