/* UserinfoEx plugin for Miranda NG Copyright: © 2012-24 Miranda NG team (https://miranda-ng.org) © 2006-10 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "stdafx.h" #include #include struct MSGPOPUPDATA { POPUPACTION pa[3]; HWND hDialog; }; /** * This helper function moves and resizes a dialog box's control element. * * @param hDlg - the dialog box's window handle * @param idCtrl - the identication number of the control to move * @param dx - number of pixels to horizontal move the control * @param dy - number of pixels to vertical move the control * @param dw - number of pixels to horizontal resize the control * @param dh - number of pixels to vertical resize the control * * @return nothing **/ void __forceinline MoveCtrl(HWND hDlg, int idCtrl, int dx, int dy, int dw, int dh) { RECT ws; HWND hCtrl = GetDlgItem(hDlg, idCtrl); GetWindowRect(hCtrl, &ws); OffsetRect(&ws, dx, dy); MoveWindow(hCtrl, ws.left, ws.top, ws.right - ws.left + dw, ws.bottom - ws.top + dh, FALSE); } /** * This function loads the icon to display for the current message. * * @param pMsgBox - pointer to a MSGBOX structure, with information about the message to display. * * @retval HICON - The function returns an icon to display with the message. * @retval NULL - There is no icon for the message. **/ static HICON MsgLoadIcon(MSGBOX *pMsgBox) { HICON hIcon; // load the desired status icon switch (pMsgBox->uType & MB_ICONMASK) { case MB_ICON_OTHER: // custom icon defined by caller function hIcon = pMsgBox->hiMsg; break; // default windows icons case MB_ICON_ERROR: case MB_ICON_QUESTION: case MB_ICON_WARNING: case MB_ICON_INFO: { LPCTSTR ico[] = { nullptr, IDI_ERROR, IDI_QUESTION, IDI_WARNING, IDI_INFORMATION }; hIcon = LoadIcon(nullptr, ico[MB_ICON_INDEX(pMsgBox->uType)]); } break; // no icon default: hIcon = nullptr; } return hIcon; } /** * This function fills a given POPUPACTION structure with the data of a given message id, * which is normally used by the message box. This is required to let the user interact * with a popup in the same way as with a normal message dialog box. * * @param pa - reference to a POPUPACTION structure to fill * @param id - the message id * @param result - This parameter is passed to the POPUPACTION structure as is. * * @return nothing **/ static void MakePopupAction(POPUPACTION &pa, int id) { pa.cbSize = sizeof(POPUPACTION); pa.flags = PAF_ENABLED; pa.wParam = MAKEWORD(id, BN_CLICKED); pa.lParam = 0; switch (id) { case IDOK: pa.lchIcon = g_plugin.getIcon(IDI_BTN_OK); mir_strcpy(pa.lpzTitle, MODULENAME"/Ok"); break; case IDCLOSE: case IDCANCEL: pa.lchIcon = g_plugin.getIcon(IDI_BTN_CLOSE); mir_strcpy(pa.lpzTitle, MODULENAME"/Cancel"); break; case IDABORT: pa.lchIcon = g_plugin.getIcon(IDI_BTN_CLOSE); mir_strcpy(pa.lpzTitle, MODULENAME"/Abort"); break; case IDRETRY: pa.lchIcon = g_plugin.getIcon(IDI_BTN_UPDATE); mir_strcpy(pa.lpzTitle, MODULENAME"/Retry"); break; case IDIGNORE: pa.lchIcon = g_plugin.getIcon(IDI_BTN_OK); mir_strcpy(pa.lpzTitle, MODULENAME"/Ignore"); break; case IDYES: pa.lchIcon = g_plugin.getIcon(IDI_BTN_OK); mir_strcpy(pa.lpzTitle, MODULENAME"/Yes"); break; case IDNO: pa.lchIcon = g_plugin.getIcon(IDI_BTN_CLOSE); mir_strcpy(pa.lpzTitle, MODULENAME"/No"); break; case IDHELP: pa.lchIcon = g_plugin.getIcon(IDI_BTN_CLOSE); mir_strcpy(pa.lpzTitle, MODULENAME"/Help"); break; case IDALL: pa.lchIcon = g_plugin.getIcon(IDI_BTN_OK); mir_strcpy(pa.lpzTitle, MODULENAME"/All"); break; case IDNONE: pa.lchIcon = g_plugin.getIcon(IDI_BTN_CLOSE); mir_strcpy(pa.lpzTitle, MODULENAME"/None"); } } /** * This is the message procedure for my nice looking message box * * @param hDlg - window handle * @param uMsg - message to handle * @param wParam - message specific parameter * @param lParam - message specific parameter * * @return TRUE, FALSE, IDOK, IDYES, IDALL, IDNO or IDCANCEL **/ static INT_PTR CALLBACK MsgBoxProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int retOk = IDOK; static int retAll = IDALL; static int retNon = IDNONE; static int retCancel = IDCANCEL; switch (uMsg) { case WM_INITDIALOG: { MSGBOX *pMsgBox = (MSGBOX *)lParam; if (PtrIsValid(pMsgBox)) { int icoWidth = 0; int InfoBarHeight = 0; HFONT hNormalFont; hNormalFont = (HFONT)SendDlgItemMessage(hDlg, TXT_NAME, WM_GETFONT, 0, 0); if (pMsgBox->uType & MB_INFOBAR) { LOGFONT lf; // set bold font for name in description area GetObject(hNormalFont, sizeof(lf), &lf); lf.lfWeight = FW_BOLD; hNormalFont = CreateFontIndirect(&lf); // set infobar's textfont SendDlgItemMessage(hDlg, TXT_NAME, WM_SETFONT, (WPARAM)hNormalFont, 0); // set infobar's logo icon SendDlgItemMessage(hDlg, ICO_DLGLOGO, STM_SETIMAGE, IMAGE_ICON, (pMsgBox->hiLogo ? (LPARAM)pMsgBox->hiLogo : (LPARAM)g_plugin.getIcon(IDI_DLG_DETAILS, true))); // enable headerbar ShowWindow(GetDlgItem(hDlg, TXT_NAME), SW_SHOW); ShowWindow(GetDlgItem(hDlg, ICO_DLGLOGO), SW_SHOW); } else { RECT rc; GetClientRect(GetDlgItem(hDlg, TXT_NAME), &rc); InfoBarHeight = rc.bottom; if (pMsgBox->hiLogo) SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)pMsgBox->hiLogo); } // draw the desired status icon HICON hIcon = MsgLoadIcon(pMsgBox); if (hIcon) SendDlgItemMessage(hDlg, ICO_MSGDLG, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); else { RECT ws; GetWindowRect(GetDlgItem(hDlg, ICO_MSGDLG), &ws); icoWidth = ws.right - ws.left; ShowWindow(GetDlgItem(hDlg, ICO_MSGDLG), SW_HIDE); } // resize the messagebox and reorganize the buttons if (HDC hDC = GetDC(hDlg)) { POINT mpt = { 0, 0 }; RECT ws = { 0, 0, 0, 0 }; int txtWidth = 0, txtHeight = 0, needX, needY; RECT rcDlg; SIZE ts; LPTSTR h, rs; SelectObject(hDC, hNormalFont); // get message text width and height if (pMsgBox->ptszMsg) for (rs = h = pMsgBox->ptszMsg; ; ++h) { if (*h == '\n' || !*h) { GetTextExtentPoint32(hDC, rs, h - rs, &ts); if (ts.cx > txtWidth) txtWidth = ts.cx; txtHeight += ts.cy; if (!*h) break; rs = h + 1; } } // increase width if info text requires more if ((pMsgBox->uType & MB_INFOBAR) && pMsgBox->ptszInfoText && *pMsgBox->ptszInfoText) { //int multiline = 0; RECT rcico; GetClientRect(GetDlgItem(hDlg, ICO_DLGLOGO), &rcico); rcico.right = rcico.right * 100 / 66; // padding for (rs = h = pMsgBox->ptszInfoText; ; ++h) { if (*h == '\n' || !*h) { GetTextExtentPoint32(hDC, rs, h - rs, &ts); ts.cx += rcico.right; if (ts.cx > txtWidth) txtWidth = ts.cx; if (!*h) break; rs = h + 1; //++multiline; } } /* used by SendSS, disabled for UserInfoEx for now if(!multiline) SetWindowLongPtr(GetDlgItem(hDlg,TXT_NAME), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hDlg,TXT_NAME), GWL_STYLE)|SS_CENTERIMAGE); */ } ReleaseDC(hDlg, hDC); // calc new dialog size GetWindowRect(hDlg, &rcDlg); GetWindowRect(GetDlgItem(hDlg, TXT_MESSAGE), &ws); needX = txtWidth - (ws.right - ws.left) - icoWidth; needY = max(0, txtHeight - (ws.bottom - ws.top) + 5); rcDlg.left -= needX / 2; rcDlg.right += needX / 2; rcDlg.top -= (needY - InfoBarHeight) / 2; rcDlg.bottom += (needY - InfoBarHeight) / 2; // resize dialog window MoveWindow(hDlg, rcDlg.left, rcDlg.top, rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top, FALSE); ClientToScreen(hDlg, &mpt); MoveCtrl(hDlg, STATIC_WHITERECT, -mpt.x, -mpt.y, needX, needY - InfoBarHeight); MoveCtrl(hDlg, TXT_NAME, -mpt.x, -mpt.y, needX, 0); MoveCtrl(hDlg, ICO_DLGLOGO, -mpt.x + needX, -mpt.y, 0, 0); MoveCtrl(hDlg, ICO_MSGDLG, -mpt.x, -mpt.y - InfoBarHeight, 0, 0); MoveCtrl(hDlg, TXT_MESSAGE, -mpt.x - icoWidth, -mpt.y - InfoBarHeight, needX, needY); MoveCtrl(hDlg, STATIC_LINE2, -mpt.x, -mpt.y + needY - InfoBarHeight, needX, 0); // // Do pushbutton positioning // RECT rcOk, rcAll, rcNone, rcCancel; // get button rectangles GetWindowRect(GetDlgItem(hDlg, IDOK), &rcOk); OffsetRect(&rcOk, -mpt.x, -mpt.y + needY - InfoBarHeight); GetWindowRect(GetDlgItem(hDlg, IDALL), &rcAll); OffsetRect(&rcAll, -mpt.x, -mpt.y + needY - InfoBarHeight); GetWindowRect(GetDlgItem(hDlg, IDNONE), &rcNone); OffsetRect(&rcNone, -mpt.x, -mpt.y + needY - InfoBarHeight); GetWindowRect(GetDlgItem(hDlg, IDCANCEL), &rcCancel); OffsetRect(&rcCancel, -mpt.x, -mpt.y + needY - InfoBarHeight); LONG okWidth = rcOk.right - rcOk.left; LONG allWidth = rcAll.right - rcAll.left; LONG noneWidth = rcNone.right - rcNone.left; LONG caWidth = rcCancel.right - rcCancel.left; LONG dlgMid = (rcDlg.right - rcDlg.left) / 2; // load button configuration switch (MB_TYPE(pMsgBox->uType)) { case MB_OK: rcOk.left = dlgMid - (okWidth / 2); rcOk.right = rcOk.left + okWidth; ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); break; case MB_OKCANCEL: retOk = IDRETRY; SetDlgItemText(hDlg, IDOK, LPGENW("OK")); retCancel = IDCANCEL; SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); rcOk.left = dlgMid - okWidth - 10; rcOk.right = rcOk.left + okWidth; rcCancel.left = dlgMid + 10; rcCancel.right = rcCancel.left + caWidth; ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); break; case MB_RETRYCANCEL: retOk = IDRETRY; SetDlgItemText(hDlg, IDOK, LPGENW("Retry")); retCancel = IDCANCEL; SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); rcOk.left = dlgMid - okWidth - 10; rcOk.right = rcOk.left + okWidth; rcCancel.left = dlgMid + 10; rcCancel.right = rcCancel.left + caWidth; ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); break; case MB_YESNO: retOk = IDYES; SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); retCancel = IDNO; SetDlgItemText(hDlg, IDCANCEL, LPGENW("No")); rcOk.left = dlgMid - okWidth - 10; rcOk.right = rcOk.left + okWidth; rcCancel.left = dlgMid + 10; rcCancel.right = rcCancel.left + caWidth; ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); break; case MB_ABORTRETRYIGNORE: retOk = IDABORT; SetDlgItemText(hDlg, IDOK, LPGENW("Abort")); retAll = IDABORT; SetDlgItemText(hDlg, IDALL, LPGENW("Retry")); retCancel = IDCANCEL; SetDlgItemText(hDlg, IDCANCEL, LPGENW("Ignore")); rcAll.left = dlgMid - (allWidth / 2); rcAll.right = rcAll.left + allWidth; rcOk.left = rcAll.left - okWidth - 5; rcOk.right = rcOk.left + okWidth; rcCancel.left = rcAll.right + 5; rcCancel.right = rcCancel.left + caWidth; ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); break; case MB_YESNOCANCEL: retOk = IDYES; SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); retAll = IDNO; SetDlgItemText(hDlg, IDALL, LPGENW("No")); retCancel = IDCANCEL; SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); rcAll.left = dlgMid - (allWidth / 2); rcAll.right = rcAll.left + allWidth; rcOk.left = rcAll.left - okWidth - 5; rcOk.right = rcOk.left + okWidth; rcCancel.left = rcAll.right + 5; rcCancel.right = rcCancel.left + caWidth; ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); break; case MB_YESALLNO: retOk = IDYES; SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); retAll = IDALL; SetDlgItemText(hDlg, IDALL, LPGENW("All")); //retNon = IDNONE; SetDlgItemText(hDlg, IDNONE, LPGENW("None")); retCancel = IDNO; SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); rcCancel.right = rcDlg.right - rcDlg.left - 10; rcCancel.left = rcCancel.right - caWidth; rcNone.right = rcCancel.left - 5; rcNone.left = rcNone.right - noneWidth; rcAll.right = rcNone.left - 5; rcAll.left = rcAll.right - allWidth; rcOk.right = rcAll.left - 5; rcOk.left = rcOk.right - okWidth; // show buttons ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDNONE), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); break; default: rcOk.left = dlgMid - (okWidth / 2); rcOk.right = rcOk.left + okWidth; } MoveWindow(GetDlgItem(hDlg, IDOK), rcOk.left, rcOk.top, rcOk.right - rcOk.left, rcOk.bottom - rcOk.top, FALSE); MoveWindow(GetDlgItem(hDlg, IDALL), rcAll.left, rcAll.top, rcAll.right - rcAll.left, rcAll.bottom - rcAll.top, FALSE); MoveWindow(GetDlgItem(hDlg, IDNONE), rcNone.left, rcNone.top, rcNone.right - rcNone.left, rcNone.bottom - rcNone.top, FALSE); MoveWindow(GetDlgItem(hDlg, IDCANCEL), rcCancel.left, rcCancel.top, rcCancel.right - rcCancel.left, rcCancel.bottom - rcCancel.top, FALSE); } // set text's SetWindowText(hDlg, pMsgBox->ptszTitle); SetDlgItemText(hDlg, TXT_NAME, pMsgBox->ptszInfoText); SetDlgItemText(hDlg, TXT_MESSAGE, pMsgBox->ptszMsg); TranslateDialogDefault(hDlg); return TRUE; } } break; case WM_CTLCOLORSTATIC: switch (GetWindowLongPtr((HWND)lParam, GWLP_ID)) { case STATIC_WHITERECT: case ICO_DLGLOGO: case ICO_MSGDLG: case TXT_MESSAGE: case TXT_NAME: SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); return GetSysColor(COLOR_WINDOW); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: EndDialog(hDlg, retOk); break; case IDCANCEL: EndDialog(hDlg, retCancel); break; case IDALL: EndDialog(hDlg, retAll); break; case IDNONE: EndDialog(hDlg, retNon); } break; case WM_DESTROY: DeleteObject((HFONT)SendDlgItemMessage(hDlg, TXT_NAME, WM_GETFONT, 0, 0)); break; } return FALSE; } /** * Dummi modal MsgBox for popup, * this set call function in wait stait and do not freece miranda main thread * the window is outside the desktop */ static INT_PTR CALLBACK MsgBoxPop(HWND hDlg, UINT uMsg, WPARAM, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: MSGBOX *pMsgBox = (MSGBOX *)lParam; MoveWindow(hDlg, -10, -10, 0, 0, FALSE); MSGPOPUPDATA *pmpd = (MSGPOPUPDATA *)mir_alloc(sizeof(MSGPOPUPDATA)); if (pmpd) { POPUPDATAW ppd; ppd.lchContact = NULL; //(HANDLE)wParam; // icon ppd.lchIcon = MsgLoadIcon(pMsgBox); mir_wstrncpy(ppd.lpwzContactName, pMsgBox->ptszTitle, _countof(ppd.lpwzContactName)); mir_wstrncpy(ppd.lpwzText, pMsgBox->ptszMsg, _countof(ppd.lpwzText)); // CALLBAC Proc ppd.PluginWindowProc = PopupProc; ppd.PluginData = pmpd; ppd.iSeconds = -1; ppd.lpActions = pmpd->pa; // set color of popup switch (pMsgBox->uType & MB_ICONMASK) { case MB_ICON_ERROR: ppd.colorBack = RGB(200, 10, 0); ppd.colorText = RGB(255, 255, 255); break; case MB_ICON_WARNING: ppd.colorBack = RGB(200, 100, 0); ppd.colorText = RGB(255, 255, 255); break; default: if (pMsgBox->uType & MB_CUSTOMCOLOR) { ppd.colorBack = pMsgBox->colorBack; ppd.colorText = pMsgBox->colorText; } } // handle for MakePopupAction pmpd->hDialog = hDlg; // active buttons switch (MB_TYPE(pMsgBox->uType)) { case MB_OK: MakePopupAction(pmpd->pa[ppd.actionCount++], IDOK); break; case MB_OKCANCEL: MakePopupAction(pmpd->pa[ppd.actionCount++], IDOK); MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); break; case MB_RETRYCANCEL: MakePopupAction(pmpd->pa[ppd.actionCount++], IDRETRY); MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); break; case MB_YESNO: MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); break; case MB_ABORTRETRYIGNORE: MakePopupAction(pmpd->pa[ppd.actionCount++], IDABORT); MakePopupAction(pmpd->pa[ppd.actionCount++], IDRETRY); MakePopupAction(pmpd->pa[ppd.actionCount++], IDIGNORE); break; case MB_YESNOCANCEL: MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); break; case MB_YESALLNO: MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); MakePopupAction(pmpd->pa[ppd.actionCount++], IDALL); MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); break; } // create popup PUAddPopupW(&ppd); if (MB_TYPE(pMsgBox->uType) == MB_OK) EndDialog(hDlg, IDOK); } break; } return FALSE; } /** * This is the message procedure for popup * * @param hDlg - window handle * @param uMsg - message to handle * @param wParam - message specific parameter * @param lParam - message specific parameter * * @return TRUE, FALSE, IDOK, IDYES, IDALL, IDNO or IDCANCEL **/ LRESULT CALLBACK PopupProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case UM_POPUPACTION: if (HIWORD(wParam) == BN_CLICKED) { MSGPOPUPDATA *pmpd = (MSGPOPUPDATA *)PUGetPluginData(hDlg); if (pmpd) { switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: case IDABORT: case IDRETRY: case IDIGNORE: case IDYES: case IDNO: case IDALL: case IDNONE: if (IsWindow(pmpd->hDialog)) EndDialog(pmpd->hDialog, LOWORD(wParam)); break; default: if (IsWindow(pmpd->hDialog)) EndDialog(pmpd->hDialog, IDCANCEL); } } PUDeletePopup(hDlg); } break; case UM_FREEPLUGINDATA: MSGPOPUPDATA *pmpd = (MSGPOPUPDATA *)PUGetPluginData(hDlg); if (pmpd > 0) MIR_FREE(pmpd); return TRUE; } return DefWindowProc(hDlg, uMsg, wParam, lParam); } /** * This is the service function for external plugins to use the nice messagebox * * @param wParam - MCONTACT hContact which can display an avatar for popups * @param lParam - MSGBOX structure holding parameters * * @return The function returns the ID of the clicked button (IDOK, IDCANCEL, ...) * or -1 on error. **/ INT_PTR MsgBoxService(WPARAM, LPARAM lParam) { MSGBOX *pMsgBox = (MSGBOX *)lParam; // check input if (PtrIsValid(pMsgBox) && pMsgBox->cbSize == sizeof(MSGBOX)) { // Shall the MessageBox displayed as popup? if (!(pMsgBox->uType & (MB_INFOBAR | MB_NOPOPUP)) // message box can be a popup? && (db_get_dw(0, "Popup", "Actions", 0) & 1) // popup++ actions on? && g_plugin.bPopupMsgbox) // user likes popups? return DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_MSGBOXDUMMI), pMsgBox->hParent, MsgBoxPop, lParam); return DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_MSGBOX), pMsgBox->hParent, MsgBoxProc, lParam); } return -1; } /** * name: MsgBox * desc: calls a messagebox * param: **/ INT_PTR CALLBACK MsgBox(HWND hParent, UINT uType, LPCTSTR pszTitle, LPCTSTR pszInfo, LPCTSTR pszFormat, ...) { wchar_t tszMsg[MAX_SECONDLINE]; va_list vl; va_start(vl, pszFormat); mir_vsnwprintf(tszMsg, _countof(tszMsg), TranslateW(pszFormat), vl); va_end(vl); MSGBOX mb = {}; mb.cbSize = sizeof(MSGBOX); mb.hParent = hParent; mb.hiLogo = g_plugin.getIcon(IDI_MAIN); mb.hiMsg = nullptr; mb.ptszTitle = TranslateW(pszTitle); mb.ptszInfoText = TranslateW(pszInfo); mb.ptszMsg = tszMsg; mb.uType = uType; return MsgBoxService(NULL, (LPARAM)&mb); } /** * name: MsgErr * desc: calls a messagebox * param: **/ INT_PTR CALLBACK MsgErr(HWND hParent, LPCTSTR pszFormat, ...) { wchar_t tszTitle[MAX_SECONDLINE], tszMsg[MAX_SECONDLINE]; mir_snwprintf(tszTitle, L"%s - %s", _T(MODULENAME), TranslateT("Error")); va_list vl; va_start(vl, pszFormat); mir_vsnwprintf(tszMsg, TranslateW(pszFormat), vl); va_end(vl); MSGBOX mb = {}; mb.cbSize = sizeof(MSGBOX); mb.hParent = hParent; mb.hiLogo = g_plugin.getIcon(IDI_MAIN); mb.hiMsg = nullptr; mb.ptszTitle = tszTitle; mb.ptszMsg = tszMsg; mb.uType = MB_OK | MB_ICON_ERROR; return MsgBoxService(NULL, (LPARAM)&mb); }