├── .gitattributes ├── .gitignore ├── AutoUpdate.cpp ├── AutoUpdate.h ├── AutoUpdate.rc ├── AutoUpdate.sln ├── AutoUpdate.vcxproj ├── AutoUpdate.vcxproj.filters ├── AutoUpdateDlg.cpp ├── AutoUpdateDlg.h ├── FileMD5.cpp ├── InternetGetFile.cpp ├── InternetGetFile.h ├── MultiLanguage.h ├── RButton.cpp ├── RButton.h ├── RDialog.cpp ├── RDialog.h ├── README.md ├── RMessageBox.cpp ├── RMessageBox.h ├── ReadMe.txt ├── StdAfx.cpp ├── StdAfx.h ├── UISkinManager.cpp ├── UISkinManager.h ├── UpdateConfig.ini ├── UpdateThread.cpp ├── UpdateThread.h ├── md5.cpp ├── md5.h ├── res ├── AutoUpdate.ico ├── AutoUpdate.rc2 ├── button01.bmp ├── button_system_control.bmp └── title01.bmp └── resource.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | -------------------------------------------------------------------------------- /AutoUpdate.cpp: -------------------------------------------------------------------------------- 1 | // AutoUpdate.cpp : Defines the class behaviors for the application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "AutoUpdate.h" 6 | #include "InternetGetFile.h" 7 | #include "UISkinManager.h" 8 | #include "RMessageBox.h" 9 | #include "AutoUpdateDlg.h" 10 | #include "tlhelp32.h" 11 | 12 | #ifdef _DEBUG 13 | #define new DEBUG_NEW 14 | #undef THIS_FILE 15 | static char THIS_FILE[] = __FILE__; 16 | #endif 17 | 18 | // 全局字符串常量表数组(数组初始化在InitStringTable()函数中进行) 19 | struct StringStru g_String[STRING_BOTTOM]; 20 | 21 | // 全局语言代码(不可随意修改其值,否则会导致程序异常!) 22 | enum enLANGUAGE g_LanguageID; 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | // CAutoUpdateApp 26 | 27 | BEGIN_MESSAGE_MAP(CAutoUpdateApp, CWinApp) 28 | //{{AFX_MSG_MAP(CAutoUpdateApp) 29 | // NOTE - the ClassWizard will add and remove mapping macros here. 30 | // DO NOT EDIT what you see in these blocks of generated code! 31 | //}}AFX_MSG 32 | ON_COMMAND(ID_HELP, CWinApp::OnHelp) 33 | END_MESSAGE_MAP() 34 | 35 | ///////////////////////////////////////////////////////////////////////////// 36 | // CAutoUpdateApp construction 37 | 38 | CAutoUpdateApp::CAutoUpdateApp() 39 | { 40 | // TODO: add construction code here, 41 | // Place all significant initialization in InitInstance 42 | m_bSilenceMode = FALSE; 43 | } 44 | 45 | ///////////////////////////////////////////////////////////////////////////// 46 | // The one and only CAutoUpdateApp object 47 | 48 | CAutoUpdateApp theApp; 49 | 50 | ///////////////////////////////////////////////////////////////////////////// 51 | // CAutoUpdateApp initialization 52 | 53 | BOOL CAutoUpdateApp::InitInstance() 54 | { 55 | // 初始化自绘界面 56 | CUISkinManager::Init(); 57 | 58 | // 初始化全局字符串常量表数组 59 | InitStringTable(); 60 | 61 | // 处理命令行 62 | if (!ParseCommandLine()) 63 | { 64 | // 清理自绘界面 65 | CUISkinManager::Uninit(); 66 | return FALSE; 67 | } 68 | 69 | // 检查程序是否已经在运行,如是则直接退出 70 | if (IsAppRunning()) 71 | { 72 | return FALSE; 73 | } 74 | 75 | AfxEnableControlContainer(); 76 | 77 | // Standard initialization 78 | // If you are not using these features and wish to reduce the size 79 | // of your final executable, you should remove from the following 80 | // the specific initialization routines you do not need. 81 | 82 | #ifdef _AFXDLL 83 | Enable3dControls(); // Call this when using MFC in a shared DLL 84 | #else 85 | Enable3dControlsStatic(); // Call this when linking to MFC statically 86 | #endif 87 | 88 | // 显示主窗口 89 | CAutoUpdateDlg dlg; 90 | m_pMainWnd = &dlg; 91 | dlg.m_sAppName = m_sAppName; 92 | dlg.m_bSilenceMode = m_bSilenceMode; 93 | if (m_bSilenceMode) 94 | { 95 | // 静默方式执行升级 96 | m_pMainWnd = NULL; 97 | dlg.SetConfigFile(GetAppDirectory() + UPDATE_CONFIG_FILENAME); 98 | dlg.DoUpdate(); 99 | } 100 | else 101 | { 102 | int nResponse = dlg.DoModal(); 103 | if (nResponse == IDOK) 104 | { 105 | // TODO: Place code here to handle when the dialog is 106 | // dismissed with OK 107 | } 108 | else if (nResponse == IDCANCEL) 109 | { 110 | // TODO: Place code here to handle when the dialog is 111 | // dismissed with Cancel 112 | } 113 | } 114 | 115 | // 清理自绘界面 116 | CUISkinManager::Uninit(); 117 | 118 | // Since the dialog has been closed, return FALSE so that we exit the 119 | // application, rather than start the application's message pump. 120 | return FALSE; 121 | } 122 | 123 | // 处理命令行 124 | // 返回值为 TRUE 表示要继续运行后面的程序,为 FALSE 表示终止程序运行 125 | BOOL CAutoUpdateApp::ParseCommandLine() 126 | { 127 | CString sParameter; 128 | 129 | // 检查命令行参数 130 | 131 | for (int i = 1; i < __argc; i++) 132 | { 133 | sParameter = __argv[i]; 134 | if (sParameter.Left(strlen(PARA_KEY_APP_NAME)).CompareNoCase(PARA_KEY_APP_NAME) == 0) 135 | { 136 | m_sAppName = sParameter.Mid(strlen(PARA_KEY_APP_NAME)); 137 | } 138 | else if (sParameter.Left(strlen(PARA_KEY_CURRENTVERSION)).CompareNoCase(PARA_KEY_CURRENTVERSION) == 0) 139 | { 140 | m_sVersion = sParameter.Mid(strlen(PARA_KEY_CURRENTVERSION)); 141 | } 142 | else if (sParameter.Left(strlen(PARA_KEY_CHECKURL)).CompareNoCase(PARA_KEY_CHECKURL) == 0) 143 | { 144 | m_sURL = sParameter.Mid(strlen(PARA_KEY_CHECKURL)); 145 | } 146 | else if (sParameter.Left(strlen(PARA_KEY_NOTIFYWINDOW)).CompareNoCase(PARA_KEY_NOTIFYWINDOW) == 0) 147 | { 148 | m_iNotifyWindow = (DWORD)atoi(sParameter.Mid(strlen(PARA_KEY_NOTIFYWINDOW))); 149 | } 150 | else if (sParameter.Left(strlen(PARA_KEY_NOTIFYWINDOWTITLE)).CompareNoCase(PARA_KEY_NOTIFYWINDOWTITLE) == 0) 151 | { 152 | m_sNotifyWindowTitle = sParameter.Mid(strlen(PARA_KEY_NOTIFYWINDOWTITLE)); 153 | } 154 | else if (sParameter.Left(strlen(PARA_KEY_NOTIFYFINISH)).CompareNoCase(PARA_KEY_NOTIFYFINISH) == 0) 155 | { 156 | m_iNotifyFinish = (DWORD)atoi(sParameter.Mid(strlen(PARA_KEY_NOTIFYFINISH))); 157 | } 158 | else if (sParameter.Left(strlen(PARA_KEY_SILENCE)).CompareNoCase(PARA_KEY_SILENCE) == 0) 159 | { 160 | m_bSilenceMode = (sParameter.Mid(strlen(PARA_KEY_SILENCE)) == "1"); 161 | } 162 | else 163 | { 164 | LOG(0, 0, "Invalid parameter : %s", sParameter.GetBuffer(0)); 165 | return FALSE; 166 | } 167 | } 168 | 169 | m_sAppName.TrimLeft(); 170 | m_sAppName.TrimRight(); 171 | if (m_sAppName.IsEmpty()) 172 | { 173 | LOG(0, 0, "Invalid parameters."); 174 | return FALSE; 175 | } 176 | 177 | m_sVersion.TrimLeft(); 178 | m_sVersion.TrimRight(); 179 | if (m_sVersion.IsEmpty()) 180 | { 181 | LOG(0, 0, "Invalid parameters."); 182 | return FALSE; 183 | } 184 | 185 | // 检查升级配置文件,判断是否有新版本的软件可用 186 | if (CheckUpdate()) 187 | { 188 | if (!m_bSilenceMode) 189 | { 190 | CRMessageBox MsgBox; 191 | MsgBox.m_sTitle = m_sAppName + " " + STRING(STR_AUTO_UPDATE, "Auto Update"); 192 | MsgBox.m_sPromptMessage = STRING(STR_PROMPT_NEWER_VERSION_AVAILABLE, "当前有更新版本的软件可用,是否立即升级?"); 193 | MsgBox.m_bOption1 = FALSE; 194 | MsgBox.m_sOptionPromptMessage1 = STRING(STR_OPTION_UPGRADE_IN_BACKGROUND , "继续运行程序,从后台执行升级。"); 195 | MsgBox.m_iType = MB_YESNO + MB_ICONQUESTION; 196 | if (IDOK == MsgBox.DoModal()) 197 | { 198 | m_bSilenceMode = MsgBox.m_bOption1; 199 | 200 | if (MsgBox.m_iID == IDYES) 201 | { 202 | CloseProgram(m_sAppName); // 进入升级,退出主程序,保证安全顺利升级 203 | return TRUE; 204 | } 205 | else 206 | { 207 | return FALSE; 208 | } 209 | } 210 | else 211 | { 212 | return FALSE; 213 | } 214 | } 215 | } 216 | else 217 | { 218 | return FALSE; 219 | } 220 | 221 | return TRUE; 222 | } 223 | 224 | // 从软件网站下载升级配置文件,检查是否有新版本的软件可用 225 | // 返回值为 TRUE 表示有新版本的软件可用 226 | BOOL CAutoUpdateApp::CheckUpdate() 227 | { 228 | CString sConfigFilename = GetAppDirectory() + UPDATE_CONFIG_FILENAME; 229 | 230 | // 从指定的URL下载升级配置文件 231 | if (!m_sURL.IsEmpty()) 232 | { 233 | if (Internet::InternetGetURL(m_sURL.GetBuffer(0), sConfigFilename.GetBuffer(0)) 234 | != Internet::INTERNET_SUCCESS) 235 | { 236 | LOG(0, 0, "Fail to download file %s", m_sURL.GetBuffer(0)); 237 | return FALSE; 238 | } 239 | } 240 | 241 | // 从升级配置文件取得最新软件版本号 242 | CString sKey = "Version"; 243 | const int BUFFER_SIZE = 512; 244 | char acBuffer[BUFFER_SIZE] = {0}; 245 | GetPrivateProfileString(SECTION_UPDATE, sKey.GetBuffer(0), "" 246 | , acBuffer, BUFFER_SIZE, sConfigFilename.GetBuffer(0)); 247 | CString sVersion = (char*)acBuffer; 248 | 249 | // 与当前软件版本号比较以确定是否需要升级 250 | if (sVersion > m_sVersion) 251 | { 252 | return TRUE; 253 | } 254 | else 255 | { 256 | return FALSE; 257 | } 258 | } 259 | 260 | // 初始化全局字符串常量表 261 | void CAutoUpdateApp::InitStringTable(enum enLANGUAGE Language) 262 | { 263 | if (Language < LANGUAGE_BOTTOM) 264 | { 265 | g_LanguageID = Language; 266 | } 267 | else 268 | { 269 | // 根据操作系统语言代码确定程序界面的语言代码 270 | switch (GetSystemDefaultLangID()) 271 | { 272 | case 0x0804: // Chinese (PRC) 273 | case 0x1004: // Chinese (Singapore) 274 | g_LanguageID = LANGUAGE_GB; 275 | break; 276 | case 0x0404: // Chinese (Taiwan) 277 | case 0x0c04: // Chinese (Hong Kong SAR, PRC) 278 | case 0x1404: // Chinese (Macao) 279 | g_LanguageID = LANGUAGE_BIG5; 280 | break; 281 | default: 282 | g_LanguageID = LANGUAGE_ENGLISH; 283 | break; 284 | } 285 | } 286 | 287 | // for test 288 | //g_LanguageID=LANGUAGE_ENGLISH; 289 | 290 | // 初始化全局字符串常量表 291 | 292 | g_String[STR_NULL].Set("", "", ""); 293 | g_String[STR_AUTO_UPDATE].Set("自动升级", "自動升級", "Auto Update"); 294 | g_String[STR_APP_ALREADY_RUNNING].Set("升级程序已经在运行中!", "升級程序已經在運行中", "Auto update program is already running."); // 退出应用程序;提示保存文档\n退出 295 | 296 | g_String[STR_PROMPT_NEWER_VERSION_AVAILABLE].Set("当前有更新版本的软件可用,是否立即升级?", "當前有更新版本的軟件可用,是否立即升級?", "There is a newer version available. Do you want to update right now?"); 297 | g_String[STR_OPTION_UPGRADE_IN_BACKGROUND].Set("后台执行升级", "後臺執行升級", "Run updating in background mode"); 298 | g_String[STR_PROMPT_UPGRADE_READY].Set("升级准备就绪。", "升級準備就緒", "Update is ready. Please press \"Start update\" button to update."); 299 | g_String[STR_PROMPT_FAIL_TO_OPEN_UPDATE_CONFIG_FILE].Set("打开升级配置文件失败,无法执行升级!", "打開升級配置文件失敗,無法執行升級!", "Fail to open update config file. Update is canceled."); 300 | g_String[STR_PROMPT_DOWNLOADING_FILE].Set("正在下载文件 %s", "正在下載文件 %s", "Downloading file %s"); 301 | g_String[STR_TOTAL_UPGRADE_PROGRESS].Set("升级总进度 %d / %d", "升級總進度 %d / %d", "Total progress %d / %d"); 302 | g_String[STR_PROMPT_FAIL_IN_DOWNLOADING_FILES].Set("下载文件 %s 失败!", "下載文件 %s 失敗!", "Fail in downloading file %s!"); 303 | g_String[STR_PROMPT_FAIL_IN_VERIFYING_FILES].Set("校验文件 %s 失败!", "校驗文件 %s 失敗!", "Fail in verifying file %s!"); 304 | g_String[STR_PROMPT_FAIL_IN_UPDATING_FILES].Set("更新文件 %s 失败!", "更新文件 %s 失敗!", "Fail in updating file %s!"); 305 | g_String[STR_PROMPT_FAIL_IN_UPDATING].Set("升级失败!", "升級失敗!", "Fail in updating!"); 306 | g_String[STR_PROMPT_UPGRADE_FINISHED].Set("升级完毕!", "升級完畢!", "Update finished!"); 307 | 308 | g_String[STR_BUTTON_START_UPGRADE].Set("开始升级", "開始升級", "Start update"); 309 | g_String[STR_BUTTON_CANCEL_UPGRADE].Set("取消升级", "取消升級", "Cancel"); 310 | g_String[STR_BUTTON_SUCCESS_UPGRADE].Set("完成升级", "完成升級", "Success update"); 311 | 312 | g_String[STR_BUTTON_OK].Set("确定(&O)", "確定(&O)", "&OK"); 313 | g_String[STR_BUTTON_CANCEL].Set("取消(&C)", "取消(&C)", "&Cancel"); 314 | g_String[STR_BUTTON_ABORT].Set("跳出(&A)", "跳出(&A)", "&Abort"); 315 | g_String[STR_BUTTON_IGANORE].Set("忽略(&I)", "忽略(&I)", "&Ignore"); 316 | g_String[STR_BUTTON_RETRY].Set("重试(&R)", "重試(&R)", "&Retry"); 317 | g_String[STR_BUTTON_CONTINUE].Set("继续(&C)", "繼續(&C)", "&Continue"); 318 | g_String[STR_BUTTON_YES].Set("是(&Y)", "是(&Y)", "&Yes"); 319 | g_String[STR_BUTTON_NO].Set("否(&N)", "否(&N)", "&No"); 320 | g_String[STR_BUTTON_CLOSE].Set("关闭", "關閉", "Close"); 321 | g_String[STR_BUTTON_APPLY].Set("应用(&A)", "應用(&A)", "&Apply"); 322 | 323 | g_String[STR_OTHER].Set("其他", "其他", "Other"); 324 | 325 | g_String[STR_ERROR].Set("错误", "錯誤", "Error"); 326 | g_String[STR_ERROR_MESSAGE].Set("错误:%s", "錯誤:%s", "Error: %s"); 327 | } 328 | 329 | BOOL CAutoUpdateApp::IsAppRunning() 330 | { 331 | // 创建互斥量,防止同时启动多个程序实例 332 | CString sMutex = m_sAppName + "AutoUpdateMutex"; 333 | if (::OpenMutex(MUTEX_ALL_ACCESS, FALSE, sMutex.GetBuffer(0))) 334 | { 335 | return TRUE; 336 | } 337 | else 338 | { 339 | ::CreateMutex(0, FALSE, sMutex.GetBuffer(0)); 340 | return FALSE; 341 | } 342 | } 343 | 344 | void CAutoUpdateApp::CloseProgram(CString strProgram) 345 | { 346 | HANDLE handle; //定义CreateToolhelp32Snapshot系统快照句柄 347 | HANDLE handle1; //定义要结束进程句柄 348 | handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得系统快照句柄 349 | PROCESSENTRY32 *info; //定义PROCESSENTRY32结构字指 350 | //PROCESSENTRY32 结构的 dwSize 成员设置成 sizeof(PROCESSENTRY32) 351 | 352 | info = new PROCESSENTRY32; 353 | info->dwSize = sizeof(PROCESSENTRY32); 354 | //调用一次 Process32First 函数,从快照中获取进程列表 355 | Process32First(handle, info); 356 | //重复调用 Process32Next,直到函数返回 FALSE 为止 357 | while(Process32Next(handle, info) != FALSE) 358 | { 359 | CString strTmp = info->szExeFile; //指向进程名字 360 | //strcmp字符串比较函数同要结束相同 361 | //if(strcmp(c, info->szExeFile) == 0 ) 362 | if (strProgram.CompareNoCase(info->szExeFile) == 0 ) 363 | { 364 | //PROCESS_TERMINATE表示为结束操作打开,FALSE=可继承,info->th32ProcessID=进程ID 365 | handle1 = OpenProcess(PROCESS_TERMINATE, FALSE, info->th32ProcessID); 366 | //结束进程 367 | TerminateProcess(handle1, 0); 368 | } 369 | } 370 | delete info; 371 | 372 | CloseHandle(handle); 373 | } -------------------------------------------------------------------------------- /AutoUpdate.h: -------------------------------------------------------------------------------- 1 | // AutoUpdate.h : main header file for the AUTOUPDATE application 2 | // 3 | 4 | #if !defined(AFX_AUTOUPDATE_H__187D3C3A_DD05_4283_9FCA_1FAF58B23B29__INCLUDED_) 5 | #define AFX_AUTOUPDATE_H__187D3C3A_DD05_4283_9FCA_1FAF58B23B29__INCLUDED_ 6 | 7 | #if _MSC_VER > 1000 8 | #pragma once 9 | #endif // _MSC_VER > 1000 10 | 11 | #ifndef __AFXWIN_H__ 12 | #error include 'stdafx.h' before including this file for PCH 13 | #endif 14 | 15 | #include "resource.h" // main symbols 16 | 17 | #include "MultiLanguage.h" 18 | 19 | // 命令行参数名 20 | #define PARA_KEY_APP_NAME "AppName=" 21 | #define PARA_KEY_CURRENTVERSION "CurrentVersion=" 22 | #define PARA_KEY_CHECKURL "CheckURL=" 23 | #define PARA_KEY_NOTIFYWINDOW "NotifyWindow=" 24 | #define PARA_KEY_NOTIFYWINDOWTITLE "NotifyWindowTitle=" 25 | #define PARA_KEY_NOTIFYFINISH "NotifyFinish=" 26 | #define PARA_KEY_SILENCE "Silence=" 27 | 28 | // 本地保存的升级配置文件名 29 | #define UPDATE_CONFIG_FILENAME "UpdateConfig.ini" 30 | 31 | // 升级配置文件中的区段名 32 | #define SECTION_UPDATE "UPDATE" 33 | #define SECTION_COMMON "COMMON" 34 | #define SECTION_LANGUAGE "LANGUAGE" 35 | 36 | // 上报到界面的升级进度消息 37 | enum 38 | { 39 | NOTIFY_DOWNLOAD_INFO = 1001, // 通知要下载的文件状况 40 | NOTIFY_DOWNLOADED_INFO, // 通知已下载的文件状况 41 | NOTIFY_DOWNLOAD_PROGRESS, // 通知下载单个文件进度 42 | NOTIFY_DOWNLOADING_FILENAME, // 通知正在下载的文件名 43 | NOTIFY_DOWNLOAD_FILE_FAIL, // 通知下载文件失败 44 | NOTIFY_VERIFY_FILE_FAIL, // 通知校验文件失败 45 | NOTIFY_UPDATE_FILE_FAIL, // 通知更新文件失败 46 | NOTIFY_FINISH_UPDATE, // 通知升级完毕消息 47 | }; 48 | 49 | // 升级下载文件状态消息结构 50 | struct DOWNLOAD_INFO_STRU 51 | { 52 | UINT iFileCount; // 合计文件数 53 | UINT iFileSize; // 合计字节数 54 | }; 55 | 56 | // 下载单个文件进度消息结构 57 | struct DOWNLOAD_PROGRESS_STRU 58 | { 59 | UINT iCurrentFileSize; // 当前正在下载的文件的字节数 60 | UINT iCurrentFileFinishedSize; // 当前文件已下载字节数 61 | }; 62 | 63 | ///////////////////////////////////////////////////////////////////////////// 64 | // CAutoUpdateApp: 65 | // See AutoUpdate.cpp for the implementation of this class 66 | // 67 | 68 | class CAutoUpdateApp : public CWinApp 69 | { 70 | public: 71 | CAutoUpdateApp(); 72 | void InitStringTable(enum enLANGUAGE Language = LANGUAGE_BOTTOM); 73 | 74 | // Overrides 75 | // ClassWizard generated virtual function overrides 76 | //{{AFX_VIRTUAL(CAutoUpdateApp) 77 | public: 78 | virtual BOOL InitInstance(); 79 | //}}AFX_VIRTUAL 80 | 81 | // Implementation 82 | 83 | //{{AFX_MSG(CAutoUpdateApp) 84 | // NOTE - the ClassWizard will add and remove member functions here. 85 | // DO NOT EDIT what you see in these blocks of generated code ! 86 | //}}AFX_MSG 87 | DECLARE_MESSAGE_MAP() 88 | 89 | private: 90 | BOOL ParseCommandLine(); // 处理命令行 91 | BOOL IsAppRunning(); 92 | BOOL CheckUpdate(); // 从软件网站下载升级配置文件,检查是否有新版本的软件可用 93 | void CloseProgram(CString strProgram); 94 | 95 | private: 96 | CString m_sAppName; // 应用程序名,用以创建互斥量 97 | CString m_sVersion; // 应用程序的当前版本 98 | CString m_sURL; // 下载升级配置文件的URL 99 | DWORD m_iNotifyWindow; // 升级过程中发送消息的目标窗口句柄 100 | CString m_sNotifyWindowTitle; // 升级过程中发送消息的目标窗口标题 101 | DWORD m_iNotifyFinish; // 升级完毕发送的消息代码 102 | BOOL m_bSilenceMode; // 静默方式执行升级,不显示升级程序界面,只在升级完毕后提醒用户 103 | }; 104 | 105 | ///////////////////////////////////////////////////////////////////////////// 106 | 107 | //{{AFX_INSERT_LOCATION}} 108 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 109 | 110 | #endif // !defined(AFX_AUTOUPDATE_H__187D3C3A_DD05_4283_9FCA_1FAF58B23B29__INCLUDED_) 111 | -------------------------------------------------------------------------------- /AutoUpdate.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuili/AutoUpdate/a8fe3bd4ef4b3b4cef8010bec4fc25a663a5a95e/AutoUpdate.rc -------------------------------------------------------------------------------- /AutoUpdate.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AutoUpdate", "AutoUpdate.vcxproj", "{CBF915DD-73F9-D5B9-A845-0D34125937AC}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {CBF915DD-73F9-D5B9-A845-0D34125937AC}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {CBF915DD-73F9-D5B9-A845-0D34125937AC}.Debug|Win32.Build.0 = Debug|Win32 14 | {CBF915DD-73F9-D5B9-A845-0D34125937AC}.Release|Win32.ActiveCfg = Release|Win32 15 | {CBF915DD-73F9-D5B9-A845-0D34125937AC}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /AutoUpdate.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | MFCProj 19 | 20 | 21 | 22 | Application 23 | Static 24 | MultiByte 25 | 26 | 27 | Application 28 | Static 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | .\Debug\ 45 | .\Debug\ 46 | true 47 | 48 | 49 | .\Release\ 50 | .\Release\ 51 | false 52 | 53 | 54 | 55 | MultiThreadedDebug 56 | Default 57 | false 58 | Disabled 59 | true 60 | Level3 61 | true 62 | EditAndContinue 63 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 64 | .\Debug\ 65 | .\Debug\AutoUpdate.pch 66 | Use 67 | stdafx.h 68 | .\Debug\ 69 | .\Debug\ 70 | EnableFastChecks 71 | 72 | 73 | true 74 | _DEBUG;%(PreprocessorDefinitions) 75 | .\Debug\AutoUpdate.tlb 76 | true 77 | Win32 78 | 79 | 80 | 0x0804 81 | _DEBUG;%(PreprocessorDefinitions) 82 | 83 | 84 | true 85 | .\Debug\AutoUpdate.bsc 86 | 87 | 88 | true 89 | true 90 | Windows 91 | .\Debug\AutoUpdate.exe 92 | wininet.lib;Winmm.lib;Version.lib;%(AdditionalDependencies) 93 | 94 | 95 | 96 | 97 | MultiThreaded 98 | OnlyExplicitInline 99 | true 100 | true 101 | MaxSpeed 102 | true 103 | Level3 104 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 105 | .\Release\ 106 | .\Release\AutoUpdate.pch 107 | Use 108 | stdafx.h 109 | .\Release\ 110 | .\Release\ 111 | 112 | 113 | true 114 | NDEBUG;%(PreprocessorDefinitions) 115 | .\Release\AutoUpdate.tlb 116 | true 117 | Win32 118 | 119 | 120 | 0x0804 121 | NDEBUG;%(PreprocessorDefinitions) 122 | 123 | 124 | true 125 | .\Release\AutoUpdate.bsc 126 | 127 | 128 | true 129 | Windows 130 | .\Release\AutoUpdate.exe 131 | wininet.lib;Winmm.lib;Version.lib;%(AdditionalDependencies) 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | Create 145 | stdafx.h 146 | Create 147 | stdafx.h 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | RC 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /AutoUpdate.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4fc46688-ecc2-4a63-8136-fa58094b2cc6} 6 | cpp;c;cxx;rc;def;r;odl;idl;hpj;bat 7 | 8 | 9 | {3c467eac-09b3-4603-b64f-61f2d8c0dc51} 10 | h;hpp;hxx;hm;inl 11 | 12 | 13 | {ca8e1d72-78af-43e9-a607-1eef2f31b147} 14 | ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | 53 | 54 | Source Files 55 | 56 | 57 | 58 | 59 | Header Files 60 | 61 | 62 | Header Files 63 | 64 | 65 | Header Files 66 | 67 | 68 | Header Files 69 | 70 | 71 | Header Files 72 | 73 | 74 | Header Files 75 | 76 | 77 | Header Files 78 | 79 | 80 | Header Files 81 | 82 | 83 | Header Files 84 | 85 | 86 | Header Files 87 | 88 | 89 | Header Files 90 | 91 | 92 | Header Files 93 | 94 | 95 | 96 | 97 | Resource Files 98 | 99 | 100 | Resource Files 101 | 102 | 103 | Resource Files 104 | 105 | 106 | Resource Files 107 | 108 | 109 | Resource Files 110 | 111 | 112 | Resource Files 113 | 114 | 115 | Resource Files 116 | 117 | 118 | Resource Files 119 | 120 | 121 | Resource Files 122 | 123 | 124 | Resource Files 125 | 126 | 127 | Resource Files 128 | 129 | 130 | Resource Files 131 | 132 | 133 | Resource Files 134 | 135 | 136 | Resource Files 137 | 138 | 139 | Resource Files 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /AutoUpdateDlg.cpp: -------------------------------------------------------------------------------- 1 | // AutoUpdateDlg.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include 6 | #include "AutoUpdate.h" 7 | #include "InternetGetFile.h" 8 | #include "UpdateThread.h" 9 | #include "UISkinManager.h" 10 | #include "AutoUpdateDlg.h" 11 | 12 | #ifdef _DEBUG 13 | #define new DEBUG_NEW 14 | #undef THIS_FILE 15 | static char THIS_FILE[] = __FILE__; 16 | #endif 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // CAboutDlg dialog used for App About 20 | 21 | class CAboutDlg : public CDialog 22 | { 23 | public: 24 | CAboutDlg(); 25 | 26 | // Dialog Data 27 | //{{AFX_DATA(CAboutDlg) 28 | enum { IDD = IDD_ABOUTBOX }; 29 | //}}AFX_DATA 30 | 31 | // ClassWizard generated virtual function overrides 32 | //{{AFX_VIRTUAL(CAboutDlg) 33 | protected: 34 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 35 | //}}AFX_VIRTUAL 36 | 37 | // Implementation 38 | protected: 39 | //{{AFX_MSG(CAboutDlg) 40 | //}}AFX_MSG 41 | DECLARE_MESSAGE_MAP() 42 | }; 43 | 44 | CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 45 | { 46 | //{{AFX_DATA_INIT(CAboutDlg) 47 | //}}AFX_DATA_INIT 48 | } 49 | 50 | void CAboutDlg::DoDataExchange(CDataExchange* pDX) 51 | { 52 | CDialog::DoDataExchange(pDX); 53 | //{{AFX_DATA_MAP(CAboutDlg) 54 | //}}AFX_DATA_MAP 55 | } 56 | 57 | BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 58 | //{{AFX_MSG_MAP(CAboutDlg) 59 | // No message handlers 60 | //}}AFX_MSG_MAP 61 | END_MESSAGE_MAP() 62 | 63 | ///////////////////////////////////////////////////////////////////////////// 64 | // CAutoUpdateDlg dialog 65 | 66 | CAutoUpdateDlg::CAutoUpdateDlg(CWnd* pParent /*=NULL*/) 67 | : CRDialog(CAutoUpdateDlg::IDD, pParent) 68 | { 69 | //{{AFX_DATA_INIT(CAutoUpdateDlg) 70 | m_sPrompt = _T(""); 71 | m_sPromptTotalProgress = _T(""); 72 | m_sProgressBar = _T(""); 73 | m_sTotalProgressBar = _T(""); 74 | m_TotalFileInfo.iFileCount = 0; 75 | m_TotalFileInfo.iFileSize = 0; 76 | m_FinishedFileInfo.iFileCount = 0; 77 | m_FinishedFileInfo.iFileSize = 0; 78 | m_fDownloadPercent = 0.0; 79 | m_bSilenceMode = FALSE; 80 | m_bUserBreak = FALSE; 81 | //}}AFX_DATA_INIT 82 | // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 83 | m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 84 | 85 | m_pUpdateThread = NULL; 86 | } 87 | 88 | void CAutoUpdateDlg::DoDataExchange(CDataExchange* pDX) 89 | { 90 | CDialog::DoDataExchange(pDX); 91 | //{{AFX_DATA_MAP(CAutoUpdateDlg) 92 | DDX_Control(pDX, IDOK, m_btnUpgrade); 93 | DDX_Control(pDX, IDCANCEL, m_btnCancel); 94 | DDX_Text(pDX, IDC_STATIC_PROMPT, m_sPrompt); 95 | DDX_Text(pDX, IDC_STATIC_PROMPT_TOTAL_PROGRESS, m_sPromptTotalProgress); 96 | DDX_Text(pDX, IDC_STATIC_PROGRESS, m_sProgressBar); 97 | DDX_Text(pDX, IDC_STATIC_TOTAL_PROGRESS, m_sTotalProgressBar); 98 | //}}AFX_DATA_MAP 99 | } 100 | 101 | BEGIN_MESSAGE_MAP(CAutoUpdateDlg, CDialog) 102 | //{{AFX_MSG_MAP(CAutoUpdateDlg) 103 | RDIALOG_UI_MESSAGE_MAP 104 | ON_WM_SYSCOMMAND() 105 | ON_WM_QUERYDRAGICON() 106 | ON_MESSAGE(WM_USER, OnUserMessage) 107 | //}}AFX_MSG_MAP 108 | END_MESSAGE_MAP() 109 | 110 | ///////////////////////////////////////////////////////////////////////////// 111 | // CAutoUpdateDlg message handlers 112 | 113 | BOOL CAutoUpdateDlg::OnInitDialog() 114 | { 115 | CRDialog::OnInitDialog(); 116 | 117 | // Add "About..." menu item to system menu. 118 | 119 | // IDM_ABOUTBOX must be in the system command range. 120 | ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 121 | ASSERT(IDM_ABOUTBOX < 0xF000); 122 | 123 | CMenu* pSysMenu = GetSystemMenu(FALSE); 124 | if (pSysMenu != NULL) 125 | { 126 | CString strAboutMenu; 127 | strAboutMenu.LoadString(IDS_ABOUTBOX); 128 | if (!strAboutMenu.IsEmpty()) 129 | { 130 | pSysMenu->AppendMenu(MF_SEPARATOR); 131 | pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 132 | } 133 | } 134 | 135 | // Set the icon for this dialog. The framework does this automatically 136 | // when the application's main window is not a dialog 137 | SetIcon(m_hIcon, TRUE); // Set big icon 138 | SetIcon(m_hIcon, FALSE); // Set small icon 139 | 140 | // TODO: Add extra initialization here 141 | SetWindowText(m_sAppName + " " + STRING(STR_AUTO_UPDATE, "Auto Update")); 142 | m_btnUpgrade.SetWindowText(STRING(STR_BUTTON_START_UPGRADE, "开始升级")); 143 | m_btnCancel.SetWindowText(STRING(STR_BUTTON_CANCEL_UPGRADE, "取消升级")); 144 | m_sPrompt = STRING(STR_PROMPT_UPGRADE_READY, "Upgrade is ready. Please press \"Start upgrade\" button to upgrade."); 145 | UpdateData(FALSE); 146 | if (m_bSilenceMode) 147 | { 148 | ShowWindow(SW_HIDE); 149 | OnOK(); 150 | } 151 | 152 | if (CUISkinManager::m_iCurrentStyle == CUISkinManager::StyleNormal) 153 | { 154 | // 以字符方式显示进度 155 | GetDlgItem(IDC_STATIC_PROGRESS)->ShowWindow(SW_SHOW); 156 | GetDlgItem(IDC_STATIC_TOTAL_PROGRESS)->ShowWindow(SW_SHOW); 157 | } 158 | else 159 | { 160 | // 以图形图显示进度 161 | GetDlgItem(IDC_STATIC_PROGRESS)->ShowWindow(SW_HIDE); 162 | GetDlgItem(IDC_STATIC_TOTAL_PROGRESS)->ShowWindow(SW_HIDE); 163 | } 164 | 165 | return TRUE; // return TRUE unless you set the focus to a control 166 | } 167 | 168 | void CAutoUpdateDlg::OnSysCommand(UINT nID, LPARAM lParam) 169 | { 170 | if ((nID & 0xFFF0) == IDM_ABOUTBOX) 171 | { 172 | CAboutDlg dlgAbout; 173 | dlgAbout.DoModal(); 174 | } 175 | else 176 | { 177 | CDialog::OnSysCommand(nID, lParam); 178 | } 179 | } 180 | 181 | // If you add a minimize button to your dialog, you will need the code below 182 | // to draw the icon. For MFC applications using the document/view model, 183 | // this is automatically done for you by the framework. 184 | 185 | void CAutoUpdateDlg::OnPaint() 186 | { 187 | CRDialog::OnPaint(); 188 | 189 | if (IsIconic()) 190 | { 191 | CPaintDC dc(this); // device context for painting 192 | 193 | SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 194 | 195 | // Center icon in client rectangle 196 | int cxIcon = GetSystemMetrics(SM_CXICON); 197 | int cyIcon = GetSystemMetrics(SM_CYICON); 198 | CRect rect; 199 | GetClientRect(&rect); 200 | int x = (rect.Width() - cxIcon + 1) / 2; 201 | int y = (rect.Height() - cyIcon + 1) / 2; 202 | 203 | // Draw the icon 204 | dc.DrawIcon(x, y, m_hIcon); 205 | } 206 | else 207 | { 208 | CDialog::OnPaint(); 209 | } 210 | 211 | // 重绘进度条 212 | if (m_fTotalDownloadPercent != 0.0) 213 | { 214 | UpdateProgress(m_TotalFileInfo.iFileCount, m_FinishedFileInfo.iFileCount 215 | , m_fTotalDownloadPercent, m_fDownloadPercent); 216 | } 217 | } 218 | 219 | // The system calls this to obtain the cursor to display while the user drags 220 | // the minimized window. 221 | HCURSOR CAutoUpdateDlg::OnQueryDragIcon() 222 | { 223 | return (HCURSOR) m_hIcon; 224 | } 225 | 226 | void CAutoUpdateDlg::OnCancel() 227 | { 228 | m_bUserBreak = TRUE; 229 | if (m_pUpdateThread != NULL) 230 | { 231 | LOG(0, 0, "User cancel upgrade."); 232 | HANDLE hThread = m_pUpdateThread->m_hThread; 233 | m_pUpdateThread->m_bUserBreak = TRUE; 234 | Internet::bInternetGetURLUserBreak = TRUE; 235 | WaitForSingleObject(hThread, 1000); 236 | } 237 | 238 | CDialog::OnCancel(); 239 | } 240 | 241 | void CAutoUpdateDlg::OnOK() 242 | { 243 | // 点击开始升级按钮,执行升级 244 | if (!SetConfigFile(GetAppDirectory() + UPDATE_CONFIG_FILENAME)) 245 | { 246 | RMessageBox(STRING(STR_PROMPT_FAIL_TO_OPEN_UPDATE_CONFIG_FILE, "Fail to open update config file.")); 247 | } 248 | else 249 | { 250 | // 开始升级,禁用按钮,避免重复点击 251 | GetDlgItem(IDOK)->EnableWindow(FALSE); 252 | DoUpdate(); 253 | } 254 | 255 | // CDialog::OnOK(); 256 | } 257 | 258 | // 设置升级配置文件名 259 | BOOL CAutoUpdateDlg::SetConfigFile(CString &sFilename) 260 | { 261 | CFileFind FileFinder; 262 | 263 | if (FileFinder.FindFile(sFilename)) 264 | { 265 | FileFinder.FindNextFile(); 266 | if (!FileFinder.IsDirectory()) 267 | { 268 | m_sConfigFilename = sFilename; 269 | FileFinder.Close(); 270 | return TRUE; 271 | } 272 | FileFinder.Close(); 273 | } 274 | 275 | return FALSE; 276 | } 277 | 278 | BOOL CAutoUpdateDlg::DoUpdate(void) 279 | { 280 | LOG(0, 0, "Start upgrade thread."); 281 | 282 | // 启动升级线程 283 | m_pUpdateThread = new CUpdateThread; 284 | m_pUpdateThread->m_bAutoDelete = TRUE; 285 | m_pUpdateThread->m_sConfigFilename = m_sConfigFilename; 286 | m_pUpdateThread->m_hProgressWindow = m_hWnd; 287 | m_pUpdateThread->CreateThread(); 288 | 289 | return TRUE; 290 | } 291 | 292 | // 处理用户消息 293 | LRESULT CAutoUpdateDlg::OnUserMessage(WPARAM wParam, LPARAM lParam) 294 | { 295 | switch (wParam) 296 | { 297 | case NOTIFY_DOWNLOAD_INFO: // 通知要下载的文件状况 298 | m_TotalFileInfo = *(DOWNLOAD_INFO_STRU*)lParam; 299 | m_fDownloadPercent = 0; 300 | m_fTotalDownloadPercent = 0; 301 | UpdateProgress(m_TotalFileInfo.iFileCount, m_FinishedFileInfo.iFileCount 302 | , m_fTotalDownloadPercent, m_fDownloadPercent); 303 | break; 304 | case NOTIFY_DOWNLOADED_INFO: // 通知已下载的文件状况 305 | m_FinishedFileInfo = *(DOWNLOAD_INFO_STRU*)lParam; 306 | m_fDownloadPercent = 0; 307 | m_fTotalDownloadPercent = float(m_FinishedFileInfo.iFileSize) / m_TotalFileInfo.iFileSize; 308 | UpdateProgress(m_TotalFileInfo.iFileCount, m_FinishedFileInfo.iFileCount 309 | , m_fTotalDownloadPercent, m_fDownloadPercent); 310 | break; 311 | case NOTIFY_DOWNLOAD_PROGRESS: // 通知下载单个文件进度 312 | { 313 | DOWNLOAD_PROGRESS_STRU* pDownloadProgress = (DOWNLOAD_PROGRESS_STRU*)lParam; 314 | m_fDownloadPercent = float(pDownloadProgress->iCurrentFileFinishedSize) / pDownloadProgress->iCurrentFileSize; 315 | m_fTotalDownloadPercent = float(m_FinishedFileInfo.iFileSize + pDownloadProgress->iCurrentFileFinishedSize) / m_TotalFileInfo.iFileSize; 316 | UpdateProgress(m_TotalFileInfo.iFileCount, m_FinishedFileInfo.iFileCount 317 | , m_fTotalDownloadPercent, m_fDownloadPercent); 318 | } 319 | break; 320 | case NOTIFY_DOWNLOADING_FILENAME: // 通知正在下载的文件名 321 | if (lParam != 0) 322 | { 323 | m_sPrompt.Format(STRING(STR_PROMPT_DOWNLOADING_FILE, "Downloading file %s."), (char*)lParam); 324 | } 325 | else 326 | { 327 | m_sPrompt = "Downloading file :"; 328 | } 329 | m_sProgressBar = ""; 330 | UpdateData(FALSE); 331 | break; 332 | case NOTIFY_DOWNLOAD_FILE_FAIL: // 通知下载文件失败 333 | m_sPrompt.Format(STRING(STR_PROMPT_FAIL_IN_DOWNLOADING_FILES, "下载文件 %s 失败!"), (char*)lParam); 334 | m_sProgressBar = ""; 335 | UpdateData(FALSE); 336 | break; 337 | case NOTIFY_VERIFY_FILE_FAIL: // 通知校验文件失败 338 | m_sPrompt.Format(STRING(STR_PROMPT_FAIL_IN_VERIFYING_FILES, "校验文件 %s 失败!"), (char*)lParam); 339 | m_sProgressBar = ""; 340 | UpdateData(FALSE); 341 | break; 342 | case NOTIFY_UPDATE_FILE_FAIL: // 通知更新文件失败 343 | m_sPrompt.Format(STRING(STR_PROMPT_FAIL_IN_UPDATING_FILES, "更新文件 %s 失败!"), (char*)lParam); 344 | m_sProgressBar = ""; 345 | UpdateData(FALSE); 346 | break; 347 | case NOTIFY_FINISH_UPDATE: // 通知升级完毕消息 348 | OnNotifyUpdateFinish((BOOL)lParam); 349 | break; 350 | default: 351 | break; 352 | } 353 | 354 | return TRUE; 355 | } 356 | 357 | // 更新显示下载文件进度 358 | void CAutoUpdateDlg::UpdateProgress(UINT iTotalFileCount, UINT iFinishedFileCount, float fTotalPercent, float fPercent) 359 | { 360 | if (m_hWnd == NULL || m_bSilenceMode || iTotalFileCount == 0) 361 | { 362 | return; 363 | } 364 | 365 | // 绘制进度条 366 | 367 | if (CUISkinManager::m_iCurrentStyle == CUISkinManager::StyleNormal) 368 | { 369 | const int BUFFER_SIZE = 500; 370 | char acBuffer[BUFFER_SIZE] = {0}; 371 | 372 | fPercent *= 100; 373 | if (fPercent < 0) 374 | { 375 | fPercent = 0; 376 | } 377 | if (fPercent > 100) 378 | { 379 | fPercent = 100; 380 | } 381 | if (fPercent < 44) 382 | { 383 | strncpy(acBuffer, ">>>>>>>>>>>>>>>>>>>>>> 100% >>>>>>>>>>>>>>>>>>>>", int(fPercent / 2)); 384 | strncat(acBuffer, " ", 22 - int(fPercent / 2)); 385 | sprintf(acBuffer, "%s %2.1f%% ", acBuffer, fPercent); 386 | } 387 | else 388 | { 389 | strncpy(acBuffer, ">>>>>>>>>>>>>>>>>>>>>> 100% >>>>>>>>>>>>>>>>>>>>", 22); 390 | sprintf(acBuffer, "%s %2.1f%% ", acBuffer, fPercent); 391 | if (fPercent > 56) 392 | { 393 | strncat(acBuffer, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", int(fPercent / 2) - 28); 394 | } 395 | } 396 | m_sProgressBar = acBuffer; 397 | 398 | memset(acBuffer, 0, BUFFER_SIZE); 399 | fTotalPercent *= 100; 400 | if (fTotalPercent < 0) 401 | { 402 | fTotalPercent = 0; 403 | } 404 | if (fTotalPercent > 100) 405 | { 406 | fTotalPercent = 100; 407 | } 408 | if (fTotalPercent < 44) 409 | { 410 | strncpy(acBuffer, ">>>>>>>>>>>>>>>>>>>>>> 100% >>>>>>>>>>>>>>>>>>>>", int(fTotalPercent / 2)); 411 | strncat(acBuffer, " ", 22 - int(fTotalPercent / 2)); 412 | sprintf(acBuffer, "%s %2.1f%% ", acBuffer, fTotalPercent); 413 | } 414 | else 415 | { 416 | strncpy(acBuffer, ">>>>>>>>>>>>>>>>>>>>>> 100% >>>>>>>>>>>>>>>>>>>>", 22); 417 | sprintf(acBuffer, "%s %2.1f%% ", acBuffer, fTotalPercent); 418 | if (fTotalPercent > 56) 419 | { 420 | strncat(acBuffer, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", int(fTotalPercent / 2) - 28); 421 | } 422 | } 423 | m_sTotalProgressBar = acBuffer; 424 | 425 | m_sPromptTotalProgress.Format(STRING(STR_TOTAL_UPGRADE_PROGRESS, "升级总进度 %d / %d") 426 | , iFinishedFileCount >= iTotalFileCount ? iTotalFileCount : iFinishedFileCount + 1 427 | , iTotalFileCount); 428 | 429 | UpdateData(FALSE); 430 | 431 | return; 432 | } 433 | else 434 | { 435 | CDC *pDC = GetDC(); 436 | CRect rcWnd; 437 | CRect rc, rc2; 438 | 439 | GetClientRect(&rcWnd); 440 | 441 | // 画进度条外框 442 | rc = rcWnd; 443 | rc.DeflateRect(30, 75, 30, 75); 444 | rc.bottom = rc.top + 18; 445 | pDC->Draw3dRect(&rc, RGB(200, 210, 220), RGB(30, 70, 100)); 446 | rc.DeflateRect(1, 1, 1, 1); 447 | pDC->Draw3dRect(&rc, RGB(140, 160, 180), RGB(90, 120, 180)); 448 | 449 | // 填充进度条背景色 450 | rc.DeflateRect(2, 2, 2, 2); 451 | pDC->FillSolidRect(&rc, RGB(239, 247, 255)); 452 | 453 | // 画进度条 454 | int iTotalWidth = rc.Width(); 455 | int iFinishedWidth = int(iTotalWidth * fPercent); 456 | rc.right = rc.left + iFinishedWidth; 457 | rc2 = rc; 458 | rc.DeflateRect(0, 0, 0, rc.Height() / 2 - 1); 459 | rc2.DeflateRect(0, rc2.Height() / 2 - 1, 0, 0); 460 | CUISkinManager::GradientFillRect(this, pDC, rc, GRADIENT_FILL_RECT_V, RGB(193, 231, 255), RGB(140, 186, 247)); 461 | CUISkinManager::GradientFillRect(this, pDC, rc2, GRADIENT_FILL_RECT_V, RGB(140, 186, 247), RGB(173, 211, 247)); 462 | 463 | m_sPromptTotalProgress.Format(STRING(STR_TOTAL_UPGRADE_PROGRESS, "升级总进度 %d / %d") 464 | , iFinishedFileCount >= iTotalFileCount ? iTotalFileCount : iFinishedFileCount + 1 465 | , iTotalFileCount); 466 | UpdateData(FALSE); 467 | 468 | // 画总进度条外框 469 | rc = rcWnd; 470 | rc.DeflateRect(30, 130, 30, 0); 471 | rc.bottom = rc.top + 18; 472 | pDC->Draw3dRect(&rc, RGB(200, 210, 220), RGB(30, 70, 100)); 473 | rc.DeflateRect(1, 1, 1, 1); 474 | pDC->Draw3dRect(&rc, RGB(140, 160, 180), RGB(90, 120, 180)); 475 | 476 | // 填充总进度条背景色 477 | rc.DeflateRect(2, 2, 2, 2); 478 | pDC->FillSolidRect(&rc, RGB(239, 247, 255)); 479 | 480 | // 画总进度条 481 | iFinishedWidth = int(iTotalWidth * fTotalPercent); 482 | rc.right = rc.left + iFinishedWidth; 483 | rc2 = rc; 484 | rc.DeflateRect(0, 0, 0, rc.Height() / 2 - 1); 485 | rc2.DeflateRect(0, rc2.Height() / 2 - 1, 0, 0); 486 | CUISkinManager::GradientFillRect(this, pDC, rc, GRADIENT_FILL_RECT_V, RGB(193, 231, 255), RGB(140, 186, 247)); 487 | CUISkinManager::GradientFillRect(this, pDC, rc2, GRADIENT_FILL_RECT_V, RGB(140, 186, 247), RGB(173, 211, 247)); 488 | 489 | ReleaseDC(pDC); 490 | } 491 | } 492 | 493 | // 升级程序执行完毕 494 | void CAutoUpdateDlg::OnNotifyUpdateFinish(BOOL bSuccess) 495 | { 496 | m_pUpdateThread = NULL; 497 | 498 | if (m_bSilenceMode) 499 | { 500 | CDialog::OnOK(); 501 | } 502 | else if (bSuccess) 503 | { 504 | m_sPrompt = STRING(STR_PROMPT_UPGRADE_FINISHED, "升级完毕!"); 505 | m_btnCancel.SetWindowText(STRING(STR_BUTTON_SUCCESS_UPGRADE, "完成升级")); 506 | } 507 | else 508 | { 509 | m_sPromptTotalProgress = ""; 510 | m_sTotalProgressBar = ""; 511 | } 512 | 513 | m_sProgressBar = ""; 514 | UpdateData(FALSE); 515 | GetDlgItem(IDOK)->EnableWindow(); 516 | } 517 | -------------------------------------------------------------------------------- /AutoUpdateDlg.h: -------------------------------------------------------------------------------- 1 | // AutoUpdateDlg.h : header file 2 | // 3 | 4 | #if !defined(AFX_AUTOUPDATEDLG_H__4CA1BB40_75FF_4A00_AF96_F141507CE885__INCLUDED_) 5 | #define AFX_AUTOUPDATEDLG_H__4CA1BB40_75FF_4A00_AF96_F141507CE885__INCLUDED_ 6 | 7 | #if _MSC_VER > 1000 8 | #pragma once 9 | #endif // _MSC_VER > 1000 10 | 11 | ///////////////////////////////////////////////////////////////////////////// 12 | // CAutoUpdateDlg dialog 13 | 14 | #include "RDialog.h" 15 | 16 | class CUpdateThread; 17 | 18 | class CAutoUpdateDlg : public CRDialog 19 | { 20 | // Construction 21 | public: 22 | CAutoUpdateDlg(CWnd* pParent = NULL); // standard constructor 23 | BOOL SetConfigFile(CString& sFilename); // 设置配置文件名 24 | BOOL DoUpdate(void); 25 | LRESULT OnUserMessage(WPARAM wParam, LPARAM lParam); 26 | void UpdateProgress(UINT iTotalFileCount, UINT iFinishedFileCount, float fTotalPercent, float fPercent); 27 | void OnNotifyUpdateFinish(BOOL bSuccess = TRUE); 28 | 29 | // Dialog Data 30 | //{{AFX_DATA(CAutoUpdateDlg) 31 | enum { IDD = IDD_AUTOUPDATE }; 32 | CRButton m_btnUpgrade; 33 | CRButton m_btnCancel; 34 | CString m_sAppName; // 应用程序名 35 | CString m_sPrompt; // 下载文件进度提示信息 36 | CString m_sPromptTotalProgress; // 升级总进度提示信息 37 | CString m_sStatus; 38 | CString m_sProgressBar; // 下载文件进度条 39 | CString m_sTotalProgressBar; // 升级总进度条 40 | BOOL m_bSilenceMode; // 静默方式执行升级,不显示升级程序界面,只在升级完毕后提醒用户 41 | BOOL m_bUserBreak; // 用户终止升级 42 | CUpdateThread *m_pUpdateThread; // 执行升级的线程 43 | //}}AFX_DATA 44 | 45 | // ClassWizard generated virtual function overrides 46 | //{{AFX_VIRTUAL(CAutoUpdateDlg) 47 | protected: 48 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 49 | //}}AFX_VIRTUAL 50 | 51 | // Implementation 52 | protected: 53 | CString m_sConfigFilename; // 升级配置文件名 54 | HICON m_hIcon; 55 | 56 | // Generated message map functions 57 | //{{AFX_MSG(CAutoUpdateDlg) 58 | virtual BOOL OnInitDialog(); 59 | afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 60 | afx_msg void OnPaint(); 61 | afx_msg HCURSOR OnQueryDragIcon(); 62 | virtual void OnCancel(); 63 | virtual void OnOK(); 64 | //}}AFX_MSG 65 | DECLARE_MESSAGE_MAP() 66 | 67 | private: 68 | DOWNLOAD_INFO_STRU m_TotalFileInfo; // 要下载的文件总数和大小总和 69 | DOWNLOAD_INFO_STRU m_FinishedFileInfo; // 已下载的文件总数和大小总和 70 | float m_fDownloadPercent; // 当前正在下载的文件进度 71 | float m_fTotalDownloadPercent; // 所有要下载的文件总进度 72 | }; 73 | 74 | //{{AFX_INSERT_LOCATION}} 75 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 76 | 77 | #endif // !defined(AFX_AUTOUPDATEDLG_H__4CA1BB40_75FF_4A00_AF96_F141507CE885__INCLUDED_) 78 | -------------------------------------------------------------------------------- /FileMD5.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuili/AutoUpdate/a8fe3bd4ef4b3b4cef8010bec4fc25a663a5a95e/FileMD5.cpp -------------------------------------------------------------------------------- /InternetGetFile.cpp: -------------------------------------------------------------------------------- 1 | // InternetGetFile.cpp: implementation of the InternetGetFile namespace. 2 | // 3 | ////////////////////////////////////////////////////////////////////// 4 | 5 | #include "stdafx.h" 6 | #include "AutoUpdate.h" 7 | #include 8 | #include 9 | #include 10 | #include "InternetGetFile.h" 11 | 12 | #ifdef _DEBUG 13 | #undef THIS_FILE 14 | static char THIS_FILE[]=__FILE__; 15 | #define new DEBUG_NEW 16 | #endif 17 | 18 | #define INTERNET_CONNECTION_OFFLINE 0x20 19 | //#define NOTIFY_DOWNLOAD_PROGRESS 1003 20 | 21 | BOOL Internet::bInternetGetURLUserBreak = FALSE; 22 | 23 | // 通过HTTP协议从制定网址下载文件并保存到磁盘 24 | // sURL:网址 25 | // sSaveFilename:要保存的本地文件全路径 26 | // sHeader:HTTP请求头信息 27 | // hProgressWindow:接收下载文件进度消息并显示的窗口句柄 28 | int Internet::InternetGetURL(const char* sURL, const char* sSaveFilename, const char* sHeader, HWND hProgressWindow) 29 | { 30 | const int BUFFER_SIZE = 32768; 31 | const int iInterval = 250; 32 | DWORD iFlags; 33 | char sAgent[64]; 34 | HINTERNET hInternet; 35 | HINTERNET hConnect; 36 | char acBuffer[BUFFER_SIZE]; 37 | DWORD iReadBytes; 38 | DWORD iTotalReadBytes = 0; 39 | FILE *pFile = NULL; 40 | DWORD iStartTime; 41 | DWORD iCurrentTime; 42 | DWORD iDuration = 10; 43 | DWORD iLastRefreshTime = 0; 44 | DOWNLOAD_PROGRESS_STRU DownloadProgress = {0}; 45 | DWORD iBytesToRead = 0; 46 | DWORD iReadBytesOfRq = 4; 47 | DWORD iCPUTickStart; 48 | DWORD iCPUTickEnd; 49 | 50 | // Get connection state 51 | InternetGetConnectedState(&iFlags, 0); 52 | if (iFlags & INTERNET_CONNECTION_OFFLINE) // take appropriate steps 53 | { 54 | return INTERNET_ERROR_OPEN; 55 | } 56 | 57 | // Set agent string 58 | _snprintf(sAgent, 64, "Agent%ld", GetTickCount() / 1000); 59 | // Open internet session 60 | if (!(iFlags & INTERNET_CONNECTION_PROXY)) 61 | { 62 | hInternet = InternetOpenA(sAgent, INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, NULL, NULL, 0); 63 | } 64 | else 65 | { 66 | hInternet = InternetOpenA(sAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 67 | } 68 | if (hInternet) 69 | { 70 | if (sHeader == NULL) 71 | { 72 | sHeader = "Accept: */*\r\n\r\n"; 73 | } 74 | 75 | // Get URL 76 | if (!(hConnect = InternetOpenUrlA (hInternet, sURL, sHeader, lstrlenA(sHeader) 77 | , INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, 0))) 78 | { 79 | InternetCloseHandle(hInternet); 80 | return INTERNET_ERROR_OPENURL; 81 | } 82 | 83 | // Open file to write 84 | if (!(pFile = fopen(sSaveFilename, "wb"))) 85 | { 86 | InternetCloseHandle(hInternet); 87 | return INTERNET_ERROR_FILEOPEN; 88 | } 89 | 90 | // Get content size 91 | if (!HttpQueryInfo(hConnect, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER 92 | , (LPVOID)&iBytesToRead, &iReadBytesOfRq, NULL)) 93 | { 94 | iBytesToRead = 0; 95 | } 96 | 97 | DownloadProgress.iCurrentFileSize = iBytesToRead; 98 | 99 | iStartTime = GetTickCount(); 100 | iCPUTickStart = GetTickCount(); 101 | 102 | do 103 | { 104 | if (bInternetGetURLUserBreak) 105 | { 106 | break; 107 | } 108 | 109 | // Keep copying in 16 KB chunks, while file has any data left. 110 | // Note: bigger buffer will greatly improve performance. 111 | if (!InternetReadFile(hConnect, acBuffer, BUFFER_SIZE, &iReadBytes)) 112 | { 113 | fclose(pFile); 114 | InternetCloseHandle(hInternet); 115 | return INTERNET_ERROR_READFILE; 116 | } 117 | if (iReadBytes > 0) 118 | { 119 | // Write to file 120 | fwrite(acBuffer, sizeof(char), iReadBytes, pFile); 121 | } 122 | 123 | iTotalReadBytes += iReadBytes; 124 | 125 | iCurrentTime = GetTickCount(); 126 | iDuration = iCurrentTime - iStartTime; 127 | if (iDuration < 10) 128 | { 129 | iDuration = 10; 130 | } 131 | 132 | if (iBytesToRead > 0 133 | && hProgressWindow != NULL 134 | && iCurrentTime - iLastRefreshTime > iInterval 135 | || iTotalReadBytes == iBytesToRead) 136 | { 137 | // Show progress 138 | iLastRefreshTime = iCurrentTime; 139 | memset(acBuffer, 0, BUFFER_SIZE); 140 | DownloadProgress.iCurrentFileFinishedSize = iTotalReadBytes; 141 | SendMessage(hProgressWindow, WM_USER, (WPARAM)NOTIFY_DOWNLOAD_PROGRESS, (LPARAM)&DownloadProgress); 142 | #ifdef _DEBUG 143 | Sleep(100); // Delay some time to see progress clearly 144 | #endif 145 | } 146 | 147 | if (iReadBytes <= 0) 148 | { 149 | break; // Condition of iReadBytes=0 indicate EOF. Stop. 150 | } 151 | 152 | // 降低资源CPU占用率 153 | iCPUTickEnd = GetTickCount(); 154 | if (iCPUTickEnd - iCPUTickStart > 50) 155 | { 156 | Sleep(iCPUTickEnd - iCPUTickStart); 157 | iCPUTickStart = GetTickCount(); 158 | } 159 | } while (TRUE); 160 | 161 | fflush (pFile); 162 | fclose (pFile); 163 | 164 | InternetCloseHandle(hInternet); 165 | } 166 | else 167 | { 168 | return INTERNET_ERROR_OPEN; 169 | } 170 | 171 | return INTERNET_SUCCESS; 172 | } 173 | -------------------------------------------------------------------------------- /InternetGetFile.h: -------------------------------------------------------------------------------- 1 | // InternetGetFile.h: interface for the InternetGetFile namespace. 2 | // 3 | ////////////////////////////////////////////////////////////////////// 4 | 5 | #pragma once 6 | 7 | #if !defined(INTERNETGETFILE_H) 8 | #define INTERNETGETFILE_H 9 | 10 | namespace Internet 11 | { 12 | enum 13 | { 14 | INTERNET_SUCCESS = 0, 15 | INTERNET_ERROR_OPENURL, 16 | INTERNET_ERROR_FILEOPEN, 17 | INTERNET_ERROR_READFILE, 18 | INTERNET_ERROR_OPEN 19 | }; 20 | 21 | extern BOOL bInternetGetURLUserBreak; // 中断下载标记,置为真则中断下载文件 22 | 23 | // Get URL form internet with inet API 24 | int InternetGetURL(const char* sURL, const char* sSaveFilename, const char* sHeader = NULL, HWND hProgressWindow = NULL); 25 | }; 26 | 27 | #endif // !defined(INTERNETGETFILE_H) 28 | -------------------------------------------------------------------------------- /MultiLanguage.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:MultiLanguage.h 3 | // 文件版本:v1.0 4 | // 创建日期:2006-02-14 11:25 5 | // 作 者:Richard Ree 6 | // 文件描述:实现多语言切换的头文件 7 | //------------------------------------------------------------------------------ 8 | 9 | // 语言ID常量枚举,增加、减少语言时直接修改此枚举定义 10 | enum enLANGUAGE 11 | { 12 | LANGUAGE_GB = 0, 13 | LANGUAGE_BIG5, 14 | LANGUAGE_ENGLISH, 15 | LANGUAGE_BOTTOM 16 | }; 17 | 18 | // 字符串常量ID枚举,增加、减少表达某个语意的字符串时直接修改此枚举定义 19 | enum enSTRING 20 | { 21 | STR_NULL = 0, 22 | STR_AUTO_UPDATE, 23 | STR_APP_ALREADY_RUNNING, 24 | 25 | STR_PROMPT_NEWER_VERSION_AVAILABLE, 26 | STR_OPTION_UPGRADE_IN_BACKGROUND, 27 | STR_PROMPT_UPGRADE_READY, 28 | STR_PROMPT_FAIL_TO_OPEN_UPDATE_CONFIG_FILE, 29 | STR_PROMPT_DOWNLOADING_FILE, 30 | STR_TOTAL_UPGRADE_PROGRESS, 31 | STR_PROMPT_FAIL_IN_DOWNLOADING_FILES, 32 | STR_PROMPT_FAIL_IN_VERIFYING_FILES, 33 | STR_PROMPT_FAIL_IN_UPDATING_FILES, 34 | STR_PROMPT_FAIL_IN_UPDATING, 35 | STR_PROMPT_UPGRADE_FINISHED, 36 | 37 | STR_OTHER, 38 | 39 | STR_BUTTON_START_UPGRADE, 40 | STR_BUTTON_CANCEL_UPGRADE, 41 | STR_BUTTON_SUCCESS_UPGRADE, 42 | 43 | STR_BUTTON_OK, 44 | STR_BUTTON_CANCEL, 45 | STR_BUTTON_ABORT, 46 | STR_BUTTON_IGANORE, 47 | STR_BUTTON_RETRY, 48 | STR_BUTTON_CONTINUE, 49 | STR_BUTTON_YES, 50 | STR_BUTTON_NO, 51 | STR_BUTTON_CLOSE, 52 | STR_BUTTON_APPLY, 53 | 54 | STR_ERROR, 55 | STR_ERROR_MESSAGE, 56 | 57 | STRING_BOTTOM 58 | }; 59 | 60 | // 保存不同语言版本的常量字符串的结构,增加、减少语言时要改写构造函数和Set函数 61 | struct StringStru 62 | { 63 | const char *Language[LANGUAGE_BOTTOM]; // 保存不同语言版本的常量字符串的指针 64 | StringStru() 65 | { 66 | Language[0] = ""; 67 | Language[1] = ""; 68 | Language[2] = ""; 69 | }; 70 | void Set(const char *s1, const char *s2, const char *s3) 71 | { 72 | if (NULL != s1) 73 | { 74 | Language[0] = s1; 75 | } 76 | if (NULL != s2) 77 | { 78 | Language[1] = s2; 79 | } 80 | if (NULL != s3) 81 | { 82 | Language[2] = s3; 83 | } 84 | }; 85 | }; 86 | 87 | // 全局字符串常量表数组(数组初始化在InitStringTable()函数中进行) 88 | extern struct StringStru g_String[STRING_BOTTOM]; 89 | 90 | // 全局语言代码(注意:随意修改其值可能会导致程序异常!) 91 | extern enum enLANGUAGE g_LanguageID; 92 | 93 | // 取得常量字符串的宏定义,STRING_ID为常量字符串ID,PROMPT为任意助记提示字符串,编译时被忽略 94 | #define STRING(STRING_ID, PROMPT) (const char *)(g_String[STRING_ID].Language[g_LanguageID]) 95 | -------------------------------------------------------------------------------- /RButton.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:RButton.h 3 | // 文件版本:v1.0 4 | // 创建日期:2006-05-06 10:39 5 | // 作 者:Richard Ree 6 | // 文件描述:自绘按钮类实现文件 7 | //------------------------------------------------------------------------------ 8 | 9 | #include "stdafx.h" 10 | #include "AutoUpdate.h" 11 | #include "UISkinManager.h" 12 | #include "RButton.h" 13 | 14 | #ifdef _DEBUG 15 | #define new DEBUG_NEW 16 | #undef THIS_FILE 17 | static char THIS_FILE[] = __FILE__; 18 | #endif 19 | 20 | // CRButton 21 | 22 | IMPLEMENT_DYNAMIC(CRButton, CButton) 23 | 24 | CRButton::CRButton(enButtonType iButtonType) 25 | { 26 | m_iButtonType = iButtonType; 27 | m_bTracking = FALSE; 28 | m_bOver = FALSE; 29 | m_bDown = FALSE; 30 | m_bFocus = FALSE; 31 | m_bDefault = FALSE; 32 | } 33 | 34 | CRButton::~CRButton() 35 | { 36 | } 37 | 38 | void CRButton::PreSubclassWindow() 39 | { 40 | CButton::PreSubclassWindow(); 41 | 42 | UINT uStyle = GetButtonStyle(); 43 | if (uStyle == BS_DEFPUSHBUTTON) 44 | { 45 | m_bDefault = TRUE; 46 | } 47 | 48 | ModifyStyle(0, BS_OWNERDRAW); 49 | } 50 | 51 | // 自绘控件 52 | void CRButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 53 | { 54 | CRect rcButton = lpDrawItemStruct->rcItem; 55 | CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); 56 | UINT iState = lpDrawItemStruct->itemState; 57 | 58 | // 获取按钮的状态 59 | m_bFocus = iState & ODS_FOCUS; 60 | m_bDown = iState & ODS_SELECTED; 61 | 62 | // 绘制按钮背景 63 | if (CUISkinManager::m_iCurrentStyle == CUISkinManager::StyleSummer) 64 | { 65 | if (m_iButtonType == ButtonTypeMinimize) 66 | { 67 | // 绘制最小化窗口按钮 68 | DrawSystemControlButtonWithBitmap(pDC->GetSafeHdc(), rcButton 69 | , (HBITMAP)CUISkinManager::m_bmSystemControlButtonImage, m_bDown ? 16 : 0); 70 | return; 71 | } 72 | else if (m_iButtonType == ButtonTypeMaximize) 73 | { 74 | if (GetWindowLong(GetParent()->m_hWnd, GWL_STYLE) & WS_MAXIMIZE) 75 | { 76 | // 绘制最大化窗口按钮 77 | DrawSystemControlButtonWithBitmap(pDC->GetSafeHdc(), rcButton 78 | , (HBITMAP)CUISkinManager::m_bmSystemControlButtonImage, m_bDown ? 48 : 32); 79 | } 80 | else 81 | { 82 | // 绘制还原窗口大小按钮 83 | DrawSystemControlButtonWithBitmap(pDC->GetSafeHdc(), rcButton 84 | , (HBITMAP)CUISkinManager::m_bmSystemControlButtonImage, m_bDown ? 80 : 64); 85 | } 86 | return; 87 | } 88 | else if (m_iButtonType == ButtonTypeClose) 89 | { 90 | // 绘制关闭窗口按钮 91 | DrawSystemControlButtonWithBitmap(pDC->GetSafeHdc(), rcButton 92 | , (HBITMAP)CUISkinManager::m_bmSystemControlButtonImage, m_bDown ? 112 : 96); 93 | return; 94 | } 95 | else if (m_bDefault) 96 | { 97 | DrawItemWithBitmap(pDC->GetSafeHdc(), rcButton, (HBITMAP)CUISkinManager::m_bmButtonImage, 20, 32); 98 | } 99 | else if (m_bOver) 100 | { 101 | DrawItemWithBitmap(pDC->GetSafeHdc(), rcButton, (HBITMAP)CUISkinManager::m_bmButtonImage, 20, 32 * 2); 102 | } 103 | else if (m_bDown) 104 | { 105 | DrawItemWithBitmap(pDC->GetSafeHdc(), rcButton, (HBITMAP)CUISkinManager::m_bmButtonImage, 20, 32 * 3); 106 | } 107 | else 108 | { 109 | DrawItemWithBitmap(pDC->GetSafeHdc(), rcButton, (HBITMAP)CUISkinManager::m_bmButtonImage, 20, 0); 110 | } 111 | } 112 | else // 缺省风格 113 | { 114 | // 内边框 115 | COLORREF crTop, crBottom; 116 | CRect rcOver = rcButton; 117 | rcOver.DeflateRect(1,1); 118 | 119 | if (m_bDefault) 120 | { 121 | crTop = RGB(203, 231, 255); 122 | crBottom = RGB(105, 130, 238); 123 | } 124 | else if (m_bOver) 125 | { 126 | crTop = RGB(255, 240, 207); 127 | crBottom = RGB(229, 151, 0); 128 | } 129 | else if (m_bDown) 130 | { 131 | crTop = RGB(209, 204, 193); 132 | crBottom = RGB(218, 216, 207); 133 | } 134 | else 135 | { 136 | crTop = RGB(254, 254, 254); 137 | crBottom = RGB(234, 245, 255); 138 | } 139 | CUISkinManager::GradientFillRect(this, pDC, rcOver, GRADIENT_FILL_RECT_V, crTop, crBottom); 140 | 141 | // 外边框 142 | CPen pen(PS_SOLID, 1, RGB(200, 210, 240)); // 边框颜色 143 | DrawRoundBorder(pDC, rcButton); 144 | 145 | // 内部填充 146 | if (!m_bDown) 147 | { 148 | CRect rcIn = rcButton; 149 | if (m_bOver || m_bFocus) 150 | { 151 | rcIn.DeflateRect(3,3); 152 | } 153 | else 154 | { 155 | rcIn.DeflateRect(2,2); 156 | } 157 | crTop = RGB(252, 252, 251); 158 | crBottom = RGB(236, 235, 230); 159 | CUISkinManager::GradientFillRect(this, pDC, rcIn, GRADIENT_FILL_RECT_V, crTop, crBottom); 160 | } 161 | } 162 | 163 | rcButton.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE))); 164 | 165 | // 绘制焦点框 166 | if (m_bFocus) 167 | { 168 | CRect rcFoucs = rcButton; 169 | pDC->DrawFocusRect(rcFoucs); 170 | } 171 | 172 | // 绘制按钮标题文本 173 | 174 | CString strTitle; 175 | 176 | GetWindowText(strTitle); 177 | 178 | if (strlen(strTitle) > 0) 179 | { 180 | CFont* hFont = GetFont(); 181 | CFont* hOldFont = pDC->SelectObject(hFont); 182 | // 计算文本显示的宽度 183 | CSize szExtent = pDC->GetTextExtent(strTitle, lstrlen(strTitle)); 184 | if (strstr(strTitle, "&") != 0) 185 | { 186 | // 减去因 '&' 字符被隐藏时的宽度 187 | szExtent.cx -= pDC->GetTextExtent("&").cx; 188 | } 189 | 190 | CPoint pt(rcButton.CenterPoint().x - szExtent.cx / 2, rcButton.CenterPoint().y - szExtent.cy / 2); 191 | if (iState & ODS_SELECTED) 192 | { 193 | pt.Offset(1, 1); 194 | } 195 | int nMode = pDC->SetBkMode(TRANSPARENT); 196 | if (iState & ODS_DISABLED) 197 | { 198 | pDC->DrawState(pt, szExtent, strTitle, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL); 199 | } 200 | else 201 | { 202 | pDC->DrawState(pt, szExtent, strTitle, DSS_NORMAL, TRUE, 0, (HBRUSH)NULL); 203 | } 204 | 205 | pDC->SelectObject(hOldFont); 206 | pDC->SetBkMode(nMode); 207 | } 208 | } 209 | 210 | 211 | BEGIN_MESSAGE_MAP(CRButton, CButton) 212 | ON_WM_SIZE() 213 | ON_WM_MOUSEMOVE() 214 | ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover) 215 | ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave) 216 | END_MESSAGE_MAP() 217 | 218 | 219 | // CRButton 消息处理程序 220 | 221 | 222 | void CRButton::OnMouseMove(UINT nFlags, CPoint point) 223 | { 224 | // TODO: Add your message handler code here and/or call default 225 | if (!m_bTracking) 226 | { 227 | TRACKMOUSEEVENT tms; 228 | tms.cbSize = sizeof(TRACKMOUSEEVENT); 229 | tms.dwFlags = TME_LEAVE|TME_HOVER; 230 | tms.dwHoverTime = 1; 231 | tms.hwndTrack = m_hWnd; 232 | m_bTracking = ::_TrackMouseEvent(&tms); 233 | } 234 | CButton::OnMouseMove(nFlags, point); 235 | } 236 | 237 | LRESULT CRButton::OnMouseHover(WPARAM wParam, LPARAM lParam) 238 | { 239 | m_bOver = TRUE; 240 | InvalidateRect(NULL); 241 | return m_bTracking; 242 | } 243 | 244 | LRESULT CRButton::OnMouseLeave(WPARAM wParam, LPARAM lParam) 245 | { 246 | m_bTracking = FALSE; 247 | m_bOver = FALSE; 248 | InvalidateRect(NULL); 249 | return m_bTracking; 250 | } 251 | 252 | // 以位图方式描绘按钮控件,要求位图宽度为32象素(左15 + 中2 + 右15,中间随着控件宽度拉伸) 253 | // HDC hdcDest:目标设备环境句柄 254 | // CRect& rc:按钮所占的区域(描绘区域) 255 | // HBITMAP hBitMap:位图句柄 256 | // UINT iBitMapHeight:位图高度 257 | // UINT cx:从位图复制的起点位置,按钮处于不同状态(正常、有焦点、鼠标悬停、按下)时对应不同的起点位置 258 | void CRButton::DrawItemWithBitmap(HDC hdcDest, CRect& rc, HBITMAP hBitMap, UINT iBitMapHeight, UINT cx) 259 | { 260 | if (hdcDest == NULL || hBitMap == NULL) 261 | { 262 | return; 263 | } 264 | 265 | HDC hdcSrc = CreateCompatibleDC(hdcDest); 266 | HGDIOBJ hOldGdiObj = SelectObject(hdcSrc, hBitMap); 267 | 268 | TransparentBlt(hdcDest, 0, 0, CUISkinManager::m_iButtonImageLeftPartWidth, rc.Height() 269 | , hdcSrc, cx, 0, CUISkinManager::m_iButtonImageLeftPartWidth, iBitMapHeight 270 | , CUISkinManager::TRANSPARENT_COLOR); 271 | TransparentBlt(hdcDest, CUISkinManager::m_iButtonImageLeftPartWidth, 0 272 | , rc.Width() - CUISkinManager::m_iButtonImageLeftPartWidth + CUISkinManager::m_iButtonImageRightPartWidth, rc.Height() 273 | , hdcSrc, cx + CUISkinManager::m_iButtonImageLeftPartWidth, 0 274 | , CUISkinManager::m_iButtonImageMiddlePartWidth, iBitMapHeight 275 | , CUISkinManager::TRANSPARENT_COLOR); 276 | TransparentBlt(hdcDest 277 | , rc.Width() - CUISkinManager::m_iButtonImageRightPartWidth, 0 278 | , CUISkinManager::m_iButtonImageRightPartWidth, rc.Height() 279 | , hdcSrc 280 | , cx + CUISkinManager::m_iButtonImageLeftPartWidth + CUISkinManager::m_iButtonImageMiddlePartWidth, 0 281 | , CUISkinManager::m_iButtonImageRightPartWidth, iBitMapHeight 282 | , CUISkinManager::TRANSPARENT_COLOR); 283 | 284 | SelectObject(hdcSrc, hOldGdiObj); 285 | DeleteDC(hdcSrc); 286 | } 287 | 288 | // 以位图方式描绘系统控制按钮控件,要求位图宽度为128象素以上 289 | // HDC hdcDest:目标设备环境句柄 290 | // CRect& rc:按钮所占的区域(描绘区域) 291 | // HBITMAP hBitMap:位图句柄 292 | // UINT cx:从位图复制的起点位置 293 | void CRButton::DrawSystemControlButtonWithBitmap(HDC hdcDest, CRect& rc, HBITMAP hBitMap, UINT cx) 294 | { 295 | if (hdcDest == NULL || hBitMap == NULL) 296 | { 297 | return; 298 | } 299 | 300 | HDC hdcSrc = CreateCompatibleDC(hdcDest); 301 | HGDIOBJ hOldGdiObj = SelectObject(hdcSrc, hBitMap); 302 | 303 | TransparentBlt(hdcDest, 0, 0, rc.Width(), rc.Height(), hdcSrc, cx, 0 304 | , CUISkinManager::m_iSystemControlButtonWidth 305 | , CUISkinManager::m_iSystemControlButtonHeight 306 | , CUISkinManager::TRANSPARENT_COLOR); 307 | 308 | SelectObject(hdcSrc, hOldGdiObj); 309 | DeleteDC(hdcSrc); 310 | } 311 | 312 | // 描绘边框 313 | void CRButton::DrawRoundBorder(CDC *pDC, CRect rcBorder) 314 | { 315 | rcBorder.DeflateRect(0, 0, 1, 1); 316 | CPoint pt[] = { 317 | CPoint(rcBorder.left, rcBorder.top + 2), 318 | CPoint(rcBorder.left, rcBorder.bottom - 2), 319 | CPoint(rcBorder.left + 1, rcBorder.bottom - 1), 320 | CPoint(rcBorder.left + 2, rcBorder.bottom), 321 | CPoint(rcBorder.right - 2, rcBorder.bottom), 322 | CPoint(rcBorder.right - 1, rcBorder.bottom - 1), 323 | CPoint(rcBorder.right, rcBorder.bottom - 2), 324 | CPoint(rcBorder.right, rcBorder.top + 2), 325 | CPoint(rcBorder.right - 1, rcBorder.top + 1), 326 | CPoint(rcBorder.right - 2, rcBorder.top), 327 | CPoint(rcBorder.left + 2, rcBorder.top), 328 | CPoint(rcBorder.left + 1, rcBorder.top + 1), 329 | CPoint(rcBorder.left, rcBorder.top + 2) 330 | }; 331 | 332 | BYTE bt[] = { 333 | PT_MOVETO, 334 | PT_LINETO, 335 | PT_LINETO, 336 | PT_LINETO, 337 | PT_LINETO, 338 | PT_LINETO, 339 | PT_LINETO, 340 | PT_LINETO, 341 | PT_LINETO, 342 | PT_LINETO, 343 | PT_LINETO, 344 | PT_LINETO, 345 | PT_LINETO 346 | }; 347 | 348 | pDC->PolyDraw(pt, bt, 13); 349 | } 350 | -------------------------------------------------------------------------------- /RButton.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:RButton.h 3 | // 文件版本:v1.0 4 | // 创建日期:2006-05-06 10:39 5 | // 作 者:Richard Ree 6 | // 文件描述:自绘按钮类 7 | //------------------------------------------------------------------------------ 8 | 9 | #pragma once 10 | 11 | #ifndef RBUTTON_H 12 | #define RBUTTON_H 13 | 14 | // CRButton 15 | 16 | class CRButton : public CButton 17 | { 18 | public: 19 | enum enButtonType 20 | { 21 | ButtonTypeNormal = 0, 22 | ButtonTypeClose, 23 | ButtonTypeMaximize, 24 | ButtonTypeMinimize, 25 | ButtonTypeBottom 26 | }; 27 | 28 | DECLARE_DYNAMIC(CRButton) 29 | 30 | public: 31 | CRButton(enButtonType m_iButtonType = ButtonTypeNormal); 32 | virtual ~CRButton(); 33 | 34 | public: 35 | virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); 36 | 37 | protected: 38 | virtual void PreSubclassWindow(); 39 | 40 | DECLARE_MESSAGE_MAP() 41 | 42 | afx_msg void OnMouseMove(UINT nFlags, CPoint point); 43 | afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam); 44 | afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam); 45 | 46 | protected: 47 | void DrawRoundBorder(CDC *pDC, CRect rcBorder); 48 | // 以位图方式描绘按钮控件,要求位图宽度为32象素(左15 + 中2 + 右15,中间随着控件宽度拉伸) 49 | void DrawItemWithBitmap(HDC hdcDest, CRect& rc, HBITMAP hBitMap, UINT iBitMapHeight, UINT cx); 50 | // 以位图方式描绘系统控制按钮控件,要求位图宽度为128象素以上 51 | void DrawSystemControlButtonWithBitmap(HDC hdcDest, CRect& rc, HBITMAP hBitMap, UINT cx); 52 | 53 | protected: 54 | enum enButtonType m_iButtonType; 55 | BOOL m_bTracking; 56 | BOOL m_bDefault; 57 | BOOL m_bFocus; 58 | BOOL m_bOver; 59 | BOOL m_bDown; 60 | }; 61 | 62 | #endif // #ifndef RBUTTON_H 63 | -------------------------------------------------------------------------------- /RDialog.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:RDialog.cpp 3 | // 文件版本:v1.0 4 | // 创建日期:2006-05-05 16:36 5 | // 作 者:Richard Ree 6 | // 文件描述:自绘对话框类实现文件 7 | //------------------------------------------------------------------------------ 8 | 9 | #include "stdafx.h" 10 | #include "AutoUpdate.h" 11 | #include "UISkinManager.h" 12 | #include "RDialog.h" 13 | 14 | #ifdef _DEBUG 15 | #define new DEBUG_NEW 16 | #undef THIS_FILE 17 | static char THIS_FILE[] = __FILE__; 18 | #endif 19 | 20 | // CRDialog 对话框 21 | 22 | IMPLEMENT_DYNAMIC(CRDialog, CDialog) 23 | 24 | CRDialog::CRDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd /*=NULL*/) 25 | : CDialog(lpszTemplateName, pParentWnd) 26 | { 27 | } 28 | 29 | CRDialog::CRDialog(UINT nIDTemplate, CWnd* pParentWnd /*=NULL*/) 30 | : CDialog(nIDTemplate, pParentWnd) 31 | , m_btnMinimize(CRButton::ButtonTypeMinimize) 32 | , m_btnMaximize(CRButton::ButtonTypeMaximize) 33 | , m_btnClose(CRButton::ButtonTypeClose) 34 | { 35 | } 36 | 37 | CRDialog::~CRDialog() 38 | { 39 | } 40 | 41 | BOOL CRDialog::OnInitDialog() 42 | { 43 | CDialog::OnInitDialog(); 44 | 45 | // 创建最小化、自动化、关闭按钮 46 | CRect rcWnd; 47 | CRect rcButton; 48 | 49 | GetClientRect(&rcWnd); 50 | rcButton.SetRect(0, 0, CUISkinManager::m_iSystemControlButtonWidth, CUISkinManager::m_iSystemControlButtonHeight); 51 | rcButton.OffsetRect(rcWnd.Width() - CUISkinManager::m_iLeftMargin - rcButton.Width(), 6); 52 | 53 | m_btnMinimize.Create("", WS_CHILD, rcButton, this, IDC_BUTTON_MINIMIZE); 54 | m_btnMaximize.Create("", WS_CHILD, rcButton, this, IDC_BUTTON_MAXIMIZE); 55 | m_btnClose.Create("", WS_CHILD, rcButton, this, IDC_BUTTON_CLOSE); 56 | 57 | m_btnClose.MoveWindow(rcButton); 58 | rcButton.OffsetRect(-rcButton.Width() - 2, 0); 59 | m_btnMaximize.MoveWindow(rcButton); 60 | rcButton.OffsetRect(-rcButton.Width() - 2, 0); 61 | m_btnMinimize.MoveWindow(rcButton); 62 | 63 | // 显示/隐藏按钮 64 | DWORD iWindowStyle; 65 | 66 | iWindowStyle = GetStyle(); 67 | if (iWindowStyle & WS_MINIMIZEBOX) 68 | { 69 | m_btnMinimize.ShowWindow(SW_SHOW); 70 | } 71 | if (iWindowStyle & WS_MAXIMIZEBOX) 72 | { 73 | m_btnMaximize.ShowWindow(SW_SHOW); 74 | } 75 | // if (iWindowStyle & WS_CLOSE) 76 | // { 77 | m_btnClose.ShowWindow(SW_SHOW); 78 | // } 79 | 80 | return TRUE; // return TRUE unless you set the focus to a control 81 | // 异常: OCX 属性页应返回 FALSE 82 | } 83 | 84 | // 处理命令消息 85 | BOOL CRDialog::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 86 | { 87 | if (nID == IDC_BUTTON_MINIMIZE) 88 | { 89 | OnBnClickedMinimize(); 90 | } 91 | else if (nID == IDC_BUTTON_MAXIMIZE) 92 | { 93 | OnBnClickedMaximize(); 94 | } 95 | else if (nID == IDC_BUTTON_CLOSE) 96 | { 97 | OnBnClickedClose(); 98 | } 99 | 100 | return CDialog::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); 101 | } 102 | 103 | BEGIN_MESSAGE_MAP(CRDialog, CDialog) 104 | // RDIALOG_UI_MESSAGE_MAP 105 | ON_BN_CLICKED(IDC_BUTTON_MINIMIZE, OnBnClickedMinimize) 106 | ON_BN_CLICKED(IDC_BUTTON_MAXIMIZE, OnBnClickedMaximize) 107 | ON_BN_CLICKED(IDC_BUTTON_CLOSE, OnBnClickedClose) 108 | END_MESSAGE_MAP() 109 | 110 | 111 | // CRDialog 消息处理程序 112 | 113 | void CRDialog::OnPaint() 114 | { 115 | if (!IsWindowVisible() || IsIconic()) 116 | { 117 | CDialog::OnPaint(); 118 | return; 119 | } 120 | 121 | CPaintDC dc(this); // device context for painting 122 | // TODO: 在此处添加消息处理程序代码 123 | // 不为绘图消息调用 CDialog::OnPaint() 124 | 125 | CUISkinManager::Paint(this, &dc); 126 | 127 | // 自绘窗口 128 | CUISkinManager::PaintDialogBorder(this, &dc); 129 | 130 | // 重绘按钮 131 | // m_btnMinimize.Invalidate(); 132 | // m_btnMaximize.Invalidate(); 133 | // m_btnClose.Invalidate(); 134 | 135 | return; 136 | } 137 | 138 | void CRDialog::OnSize(UINT nType, int cx, int cy) 139 | { 140 | CDialog::OnSize(nType, cx, cy); 141 | 142 | // 移动按钮 143 | if (m_btnClose.m_hWnd != NULL) 144 | { 145 | CRect rcButton; 146 | m_btnClose.GetWindowRect(&rcButton); 147 | rcButton.OffsetRect(cx - CUISkinManager::m_iLeftMargin - rcButton.Width() - rcButton.left, 6 - rcButton.top); 148 | m_btnClose.MoveWindow(rcButton); 149 | rcButton.OffsetRect(-rcButton.Width() - 2, 0); 150 | m_btnMaximize.MoveWindow(rcButton); 151 | rcButton.OffsetRect(-rcButton.Width() - 2, 0); 152 | m_btnMinimize.MoveWindow(rcButton); 153 | } 154 | 155 | CUISkinManager::SetRgn(this); 156 | } 157 | 158 | HBRUSH CRDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 159 | { 160 | // HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); 161 | 162 | // TODO: 在此更改 DC 的任何属性 163 | 164 | // TODO: 如果默认的不是所需画笔,则返回另一个画笔 165 | // return hbr; 166 | return CUISkinManager::OnCtlColor(pDC, pWnd, nCtlColor); 167 | } 168 | 169 | void CRDialog::OnLButtonDown(UINT nFlags, CPoint point) 170 | { 171 | // 鼠标点击窗口标题栏,发送消息模拟实现拖动窗口的功能 172 | if (point.y <= (LONG)CUISkinManager::m_iTitleBarHeight) 173 | { 174 | SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0); 175 | } 176 | 177 | CDialog::OnLButtonDown(nFlags, point); 178 | } 179 | 180 | // 点击最小化按钮 181 | void CRDialog::OnBnClickedMinimize() 182 | { 183 | // 发送最小化窗口消息 184 | SendMessage(WM_SYSCOMMAND, SC_MINIMIZE); 185 | } 186 | 187 | // 点击最大化按钮 188 | void CRDialog::OnBnClickedMaximize() 189 | { 190 | if (GetWindowLong(m_hWnd, GWL_STYLE) & WS_MAXIMIZE) 191 | { 192 | // 如果当前窗口处于最大化状态,发送恢复窗口大小消息 193 | SendMessage(WM_SYSCOMMAND, SC_RESTORE); 194 | } 195 | else 196 | { 197 | // 发送最大化窗口消息 198 | SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE); 199 | } 200 | } 201 | 202 | // 点击关闭按钮 203 | void CRDialog::OnBnClickedClose() 204 | { 205 | // 发送关闭窗口消息 206 | SendMessage(WM_SYSCOMMAND, SC_CLOSE); 207 | } 208 | -------------------------------------------------------------------------------- /RDialog.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:RDialog.h 3 | // 文件版本:v1.0 4 | // 创建日期:2006-05-05 16:36 5 | // 作 者:Richard Ree 6 | // 文件描述:自绘对话框类 7 | // 使用自绘对话框类派生自定义对话框的步骤是: 8 | // 1、将自定义对话框类的基类由CDialog改为CRDialog 9 | // 2、在派生类的构造函数、对话框初始化函数OnInitDialog等各处,将CDialog改为CRDialog 10 | // 3、在派生类的消息定义BEGIN_MESSAGE_MAP后添加宏RDIALOG_UI_MESSAGE_MAP 11 | //------------------------------------------------------------------------------ 12 | 13 | #pragma once 14 | 15 | #ifndef RDIALOG_H 16 | #define RDIALOG_H 17 | 18 | #include "RButton.h" 19 | 20 | // 实现自绘界面的消息映射宏,将此宏插入到派生类的BEGIN_MESSAGE_MAP后 21 | #define RDIALOG_UI_MESSAGE_MAP\ 22 | ON_WM_PAINT()\ 23 | ON_WM_SIZE()\ 24 | ON_WM_CTLCOLOR()\ 25 | ON_WM_LBUTTONDOWN() 26 | 27 | // CRDialog 对话框 28 | 29 | class CRDialog : public CDialog 30 | { 31 | DECLARE_DYNAMIC(CRDialog) 32 | 33 | public: 34 | // 构造/析构函数 35 | CRDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL); 36 | CRDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL); 37 | virtual ~CRDialog(); 38 | 39 | protected: 40 | virtual BOOL OnInitDialog(); 41 | virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); 42 | 43 | DECLARE_MESSAGE_MAP() 44 | 45 | public: 46 | afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); 47 | afx_msg void OnPaint(); 48 | afx_msg void OnSize(UINT nType, int cx, int cy); 49 | afx_msg void OnBnClickedMinimize(); 50 | afx_msg void OnBnClickedMaximize(); 51 | afx_msg void OnBnClickedClose(); 52 | afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 53 | 54 | protected: 55 | // 最小化按钮 56 | CRButton m_btnMinimize; 57 | // 最大化按钮 58 | CRButton m_btnMaximize; 59 | // 关闭按钮 60 | CRButton m_btnClose; 61 | }; 62 | 63 | #endif // #ifndef RDIALOG_H 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AutoUpdate 2 | ========== 3 | 4 | 自动在线升级源码,暂时只支持http方式升级,可自动先执行升级程序后再执行应用程序。 5 | 6 | -Automatic online upgrade code, can automatically perform the upgrade process after the implementation of applications. 7 | 8 | 1.在你程序开始运行的代码中加入: 9 | 10 | WinExec(PChar('"AutoUpdate.exe" /silence'), SW_SHOW); 11 | 12 | 2.在你程序菜单加一项<自动升级>,其代码为: 13 | 14 | WinExec(PChar('"AutoUpdate.exe"'), SW_SHOW); 15 | 16 | AutoUpdate.ini为自动升级的配置文件 17 | 18 | [AutoUpdate] 19 | 20 | URL=http://www.yourweb/update/AutoUpdate.xml #指定下载的新版本说明文件 21 | 22 | updateAppCaption=smartit IM #要更新的更新界面的程序名称 23 | 24 | checkVerApp=smartitIM.exe #要更新的主程序,以此程序的版本与AutoUpdate.xml中版本对比 25 | 26 | checkVerAppRegRootKey=\Software\smartitIM #若主程序中将当前版本号写入的注册表区,可不配置 27 | 28 | [copyright] 29 | 30 | homepage= #更新界面的连接网址 31 | 32 | licensekey= #注册后可设置你自己的版权信息 33 | 34 | #多语言配置 35 | 36 | [Locale_en] 37 | 38 | [Locale_zh-CN] 39 | 40 | AutoUpdate.xml为批明新版本的下载文件和新版本说明等,大家可参考此格式写自己的更新文件,有两种格式: 41 | 42 | 1.以一个安装程序来更新: 43 | 44 | 45 | 46 | 新版本说明 47 | 48 | 49 | 50 | 2.只更新几个文件的: 51 | 52 | 53 | 54 | 55 | 56 | 新版本说明 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /RMessageBox.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:RMessageBox.cpp 3 | // 文件版本:v1.0 4 | // 创建日期:2006-05-06 04:25 5 | // 作 者:Richard Ree 6 | // 文件描述:自定义消息框类实现文件 7 | //------------------------------------------------------------------------------ 8 | 9 | #include "stdafx.h" 10 | #include "AutoUpdate.h" 11 | #include "RMessageBox.h" 12 | 13 | #ifdef _DEBUG 14 | #define new DEBUG_NEW 15 | #undef THIS_FILE 16 | static char THIS_FILE[] = __FILE__; 17 | #endif 18 | 19 | // CRMessageBox 对话框 20 | 21 | IMPLEMENT_DYNAMIC(CRMessageBox, CDialog) 22 | 23 | CRMessageBox::CRMessageBox(CWnd* pParent /*=NULL*/) 24 | : CRDialog(CRMessageBox::IDD, pParent) 25 | { 26 | m_iID = MB_OK; 27 | m_bOption1 = FALSE; 28 | m_bOption2 = FALSE; 29 | } 30 | 31 | CRMessageBox::~CRMessageBox() 32 | { 33 | } 34 | 35 | void CRMessageBox::DoDataExchange(CDataExchange* pDX) 36 | { 37 | CDialog::DoDataExchange(pDX); 38 | DDX_Control(pDX, IDC_STATIC_ICON, m_stcIcon); 39 | DDX_Control(pDX, IDC_STATIC_PROMPT, m_stcPromptMessage); 40 | DDX_Control(pDX, IDC_CHECK_OPTION1, m_chkOption1); 41 | DDX_Check(pDX, IDC_CHECK_OPTION1, m_bOption1); 42 | DDX_Control(pDX, IDC_CHECK_OPTION2, m_chkOption2); 43 | DDX_Check(pDX, IDC_CHECK_OPTION2, m_bOption2); 44 | DDX_Control(pDX, IDC_BUTTON_OK, m_btnOK); 45 | DDX_Control(pDX, IDC_BUTTON_CANCEL, m_btnCancel); 46 | DDX_Control(pDX, IDC_BUTTON_ABORT, m_btnAbort); 47 | DDX_Control(pDX, IDC_BUTTON_IGANORE, m_btnIganore); 48 | DDX_Control(pDX, IDC_BUTTON_RETRY, m_btnRetry); 49 | DDX_Control(pDX, IDC_BUTTON_CONTINUE, m_btnContinue); 50 | DDX_Control(pDX, IDC_BUTTON_YES, m_btnYes); 51 | DDX_Control(pDX, IDC_BUTTON_NO, m_btnNo); 52 | } 53 | 54 | BOOL CRMessageBox::OnInitDialog() 55 | { 56 | CRDialog::OnInitDialog(); 57 | 58 | // 设置对话框标题 59 | SetWindowText(m_sTitle); 60 | 61 | m_btnOK.SetWindowText(STRING(STR_BUTTON_OK, "确定(&O)")); 62 | m_btnCancel.SetWindowText(STRING(STR_BUTTON_CANCEL, "取消(&C)")); 63 | m_btnAbort.SetWindowText(STRING(STR_BUTTON_ABORT, "跳出(&A)")); 64 | m_btnIganore.SetWindowText(STRING(STR_BUTTON_IGANORE, "忽略(&I)")); 65 | m_btnRetry.SetWindowText(STRING(STR_BUTTON_RETRY, "重试(&R)")); 66 | m_btnContinue.SetWindowText(STRING(STR_BUTTON_CONTINUE, "继续(&C)")); 67 | m_btnYes.SetWindowText(STRING(STR_BUTTON_YES, "是(&Y)")); 68 | m_btnNo.SetWindowText(STRING(STR_BUTTON_NO, "否(&N)")); 69 | 70 | // 判断是否需要显示复选框 71 | if (!m_sOptionPromptMessage1.IsEmpty()) 72 | { 73 | m_chkOption1.SetWindowText(m_sOptionPromptMessage1); 74 | m_chkOption1.ShowWindow(SW_SHOW); 75 | } 76 | else 77 | { 78 | m_chkOption1.ShowWindow(SW_HIDE); 79 | } 80 | if (!m_sOptionPromptMessage2.IsEmpty()) 81 | { 82 | m_chkOption2.SetWindowText(m_sOptionPromptMessage2); 83 | m_chkOption2.ShowWindow(SW_SHOW); 84 | } 85 | else 86 | { 87 | m_chkOption2.ShowWindow(SW_HIDE); 88 | } 89 | 90 | // 图标控件仅作为占位符来用,不显示 91 | m_stcIcon.ShowWindow(SW_HIDE); 92 | 93 | UpdateData(FALSE); 94 | 95 | // 重置对话框大小、按钮位置 96 | ResetMessageBox(); 97 | 98 | return TRUE; // return TRUE unless you set the focus to a control 99 | // 异常: OCX 属性页应返回 FALSE 100 | } 101 | 102 | void CRMessageBox::OnOK() 103 | { 104 | CWnd *pActiveControl = GetFocus(); 105 | if (*pActiveControl == m_btnOK) 106 | { 107 | OnBnClickedOk(); 108 | } 109 | else if (*pActiveControl == m_btnCancel) 110 | { 111 | OnBnClickedCancel(); 112 | } 113 | else if (*pActiveControl == m_btnAbort) 114 | { 115 | OnBnClickedAbort(); 116 | } 117 | else if (*pActiveControl == m_btnIganore) 118 | { 119 | OnBnClickedIganore(); 120 | } 121 | else if (*pActiveControl == m_btnRetry) 122 | { 123 | OnBnClickedRetry(); 124 | } 125 | else if (*pActiveControl == m_btnContinue) 126 | { 127 | OnBnClickedContinue(); 128 | } 129 | else if (*pActiveControl == m_btnYes) 130 | { 131 | OnBnClickedYes(); 132 | } 133 | else if (*pActiveControl == m_btnNo) 134 | { 135 | OnBnClickedNo(); 136 | } 137 | 138 | // CDialog::OnOK(); 139 | } 140 | 141 | void CRMessageBox::OnCancel() 142 | { 143 | // 根据消息框样式对按下ESC键及关闭对话框按钮操作的结果进行修正 144 | switch (m_iType & 0xF) 145 | { 146 | case MB_OK: 147 | m_iID = IDOK; 148 | break; 149 | case MB_OKCANCEL: 150 | m_iID = IDCANCEL; 151 | break; 152 | case MB_YESNO: 153 | m_iID = IDNO; 154 | break; 155 | case MB_YESNOCANCEL: 156 | m_iID = IDCANCEL; 157 | break; 158 | case MB_RETRYCANCEL: 159 | m_iID = IDCANCEL; 160 | break; 161 | // case MB_CANCELTRYCONTINUE: 162 | // m_iID = IDCANCEL; 163 | // break; 164 | case MB_ABORTRETRYIGNORE: 165 | m_iID = IDABORT; 166 | break; 167 | default: 168 | m_iID = IDCANCEL; 169 | break; 170 | } 171 | CDialog::OnCancel(); 172 | } 173 | 174 | 175 | BEGIN_MESSAGE_MAP(CRMessageBox, CDialog) 176 | RDIALOG_UI_MESSAGE_MAP 177 | ON_BN_CLICKED(IDOK, OnOK) 178 | ON_BN_CLICKED(IDCANCEL, OnCancel) 179 | ON_BN_CLICKED(IDC_BUTTON_OK, OnBnClickedOk) 180 | ON_BN_CLICKED(IDC_BUTTON_CANCEL, OnBnClickedCancel) 181 | ON_BN_CLICKED(IDC_BUTTON_ABORT, OnBnClickedAbort) 182 | ON_BN_CLICKED(IDC_BUTTON_IGANORE, OnBnClickedIganore) 183 | ON_BN_CLICKED(IDC_BUTTON_RETRY, OnBnClickedRetry) 184 | ON_BN_CLICKED(IDC_BUTTON_CONTINUE, OnBnClickedContinue) 185 | ON_BN_CLICKED(IDC_BUTTON_YES, OnBnClickedYes) 186 | ON_BN_CLICKED(IDC_BUTTON_NO, OnBnClickedNo) 187 | END_MESSAGE_MAP() 188 | 189 | // CRMessageBox 消息处理程序 190 | 191 | void CRMessageBox::OnPaint() 192 | { 193 | if (!IsWindowVisible() || IsIconic()) 194 | { 195 | CDialog::OnPaint(); 196 | return; 197 | } 198 | 199 | // 绘制窗口 200 | CRDialog::OnPaint(); 201 | 202 | // 显示图标 203 | HICON hIcon; 204 | CRect rcIcon; 205 | POINT point; 206 | 207 | m_stcIcon.GetWindowRect(&rcIcon); 208 | ScreenToClient(&rcIcon); 209 | point.x = rcIcon.left; 210 | point.y = rcIcon.top; 211 | 212 | // 根据消息框类型加载不同的图标 213 | switch (m_iType & 0xF0) 214 | { 215 | case MB_ICONHAND: // MB_ICONERROR/MB_ICONSTOP 216 | hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_HAND)); 217 | break; 218 | case MB_ICONQUESTION: 219 | hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_QUESTION)); 220 | break; 221 | case MB_ICONEXCLAMATION: // MB_ICONWARNING 222 | hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_WARNING)); 223 | break; 224 | case MB_ICONINFORMATION: // MB_ICONASTERISK 225 | hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_INFORMATION)); 226 | break; 227 | case MB_USERICON: 228 | default: 229 | hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_INFORMATION)); 230 | break; 231 | } 232 | 233 | // 画图标 234 | CDC *pDC = GetDC(); 235 | pDC->DrawIcon(point, hIcon); 236 | ReleaseDC(pDC); 237 | } 238 | 239 | void CRMessageBox::OnBnClickedOk() 240 | { 241 | m_iID = IDOK; 242 | 243 | // 隐藏窗口 244 | CDialog::OnOK(); 245 | } 246 | 247 | void CRMessageBox::OnBnClickedCancel() 248 | { 249 | m_iID = IDCANCEL; 250 | 251 | // 隐藏窗口 252 | CDialog::OnOK(); 253 | } 254 | 255 | void CRMessageBox::OnBnClickedAbort() 256 | { 257 | m_iID = IDABORT; 258 | 259 | // 隐藏窗口 260 | CDialog::OnOK(); 261 | } 262 | 263 | void CRMessageBox::OnBnClickedIganore() 264 | { 265 | m_iID = IDIGNORE; 266 | 267 | // 隐藏窗口 268 | CDialog::OnOK(); 269 | } 270 | 271 | void CRMessageBox::OnBnClickedRetry() 272 | { 273 | m_iID = IDRETRY; 274 | 275 | // 隐藏窗口 276 | CDialog::OnOK(); 277 | } 278 | 279 | void CRMessageBox::OnBnClickedContinue() 280 | { 281 | // m_iID = IDCONTINUE; 282 | 283 | // 隐藏窗口 284 | CDialog::OnOK(); 285 | } 286 | 287 | void CRMessageBox::OnBnClickedYes() 288 | { 289 | m_iID = IDYES; 290 | 291 | // 隐藏窗口 292 | CDialog::OnOK(); 293 | } 294 | 295 | void CRMessageBox::OnBnClickedNo() 296 | { 297 | m_iID = IDNO; 298 | 299 | // 隐藏窗口 300 | CDialog::OnOK(); 301 | } 302 | 303 | // 重置消息框样式和外观 304 | void CRMessageBox::ResetMessageBox() 305 | { 306 | // 根据信息的多少重置对话框窗口大小 307 | CRect rcWnd; 308 | CRect rcPromptMessage; 309 | CRect rcButton; 310 | CSize size; 311 | CDC* pDC; 312 | int iOffsetY; // 按钮控件需要在垂直方向上的移位距离 313 | 314 | GetWindowRect(&rcWnd); 315 | 316 | // 根据提示文字的多少计算窗口大小 317 | pDC = m_stcPromptMessage.GetDC(); 318 | size = pDC->GetTextExtent(m_sPromptMessage); 319 | m_stcPromptMessage.ReleaseDC(pDC); 320 | if (size.cx < 200) 321 | { 322 | size.cx = 200; 323 | } 324 | else if (size.cx > 500) 325 | { 326 | size.cy = size.cx / 500 * size.cy; 327 | size.cx = 500; 328 | } 329 | if (size.cy < 32) 330 | { 331 | size.cy = 32; 332 | } 333 | rcWnd.right = rcWnd.left + size.cx + 100; 334 | rcWnd.bottom = rcWnd.top + size.cy + 155; 335 | // 如果要显示复选框,要加上复选框的高度 336 | if (!m_sOptionPromptMessage1.IsEmpty()) 337 | { 338 | rcWnd.bottom += 18; 339 | } 340 | if (!m_sOptionPromptMessage2.IsEmpty()) 341 | { 342 | rcWnd.bottom += 18; 343 | } 344 | 345 | // 将窗口移动到屏幕中间 346 | CRect rcScreen; 347 | ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, 0); // 取得屏幕大小 348 | rcWnd.OffsetRect(rcScreen.CenterPoint() - rcWnd.CenterPoint()); 349 | 350 | MoveWindow(&rcWnd); 351 | 352 | // 重置提示信息标签的大小 353 | m_stcPromptMessage.GetWindowRect(&rcPromptMessage); 354 | ScreenToClient(&rcPromptMessage); 355 | rcPromptMessage.right = rcPromptMessage.left + size.cx; 356 | rcPromptMessage.bottom = rcPromptMessage.top + size.cy + 5; 357 | m_stcPromptMessage.MoveWindow(&rcPromptMessage); 358 | 359 | // 重置复选框控件的大小 360 | m_chkOption1.GetWindowRect(&rcPromptMessage); 361 | ScreenToClient(&rcPromptMessage); 362 | rcPromptMessage.right = rcPromptMessage.left + size.cx; 363 | m_chkOption1.MoveWindow(&rcPromptMessage); 364 | m_chkOption2.GetWindowRect(&rcPromptMessage); 365 | ScreenToClient(&rcPromptMessage); 366 | rcPromptMessage.right = rcPromptMessage.left + size.cx; 367 | m_chkOption2.MoveWindow(&rcPromptMessage); 368 | 369 | // 显示提示信息 370 | m_stcPromptMessage.SetWindowText(m_sPromptMessage); 371 | 372 | // 根据类型显示不同的按钮,并将它们移动到对话框中间 373 | m_btnOK.GetWindowRect(&rcButton); 374 | ScreenToClient(&rcButton); 375 | iOffsetY = rcWnd.Height() - rcButton.top - 48; 376 | switch (m_iType & 0xF) 377 | { 378 | case MB_OK: 379 | m_btnOK.ShowWindow(SW_SHOW); 380 | rcButton.OffsetRect((rcWnd.Width() - rcButton.Width()) / 2 - rcButton.left, iOffsetY); 381 | m_btnOK.MoveWindow(&rcButton); 382 | break; 383 | case MB_OKCANCEL: 384 | m_btnOK.ShowWindow(SW_SHOW); 385 | m_btnCancel.ShowWindow(SW_SHOW); 386 | rcButton.OffsetRect(rcWnd.Width() / 2 - rcButton.Width() - 2 - rcButton.left, iOffsetY); 387 | m_btnOK.MoveWindow(&rcButton); 388 | rcButton.OffsetRect(rcButton.Width() + 4, 0); 389 | m_btnCancel.MoveWindow(&rcButton); 390 | break; 391 | case MB_YESNO: 392 | m_btnYes.ShowWindow(SW_SHOW); 393 | m_btnNo.ShowWindow(SW_SHOW); 394 | rcButton.OffsetRect(rcWnd.Width() / 2 - rcButton.Width() - 2 - rcButton.left, iOffsetY); 395 | m_btnYes.MoveWindow(&rcButton); 396 | rcButton.OffsetRect(rcButton.Width() + 4, 0); 397 | m_btnNo.MoveWindow(&rcButton); 398 | break; 399 | case MB_YESNOCANCEL: 400 | m_btnYes.ShowWindow(SW_SHOW); 401 | m_btnNo.ShowWindow(SW_SHOW); 402 | m_btnCancel.ShowWindow(SW_SHOW); 403 | rcButton.OffsetRect((rcWnd.Width() - rcButton.Width()) / 2 - 2 - rcButton.Width() - rcButton.left, iOffsetY); 404 | m_btnYes.MoveWindow(&rcButton); 405 | rcButton.OffsetRect(rcButton.Width() + 4, 0); 406 | m_btnNo.MoveWindow(&rcButton); 407 | rcButton.OffsetRect(rcButton.Width() + 4, 0); 408 | m_btnCancel.MoveWindow(&rcButton); 409 | break; 410 | case MB_RETRYCANCEL: 411 | m_btnRetry.ShowWindow(SW_SHOW); 412 | m_btnCancel.ShowWindow(SW_SHOW); 413 | rcButton.OffsetRect(rcWnd.Width() / 2 - rcButton.Width() - 2 - rcButton.left, iOffsetY); 414 | m_btnRetry.MoveWindow(&rcButton); 415 | rcButton.OffsetRect(rcButton.Width() + 4, 0); 416 | m_btnCancel.MoveWindow(&rcButton); 417 | break; 418 | // case MB_CANCELTRYCONTINUE: 419 | // m_btnCancel.ShowWindow(SW_SHOW); 420 | // m_btnContinue.ShowWindow(SW_SHOW); 421 | // rcButton.OffsetRect(rcWnd.Width() / 2 - rcButton.Width() - 2 - rcButton.left, iOffsetY); 422 | // m_btnCancel.MoveWindow(&rcButton); 423 | // rcButton.OffsetRect(rcButton.Width() + 4, 0); 424 | // m_btnContinue.MoveWindow(&rcButton); 425 | // break; 426 | case MB_ABORTRETRYIGNORE: 427 | m_btnAbort.ShowWindow(SW_SHOW); 428 | m_btnRetry.ShowWindow(SW_SHOW); 429 | m_btnIganore.ShowWindow(SW_SHOW); 430 | rcButton.OffsetRect((rcWnd.Width() - rcButton.Width()) / 2 - 2 - rcButton.Width() - rcButton.left, iOffsetY); 431 | m_btnAbort.MoveWindow(&rcButton); 432 | rcButton.OffsetRect(rcButton.Width() + 4, 0); 433 | m_btnRetry.MoveWindow(&rcButton); 434 | rcButton.OffsetRect(rcButton.Width() + 4, 0); 435 | m_btnIganore.MoveWindow(&rcButton); 436 | break; 437 | default: 438 | break; 439 | } 440 | 441 | // 图标的显示在OnPaint函数中实现 442 | } 443 | -------------------------------------------------------------------------------- /RMessageBox.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:RMessageBox.h 3 | // 文件版本:v1.0 4 | // 创建日期:2006-05-06 04:25 5 | // 作 者:Richard Ree 6 | // 文件描述:自定义消息框类 7 | //------------------------------------------------------------------------------ 8 | 9 | #pragma once 10 | 11 | #ifndef RMESSAGEBOX_H 12 | #define RMESSAGEBOX_H 13 | 14 | #include "RDialog.h" 15 | #include "RButton.h" 16 | 17 | // CRMessageBox 对话框 18 | 19 | class CRMessageBox : public CRDialog 20 | { 21 | DECLARE_DYNAMIC(CRMessageBox) 22 | 23 | public: 24 | CRMessageBox(CWnd* pParent = NULL); // 标准构造函数 25 | virtual ~CRMessageBox(); 26 | 27 | // 对话框数据 28 | enum { IDD = IDD_MESSAGEBOX }; 29 | 30 | protected: 31 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 32 | virtual BOOL OnInitDialog(); 33 | virtual void OnOK(); 34 | virtual void OnCancel(); 35 | 36 | DECLARE_MESSAGE_MAP() 37 | 38 | protected: 39 | afx_msg void OnPaint(); 40 | afx_msg void OnBnClickedOk(); 41 | afx_msg void OnBnClickedCancel(); 42 | afx_msg void OnBnClickedAbort(); 43 | afx_msg void OnBnClickedIganore(); 44 | afx_msg void OnBnClickedRetry(); 45 | afx_msg void OnBnClickedContinue(); 46 | afx_msg void OnBnClickedYes(); 47 | afx_msg void OnBnClickedNo(); 48 | void ResetMessageBox(); 49 | 50 | public: 51 | // 消息框标题 52 | CString m_sTitle; 53 | // 消息框样式 54 | int m_iType; 55 | // 用户点中的按钮 56 | int m_iID; 57 | // 提示信息 58 | CString m_sPromptMessage; 59 | // 复选框1提示信息,当此字符串不为空时,显示复选框,否则隐藏复选框 60 | CString m_sOptionPromptMessage1; 61 | // 复选框1选则状态的值 62 | BOOL m_bOption1; 63 | // 复选框2提示信息,当此字符串不为空时,显示复选框,否则隐藏复选框 64 | CString m_sOptionPromptMessage2; 65 | // 复选框2选则状态的值 66 | BOOL m_bOption2; 67 | 68 | protected: 69 | CStatic m_stcIcon; 70 | CStatic m_stcPromptMessage; 71 | CButton m_chkOption1; 72 | CButton m_chkOption2; 73 | CRButton m_btnOK; 74 | CRButton m_btnCancel; 75 | CRButton m_btnAbort; 76 | CRButton m_btnIganore; 77 | CRButton m_btnRetry; 78 | CRButton m_btnContinue; 79 | CRButton m_btnYes; 80 | CRButton m_btnNo; 81 | }; 82 | 83 | #endif // #ifndef RMESSAGEBOX_H 84 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | MICROSOFT FOUNDATION CLASS LIBRARY : AutoUpdate 3 | ======================================================================== 4 | 5 | 6 | AppWizard has created this AutoUpdate application for you. This application 7 | not only demonstrates the basics of using the Microsoft Foundation classes 8 | but is also a starting point for writing your application. 9 | 10 | This file contains a summary of what you will find in each of the files that 11 | make up your AutoUpdate application. 12 | 13 | AutoUpdate.dsp 14 | This file (the project file) contains information at the project level and 15 | is used to build a single project or subproject. Other users can share the 16 | project (.dsp) file, but they should export the makefiles locally. 17 | 18 | AutoUpdate.h 19 | This is the main header file for the application. It includes other 20 | project specific headers (including Resource.h) and declares the 21 | CAutoUpdateApp application class. 22 | 23 | AutoUpdate.cpp 24 | This is the main application source file that contains the application 25 | class CAutoUpdateApp. 26 | 27 | AutoUpdate.rc 28 | This is a listing of all of the Microsoft Windows resources that the 29 | program uses. It includes the icons, bitmaps, and cursors that are stored 30 | in the RES subdirectory. This file can be directly edited in Microsoft 31 | Visual C++. 32 | 33 | AutoUpdate.clw 34 | This file contains information used by ClassWizard to edit existing 35 | classes or add new classes. ClassWizard also uses this file to store 36 | information needed to create and edit message maps and dialog data 37 | maps and to create prototype member functions. 38 | 39 | res\AutoUpdate.ico 40 | This is an icon file, which is used as the application's icon. This 41 | icon is included by the main resource file AutoUpdate.rc. 42 | 43 | res\AutoUpdate.rc2 44 | This file contains resources that are not edited by Microsoft 45 | Visual C++. You should place all resources not editable by 46 | the resource editor in this file. 47 | 48 | 49 | 50 | 51 | ///////////////////////////////////////////////////////////////////////////// 52 | 53 | AppWizard creates one dialog class: 54 | 55 | AutoUpdateDlg.h, AutoUpdateDlg.cpp - the dialog 56 | These files contain your CAutoUpdateDlg class. This class defines 57 | the behavior of your application's main dialog. The dialog's 58 | template is in AutoUpdate.rc, which can be edited in Microsoft 59 | Visual C++. 60 | 61 | 62 | ///////////////////////////////////////////////////////////////////////////// 63 | Other standard files: 64 | 65 | StdAfx.h, StdAfx.cpp 66 | These files are used to build a precompiled header (PCH) file 67 | named AutoUpdate.pch and a precompiled types file named StdAfx.obj. 68 | 69 | Resource.h 70 | This is the standard header file, which defines new resource IDs. 71 | Microsoft Visual C++ reads and updates this file. 72 | 73 | ///////////////////////////////////////////////////////////////////////////// 74 | Other notes: 75 | 76 | AppWizard uses "TODO:" to indicate parts of the source code you 77 | should add to or customize. 78 | 79 | If your application uses MFC in a shared DLL, and your application is 80 | in a language other than the operating system's current language, you 81 | will need to copy the corresponding localized resources MFC42XXX.DLL 82 | from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, 83 | and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. 84 | For example, MFC42DEU.DLL contains resources translated to German.) If you 85 | don't do this, some of the UI elements of your application will remain in the 86 | language of the operating system. 87 | 88 | ///////////////////////////////////////////////////////////////////////////// 89 | -------------------------------------------------------------------------------- /StdAfx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // AutoUpdate.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | #include "AutoUpdate.h" 7 | #include "RMessageBox.h" 8 | 9 | // 记录日志级别 10 | int g_iLogLevel; 11 | 12 | // 显示日志的文本框 13 | //extern CRichEditCtrl *g_pLogViewer; 14 | 15 | // 日志格式[时间][模块ID][日志级别][日志内容] 16 | #define LOG_FORMAT "[%s][%d][%d][%s]\r\n" 17 | // 日志缓冲区大小 18 | #define LOG_BUFFER_SIZE 1024 19 | // 写日志 20 | // iModuleID:模块ID 21 | // iLevel:日志级别 22 | // szFormat:日志格式 23 | // ...:日志内容 24 | void LOG(int iModuleID, int iLevel, const char* sFormat, ...) 25 | { 26 | #ifdef _DEBUG 27 | // 只记录级别在指定日志级别以上的日志 28 | if (iLevel < g_iLogLevel) 29 | { 30 | return; 31 | } 32 | 33 | char *pBuffer1 = new char[LOG_BUFFER_SIZE]; 34 | char *pBuffer2 = new char[LOG_BUFFER_SIZE]; 35 | memset(pBuffer1, 0, LOG_BUFFER_SIZE); 36 | memset(pBuffer2, 0, LOG_BUFFER_SIZE); 37 | 38 | va_list args; 39 | va_start(args, sFormat); 40 | _vsnprintf(pBuffer1, LOG_BUFFER_SIZE, sFormat, args); 41 | va_end(args); 42 | 43 | CString sNow = CTime::GetCurrentTime().Format("%Y-%m-%d %H:%M:%S"); 44 | _snprintf(pBuffer2, LOG_BUFFER_SIZE, LOG_FORMAT, sNow.GetBuffer(0), iModuleID, iLevel, pBuffer1); 45 | 46 | // 输出到文本框 47 | // g_pLogViewer->SetSel(-1, 0); 48 | // g_pLogViewer->ReplaceSel(pBuffer2 + CString("\n")); 49 | 50 | // 写入文件 51 | CFile file; 52 | file.Open(GetAppDirectory() + "debug.log" 53 | , CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); 54 | file.SeekToEnd(); 55 | file.Write(pBuffer2, (UINT)strlen(pBuffer2)); 56 | 57 | // 释放临时申请的内存 58 | delete []pBuffer1; 59 | delete []pBuffer2; 60 | pBuffer1 = NULL; 61 | pBuffer2 = NULL; 62 | #endif 63 | } 64 | 65 | // 取得程序运行的目录 66 | // bEndWithBackSlash:是否以反斜线结尾 67 | CString GetAppDirectory(BOOL bEndWithBackSlash) 68 | { 69 | char acBuffer[MAX_PATH]; 70 | 71 | memset((void *)acBuffer, 0, MAX_PATH); 72 | GetModuleFileName(AfxGetInstanceHandle(), acBuffer, sizeof(acBuffer)); 73 | 74 | char *p = strrchr(acBuffer, '\\'); 75 | if (p != NULL) 76 | { 77 | if (bEndWithBackSlash) 78 | { 79 | *(p + 1) = '\0'; 80 | } 81 | else 82 | { 83 | *p = '\0'; 84 | } 85 | } 86 | else 87 | { 88 | p = strrchr(acBuffer, ':'); 89 | if (p != NULL) 90 | { 91 | if (bEndWithBackSlash) 92 | { 93 | *(p + 1) = '\\'; 94 | *(p + 2) = '\0'; 95 | } 96 | else 97 | { 98 | *p = '\\'; 99 | *(p + 1) = '\0'; 100 | } 101 | } 102 | } 103 | 104 | return CString(acBuffer); 105 | } 106 | 107 | // 从文件全路径取得文件名 108 | CString GetFilename(const char* sFilePath) 109 | { 110 | if (sFilePath == NULL) 111 | { 112 | return CString(""); 113 | } 114 | 115 | char *pBackSlash = strrchr(const_cast(sFilePath), '\\'); 116 | if (pBackSlash == NULL) 117 | { 118 | return CString(sFilePath); 119 | } 120 | else 121 | { 122 | return CString(++pBackSlash); 123 | } 124 | } 125 | 126 | CString GetFilename(const CString &sFilePath) 127 | { 128 | int iPos = sFilePath.ReverseFind('\\'); 129 | if (iPos == -1) 130 | { 131 | return sFilePath; 132 | } 133 | else 134 | { 135 | return sFilePath.Mid(iPos + 1); 136 | } 137 | } 138 | 139 | // 取得文件扩展名(不含'.'字符) 140 | CString GetFileExtendName(const char* sFilename) 141 | { 142 | if (sFilename == NULL) 143 | { 144 | return CString(""); 145 | } 146 | 147 | char *pExtendName = strrchr(const_cast(sFilename), '.'); 148 | if (pExtendName == NULL) 149 | { 150 | return CString(""); 151 | } 152 | else 153 | { 154 | return CString(++pExtendName); 155 | } 156 | } 157 | 158 | // 取得文件扩展名(不含'.'字符) 159 | CString GetFileExtendName(const CString& sFilename) 160 | { 161 | int iPos = sFilename.ReverseFind('.'); 162 | if (iPos == -1) 163 | { 164 | return CString(""); 165 | } 166 | else 167 | { 168 | return sFilename.Mid(iPos + 1); 169 | } 170 | } 171 | 172 | // 取得文件大小 173 | size_t GetFileSize(const char* sFilename) 174 | { 175 | CFileFind FileFinder; 176 | 177 | if (sFilename == NULL) 178 | { 179 | return 0; 180 | } 181 | 182 | if (FileFinder.FindFile(sFilename)) 183 | { 184 | FileFinder.FindNextFile(); 185 | return (size_t)FileFinder.GetLength(); 186 | } 187 | else 188 | { 189 | return 0; 190 | } 191 | } 192 | 193 | // 取得文件大小 194 | size_t GetFileSize(const CString& sFilename) 195 | { 196 | CFileFind FileFinder; 197 | 198 | if (FileFinder.FindFile(sFilename)) 199 | { 200 | FileFinder.FindNextFile(); 201 | return (size_t)FileFinder.GetLength(); 202 | } 203 | else 204 | { 205 | return 0; 206 | } 207 | } 208 | 209 | // 显示消息框 210 | int RMessageBox(CString& sText, UINT nType, UINT nIDHelp) 211 | { 212 | return RMessageBox(sText.GetBuffer(0), nType, nIDHelp); 213 | } 214 | 215 | // 显示消息框 216 | int RMessageBox(LPCTSTR lpszText, UINT nType, UINT nIDHelp) 217 | { 218 | ASSERT(lpszText); 219 | 220 | CRMessageBox mb; 221 | 222 | mb.m_sTitle = AfxGetApp()->m_pszAppName; 223 | mb.m_iType = nType; 224 | mb.m_sPromptMessage = lpszText; 225 | mb.DoModal(); 226 | return mb.m_iID; 227 | } 228 | 229 | // 替换路径中的特殊字符串为实际路径 230 | CString ResolvePath(const char* sPath) 231 | { 232 | if (sPath == NULL) 233 | { 234 | ASSERT(FALSE); 235 | return CString(""); 236 | } 237 | 238 | char acBuffer[MAX_PATH]; 239 | CString sDestFilename = sPath; 240 | 241 | sDestFilename.Replace("", GetAppDirectory().GetBuffer(0)); 242 | 243 | memset(acBuffer, 0, MAX_PATH); 244 | GetWindowsDirectory(acBuffer, MAX_PATH); 245 | sDestFilename.Replace("", acBuffer); 246 | 247 | memset(acBuffer, 0, MAX_PATH); 248 | GetSystemDirectory(acBuffer, MAX_PATH); 249 | sDestFilename.Replace("", acBuffer); 250 | 251 | memset(acBuffer, 0, MAX_PATH); 252 | SHGetSpecialFolderPath(NULL, acBuffer, 0x0014, FALSE); // CSIDL_FONTS (0x0014) 253 | sDestFilename.Replace("", acBuffer); 254 | 255 | memset(acBuffer, 0, MAX_PATH); 256 | SHGetSpecialFolderPath(NULL, acBuffer, 0x0026, FALSE); // CSIDL_PROGRAM_FILES (0x0026) 257 | sDestFilename.Replace("", acBuffer); 258 | 259 | memset(acBuffer, 0, MAX_PATH); 260 | SHGetSpecialFolderPath(NULL, acBuffer, 0x002b, FALSE); // CSIDL_PROGRAM_FILES_COMMON (0x002b) 261 | sDestFilename.Replace("", acBuffer); 262 | 263 | memset(acBuffer, 0, MAX_PATH); 264 | SHGetSpecialFolderPath(NULL, acBuffer, 0x0028, FALSE); // CSIDL_PROFILE (0x0028) 265 | sDestFilename.Replace("", acBuffer); 266 | 267 | memset(acBuffer, 0, MAX_PATH); 268 | SHGetSpecialFolderPath(NULL, acBuffer, CSIDL_PERSONAL, FALSE); 269 | sDestFilename.Replace("", acBuffer); 270 | 271 | memset(acBuffer, 0, MAX_PATH); 272 | SHGetSpecialFolderPath(NULL, acBuffer, CSIDL_DESKTOPDIRECTORY, FALSE); 273 | sDestFilename.Replace("", acBuffer); 274 | 275 | memset(acBuffer, 0, MAX_PATH); 276 | SHGetSpecialFolderPath(NULL, acBuffer, CSIDL_STARTMENU, FALSE); 277 | sDestFilename.Replace("", acBuffer); 278 | 279 | memset(acBuffer, 0, MAX_PATH); 280 | SHGetSpecialFolderPath(NULL, acBuffer, CSIDL_PROGRAMS, FALSE); 281 | sDestFilename.Replace("", acBuffer); 282 | 283 | memset(acBuffer, 0, MAX_PATH); 284 | SHGetSpecialFolderPath(NULL, acBuffer, CSIDL_STARTUP, FALSE); 285 | sDestFilename.Replace("", acBuffer); 286 | 287 | // sDestFilename.Replace("", acBuffer); 288 | 289 | memset(acBuffer, 0, MAX_PATH); 290 | SHGetSpecialFolderPath(NULL, acBuffer, CSIDL_SENDTO, FALSE); 291 | sDestFilename.Replace("", acBuffer); 292 | 293 | memset(acBuffer, 0, MAX_PATH); 294 | SHGetSpecialFolderPath(NULL, acBuffer, 0x0006, FALSE); // CSIDL_FAVORITES (0x0006) 295 | sDestFilename.Replace("", acBuffer); 296 | 297 | memset(acBuffer, 0, MAX_PATH); 298 | SHGetSpecialFolderPath(NULL, acBuffer, CSIDL_APPDATA, FALSE); 299 | sDestFilename.Replace("", acBuffer); 300 | 301 | memset(acBuffer, 0, MAX_PATH); 302 | SHGetSpecialFolderPath(NULL, acBuffer, 0x001c, FALSE); // CSIDL_LOCAL_APPDATA (0x001c) 303 | sDestFilename.Replace("", acBuffer); 304 | 305 | // sDestFilename.Replace("", acBuffer); 306 | 307 | return sDestFilename; 308 | } 309 | -------------------------------------------------------------------------------- /StdAfx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #if !defined(AFX_STDAFX_H__6E171DE5_929C_4558_880B_14D7DDC8781D__INCLUDED_) 7 | #define AFX_STDAFX_H__6E171DE5_929C_4558_880B_14D7DDC8781D__INCLUDED_ 8 | 9 | #if _MSC_VER > 1000 10 | #pragma once 11 | #endif // _MSC_VER > 1000 12 | 13 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 14 | 15 | #include // MFC core and standard components 16 | #include // MFC extensions 17 | #include // MFC Automation classes 18 | #include // MFC support for Internet Explorer 4 Common Controls 19 | #ifndef _AFX_NO_AFXCMN_SUPPORT 20 | #include // MFC support for Windows Common Controls 21 | #endif // _AFX_NO_AFXCMN_SUPPORT 22 | 23 | // 取得程序运行的目录 24 | CString GetAppDirectory(BOOL bEndWithBackSlash = TRUE); 25 | 26 | // 从文件全路径取得文件名 27 | CString GetFilename(const char* sFilePath); 28 | CString GetFilename(const CString& sFilePath); 29 | 30 | // 取得文件扩展名 31 | CString GetFileExtendName(const char* sFilename); 32 | CString GetFileExtendName(const CString& sFilename); 33 | 34 | // 取得文件大小 35 | size_t GetFileSize(const char* sFilename); 36 | size_t GetFileSize(const CString& sFilename); 37 | 38 | // 写日志 39 | void LOG(int iModuleID, int iLevel, const char* sFormat, ...); 40 | 41 | // 计算文件的MD5摘要码 42 | extern BOOL CalculateMD5(const char* sFilename, unsigned char acMD5Digest[]); 43 | extern CString MD5toString(unsigned char acMD5Digest[]); 44 | 45 | // 显示消息框函数,用于替代AfxMessageBox函数 46 | int RMessageBox(CString& sText, UINT nType = MB_OK, UINT nIDHelp = 0); 47 | int RMessageBox(LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0); 48 | 49 | // 替换路径中的特殊字符串为实际路径 50 | CString ResolvePath(const char* sPath); 51 | 52 | //{{AFX_INSERT_LOCATION}} 53 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 54 | 55 | #endif // !defined(AFX_STDAFX_H__6E171DE5_929C_4558_880B_14D7DDC8781D__INCLUDED_) 56 | -------------------------------------------------------------------------------- /UISkinManager.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:UISkinManager.cpp 3 | // 文件版本:v1.0 4 | // 创建日期:2006-02-14 16:59 5 | // 作 者:Richard Ree 6 | // 文件描述:界面管理类的实现文件 7 | //------------------------------------------------------------------------------ 8 | 9 | #include "stdafx.h" 10 | #include "AutoUpdate.h" 11 | #include "UISkinManager.h" 12 | 13 | #pragma comment(lib, "msimg32.lib") 14 | #pragma message("Automatically linking with msimg32.lib") 15 | 16 | // 透明色 17 | const COLORREF CUISkinManager::TRANSPARENT_COLOR = RGB(255, 0, 255); 18 | 19 | // 当前界面风格 20 | enum CUISkinManager::SkinStyle CUISkinManager::m_iCurrentStyle; 21 | 22 | // 窗口标题栏风格 23 | 24 | // 标题栏高度 25 | UINT CUISkinManager::m_iTitleBarHeight; 26 | // 绘制标题栏所需的图像宽度(象素) 27 | UINT CUISkinManager::m_iTitleBarImageWidth; 28 | // 标题栏图象左边部分的宽度 29 | UINT CUISkinManager::m_iTitleBarImageLeftPartWidth; 30 | // 标题栏图象中间部分的宽度(此部分是可拉伸的) 31 | UINT CUISkinManager::m_iTitleBarImageMiddlePartWidth; 32 | // 标题栏图象右边部分的宽度 33 | UINT CUISkinManager::m_iTitleBarImageRightPartWidth; 34 | // 绘制标题栏所需的图像集(每个图像宽度为 m_iTitleBarImageWidth 象素,按正常、失去焦点的顺序排列,总宽度不小于 2 * m_iTitleBarImageWidth 象素) 35 | CBitmap CUISkinManager::m_bmTitleBarImage; 36 | 37 | // 对话框窗口左右边距 38 | UINT CUISkinManager::m_iLeftMargin; 39 | // 对话框窗口上下边距 40 | UINT CUISkinManager::m_iTopMargin; 41 | 42 | // 按钮风格 43 | 44 | // 按钮高度(绘制按钮所需的图像高度) 45 | UINT CUISkinManager::m_iButtonHeight; 46 | // 绘制按钮所需的图像宽度(象素) 47 | UINT CUISkinManager::m_iButtonImageWidth; 48 | // 按钮图象左边部分的宽度 49 | UINT CUISkinManager::m_iButtonImageLeftPartWidth; 50 | // 按钮图象中间部分的宽度(此部分是可拉伸的) 51 | UINT CUISkinManager::m_iButtonImageMiddlePartWidth; 52 | // 按钮图象右边部分的宽度 53 | UINT CUISkinManager::m_iButtonImageRightPartWidth; 54 | // 绘制按钮所需的图像集(每个图像宽度为 m_iButtonImageWidth 象素,按正常、缺省、鼠标悬停、鼠标按下的顺序排列,总宽度不小于 4 * m_iButtonImageWidth 象素) 55 | CBitmap CUISkinManager::m_bmButtonImage; 56 | // 系统控制按钮的宽度和高度(象素) 57 | UINT CUISkinManager::m_iSystemControlButtonWidth; 58 | UINT CUISkinManager::m_iSystemControlButtonHeight; 59 | // 绘制系统控制按钮(最小化、最大化、关闭等按钮)所需的图像集(每个图像宽度为 m_iSystemControlButtonImageWidth 象素,按最小化、最大化、恢复、关闭、按钮按下状态的顺序排列,总宽度不小于 8 * m_iSystemControlButtonImageWidth 象素) 60 | CBitmap CUISkinManager::m_bmSystemControlButtonImage; 61 | 62 | // 绘制控件的画笔 63 | HBRUSH CUISkinManager::m_hbr; 64 | 65 | CUISkinManager::CUISkinManager() 66 | { 67 | } 68 | 69 | CUISkinManager::~CUISkinManager() 70 | { 71 | } 72 | 73 | BOOL CUISkinManager::Init() 74 | { 75 | m_hbr = NULL; 76 | 77 | if (!LoadImages()) 78 | { 79 | return FALSE; 80 | } 81 | 82 | ChangeStyle(StyleSummer); 83 | 84 | return TRUE; 85 | } 86 | 87 | void CUISkinManager::Uninit() 88 | { 89 | if (m_hbr != NULL) 90 | { 91 | DeleteObject(m_hbr); 92 | } 93 | 94 | m_bmTitleBarImage.DeleteObject(); 95 | m_bmButtonImage.DeleteObject(); 96 | m_bmSystemControlButtonImage.DeleteObject(); 97 | } 98 | 99 | BOOL CUISkinManager::LoadImages() 100 | { 101 | m_bmTitleBarImage.DeleteObject(); 102 | m_bmButtonImage.DeleteObject(); 103 | m_bmSystemControlButtonImage.DeleteObject(); 104 | 105 | switch (m_iCurrentStyle) 106 | { 107 | case StyleSummer: 108 | default: 109 | m_bmTitleBarImage.LoadBitmap(IDB_TITLEBAR); 110 | m_bmButtonImage.LoadBitmap(IDB_BUTTON); 111 | m_bmSystemControlButtonImage.LoadBitmap(IDB_SYSTEM_CONTROL_BUTTON); 112 | break; 113 | } 114 | 115 | return TRUE; 116 | } 117 | 118 | HBRUSH CUISkinManager::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 119 | { 120 | if (pDC == NULL || pWnd == NULL || pWnd->m_hWnd == NULL) 121 | { 122 | return NULL; 123 | } 124 | 125 | if (nCtlColor == CTLCOLOR_EDIT 126 | || nCtlColor == CTLCOLOR_MSGBOX 127 | || nCtlColor == CTLCOLOR_LISTBOX 128 | || nCtlColor == CTLCOLOR_SCROLLBAR) 129 | { 130 | return (HBRUSH)GetStockObject(WHITE_BRUSH); 131 | } 132 | 133 | pDC->SetBkMode(TRANSPARENT); 134 | 135 | return GetBrush(); 136 | } 137 | 138 | // 返回窗口背景色 139 | COLORREF CUISkinManager::GetColor() 140 | { 141 | switch (m_iCurrentStyle) 142 | { 143 | case StyleSpring: 144 | return RGB(240, 245, 255); 145 | case StyleSummer: 146 | return RGB(238, 247, 255); 147 | case StyleAutumn: 148 | return RGB(122, 33, 123); 149 | case StyleWinter: 150 | // return RGB(225, 233, 240); // 蓝灰色 151 | return RGB(245, 245, 245); // 灰色 152 | case StyleXP: 153 | return RGB(240, 245, 255); 154 | case StyleNormal: 155 | case StyleCustomize: 156 | default: 157 | return ::GetSysColor(COLOR_WINDOW); 158 | break; 159 | } 160 | } 161 | 162 | HBRUSH CUISkinManager::GetBrush() 163 | { 164 | return m_hbr; 165 | } 166 | 167 | // 切换界面风格 168 | void CUISkinManager::ChangeStyle(enum CUISkinManager::SkinStyle iNewStyle) 169 | { 170 | m_iCurrentStyle = iNewStyle; 171 | 172 | switch (m_iCurrentStyle) 173 | { 174 | case StyleSummer: 175 | default: 176 | m_iTitleBarHeight = 24; 177 | m_iTitleBarImageWidth = 64; 178 | m_iTitleBarImageLeftPartWidth = 15; 179 | m_iTitleBarImageMiddlePartWidth = 2; 180 | m_iTitleBarImageRightPartWidth = 15; 181 | m_iLeftMargin = 8; 182 | m_iTopMargin = 8; 183 | m_iButtonHeight = 20; 184 | m_iButtonImageWidth = 128; 185 | m_iButtonImageLeftPartWidth = 15; 186 | m_iButtonImageMiddlePartWidth = 2; 187 | m_iButtonImageRightPartWidth = 15; 188 | m_iSystemControlButtonWidth = 16; 189 | m_iSystemControlButtonHeight = 14; 190 | break; 191 | } 192 | 193 | if (m_hbr != NULL) 194 | { 195 | DeleteObject(m_hbr); 196 | } 197 | 198 | m_hbr = ::CreateSolidBrush(GetColor()); 199 | } 200 | 201 | // 以渐变方式填充矩形 202 | void CUISkinManager::GradientFillRect(CWnd* pWnd, CDC* pDC, CRect& rcFill, ULONG nMode, COLORREF crLeftTop, COLORREF crRightBottom) 203 | { 204 | if (pWnd == NULL || pWnd->m_hWnd == NULL) 205 | { 206 | return; 207 | } 208 | 209 | COLOR16 r = (COLOR16)((crLeftTop & 0x000000FF) << 8); 210 | COLOR16 g = (COLOR16)(crLeftTop & 0x0000FF00); 211 | COLOR16 b = (COLOR16)((crLeftTop & 0x00FF0000) >> 8); 212 | 213 | TRIVERTEX vert[2] ; 214 | GRADIENT_RECT gRect; 215 | vert[0].x = rcFill.left; 216 | vert[0].y = rcFill.top; 217 | vert[0].Red = r; 218 | vert[0].Green = g; 219 | vert[0].Blue = b; 220 | vert[0].Alpha = 0x0000; 221 | 222 | r = (COLOR16) ((crRightBottom & 0x000000FF)<<8); 223 | g = (COLOR16) (crRightBottom & 0x0000FF00); 224 | b = (COLOR16) ((crRightBottom & 0x00FF0000)>>8); 225 | 226 | vert[1].x = rcFill.right; 227 | vert[1].y = rcFill.bottom; 228 | vert[1].Red = r; 229 | vert[1].Green = g; 230 | vert[1].Blue = b; 231 | vert[1].Alpha = 0x0000; 232 | 233 | gRect.UpperLeft = 0; 234 | gRect.LowerRight = 1; 235 | 236 | GradientFill(pDC->m_hDC, vert, 2, &gRect, 1, nMode); 237 | } 238 | 239 | // 透明拉伸复制 240 | void CUISkinManager::TransparentBlt(HDC hdcDest, int nXDest, int nYDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXSrc, int nYSrc, int nWidthSrc,int nHeightSrc, COLORREF crTransparent) 241 | { 242 | HBITMAP hbm = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest); 243 | HBITMAP hbmMemory = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); 244 | HDC hdc = CreateCompatibleDC(hdcDest); 245 | HDC hdcMemory = CreateCompatibleDC(hdcDest); 246 | HBITMAP hbmOld = (HBITMAP)SelectObject(hdc, hbm); 247 | HBITMAP hbmOldMemory = (HBITMAP)SelectObject(hdcMemory, hbmMemory); 248 | 249 | // step 1: hdcSrc--(copy)-->hdc 250 | if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc) 251 | { 252 | // 原样复制 253 | BitBlt(hdc, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXSrc, nYSrc, SRCCOPY); 254 | } 255 | else 256 | { 257 | // 拉伸复制 258 | StretchBlt(hdc, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXSrc, nYSrc, nWidthSrc, nHeightSrc, SRCCOPY); 259 | } 260 | 261 | // step 2: hdc--(copy)-->hdcMemory 262 | SetBkColor(hdc, crTransparent); 263 | BitBlt(hdcMemory, 0, 0, nWidthDest, nHeightDest, hdc, 0, 0, SRCCOPY); 264 | 265 | // step 3: hdcMemory--(and)-->hdc 266 | SetBkColor(hdc, RGB(0, 0, 0)); 267 | SetTextColor(hdc, RGB(255, 255, 255)); 268 | BitBlt(hdc, 0, 0, nWidthDest, nHeightDest, hdcMemory, 0, 0, SRCAND); 269 | 270 | // step 4: hdcMemory--(and)-->hdcDest 271 | SetBkColor(hdcDest, RGB(255, 255, 255)); 272 | SetTextColor(hdcDest, RGB(0, 0, 0)); 273 | BitBlt(hdcDest, nXDest, nYDest, nWidthDest, nHeightDest, hdcMemory, 0, 0, SRCAND); 274 | 275 | // step 5: hdc--(paint)-->hdcDest 276 | BitBlt(hdcDest, nXDest, nYDest, nWidthDest, nHeightDest, hdc, 0, 0, SRCPAINT); 277 | 278 | // 释放资源 279 | SelectObject(hdc, hbmOld); 280 | DeleteDC(hdc); 281 | SelectObject(hdcMemory, hbmOldMemory); 282 | DeleteDC(hdcMemory); 283 | DeleteObject(hbm); 284 | DeleteObject(hbmMemory); 285 | } 286 | 287 | // 绘制窗口 288 | void CUISkinManager::Paint(CWnd* pWnd, CDC* pDC, BOOL bFillClient, COLORREF crFillColor) 289 | { 290 | if (pWnd == NULL || pWnd->m_hWnd == NULL) 291 | { 292 | return; 293 | } 294 | 295 | BOOL bGetDC = FALSE; 296 | 297 | if (!pDC) 298 | { 299 | bGetDC = TRUE; 300 | pDC = pWnd->GetDC(); 301 | } 302 | 303 | switch (m_iCurrentStyle) 304 | { 305 | case StyleXP: 306 | Paint_XP(pWnd, pDC, bFillClient, crFillColor); 307 | break; 308 | default: 309 | Paint_Normal(pWnd, pDC, bFillClient, crFillColor); 310 | break; 311 | } 312 | 313 | if (bGetDC) 314 | { 315 | pWnd->ReleaseDC(pDC); 316 | } 317 | } 318 | 319 | void CUISkinManager::Paint_Normal(CWnd* pWnd, CDC* pDC, BOOL bFillClient, COLORREF crFillColor) 320 | { 321 | if (pWnd == NULL || pWnd->m_hWnd == NULL) 322 | { 323 | return; 324 | } 325 | 326 | CRect rcWnd; 327 | pWnd->GetClientRect(&rcWnd); 328 | 329 | CDC dcMemory; 330 | dcMemory.CreateCompatibleDC(pDC); 331 | CBitmap bmpMemory; 332 | bmpMemory.CreateCompatibleBitmap(pDC, rcWnd.Width(), rcWnd.Height()); 333 | CBitmap* pOldbmpMemory = (CBitmap*)dcMemory.SelectObject(&bmpMemory); 334 | 335 | // 填充窗口背景色 336 | dcMemory.FillSolidRect(&rcWnd, GetColor()); 337 | 338 | int cx = ::GetSystemMetrics(SM_CXDLGFRAME); 339 | int cy = ::GetSystemMetrics(SM_CYDLGFRAME); 340 | 341 | CRect rc; 342 | CRgn rgn; 343 | pWnd->GetWindowRect(&rc); 344 | rc.right -= 2 * cx; 345 | rc.bottom -= 2 * cy; 346 | 347 | // 以背景图填充标题栏 348 | CRect rcTitleBar; 349 | rcTitleBar.SetRect(rc.left, rc.top, rc.right, rc.top + m_iTitleBarHeight); 350 | HDC hdcSrc = CreateCompatibleDC(dcMemory.GetSafeHdc()); 351 | HGDIOBJ hOldGdiObj = SelectObject(hdcSrc, m_bmTitleBarImage); 352 | // 左部 353 | TransparentBlt(dcMemory.GetSafeHdc(), 0, 0, m_iTitleBarImageLeftPartWidth, m_iTitleBarHeight 354 | , hdcSrc, 0, 0, m_iTitleBarImageLeftPartWidth, m_iTitleBarHeight, TRANSPARENT_COLOR); 355 | // 中部 356 | TransparentBlt(dcMemory.GetSafeHdc(), m_iTitleBarImageLeftPartWidth, 0 357 | , rcTitleBar.Width() - m_iTitleBarImageLeftPartWidth - m_iTitleBarImageRightPartWidth, m_iTitleBarHeight 358 | , hdcSrc, m_iTitleBarImageLeftPartWidth, 0 359 | , m_iTitleBarImageMiddlePartWidth, m_iTitleBarHeight, TRANSPARENT_COLOR); 360 | // 右部 361 | TransparentBlt(dcMemory.GetSafeHdc(), rcTitleBar.Width() - m_iTitleBarImageRightPartWidth, 0 362 | , m_iTitleBarImageRightPartWidth, m_iTitleBarHeight 363 | , hdcSrc, m_iTitleBarImageLeftPartWidth + m_iTitleBarImageMiddlePartWidth, 0 364 | , m_iTitleBarImageRightPartWidth, m_iTitleBarHeight, TRANSPARENT_COLOR); 365 | SelectObject(hdcSrc, hOldGdiObj); 366 | 367 | // 填充客户区背景色 368 | pWnd->GetClientRect(&rc); 369 | rc.OffsetRect(-rc.left, -rc.top); 370 | rc.DeflateRect(m_iLeftMargin, m_iTitleBarHeight + 8, m_iLeftMargin, m_iTopMargin); 371 | dcMemory.FillSolidRect(rc.left, rc.top, rc.Width(), rc.Height(), RGB(238, 247, 255)); 372 | 373 | // 画稍暗的左、右、底边线 374 | pWnd->GetClientRect(&rc); 375 | rgn.CreateRoundRectRgn(0, 0, rc.Width(), rc.Height(), 5, 5); 376 | CBrush br3(RGB(141, 193, 250)); 377 | dcMemory.FrameRgn(&rgn, &br3, 1, 1); 378 | br3.DeleteObject(); 379 | rgn.DeleteObject(); 380 | 381 | // 输出标题栏文字 382 | 383 | CFont font; 384 | LOGFONT lf; 385 | memset(&lf, 0, sizeof(LOGFONT)); 386 | lf.lfHeight = 18; // 字号 387 | strncpy(lf.lfFaceName, "Microsoft Sans Serif", 32); // 字体 388 | lf.lfWeight = 600; // 粗细 389 | VERIFY(font.CreateFontIndirect(&lf)); 390 | 391 | CString strCaption; 392 | pWnd->GetWindowText(strCaption); 393 | CFont* pOldFont = dcMemory.SelectObject(&font); 394 | dcMemory.SetBkMode(TRANSPARENT); 395 | 396 | // 以灰、黑色输出文字形成阴影效果 397 | dcMemory.SetTextColor(RGB(160, 160, 160)); 398 | dcMemory.TextOut(12, 4, strCaption); 399 | dcMemory.SetTextColor(RGB(10, 30, 100)); 400 | dcMemory.TextOut(11, 3, strCaption); 401 | 402 | dcMemory.SelectObject(pOldFont); 403 | font.DeleteObject(); 404 | 405 | // 从内存设备环境复制位图到窗口 406 | pDC->BitBlt(0, 0, rcWnd.Width(), rcWnd.Height(), &dcMemory, 0, 0, SRCCOPY); 407 | 408 | // 释放资源 409 | dcMemory.SelectObject(::GetStockObject(WHITE_PEN)); 410 | dcMemory.SelectObject(pOldbmpMemory); 411 | bmpMemory.DeleteObject(); 412 | dcMemory.DeleteDC(); 413 | } 414 | 415 | void CUISkinManager::Paint_XP(CWnd* pWnd, CDC* pDC, BOOL bFillClient, COLORREF crFillColor) 416 | { 417 | } 418 | 419 | // 绘制对话框边框,对话框具有通用样式:蓝色框线、下方有按钮工具条 420 | void CUISkinManager::PaintDialogBorder(CWnd* pWnd, CDC* pDC) 421 | { 422 | if (pWnd == NULL || pWnd->m_hWnd == NULL) 423 | { 424 | return; 425 | } 426 | 427 | BOOL bGetDC = FALSE; 428 | 429 | if (!pDC) 430 | { 431 | bGetDC = TRUE; 432 | pDC = pWnd->GetDC(); 433 | } 434 | 435 | const int BOTTOM_COMMAND_BUTTON_BAR_HEIGHT = 45; // 对话框底部按钮工具条高度(象素) 436 | CRect rcWnd; 437 | CRect rc; 438 | 439 | pWnd->GetClientRect(&rcWnd); 440 | rcWnd.DeflateRect(m_iLeftMargin, m_iTitleBarHeight + m_iTopMargin, m_iLeftMargin + 1, m_iTopMargin + 1); 441 | 442 | // 画水平分隔线 443 | rc.SetRect(rcWnd.left, rcWnd.bottom - BOTTOM_COMMAND_BUTTON_BAR_HEIGHT, rcWnd.right, rcWnd.bottom - BOTTOM_COMMAND_BUTTON_BAR_HEIGHT + 2); 444 | pDC->Draw3dRect(rc, RGB(162, 185, 201), RGB(255, 255, 255)); 445 | 446 | // 画边框 447 | CBrush br(RGB(100, 155, 194)); 448 | rc = rcWnd; 449 | pDC->FrameRect(&rc, &br); 450 | rc.DeflateRect(1, 1, 1, 1); 451 | pDC->FrameRect(&rc, &br); 452 | 453 | // 画下方的按钮栏渐变背景 454 | rc.DeflateRect(1, 1, 1, 1); 455 | rc.top = rc.bottom - BOTTOM_COMMAND_BUTTON_BAR_HEIGHT + 4; 456 | GradientFillRect(pWnd, pDC, rc, GRADIENT_FILL_RECT_V, RGB(170, 210, 245), RGB(255, 255, 255)); 457 | 458 | if (bGetDC) 459 | { 460 | pWnd->ReleaseDC(pDC); 461 | } 462 | } 463 | 464 | // 设置窗口可见区域 465 | void CUISkinManager::SetRgn(CWnd* pWnd) 466 | { 467 | switch (m_iCurrentStyle) 468 | { 469 | case StyleXP: 470 | SetRgn_XP(pWnd); 471 | break; 472 | default: 473 | SetRgn_Normal(pWnd); 474 | break; 475 | } 476 | } 477 | 478 | void CUISkinManager::SetRgn_Normal(CWnd* pWnd) 479 | { 480 | if (NULL == pWnd || NULL == pWnd->m_hWnd) 481 | { 482 | return; 483 | } 484 | 485 | // 取得窗口边框线宽度,边框线属于不可重绘范围,需隐藏掉 486 | int cx = ::GetSystemMetrics(SM_CXDLGFRAME); 487 | int cy = ::GetSystemMetrics(SM_CYDLGFRAME); 488 | 489 | CRect rc; 490 | CRgn rgn; 491 | pWnd->GetWindowRect(&rc); 492 | 493 | // 构造圆角矩形作为窗口的可见区域,排除边框线 494 | rgn.CreateRoundRectRgn(cx, cy, rc.Width() - cx, rc.Height() - cy, 5, 5); 495 | 496 | // 设置窗口可见区域 497 | pWnd->SetWindowRgn(rgn, TRUE); 498 | 499 | rgn.DeleteObject(); 500 | } 501 | 502 | void CUISkinManager::SetRgn_XP(CWnd* pWnd) 503 | { 504 | int cx = ::GetSystemMetrics(SM_CXDLGFRAME); 505 | int cy = ::GetSystemMetrics(SM_CYDLGFRAME); 506 | 507 | CRect rc; 508 | CRgn rgn; 509 | pWnd->GetWindowRect(&rc); 510 | 511 | // 构造圆角矩形作为窗口的可见区域 512 | rgn.CreateRoundRectRgn(cx, cy, rc.Width() - cx, rc.Height() - cy, 33, 33); 513 | 514 | // 设置窗口可见区域 515 | pWnd->SetWindowRgn(rgn, TRUE); 516 | 517 | rgn.DeleteObject(); 518 | } 519 | -------------------------------------------------------------------------------- /UISkinManager.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:UISkinManager.h 3 | // 文件版本:v1.0 4 | // 创建日期:2006-02-14 16:59 5 | // 作 者:Richard Ree 6 | // 文件描述:界面管理类,提供实现自绘界面的公用函数以及风格设置和切换 7 | //------------------------------------------------------------------------------ 8 | 9 | #pragma once 10 | 11 | #ifndef UISKINMANAGER_H 12 | #define UISKINMANAGER_H 13 | 14 | class CUISkinManager 15 | { 16 | public: 17 | CUISkinManager(); 18 | ~CUISkinManager(); 19 | 20 | static BOOL Init(); 21 | static void Uninit(); 22 | static BOOL LoadImages(); 23 | static HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); 24 | static COLORREF GetColor(); 25 | static HBRUSH GetBrush(); 26 | 27 | // 以渐变方式填充矩形 28 | static void GradientFillRect(CWnd* pWnd, CDC* pDC, CRect& rcFill, ULONG nMode, COLORREF crLeftTop, COLORREF crRightBottom); 29 | 30 | // 透明拉伸复制 31 | static void TransparentBlt(HDC hdcDest, int nXDest, int nYDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXSrc, int nYSrc, int nWidthSrc,int nHeightSrc, COLORREF crTransparent); 32 | 33 | // 绘制对话框 34 | static void Paint(CWnd* pWnd, CDC* pDC = NULL, BOOL bFillClient = TRUE, COLORREF crFillColor = RGB(255, 255, 255)); 35 | static void Paint_Normal(CWnd* pWnd, CDC* pDC = NULL, BOOL bFillClient = TRUE, COLORREF crFillColor = RGB(255, 255, 255)); 36 | static void Paint_XP(CWnd* pWnd, CDC* pDC = NULL, BOOL bFillClient = TRUE, COLORREF crFillColor = RGB(255, 255, 255)); 37 | static void PaintDialogBorder(CWnd* pWnd, CDC* pDC = NULL); 38 | 39 | // 设置对话框边框 40 | static void SetRgn(CWnd* pWnd); 41 | static void SetRgn_Normal(CWnd* pWnd); 42 | static void SetRgn_XP(CWnd* pWnd); 43 | 44 | public: 45 | // 界面风格枚举 46 | enum SkinStyle 47 | { 48 | StyleNormal = 0, 49 | StyleSpring, 50 | StyleSummer, 51 | StyleAutumn, 52 | StyleWinter, 53 | StyleXP, 54 | StyleCustomize, 55 | SkinStyleBottom 56 | }; 57 | // 切换界面风格 58 | static void ChangeStyle(enum SkinStyle iNewStyle); 59 | 60 | public: 61 | // 透明色 62 | static const COLORREF TRANSPARENT_COLOR; 63 | 64 | // 当前界面风格 65 | static enum SkinStyle m_iCurrentStyle; 66 | 67 | // 窗口标题栏风格 68 | 69 | // 标题栏高度 70 | static UINT m_iTitleBarHeight; 71 | // 绘制标题栏所需的图像宽度(象素) 72 | static UINT m_iTitleBarImageWidth; 73 | // 标题栏图象左边部分的宽度 74 | static UINT m_iTitleBarImageLeftPartWidth; 75 | // 标题栏图象中间部分的宽度(此部分是可拉伸的) 76 | static UINT m_iTitleBarImageMiddlePartWidth; 77 | // 标题栏图象右边部分的宽度 78 | static UINT m_iTitleBarImageRightPartWidth; 79 | // 绘制标题栏所需的图像集(每个图像宽度为 m_iTitleBarImageWidth 象素,按正常、失去焦点的顺序排列,总宽度不小于 2 * m_iTitleBarImageWidth 象素) 80 | static CBitmap m_bmTitleBarImage; 81 | 82 | // 对话框窗口左右边距 83 | static UINT m_iLeftMargin; 84 | // 对话框窗口上下边距 85 | static UINT m_iTopMargin; 86 | 87 | // 按钮风格 88 | 89 | // 按钮高度(绘制按钮所需的图像高度) 90 | static UINT m_iButtonHeight; 91 | // 绘制按钮所需的图像宽度(象素) 92 | static UINT m_iButtonImageWidth; 93 | // 按钮图象左边部分的宽度 94 | static UINT m_iButtonImageLeftPartWidth; 95 | // 按钮图象中间部分的宽度(此部分是可拉伸的) 96 | static UINT m_iButtonImageMiddlePartWidth; 97 | // 按钮图象右边部分的宽度 98 | static UINT m_iButtonImageRightPartWidth; 99 | // 绘制按钮所需的图像集(每个图像宽度为 m_iButtonImageWidth 象素,按正常、缺省、鼠标悬停、鼠标按下的顺序排列,总宽度不小于 4 * m_iButtonImageWidth 象素) 100 | static CBitmap m_bmButtonImage; 101 | // 系统控制按钮的宽度和高度(象素) 102 | static UINT m_iSystemControlButtonWidth; 103 | static UINT m_iSystemControlButtonHeight; 104 | // 绘制系统控制按钮(最小化、最大化、关闭等按钮)所需的图像集(每个图像宽度为 m_iSystemControlButtonImageWidth 象素,按最小化、最大化、恢复、关闭、按钮按下状态的顺序排列,总宽度不小于 8 * m_iSystemControlButtonImageWidth 象素) 105 | static CBitmap m_bmSystemControlButtonImage; 106 | 107 | // 绘制控件的画笔 108 | static HBRUSH m_hbr; 109 | }; 110 | 111 | #endif // #ifndef UISKINMANAGER_H 112 | -------------------------------------------------------------------------------- /UpdateConfig.ini: -------------------------------------------------------------------------------- 1 | # 更新配置文件UpdateCofig.ini的内容示例 2 | 3 | # 软件升级基本信息区段 4 | [UPDATE] 5 | # 软件名,用以检验该更新配置文件的有效性 6 | AppName=MyProgram 7 | # 软件的版本号 8 | Version=1.2.3 9 | # 更新完毕后要执行的程序文件名 10 | RunAfterDownload=Update.exe 11 | 12 | # 各语言版本公共文件区段 13 | [COMMON] 14 | # 要下载的文件数 15 | FileCount=2 16 | # 第一个文件名 17 | File1=MyProgram.exe 18 | # 第二个文件名 19 | File2=Update.exe 20 | # 第三个文件名 21 | File3= 22 | 23 | # 语言信息区段,定义支持的语言代码对应的区段名 24 | [LANGUAGE] 25 | # 缺省语言——英语 26 | Default=ENG 27 | # 简体中文 28 | 2052=CHS 29 | 4100=CHS 30 | # 繁体中文 31 | 1028=CHT 32 | 3076=CHT 33 | 34 | # 英语专用文件区段 35 | [ENG] 36 | # 新版本软件优于以往版本的特性描述,用\n代替换行字符 37 | Information=New version description... 38 | # 英文版专用文件数 39 | FileCount=1 40 | # 第一个文件名 41 | File1=Help.chm 42 | # 第二个文件名 43 | File2= 44 | 45 | # 简体中文专用文件区段 46 | [CHS] 47 | # 新版本软件优于以往版本的特性描述,用\n代替换行字符 48 | Information=软件更新说明…… 49 | # 简体中文版专用文件数 50 | FileCount=1 51 | # 第一个文件名 52 | File1=Help.chm 53 | # 第二个文件名 54 | File2= 55 | 56 | # 繁体中文专用文件区段 57 | [CHT] 58 | # 新版本软件优于以往版本的特性描述,用\n代替换行字符 59 | Information=硁ン穝弧 60 | # 繁体中文版专用文件数 61 | FileCount=1 62 | # 第一个文件名 63 | File1=Help.chm 64 | # 第二个文件名 65 | File2= 66 | 67 | # 第一个公共文件信息区段 68 | [CommonFile1] 69 | # 文件名 70 | Name=MyProgram.exe 71 | # 文件大小 72 | Size=3567811 73 | # 文件下载地址 74 | URL=http://www.mysite.org/download/1.2.3/MyProgram.exe 75 | # 文件压缩方式 76 | CompressMethod=None 77 | # 文件摘要码,用标准MD5算法得到 78 | Hash=3177D58949143219E06E5C346674AE02 79 | # 文件安装路径,可包含路径变量,见附录 80 | DestPath= 81 | 82 | # 第二个公共文件信息区段 83 | [CommonFile2] 84 | # 文件名 85 | Name=Update.exe 86 | # 文件大小 87 | Size=172864 88 | # 文件下载地址 89 | URL=http://www.mysite.org/download/1.2.3/Update.exe 90 | # 文件压缩方式 91 | CompressMethod=None 92 | # 文件摘要码,用标准MD5算法得到 93 | Hash=4914324AE021C3319E06E577D5894667 94 | # 文件安装路径,可包含路径变量,见附录 95 | DestPath= 96 | 97 | # 英文版第一个专用文件信息区段 98 | [ENGFile1] 99 | # 文件名 100 | Name=Help.chm 101 | # 文件大小 102 | Size=1581671 103 | # 文件下载地址 104 | URL=http://www.mysite.org/download/1.2.3/Help.ENG.chm 105 | # 文件压缩方式 106 | CompressMethod=None 107 | # 文件摘要码,用标准MD5算法得到 108 | Hash=7D586493193219E0714E0274E5C3466A 109 | # 文件安装路径,可包含路径变量,见附录 110 | DestPath= 111 | 112 | # 简体中文版第一个专用文件信息区段 113 | [CHSFile1] 114 | # 文件名 115 | Name=Help.chm 116 | # 文件大小 117 | Size=1581888 118 | # 文件下载地址 119 | URL=http://www.mysite.org/download/1.2.3/Help.CHS.chm 120 | # 文件压缩方式 121 | CompressMethod=None 122 | # 文件摘要码,用标准MD5算法得到 123 | Hash=931932197D5864E0714E0C3466A274E5 124 | # 文件安装路径,可包含路径变量,见附录 125 | DestPath= 126 | 127 | # 繁体中文版第一个专用文件信息区段 128 | [CHTFile1] 129 | # 文件名 130 | Name=Help.chm 131 | # 文件大小 132 | Size=1581369 133 | # 文件下载地址 134 | URL=http://www.mysite.org/download/1.2.3/Help.CHT.chm 135 | # 文件压缩方式 136 | CompressMethod=None 137 | # 文件摘要码,用标准MD5算法得到 138 | Hash=66A3197D58649274E5C343219E0714E0 139 | # 文件安装路径,可包含路径变量,见附录 140 | DestPath= 141 | 142 | 143 | ################################################################################ 144 | 附录:路径字符串变量中一些固定变量的替换 145 | # 自动更新软件运行目录,即软件安装目录 146 | # Windows程序文件目录,例如C:\Program Files 147 | # Windows公共程序文件目录,例如C:\Program Files\Common Files 148 | # 用户桌面目录 149 | # Windows目录,例如C:\Windows 150 | # Windows系统文件目录,例如C:\Windows\System32 151 | # 临时文件目录,例如C:\Windows\Temp 152 | # 开始菜单目录 153 | # 开始菜单下的程序目录 154 | # 开始菜单下的启动目录 155 | # Windows任务条快速启动目录 156 | # 我的文档目录 157 | # 应用程序数据目录 158 | # 用户目录,例如C:\Documents and Settings\Administrator 159 | -------------------------------------------------------------------------------- /UpdateThread.cpp: -------------------------------------------------------------------------------- 1 | // UpdateThread.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "AutoUpdate.h" 6 | #include "InternetGetFile.h" 7 | #include "UpdateThread.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // CUpdateThread 17 | 18 | IMPLEMENT_DYNCREATE(CUpdateThread, CWinThread) 19 | 20 | CUpdateThread::CUpdateThread() 21 | { 22 | m_bSilenceMode = FALSE; 23 | m_bUserBreak = FALSE; 24 | m_fPercent = 0; 25 | m_hProgressWindow = NULL; 26 | } 27 | 28 | CUpdateThread::~CUpdateThread() 29 | { 30 | } 31 | 32 | BOOL CUpdateThread::InitInstance() 33 | { 34 | // TODO: perform and per-thread initialization here 35 | return TRUE; 36 | } 37 | 38 | int CUpdateThread::ExitInstance() 39 | { 40 | // TODO: perform any per-thread cleanup here 41 | m_bUserBreak = TRUE; 42 | 43 | return CWinThread::ExitInstance(); 44 | } 45 | 46 | BEGIN_MESSAGE_MAP(CUpdateThread, CWinThread) 47 | //{{AFX_MSG_MAP(CUpdateThread) 48 | // NOTE - the ClassWizard will add and remove mapping macros here. 49 | //}}AFX_MSG_MAP 50 | END_MESSAGE_MAP() 51 | 52 | ///////////////////////////////////////////////////////////////////////////// 53 | // CUpdateThread message handlers 54 | 55 | int CUpdateThread::Run() 56 | { 57 | if (DoUpdate()) 58 | { 59 | if (m_hProgressWindow) 60 | { 61 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_FINISH_UPDATE, (LPARAM)1); 62 | } 63 | return 1; 64 | } 65 | else 66 | { 67 | if (m_hProgressWindow) 68 | { 69 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_FINISH_UPDATE, (LPARAM)0); 70 | } 71 | return 0; 72 | } 73 | 74 | // return CWinThread::Run(); 75 | } 76 | 77 | // 执行升级 78 | BOOL CUpdateThread::DoUpdate() 79 | { 80 | if (m_sConfigFilename.IsEmpty()) 81 | { 82 | return FALSE; 83 | } 84 | 85 | UINT iCommonFileCount = 0; 86 | UINT iLanguageFileCount = 0; 87 | DOWNLOAD_INFO_STRU DownloadInfo = {0}; 88 | UINT i; 89 | const int BUFFER_SIZE = 512; 90 | char acBuffer[BUFFER_SIZE]; 91 | CString sSection; 92 | CString sLanguageSection; 93 | CString sKey; 94 | CString sFilename; 95 | CString sHash; 96 | CString sURL; 97 | CString sTemp; 98 | 99 | // 创建保存升级文件的目录 100 | CreateDirectory(GetAppDirectory() + "Update", NULL); 101 | 102 | // 取得公共文件数及文件大小总和 103 | iCommonFileCount = GetPrivateProfileInt(SECTION_COMMON, "FileCount", 0, 104 | m_sConfigFilename.GetBuffer(0)); 105 | for (i = 1; i <= iCommonFileCount; i++) 106 | { 107 | sSection.Format("CommonFile%d", i); 108 | DownloadInfo.iFileSize += GetPrivateProfileInt(sSection.GetBuffer(0), "Size", 0 109 | , m_sConfigFilename.GetBuffer(0)); 110 | } 111 | DownloadInfo.iFileCount += iCommonFileCount; 112 | 113 | // 取得与操作系统代码页相关的文件数及文件大小总和 114 | sKey.Format("%d", GetSystemDefaultLangID()); 115 | memset(acBuffer, 0, BUFFER_SIZE); 116 | GetPrivateProfileString(SECTION_LANGUAGE, sKey.GetBuffer(0) 117 | , "", (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 118 | sLanguageSection = (char*)acBuffer; 119 | 120 | if (sLanguageSection.IsEmpty()) 121 | { 122 | // 没有与操作系统代码页相关的语言,读取缺省的语言 123 | sKey = "Default"; 124 | memset(acBuffer, 0, BUFFER_SIZE); 125 | GetPrivateProfileString(SECTION_LANGUAGE, sKey.GetBuffer(0), "" 126 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 127 | sLanguageSection = (char*)acBuffer; 128 | } 129 | 130 | if (!sLanguageSection.IsEmpty()) 131 | { 132 | iLanguageFileCount = GetPrivateProfileInt(sLanguageSection.GetBuffer(0), "FileCount", 0 133 | , m_sConfigFilename.GetBuffer(0)); 134 | for (i = 1; i <= iLanguageFileCount; i++) 135 | { 136 | sSection.Format("%sFile%d", sLanguageSection.GetBuffer(0), i); 137 | DownloadInfo.iFileSize += GetPrivateProfileInt(sSection.GetBuffer(0), "Size", 0 138 | , m_sConfigFilename.GetBuffer(0)); 139 | } 140 | DownloadInfo.iFileCount += iLanguageFileCount; 141 | } 142 | 143 | // 将文件总数和文件大小总和上报到界面 144 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 145 | { 146 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_DOWNLOAD_INFO, (LPARAM)&DownloadInfo); 147 | } 148 | 149 | LOG(0, 0, "Total files to download is %u. Total file size is %u.", DownloadInfo.iFileCount, DownloadInfo.iFileSize); 150 | 151 | // 下载所有文件 152 | 153 | memset(&DownloadInfo, 0, sizeof(DOWNLOAD_INFO_STRU)); 154 | 155 | // 循环下载所有公共文件 156 | for (i = 1; i <= iCommonFileCount; i++) 157 | { 158 | if (m_bUserBreak) 159 | { 160 | return FALSE; 161 | } 162 | 163 | sSection.Format("CommonFile%d", i); 164 | if (!DownloadFile(sSection)) 165 | { 166 | // 文件下载失败,升级失败 167 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 168 | { 169 | sKey = "Name"; 170 | memset(acBuffer, 0, BUFFER_SIZE); 171 | GetPrivateProfileString(sSection.GetBuffer(0), sKey.GetBuffer(0), "" 172 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 173 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_DOWNLOAD_FILE_FAIL, (LPARAM)acBuffer); 174 | } 175 | return FALSE; 176 | } 177 | 178 | // 将升级进度上报到界面 179 | DownloadInfo.iFileCount++; 180 | DownloadInfo.iFileSize += GetPrivateProfileInt(sSection.GetBuffer(0), "Size", 0 181 | , m_sConfigFilename.GetBuffer(0)); 182 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 183 | { 184 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_DOWNLOADED_INFO, (LPARAM)&DownloadInfo); 185 | } 186 | LOG(0, 0, "CUpdateThread::DoUpdate : Finished files %u (%u bytes).", DownloadInfo.iFileCount, DownloadInfo.iFileSize); 187 | } 188 | // 根据操作系统代码页下载所有相应语言的文件 189 | if (!sLanguageSection.IsEmpty()) 190 | { 191 | for (i = 1; i <= iLanguageFileCount; i++) 192 | { 193 | if (m_bUserBreak) 194 | { 195 | return FALSE; 196 | } 197 | 198 | sSection.Format("%sFile%d", sLanguageSection.GetBuffer(0), i); 199 | if (!DownloadFile(sSection)) 200 | { 201 | // 文件下载失败,升级失败 202 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 203 | { 204 | sKey = "Name"; 205 | memset(acBuffer, 0, BUFFER_SIZE); 206 | GetPrivateProfileString(sSection.GetBuffer(0), sKey.GetBuffer(0), "" 207 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 208 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_DOWNLOAD_FILE_FAIL, (LPARAM)acBuffer); 209 | } 210 | return FALSE; 211 | } 212 | 213 | // 将升级进度上报到界面 214 | DownloadInfo.iFileCount++; 215 | DownloadInfo.iFileSize += GetPrivateProfileInt(sSection.GetBuffer(0), "Size", 0 216 | , m_sConfigFilename.GetBuffer(0)); 217 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 218 | { 219 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_DOWNLOADED_INFO, (LPARAM)&DownloadInfo); 220 | } 221 | LOG(0, 0, "CUpdateThread::DoUpdate : Finished files %u (%u bytes).", DownloadInfo.iFileCount, DownloadInfo.iFileSize); 222 | } 223 | } 224 | 225 | // 下载完毕后校验文件 226 | 227 | // 循环校验所有公共文件 228 | for (i = 1; i <= iCommonFileCount; i++) 229 | { 230 | if (m_bUserBreak) 231 | { 232 | return FALSE; 233 | } 234 | 235 | sSection.Format("CommonFile%d", i); 236 | if (!VerifyFile(sSection)) 237 | { 238 | // 文件校验不通过,升级失败 239 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 240 | { 241 | sKey = "Name"; 242 | memset(acBuffer, 0, BUFFER_SIZE); 243 | GetPrivateProfileString(sSection.GetBuffer(0), sKey.GetBuffer(0), "" 244 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 245 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_VERIFY_FILE_FAIL, (LPARAM)acBuffer); 246 | } 247 | return FALSE; 248 | } 249 | } 250 | // 循环校验所有文件 251 | for (i = 1; i <= iLanguageFileCount; i++) 252 | { 253 | if (m_bUserBreak) 254 | { 255 | return FALSE; 256 | } 257 | 258 | sTemp.Format("%sFile%d", sLanguageSection.GetBuffer(0), i); 259 | if (!VerifyFile(sTemp)) 260 | { 261 | // 文件校验不通过,升级失败 262 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 263 | { 264 | sKey = "Name"; 265 | memset(acBuffer, 0, BUFFER_SIZE); 266 | GetPrivateProfileString(sSection.GetBuffer(0), sKey.GetBuffer(0), "" 267 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 268 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_VERIFY_FILE_FAIL, (LPARAM)acBuffer); 269 | } 270 | return FALSE; 271 | } 272 | } 273 | 274 | // 复制、更新文件 275 | 276 | // 创建备份文件目录 277 | CreateDirectory((GetAppDirectory() + "Backup").GetBuffer(0), NULL); 278 | // 循环更新所有文件 279 | for (i = 1; i <= iCommonFileCount; i++) 280 | { 281 | if (m_bUserBreak) 282 | { 283 | return FALSE; 284 | } 285 | 286 | sSection.Format("CommonFile%d", i); 287 | if (!UpdateFile(sSection)) 288 | { 289 | // 文件更新不成功,升级失败 290 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 291 | { 292 | sKey = "Name"; 293 | memset(acBuffer, 0, BUFFER_SIZE); 294 | GetPrivateProfileString(sSection.GetBuffer(0), sKey.GetBuffer(0), "" 295 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 296 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_UPDATE_FILE_FAIL, (LPARAM)acBuffer); 297 | } 298 | return FALSE; 299 | } 300 | } 301 | // 循环更新所有文件 302 | for (i = 1; i <= iLanguageFileCount; i++) 303 | { 304 | if (m_bUserBreak) 305 | { 306 | return FALSE; 307 | } 308 | 309 | sTemp.Format("%sFile%d", sLanguageSection.GetBuffer(0), i); 310 | if (!UpdateFile(sTemp)) 311 | { 312 | // 文件校验不通过,升级失败 313 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 314 | { 315 | sKey = "Name"; 316 | memset(acBuffer, 0, BUFFER_SIZE); 317 | GetPrivateProfileString(sSection.GetBuffer(0), sKey.GetBuffer(0), "" 318 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 319 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_UPDATE_FILE_FAIL, (LPARAM)acBuffer); 320 | } 321 | return FALSE; 322 | } 323 | } 324 | 325 | // 执行升级程序 326 | sKey = "RunAfterDownload"; 327 | memset(acBuffer, 0, BUFFER_SIZE); 328 | GetPrivateProfileString(SECTION_UPDATE, sKey.GetBuffer(0), "" 329 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 330 | sFilename = (char*)acBuffer; 331 | 332 | if (!sFilename.IsEmpty()) 333 | { 334 | LOG(0, 0, "Run \"%s\" after downloading and verifying.", sFilename.GetBuffer(0)); 335 | ShellExecute(NULL, "open", (GetAppDirectory() + "Update\\" + sFilename).GetBuffer(0), "", "", SW_NORMAL); 336 | } 337 | 338 | // 通知界面升级完毕 339 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 340 | { 341 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_FINISH_UPDATE, 0); 342 | } 343 | 344 | return TRUE; 345 | } 346 | 347 | // 检查并下载一个文件 348 | BOOL CUpdateThread::DownloadFile(CString &sFileSection) 349 | { 350 | const int BUFFER_SIZE = 512; 351 | char acBuffer[BUFFER_SIZE]; 352 | CString sFilename; 353 | CString sHash; 354 | CString sURL; 355 | CString sKey; 356 | 357 | LOG(0, 0, "CUpdateThread::DownloadFile : sFileSection = %s.", sFileSection.GetBuffer(0)); 358 | 359 | // 比较文件是否已经下载了,如是则跳过 360 | if (VerifyFile(sFileSection)) 361 | { 362 | return TRUE; 363 | } 364 | 365 | // 取得文件名 366 | sKey = "Name"; 367 | memset(acBuffer, 0, BUFFER_SIZE); 368 | GetPrivateProfileString(sFileSection.GetBuffer(0), sKey.GetBuffer(0), "" 369 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 370 | sFilename = (char*)acBuffer; 371 | 372 | LOG(0, 0, "Start downloading file %s.", sFilename.GetBuffer(0)); 373 | 374 | // 取得文件URL 375 | sKey = "URL"; 376 | memset(acBuffer, 0, BUFFER_SIZE); 377 | GetPrivateProfileString(sFileSection.GetBuffer(0), sKey.GetBuffer(0), "" 378 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 379 | sURL = (char*)acBuffer; 380 | 381 | // 更新显示正在下载的文件 382 | // 下载文件 383 | if (!m_bSilenceMode && m_hProgressWindow != NULL) 384 | { 385 | SendMessage(m_hProgressWindow, WM_USER, (WPARAM)NOTIFY_DOWNLOADING_FILENAME 386 | , (LPARAM)sFilename.GetBuffer(0)); 387 | } 388 | if (Internet::InternetGetURL(sURL.GetBuffer(0) 389 | , (GetAppDirectory() + "Update\\" + sFilename).GetBuffer(0) 390 | , NULL 391 | , m_hProgressWindow) 392 | != Internet::INTERNET_SUCCESS) 393 | { 394 | // 记录下载文件失败日志 395 | LOG(0, 0, "Fail to download file \"%s\".", sFilename.GetBuffer(0)); 396 | return FALSE; 397 | } 398 | 399 | return TRUE; 400 | } 401 | 402 | // 校验文件 403 | BOOL CUpdateThread::VerifyFile(CString &sFileSection) 404 | { 405 | const int BUFFER_SIZE = 512; 406 | char acBuffer[BUFFER_SIZE]; 407 | CString sFilename; 408 | UINT iFileSize; 409 | CString sHash; 410 | CString sKey; 411 | 412 | LOG(0, 0, "CUpdateThread::VerifyFile : sFileSection = %s.", sFileSection.GetBuffer(0)); 413 | 414 | // 取得文件名 415 | sKey = "Name"; 416 | memset(acBuffer, 0, BUFFER_SIZE); 417 | GetPrivateProfileString(sFileSection.GetBuffer(0), sKey.GetBuffer(0), "" 418 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 419 | sFilename = (char*)acBuffer; 420 | 421 | // 取得文件大小 422 | sKey = "Size"; 423 | iFileSize = GetPrivateProfileInt(sFileSection.GetBuffer(0), sKey.GetBuffer(0) 424 | , 0, m_sConfigFilename.GetBuffer(0)); 425 | 426 | if (GetFileSize(GetAppDirectory() + "Update\\" + sFilename) == iFileSize) 427 | { 428 | sKey = "Hash"; 429 | memset(acBuffer, 0, BUFFER_SIZE); 430 | GetPrivateProfileString(sFileSection.GetBuffer(0), sKey.GetBuffer(0), "" 431 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 432 | sHash = (char*)acBuffer; 433 | 434 | // 计算文件的Hash码以进行比较 435 | unsigned char acMD5Digest[16]; 436 | CalculateMD5((GetAppDirectory() + "Update\\" + sFilename).GetBuffer(0), acMD5Digest); 437 | 438 | if (sHash.CompareNoCase(MD5toString(acMD5Digest)) == 0) 439 | { 440 | return TRUE; 441 | } 442 | else 443 | { 444 | LOG(0, 0, "Fail in verifying file \"%s\".", sFilename.GetBuffer(0)); 445 | } 446 | } 447 | 448 | return FALSE; 449 | } 450 | 451 | // 更新文件 452 | BOOL CUpdateThread::UpdateFile(CString &sFileSection) 453 | { 454 | const int BUFFER_SIZE = 512; 455 | char acBuffer[BUFFER_SIZE]; 456 | CString sFilename; 457 | CString sFileSubcatalog; 458 | CString sDestFilename; 459 | CString sBackupFilename; 460 | CString sKey; 461 | 462 | // 取得文件名 463 | sKey = "Name"; 464 | memset(acBuffer, 0, BUFFER_SIZE); 465 | GetPrivateProfileString(sFileSection.GetBuffer(0), sKey.GetBuffer(0), "" 466 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 467 | sFilename = (char*)acBuffer; 468 | 469 | // 取得子目录结构 470 | sKey = "Subcatalog"; 471 | memset(acBuffer, 0, BUFFER_SIZE); 472 | GetPrivateProfileString(sFileSection.GetBuffer(0), sKey.GetBuffer(0), "" 473 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 474 | sFileSubcatalog = (char*)acBuffer; 475 | 476 | // 取得目标文件名 477 | sKey = "DestPath"; 478 | memset(acBuffer, 0, BUFFER_SIZE); 479 | GetPrivateProfileString(sFileSection.GetBuffer(0), sKey.GetBuffer(0), "" 480 | , (char*)acBuffer, BUFFER_SIZE, m_sConfigFilename.GetBuffer(0)); 481 | sDestFilename = (char*)acBuffer; 482 | sDestFilename.TrimLeft(); 483 | sDestFilename.TrimRight(); 484 | if (sDestFilename.IsEmpty()) 485 | { 486 | // 无目标目录,文件无需复制 487 | return TRUE; 488 | } 489 | sDestFilename += sFileSubcatalog + sFilename; 490 | 491 | // 替换变量字符串为系统变量 492 | sDestFilename = ResolvePath(sDestFilename.GetBuffer(0)); 493 | 494 | // 备份原文件 495 | sBackupFilename = GetAppDirectory() + "Backup\\" + sFilename; 496 | if (GetFileSize(sDestFilename) > 0) 497 | { 498 | char acBuffer[MAX_PATH] = {0}; 499 | 500 | // 取得本自动升级程序的文件全路径 501 | GetModuleFileName(AfxGetInstanceHandle(), acBuffer, sizeof(acBuffer)); 502 | 503 | if (sFilename.CompareNoCase(GetFilename(acBuffer)) == 0) 504 | { 505 | // 要更新的文件是本自动升级程序,须换名更新 506 | CopyFile(sDestFilename.GetBuffer(0), sBackupFilename.GetBuffer(0), FALSE); 507 | // 复制新文件,新文件名加上 .new 后缀,由主程序来将其更名 508 | sDestFilename += ".new"; 509 | return CopyFile((GetAppDirectory() + "Update\\" + sFilename).GetBuffer(0), sDestFilename.GetBuffer(0), FALSE); 510 | } 511 | else 512 | { 513 | MoveFile(sDestFilename.GetBuffer(0), sBackupFilename.GetBuffer(0)); 514 | } 515 | } 516 | 517 | // 如果输出目录在子目录中,则创建对应的目录结构 518 | if (sFileSubcatalog!="") 519 | { 520 | CString csTemp = sFileSubcatalog.Left(strlen(sFileSubcatalog)-1); 521 | CreateDirectory(GetAppDirectory() + csTemp, NULL); 522 | } 523 | 524 | // 复制新文件 525 | return CopyFile((GetAppDirectory() + "Update\\" + sFilename).GetBuffer(0), sDestFilename.GetBuffer(0), FALSE); 526 | } 527 | -------------------------------------------------------------------------------- /UpdateThread.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 文件名称:UpdateThread.h 3 | // 文件版本:v1.0 4 | // 创建日期:2006-05-04 14:25 5 | // 作 者:Richard Ree 6 | // 文件描述:自动升级线程类 7 | //------------------------------------------------------------------------------ 8 | 9 | #if !defined(AFX_UPDATETHREAD_H__194A514F_A0D7_4ADD_8D2A_9E7081810D82__INCLUDED_) 10 | #define AFX_UPDATETHREAD_H__194A514F_A0D7_4ADD_8D2A_9E7081810D82__INCLUDED_ 11 | 12 | #if _MSC_VER > 1000 13 | #pragma once 14 | #endif // _MSC_VER > 1000 15 | 16 | // UpdateThread.h : header file 17 | // 18 | 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // CUpdateThread thread 21 | 22 | class CUpdateThread : public CWinThread 23 | { 24 | DECLARE_DYNCREATE(CUpdateThread) 25 | protected: 26 | 27 | // Attributes 28 | public: 29 | CString m_sConfigFilename; // 升级配置文件名 30 | BOOL m_bSilenceMode; // 静默方式执行升级,不显示升级程序界面,只在升级完毕后提醒用户 31 | BOOL m_bUserBreak; // 用户终止升级 32 | double m_fPercent; // 下载文件进度百分比 33 | HWND m_hProgressWindow; // 显示升级进度的窗口句柄 34 | 35 | // Operations 36 | public: 37 | CUpdateThread(); // protected constructor used by dynamic creation 38 | BOOL DoUpdate(); // 执行升级 39 | 40 | // Overrides 41 | // ClassWizard generated virtual function overrides 42 | //{{AFX_VIRTUAL(CUpdateThread) 43 | public: 44 | virtual BOOL InitInstance(); 45 | virtual int ExitInstance(); 46 | virtual int Run(); 47 | //}}AFX_VIRTUAL 48 | 49 | // Implementation 50 | protected: 51 | virtual ~CUpdateThread(); 52 | 53 | // Generated message map functions 54 | //{{AFX_MSG(CUpdateThread) 55 | // NOTE - the ClassWizard will add and remove member functions here. 56 | //}}AFX_MSG 57 | 58 | DECLARE_MESSAGE_MAP() 59 | 60 | private: 61 | BOOL DownloadFile(CString& sFileSection); // 下载文件 62 | BOOL VerifyFile(CString &sFileSection); // 校验文件 63 | BOOL UpdateFile(CString &sFileSection); // 更新文件 64 | }; 65 | 66 | ///////////////////////////////////////////////////////////////////////////// 67 | 68 | //{{AFX_INSERT_LOCATION}} 69 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 70 | 71 | #endif // !defined(AFX_UPDATETHREAD_H__194A514F_A0D7_4ADD_8D2A_9E7081810D82__INCLUDED_) 72 | -------------------------------------------------------------------------------- /md5.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Copyright (C) 2000 by Robert Hubley. * 3 | * All rights reserved. * 4 | * * 5 | * This software is provided ``AS IS'' and any express or implied * 6 | * warranties, including, but not limited to, the implied warranties of * 7 | * merchantability and fitness for a particular purpose, are disclaimed. * 8 | * In no event shall the authors be liable for any direct, indirect, * 9 | * incidental, special, exemplary, or consequential damages (including, but * 10 | * not limited to, procurement of substitute goods or services; loss of use, * 11 | * data, or profits; or business interruption) however caused and on any * 12 | * theory of liability, whether in contract, strict liability, or tort * 13 | * (including negligence or otherwise) arising in any way out of the use of * 14 | * this software, even if advised of the possibility of such damage. * 15 | * * 16 | ****************************************************************************** 17 | 18 | MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 19 | 20 | Port to Win32 DLL by Robert Hubley 1/5/2000 21 | 22 | Original Copyright: 23 | 24 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 25 | rights reserved. 26 | 27 | License to copy and use this software is granted provided that it 28 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 29 | Algorithm" in all material mentioning or referencing this software 30 | or this function. 31 | 32 | License is also granted to make and use derivative works provided 33 | that such works are identified as "derived from the RSA Data 34 | Security, Inc. MD5 Message-Digest Algorithm" in all material 35 | mentioning or referencing the derived work. 36 | 37 | RSA Data Security, Inc. makes no representations concerning either 38 | the merchantability of this software or the suitability of this 39 | software for any particular purpose. It is provided "as is" 40 | without express or implied warranty of any kind. 41 | 42 | These notices must be retained in any copies of any part of this 43 | documentation and/or software. 44 | */ 45 | 46 | #include "stdafx.h" 47 | #ifdef _WIN32 48 | # include 49 | #endif 50 | #include "md5.h" 51 | 52 | /* Constants for MD5Transform routine. 53 | */ 54 | #define S11 7 55 | #define S12 12 56 | #define S13 17 57 | #define S14 22 58 | #define S21 5 59 | #define S22 9 60 | #define S23 14 61 | #define S24 20 62 | #define S31 4 63 | #define S32 11 64 | #define S33 16 65 | #define S34 23 66 | #define S41 6 67 | #define S42 10 68 | #define S43 15 69 | #define S44 21 70 | 71 | /* F, G, H and I are basic MD5 functions. 72 | */ 73 | #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 74 | #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 75 | #define H(x, y, z) ((x) ^ (y) ^ (z)) 76 | #define I(x, y, z) ((y) ^ ((x) | (~z))) 77 | 78 | /* ROTATE_LEFT rotates x left n bits. 79 | */ 80 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 81 | 82 | /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 83 | Rotation is separate from addition to prevent recomputation. 84 | */ 85 | #define FF(a, b, c, d, x, s, ac) { \ 86 | (a) += F ((b), (c), (d)) + (x) + (unsigned long int)(ac); \ 87 | (a) = ROTATE_LEFT ((a), (s)); \ 88 | (a) += (b); \ 89 | } 90 | #define GG(a, b, c, d, x, s, ac) { \ 91 | (a) += G ((b), (c), (d)) + (x) + (unsigned long int)(ac); \ 92 | (a) = ROTATE_LEFT ((a), (s)); \ 93 | (a) += (b); \ 94 | } 95 | #define HH(a, b, c, d, x, s, ac) { \ 96 | (a) += H ((b), (c), (d)) + (x) + (unsigned long int)(ac); \ 97 | (a) = ROTATE_LEFT ((a), (s)); \ 98 | (a) += (b); \ 99 | } 100 | #define II(a, b, c, d, x, s, ac) { \ 101 | (a) += I ((b), (c), (d)) + (x) + (unsigned long int)(ac); \ 102 | (a) = ROTATE_LEFT ((a), (s)); \ 103 | (a) += (b); \ 104 | } 105 | 106 | MD5_CTX::MD5_CTX() 107 | { 108 | MD5Init(); 109 | } 110 | 111 | MD5_CTX::~MD5_CTX() 112 | { 113 | } 114 | 115 | /* MD5 initialization. Begins an MD5 operation, writing a new context. 116 | */ 117 | void MD5_CTX::MD5Init() 118 | { 119 | this->count[0] = this->count[1] = 0; 120 | /* Load magic initialization constants.*/ 121 | this->state[0] = 0x67452301; 122 | this->state[1] = 0xefcdab89; 123 | this->state[2] = 0x98badcfe; 124 | this->state[3] = 0x10325476; 125 | MD5_memset (PADDING, 0, sizeof(PADDING)); 126 | *PADDING = 0x80; 127 | } 128 | 129 | /* MD5 block update operation. Continues an MD5 message-digest 130 | operation, processing another message block, and updating the 131 | context. 132 | */ 133 | void MD5_CTX::MD5Update (unsigned char *input, unsigned int inputLen) 134 | { 135 | unsigned int i, index, partLen; 136 | 137 | /* Compute number of bytes mod 64 */ 138 | index = (unsigned int)((this->count[0] >> 3) & 0x3F); 139 | 140 | /* Update number of bits */ 141 | if ((this->count[0] += ((unsigned long int)inputLen << 3)) 142 | < ((unsigned long int)inputLen << 3)) 143 | { 144 | this->count[1]++; 145 | } 146 | this->count[1] += ((unsigned long int)inputLen >> 29); 147 | 148 | partLen = 64 - index; 149 | 150 | /* Transform as many times as possible. */ 151 | if (inputLen >= partLen) 152 | { 153 | MD5_memcpy ((unsigned char*)&this->buffer[index], 154 | (unsigned char*)input, partLen); 155 | MD5Transform (this->state, this->buffer); 156 | for (i = partLen; i + 63 < inputLen; i += 64) 157 | { 158 | MD5Transform (this->state, &input[i]); 159 | } 160 | index = 0; 161 | } 162 | else 163 | { 164 | i = 0; 165 | } 166 | 167 | /* Buffer remaining input */ 168 | MD5_memcpy ((unsigned char*)&this->buffer[index], (unsigned char*)&input[i], inputLen-i); 169 | } 170 | 171 | /* MD5 finalization. Ends an MD5 message-digest operation, writing the 172 | the message digest and zeroizing the context. 173 | */ 174 | void MD5_CTX::MD5Final (unsigned char digest[16]) 175 | { 176 | unsigned char bits[8]; 177 | unsigned int index, padLen; 178 | 179 | /* Save number of bits */ 180 | Encode (bits, this->count, 8); 181 | 182 | /* Pad out to 56 mod 64. */ 183 | index = (unsigned int)((this->count[0] >> 3) & 0x3f); 184 | padLen = (index < 56) ? (56 - index) : (120 - index); 185 | MD5Update ( PADDING, padLen); 186 | 187 | /* Append length (before padding) */ 188 | MD5Update (bits, 8); 189 | /* Store state in digest */ 190 | Encode (digest, this->state, 16); 191 | 192 | /* Zeroize sensitive information. */ 193 | MD5_memset ((unsigned char*)this, 0, sizeof (*this)); 194 | this->MD5Init(); 195 | } 196 | 197 | /* MD5 basic transformation. Transforms state based on block. 198 | */ 199 | void MD5_CTX::MD5Transform (unsigned long int state[4], unsigned char block[64]) 200 | { 201 | unsigned long int a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 202 | 203 | Decode (x, block, 64); 204 | 205 | /* Round 1 */ 206 | FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ 207 | FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ 208 | FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ 209 | FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ 210 | FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ 211 | FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ 212 | FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ 213 | FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ 214 | FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ 215 | FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ 216 | FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 217 | FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 218 | FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 219 | FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 220 | FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 221 | FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 222 | 223 | /* Round 2 */ 224 | GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ 225 | GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ 226 | GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 227 | GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ 228 | GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ 229 | GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */ 230 | GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 231 | GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ 232 | GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ 233 | GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 234 | GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ 235 | GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ 236 | GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 237 | GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ 238 | GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ 239 | GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 240 | 241 | /* Round 3 */ 242 | HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ 243 | HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ 244 | HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 245 | HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 246 | HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ 247 | HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ 248 | HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ 249 | HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 250 | HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 251 | HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ 252 | HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ 253 | HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */ 254 | HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ 255 | HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 256 | HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 257 | HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ 258 | 259 | /* Round 4 */ 260 | II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ 261 | II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ 262 | II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 263 | II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ 264 | II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 265 | II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ 266 | II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 267 | II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ 268 | II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ 269 | II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 270 | II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ 271 | II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 272 | II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ 273 | II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 274 | II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ 275 | II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ 276 | 277 | state[0] += a; 278 | state[1] += b; 279 | state[2] += c; 280 | state[3] += d; 281 | 282 | /* Zeroize sensitive information. */ 283 | MD5_memset ((unsigned char*)x, 0, sizeof (x)); 284 | } 285 | 286 | /* Encodes input (unsigned long int) into output (unsigned char). Assumes len is 287 | a multiple of 4. 288 | */ 289 | void MD5_CTX::Encode (unsigned char *output, unsigned long int *input,unsigned int len) 290 | { 291 | unsigned int i, j; 292 | 293 | for (i = 0, j = 0; j < len; i++, j += 4) 294 | { 295 | output[j] = (unsigned char)(input[i] & 0xff); 296 | output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 297 | output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 298 | output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 299 | } 300 | } 301 | 302 | /* Decodes input (unsigned char) into output (unsigned long int). Assumes len is 303 | a multiple of 4. 304 | */ 305 | void MD5_CTX::Decode (unsigned long int *output, unsigned char *input, unsigned int len) 306 | { 307 | unsigned int i, j; 308 | 309 | for (i = 0, j = 0; j < len; i++, j += 4) 310 | { 311 | output[i] = ((unsigned long int)input[j]) 312 | | (((unsigned long int)input[j+1]) << 8) 313 | | (((unsigned long int)input[j+2]) << 16) 314 | | (((unsigned long int)input[j+3]) << 24); 315 | } 316 | } 317 | 318 | #ifndef _WIN32 319 | 320 | /* Note: Replace "for loop" with standard memcpy if possible. 321 | */ 322 | void MD5_CTX::MD5_memcpy (unsigned char* output, unsigned char* input, unsigned int len) 323 | { 324 | unsigned int i; 325 | 326 | for (i = 0; i < len; i++) 327 | { 328 | output[i] = input[i]; 329 | } 330 | } 331 | 332 | /* Note: Replace "for loop" with standard memset if possible. 333 | */ 334 | void MD5_CTX::MD5_memset (unsigned char* output, int value, unsigned int len) 335 | { 336 | unsigned int i; 337 | 338 | for (i = 0; i < len; i++) 339 | { 340 | ((char *)output)[i] = (char)value; 341 | } 342 | } 343 | 344 | #endif /* #ifndef _WIN32 */ 345 | -------------------------------------------------------------------------------- /md5.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Copyright (C) 2000 by Robert Hubley. * 3 | * All rights reserved. * 4 | * * 5 | * This software is provided ``AS IS'' and any express or implied * 6 | * warranties, including, but not limited to, the implied warranties of * 7 | * merchantability and fitness for a particular purpose, are disclaimed. * 8 | * In no event shall the authors be liable for any direct, indirect, * 9 | * incidental, special, exemplary, or consequential damages (including, but * 10 | * not limited to, procurement of substitute goods or services; loss of use, * 11 | * data, or profits; or business interruption) however caused and on any * 12 | * theory of liability, whether in contract, strict liability, or tort * 13 | * (including negligence or otherwise) arising in any way out of the use of * 14 | * this software, even if advised of the possibility of such damage. * 15 | * * 16 | ****************************************************************************** 17 | 18 | MD5.H - header file for MD5C.C 19 | 20 | Port to Win32 DLL by Robert Hubley 1/5/2000 21 | 22 | Original Copyright: 23 | 24 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 25 | rights reserved. 26 | 27 | License to copy and use this software is granted provided that it 28 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 29 | Algorithm" in all material mentioning or referencing this software 30 | or this function. 31 | 32 | License is also granted to make and use derivative works provided 33 | that such works are identified as "derived from the RSA Data 34 | Security, Inc. MD5 Message-Digest Algorithm" in all material 35 | mentioning or referencing the derived work. 36 | 37 | RSA Data Security, Inc. makes no representations concerning either 38 | the merchantability of this software or the suitability of this 39 | software for any particular purpose. It is provided "as is" 40 | without express or implied warranty of any kind. 41 | 42 | These notices must be retained in any copies of any part of this 43 | documentation and/or software. 44 | */ 45 | /****************************************************************************** 46 | * Copyright (C) 2000 by Robert Hubley. * 47 | * All rights reserved. * 48 | * * 49 | * This software is provided ``AS IS'' and any express or implied * 50 | * warranties, including, but not limited to, the implied warranties of * 51 | * merchantability and fitness for a particular purpose, are disclaimed. * 52 | * In no event shall the authors be liable for any direct, indirect, * 53 | * incidental, special, exemplary, or consequential damages (including, but * 54 | * not limited to, procurement of substitute goods or services; loss of use, * 55 | * data, or profits; or business interruption) however caused and on any * 56 | * theory of liability, whether in contract, strict liability, or tort * 57 | * (including negligence or otherwise) arising in any way out of the use of * 58 | * this software, even if advised of the possibility of such damage. * 59 | * * 60 | ****************************************************************************** 61 | */ 62 | 63 | /****************************************************************************** 64 | * 2002-4-18 Modified by Liguangyi. * 65 | * struct MD5_CTX ==> class MD5_CTX. * 66 | * Take off the Globals Functions * 67 | ****************************************************************************** 68 | */ 69 | 70 | #ifndef _LGY_MD5_H 71 | #define _LGY_MD5_H 72 | 73 | /* MD5 Class. */ 74 | class MD5_CTX 75 | { 76 | public: 77 | MD5_CTX(); 78 | virtual ~MD5_CTX(); 79 | void MD5Update (unsigned char *input, unsigned int inputLen); 80 | void MD5Final (unsigned char digest[16]); 81 | 82 | private: 83 | unsigned long int state[4]; /* state (ABCD) */ 84 | unsigned long int count[2]; /* number of bits, modulo 2^64 (lsb first) */ 85 | unsigned char buffer[64]; /* input buffer */ 86 | unsigned char PADDING[64]; /* What? */ 87 | 88 | private: 89 | void MD5Init (); 90 | void MD5Transform (unsigned long int state[4], unsigned char block[64]); 91 | void Encode (unsigned char* output, unsigned long int* input, unsigned int len); 92 | void Decode (unsigned long int* output, unsigned char* input, unsigned int len); 93 | #ifndef _WIN32 94 | void MD5_memcpy (unsigned char* output, unsigned char* input, unsigned int len); 95 | void MD5_memset (unsigned char* output, int value, unsigned int len); 96 | #else 97 | # define MD5_memcpy memcpy 98 | # define MD5_memset memset 99 | #endif /* #ifndef _WIN32 */ 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /res/AutoUpdate.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuili/AutoUpdate/a8fe3bd4ef4b3b4cef8010bec4fc25a663a5a95e/res/AutoUpdate.ico -------------------------------------------------------------------------------- /res/AutoUpdate.rc2: -------------------------------------------------------------------------------- 1 | // 2 | // AUTOUPDATE.RC2 - resources Microsoft Visual C++ does not edit directly 3 | // 4 | 5 | #ifdef APSTUDIO_INVOKED 6 | #error this file is not editable by Microsoft Visual C++ 7 | #endif //APSTUDIO_INVOKED 8 | 9 | 10 | ///////////////////////////////////////////////////////////////////////////// 11 | // Add manually edited resources here... 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | -------------------------------------------------------------------------------- /res/button01.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuili/AutoUpdate/a8fe3bd4ef4b3b4cef8010bec4fc25a663a5a95e/res/button01.bmp -------------------------------------------------------------------------------- /res/button_system_control.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuili/AutoUpdate/a8fe3bd4ef4b3b4cef8010bec4fc25a663a5a95e/res/button_system_control.bmp -------------------------------------------------------------------------------- /res/title01.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuili/AutoUpdate/a8fe3bd4ef4b3b4cef8010bec4fc25a663a5a95e/res/title01.bmp -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by AutoUpdate.rc 4 | // 5 | #define IDM_ABOUTBOX 0x0010 6 | #define IDD_ABOUTBOX 100 7 | #define IDS_ABOUTBOX 101 8 | #define IDD_AUTOUPDATE 102 9 | #define IDD_MESSAGEBOX 103 10 | #define IDC_BUTTON_OK 118 11 | #define IDC_BUTTON_CANCEL 119 12 | #define IDC_BUTTON_YES 120 13 | #define IDC_BUTTON_NO 121 14 | #define IDC_BUTTON_ABORT 122 15 | #define IDC_BUTTON_RETRY 123 16 | #define IDC_BUTTON_IGANORE 124 17 | #define IDC_BUTTON_CONTINUE 125 18 | #define IDC_CHECK_OPTION2 126 19 | #define IDC_CHECK_OPTION1 127 20 | #define IDR_MAINFRAME 128 21 | #define IDB_TITLEBAR 129 22 | #define IDB_BUTTON 130 23 | #define IDC_BUTTON_MINIMIZE 131 24 | #define IDC_BUTTON_MAXIMIZE 132 25 | #define IDC_BUTTON_CLOSE 133 26 | #define IDC_STATIC_PROMPT 134 27 | #define IDC_STATIC_PROGRESS 135 28 | #define IDC_STATIC_ICON 136 29 | #define IDC_STATIC_PROMPT_TOTAL_PROGRESS 137 30 | #define IDC_STATIC_TOTAL_PROGRESS 138 31 | #define IDB_SYSTEM_CONTROL_BUTTON 139 32 | 33 | // Next default values for new objects 34 | // 35 | #ifdef APSTUDIO_INVOKED 36 | #ifndef APSTUDIO_READONLY_SYMBOLS 37 | #define _APS_NEXT_RESOURCE_VALUE 140 38 | #define _APS_NEXT_COMMAND_VALUE 32771 39 | #define _APS_NEXT_CONTROL_VALUE 1002 40 | #define _APS_NEXT_SYMED_VALUE 101 41 | #endif 42 | #endif 43 | --------------------------------------------------------------------------------