sp_gui.cpp 23 KB

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