Skip to content

Commit

Permalink
Implemented Windows7 taskbar progress indicator.
Browse files Browse the repository at this point in the history
  • Loading branch information
lordmulder committed Jun 13, 2014
1 parent c4e2055 commit be5649f
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 7 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Expand Up @@ -2,9 +2,9 @@
*.sdf
*.suo
*.user
*/tmp/*
/__old__
*.local.*
/bin
/ipch
/doc
/tmp
/out
18 changes: 14 additions & 4 deletions DoubleFileScanner.vcxproj
Expand Up @@ -22,6 +22,7 @@
<TreatWChar_tAsBuiltInType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</TreatWChar_tAsBuiltInType>
</ClCompile>
<ClCompile Include="src\Model_Duplicates.cpp" />
<ClCompile Include="src\Taskbar.cpp" />
<ClCompile Include="src\Thread_DirectoryScanner.cpp" />
<ClCompile Include="src\Thread_FileComparator.cpp" />
<ClCompile Include="src\Main.cpp" />
Expand Down Expand Up @@ -63,6 +64,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Config.h" />
<ClInclude Include="src\Taskbar.h" />
<ClInclude Include="src\Version.h" />
<CustomBuild Include="src\Window_Directories.h">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)\tmp\Common\moc\MOC_%(Filename).cpp" "%(FullPath)"</Command>
Expand Down Expand Up @@ -226,17 +228,21 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(SolutionDir)\tmp\Common\uic;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<TreatWarningAsError>true</TreatWarningAsError>
<DisableSpecificWarnings>4127</DisableSpecificWarnings>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -252,10 +258,10 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;QT_NO_DEBUG;QT_NODLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
Expand All @@ -264,6 +270,10 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DisableSpecificWarnings>4127</DisableSpecificWarnings>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand Down
6 changes: 6 additions & 0 deletions DoubleFileScanner.vcxproj.filters
Expand Up @@ -75,6 +75,9 @@
<ClCompile Include="src\Window_Directories.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Taskbar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\System.h">
Expand All @@ -89,6 +92,9 @@
<ClInclude Include="src\Version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Taskbar.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="DoubleFileScanner.qrc">
Expand Down
7 changes: 7 additions & 0 deletions src/Main.cpp
Expand Up @@ -32,6 +32,7 @@

#include "Config.h"
#include "System.h"
#include "Taskbar.h"
#include "Window_Main.h"

//Initialize static Qt plugins
Expand Down Expand Up @@ -106,6 +107,9 @@ static int double_file_scanner(int argc, char* argv[])
//Create application
QApplication *application = init_qt(argc, argv);

//Initialize taskbar
Taskbar::init();

//Create main window
MainWindow *mainWindow = new MainWindow();
mainWindow->show();
Expand All @@ -117,6 +121,9 @@ static int double_file_scanner(int argc, char* argv[])
delete mainWindow;
delete application;

//Uninitialize taskbar
Taskbar::uninit();

return EXIT_SUCCESS;
}

Expand Down
2 changes: 2 additions & 0 deletions src/System.cpp
Expand Up @@ -130,6 +130,8 @@ void initConsole(void)
}
}
}

_InterlockedExchange(&g_consoleLock, 0L);
}

void printConsole(const char* text, const int &logLevel)
Expand Down
203 changes: 203 additions & 0 deletions src/Taskbar.cpp
@@ -0,0 +1,203 @@
///////////////////////////////////////////////////////////////////////////////
// Double File Scanner
// Copyright (C) 2014 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version, but always including the *additional*
// restrictions defined in the "License.txt" file.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////

#include "Taskbar.h"
#include "Config.h"

#include <QWidget>
#include <QIcon>
#include <QMutexLocker>

//Windows includes
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <ShObjIdl.h>

class TaskbarData
{
friend class Taskbar;

protected:
TaskbarData(void)
{
winMsg = 0;
ptbl = NULL;
}

UINT winMsg;
ITaskbarList3 *ptbl;
};

QMutex Taskbar::s_lock;
TaskbarData *Taskbar::s_data = NULL;

//===================================================================
// Constructor & Destructor
//===================================================================

Taskbar::Taskbar(void)
{
throw std::runtime_error("Cannot create instance of this class!");
}

Taskbar::~Taskbar(void)
{
}

//===================================================================
// Public Functions
//===================================================================

void Taskbar::init(void)
{
QMutexLocker lock(&s_lock);

if(!s_data)
{
s_data = new TaskbarData();
s_data->winMsg = RegisterWindowMessageW(L"TaskbarButtonCreated");

if(s_data->winMsg == 0)
{
qWarning("RegisterWindowMessageW has failed!");
}
}
}

void Taskbar::uninit(void)
{
QMutexLocker lock(&s_lock);

if(s_data)
{
if(s_data->ptbl)
{
s_data->ptbl->Release();
s_data->ptbl = NULL;
}
MY_DELETE(s_data);
}
}

bool Taskbar::handleWinEvent(void *message, long *result)
{
QMutexLocker lock(&s_lock);
bool stopEvent = false;

if(s_data && (s_data->winMsg != 0))
{
if(((MSG*)message)->message == s_data->winMsg)
{
if(!s_data->ptbl) createInterface();
*result = (s_data->ptbl) ? S_OK : S_FALSE;
stopEvent = true;
}
}

return stopEvent;
}

bool Taskbar::setTaskbarState(QWidget *window, TaskbarState state)
{
QMutexLocker lock(&s_lock);
bool result = false;

if(s_data && s_data->ptbl && window)
{
HRESULT hr = HRESULT(-1);

switch(state)
{
case TaskbarNoState:
hr = s_data->ptbl->SetProgressState(reinterpret_cast<HWND>(window->winId()), TBPF_NOPROGRESS);
break;
case TaskbarNormalState:
hr = s_data->ptbl->SetProgressState(reinterpret_cast<HWND>(window->winId()), TBPF_NORMAL);
break;
case TaskbarIndeterminateState:
hr = s_data->ptbl->SetProgressState(reinterpret_cast<HWND>(window->winId()), TBPF_INDETERMINATE);
break;
case TaskbarErrorState:
hr = s_data->ptbl->SetProgressState(reinterpret_cast<HWND>(window->winId()), TBPF_ERROR);
break;
case TaskbarPausedState:
hr = s_data->ptbl->SetProgressState(reinterpret_cast<HWND>(window->winId()), TBPF_PAUSED);
break;
}

result = SUCCEEDED(hr);
}

return result;
}

void Taskbar::setTaskbarProgress(QWidget *window, unsigned __int64 currentValue, unsigned __int64 maximumValue)
{
QMutexLocker lock(&s_lock);

if(s_data && s_data->ptbl && window)
{
s_data->ptbl->SetProgressValue(reinterpret_cast<HWND>(window->winId()), currentValue, maximumValue);
}
}

void Taskbar::setOverlayIcon(QWidget *window, QIcon *icon)
{
QMutexLocker lock(&s_lock);

if(s_data && s_data->ptbl && window)
{
s_data->ptbl->SetOverlayIcon(window->winId(), (icon ? icon->pixmap(16,16).toWinHICON() : NULL), L"DoubeFileScanner");
}
}

//===================================================================
// Private Functions
//===================================================================

void Taskbar::createInterface(void)
{
if(s_data && (!s_data->ptbl))
{
ITaskbarList3 *ptbl = NULL;
const HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&ptbl));

if(SUCCEEDED(hr))
{
const HRESULT hr2 = ptbl->HrInit();
if(SUCCEEDED(hr2))
{
s_data->ptbl = ptbl;
}
else
{
ptbl->Release();
qWarning("ITaskbarList3::HrInit() has failed!");
}
}
else
{
qWarning("ITaskbarList3 could not be created!");
}
}
}
60 changes: 60 additions & 0 deletions src/Taskbar.h
@@ -0,0 +1,60 @@
///////////////////////////////////////////////////////////////////////////////
// Double File Scanner
// Copyright (C) 2014 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version, but always including the *additional*
// restrictions defined in the "License.txt" file.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////

#pragma once

#include <QMutex>

class QWidget;
class QIcon;
class TaskbarData;

class Taskbar
{
public:
Taskbar(void);
~Taskbar(void);

//Taskbar states
enum TaskbarState
{
TaskbarNoState = 0,
TaskbarNormalState = 1,
TaskbarIndeterminateState = 2,
TaskbarPausedState = 3,
TaskbarErrorState = 4
};

//Public interface
static bool handleWinEvent(void *message, long *result);
static bool setTaskbarState(QWidget *window, TaskbarState state);
static void setTaskbarProgress(QWidget *window, unsigned __int64 currentValue, unsigned __int64 maximumValue);
static void setOverlayIcon(QWidget *window, QIcon *icon);

static void init(void);
static void uninit(void);

private:
static void createInterface(void);
static QMutex s_lock;
static TaskbarData *s_data;
};

0 comments on commit be5649f

Please sign in to comment.