#include "precompile.h" #include "sp_gui.h" #include "sp_def.h" #include "memutil.h" #ifdef _WIN32 #include #include #include using namespace Gdiplus; #include "resource1.h" #include "sp_checkEntity.h" #endif //_WIN32 #include "SimpleString.h" #include #include using namespace std; #include "sp_env.h" #include "array.h" #include "sp_cfg.h" #include #define SHELL_WND_CLS "SpShell_Wnd" #define BLUE_COLOR RGB(0, 0, 255) #define WHITE_COLOR RGB(255,255, 255) #define RED_COLOR RGB(255,0, 0) #define WM_DISPLAY (WM_APP+1) #define WM_UNDISPLAY (WM_APP+2) #define FONT_SMALL_SIZE 20 // show message in a big font #define FONT_LARGE_SIZE 48 // show message in a big font int g_guiShowFirst = 1; struct sp_gui_t { #ifdef _WIN32 HINSTANCE hInst; HWND hWnd; HWND hWndEditBox; HFONT hSmallFont; HFONT hLargeFont; //HPEN hPen; HBRUSH hBkBrush; BOOL bShow; HANDLE hThreadWorker; int iNotifyResult; HANDLE hEventNotify; BOOL bBlueScreen; ULONG_PTR pGDIToken; #endif //_WIN32 }; #ifdef _WIN32 static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static int GetTotalEntityCount() { auto env = sp_get_env(); if (env == NULL) { return getEntityResource()->m_EntityCount; } auto cfg = env->cfg; if (cfg == NULL) { return getEntityResource()->m_EntityCount; } return cfg->shell_ini->arr_entity->nelts; } static const wchar_t *GetTerminalInfo() { static wchar_t wszInfo[256] = {}; if (wszInfo[0] != 0) return wszInfo; auto env = sp_get_env(); if (env == NULL) { return NULL; } auto cfg = env->cfg; if (cfg == NULL) { return NULL; } swprintf(wszInfo, L"%S %S V%d.%d.%d.%d", cfg->root_ini->terminal_no, cfg->root_ini->site, cfg->install_ini->install_version.major, cfg->install_ini->install_version.minor, cfg->install_ini->install_version.revision, cfg->install_ini->install_version.build); return wszInfo; } static int OnCreate(sp_gui_t *gui, HWND hWnd, WPARAM wParam, LPARAM lParam) { HDC hdc; long lfHeight; LPCREATESTRUCTA lpCreateStruct = (LPCREATESTRUCTA)lParam; int nLogPixelsY; //gui->hWndEditBox = CreateWindowA("STATIC", "", WS_VISIBLE | WS_CHILD/*|SS_CENTER*/, 20, 20, // lpCreateStruct->cx - 20, lpCreateStruct->cy - 20, hWnd, (HMENU)101, gui->hInst, NULL); //gui->hWndEditBox = CreateWindowA("EDIT", "", WS_VISIBLE | WS_CHILD | ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL, // 10, 10, lpCreateStruct->cx - 20, lpCreateStruct->cy - 20, hWnd, (HMENU)101, gui->hInst, NULL); hdc = GetDC(NULL); nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); ReleaseDC(NULL, hdc); lfHeight = -MulDiv(FONT_SMALL_SIZE, nLogPixelsY, 72); //gui->hSmallFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman"); gui->hSmallFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "微软雅黑"); lfHeight = -MulDiv(FONT_LARGE_SIZE, nLogPixelsY, 72); //gui->hLargeFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman"); gui->hLargeFont = CreateFontA(lfHeight, 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "微软雅黑"); //SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT); return 0; } static int OnDestroy(sp_gui_t *gui, HWND hWnd, WPARAM wParam, LPARAM lParam) { DestroyWindow(gui->hWndEditBox); gui->hWndEditBox = NULL; DeleteObject(gui->hSmallFont); DeleteObject(gui->hLargeFont); PostQuitMessage(0); return 0; } typedef void (WINAPI *PSwitchToThisWindow)(HWND, BOOL); static int init(sp_gui_t *gui) { //GdiPlus初始化 GdiplusStartupInput gdiplusInput; GdiplusStartup(&gui->pGDIToken, &gdiplusInput, NULL); // 窗口类注册 WNDCLASSA wc = {0}; gui->hInst = GetModuleHandleA(NULL); gui->hBkBrush = wc.hbrBackground = CreateSolidBrush(BLUE_COLOR); wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW)); wc.hIcon = LoadIconA(NULL, MAKEINTRESOURCEA(IDI_APPLICATION)); wc.hInstance = gui->hInst; wc.lpfnWndProc = &WndProc; wc.lpszClassName = SHELL_WND_CLS; wc.style = CS_HREDRAW | CS_VREDRAW; if (RegisterClassA(&wc) == 0) return -1; gui->hWnd = CreateWindowExA(WS_EX_TOOLWINDOW, wc.lpszClassName, "", WS_POPUP|WS_BORDER, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, gui->hInst, gui); if (gui->hWnd == NULL) return Error_Unexpect; gui->bShow = TRUE; RegisterTouchWindow(gui->hWnd, 0); // support WM_TOUCH ShowWindow(gui->hWnd, g_guiShowFirst ? SW_SHOW : SW_HIDE); UpdateWindow(gui->hWnd); //BringWindowToTop(gui->hWnd); //SetWindowPos(gui->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); return 0; } static int term(sp_gui_t *gui) { //DestroyWindow(gui->hWnd); //gui->hWnd = NULL; UnregisterClassA(SHELL_WND_CLS, gui->hInst); DeleteObject(gui->hBkBrush); gui->hBkBrush = NULL; //GdiPlus 取消初始化 GdiplusShutdown(gui->pGDIToken); return 0; } static unsigned int __stdcall work_proc(void *param) { sp_gui_t *gui = (sp_gui_t*)param; int rc; MSG msg; rc = init(gui); gui->iNotifyResult = rc; SetEvent(gui->hEventNotify); if (rc != 0) return rc; //--> will disable the Display and Sleep Idle Timeouts . SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); while (GetMessageA(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessageA(&msg); } SetThreadExecutionState(ES_CONTINUOUS); term(gui); return 0; } // 从资源中读出Logo static int LoadLogoImage(int nResourceID, Image *&pImage) { auto hMod = GetModuleHandle("spbase"); auto hResInfo = FindResource(hMod, MAKEINTRESOURCE(nResourceID), TEXT("PNG")); if (hResInfo == NULL) return 1; auto hResData = LoadResource(hMod, hResInfo); if (hResData == NULL) return 2; auto pResData = LockResource(hResData); if (pResData == NULL) return 3; int iSize = SizeofResource(hMod, hResInfo); if (iSize <= 0) return 4; HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, iSize); if (!hMem) { UnlockResource(hResData); return 5; } LPVOID pTemp = ::GlobalLock(hMem); if (pTemp == NULL) { UnlockResource(hResData); GlobalFree(hMem); return 6; } // copy data memcpy(pTemp, pResData, iSize); ::GlobalUnlock(hMem); UnlockResource(hResData); CComPtr spStream; HRESULT hr = ::CreateStreamOnHGlobal(hMem, TRUE, &spStream); if (!SUCCEEDED(hr)) { GlobalFree(hMem); return 7; } pImage = Image::FromStream(spStream); if (pImage == NULL) return 8; return 0; } static int DrawConsoleTitle(Graphics &graphics, int nLeftWidth, int nRightWidth) { FontFamily fontFamily(L"宋体"); Font font(&fontFamily, 18, FontStyleBold, UnitPoint); RectF rectF(nLeftWidth, 0, nRightWidth, nRightWidth / 3); StringFormat format; format.SetAlignment(StringAlignmentCenter); format.SetLineAlignment(StringAlignmentCenter); SolidBrush fontBrush(Color(255, 67, 67, 67)); CSimpleStringW strMsg= TEXT("招商银行视频柜台"); graphics.DrawString(strMsg, strMsg.GetLength(), &font, rectF, &format, &fontBrush); return 0; } static int DrawBackground(Graphics &graphics, int nLeftWidth, int nRightWidth, int nHeight) { // draw left SolidBrush leftBrush(Color(255, 101, 105, 108)); Pen leftPen(&leftBrush); graphics.DrawRectangle(&leftPen, 0, 0, nLeftWidth, nHeight); graphics.FillRectangle(&leftBrush, 0, 0, nLeftWidth, nHeight); // draw right SolidBrush rightBrush(Color(255, 161, 163, 165)); Pen rightPen(&rightBrush); graphics.DrawRectangle(&rightPen, nLeftWidth, 0, nRightWidth, nHeight); graphics.FillRectangle(&rightBrush, nLeftWidth, 0, nRightWidth, nHeight); // draw logo Image *pLogoImage = NULL; if (LoadLogoImage(IDB_VTMLOGO, pLogoImage) !=0) { // 直接输出可视柜台文字 DrawConsoleTitle(graphics, nLeftWidth, nRightWidth); } else { graphics.DrawImage(pLogoImage, nLeftWidth + nRightWidth / 8, 20, nRightWidth * 3 / 4, nRightWidth * 3 / 4 / 3); } delete pLogoImage; return 0; } static int DrawLineString(Graphics &graphics, wstring &msg, Font *font, RectF &rect, StringFormat *format, Brush *brush, int nLineSpace, int &nNextLinePosY) { nNextLinePosY = rect.Y; // 一次最多32个 CharacterRange crs[32]; for (int i = 0; i < 32; i++) { crs[i].First = i; crs[i].Length = 1; } format->SetFormatFlags(StringFormatFlagsNoClip); // 当前输出区域 RectF layoutRect = rect; int nDelta = 60; // 每行输出留白空间 int nFrom = 0; int nLineCount = 0; int nTotalWidth = 0; int nLineHeight = 0; int nMsgLen = msg.length(); while (nFrom + nLineCount < nMsgLen) { Region regions[32] = {}; int nCount = 32; if (nFrom + nLineCount + nCount > nMsgLen) nCount = nMsgLen - nFrom - nLineCount; format->SetMeasurableCharacterRanges(nCount, crs); //tempMsg = msg.substr(nFrom + nLineCount, nCount); graphics.MeasureCharacterRanges(msg.data() + nFrom + nLineCount, nCount, font, layoutRect, format, nCount, regions); for (int i = 0; i < nCount; i++) { Rect r; regions[i].GetBounds(&r, &graphics); nTotalWidth += r.Width; if (r.Height > nLineHeight) nLineHeight = r.Height; if (nTotalWidth <= layoutRect.Width - nDelta && msg[nFrom + nLineCount] != TEXT('\r') && msg[nFrom + nLineCount] != TEXT('\n')) { nLineCount++; } else { if (msg[nFrom + nLineCount] == TEXT('\r') || msg[nFrom + nLineCount] == TEXT('\n')) { if (nFrom + nLineCount + 1 < nMsgLen && ((msg[nFrom + nLineCount] == TEXT('\r') && msg[nFrom + nLineCount + 1] == TEXT('\n')) || (msg[nFrom + nLineCount] == TEXT('\n') && msg[nFrom + nLineCount + 1] == TEXT('\r')))) { nLineCount += 2; i++; } else nLineCount++; } //auto wszLine = msg.substr(nFrom, nLineCount); graphics.DrawString(msg.data() + nFrom, nLineCount, font, layoutRect, format, brush); // reset vars nFrom += nLineCount; nLineCount = 0; nTotalWidth = 0; layoutRect.Y += nLineHeight + nLineSpace; //nLineHeight = 0; nNextLinePosY = layoutRect.Y; // 写满显示高度,直接返回 if (layoutRect.Y >= rect.Y + rect.Height) return 0; } } } // output last line if (nLineCount > 0) { graphics.DrawString(msg.data() + nFrom, nLineCount, font, layoutRect, format, brush); nNextLinePosY += nLineHeight + nLineSpace; } return 0; } static int DrawRunningInfo(Graphics &graphics, int nLeftWidth, int nRightWidth, int nHeight) { // 全部输出 // get lock auto entityRes = getEntityResource(); while (InterlockedCompareExchange(&entityRes->m_Locking, 1, 0) == 1) { Sleep(100); } // draw left wstring strLeft; FontFamily fontFamily(L"微软雅黑"); SolidBrush blackBrush(Color(255, 0, 0, 0)); SolidBrush whiteBrush(Color(255, 255, 255, 255)); SolidBrush redBrush(Color(255, 174, 0, 0)); SolidBrush redBrush2(Color(255, 130, 0, 0)); if (entityRes->m_InBlueScreenMode) { strLeft = entityRes->m_BlueScreenMsg; Font font(&fontFamily, 32, FontStyleBold, UnitPoint); StringFormat format; format.SetFormatFlags(StringFormatFlagsNoClip); format.SetLineAlignment(StringAlignmentCenter); RectF rectF(10, 10, nLeftWidth - 20, nHeight - 20); graphics.DrawString(strLeft.c_str(), strLeft.length(), &font, rectF, &format, &whiteBrush); } else { Font font(&fontFamily, 10, FontStyleRegular, UnitPoint); StringFormat format; int nNextLinePosY = 10; auto it = entityRes->m_OutputMsgs.rbegin(); if (entityRes->m_InBrowseMode) { for (int i = 0; i < entityRes->m_SkipLineNum && i < (int)entityRes->m_OutputMsgs.size(); i++) it++; } for (; it != entityRes->m_OutputMsgs.rend() && nNextLinePosY < nHeight; it++) { auto &strLine = *it; // output Brush *brush = NULL; if (wcsstr(strLine.c_str(), L"] W:{") != NULL) brush = &whiteBrush; else if (wcsstr(strLine.c_str(), L"] E:{") != NULL) brush = &redBrush2; else brush = &blackBrush; RectF rectF(10, nNextLinePosY, nLeftWidth - 20, nHeight - 20); DrawLineString(graphics, strLine, &font, rectF, &format, brush, 5, nNextLinePosY); } } // draw right wstring strLostEntitys; wstring strSum; int nStartedCount = 0; int nLostCount = 0; int nToStartCount = 0; wchar_t strTmp[128] = {}; for (int i = 0; i < entityRes->m_EntityCount; i++) { if (entityRes->m_EntitysInfo[i].EntityState >= 2 && entityRes->m_EntitysInfo[i].EntityState <= 4) { nStartedCount++; } else if (entityRes->m_EntitysInfo[i].EntityState == 6) { nLostCount++; swprintf_s(strTmp, 128, L" 模块[%s]启动失败\r\n", entityRes->m_EntitysInfo[i].EntityName.c_str()); strLostEntitys += strTmp; } } // 输出终端号、场所、版本 StringFormat centerFormat; centerFormat.SetAlignment(StringAlignmentCenter); auto wszTerminalInfo = GetTerminalInfo(); if (wszTerminalInfo != NULL) { Font rfont(&fontFamily, 10, FontStyleRegular, UnitPoint); RectF rrectF(nLeftWidth + 10, 110, nRightWidth - 20, nHeight - 180); int nNextLinePosY; DrawLineString(graphics, wstring(wszTerminalInfo), &rfont, rrectF, ¢erFormat, &blackBrush, 20, nNextLinePosY); } // 实体启动成功计数 Font rfont(&fontFamily, 12, FontStyleBold, UnitPoint); swprintf_s(strTmp, 128, L"%d/%d 个模块启动成功", nStartedCount, GetTotalEntityCount()); strSum = strTmp; int nNextLinePosY; RectF rrectF(nLeftWidth + 10, 140, nRightWidth - 20, nHeight - 180); DrawLineString(graphics, strSum, &rfont, rrectF, ¢erFormat, &blackBrush, 20, nNextLinePosY); // 输出当前启动状态信息 Font rfont2(&fontFamily, 11, FontStyleRegular, UnitPoint); if (entityRes->m_StartupInfo.length() > 0) { RectF rrectF2(nLeftWidth + 6, nNextLinePosY, nRightWidth, nHeight - 180); DrawLineString(graphics, entityRes->m_StartupInfo, &rfont2, rrectF2, ¢erFormat, &whiteBrush, 5, nNextLinePosY); nNextLinePosY += 10; } // 输出实体启动错误 StringFormat rformat2; { RectF rrectF2(nLeftWidth + 30, nNextLinePosY, nRightWidth, nHeight - 200); DrawLineString(graphics, strLostEntitys, &rfont2, rrectF2, &rformat2, &redBrush, 5, nNextLinePosY); } // 输出严重错误信息 for (auto it2 = entityRes->m_FatalMsgs.rbegin(); it2!= entityRes->m_FatalMsgs.rend() && nNextLinePosY < nHeight; it2++) { RectF rrectF2(nLeftWidth + 30, nNextLinePosY, nRightWidth, nHeight - 200); wstring strLine = L"\r\n 【" + *it2+ L"】"; DrawLineString(graphics, strLine, &rfont2, rrectF2, &rformat2, &redBrush, 5, nNextLinePosY); } // release lock InterlockedExchange(&entityRes->m_Locking, 0); return 0; } static int RepaintWindow(HWND hWnd, bool bCanUseCache) { static RECT lastRect = {}; static HDC hBkgMemDC = NULL; RECT rect = {}; GetClientRect(hWnd, &rect); HDC hDC = GetDC(hWnd); if (lastRect.right == rect.right && lastRect.bottom == rect.bottom && hBkgMemDC != NULL && bCanUseCache) { // copy mem dc to hwnd dc //MessageBox(NULL, TEXT("use cached dc"), NULL, 0); BitBlt(hDC, 0, 0, rect.right, rect.bottom, hBkgMemDC, 0, 0, SRCCOPY); ReleaseDC(hWnd, hDC); return 0; } if (hBkgMemDC != NULL) { DeleteDC(hBkgMemDC); hBkgMemDC = NULL; } lastRect = rect; int nWidth = rect.right - rect.left; int nHeight = rect.bottom - rect.top; int nRightWidth = nWidth / 3; if (nRightWidth > 450) nRightWidth = 450; int nLeftWidth = nWidth - nRightWidth; hBkgMemDC = CreateCompatibleDC(hDC); auto hMemBitmap = CreateCompatibleBitmap(hDC, nWidth, nHeight); auto hOldObject = SelectObject(hBkgMemDC, hMemBitmap); Graphics graphics(hBkgMemDC); // draw background image DrawBackground(graphics, nLeftWidth, nRightWidth, nHeight); // draw output string DrawRunningInfo(graphics, nLeftWidth, nRightWidth, nHeight); // copy mem dc to hwnd dc BitBlt(hDC, 0, 0, rect.right, rect.bottom, hBkgMemDC, 0, 0, SRCCOPY); SelectObject(hBkgMemDC, hOldObject); DeleteObject(hMemBitmap); //DeleteDC(hBkgMemDC); ReleaseDC(hWnd, hDC); return 0; } static void SetBrowseModeShift(int nShiftLines) { if ((!getEntityResource()->m_InBrowseMode && nShiftLines <= 0) || getEntityResource()->m_OutputMsgs.size() <=20) return; // get lock auto entityRes = getEntityResource(); while (InterlockedCompareExchange(&entityRes->m_Locking, 1, 0) == 1) { Sleep(100); } getEntityResource()->m_InBrowseMode = true; getEntityResource()->m_SkipLineNum += nShiftLines; if (nShiftLines > 0) { if (getEntityResource()->m_SkipLineNum + 20 > (int)getEntityResource()->m_OutputMsgs.size()) { getEntityResource()->m_SkipLineNum = (int)getEntityResource()->m_OutputMsgs.size() - 20; } } else { if (getEntityResource()->m_SkipLineNum <= 0) { // 解除浏览模式 getEntityResource()->m_SkipLineNum = 0; getEntityResource()->m_InBrowseMode = false; } } // release lock InterlockedExchange(&getEntityResource()->m_Locking, 0); } static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { sp_gui_t *gui = NULL; static POINTS lastPoint = {}; if (msg == WM_CREATE) { LPCREATESTRUCTA lpCreateStruct = (LPCREATESTRUCTA)lParam; gui = (sp_gui_t*)lpCreateStruct->lpCreateParams; SetWindowLongA(hWnd, GWL_USERDATA, (LONG)gui); } else { gui = (sp_gui_t*)GetWindowLongA(hWnd, GWL_USERDATA); } switch (msg) { case WM_CREATE: { if (OnCreate(gui, hWnd, wParam, lParam) != 0) return -1; } break; case WM_CLOSE: DestroyWindow(hWnd); break; case WM_MOUSEWHEEL: { getEntityResource()->m_LastShiftTick = GetTickCount(); short sDelta = (short)HIWORD(wParam); //WORD wKeys = LOWORD(wParam); //short sXPos = (short)LOWORD(lParam); //short sYPos = (short)HIWORD(lParam); //char szTmp[128] = {}; //sprintf(szTmp, "delta: %d, xpos: %d, ypos: %d", sDelta, sXPos, sYPos); //sp_gui_show_running_info(gui, szTmp, 0); SetBrowseModeShift(sDelta > 0 ? 10 : -10); RepaintWindow(hWnd, false); } break; case WM_TOUCH: { getEntityResource()->m_LastShiftTick = GetTickCount(); DWORD nInputNum = (DWORD)wParam; TOUCHINPUT *tis = new TOUCHINPUT[nInputNum];\ if (GetTouchInputInfo((HTOUCHINPUT)lParam, nInputNum, tis, sizeof(TOUCHINPUT))) { for (int i = 0; i < nInputNum; i++) { POINT pt = {}; pt.x = TOUCH_COORD_TO_PIXEL(tis[i].x); pt.y = TOUCH_COORD_TO_PIXEL(tis[i].y); ScreenToClient(gui->hWnd, &pt); if (tis[i].dwFlags & TOUCHEVENTF_DOWN) { getEntityResource()->m_LastTouchID = tis[i].dwID; getEntityResource()->m_LastTouchYPos = pt.y; } else if (tis[i].dwFlags & TOUCHEVENTF_MOVE) { } else if (tis[i].dwFlags & TOUCHEVENTF_UP) { if (tis[i].dwID == getEntityResource()->m_LastTouchID) { //char szTmp[128] = {}; //sprintf(szTmp, "WM_TOUCH, id: %d, lastY: %d, curY: %d", gLastTouchID, gLastTouchYPos, pt.y); //sp_gui_show_running_info(gui, szTmp, 0); SetBrowseModeShift(pt.y < getEntityResource()->m_LastTouchYPos ? 10 : -10); RepaintWindow(hWnd, false); getEntityResource()->m_LastTouchID = 0; getEntityResource()->m_LastTouchYPos = 0; } } } CloseTouchInputHandle((HTOUCHINPUT)lParam); delete[] tis; } } break; case WM_DESTROY: OnDestroy(gui, hWnd, wParam, lParam); break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); RepaintWindow(hWnd, true); EndPaint(hWnd, &ps); } break; case WM_KEYDOWN: { if (wParam == VK_F3) { // hide SendMessageA(hWnd, WM_UNDISPLAY, 0, 0); } } break; case WM_CTLCOLORSTATIC: { HDC hDC = (HDC)wParam; HWND hWndControl = (HWND)lParam; SetBkColor(hDC, BLUE_COLOR); SetTextColor(hDC, WHITE_COLOR); return (LRESULT)gui->hBkBrush; } break; case WM_DISPLAY: { RepaintWindow(hWnd, false); if (getEntityResource()->m_InBlueScreenMode && !gui->bShow) { gui->bShow = TRUE; ShowWindow(gui->hWnd, SW_SHOW); } } break; case WM_UNDISPLAY: { ShowWindow(hWnd, SW_HIDE); UpdateWindow(hWnd); gui->bShow = FALSE; } break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; } #endif //_WIN32 void sp_gui_setShow(int isShowFirst) { g_guiShowFirst = isShowFirst; } int sp_gui_create(sp_gui_t **p_gui) { sp_gui_t *gui = ZALLOC_T(sp_gui_t); #ifdef _WIN32 gui->hEventNotify = CreateEventA(NULL, TRUE, FALSE, NULL); if (!gui->hEventNotify) goto on_error; gui->hThreadWorker = (HANDLE)_beginthreadex(NULL, 0, &work_proc, gui, 0, NULL); if (!gui->hThreadWorker) goto on_error; WaitForSingleObject(gui->hEventNotify, INFINITE); if (gui->iNotifyResult) goto on_error; #endif //_WIN32 *p_gui = gui; return 0; #ifdef _WIN32 on_error : if (gui->hThreadWorker) CloseHandle(gui->hThreadWorker); if (gui->hEventNotify) CloseHandle(gui->hEventNotify); free(gui); return Error_Unexpect; #endif //_WIN32 } void sp_gui_destroy(sp_gui_t *gui) { #ifdef _WIN32 PostMessageA(gui->hWnd, WM_CLOSE, 0, 0); WaitForSingleObject(gui->hThreadWorker, INFINITE); CloseHandle(gui->hThreadWorker); CloseHandle(gui->hEventNotify); #endif //_WIN32 free(gui); } int sp_gui_show_running_info(sp_gui_t *gui, const char *pMsg, int type) { #ifdef _WIN32 // get lock auto entityRes = getEntityResource(); while (InterlockedCompareExchange(&entityRes->m_Locking, 1, 0) == 1) Sleep(100); SYSTEMTIME st = {}; GetLocalTime(&st); wchar_t szBuf[1024] = {}; if (type == 1) { // bluescreen entityRes->m_InBlueScreenMode = true; swprintf_s(szBuf, 1024, L"%S\r\n", pMsg); entityRes->m_BlueScreenMsg = szBuf; } else if (type == 2) { // fatal error swprintf_s(szBuf, 1024, L"%S", pMsg); entityRes->m_FatalMsgs.push_back(szBuf); if (entityRes->m_FatalMsgs.size() > 100) entityRes->m_FatalMsgs.pop_front(); } else if (type == 3) { // important startup info swprintf_s(szBuf, 1024, L"%S", pMsg); entityRes->m_StartupInfo = szBuf; } else { // startup info swprintf_s(szBuf, 1024, L"[%02d:%02d:%02d] %S\r\n", st.wHour, st.wMinute, st.wSecond, pMsg); entityRes->m_OutputMsgs.push_back(szBuf); // 只保留最近500条 if (entityRes->m_OutputMsgs.size() > 500) entityRes->m_OutputMsgs.pop_front(); } // browse mode continues 30s if (entityRes->m_InBrowseMode && GetTickCount() - entityRes->m_LastShiftTick >= 30000) { entityRes->m_InBrowseMode = false; entityRes->m_SkipLineNum = 0; } // release lock InterlockedExchange(&entityRes->m_Locking, 0); if (type >= 1 || (!entityRes->m_InBlueScreenMode && !entityRes->m_InBrowseMode)) { if (!PostMessageA(gui->hWnd, WM_DISPLAY, NULL, NULL)) { return Error_Unexpect; } } #endif //_WIN32 return 0; } int sp_gui_show_entity_info(sp_gui_t *gui, const char *entity, int state) { #ifdef _WIN32 auto strEntity = CSimpleStringA2W(CSimpleStringA(entity)); auto entityRes = getEntityResource(); int i = 0; for (; i < entityRes->m_EntityCount; i++) { if (wcsicmp(strEntity, entityRes->m_EntitysInfo[i].EntityName.c_str()) == 0) { entityRes->m_EntitysInfo[i].EntityState = state; break; } } if (i == entityRes->m_EntityCount && entityRes->m_EntityCount < 80) { // new entity entityRes->m_EntitysInfo[i].EntityName = strEntity; entityRes->m_EntitysInfo[i].EntityState = state; entityRes->m_EntityCount++; } if (!PostMessageA(gui->hWnd, WM_DISPLAY, NULL, NULL)) { return Error_Unexpect; } #endif //_WIN32 return 0; } int sp_gui_display(sp_gui_t *gui) { #ifdef _WIN32 if (!gui->bShow) { gui->bShow = TRUE; HWND hShellWnd = FindWindow(_T("Shell_TrayWnd"), NULL); if (hShellWnd != NULL) SendMessage(hShellWnd, WM_COMMAND, 419, 0); ShowWindow(gui->hWnd, SW_SHOW); } #endif //_WIN32 return 0; } int sp_gui_undisplay(sp_gui_t *gui) { #ifdef _WIN32 getEntityResource()->m_InBlueScreenMode = false; if (!PostMessageA(gui->hWnd, WM_UNDISPLAY, 0, 0)) return Error_Unexpect; #endif //_WIN32 return 0; }