sp_gui.cpp 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. #include "precompile.h"
  2. #include "sp_gui.h"
  3. #include "sp_def.h"
  4. #include "memutil.h"
  5. #include "log_define.h"
  6. #ifdef _WIN32
  7. #include <tchar.h>
  8. #include "resource1.h"
  9. #include <atlbase.h>
  10. #include <gdiplus.h>
  11. using namespace Gdiplus;
  12. #include "resource1.h"
  13. #include "sp_checkEntity.h"
  14. #endif //_WIN32
  15. #include "SimpleString.h"
  16. #include <string>
  17. #include <list>
  18. using namespace std;
  19. #include "sp_env.h"
  20. #include "array.h"
  21. #include "sp_cfg.h"
  22. #include "SpBase.h"
  23. #include <winpr/wtypes.h>
  24. #define SHELL_WND_CLS "SpShell_Wnd"
  25. #define BLUE_COLOR RGB(0, 0, 255)
  26. #define WHITE_COLOR RGB(255,255, 255)
  27. #define RED_COLOR RGB(255,0, 0)
  28. #define WM_DISPLAY (WM_APP+1)
  29. #define WM_UNDISPLAY (WM_APP+2)
  30. #define FONT_SMALL_SIZE 20 // show message in a big font
  31. #define FONT_LARGE_SIZE 48 // show message in a big font
  32. int g_guiShowFirst = 1;
  33. struct sp_gui_t
  34. {
  35. #ifdef _WIN32
  36. HINSTANCE hInst;
  37. HWND hWnd;
  38. HWND hWndEditBox;
  39. HFONT hSmallFont;
  40. HFONT hLargeFont;
  41. //HPEN hPen;
  42. HBRUSH hBkBrush;
  43. BOOL bShow;
  44. HANDLE hThreadWorker;
  45. int iNotifyResult;
  46. HANDLE hEventNotify;
  47. BOOL bBlueScreen;
  48. ULONG_PTR pGDIToken;
  49. #endif // _WIN32
  50. };
  51. #ifdef _WIN32
  52. static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
  53. static int GetTotalEntityCount()
  54. {
  55. auto env = sp_get_env();
  56. if (env == NULL) {
  57. return getEntityResource()->m_EntityCount;
  58. }
  59. auto cfg = env->cfg;
  60. if (cfg == NULL) {
  61. return getEntityResource()->m_EntityCount;
  62. }
  63. return cfg->shell_ini->arr_entity->nelts;
  64. }
  65. static const wchar_t *GetTerminalInfo()
  66. {
  67. static wchar_t wszInfo[256] = {};
  68. if (wszInfo[0] != 0)
  69. return wszInfo;
  70. auto env = sp_get_env();
  71. if (env == NULL) {
  72. return NULL;
  73. }
  74. auto cfg = env->cfg;
  75. if (cfg == NULL) {
  76. return NULL;
  77. }
  78. swprintf(wszInfo, L"%S %S V%d.%d.%d.%d",
  79. cfg->root_ini->terminal_no == NULL ? "" : cfg->root_ini->terminal_no,
  80. cfg->root_ini->site == NULL ? "" : cfg->root_ini->site,
  81. cfg->install_ini->install_version.major,
  82. cfg->install_ini->install_version.minor,
  83. cfg->install_ini->install_version.revision,
  84. cfg->install_ini->install_version.build);
  85. return wszInfo;
  86. }
  87. static int OnCreate(sp_gui_t *gui, HWND hWnd, WPARAM wParam, LPARAM lParam)
  88. {
  89. HDC hdc;
  90. long lfHeight;
  91. LPCREATESTRUCTA lpCreateStruct = (LPCREATESTRUCTA)lParam;
  92. int nLogPixelsY;
  93. //gui->hWndEditBox = CreateWindowA("STATIC", "", WS_VISIBLE | WS_CHILD/*|SS_CENTER*/, 20, 20,
  94. // lpCreateStruct->cx - 20, lpCreateStruct->cy - 20, hWnd, (HMENU)101, gui->hInst, NULL);
  95. //gui->hWndEditBox = CreateWindowA("EDIT", "", WS_VISIBLE | WS_CHILD | ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL,
  96. // 10, 10, lpCreateStruct->cx - 20, lpCreateStruct->cy - 20, hWnd, (HMENU)101, gui->hInst, NULL);
  97. hdc = GetDC(NULL);
  98. nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
  99. ReleaseDC(NULL, hdc);
  100. lfHeight = -MulDiv(FONT_SMALL_SIZE, nLogPixelsY, 72);
  101. //gui->hSmallFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
  102. gui->hSmallFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "微软雅黑");
  103. lfHeight = -MulDiv(FONT_LARGE_SIZE, nLogPixelsY, 72);
  104. //gui->hLargeFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
  105. gui->hLargeFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "微软雅黑");
  106. //SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT);
  107. return 0;
  108. }
  109. static int OnDestroy(sp_gui_t *gui, HWND hWnd, WPARAM wParam, LPARAM lParam)
  110. {
  111. DestroyWindow(gui->hWndEditBox);
  112. gui->hWndEditBox = NULL;
  113. DeleteObject(gui->hSmallFont);
  114. DeleteObject(gui->hLargeFont);
  115. PostQuitMessage(0);
  116. return 0;
  117. }
  118. typedef void (WINAPI *PSwitchToThisWindow)(HWND, BOOL);
  119. static int init(sp_gui_t *gui)
  120. {
  121. //GdiPlus初始化
  122. GdiplusStartupInput gdiplusInput;
  123. GdiplusStartup(&gui->pGDIToken, &gdiplusInput, NULL);
  124. // 窗口类注册
  125. WNDCLASSA wc = {0};
  126. gui->hInst = GetModuleHandleA(NULL);
  127. gui->hBkBrush = wc.hbrBackground = CreateSolidBrush(BLUE_COLOR);
  128. wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));
  129. wc.hIcon = LoadIconA(NULL, MAKEINTRESOURCEA(IDI_APPLICATION));
  130. wc.hInstance = gui->hInst;
  131. wc.lpfnWndProc = &WndProc;
  132. wc.lpszClassName = SHELL_WND_CLS;
  133. wc.style = CS_HREDRAW | CS_VREDRAW;
  134. if (RegisterClassA(&wc) == 0)
  135. return -1;
  136. gui->hWnd = CreateWindowExA(WS_EX_TOOLWINDOW, wc.lpszClassName, "", WS_POPUP|WS_BORDER,
  137. 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, gui->hInst, gui);
  138. if (gui->hWnd == NULL)
  139. return Error_Unexpect;
  140. gui->bShow = TRUE;
  141. RegisterTouchWindow(gui->hWnd, 0); // support WM_TOUCH
  142. ShowWindow(gui->hWnd, g_guiShowFirst ? SW_SHOW : SW_HIDE);
  143. UpdateWindow(gui->hWnd);
  144. //BringWindowToTop(gui->hWnd);
  145. //SetWindowPos(gui->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  146. return 0;
  147. }
  148. static int term(sp_gui_t *gui)
  149. {
  150. //DestroyWindow(gui->hWnd);
  151. //gui->hWnd = NULL;
  152. UnregisterClassA(SHELL_WND_CLS, gui->hInst);
  153. DeleteObject(gui->hBkBrush);
  154. gui->hBkBrush = NULL;
  155. //GdiPlus 取消初始化
  156. GdiplusShutdown(gui->pGDIToken);
  157. return 0;
  158. }
  159. static unsigned int __stdcall work_proc(void *param)
  160. {
  161. sp_gui_t *gui = (sp_gui_t*)param;
  162. int rc;
  163. MSG msg;
  164. rc = init(gui);
  165. gui->iNotifyResult = rc;
  166. SetEvent(gui->hEventNotify);
  167. if (rc != 0)
  168. return rc;
  169. //--> will disable the Display and Sleep Idle Timeouts .
  170. SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
  171. while (GetMessageA(&msg, NULL, 0, 0)) {
  172. TranslateMessage(&msg);
  173. DispatchMessageA(&msg);
  174. }
  175. SetThreadExecutionState(ES_CONTINUOUS);
  176. term(gui);
  177. return 0;
  178. }
  179. // 从资源中读出Logo
  180. static int LoadLogoImage(int nResourceID, Image *&pImage)
  181. {
  182. auto hMod = GetModuleHandle("spbase");
  183. auto hResInfo = FindResource(hMod, MAKEINTRESOURCE(nResourceID), TEXT("PNG"));
  184. if (hResInfo == NULL)
  185. return 1;
  186. auto hResData = LoadResource(hMod, hResInfo);
  187. if (hResData == NULL)
  188. return 2;
  189. auto pResData = LockResource(hResData);
  190. if (pResData == NULL)
  191. return 3;
  192. int iSize = SizeofResource(hMod, hResInfo);
  193. if (iSize <= 0)
  194. return 4;
  195. HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, iSize);
  196. if (!hMem)
  197. {
  198. UnlockResource(hResData);
  199. return 5;
  200. }
  201. LPVOID pTemp = ::GlobalLock(hMem);
  202. if (pTemp == NULL)
  203. {
  204. UnlockResource(hResData);
  205. GlobalFree(hMem);
  206. return 6;
  207. }
  208. // copy data
  209. memcpy(pTemp, pResData, iSize);
  210. ::GlobalUnlock(hMem);
  211. UnlockResource(hResData);
  212. CComPtr<IStream> spStream;
  213. HRESULT hr = ::CreateStreamOnHGlobal(hMem, TRUE, &spStream);
  214. if (!SUCCEEDED(hr))
  215. {
  216. GlobalFree(hMem);
  217. return 7;
  218. }
  219. pImage = Image::FromStream(spStream);
  220. if (pImage == NULL)
  221. return 8;
  222. return 0;
  223. }
  224. static int DrawConsoleTitle(Graphics &graphics, int nLeftWidth, int nRightWidth)
  225. {
  226. FontFamily fontFamily(L"宋体");
  227. Font font(&fontFamily, 18, FontStyleBold, UnitPoint);
  228. RectF rectF(nLeftWidth, 0, nRightWidth, nRightWidth / 3);
  229. StringFormat format;
  230. format.SetAlignment(StringAlignmentCenter);
  231. format.SetLineAlignment(StringAlignmentCenter);
  232. SolidBrush fontBrush(Color(255, 67, 67, 67));
  233. CSimpleStringW strMsg= TEXT("招商银行视频柜台");
  234. graphics.DrawString(strMsg, strMsg.GetLength(), &font, rectF, &format, &fontBrush);
  235. return 0;
  236. }
  237. static int DrawBackground(Graphics &graphics, int nLeftWidth, int nRightWidth, int nHeight)
  238. {
  239. // draw left
  240. SolidBrush leftBrush(Color(255, 101, 105, 108));
  241. Pen leftPen(&leftBrush);
  242. graphics.DrawRectangle(&leftPen, 0, 0, nLeftWidth, nHeight);
  243. graphics.FillRectangle(&leftBrush, 0, 0, nLeftWidth, nHeight);
  244. // draw right
  245. SolidBrush rightBrush(Color(255, 161, 163, 165));
  246. Pen rightPen(&rightBrush);
  247. graphics.DrawRectangle(&rightPen, nLeftWidth, 0, nRightWidth, nHeight);
  248. graphics.FillRectangle(&rightBrush, nLeftWidth, 0, nRightWidth, nHeight);
  249. // draw logo
  250. Image *pLogoImage = NULL;
  251. if (LoadLogoImage(IDB_VTMLOGO, pLogoImage) !=0)
  252. {
  253. // 直接输出可视柜台文字
  254. DrawConsoleTitle(graphics, nLeftWidth, nRightWidth);
  255. }
  256. else
  257. {
  258. graphics.DrawImage(pLogoImage, nLeftWidth + nRightWidth / 8, 20, nRightWidth * 3 / 4, nRightWidth * 3 / 4 / 3);
  259. }
  260. delete pLogoImage;
  261. return 0;
  262. }
  263. static int DrawLineString(Graphics &graphics, wstring &msg, Font *font, RectF &rect, StringFormat *format, Brush *brush, int nLineSpace, int &nNextLinePosY)
  264. {
  265. nNextLinePosY = rect.Y;
  266. // 一次最多32个
  267. CharacterRange crs[32];
  268. for (int i = 0; i < 32; i++)
  269. {
  270. crs[i].First = i;
  271. crs[i].Length = 1;
  272. }
  273. format->SetFormatFlags(StringFormatFlagsNoClip);
  274. // 当前输出区域
  275. RectF layoutRect = rect;
  276. int nDelta = 60; // 每行输出留白空间
  277. int nFrom = 0;
  278. int nLineCount = 0;
  279. int nTotalWidth = 0;
  280. int nLineHeight = 0;
  281. int nMsgLen = msg.length();
  282. while (nFrom + nLineCount < nMsgLen)
  283. {
  284. Region regions[32] = {};
  285. int nCount = 32;
  286. if (nFrom + nLineCount + nCount > nMsgLen)
  287. nCount = nMsgLen - nFrom - nLineCount;
  288. format->SetMeasurableCharacterRanges(nCount, crs);
  289. //tempMsg = msg.substr(nFrom + nLineCount, nCount);
  290. graphics.MeasureCharacterRanges(msg.data() + nFrom + nLineCount, nCount, font, layoutRect, format, nCount, regions);
  291. for (int i = 0; i < nCount; i++)
  292. {
  293. Rect r;
  294. regions[i].GetBounds(&r, &graphics);
  295. nTotalWidth += r.Width;
  296. if (r.Height > nLineHeight)
  297. nLineHeight = r.Height;
  298. if (nTotalWidth <= layoutRect.Width - nDelta && msg[nFrom + nLineCount] != TEXT('\r') && msg[nFrom + nLineCount] != TEXT('\n'))
  299. {
  300. nLineCount++;
  301. }
  302. else
  303. {
  304. if (msg[nFrom + nLineCount] == TEXT('\r') || msg[nFrom + nLineCount] == TEXT('\n'))
  305. {
  306. if (nFrom + nLineCount + 1 < nMsgLen
  307. && ((msg[nFrom + nLineCount] == TEXT('\r') && msg[nFrom + nLineCount + 1] == TEXT('\n'))
  308. || (msg[nFrom + nLineCount] == TEXT('\n') && msg[nFrom + nLineCount + 1] == TEXT('\r'))))
  309. {
  310. nLineCount += 2;
  311. i++;
  312. }
  313. else
  314. nLineCount++;
  315. }
  316. //auto wszLine = msg.substr(nFrom, nLineCount);
  317. graphics.DrawString(msg.data() + nFrom, nLineCount, font, layoutRect, format, brush);
  318. // reset vars
  319. nFrom += nLineCount;
  320. nLineCount = 0;
  321. nTotalWidth = 0;
  322. layoutRect.Y += nLineHeight + nLineSpace;
  323. //nLineHeight = 0;
  324. nNextLinePosY = layoutRect.Y;
  325. // 写满显示高度,直接返回
  326. if (layoutRect.Y >= rect.Y + rect.Height)
  327. return 0;
  328. }
  329. }
  330. }
  331. // output last line
  332. if (nLineCount > 0)
  333. {
  334. graphics.DrawString(msg.data() + nFrom, nLineCount, font, layoutRect, format, brush);
  335. nNextLinePosY += nLineHeight + nLineSpace;
  336. }
  337. return 0;
  338. }
  339. static int DrawRunningInfo(Graphics &graphics, int nLeftWidth, int nRightWidth, int nHeight)
  340. {
  341. // 全部输出
  342. // get lock
  343. auto entityRes = getEntityResource();
  344. while (InterlockedCompareExchange(&entityRes->m_Locking, 1, 0) == 1)
  345. {
  346. Sleep(100);
  347. }
  348. // draw left
  349. wstring strLeft;
  350. FontFamily fontFamily(L"微软雅黑");
  351. SolidBrush blackBrush(Color(255, 0, 0, 0));
  352. SolidBrush whiteBrush(Color(255, 255, 255, 255));
  353. SolidBrush redBrush(Color(255, 174, 0, 0));
  354. SolidBrush redBrush2(Color(255, 130, 0, 0));
  355. if (entityRes->m_InBlueScreenMode)
  356. {
  357. strLeft = entityRes->m_BlueScreenMsg;
  358. Font font(&fontFamily, 32, FontStyleBold, UnitPoint);
  359. StringFormat format;
  360. format.SetFormatFlags(StringFormatFlagsNoClip);
  361. format.SetLineAlignment(StringAlignmentCenter);
  362. RectF rectF(10, 10, nLeftWidth - 20, nHeight - 20);
  363. graphics.DrawString(strLeft.c_str(), strLeft.length(), &font, rectF, &format, &whiteBrush);
  364. }
  365. else
  366. {
  367. Font font(&fontFamily, 10, FontStyleRegular, UnitPoint);
  368. StringFormat format;
  369. int nNextLinePosY = 10;
  370. auto it = entityRes->m_OutputMsgs.rbegin();
  371. if (entityRes->m_InBrowseMode)
  372. {
  373. for (int i = 0; i < entityRes->m_SkipLineNum && i < (int)entityRes->m_OutputMsgs.size(); i++)
  374. it++;
  375. }
  376. for (; it != entityRes->m_OutputMsgs.rend() && nNextLinePosY < nHeight; it++)
  377. {
  378. auto &strLine = *it;
  379. // output
  380. Brush *brush = NULL;
  381. if (wcsstr(strLine.c_str(), L"] W:{") != NULL)
  382. brush = &whiteBrush;
  383. else if (wcsstr(strLine.c_str(), L"] E:{") != NULL)
  384. brush = &redBrush2;
  385. else
  386. brush = &blackBrush;
  387. RectF rectF(10, nNextLinePosY, nLeftWidth - 20, nHeight - 20);
  388. DrawLineString(graphics, strLine, &font, rectF, &format, brush, 5, nNextLinePosY);
  389. }
  390. }
  391. // draw right
  392. wstring strLostEntitys;
  393. wstring strSum;
  394. int nStartedCount = 0;
  395. int nLostCount = 0;
  396. int nToStartCount = 0;
  397. wchar_t strTmp[128] = {};
  398. for (int i = 0; i < entityRes->m_EntityCount; i++)
  399. {
  400. if (entityRes->m_EntitysInfo[i].EntityState >= 2 && entityRes->m_EntitysInfo[i].EntityState <= 4)
  401. {
  402. nStartedCount++;
  403. }
  404. else if (entityRes->m_EntitysInfo[i].EntityState == 6)
  405. {
  406. nLostCount++;
  407. swprintf_s(strTmp, 128, L" 模块[%s]启动失败\r\n", entityRes->m_EntitysInfo[i].EntityName.c_str());
  408. strLostEntitys += strTmp;
  409. }
  410. }
  411. // 输出终端号、场所、版本
  412. StringFormat centerFormat;
  413. centerFormat.SetAlignment(StringAlignmentCenter);
  414. auto wszTerminalInfo = GetTerminalInfo();
  415. if (wszTerminalInfo != NULL)
  416. {
  417. Font rfont(&fontFamily, 10, FontStyleRegular, UnitPoint);
  418. RectF rrectF(nLeftWidth + 10, 110, nRightWidth - 20, nHeight - 180);
  419. int nNextLinePosY;
  420. DrawLineString(graphics, wstring(wszTerminalInfo), &rfont, rrectF, &centerFormat, &blackBrush, 20, nNextLinePosY);
  421. }
  422. // 实体启动成功计数
  423. Font rfont(&fontFamily, 12, FontStyleBold, UnitPoint);
  424. swprintf_s(strTmp, 128, L"%d/%d 个模块启动成功", nStartedCount, GetTotalEntityCount());
  425. strSum = strTmp;
  426. int nNextLinePosY;
  427. RectF rrectF(nLeftWidth + 10, 140, nRightWidth - 20, nHeight - 180);
  428. DrawLineString(graphics, strSum, &rfont, rrectF, &centerFormat, &blackBrush, 20, nNextLinePosY);
  429. // 输出当前启动状态信息
  430. Font rfont2(&fontFamily, 11, FontStyleRegular, UnitPoint);
  431. if (entityRes->m_StartupInfo.length() > 0)
  432. {
  433. RectF rrectF2(nLeftWidth + 6, nNextLinePosY, nRightWidth, nHeight - 180);
  434. DrawLineString(graphics, entityRes->m_StartupInfo, &rfont2, rrectF2, &centerFormat, &whiteBrush, 5, nNextLinePosY);
  435. nNextLinePosY += 10;
  436. }
  437. // 输出实体启动错误
  438. StringFormat rformat2;
  439. {
  440. RectF rrectF2(nLeftWidth + 30, nNextLinePosY, nRightWidth, nHeight - 200);
  441. DrawLineString(graphics, strLostEntitys, &rfont2, rrectF2, &rformat2, &redBrush, 5, nNextLinePosY);
  442. }
  443. // 输出严重错误信息
  444. for (auto it2 = entityRes->m_FatalMsgs.rbegin(); it2!= entityRes->m_FatalMsgs.rend() && nNextLinePosY < nHeight; it2++)
  445. {
  446. RectF rrectF2(nLeftWidth + 30, nNextLinePosY, nRightWidth, nHeight - 200);
  447. wstring strLine = L"\r\n 【" + *it2+ L"】";
  448. DrawLineString(graphics, strLine, &rfont2, rrectF2, &rformat2, &redBrush, 5, nNextLinePosY);
  449. }
  450. // release lock
  451. InterlockedExchange(&entityRes->m_Locking, 0);
  452. return 0;
  453. }
  454. static int RepaintWindow(HWND hWnd, bool bCanUseCache)
  455. {
  456. static RECT lastRect = {};
  457. static HDC hBkgMemDC = NULL;
  458. if (!g_guiShowFirst)
  459. return 0;
  460. RECT rect = {};
  461. GetClientRect(hWnd, &rect);
  462. HDC hDC = GetDC(hWnd);
  463. if (lastRect.right == rect.right && lastRect.bottom == rect.bottom && hBkgMemDC != NULL && bCanUseCache)
  464. {
  465. // copy mem dc to hwnd dc
  466. //MessageBox(NULL, TEXT("use cached dc"), NULL, 0);
  467. BitBlt(hDC, 0, 0, rect.right, rect.bottom, hBkgMemDC, 0, 0, SRCCOPY);
  468. ReleaseDC(hWnd, hDC);
  469. return 0;
  470. }
  471. if (hBkgMemDC != NULL)
  472. {
  473. DeleteDC(hBkgMemDC);
  474. hBkgMemDC = NULL;
  475. }
  476. lastRect = rect;
  477. int nWidth = rect.right - rect.left;
  478. int nHeight = rect.bottom - rect.top;
  479. int nRightWidth = nWidth / 3;
  480. if (nRightWidth > 450)
  481. nRightWidth = 450;
  482. int nLeftWidth = nWidth - nRightWidth;
  483. hBkgMemDC = CreateCompatibleDC(hDC);
  484. auto hMemBitmap = CreateCompatibleBitmap(hDC, nWidth, nHeight);
  485. auto hOldObject = SelectObject(hBkgMemDC, hMemBitmap);
  486. Graphics graphics(hBkgMemDC);
  487. // draw background image
  488. DrawBackground(graphics, nLeftWidth, nRightWidth, nHeight);
  489. // draw output string
  490. DrawRunningInfo(graphics, nLeftWidth, nRightWidth, nHeight);
  491. // copy mem dc to hwnd dc
  492. BitBlt(hDC, 0, 0, rect.right, rect.bottom, hBkgMemDC, 0, 0, SRCCOPY);
  493. SelectObject(hBkgMemDC, hOldObject);
  494. DeleteObject(hMemBitmap);
  495. //DeleteDC(hBkgMemDC);
  496. ReleaseDC(hWnd, hDC);
  497. return 0;
  498. }
  499. static void SetBrowseModeShift(int nShiftLines)
  500. {
  501. if ((!getEntityResource()->m_InBrowseMode && nShiftLines <= 0) || getEntityResource()->m_OutputMsgs.size() <=20)
  502. return;
  503. // get lock
  504. auto entityRes = getEntityResource();
  505. while (InterlockedCompareExchange(&entityRes->m_Locking, 1, 0) == 1)
  506. {
  507. Sleep(100);
  508. }
  509. getEntityResource()->m_InBrowseMode = true;
  510. getEntityResource()->m_SkipLineNum += nShiftLines;
  511. if (nShiftLines > 0)
  512. {
  513. if (getEntityResource()->m_SkipLineNum + 20 > (int)getEntityResource()->m_OutputMsgs.size())
  514. {
  515. getEntityResource()->m_SkipLineNum = (int)getEntityResource()->m_OutputMsgs.size() - 20;
  516. }
  517. }
  518. else
  519. {
  520. if (getEntityResource()->m_SkipLineNum <= 0)
  521. {
  522. // 解除浏览模式
  523. getEntityResource()->m_SkipLineNum = 0;
  524. getEntityResource()->m_InBrowseMode = false;
  525. }
  526. }
  527. // release lock
  528. InterlockedExchange(&getEntityResource()->m_Locking, 0);
  529. }
  530. static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  531. {
  532. sp_gui_t *gui = NULL;
  533. static POINTS lastPoint = {};
  534. if (msg == WM_CREATE) {
  535. LPCREATESTRUCTA lpCreateStruct = (LPCREATESTRUCTA)lParam;
  536. gui = (sp_gui_t*)lpCreateStruct->lpCreateParams;
  537. SetWindowLongA(hWnd, GWL_USERDATA, (LONG)gui);
  538. }
  539. else {
  540. gui = (sp_gui_t*)GetWindowLongA(hWnd, GWL_USERDATA);
  541. }
  542. switch (msg) {
  543. case WM_CREATE:
  544. {
  545. if (OnCreate(gui, hWnd, wParam, lParam) != 0)
  546. return -1;
  547. }
  548. break;
  549. case WM_CLOSE:
  550. DestroyWindow(hWnd);
  551. break;
  552. case WM_MOUSEWHEEL:
  553. {
  554. getEntityResource()->m_LastShiftTick = GetTickCount();
  555. short sDelta = (short)HIWORD(wParam);
  556. SetBrowseModeShift(sDelta > 0 ? 10 : -10);
  557. RepaintWindow(hWnd, false);
  558. }
  559. break;
  560. case WM_TOUCH:
  561. {
  562. getEntityResource()->m_LastShiftTick = GetTickCount();
  563. DWORD nInputNum = (DWORD)wParam;
  564. TOUCHINPUT *tis = new TOUCHINPUT[nInputNum];\
  565. if (GetTouchInputInfo((HTOUCHINPUT)lParam, nInputNum, tis, sizeof(TOUCHINPUT)))
  566. {
  567. for (int i = 0; i < nInputNum; i++)
  568. {
  569. POINT pt = {};
  570. pt.x = TOUCH_COORD_TO_PIXEL(tis[i].x);
  571. pt.y = TOUCH_COORD_TO_PIXEL(tis[i].y);
  572. ScreenToClient(gui->hWnd, &pt);
  573. if (tis[i].dwFlags & TOUCHEVENTF_DOWN)
  574. {
  575. getEntityResource()->m_LastTouchID = tis[i].dwID;
  576. getEntityResource()->m_LastTouchYPos = pt.y;
  577. }
  578. else if (tis[i].dwFlags & TOUCHEVENTF_MOVE)
  579. {
  580. }
  581. else if (tis[i].dwFlags & TOUCHEVENTF_UP)
  582. {
  583. if (tis[i].dwID == getEntityResource()->m_LastTouchID)
  584. {
  585. SetBrowseModeShift(pt.y < getEntityResource()->m_LastTouchYPos ? 10 : -10);
  586. RepaintWindow(hWnd, false);
  587. getEntityResource()->m_LastTouchID = 0;
  588. getEntityResource()->m_LastTouchYPos = 0;
  589. }
  590. }
  591. }
  592. CloseTouchInputHandle((HTOUCHINPUT)lParam);
  593. delete[] tis;
  594. }
  595. }
  596. break;
  597. case WM_DESTROY:
  598. OnDestroy(gui, hWnd, wParam, lParam);
  599. break;
  600. case WM_PAINT:
  601. {
  602. PAINTSTRUCT ps;
  603. HDC hdc = BeginPaint(hWnd, &ps);
  604. RepaintWindow(hWnd, true);
  605. EndPaint(hWnd, &ps);
  606. }
  607. break;
  608. case WM_KEYDOWN:
  609. {
  610. if (wParam == VK_F3) { // hide
  611. SendMessageA(hWnd, WM_UNDISPLAY, 0, 0);
  612. }
  613. }
  614. break;
  615. case WM_CTLCOLORSTATIC:
  616. {
  617. HDC hDC = (HDC)wParam;
  618. HWND hWndControl = (HWND)lParam;
  619. SetBkColor(hDC, BLUE_COLOR);
  620. SetTextColor(hDC, WHITE_COLOR);
  621. return (LRESULT)gui->hBkBrush;
  622. }
  623. break;
  624. case WM_DISPLAY:
  625. {
  626. RepaintWindow(hWnd, false);
  627. if (getEntityResource()->m_InBlueScreenMode && !gui->bShow)
  628. {
  629. gui->bShow = TRUE;
  630. ShowWindow(gui->hWnd, SW_SHOW);
  631. }
  632. }
  633. break;
  634. case WM_UNDISPLAY:
  635. {
  636. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("WM_UNDISPLAY, show gui undisplay");
  637. ShowWindow(hWnd, SW_HIDE);
  638. UpdateWindow(hWnd);
  639. gui->bShow = FALSE;
  640. }
  641. break;
  642. default:
  643. return DefWindowProc(hWnd, msg, wParam, lParam);
  644. }
  645. return 0;
  646. }
  647. #endif //_WIN32
  648. void sp_gui_setShow(int isShowFirst)
  649. {
  650. g_guiShowFirst = isShowFirst;
  651. }
  652. int sp_gui_create(sp_gui_t **p_gui)
  653. {
  654. sp_gui_t *gui = ZALLOC_T(sp_gui_t);
  655. #ifdef RVC_OS_WIN
  656. gui->hEventNotify = CreateEventA(NULL, TRUE, FALSE, NULL);
  657. if (!gui->hEventNotify)
  658. goto on_error;
  659. gui->hThreadWorker = (HANDLE)_beginthreadex(NULL, 0, &work_proc, gui, 0, NULL);
  660. if (!gui->hThreadWorker)
  661. goto on_error;
  662. WaitForSingleObject(gui->hEventNotify, INFINITE);
  663. if (gui->iNotifyResult)
  664. goto on_error;
  665. #endif //RVC_OS_WIN
  666. *p_gui = gui;
  667. return 0;
  668. #ifdef RVC_OS_WIN
  669. on_error :
  670. if (gui->hThreadWorker)
  671. CloseHandle(gui->hThreadWorker);
  672. if (gui->hEventNotify)
  673. CloseHandle(gui->hEventNotify);
  674. free(gui);
  675. return Error_Unexpect;
  676. #endif //RVC_OS_WIN
  677. }
  678. void sp_gui_destroy(sp_gui_t *gui)
  679. {
  680. #ifdef _WIN32
  681. PostMessageA(gui->hWnd, WM_CLOSE, 0, 0);
  682. WaitForSingleObject(gui->hThreadWorker, INFINITE);
  683. CloseHandle(gui->hThreadWorker);
  684. CloseHandle(gui->hEventNotify);
  685. #endif //_WIN32
  686. free(gui);
  687. }
  688. #if defined(_MSC_VER)
  689. int sp_gui_show_running_info(sp_gui_t* gui, const char* pMsg, int type)
  690. {
  691. // get lock
  692. auto entityRes = getEntityResource();
  693. while (InterlockedCompareExchange(&entityRes->m_Locking, 1, 0) == 1)
  694. Sleep(100);
  695. SYSTEMTIME st = {};
  696. GetLocalTime(&st);
  697. wchar_t szBuf[1024] = {};
  698. CSimpleStringA curMsg = pMsg;
  699. CSimpleStringW dstMsg = CSimpleStringA2W(curMsg);
  700. dstMsg = dstMsg.SubString(0, 1000);
  701. if (type == 1) {
  702. // bluescreen
  703. entityRes->m_InBlueScreenMode = true;
  704. swprintf_s(szBuf, 1024, L"%s\r\n", dstMsg.GetData());
  705. entityRes->m_BlueScreenMsg = szBuf;
  706. } else if (type == 2) {
  707. // fatal error
  708. swprintf_s(szBuf, 1024, L"%s", dstMsg.GetData());
  709. entityRes->m_FatalMsgs.push_back(szBuf);
  710. if (entityRes->m_FatalMsgs.size() > 100)
  711. entityRes->m_FatalMsgs.pop_front();
  712. } else if (type == 3) {
  713. // important startup info
  714. swprintf_s(szBuf, 1024, L"%s", dstMsg.GetData());
  715. entityRes->m_StartupInfo = szBuf;
  716. } else {
  717. // startup info
  718. swprintf_s(szBuf, 1024, L"[%02d:%02d:%02d] %s\r\n", st.wHour, st.wMinute, st.wSecond, dstMsg.GetData());
  719. entityRes->m_OutputMsgs.push_back(szBuf);
  720. // 只保留最近500条
  721. if (entityRes->m_OutputMsgs.size() > 500)
  722. entityRes->m_OutputMsgs.pop_front();
  723. }
  724. // browse mode continues 30s
  725. if (entityRes->m_InBrowseMode && GetTickCount() - entityRes->m_LastShiftTick >= 30000) {
  726. entityRes->m_InBrowseMode = false;
  727. entityRes->m_SkipLineNum = 0;
  728. }
  729. // release lock
  730. InterlockedExchange(&entityRes->m_Locking, 0);
  731. if (type >= 1 || (!entityRes->m_InBlueScreenMode && !entityRes->m_InBrowseMode)) {
  732. if (!PostMessageA(gui->hWnd, WM_DISPLAY, NULL, NULL)) {
  733. return Error_Unexpect;
  734. }
  735. }
  736. return 0;
  737. }
  738. int sp_gui_show_entity_info(sp_gui_t* gui, const char* entity, int state)
  739. {
  740. auto strEntity = CSimpleStringA2W(CSimpleStringA(entity));
  741. auto entityRes = getEntityResource();
  742. int i = 0;
  743. for (; i < entityRes->m_EntityCount; i++) {
  744. if (wcsicmp(strEntity, entityRes->m_EntitysInfo[i].EntityName.c_str()) == 0) {
  745. entityRes->m_EntitysInfo[i].EntityState = state;
  746. break;
  747. }
  748. }
  749. if (i == entityRes->m_EntityCount && entityRes->m_EntityCount < 80) {
  750. // new entity
  751. entityRes->m_EntitysInfo[i].EntityName = strEntity;
  752. entityRes->m_EntitysInfo[i].EntityState = state;
  753. entityRes->m_EntityCount++;
  754. }
  755. if (!PostMessageA(gui->hWnd, WM_DISPLAY, NULL, NULL)) {
  756. return Error_Unexpect;
  757. }
  758. return 0;
  759. }
  760. int sp_gui_display(sp_gui_t* gui)
  761. {
  762. if (!gui->bShow) {
  763. gui->bShow = TRUE;
  764. HWND hShellWnd = FindWindow(_T("Shell_TrayWnd"), NULL);
  765. if (hShellWnd != NULL)
  766. SendMessage(hShellWnd, WM_COMMAND, 419, 0);
  767. ShowWindow(gui->hWnd, SW_SHOW);
  768. }
  769. return 0;
  770. }
  771. int sp_gui_undisplay(sp_gui_t* gui)
  772. {
  773. getEntityResource()->m_InBlueScreenMode = false;
  774. if (!PostMessageA(gui->hWnd, WM_UNDISPLAY, 0, 0))
  775. return Error_Unexpect;
  776. return 0;
  777. }
  778. #else
  779. int sp_gui_create_format(sp_gui_format_t** p_gui)
  780. {
  781. int result = 0;
  782. sp_gui_format_t* gui = ZALLOC_T(sp_gui_format_t);
  783. sp_gui_t* inst = NULL;
  784. result = sp_gui_create(&inst);
  785. if (result == 0) {
  786. gui->gui_inst = inst;
  787. gui->display = &sp_gui_display;
  788. gui->hide = &sp_gui_undisplay;
  789. gui->show_entity_info = &sp_gui_show_entity_info;
  790. gui->show_running_info = &sp_gui_show_running_info;
  791. gui->post_message = &sp_gui_post_message;
  792. *p_gui = gui;
  793. } else {
  794. FREE(gui);
  795. }
  796. return result;
  797. }
  798. void sp_gui_destroy_format(sp_gui_format_t* p_gui)
  799. {
  800. sp_gui_destroy((sp_gui_t*)p_gui->gui_inst);
  801. FREE(p_gui);
  802. }
  803. int sp_gui_show_running_info(void* data, const char* pMsg, int type)
  804. {
  805. sp_gui_t* gui = (sp_gui_t*)data;
  806. return 0;
  807. }
  808. int sp_gui_show_entity_info(void* data, const char* entity, int state)
  809. {
  810. //void* data
  811. sp_gui_t* gui = (sp_gui_t*)data;
  812. return 0;
  813. }
  814. int sp_gui_display(void* data)
  815. {
  816. //void* data
  817. sp_gui_t* gui = (sp_gui_t*)data;
  818. return 0;
  819. }
  820. int sp_gui_undisplay(void* data)
  821. {
  822. //void* data
  823. sp_gui_t* gui = (sp_gui_t*)data;
  824. return 0;
  825. }
  826. void sp_gui_post_message(void* gui, unsigned long param1, unsigned long param2)
  827. {
  828. return;
  829. }
  830. #endif //_MSC_VER