CUpdateWnd.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #include "../pch/pch.h"
  2. #include "CUpdateWnd.h"
  3. double CUpdateWnd::m_Percent;
  4. void CUpdateWnd::Init()
  5. {
  6. std::thread(&CUpdateWnd::Run, this).detach();
  7. }
  8. void CUpdateWnd::Notify(TNotifyUI& msg)
  9. {
  10. if(msg.sType == _T("click"))
  11. {
  12. if(msg.pSender->GetName() == _T("closebtn"))
  13. {
  14. PostQuitMessage(0);
  15. return;
  16. }
  17. else if(msg.pSender->GetName() == _T("guanwang"))
  18. {
  19. ShellExecute(NULL, _T("open"), _T("explorer.exe"), _T("https://www.qiaoba.ren"), NULL, SW_SHOW);
  20. }
  21. }
  22. else if(msg.sType == _T("itemselect"))
  23. {
  24. CDuiString name = msg.pSender->GetName();
  25. if(name == _T("accountcombo"))
  26. {
  27. CComboUI* pCom = static_cast<CComboUI*>(m_pm.FindControl(_T("accountcombo")));
  28. std::wstring name = pCom->GetItemAt(pCom->GetCurSel())->GetText();
  29. std::string password = CSetting::GetUser(CLewaimaiString::UnicodeToUTF8(name));
  30. std::wstring wspassword = CLewaimaiString::UTF8ToUnicode(password);
  31. CEditUI* pEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
  32. pEdit->SetText(name.c_str());
  33. CEditUI* pPassword = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
  34. pPassword->SetText(wspassword.c_str());
  35. }
  36. }
  37. }
  38. LRESULT CUpdateWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  39. {
  40. LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
  41. styleValue &= ~WS_CAPTION;
  42. ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  43. // 把自己的窗口句柄与窗口绘制管理器挂接在一起
  44. m_pm.Init(m_hWnd);
  45. m_pm.AddPreMessageFilter(this);
  46. CDialogBuilder builder;
  47. CControlUI* pRoot = builder.Create(_T("update.xml"), (UINT)0, NULL, &m_pm);
  48. ASSERT(pRoot && "Failed to parse XML");
  49. // 把这些控件绘制到本窗口上
  50. m_pm.AttachDialog(pRoot);
  51. // 把自己加入到CPaintManagerUI的m_aNotifiers数组中,用于处理Notify函数
  52. m_pm.AddNotifier(this);
  53. Init();
  54. return 0;
  55. }
  56. LRESULT CUpdateWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  57. {
  58. bHandled = FALSE;
  59. return 0;
  60. }
  61. /*
  62. *这个是窗口被销毁的时候调用的
  63. **/
  64. LRESULT CUpdateWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  65. {
  66. bHandled = FALSE;
  67. return 0;
  68. }
  69. LRESULT CUpdateWnd::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  70. {
  71. if(::IsIconic(*this))
  72. {
  73. bHandled = FALSE;
  74. }
  75. return (wParam == 0) ? TRUE : FALSE;
  76. }
  77. LRESULT CUpdateWnd::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  78. {
  79. return 0;
  80. }
  81. LRESULT CUpdateWnd::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  82. {
  83. //在这里设置焦点才有用
  84. CEditUI* pAccountEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
  85. if(pAccountEdit)
  86. {
  87. pAccountEdit->SetFocus();
  88. }
  89. return 0;
  90. }
  91. LRESULT CUpdateWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  92. {
  93. POINT pt;
  94. pt.x = GET_X_LPARAM(lParam);
  95. pt.y = GET_Y_LPARAM(lParam);
  96. ::ScreenToClient(*this, &pt);
  97. RECT rcClient;
  98. ::GetClientRect(*this, &rcClient);
  99. RECT rcCaption = m_pm.GetCaptionRect();
  100. if(pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
  101. && pt.y >= rcCaption.top && pt.y < rcCaption.bottom)
  102. {
  103. CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
  104. if(pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0)
  105. {
  106. return HTCAPTION;
  107. }
  108. }
  109. return HTCLIENT;
  110. }
  111. LRESULT CUpdateWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  112. {
  113. SIZE szRoundCorner = m_pm.GetRoundCorner();
  114. if(!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0))
  115. {
  116. CDuiRect rcWnd;
  117. ::GetWindowRect(*this, &rcWnd);
  118. rcWnd.Offset(-rcWnd.left, -rcWnd.top);
  119. rcWnd.right++;
  120. rcWnd.bottom++;
  121. HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
  122. ::SetWindowRgn(*this, hRgn, TRUE);
  123. ::DeleteObject(hRgn);
  124. }
  125. bHandled = FALSE;
  126. return 0;
  127. }
  128. LRESULT CUpdateWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  129. {
  130. LRESULT lRes = 0;
  131. BOOL bHandled = TRUE;
  132. switch(uMsg)
  133. {
  134. case WM_CREATE:
  135. lRes = OnCreate(uMsg, wParam, lParam, bHandled);
  136. break;
  137. case WM_CLOSE:
  138. lRes = OnClose(uMsg, wParam, lParam, bHandled);
  139. break;
  140. case WM_DESTROY:
  141. lRes = OnDestroy(uMsg, wParam, lParam, bHandled);
  142. break;
  143. case WM_NCACTIVATE:
  144. lRes = OnNcActivate(uMsg, wParam, lParam, bHandled);
  145. break;
  146. case WM_NCCALCSIZE:
  147. lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled);
  148. break;
  149. case WM_NCPAINT:
  150. lRes = OnNcPaint(uMsg, wParam, lParam, bHandled);
  151. break;
  152. case WM_NCHITTEST:
  153. lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled);
  154. break;
  155. case WM_SIZE:
  156. lRes = OnSize(uMsg, wParam, lParam, bHandled);
  157. break;
  158. case WM_UPDATEPROGRESS:
  159. lRes = OnRefresh(uMsg, wParam, lParam, bHandled);
  160. break;
  161. case WM_DOWNLOAD_FINISH:
  162. lRes = OnDownloadFinish(uMsg, wParam, lParam, bHandled);
  163. break;
  164. default:
  165. bHandled = FALSE;
  166. }
  167. if(bHandled)
  168. {
  169. return lRes;
  170. }
  171. if(m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
  172. {
  173. return lRes;
  174. }
  175. return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  176. }
  177. LRESULT CUpdateWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
  178. {
  179. return false;
  180. }
  181. std::string CUpdateWnd::GetFileNameFormUrl(std::string url)
  182. {
  183. char fileName[512] = { 0 };
  184. int urlLen = strlen(url.c_str());
  185. char mUrl[512] = { 0 };
  186. char fName[256] = { 0 };
  187. strcpy(mUrl, url.c_str());
  188. int cutIndex = 0;
  189. int i = urlLen - 1, j = 0;
  190. while (mUrl[--i] != '/');
  191. i++;
  192. while (mUrl[i] != '\0' && mUrl[i] != '?' &&mUrl[i] != '&')
  193. {
  194. fName[j++] = mUrl[i++];
  195. }
  196. fName[j] = '\0';
  197. strcpy(fileName, fName);
  198. return fileName;
  199. }
  200. double CUpdateWnd::getDownloadFileLength(std::string url)
  201. {
  202. CURL *easy_handle = NULL;
  203. int ret = CURLE_OK;
  204. double size = -1;
  205. do
  206. {
  207. easy_handle = curl_easy_init();
  208. if(!easy_handle)
  209. {
  210. break;
  211. }
  212. // Only get the header data
  213. ret = curl_easy_setopt(easy_handle, CURLOPT_URL, url.c_str());
  214. if (url.find("https://") == 0)
  215. {
  216. ret |= curl_easy_setopt(easy_handle, CURLOPT_SSL_VERIFYPEER, false);
  217. ret |= curl_easy_setopt(easy_handle, CURLOPT_SSL_VERIFYHOST, false);
  218. }
  219. ret |= curl_easy_setopt(easy_handle, CURLOPT_HEADER, 1L);
  220. ret |= curl_easy_setopt(easy_handle, CURLOPT_NOBODY, 1L);
  221. ret |= curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, nousecb); // libcurl_a.lib will return error code 23 without this sentence on windows
  222. if(ret != CURLE_OK)
  223. {
  224. break;
  225. }
  226. ret = curl_easy_perform(easy_handle);
  227. if(ret != CURLE_OK)
  228. {
  229. char s[100] = { 0 };
  230. sprintf_s(s, sizeof(s), "error:%d:%s", ret, curl_easy_strerror(static_cast<CURLcode>(ret)));
  231. break;
  232. }
  233. // size = -1 if no Content-Length return or Content-Length=0
  234. ret = curl_easy_getinfo(easy_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &size);
  235. if(ret != CURLE_OK)
  236. {
  237. break;
  238. }
  239. }
  240. while(0);
  241. curl_easy_cleanup(easy_handle);
  242. return size;
  243. }
  244. void CUpdateWnd::Run()
  245. {
  246. m_filepath = m_dir + GetFileNameFormUrl(m_url);
  247. CURLcode res;
  248. m_curl = curl_easy_init();
  249. if(m_curl)
  250. {
  251. m_resumeByte = 0;
  252. m_downloadFileLength = getDownloadFileLength(m_url);
  253. if(m_resumeByte >= (int)m_downloadFileLength)
  254. {
  255. return;
  256. }
  257. m_outfile = fopen(m_filepath.c_str(), "ab+");
  258. curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());//在此要注意,此url必须是多字节
  259. if (m_url.find("https://") == 0)
  260. {
  261. curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, false);
  262. curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, false);
  263. }
  264. curl_easy_setopt(m_curl, CURLOPT_TIMEOUT, 0);
  265. curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, m_outfile);
  266. curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, my_write_func);
  267. curl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, FALSE);
  268. curl_easy_setopt(m_curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
  269. curl_easy_setopt(m_curl, CURLOPT_PROGRESSDATA, NULL);//给下载进度回调函数传参数,在此是指针
  270. res = curl_easy_perform(m_curl);
  271. fclose(m_outfile);
  272. curl_easy_cleanup(m_curl);
  273. }
  274. //走到这里,下载完成了
  275. HWND hWnd = FindWindow(NULL, L"自动更新");
  276. if (hWnd)
  277. {
  278. ::PostMessage(hWnd, WM_DOWNLOAD_FINISH, 0, 0);
  279. }
  280. }
  281. size_t CUpdateWnd::my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
  282. {
  283. size_t nWrite = fwrite(ptr, size, nmemb, stream);
  284. if(nWrite == 0)
  285. {
  286. return CURL_WRITEFUNC_PAUSE;
  287. }
  288. else
  289. {
  290. return nWrite;
  291. }
  292. }
  293. int CUpdateWnd::my_progress_func(void *progress_data,
  294. double t, /* dltotal */
  295. double d, /* dlnow */
  296. double ultotal,
  297. double ulnow)
  298. {
  299. if (t > 0)
  300. {
  301. CUpdateWnd::m_Percent = d * 100.0 / t;
  302. }
  303. else
  304. {
  305. CUpdateWnd::m_Percent = 0;
  306. }
  307. HWND hWnd = FindWindow(NULL, L"自动更新");
  308. if(hWnd)
  309. {
  310. ::PostMessage(hWnd, WM_UPDATEPROGRESS, 0, 0);
  311. }
  312. return 0;
  313. }
  314. size_t CUpdateWnd::nousecb(char *buffer, size_t x, size_t y, void *userdata)
  315. {
  316. (void)buffer;
  317. (void)userdata;
  318. return x * y;
  319. }
  320. LRESULT CUpdateWnd::OnRefresh(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  321. {
  322. CProgressUI* pProgress = static_cast<CProgressUI*>(m_pm.FindControl(_T("update_progress")));
  323. if(pProgress)
  324. {
  325. pProgress->SetValue((int)m_Percent);
  326. }
  327. return 0;
  328. }
  329. LRESULT CUpdateWnd::OnDownloadFinish(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  330. {
  331. HINSTANCE hNewExe = ShellExecuteA(NULL, "open", m_filepath.c_str(), NULL, NULL, SW_SHOW);
  332. PostQuitMessage(0);
  333. return 0;
  334. }