├── .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 |
--------------------------------------------------------------------------------