Add Windows implementation of updater dialog

The Windows implementation uses Win++, a thin header-only wrapper
 around the Windows API
This commit is contained in:
Robert Knight 2011-08-23 19:53:03 +01:00
parent 214f2273b9
commit 5cd7d22192
4 changed files with 256 additions and 5 deletions

View file

@ -32,6 +32,9 @@ endif()
if (APPLE)
set(SOURCES ${SOURCES} UpdateDialogCocoa.mm)
endif()
if (WIN32)
set(SOURCES ${SOURCES} UpdateDialogWin32.cpp)
endif()
set (HEADERS
Dir.h
@ -47,7 +50,10 @@ if (ENABLE_GTK)
set(HEADERS ${HEADERS} UpdateDialogGtk.h)
endif()
if (APPLE)
set(SOURCES ${SOURCES} UpdateDialogCocoa.h)
set(HEADERS ${HEADERS} UpdateDialogCocoa.h)
endif()
if (WIN32)
set(HEADERS ${HEADERS} UpdateDialogWin32.h)
endif()
add_library(updatershared

187
src/UpdateDialogWin32.cpp Normal file
View file

@ -0,0 +1,187 @@
#include "UpdateDialogWin32.h"
#include "Log.h"
// enable themed controls
// see http://msdn.microsoft.com/en-us/library/bb773175%28v=vs.85%29.aspx
// for details
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
static const char* updateDialogClassName = "UPDATEDIALOG";
static std::map<HWND,UpdateDialogWin32*> windowDialogMap;
// enable the standard Windows font for a widget
// (typically Tahoma or Segoe UI)
void setDefaultFont(HWND window)
{
SendMessage(window, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));
}
LRESULT WINAPI updateDialogWindowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
std::map<HWND,UpdateDialogWin32*>::const_iterator iter = windowDialogMap.find(window);
if (iter != windowDialogMap.end())
{
return iter->second->windowProc(window,message,wParam,lParam);
}
else
{
return DefWindowProc(window,message,wParam,lParam);
}
};
void registerWindowClass()
{
WNDCLASSEX wcex;
ZeroMemory(&wcex,sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
HBRUSH background = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = updateDialogWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(0,IDC_ARROW);
wcex.hbrBackground = (HBRUSH)background;
wcex.lpszMenuName = (LPCTSTR)0;
wcex.lpszClassName = updateDialogClassName;
wcex.hIconSm = 0;
wcex.hInstance = GetModuleHandle(0);
RegisterClassEx(&wcex);
}
UpdateDialogWin32::UpdateDialogWin32()
{
registerWindowClass();
}
UpdateDialogWin32::~UpdateDialogWin32()
{
for (std::map<HWND,UpdateDialogWin32*>::iterator iter = windowDialogMap.begin();
iter != windowDialogMap.end();
iter++)
{
if (iter->second == this)
{
std::map<HWND,UpdateDialogWin32*>::iterator oldIter = iter;
++iter;
windowDialogMap.erase(oldIter);
}
else
{
++iter;
}
}
}
void UpdateDialogWin32::init()
{
int width = 300;
int height = 130;
DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
m_window.CreateEx(0 /* dwExStyle */,
updateDialogClassName /* class name */,
"Mendeley Updater",
style,
0, 0, width, height,
0 /* parent */, 0 /* menu */, 0 /* reserved */);
m_progressBar.Create(&m_window);
m_finishButton.Create(&m_window);
m_progressLabel.Create(&m_window);
installWindowProc(&m_window);
installWindowProc(&m_finishButton);
setDefaultFont(m_progressLabel);
setDefaultFont(m_finishButton);
m_progressBar.SetRange(0,100);
m_finishButton.SetWindowText("Finish");
m_finishButton.EnableWindow(false);
m_progressLabel.SetWindowText("Installing Updates");
m_window.SetWindowPos(0,0,0,width,height,0);
m_progressBar.SetWindowPos(0,10,40,width - 30,20,0);
m_progressLabel.SetWindowPos(0,10,15,width - 30,20,0);
m_finishButton.SetWindowPos(0,width-100,70,80,25,0);
m_window.CenterWindow();
m_window.ShowWindow();
}
void UpdateDialogWin32::exec()
{
m_app.Run();
}
void UpdateDialogWin32::updateError(const std::string& errorMessage)
{
}
bool UpdateDialogWin32::updateRetryCancel(const std::string& message)
{
return false;
}
void UpdateDialogWin32::updateProgress(int percentage)
{
Message* message = new Message(Message::UpdateProgress);
message->progress = percentage;
SendNotifyMessage(m_window.GetHwnd(),WM_USER,reinterpret_cast<WPARAM>(message),0);
}
void UpdateDialogWin32::updateFinished()
{
Message* message = new Message(Message::UpdateFinished);
SendNotifyMessage(m_window.GetHwnd(),WM_USER,reinterpret_cast<WPARAM>(message),0);
}
LRESULT WINAPI UpdateDialogWin32::windowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
if (reinterpret_cast<HWND>(lParam) == m_finishButton.GetHwnd())
{
PostQuitMessage(0);
}
}
break;
case WM_USER:
{
if (window == m_window.GetHwnd())
{
Message* message = reinterpret_cast<Message*>(wParam);
switch (message->type)
{
case Message::UpdateFailed:
break;
case Message::UpdateProgress:
m_progressBar.SetPos(message->progress);
break;
case Message::UpdateFinished:
m_finishButton.EnableWindow(true);
m_progressLabel.SetWindowText("Updates installed. Click 'Finish' to restart the application.");
break;
}
delete message;
}
}
break;
}
return DefWindowProc(window,message,wParam,lParam);
}
void UpdateDialogWin32::installWindowProc(CWnd* window)
{
windowDialogMap[window->GetHwnd()] = this;
}

View file

@ -1,7 +1,56 @@
#pragma once
class UpdateDialogWin32
#include "Platform.h"
#include "UpdateObserver.h"
#include "wincore.h"
#include "controls.h"
#include "stdcontrols.h"
class UpdateDialogWin32 : public UpdateObserver
{
// TODO - UI for update dialog on Windows
public:
UpdateDialogWin32();
~UpdateDialogWin32();
void init();
void exec();
// implements UpdateObserver
virtual void updateError(const std::string& errorMessage);
virtual bool updateRetryCancel(const std::string& message);
virtual void updateProgress(int percentage);
virtual void updateFinished();
LRESULT WINAPI windowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
private:
struct Message
{
enum Type
{
UpdateFailed,
UpdateProgress,
UpdateFinished
};
Message(Type _type)
: type(_type)
, progress(0)
{
}
Type type;
std::string message;
int progress;
};
void installWindowProc(CWnd* window);
CWinApp m_app;
CWnd m_window;
CStatic m_progressLabel;
CProgressBar m_progressBar;
CButton m_finishButton;
};

View file

@ -14,6 +14,10 @@
#include "UpdateDialogCocoa.h"
#endif
#if defined(PLATFORM_WINDOWS)
#include "UpdateDialogWin32.h"
#endif
#include <iostream>
void runWithUi(int argc, char** argv, UpdateInstaller* installer);
@ -118,7 +122,12 @@ void runWithUi(int argc, char** argv, UpdateInstaller* installer)
#ifdef PLATFORM_WINDOWS
void runWithUi(int argc, char** argv, UpdateInstaller* installer)
{
// TODO - Windows UI
installer->run();
UpdateDialogWin32 dialog;
installer->setObserver(&dialog);
dialog.init();
tthread::thread updaterThread(runUpdaterThread,installer);
dialog.exec();
updaterThread.join();
installer->restartMainApp();
}
#endif