#include "UpdateDialogWin32.h" #include "AppInfo.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 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::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 = LoadIcon(GetModuleHandle(0),"IDI_APPICON"); 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() : m_hadError(false) { registerWindowClass(); } UpdateDialogWin32::~UpdateDialogWin32() { for (std::map::iterator iter = windowDialogMap.begin(); iter != windowDialogMap.end(); iter++) { if (iter->second == this) { std::map::iterator oldIter = iter; ++iter; windowDialogMap.erase(oldIter); } else { ++iter; } } } void UpdateDialogWin32::init(int /* argc */, char** /* argv */) { int width = 400; int height = 150; DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; m_window.CreateEx(0 /* dwExStyle */, updateDialogClassName /* class name */, AppInfo::name().c_str(), 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) { UpdateMessage* message = new UpdateMessage(UpdateMessage::UpdateFailed); message->message = errorMessage; SendNotifyMessage(m_window.GetHwnd(),WM_USER,reinterpret_cast(message),0); } void UpdateDialogWin32::updateProgress(int percentage) { UpdateMessage* message = new UpdateMessage(UpdateMessage::UpdateProgress); message->progress = percentage; SendNotifyMessage(m_window.GetHwnd(),WM_USER,reinterpret_cast(message),0); } void UpdateDialogWin32::updateFinished() { UpdateMessage* message = new UpdateMessage(UpdateMessage::UpdateFinished); SendNotifyMessage(m_window.GetHwnd(),WM_USER,reinterpret_cast(message),0); UpdateDialog::updateFinished(); } void UpdateDialogWin32::quit() { PostThreadMessage(GetWindowThreadProcessId(m_window.GetHwnd(), 0 /* process ID */), WM_QUIT, 0, 0); } LRESULT WINAPI UpdateDialogWin32::windowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CLOSE: if (window == m_window.GetHwnd()) { return 0; } break; case WM_COMMAND: { if (reinterpret_cast(lParam) == m_finishButton.GetHwnd()) { quit(); } } break; case WM_USER: { if (window == m_window.GetHwnd()) { UpdateMessage* message = reinterpret_cast(wParam); switch (message->type) { case UpdateMessage::UpdateFailed: { m_hadError = true; std::string text = AppInfo::updateErrorMessage(message->message); MessageBox(m_window.GetHwnd(),text.c_str(),"Update Problem",MB_OK); } break; case UpdateMessage::UpdateProgress: m_progressBar.SetPos(message->progress); break; case UpdateMessage::UpdateFinished: { std::string message; m_finishButton.EnableWindow(true); if (m_hadError) { message = "Update failed."; } else { message = "Updates installed."; } message += " Click 'Finish' to restart the application."; m_progressLabel.SetWindowText(message.c_str()); } break; } delete message; } } break; } return DefWindowProc(window,message,wParam,lParam); } void UpdateDialogWin32::installWindowProc(CWnd* window) { windowDialogMap[window->GetHwnd()] = this; }