From f04d64869f3b1de54fb343f28f955584780001b8 Mon Sep 17 00:00:00 2001 From: mataes2007 Date: Sat, 26 Nov 2011 15:41:10 +0000 Subject: Project folders rename part 3 git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@215 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- Popup/src/actions.cpp | 440 ++++++++++ Popup/src/actions.h | 46 + Popup/src/avatars.cpp | 60 ++ Popup/src/avatars.h | 57 ++ Popup/src/avatars_flash.cpp | 34 + Popup/src/avatars_flash.h | 45 + Popup/src/avatars_gif.cpp | 143 ++++ Popup/src/avatars_gif.h | 55 ++ Popup/src/avatars_simple.cpp | 149 ++++ Popup/src/avatars_simple.h | 49 ++ Popup/src/bitmap_funcs.cpp | 1019 ++++++++++++++++++++++ Popup/src/bitmap_funcs.h | 132 +++ Popup/src/common.h | 296 +++++++ Popup/src/config.cpp | 210 +++++ Popup/src/config.h | 249 ++++++ Popup/src/def_settings.h | 156 ++++ Popup/src/defs.h | 52 ++ Popup/src/effects.cpp | 94 ++ Popup/src/effects.h | 38 + Popup/src/font.cpp | 154 ++++ Popup/src/font.h | 81 ++ Popup/src/formula.cpp | 177 ++++ Popup/src/formula.h | 98 +++ Popup/src/headers.cpp | 34 + Popup/src/headers.h | 190 +++++ Popup/src/history.cpp | 550 ++++++++++++ Popup/src/history.h | 43 + Popup/src/icons.cpp | 145 ++++ Popup/src/icons.h | 79 ++ Popup/src/main.cpp | 743 ++++++++++++++++ Popup/src/notifications.cpp | 349 ++++++++ Popup/src/notifications.h | 73 ++ Popup/src/opt_adv.cpp | 762 +++++++++++++++++ Popup/src/opt_adv.h | 45 + Popup/src/opt_class.cpp | 603 +++++++++++++ Popup/src/opt_class.h | 41 + Popup/src/opt_contacts.cpp | 175 ++++ Popup/src/opt_contacts.h | 46 + Popup/src/opt_gen.cpp | 761 +++++++++++++++++ Popup/src/opt_gen.h | 43 + Popup/src/opt_skins.cpp | 695 +++++++++++++++ Popup/src/opt_skins.h | 46 + Popup/src/opttree.cpp | 442 ++++++++++ Popup/src/opttree.h | 57 ++ Popup/src/popup_gdiplus.cpp | 229 +++++ Popup/src/popup_gdiplus.h | 42 + Popup/src/popup_thread.cpp | 372 ++++++++ Popup/src/popup_thread.h | 52 ++ Popup/src/popup_wnd2.cpp | 1945 ++++++++++++++++++++++++++++++++++++++++++ Popup/src/popup_wnd2.h | 273 ++++++ Popup/src/services.cpp | 675 +++++++++++++++ Popup/src/services.h | 67 ++ Popup/src/skin.cpp | 1518 ++++++++++++++++++++++++++++++++ Popup/src/skin.h | 203 +++++ Popup/src/srmm_menu.cpp | 171 ++++ Popup/src/srmm_menu.h | 39 + 56 files changed, 15342 insertions(+) create mode 100644 Popup/src/actions.cpp create mode 100644 Popup/src/actions.h create mode 100644 Popup/src/avatars.cpp create mode 100644 Popup/src/avatars.h create mode 100644 Popup/src/avatars_flash.cpp create mode 100644 Popup/src/avatars_flash.h create mode 100644 Popup/src/avatars_gif.cpp create mode 100644 Popup/src/avatars_gif.h create mode 100644 Popup/src/avatars_simple.cpp create mode 100644 Popup/src/avatars_simple.h create mode 100644 Popup/src/bitmap_funcs.cpp create mode 100644 Popup/src/bitmap_funcs.h create mode 100644 Popup/src/common.h create mode 100644 Popup/src/config.cpp create mode 100644 Popup/src/config.h create mode 100644 Popup/src/def_settings.h create mode 100644 Popup/src/defs.h create mode 100644 Popup/src/effects.cpp create mode 100644 Popup/src/effects.h create mode 100644 Popup/src/font.cpp create mode 100644 Popup/src/font.h create mode 100644 Popup/src/formula.cpp create mode 100644 Popup/src/formula.h create mode 100644 Popup/src/headers.cpp create mode 100644 Popup/src/headers.h create mode 100644 Popup/src/history.cpp create mode 100644 Popup/src/history.h create mode 100644 Popup/src/icons.cpp create mode 100644 Popup/src/icons.h create mode 100644 Popup/src/main.cpp create mode 100644 Popup/src/notifications.cpp create mode 100644 Popup/src/notifications.h create mode 100644 Popup/src/opt_adv.cpp create mode 100644 Popup/src/opt_adv.h create mode 100644 Popup/src/opt_class.cpp create mode 100644 Popup/src/opt_class.h create mode 100644 Popup/src/opt_contacts.cpp create mode 100644 Popup/src/opt_contacts.h create mode 100644 Popup/src/opt_gen.cpp create mode 100644 Popup/src/opt_gen.h create mode 100644 Popup/src/opt_skins.cpp create mode 100644 Popup/src/opt_skins.h create mode 100644 Popup/src/opttree.cpp create mode 100644 Popup/src/opttree.h create mode 100644 Popup/src/popup_gdiplus.cpp create mode 100644 Popup/src/popup_gdiplus.h create mode 100644 Popup/src/popup_thread.cpp create mode 100644 Popup/src/popup_thread.h create mode 100644 Popup/src/popup_wnd2.cpp create mode 100644 Popup/src/popup_wnd2.h create mode 100644 Popup/src/services.cpp create mode 100644 Popup/src/services.h create mode 100644 Popup/src/skin.cpp create mode 100644 Popup/src/skin.h create mode 100644 Popup/src/srmm_menu.cpp create mode 100644 Popup/src/srmm_menu.h (limited to 'Popup/src') diff --git a/Popup/src/actions.cpp b/Popup/src/actions.cpp new file mode 100644 index 0000000..32ad120 --- /dev/null +++ b/Popup/src/actions.cpp @@ -0,0 +1,440 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/actions.cpp $ +Revision : $Revision: 1622 $ +Last change on : $Date: 2010-06-23 23:32:21 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +static int ActionsSortFunc(const POPUPACTION *p1, const POPUPACTION *p2) +{ + return lstrcmpA(p1->lpzTitle, p2->lpzTitle); +} + +static LIST gActions(3, ActionsSortFunc); + +// interface +void LoadActions() +{ + POPUPACTION actions[] = + { + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_REPLY,0), "General/Quick reply", 0}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_MESS,0), "General/Send message", 0}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_INFO,0), "General/User details", 0}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_MENU,0), "General/Contact menu", 0}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_ADD,0), "General/Add permanently", 0}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_PIN,0), "General/Pin popup", 0}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_CLOSE,0), "General/Dismiss popup", 0}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_COPY,0), "General/Copy to clipboard", 0}, + +//remove popup action + #if defined(_DEBUG) + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_POPUP_ON,0), "Popup Plus/Test action", PAF_ENABLED}, + { sizeof(POPUPACTION), IcoLib_GetIcon(ICO_ACT_CLOSE,0), "Popup Plus/Second test action", 0}, + { sizeof(POPUPACTION), LoadSkinnedIcon(SKINICON_OTHER_MIRANDA), "Popup Plus/One more action", PAF_ENABLED}, + #endif + + }; + + for (int i = 0; i < SIZEOF(actions); ++i) + RegisterAction(&actions[i]); +} + +void UnloadActions() +{ +// for (int i = 0; i < gActions.getCount(); ++i) +// delete gActions[i]; + gActions.destroy(); +} + +void RegisterAction(POPUPACTION *action) +{ + int index; + if ((index = gActions.getIndex(action)) >= 0) + { + DWORD flags = gActions[index]->flags; + *gActions[index] = *action; + gActions[index]->flags = flags; + } else + { + POPUPACTION *actionCopy = (POPUPACTION *)mir_alloc(sizeof(POPUPACTION)); + *actionCopy = *action; + actionCopy->flags = + DBGetContactSettingByte(NULL, "PopUpActions", actionCopy->lpzTitle, actionCopy->flags & PAF_ENABLED) ? + PAF_ENABLED : 0; + gActions.insert(actionCopy); + } +} + +bool IsActionEnabled(POPUPACTION *action) +{ + if (!(action->flags & PAF_ENABLED)) + return false; + + int index; + if ((index = gActions.getIndex(action)) >= 0) + if (!(gActions[index]->flags & PAF_ENABLED)) + return false; + + return true; +} + +bool IsActionEnabled(char *name) +{ + POPUPACTION action = {0}; + action.flags = PAF_ENABLED; + lstrcpyA(action.lpzTitle, name); + return IsActionEnabled(&action); +} + +DWORD MouseOverride(HWND hCombo, int number) +{ + DWORD dwItem = 0; + DWORD ItemActive = 0; + if(number<0 || number >7) + number = 0; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("no overwrite")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 0); + if(number == 0) + ItemActive = dwItem; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("Send message")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 1); + if(number == 1) + ItemActive = dwItem; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("Quick reply")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 2); + if(number == 2) + ItemActive = dwItem; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("User details")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 3); + if(number == 3) + ItemActive = dwItem; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("Contact menu")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 4); + if(number == 4) + ItemActive = dwItem; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("Dismiss popup")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 5); + if(number == 5) + ItemActive = dwItem; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("Pin popup")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 6); + if(number == 6) + ItemActive = dwItem; + dwItem = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)TranslateT("Copy to clipboard")); + SendMessage(hCombo, CB_SETITEMDATA, dwItem, 7); + if(number == 7) + ItemActive = dwItem; + return ItemActive; +} + +// options +#if defined(_UNICODE) +#define ListView_InsertItemW(hwnd, pitem) \ + (int)SendMessageW((hwnd), LVM_INSERTITEMW, 0, (LPARAM)(const LVITEMW *)(pitem)) +#else +#define ListView_InsertItemW(hwnd, pitem) \ + (int)MySendMessageW((hwnd), LVM_INSERTITEMW, 0, (LPARAM)(const LVITEMW *)(pitem)) +#endif + +void LoadOption_Actions() { + PopUpOptions.actions = DBGetContactSettingDword(NULL, MODULNAME, "Actions", + ACT_ENABLE|ACT_RIGHTICONS|ACT_DEF_KEEPWND|ACT_DEF_IMONLY| + ACT_DEF_NOGLOBAL|ACT_DEF_MESSAGE|ACT_DEF_DETAILS|ACT_DEF_MENU| + ACT_DEF_ADD|ACT_DEF_DISMISS|ACT_DEF_PIN); + PopUpOptions.overrideLeft = DBGetContactSettingDword(NULL,MODULNAME, "OverrideLeft", 0); + PopUpOptions.overrideMiddle = DBGetContactSettingDword(NULL,MODULNAME, "OverrideMiddle", 0); + PopUpOptions.overrideRight = DBGetContactSettingDword(NULL,MODULNAME, "OverrideRight", 0); +} + +INT_PTR CALLBACK DlgProcPopupActions(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static bool windowInitialized = false; + + static UINT controls[] = + { + IDC_GRP_CUSTOMACTIONS, + IDC_TXT_CUSTOMACTIONS, + IDC_CHK_IMCONTACTSONLY, + IDC_CHK_CONTACTSONLY, + IDC_CHK_DONTCLOSE, + IDC_GRP_SIZEPOSITION, + IDC_CHK_LARGEICONS, + IDC_TXT_POSITION, + IDC_RD_TEXT, + IDC_RD_LEFTICONS, + IDC_RD_RIGHTICONS, + IDC_GRP_ACTIONS, + IDC_ACTIONS, + IDC_GRP_SIZEPOSITION2, + IDC_TXT_POSITION2, + IDC_CB_LEFT, + IDC_TXT_MIDDLE, + IDC_CB_MIDDLE, + IDC_TXT_RIGHT, + IDC_CB_RIGHT + }; + + switch (msg) + { + case WM_INITDIALOG: + { + int i; + windowInitialized = false; + + TranslateDialogDefault(hwnd); + + SendMessage(GetDlgItem(hwnd, IDC_ICO_INFO), STM_SETICON, (WPARAM)IcoLib_GetIcon(ICO_MISC_NOTIFY,0), 0); + + CheckDlgButton(hwnd, IDC_CHK_ENABLEACTIONS, PopUpOptions.actions&ACT_ENABLE ? TRUE : FALSE); + CheckDlgButton(hwnd, IDC_CHK_IMCONTACTSONLY, PopUpOptions.actions&ACT_DEF_IMONLY ? TRUE : FALSE); + CheckDlgButton(hwnd, IDC_CHK_CONTACTSONLY, PopUpOptions.actions&ACT_DEF_NOGLOBAL ? TRUE : FALSE); + CheckDlgButton(hwnd, IDC_CHK_DONTCLOSE, PopUpOptions.actions&ACT_DEF_KEEPWND ? TRUE : FALSE); + CheckDlgButton(hwnd, IDC_CHK_LARGEICONS, PopUpOptions.actions&ACT_LARGE ? TRUE : FALSE); + CheckDlgButton(hwnd, IDC_RD_TEXT, PopUpOptions.actions&ACT_TEXT ? TRUE : FALSE); + CheckDlgButton(hwnd, IDC_RD_LEFTICONS, PopUpOptions.actions&ACT_LEFTICONS ? TRUE : FALSE); + CheckDlgButton(hwnd, IDC_RD_RIGHTICONS, PopUpOptions.actions&ACT_RIGHTICONS ? TRUE : FALSE); + + { + DWORD dwActiveItem = 0; + HWND hCombo = GetDlgItem(hwnd, IDC_CB_LEFT); + dwActiveItem = MouseOverride(hCombo, PopUpOptions.overrideLeft); + SendDlgItemMessage(hwnd, IDC_CB_LEFT, CB_SETCURSEL, dwActiveItem, 0); + + dwActiveItem = 0; + hCombo = GetDlgItem(hwnd, IDC_CB_MIDDLE); + dwActiveItem = MouseOverride(hCombo, PopUpOptions.overrideMiddle); + SendDlgItemMessage(hwnd, IDC_CB_MIDDLE, CB_SETCURSEL, dwActiveItem, 0); + + dwActiveItem = 0; + hCombo = GetDlgItem(hwnd, IDC_CB_RIGHT); + dwActiveItem = MouseOverride(hCombo, PopUpOptions.overrideRight); + SendDlgItemMessage(hwnd, IDC_CB_RIGHT, CB_SETCURSEL, dwActiveItem, 0); + } + + HWND hwndList = GetDlgItem(hwnd, IDC_ACTIONS); + ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_CHECKBOXES|LVS_EX_LABELTIP); + HIMAGELIST hImgList = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus()? ILC_COLOR32 : ILC_COLOR16), 10, 1); + ListView_SetImageList(hwndList, hImgList, LVSIL_SMALL); + + LVCOLUMN column = {0}; + column.mask = LVCF_TEXT|LVCF_WIDTH; + column.pszText = TranslateT("Action"); + column.cx = 175; + ListView_InsertColumn(hwndList, 0, &column); + + if (IsWinVerXPPlus()) + ListView_EnableGroupView(hwndList, TRUE); + + LIST groups(1, strcmp); + + for (i = 0; i < gActions.getCount(); ++i) + { + char szGroup[64]; + char *szName = strchr(gActions[i]->lpzTitle, '/'); + if (!szName) szName = gActions[i]->lpzTitle; + else ++szName; + lstrcpynA(szGroup, gActions[i]->lpzTitle, szName - gActions[i]->lpzTitle); + + int grpId = 0; + + if (IsWinVerXPPlus() && ((grpId = groups.getIndex(szGroup)) < 0)) + { + LVGROUP group = {0}; + group.cbSize = sizeof(group); + group.mask = LVGF_HEADER|LVGF_GROUPID; + LPWSTR wszGroup = mir_a2u(szGroup); + group.pszHeader = TranslateW(wszGroup); + group.cchHeader = lstrlenW(wszGroup); + grpId = group.iGroupId = groups.getCount(); + int grpId = ListView_InsertGroup(hwndList, -1, &group); + mir_free(wszGroup); + groups.insert(mir_strdup(szGroup), groups.getCount()); + } + + if (g_popup.isOsUnicode) + { + LVITEMW item = {0}; + item.mask = LVIF_IMAGE|LVIF_PARAM|LVIF_TEXT|LVIF_STATE|LVIF_INDENT; + item.iItem = i; + LPWSTR wszName = mir_a2u(szName); + item.pszText = TranslateW(wszName); + item.iImage = ImageList_AddIcon(hImgList, gActions[i]->lchIcon); + item.lParam = i; + if (IsWinVerXPPlus()) + { + item.mask |= LVIF_GROUPID; + item.iGroupId = grpId; + } + item.iIndent = 0; + ListView_InsertItemW(hwndList, &item); + mir_free(wszName); + } else + { + LVITEMA item = {0}; + item.mask = LVIF_IMAGE|LVIF_PARAM|LVIF_TEXT|LVIF_STATE|LVIF_GROUPID|LVIF_INDENT; + item.iItem = i; + item.pszText = Translate(szName); + item.iImage = ImageList_AddIcon(hImgList, gActions[i]->lchIcon); + item.lParam = i; + item.iGroupId = grpId; + item.iIndent = 0; + ListView_InsertItem(hwndList, &item); + } + + ListView_SetItemState(hwndList, i, (gActions[i]->flags & PAF_ENABLED) ? 0x2000 : 0x1000, LVIS_STATEIMAGEMASK); + } + + groups.destroy(); + + BOOL enabled = (PopUpOptions.actions&ACT_ENABLE) ? TRUE : FALSE; + for (i = 0; i < SIZEOF(controls); ++i) + EnableWindow(GetDlgItem(hwnd, controls[i]), enabled); + + windowInitialized = true; + break; + } + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_CHK_ENABLEACTIONS: + { + PopUpOptions.actions &= ~ACT_ENABLE; + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_CHK_ENABLEACTIONS) ? ACT_ENABLE : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + + BOOL enabled = (PopUpOptions.actions&ACT_ENABLE) ? TRUE : FALSE; + for (int i = 0; i < SIZEOF(controls); ++i) + EnableWindow(GetDlgItem(hwnd, controls[i]), enabled); + break; + } + + case IDC_CHK_IMCONTACTSONLY: + PopUpOptions.actions &= ~ACT_DEF_IMONLY; + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_CHK_IMCONTACTSONLY) ? ACT_DEF_IMONLY : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + case IDC_CHK_CONTACTSONLY: + PopUpOptions.actions &= ~ACT_DEF_NOGLOBAL; + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_CHK_CONTACTSONLY) ? ACT_DEF_NOGLOBAL : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + case IDC_CHK_DONTCLOSE: + PopUpOptions.actions &= ~ACT_DEF_KEEPWND; + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_CHK_DONTCLOSE) ? ACT_DEF_KEEPWND : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + case IDC_CHK_LARGEICONS: + PopUpOptions.actions &= ~ACT_LARGE; + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_CHK_LARGEICONS) ? ACT_LARGE : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + case IDC_RD_TEXT: + PopUpOptions.actions &= ~(ACT_TEXT|ACT_LEFTICONS|ACT_RIGHTICONS); + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_CHK_ENABLEACTIONS) ? ACT_TEXT : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + case IDC_RD_LEFTICONS: + PopUpOptions.actions &= ~(ACT_TEXT|ACT_LEFTICONS|ACT_RIGHTICONS); + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_RD_LEFTICONS) ? ACT_LEFTICONS : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + case IDC_RD_RIGHTICONS: + PopUpOptions.actions &= ~(ACT_TEXT|ACT_LEFTICONS|ACT_RIGHTICONS); + PopUpOptions.actions |= IsDlgButtonChecked(hwnd, IDC_RD_RIGHTICONS) ? ACT_RIGHTICONS : 0; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + case IDC_PREVIEW: + PopUpPreview(); + break; + case IDC_CB_LEFT: + case IDC_CB_MIDDLE: + case IDC_CB_RIGHT: + PopUpOptions.overrideLeft = SendDlgItemMessage(hwnd, IDC_CB_LEFT, CB_GETITEMDATA, + SendDlgItemMessage(hwnd, IDC_CB_LEFT, CB_GETCURSEL,0,0),0); + PopUpOptions.overrideMiddle = SendDlgItemMessage(hwnd, IDC_CB_MIDDLE, CB_GETITEMDATA, + SendDlgItemMessage(hwnd, IDC_CB_MIDDLE, CB_GETCURSEL,0,0),0); + PopUpOptions.overrideRight = SendDlgItemMessage(hwnd, IDC_CB_RIGHT, CB_GETITEMDATA, + SendDlgItemMessage(hwnd, IDC_CB_RIGHT, CB_GETCURSEL,0,0),0); + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + break; + } + break; + } + + case WM_NOTIFY: + { + switch (((LPNMHDR)lParam)->idFrom) + { + case 0: + { + switch (((LPNMHDR)lParam)->code) + { + case PSN_RESET: + LoadOption_Actions(); + break; + case PSN_APPLY: + { + DBWriteContactSettingDword(NULL, MODULNAME, "Actions", PopUpOptions.actions); + HWND hwndList = GetDlgItem(hwnd, IDC_ACTIONS); + for (int i = 0; i < gActions.getCount(); ++i) + { + gActions[i]->flags = (ListView_GetItemState(hwndList, i, LVIS_STATEIMAGEMASK) == 0x2000) ? PAF_ENABLED : 0; + DBWriteContactSettingByte(NULL, "PopUpActions", gActions[i]->lpzTitle, (gActions[i]->flags&PAF_ENABLED) ? 1 : 0); + } + //overrideActions + DBWriteContactSettingDword(NULL, MODULNAME, "OverrideLeft", PopUpOptions.overrideLeft); + DBWriteContactSettingDword(NULL, MODULNAME, "OverrideMiddle", PopUpOptions.overrideMiddle); + DBWriteContactSettingDword(NULL, MODULNAME, "OverrideRight", PopUpOptions.overrideRight); + break; + } + } + break; + } + + case IDC_ACTIONS: + { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + if (windowInitialized && + nmlv && nmlv->hdr.code == LVN_ITEMCHANGED && nmlv->uOldState != 0 && + (nmlv->uNewState == 0x1000 || nmlv->uNewState == 0x2000)) + { + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + } + } + break; + } + + } + return FALSE; +} diff --git a/Popup/src/actions.h b/Popup/src/actions.h new file mode 100644 index 0000000..7938f1e --- /dev/null +++ b/Popup/src/actions.h @@ -0,0 +1,46 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/actions.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __actions_h__ +#define __actions_h__ + +void LoadActions(); +void UnloadActions(); + +void RegisterAction(POPUPACTION *action); +bool IsActionEnabled(POPUPACTION *action); +bool IsActionEnabled(char *name); + +void LoadOption_Actions(); +INT_PTR CALLBACK DlgProcPopupActions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif // __actions_h__ diff --git a/Popup/src/avatars.cpp b/Popup/src/avatars.cpp new file mode 100644 index 0000000..93cab8d --- /dev/null +++ b/Popup/src/avatars.cpp @@ -0,0 +1,60 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +PopupAvatar *PopupAvatar::create(HANDLE hContact) +{ + if (hContact) + { + if (ServiceExists(MS_AV_GETAVATARBITMAP)) + { + avatarCacheEntry *av = (avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0); +// MessageBox(NULL, _T("00"), _T(MODULNAME_LONG), MB_OK); + if (av && (strlen(av->szFilename) > 4)) + { +// MessageBox(NULL, _T("01"), _T(MODULNAME_LONG), MB_OK); + if (!stricmp(av->szFilename+strlen(av->szFilename)-4, ".gif")) + { +// MessageBox(NULL, _T("02"), _T(MODULNAME_LONG), MB_OK); + if (DBGetContactSettingByte(NULL, MODULNAME, "EnableGifAnimation", 1) && GDIPlus_IsAnimatedGIF(av->szFilename)) + { +// MessageBox(NULL, _T("03"), _T(MODULNAME_LONG), MB_OK); + return new GifAvatar(hContact); + } + } + } + } + } + + return new SimpleAvatar(hContact); +} diff --git a/Popup/src/avatars.h b/Popup/src/avatars.h new file mode 100644 index 0000000..77d2461 --- /dev/null +++ b/Popup/src/avatars.h @@ -0,0 +1,57 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __avatars_h__ +#define __avatars_h__ + +class PopupAvatar +{ +protected: + int width, height; + bool bIsAnimated, bIsValid; + +public: + PopupAvatar(HANDLE hContact) {} + virtual ~PopupAvatar() {} + virtual int activeFrameDelay() = 0; + virtual void draw(MyBitmap *bmp, int x, int y, int w, int h, POPUPOPTIONS *options) = 0; + + inline bool isValid() { return bIsValid; } + inline void invalidate() { bIsValid = false; } + inline bool isAnimated() { return bIsAnimated; } + inline int getWidth() { return width; } + inline int getHeight() { return height; } + + static PopupAvatar *create(HANDLE hContact); +}; + +#endif // __avatars_h__ diff --git a/Popup/src/avatars_flash.cpp b/Popup/src/avatars_flash.cpp new file mode 100644 index 0000000..2cd95e2 --- /dev/null +++ b/Popup/src/avatars_flash.cpp @@ -0,0 +1,34 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars_flash.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + diff --git a/Popup/src/avatars_flash.h b/Popup/src/avatars_flash.h new file mode 100644 index 0000000..9c54830 --- /dev/null +++ b/Popup/src/avatars_flash.h @@ -0,0 +1,45 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars_flash.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __avatars_flash_h__ +#define __avatars_flash_h__ + +class FlashAvatar: public PopupAvatar +{ +public: + FlashAvatar(HANDLE hContact); + virtual ~FlashAvatar(); + virtual int activeFrameDelay() = 0; + virtual void draw(MyBitmap *bmp, int x, int y, int w, int h, POPUPOPTIONS *options) = 0; +}; + +#endif // __avatars_flash_h__ diff --git a/Popup/src/avatars_gif.cpp b/Popup/src/avatars_gif.cpp new file mode 100644 index 0000000..24ee798 --- /dev/null +++ b/Popup/src/avatars_gif.cpp @@ -0,0 +1,143 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars_gif.cpp $ +Revision : $Revision: 1624 $ +Last change on : $Date: 2010-06-24 19:39:34 +0300 (Чт, 24 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +GifAvatar::GifAvatar(HANDLE hContact): PopupAvatar(hContact) +{ + av = (avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0); + bIsAnimated = true; + bIsValid = true; + GDIPlus_GetGIFSize(av->szFilename, &this->width, &this->height); + + hBitmap = NULL; + frameDelays = NULL; + frameCount = 0; + frameSize.cx = frameSize.cy = 0; + + cachedHeight = cachedWidth = -1; + + activeFrame = 0; +} + +GifAvatar::~GifAvatar() +{ + if (frameDelays) { + mir_free(frameDelays); + frameDelays = NULL; + } + if (hBitmap) DeleteObject(hBitmap); +} + +int GifAvatar::activeFrameDelay() +{ + if (!av || !frameCount || !frameDelays || !hBitmap || (activeFrame < 0) || (activeFrame >= frameCount)) + return -1; + return frameDelays[activeFrame]; +} + +void GifAvatar::draw(MyBitmap *bmp, int x, int y, int w, int h, POPUPOPTIONS *options) +{ + if (!av || (w <= 0) || (h <= 0)) return; + + if (!frameCount || !frameDelays || !hBitmap || (cachedWidth != w) || (cachedHeight != h)) + { + cachedWidth = w; + cachedHeight = h; + if (frameDelays) { + mir_free(frameDelays); + frameDelays = NULL; + } + if (hBitmap) DeleteObject(hBitmap); + GDIPlus_ExtractAnimatedGIF(av->szFilename, w, h, &hBitmap, &frameDelays, &frameCount, &frameSize); + } + + if (!frameCount) return; + + HRGN rgn; + if (options->avatarRadius) + { + rgn = CreateRoundRectRgn(x, y, x+w, y+h, 2 * options->avatarRadius, 2 * options->avatarRadius); + SelectClipRgn(bmp->getDC(), rgn); + } else + { + rgn = CreateRectRgn(x, y, x+w, y+h); + } + + HDC hdcTmp = CreateCompatibleDC(bmp->getDC()); + SelectObject(hdcTmp, hBitmap); + SetStretchBltMode(bmp->getDC(), HALFTONE); + +#if defined(_UNICODE) + if (av->dwFlags & AVS_PREMULTIPLIED) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + AlphaBlend(bmp->getDC(), x, y, w, h, hdcTmp, frameSize.cx*activeFrame, 0, frameSize.cx, frameSize.cy, bf); +#else + if (MyAlphaBlend && (av->dwFlags & AVS_PREMULTIPLIED)) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + MyAlphaBlend(bmp->getDC(), x, y, w, h, hdcTmp, frameSize.cx*activeFrame, 0, frameSize.cx, frameSize.cy, bf); +#endif + if (options->avatarBorders && options->avatarPNGBorders) + { + HBRUSH hbr = CreateSolidBrush(fonts.clAvatarBorder); + bmp->saveAlpha(x, y, w, h); + FrameRgn(bmp->getDC(), rgn, hbr, 1, 1); + DeleteObject(hbr); + bmp->restoreAlpha(x, y, w, h); + } + } + else { + bmp->saveAlpha(x, y, w, h); + StretchBlt(bmp->getDC(), x, y, w, h, hdcTmp, frameSize.cx*activeFrame, 0, frameSize.cx, frameSize.cy, SRCCOPY); + if (options->avatarBorders) { + HBRUSH hbr = CreateSolidBrush(fonts.clAvatarBorder); + FrameRgn(bmp->getDC(), rgn, hbr, 1, 1); + DeleteObject(hbr); + } + bmp->restoreAlpha(x, y, w, h); + } + DeleteObject(rgn); + SelectClipRgn(bmp->getDC(), NULL); + DeleteDC(hdcTmp); + + activeFrame = (activeFrame + 1) % frameCount; +} diff --git a/Popup/src/avatars_gif.h b/Popup/src/avatars_gif.h new file mode 100644 index 0000000..e7ec905 --- /dev/null +++ b/Popup/src/avatars_gif.h @@ -0,0 +1,55 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars_gif.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __avatars_gif_h__ +#define __avatars_gif_h__ + +class GifAvatar: public PopupAvatar +{ +protected: + avatarCacheEntry *av; + int cachedWidth, cachedHeight; + int activeFrame; + + HBITMAP hBitmap; + int *frameDelays; + int frameCount; + SIZE frameSize; + +public: + GifAvatar(HANDLE hContact); + virtual ~GifAvatar(); + virtual int activeFrameDelay(); + virtual void draw(MyBitmap *bmp, int x, int y, int w, int h, POPUPOPTIONS *options); +}; + +#endif // __avatars_gif_h__ diff --git a/Popup/src/avatars_simple.cpp b/Popup/src/avatars_simple.cpp new file mode 100644 index 0000000..2c3b334 --- /dev/null +++ b/Popup/src/avatars_simple.cpp @@ -0,0 +1,149 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars_simple.cpp $ +Revision : $Revision: 1624 $ +Last change on : $Date: 2010-06-24 19:39:34 +0300 (Чт, 24 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +SimpleAvatar::SimpleAvatar(HANDLE hContact, bool bUseBitmap): PopupAvatar(bUseBitmap ? 0 : hContact) +{ + bIsAnimated = false; + bIsValid = true; + + if (bUseBitmap) + { + BITMAP bmp; + GetObject((HBITMAP)hContact, sizeof(bmp), &bmp); + width = abs(bmp.bmWidth); + height = abs(bmp.bmHeight); + + avNeedFree = true; + av = new avatarCacheEntry; + av->bmHeight = abs(bmp.bmHeight); + av->bmWidth = abs(bmp.bmWidth); + av->hbmPic = (HBITMAP)hContact; + av->dwFlags = AVS_BITMAP_VALID; + return; + } + + if (hContact && ServiceExists(MS_AV_GETAVATARBITMAP)) + { + avNeedFree = false; + av = (avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0); + if (av) + { + if (av->hbmPic && (av->dwFlags&AVS_BITMAP_VALID) && !(av->dwFlags&AVS_HIDEONCLIST) && !(av->dwFlags&AVS_NOTREADY)) + { + width = av->bmWidth; + height = av->bmHeight; + return; + } + + if (av->dwFlags&AVS_NOTREADY) + bIsValid = false; + } + } + + width = height = 0; + av = NULL; + avNeedFree = false; +} + +SimpleAvatar::~SimpleAvatar() +{ + if (avNeedFree) delete av; +} + +int SimpleAvatar::activeFrameDelay() +{ + return -1; +} + +void SimpleAvatar::draw(MyBitmap *bmp, int x, int y, int w, int h, POPUPOPTIONS *options) +{ + if (!av) return; + + HRGN rgn; + if (options->avatarRadius) + { + rgn = CreateRoundRectRgn(x, y, x+w, y+h, 2 * options->avatarRadius, 2 * options->avatarRadius); + SelectClipRgn(bmp->getDC(), rgn); + } else + { + rgn = CreateRectRgn(x, y, x+w, y+h); + } + + HDC hdcTmp = CreateCompatibleDC(bmp->getDC()); + SelectObject(hdcTmp, av->hbmPic); + SetStretchBltMode(bmp->getDC(), HALFTONE); + +#if defined(_UNICODE) + if (av->dwFlags & AVS_HASTRANSPARENCY) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + AlphaBlend(bmp->getDC(), x, y, w, h, hdcTmp, 0, 0, av->bmWidth, av->bmHeight, bf); +#else +// if (MyAlphaBlend && (av->dwFlags & AVS_PREMULTIPLIED)) + if (MyAlphaBlend && (av->dwFlags & AVS_HASTRANSPARENCY)) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + MyAlphaBlend(bmp->getDC(), x, y, w, h, hdcTmp, 0, 0, av->bmWidth, av->bmHeight, bf); +#endif + if (options->avatarBorders && options->avatarPNGBorders) + { + HBRUSH hbr = CreateSolidBrush(fonts.clAvatarBorder); + bmp->saveAlpha(x, y, w, h); + FrameRgn(bmp->getDC(), rgn, hbr, 1, 1); + DeleteObject(hbr); + bmp->restoreAlpha(x, y, w, h); + } + } + else { + bmp->saveAlpha(x, y, w, h); + StretchBlt(bmp->getDC(), x, y, w, h, hdcTmp, 0, 0, av->bmWidth, av->bmHeight, SRCCOPY); + if (options->avatarBorders){ + HBRUSH hbr = CreateSolidBrush(fonts.clAvatarBorder); + FrameRgn(bmp->getDC(), rgn, hbr, 1, 1); + DeleteObject(hbr); + } + bmp->restoreAlpha(x, y, w, h); + } + DeleteObject(rgn); + SelectClipRgn(bmp->getDC(), NULL); + DeleteDC(hdcTmp); +} diff --git a/Popup/src/avatars_simple.h b/Popup/src/avatars_simple.h new file mode 100644 index 0000000..5cc8037 --- /dev/null +++ b/Popup/src/avatars_simple.h @@ -0,0 +1,49 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/avatars_simple.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __avatars_simple_h__ +#define __avatars_simple_h__ + +class SimpleAvatar: public PopupAvatar +{ +private: + avatarCacheEntry *av; + bool avNeedFree; + +public: + SimpleAvatar(HANDLE hContact, bool bUseBitmap = false); + virtual ~SimpleAvatar(); + virtual int activeFrameDelay(); + virtual void draw(MyBitmap *bmp, int x, int y, int w, int h, POPUPOPTIONS *options); +}; + +#endif // __avatars_simple_h__ diff --git a/Popup/src/bitmap_funcs.cpp b/Popup/src/bitmap_funcs.cpp new file mode 100644 index 0000000..4cb013a --- /dev/null +++ b/Popup/src/bitmap_funcs.cpp @@ -0,0 +1,1019 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/bitmap_funcs.cpp $ +Revision : $Revision: 1627 $ +Last change on : $Date: 2010-06-29 10:34:46 +0300 (Ð’Ñ‚, 29 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" +#include "bitmap_funcs.h" + +#define PU_BMP_ACCURATE_ARITHMETICS + +#ifdef PU_BMP_ACCURATE_ARITHMETICS + #define PU_DIV255(x) ((x)/255) + #define PU_DIV128(x) ((x)/128) + typedef float pu_koef; +#else + #define PU_DIV255(x) ((x)>>8) + #define PU_DIV128(x) ((x)>>7) + typedef long pu_koef; +#endif + +MyBitmap::MyBitmap() +{ + dcBmp = 0; + hBmp = 0; + bits = 0; + width = height = 0; + bitsSave = 0; +} + +MyBitmap::MyBitmap(int w, int h) +{ + dcBmp = 0; + hBmp = 0; + bits = 0; + width = height = 0; + bitsSave = 0; + allocate(w,h); +} + +MyBitmap::MyBitmap(const char *fn, const char *fnAlpha) +{ + dcBmp = 0; + hBmp = 0; + bits = 0; + width = height = 0; + bitsSave = 0; + loadFromFile(fn, fnAlpha); +} + +MyBitmap::~MyBitmap() +{ + if (bitsSave) + delete [] bitsSave; + free(); +} + +void MyBitmap::makeOpaque() +{ + if (!bits) return; + + GdiFlush(); + for (int i = 0; i < width*height; i++) + bits[i] |= 0xff000000; +} + +void MyBitmap::makeOpaqueRect(int x1, int y1, int x2, int y2) +{ + if (!bits) return; + + GdiFlush(); + for (int i = y1; i < y2; i++) + for (int j = x1; j < x2; j++) + { + int idx = i * width + j; + bits[idx] |= 0xff000000; + } +} + +void MyBitmap::saveAlpha(int x, int y, int w, int h) +{ + if (bitsSave) + delete [] bitsSave; + + GdiFlush(); + + if (!w) w = width; + if (!h) h = height; + if (!w || !h) + return; + if (x < 0 || y < 0) + return; + + bitsSave = new COLOR32[w*h]; + COLOR32 *p1 = bitsSave; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + COLOR32 *p2 = bits + (y+i)*width + x; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + *p1++ = *p2++; + } + } +} + +void MyBitmap::restoreAlpha(int x, int y, int w, int h) +{ + if (!bitsSave) + return; + + GdiFlush(); + + if (!w) w = width; + if (!h) h = height; + + COLOR32 *p1 = bitsSave; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + COLOR32 *p2 = bits + (y+i)*width + x; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + if ((*p1&0x00ffffff) != (*p2&0x00ffffff)) + { + *p2 |= 0xff000000; + } else + { + *p2 = (*p2&0x00ffffff) | (*p1&0xff000000); + } + ++p1; + ++p2; + } + } + + delete [] bitsSave; + bitsSave = 0; +} + +void MyBitmap::DrawBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h) +{ + if (!(bits && inbits)) return; + + GdiFlush(); + + float kx = (float)inw / w; + float ky = (float)inh / h; + + if (x+w >= this->getWidth()) + w = this->getWidth() - x; + if (y+h >= this->getHeight()) + h = this->getHeight() - y; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + bits[(i+y)*width + (j+x)] = inbits[int(i*ky)*inw + int(j*kx)]; + } + } +} + +void MyBitmap::BlendBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h) +{ + if (!(bits && inbits)) return; + + GdiFlush(); + + float kx = (float)inw / w; + float ky = (float)inh / h; + + if (x+w >= this->getWidth()) + w = this->getWidth() - x; + if (y+h >= this->getHeight()) + h = this->getHeight() - y; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + COLOR32 src = inbits[int(i*ky)*inw + int(j*kx)]; + COLOR32 dst = bits[(i+y)*width + (j+x)]; + long alpha = geta(src); + bits[(i+y)*width + (j+x)] = rgba( + getr(src)+PU_DIV255((255-alpha)*getr(dst)), + getg(src)+PU_DIV255((255-alpha)*getg(dst)), + getb(src)+PU_DIV255((255-alpha)*getb(dst)), + geta(src)+PU_DIV255((255-alpha)*geta(dst)) + ); + } + } +} + +void MyBitmap::Blend(MyBitmap *bmp, int x, int y, int w, int h) +{ + if (!(bits && bmp && bmp->bits)) return; + + GdiFlush(); + + if (!w) w = bmp->width; + if (!h) h = bmp->height; + float kx = (float)bmp->width / w; + float ky = (float)bmp->height / h; + + if (x+w >= this->getWidth()) + w = this->getWidth() - x; + if (y+h >= this->getHeight()) + h = this->getHeight() - y; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + COLOR32 src = bmp->bits[int(i*ky)*bmp->width + int(j*kx)]; + COLOR32 dst = bits[(i+y)*width + (j+x)]; + long alpha = geta(src); + bits[(i+y)*width + (j+x)] = rgba( + getr(src)+PU_DIV255((255-alpha)*getr(dst)), + getg(src)+PU_DIV255((255-alpha)*getg(dst)), + getb(src)+PU_DIV255((255-alpha)*getb(dst)), + geta(src)+PU_DIV255((255-alpha)*geta(dst)) + ); + } + } +} + +void MyBitmap::Draw(MyBitmap *bmp, int x, int y, int w, int h) +{ + if (!(bits && bmp && bmp->bits)) return; + + GdiFlush(); + + if (!w) w = bmp->width; + if (!h) h = bmp->height; + + if (!x && !y && (w == width) && (h == height) && (w == bmp->width) && (h == bmp->height)) + { + // fast bitmap copy is possible good for animated avatars + CopyMemory(bits, bmp->bits, width*height*sizeof(COLOR32)); + return; + } + + float kx = (float)bmp->width / w; + float ky = (float)bmp->height / h; + + if (x+w >= this->getWidth()) + w = this->getWidth() - x; + if (y+h >= this->getHeight()) + h = this->getHeight() - y; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + bits[(i+y)*width + (j+x)] = bmp->bits[int(i*ky)*bmp->width + int(j*kx)]; + } + } +} + +void MyBitmap::BlendColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color) +{ + if (!(bits && bmp && bmp->bits)) return; + + GdiFlush(); + + if (!w) w = bmp->width; + if (!h) h = bmp->height; + float kx = (float)bmp->width / w; + float ky = (float)bmp->height / h; + + // we should swap B and R channels when working with win32 COLORREF + float koef1r = (255 - getb(color)) / 128.0; + float koef1g = (255 - getg(color)) / 128.0; + float koef1b = (255 - getr(color)) / 128.0; + + int br = - 255 + 2 * getb(color); + int bg = - 255 + 2 * getg(color); + int bb = - 255 + 2 * getr(color); + + float koef2r = (getb(color)) / 128.0; + float koef2g = (getg(color)) / 128.0; + float koef2b = (getr(color)) / 128.0; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + +// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); +// bits[(i+y)*width + (j+x)] = (cl > 128) ? +// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])): +// rgba(koef2r * cl, koef2g * cl, koef2b * cl, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])); + + long alpha = geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); +// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); + COLOR32 cl = alpha ? getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])*255/alpha : 0; +#pragma warning(push) +#pragma warning(disable: 4244) + COLOR32 src = (cl > 128) ? + rgba( + PU_DIV255((koef1r * cl + br)*alpha), + PU_DIV255((koef1g * cl + bg)*alpha), + PU_DIV255((koef1b * cl + bb)*alpha), + alpha): + rgba( + PU_DIV255(koef2r * cl * alpha), + PU_DIV255(koef2g * cl * alpha), + PU_DIV255(koef2b * cl * alpha), + alpha); +#pragma warning(pop) +// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); +// COLOR32 src = (cl > 128) ? +// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, alpha): +// rgba(koef2r * cl, koef2g * cl, koef2b * cl, alpha); + COLOR32 dst = bits[(i+y)*width + (j+x)]; +// long alpha = geta(src); + bits[(i+y)*width + (j+x)] = rgba( + getr(src)+PU_DIV255((255-alpha)*getr(dst)), + getg(src)+PU_DIV255((255-alpha)*getg(dst)), + getb(src)+PU_DIV255((255-alpha)*getb(dst)), + geta(src)+PU_DIV255((255-alpha)*geta(dst)) + ); + + } + } +} + +void MyBitmap::DrawColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color) +{ + if (!(bits && bmp && bmp->bits)) return; + + GdiFlush(); + + if (!w) w = bmp->width; + if (!h) h = bmp->height; + float kx = (float)bmp->width / w; + float ky = (float)bmp->height / h; + + // we should swap B and R channels when working with win32 COLORREF + float koef1r = (255 - getb(color)) / 128.0; + float koef1g = (255 - getg(color)) / 128.0; + float koef1b = (255 - getr(color)) / 128.0; + + int br = - 255 + 2 * getb(color); + int bg = - 255 + 2 * getg(color); + int bb = - 255 + 2 * getr(color); + + float koef2r = (getb(color)) / 128.0; + float koef2g = (getg(color)) / 128.0; + float koef2b = (getr(color)) / 128.0; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + + long alpha = geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); +// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); + COLOR32 cl = alpha ? getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])*255/alpha : 0; +#pragma warning(push) +#pragma warning(disable: 4244) + bits[(i+y)*width + (j+x)] = (cl > 128) ? + rgba( + PU_DIV255((koef1r * cl + br)*alpha), + PU_DIV255((koef1g * cl + bg)*alpha), + PU_DIV255((koef1b * cl + bb)*alpha), + alpha): + rgba( + PU_DIV255(koef2r * cl * alpha), + PU_DIV255(koef2g * cl * alpha), + PU_DIV255(koef2b * cl * alpha), + alpha); +#pragma warning(pop) +// bits[(i+y)*width + (j+x)] = (cl > 128) ? +// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])): +// rgba(koef2r * cl, koef2g * cl, koef2b * cl, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])); + } + } +} + +void MyBitmap::BlendPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h) +{ + if (!(bits && bmp && bmp->bits)) return; + if (!win || !hin) return; + + GdiFlush(); + + if (!w) w = win; + if (!h) h = hin; + float kx = (float)win / w; + float ky = (float)hin / h; + + if (x+w >= this->getWidth()) + w = this->getWidth() - x; + if (y+h >= this->getHeight()) + h = this->getHeight() - y; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + COLOR32 src = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]; + COLOR32 dst = bits[(i+y)*width + (j+x)]; + long alpha = geta(src); + bits[(i+y)*width + (j+x)] = rgba( + getr(src)+PU_DIV255((255-alpha)*getr(dst)), + getg(src)+PU_DIV255((255-alpha)*getg(dst)), + getb(src)+PU_DIV255((255-alpha)*getb(dst)), + geta(src)+PU_DIV255((255-alpha)*geta(dst)) + ); +// bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]; + } + } +} + +void MyBitmap::BlendPartColorized(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h, COLOR32 color) +{ + if (!(bits && bmp && bmp->bits)) return; + if (!win || !hin) return; + + GdiFlush(); + + if (!w) w = win; + if (!h) h = hin; + float kx = (float)win / w; + float ky = (float)hin / h; + + if (x+w >= this->getWidth()) + w = this->getWidth() - x; + if (y+h >= this->getHeight()) + h = this->getHeight() - y; + + // we should swap B and R channels when working with win32 COLORREF + float koef1r = (255 - getb(color)) / 128.0; + float koef1g = (255 - getg(color)) / 128.0; + float koef1b = (255 - getr(color)) / 128.0; + + int br = - 255 + 2 * getb(color); + int bg = - 255 + 2 * getg(color); + int bb = - 255 + 2 * getr(color); + + float koef2r = (getb(color)) / 128.0; + float koef2g = (getg(color)) / 128.0; + float koef2b = (getr(color)) / 128.0; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + + long alpha = geta(bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]); +// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); + COLOR32 cl = alpha ? getr(bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)])*255/alpha : 0; +#pragma warning(push) +#pragma warning(disable: 4244) + COLOR32 src = (cl > 128) ? + rgba( + PU_DIV255((koef1r * cl + br)*alpha), + PU_DIV255((koef1g * cl + bg)*alpha), + PU_DIV255((koef1b * cl + bb)*alpha), + alpha): + rgba( + PU_DIV255(koef2r * cl * alpha), + PU_DIV255(koef2g * cl * alpha), + PU_DIV255(koef2b * cl * alpha), + alpha); +#pragma warning(pop) +// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]); +// COLOR32 src = (cl > 128) ? +// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, alpha): +// rgba(koef2r * cl, koef2g * cl, koef2b * cl, alpha); + COLOR32 dst = bits[(i+y)*width + (j+x)]; +// long alpha = geta(src); + bits[(i+y)*width + (j+x)] = rgba( + getr(src)+PU_DIV255((255-alpha)*getr(dst)), + getg(src)+PU_DIV255((255-alpha)*getg(dst)), + getb(src)+PU_DIV255((255-alpha)*getb(dst)), + geta(src)+PU_DIV255((255-alpha)*geta(dst)) + ); + +/* COLOR32 src = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]; + COLOR32 dst = bits[(i+y)*width + (j+x)]; + long alpha = geta(src); + bits[(i+y)*width + (j+x)] = rgba( + getr(src)+(255-alpha)*getr(dst)/255, + getg(src)+(255-alpha)*getg(dst)/255, + getb(src)+(255-alpha)*getb(dst)/255, + geta(src)+(255-alpha)*geta(dst)/255 + );*/ +// bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]; + } + } +} + +void MyBitmap::DrawPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h) +{ + if (!(bits && bmp && bmp->bits)) return; + if (!win || !hin) return; + + GdiFlush(); + + if (!w) w = win; + if (!h) h = hin; + float kx = (float)win / w; + float ky = (float)hin / h; + + if (x+w >= this->getWidth()) + w = this->getWidth() - x; + if (y+h >= this->getHeight()) + h = this->getHeight() - y; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]; + } + } +} + +void MyBitmap::DrawNoAlpha(MyBitmap *bmp, int x, int y, int w, int h) +{ + if (!(bits && bmp && bmp->bits)) return; + + GdiFlush(); + + for (int i = 0; i < bmp->height; i++) + { + if (i+y < 0) continue; + if (i+y >= height) break; + for (int j = 0; j < bmp->width; j++) + { + if (j+x < 0) continue; + if (j+x >= width) break; + bits[(i+y)*width + (j+x)] = bmp->bits[i*bmp->width + j]; + } + } +} + +void MyBitmap::DrawIcon(HICON hic, int x, int y, int w, int h) +{ + GdiFlush(); + + ICONINFO info; + GetIconInfo(hic, &info); + + BITMAP bmpColor, bmpMask; + GetObject(info.hbmMask, sizeof(bmpMask), &bmpMask); + GetObject(info.hbmColor, sizeof(bmpColor), &bmpColor); + + if (!w) w = abs(bmpMask.bmWidth); + if (!h) h = abs(bmpMask.bmHeight); + + if (bmpColor.bmBitsPixel == 32) + { + if ((w != abs(bmpMask.bmWidth)) || (h != abs(bmpMask.bmHeight))) + { + DeleteObject(info.hbmColor); + DeleteObject(info.hbmMask); + HICON hicTmp = (HICON)CopyImage(hic,IMAGE_ICON,w,h,LR_COPYFROMRESOURCE); + GetIconInfo(hicTmp, &info); + GetObject(info.hbmMask, sizeof(bmpMask), &bmpMask); + GetObject(info.hbmColor, sizeof(bmpColor), &bmpColor); + DestroyIcon(hicTmp); + } + + BYTE *cbit = new BYTE[bmpColor.bmWidthBytes*bmpColor.bmHeight]; + BYTE *mbit = new BYTE[bmpMask.bmWidthBytes*bmpMask.bmHeight]; + GetBitmapBits(info.hbmColor, bmpColor.bmWidthBytes*bmpColor.bmHeight, cbit); + GetBitmapBits(info.hbmMask, bmpMask.bmWidthBytes*bmpMask.bmHeight, mbit); + + for (int i = 0; i < bmpColor.bmHeight; i++) + { + for (int j = 0; j < bmpColor.bmWidth; j++) + { + BYTE *pixel = cbit + i*bmpColor.bmWidthBytes + j*4; + if (!pixel[3]) + { + pixel[3] = (*(mbit + i*bmpMask.bmWidthBytes + j*bmpMask.bmBitsPixel/8) & (1<<(7-j%8))) ? 0 : 255; + } + + if (pixel[3] != 255) + { + pixel[0] = PU_DIV255(pixel[0] * pixel[3]); + pixel[1] = PU_DIV255(pixel[1] * pixel[3]); + pixel[2] = PU_DIV255(pixel[2] * pixel[3]); + } + } + } + + this->BlendBits((COLOR32 *)cbit, bmpColor.bmWidth, bmpColor.bmHeight, x, y, w, h); + + delete [] mbit; + delete [] cbit; + } else + { + this->saveAlpha(x,y,w,h); + DrawIconEx(this->getDC(), x, y, hic, w, h, 0, NULL, DI_NORMAL); + this->restoreAlpha(x,y,w,h); + } + + DeleteObject(info.hbmColor); + DeleteObject(info.hbmMask); +} + +void MyBitmap::Draw_TextA(char *str, int x, int y) +{ + GdiFlush(); + + SIZE sz; GetTextExtentPoint32A(this->getDC(), str, lstrlenA(str), &sz); + RECT rc; SetRect(&rc, x, y, x+10000, y+10000); + this->saveAlpha(x-2,y-2,sz.cx+2,sz.cy+2); + ::DrawTextA(this->getDC(), str, (int)strlen(str), &rc, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX); + this->restoreAlpha(x-2,y-2,sz.cx+2,sz.cy+2); + //(x,y,sz.cx,sz.cy); +} + +void MyBitmap::Draw_TextW(WCHAR *str, int x, int y) +{ +#if defined(_UNICODE) + SIZE sz; GetTextExtentPoint32W(this->getDC(), str, lstrlenW(str), &sz); + RECT rc; SetRect(&rc, x, y, x+10000, y+10000); + this->saveAlpha(x,y,sz.cx,sz.cy); + DrawTextW(this->getDC(), str, lstrlenW(str), &rc, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX); + this->restoreAlpha(x,y,sz.cx,sz.cy); +#else + if (MyGetTextExtentPoint32W && MyDrawTextW) + { + SIZE sz; MyGetTextExtentPoint32W(this->getDC(), str, lstrlenW(str), &sz); + RECT rc; SetRect(&rc, x, y, x+10000, y+10000); + this->saveAlpha(x,y,sz.cx,sz.cy); + MyDrawTextW(this->getDC(), str, lstrlenW(str), &rc, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX); + this->restoreAlpha(x,y,sz.cx,sz.cy); + } +#endif +} + +// based on code by Yuriy Zaporozhets from: +// http://www.codeproject.com/gdi/coolrgn.asp?df=100&forumid=739&exp=0&select=6341 +// slightly modified to integrate with MyBitmap class. +HRGN MyBitmap::buildOpaqueRgn(int level, bool opaque) +{ + GdiFlush(); + + const int addRectsCount = 64; + int rectsCount = addRectsCount; + PRGNDATA pRgnData = (PRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]); + LPRECT pRects = (LPRECT)(&pRgnData->Buffer); + + memset(pRgnData, 0, sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)); + pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER); + pRgnData->rdh.iType = RDH_RECTANGLES; + + int first = 0; + bool wasfirst = false; + bool ismask = false; + for (int i = 0; i < height; i++) + { + int j; // we will need j after the loop! + for (j = 0; j < width; j++) + { + ismask = opaque ? geta(this->getRow(i)[j]) > (DWORD)level : geta(this->getRow(i)[j]) < (DWORD)level; + if (wasfirst) + { + if (!ismask) + { + SetRect(&pRects[pRgnData->rdh.nCount++], first, i, j, i+1); + if (pRgnData->rdh.nCount >= (DWORD) rectsCount) + { + rectsCount += addRectsCount; + LPRGNDATA pRgnDataNew = (LPRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]); + memcpy(pRgnDataNew, pRgnData, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT)); + delete pRgnData; + pRgnData = pRgnDataNew; + pRects = (LPRECT)(&pRgnData->Buffer); + } + wasfirst = false; + } + } else + if (ismask) // set wasfirst when mask is found + { + first = j; + wasfirst = true; + } + } + + if (wasfirst && ismask) + { + SetRect(&pRects[pRgnData->rdh.nCount++], first, i, j, i+1); + if (pRgnData->rdh.nCount >= (DWORD) rectsCount) + { + rectsCount += addRectsCount; + LPRGNDATA pRgnDataNew = (LPRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]); + memcpy(pRgnDataNew, pRgnData, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT)); + delete pRgnData; + pRgnData = pRgnDataNew; + pRects = (LPRECT)(&pRgnData->Buffer); + } + wasfirst = false; + } + + } + + HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData); + delete pRgnData; + return hRgn; +} + +static int hex2dec(char hex) +{ + if ((hex >= '0') && (hex <= '9')) + return hex - '0'; + if ((hex >= 'a') && (hex <= 'f')) + return hex - 'a' + 0xa; + if ((hex >= 'A') && (hex <= 'F')) + return hex - 'A' + 0xa; + return 0; +} + +bool MyBitmap::loadFromFile_pixel(const char *fn, const char *fnAlpha) +{ + allocate(1,1); + int r, g, b, a=255; + const char *p = fn + lstrlenA("pixel:"); + r = (hex2dec(p[0]) << 4) + hex2dec(p[1]); + g = (hex2dec(p[2]) << 4) + hex2dec(p[3]); + b = (hex2dec(p[4]) << 4) + hex2dec(p[5]); + *bits = rgba(r,g,b,a); + return true; +} + +bool MyBitmap::loadFromFile_gradient(const char *fn, const char *fnAlpha) +{ + const char *p = fn + lstrlenA("gradient:"); + + if (*p == 'h') allocate(256,1); + else allocate(1,256); + + int r, g, b, a=255; + + p += 2; + r = (hex2dec(p[0]) << 4) + hex2dec(p[1]); + g = (hex2dec(p[2]) << 4) + hex2dec(p[3]); + b = (hex2dec(p[4]) << 4) + hex2dec(p[5]); + COLOR32 from = rgba(r,g,b,a); + + p += 7; + r = (hex2dec(p[0]) << 4) + hex2dec(p[1]); + g = (hex2dec(p[2]) << 4) + hex2dec(p[3]); + b = (hex2dec(p[4]) << 4) + hex2dec(p[5]); + COLOR32 to = rgba(r,g,b,a); + + for (int i = 0; i < 256; ++i) + { + bits[i] = rgba( + ((255-i) * getr(from) + i * getr(to)) / 255, + ((255-i) * getg(from) + i * getg(to)) / 255, + ((255-i) * getb(from) + i * getb(to)) / 255, + 255 + ); + } + + return true; +} + +bool MyBitmap::loadFromFile_png(const char *fn, const char *fnAlpha) +{ + if (ServiceExists(MS_PNG2DIB)) + { + HANDLE hFile, hMap = 0; + BYTE *ppMap = 0; + long cbFileSize = 0; + BITMAPINFOHEADER *pDib; + BYTE *pDibBits; + if ((hFile = CreateFileA(fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) + if ((hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) + if ((ppMap = (BYTE*)MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 )) != NULL) + cbFileSize = GetFileSize(hFile, NULL); + if (cbFileSize) + { + PNG2DIB param; + param.pSource = ppMap; + param.cbSourceSize = cbFileSize; + param.pResult = &pDib; + if (CallService(MS_PNG2DIB, 0, (LPARAM)¶m)) + pDibBits = (BYTE*)(pDib+1); + else + cbFileSize = 0; + } + + if (ppMap) UnmapViewOfFile(ppMap); + if (hMap) CloseHandle(hMap); + if (hFile) CloseHandle(hFile); + + if (!cbFileSize) return false; + + BITMAPINFO *bi=(BITMAPINFO*)pDib; + BYTE *pt=(BYTE*)bi; + pt+=bi->bmiHeader.biSize; + + if (bi->bmiHeader.biBitCount != 32) + { + allocate(abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight)); + HDC hdcTmp = CreateCompatibleDC(getDC()); + HBITMAP hBitmap = CreateDIBitmap(getDC(), pDib, CBM_INIT, pDibBits, bi, DIB_PAL_COLORS); + SelectObject(hdcTmp, hBitmap); + BitBlt(this->getDC(), 0, 0, abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight), hdcTmp, 0, 0, SRCCOPY); + this->makeOpaque(); + DeleteDC(hdcTmp); + DeleteObject(hBitmap); + } else + { + allocate(abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight)); + BYTE *p2=(BYTE *)pt; + for (int y=0; ybmiHeader.biHeight; ++y) + { + BYTE *p1=(BYTE *)bits + (bi->bmiHeader.biHeight-y-1)*bi->bmiHeader.biWidth*4; + for (int x=0; xbmiHeader.biWidth; ++x) + { + p1[0]= p2[0]; + p1[1]= p2[1]; + p1[2]= p2[2]; + p1[3]= p2[3]; + p1 += 4; + p2 += 4; + } + } +// memcpy(bits, pt, bi->bmiHeader.biSizeImage); + premultipleChannels(); + } + + GlobalFree(pDib); + return true; + } else + { +// MSGERROR(TranslateT("You need the png2dib plugin v. 0.1.3.x or later to process PNG images"); + return false; + } +} + +bool MyBitmap::loadFromFile_default(const char *fn, const char *fnAlpha) +{ + SIZE sz; + HBITMAP hBmpLoaded = (HBITMAP)LoadImageA(NULL, fn, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + if (!hBmpLoaded) + return false; + + BITMAP bm; GetObject(hBmpLoaded, sizeof(bm), &bm); + SetBitmapDimensionEx(hBmpLoaded, bm.bmWidth, bm.bmHeight, NULL); + + HDC dcTmp = CreateCompatibleDC(0); + GetBitmapDimensionEx(hBmpLoaded, &sz); + HBITMAP hBmpDcSave = (HBITMAP)SelectObject(dcTmp, hBmpLoaded); + + allocate(sz.cx, sz.cy); + BitBlt(dcBmp, 0, 0, width, height, dcTmp, 0, 0, SRCCOPY); + + DeleteObject(SelectObject(dcTmp, hBmpDcSave)); + DeleteDC(dcTmp); + + MyBitmap alpha; + if (fnAlpha && alpha.loadFromFile(fnAlpha) && + (alpha.getWidth() == width) && + (alpha.getHeight() == height) ) + { + for (int i = 0; i < width*height; i++) + bits[i] = (bits[i] & 0x00ffffff) | ( (alpha.bits[i] & 0x000000ff) << 24 ); + premultipleChannels(); + } else + { + makeOpaque(); + } + return true; +} + +bool MyBitmap::loadFromFile(const char *fn, const char *fnAlpha) +{ + if (bits) free(); + + if (!strncmp(fn, "pixel:", lstrlenA("pixel:"))) + { + return loadFromFile_pixel(fn, fnAlpha); + } else + if (!strncmp(fn, "gradient:", lstrlenA("gradient:"))) + { + return loadFromFile_gradient(fn, fnAlpha); + } else + { + char ext[5]; + memcpy(ext,fn+(strlen(fn)-4),5); + if (!lstrcmpiA(ext,".png")) + { + return loadFromFile_png(fn, fnAlpha); + } else + { + return loadFromFile_default(fn, fnAlpha); + } + } + // unreachable place + return false; +} + +void MyBitmap::allocate(int w, int h) +{ + width = w; + height = h; + + BITMAPINFO bi; + + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = w; + bi.bmiHeader.biHeight = -h; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + + if (dcBmp) + { + DeleteObject(SelectObject(dcBmp, hBmpSave)); + DeleteDC(dcBmp); + } + + hBmp = (HBITMAP)CreateDIBSection(0, &bi, DIB_RGB_COLORS, (void **)&bits, 0, 0); + dcBmp = CreateCompatibleDC(0); + hBmpSave = (HBITMAP)SelectObject(dcBmp, hBmp); + + GdiFlush(); +} + +void MyBitmap::free() +{ + GdiFlush(); + + DeleteObject(SelectObject(dcBmp, hBmpSave)); + DeleteDC(dcBmp); + + dcBmp = 0; + hBmp = 0; + bits = 0; + width = height = 0; +} + +void MyBitmap::premultipleChannels() +{ + GdiFlush(); + + for (int i = 0; i < width*height; i++) + bits[i] = rgba(getr(bits[i])*geta(bits[i])/255, getg(bits[i])*geta(bits[i])/255, getb(bits[i])*geta(bits[i])/255, geta(bits[i])); +} diff --git a/Popup/src/bitmap_funcs.h b/Popup/src/bitmap_funcs.h new file mode 100644 index 0000000..8a66c30 --- /dev/null +++ b/Popup/src/bitmap_funcs.h @@ -0,0 +1,132 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/bitmap_funcs.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __bitmap_funcs_h__ +#define __bitmap_funcs_h__ + +// This should make bitmap manipulations much easier... +class MyBitmap +{ +public: + typedef unsigned long COLOR32; + static inline COLOR32 RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 0xff) + { + return (a << 24) | (r << 16) | (g << 8) | b; + }; + +private: + HBITMAP hBmpSave, hBmp; + HDC dcBmp; + COLOR32 *bits; + COLOR32 *bitsSave; + int width, height; + + void free(); + + bool loadFromFile_pixel(const char *fn, const char *fnAlpha = 0); + bool loadFromFile_gradient(const char *fn, const char *fnAlpha = 0); + bool loadFromFile_png(const char *fn, const char *fnAlpha = 0); + bool loadFromFile_default(const char *fn, const char *fnAlpha = 0); + void premultipleChannels(); + +public: + MyBitmap(); + MyBitmap(int w, int h); + MyBitmap(const char *fn, const char *fnAlpha = 0); + ~MyBitmap(); + void allocate(int w, int h); + + bool loadFromFile(const char *fn, const char *fnAlpha = 0); + + int getWidth() { return width; } + int getHeight() { return height; } + + HDC getDC() { return dcBmp; } + HBITMAP getBitmap() { return hBmp; } + + void makeOpaque(); + void makeOpaqueRect(int x1, int y1, int x2, int y2); + void makeOpaqueRect(RECT rc) { makeOpaqueRect(rc.left, rc.top, rc.right, rc.bottom); } + + void saveAlpha(int x = 0, int y = 0, int w = 0, int h = 0); + void restoreAlpha(int x = 0, int y = 0, int w = 0, int h = 0); + + void DrawBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h); + void BlendBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h); + + void DrawNoAlpha(MyBitmap *bmp, int x, int y, int w, int h); + + void Blend(MyBitmap *bmp, int x, int y, int w, int h); + void Draw(MyBitmap *bmp, int x, int y, int w, int h); + + void BlendColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color); + void DrawColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color); + + void BlendPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h); + void BlendPartColorized(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h, COLOR32 color); + void DrawPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h); +// void DrawPartNoAlpha(MyBitmap *bmp, int x, int y, int w, int h); +// void DrawPartColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color); + + void DrawIcon(HICON hic, int x, int y, int w = 0, int h = 0); + void Draw_TextA(char *str, int x, int y); + void Draw_TextW(WCHAR *str, int x, int y); + + __forceinline COLOR32 *getBits() { return bits; } + __forceinline COLOR32 *getRow(int row) { return bits + row * width; } + __forceinline COLOR32 *operator[] (int row) { return bits + row * width; } + + static __forceinline COLOR32 rgba(COLOR32 r, COLOR32 g, COLOR32 b, COLOR32 a) + { + return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); + } + static __forceinline COLOR32 getr(COLOR32 c) + { + return (c >> 16) & 0xff; + } + static __forceinline COLOR32 getg(COLOR32 c) + { + return (c >> 8) & 0xff; + } + static __forceinline COLOR32 getb(COLOR32 c) + { + return c & 0xff; + } + static __forceinline COLOR32 geta(COLOR32 c) + { + return (c >> 24) & 0xff; + } + + HRGN buildOpaqueRgn(int level = 64, bool opaque = true); +}; + +#endif // __bitmap_funcs_h__ \ No newline at end of file diff --git a/Popup/src/common.h b/Popup/src/common.h new file mode 100644 index 0000000..d975e0d --- /dev/null +++ b/Popup/src/common.h @@ -0,0 +1,296 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/common.h $ +Revision : $Revision: 1622 $ +Last change on : $Date: 2010-06-23 23:32:21 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef COMMON_H +#define COMMON_H + +void PopUpPreview(); + +#define MAX_POPUPS 48 + +#define DB_READ_SUCCESS 0 +#define DB_READ_FAIL -1 + +//===== Definitions ===== +#define LIGHTEN 24 +#define DARKEN 64 + +inline void GetBmpSize(HBITMAP hbm, SIZE *sz) +{ + GetBitmapDimensionEx(hbm, sz); +} + +inline void DebugMsg(LPTSTR msg){ + if(PopUpOptions.debug){ + MessageBox(NULL, msg, _T("debug"), MB_OK); + } +} + +/* not used +inline void GetDCBmpSize(HDC hdc, SIZE *sz) +{ + BITMAP bmp; + GetObject(GetCurrentObject(hdc, OBJ_BITMAP), sizeof(bmp), &bmp); + sz->cx = bmp.bmWidth; + sz->cy = bmp.bmHeight; +} + +inline HBITMAP myLoadBitmap(LPCTSTR fn) +{ + HBITMAP res = (HBITMAP)LoadImage(NULL, fn, IMAGE_BITMAP, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_LOADFROMFILE); + + BITMAPFILEHEADER bfh; + BITMAPINFOHEADER bih; + FILE *f = _tfopen (fn, _T("rb")); + fread(&bfh, sizeof(bfh), 1, f); + fread(&bih, sizeof(bih), 1, f); + fclose(f); + SetBitmapDimensionEx(res, bih.biWidth, bih.biHeight, NULL); + + return res; +} +*/ + +//===== Percentile to Byte and viceversa ===== +inline int Byte2Percentile(int vByte) { return (vByte*100)/255; } +inline int Percentile2Byte(int vPerc) { return (vPerc*255)/100; } + +//===== Strings & MirandaDB ================== +inline char *DBGetContactSettingString(HANDLE hContact, const char *ModuleName, const char *SettingName, const char *Default) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING dbcgs; + dbcgs.szModule = ModuleName; + dbcgs.pValue = &dbv; + dbcgs.szSetting = SettingName; + + CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); + + char *result = 0; + if (dbv.type == DBVT_ASCIIZ) + { + result = mir_strdup(dbv.pszVal); + } + else if (Default) + { + result = mir_strdup(Default); + } + + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + return result; +} + +inline INT_PTR DBGetContactSettingStringX(HANDLE hContact, const char *ModuleName, const char *SettingName, const char *Default, const int retType) +{ + INT_PTR ret = NULL; + BOOL result = 0; + DBVARIANT dbv; + DBCONTACTGETSETTING dbcgs; + dbcgs.szModule = ModuleName; + dbcgs.szSetting = SettingName; + dbcgs.pValue = &dbv; + dbv.type=(BYTE)retType; + + result = CallService(MS_DB_CONTACT_GETSETTING_STR, (WPARAM)hContact, (LPARAM)&dbcgs); + + switch(retType) { + case DBVT_ASCIIZ: + ret = (INT_PTR)mir_strdup(result ? Default : dbv.pszVal); + break; + case DBVT_WCHAR: + if(!result) { + ret = (INT_PTR)mir_wstrdup(dbv.pwszVal); + } + else { + ret = (INT_PTR)mir_a2u(Default); + } + break; + default: + break; + } + if(!result) + CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); + return ret; +} + +/* not used +#if !defined(_UNICODE) +inline void SetWindowTextTraslated(HWND hwnd, const char *text) +{ + if (!(hwnd && text)) return; + if (g_popup.isOsUnicode && IsWindowUnicode(hwnd) && MySetWindowTextW) + { + UINT codepage = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); + int size = MultiByteToWideChar(codepage, 0, text, lstrlenA(text), 0, 0); + WCHAR *wtext = new WCHAR[size+1]; + MultiByteToWideChar(codepage, 0, text, lstrlenA(text), wtext, size+1); wtext[size]=0; + MySetWindowTextW(hwnd, TranslateW(wtext)); + delete [] wtext; + } else + { + SetWindowTextA(hwnd, Translate(text)); + } +} +#endif +*/ +/*/dedrecatet (tricky thing to minimize memory fragmentation) +inline wchar_t* a2u( char* src ) +{ + int codepage = CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 ); + + int cbLen = MultiByteToWideChar( codepage, 0, src, -1, NULL, 0 ); + wchar_t* result = ( wchar_t* )mir_alloc( sizeof( wchar_t )*(cbLen+1)); + if ( result == NULL ) + return NULL; + + MultiByteToWideChar( codepage, 0, src, -1, result, cbLen ); + result[ cbLen ] = 0; + return result; +} + +#define nb_a2u_init() \ + int nb_a2u_codepage = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); \ + int nb_a2u_len = 0; \ + +#define nb_a2u(dst, src) \ + bool dst##_free = false; \ + WCHAR *dst = NULL; \ + nb_a2u_len = MultiByteToWideChar(nb_a2u_codepage, 0, src, -1, NULL, 0); \ + __try \ + { \ + dst = (WCHAR *)_alloca(sizeof(WCHAR)*(nb_a2u_len+1)); \ + } \ + __except( EXCEPTION_EXECUTE_HANDLER ) \ + { \ + dst = (WCHAR *)mir_alloc(sizeof(WCHAR)*(nb_a2u_len+1)); \ + dst##_free = true; \ + } \ + MultiByteToWideChar(nb_a2u_codepage, 0, src, -1, dst, nb_a2u_len); \ + dst[nb_a2u_len] = 0; + +#define nb_a2u_free(dst) \ + if (dst##_free) \ + mir_free(dst); +*/ + +inline void AddTooltipTranslated(HWND hwndToolTip, HWND hwnd, int id, RECT rc, char *text) +{ +#if defined(_UNICODE) + TOOLINFO ti = {0}; + ti.cbSize = sizeof(TOOLINFO); + + ti.hwnd = hwnd; + ti.uId = id; + SendMessage(hwndToolTip, TTM_DELTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); + + LPWSTR wtext = mir_a2u(text); + + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = hwnd; + ti.uId = id; + ti.hinst = hInst; + ti.lpszText = TranslateW(wtext); + ti.rect = rc; + SendMessage(hwndToolTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); + + mir_free(wtext); + +#else + if (g_popup.isOsUnicode && MySendMessageW) + { + TOOLINFOW ti = {0}; + ti.cbSize = sizeof(TOOLINFO); + + ti.hwnd = hwnd; + ti.uId = id; + MySendMessageW(hwndToolTip, TTM_DELTOOLW, 0, (LPARAM) (LPTOOLINFOW) &ti); + + LPWSTR wtext = mir_a2u(text); + + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = hwnd; + ti.uId = id; + ti.hinst = hInst; + ti.lpszText = TranslateW(wtext); + ti.rect = rc; + MySendMessageW(hwndToolTip, TTM_ADDTOOLW, 0, (LPARAM) (LPTOOLINFOW) &ti); + + mir_free(wtext); + } else + { + TOOLINFOA ti = {0}; + ti.cbSize = sizeof(TOOLINFO); + + ti.hwnd = hwnd; + ti.uId = id; + SendMessage(hwndToolTip, TTM_DELTOOLA, 0, (LPARAM) (LPTOOLINFOA) &ti); + + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = hwnd; + ti.uId = id; + ti.hinst = hInst; + ti.lpszText = Translate(text); + ti.rect = rc; + SendMessage(hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM) (LPTOOLINFOA) &ti); + } +#endif +} + +/* not used +inline UINT getCodepageFromCharset(BYTE charset) +{ + switch (charset) + { + case ANSI_CHARSET: return 1252; + case BALTIC_CHARSET: return 1257; + case CHINESEBIG5_CHARSET: return 950; + case DEFAULT_CHARSET: return CP_ACP; + case EASTEUROPE_CHARSET: return 1250; + case GB2312_CHARSET: return 936; + case GREEK_CHARSET: return 1253; + case HANGUL_CHARSET: return 949; + case MAC_CHARSET: return CP_MACCP; + case OEM_CHARSET: return CP_OEMCP; + case RUSSIAN_CHARSET: return 1251; + case SHIFTJIS_CHARSET: return 932; +// case SYMBOL_CHARSET: return ; + case TURKISH_CHARSET: return 1254; + case VIETNAMESE_CHARSET: return 1258; + case JOHAB_CHARSET: return 1361; + case ARABIC_CHARSET: return 1256; + case HEBREW_CHARSET: return 1255; + default: return CP_ACP; + } +} +*/ + +#endif //COMMON_H diff --git a/Popup/src/config.cpp b/Popup/src/config.cpp new file mode 100644 index 0000000..5831de5 --- /dev/null +++ b/Popup/src/config.cpp @@ -0,0 +1,210 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/config.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +//===== General Plugin ===== +HINSTANCE hInst; +HANDLE hMainThread; +//MNOTIFYLINK *notifyLink; //deprecatet +PLUGINLINK *pluginLink; +HANDLE hSemaphore; +BOOL closing = FALSE; +MM_INTERFACE mmi; +LIST_INTERFACE li; +UTF8_INTERFACE utfi; +MTEXT_INTERFACE MText = {0}; +HANDLE folderId; +BOOL gbPopupLoaded = FALSE; +BOOL gbHppInstalled = FALSE; +LPCSTR gszMetaProto = ""; + +//===== Brushes, Colours and Fonts ===== +HBITMAP hbmNoAvatar; + +//===== Options ===== +POPUPOPTIONS PopUpOptions; +//SKINELEMENT *skin; +//SKINELEMENT *w_skin; +//SKINELEMENT *n_skin; + + +//===== Plugin information ===== + +PLUGININFOEX pluginInfoEx = +{ + sizeof(PLUGININFOEX), + POPUP_DISPLAYNAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM), + POPUP_DESCRIPTION, + POPUP_AUTHOR, + POPUP_EMAIL, + POPUP_COPYRIGHT, + POPUP_WEBPAGE, + 0, + 0, + POPUP_UUID +}; + +// MLU layer for ansi release +#if !defined(_UNICODE) +BOOL (WINAPI *MySetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD); +BOOL (WINAPI *MyAnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags); +BOOL (WINAPI *MyGetMonitorInfo)(HMONITOR hMonitor, LPMONITORINFO lpmi); +BOOL (WINAPI *MyUpdateLayeredWindow) + (HWND hwnd, HDC hdcDST, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, + COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags); +HMONITOR (WINAPI *MyMonitorFromWindow)(HWND hWnd, DWORD dwFlags); +BOOL (WINAPI *MyTransparentBlt)(HDC, int, int, int, int, HDC, int, int, int, int, UINT); +BOOL (WINAPI *MyAlphaBlend)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION); + +// gdi32.dll +BOOL (WINAPI *MyGetTextExtentPoint32W)(HDC, LPCWSTR, int, LPSIZE); + +//user32.dll +int (WINAPI *MyDrawTextW)(HDC, LPCWSTR, int, LPRECT, UINT); +int (WINAPI *MyDrawTextExW)(HDC, LPCWSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); +BOOL (WINAPI *MySetWindowTextW)(HWND, LPCWSTR); +LRESULT (WINAPI *MySendMessageW)(HWND, UINT, WPARAM, LPARAM); +LRESULT (WINAPI *MyCallWindowProcW)(WNDPROC, HWND, UINT, WPARAM, LPARAM); +HWND (WINAPI *MyCreateWindowExW)(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); + +#endif + +HRESULT (WINAPI *MyDwmEnableBlurBehindWindow)(HWND hWnd, DWM_BLURBEHIND *pBlurBehind); + +//====== Common Vars ======================== + +// common funcs +void LoadOptions() { + ZeroMemory(&PopUpOptions, sizeof(PopUpOptions)); + #if defined(_DEBUG) + PopUpOptions.debug = DBGetContactSettingByte(NULL, MODULNAME, "debug", FALSE); + #endif + + //Load PopUp Options + if(!OptionLoaded){ + LoadOption_General(); + LoadOption_Skins(); + LoadOption_Actions(); + LoadOption_AdvOpts(); + } + Check_ReorderPopUps(); + OptionLoaded = true; + return; +} + +void PopUpPreview() +{ + TCHAR *lptzTitle1Eng = TranslateT("The Jabberwocky"); + TCHAR *lptzText1Eng = TranslateTS( + _T("`Twas brillig, and the slithy toves\r\n") + _T("Did gyre and gimble in the wabe:\r\n") + _T("All mimsy were the borogoves,\r\n") + _T("And the mome raths outgrabe.\r\n") + _T("\t[b][i]Lewis Carroll, 1855[/i][/b]") + ); + + TCHAR *lptzTitle2 = TranslateT("Test preview for the popup plugin settings. This is supposed to be long enough not to fit in one line..."); + TCHAR *lptzText2 = TranslateTS( + _T("This is a special test preview for the popup ") + _T("plugin settings. The text and title are quite ") + _T("long so you can tweak your skin and plugin ") + _T("settings to best fit your needs :)") + ); + + POPUPDATA2 ppd = {0}; + + ZeroMemory(&ppd, sizeof(ppd)); + ppd.cbSize = sizeof(ppd); + ppd.flags = PU2_TCHAR; + +#if defined(_DEBUG) + // test per-contact popups + for (HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); hContact; + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + if (DBGetContactSettingDword(hContact, "ICQ", "UIN", 0) == 256771455) + { + ppd.lchContact = hContact; + break; + } + } +#endif + ppd.lptzTitle = lptzTitle1Eng; + ppd.lptzText = lptzText1Eng; + ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + CallService(MS_POPUP_ADDPOPUP2, (WPARAM)&ppd, APF_NO_HISTORY); + if (PopUpOptions.UseAnimations || PopUpOptions.UseEffect) Sleep((ANIM_TIME*2)/3); //Pause + + ZeroMemory(&ppd, sizeof(ppd)); + ppd.cbSize = sizeof(ppd); + ppd.flags = PU2_TCHAR; + ppd.lptzTitle = lptzTitle2; + ppd.lptzText = lptzText2; + ppd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + ppd.hbmAvatar = hbmNoAvatar; +#if defined(_DEBUG) +//remove testactions + POPUPACTION actions[3]; + actions[0].cbSize = sizeof(POPUPACTION); + actions[0].flags = PAF_ENABLED; + lstrcpyA(actions[0].lpzTitle, "Popup Plus/Test action"); + actions[0].lchIcon = IcoLib_GetIcon(ICO_POPUP_ON,0); + actions[0].wParam = actions[0].lParam = -1; + + actions[1].cbSize = sizeof(POPUPACTION); + actions[1].flags = PAF_ENABLED; + lstrcpyA(actions[1].lpzTitle, "Popup Plus/Second test action"); + actions[1].lchIcon = IcoLib_GetIcon(ICO_ACT_CLOSE,0); + actions[1].wParam = actions[1].lParam = -1; + + actions[2].cbSize = sizeof(POPUPACTION); + actions[2].flags = PAF_ENABLED; + lstrcpyA(actions[2].lpzTitle, "Popup Plus/One more action"); + actions[2].lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + actions[2].wParam = actions[2].lParam = -1; + + ppd.lpActions = actions; + ppd.actionCount = SIZEOF(actions); +#endif + CallService(MS_POPUP_ADDPOPUP2, (WPARAM)&ppd, APF_NO_HISTORY); + if (PopUpOptions.UseAnimations || PopUpOptions.UseEffect) Sleep((ANIM_TIME*2)/3); //Pause + + PUShowMessageT(TranslateT("This is a notification message"), (DWORD)SM_NOTIFY|0x80000000); + if (PopUpOptions.UseAnimations || PopUpOptions.UseEffect) Sleep((ANIM_TIME*2)/3); //Pause + + PUShowMessageT(TranslateT("This is a warning message"), (DWORD)SM_WARNING|0x80000000); + if (PopUpOptions.UseAnimations || PopUpOptions.UseEffect) Sleep((ANIM_TIME*2)/3); //Pause + + PUShowMessageT(TranslateT("This is an error message"), (DWORD)SM_ERROR|0x80000000); +} \ No newline at end of file diff --git a/Popup/src/config.h b/Popup/src/config.h new file mode 100644 index 0000000..6b293ba --- /dev/null +++ b/Popup/src/config.h @@ -0,0 +1,249 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/config.h $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __config_h__ +#define __config_h__ + +typedef struct tagPOPUPOPTIONS { +//==Page General==== + //Timeout + BYTE InfiniteDelay; + int Seconds; + BYTE LeaveHovered; + //Size&Position + BYTE DynamicResize; + BYTE UseMinimumWidth; + WORD MinimumWidth; + BYTE UseMaximumWidth; + WORD MaximumWidth; + int Position; + int Spreading; + //position Popup + int gapTop; + int gapBottom; + int gapLeft; + int gapRight; + int spacing; + //Miscellaneous + BYTE ReorderPopUps; + BYTE ReorderPopUpsWarning; + //Disable when + BOOL ModuleIsEnabled; + BYTE DisableWhenFullscreen; + //others + BYTE debug; +//==Page Skins==== + LPTSTR SkinPack; + BYTE DisplayTime; + BYTE DropShadow; + BYTE EnableFreeformShadows; + BYTE EnableAeroGlass; + BYTE UseWinColors; + BYTE UseMText; +//==Page Actions==== + DWORD actions; + //Mouse Override + int overrideLeft; + int overrideRight; + int overrideMiddle; +//==Page Advanced==== + //History + BYTE EnableHistory; + WORD HistorySize; + BYTE UseHppHistoryLog; + //Avatars + BYTE avatarBorders; + BYTE avatarPNGBorders; + BYTE avatarRadius; + WORD avatarSize; + BYTE EnableAvatarUpdates; + //Monitor + BYTE Monitor; + //Transparency + BYTE Enable9xTransparency; + BYTE UseTransparency; + BYTE Alpha; + BYTE OpaqueOnHover; + //Effect + BYTE UseAnimations; + BYTE UseEffect; + LPTSTR Effect; + DWORD FadeIn; + DWORD FadeOut; + //Others + WORD MaxPopups; +} POPUPOPTIONS; + +struct GLOBAL{ + bool isOsUnicode; + bool isMirUnicode; + int MirVer; +}; +extern GLOBAL g_popup; + +//===== User wnd class ===== +struct GLOBAL_WND_CLASSES{ + ATOM cPopupWnd2; + ATOM cPopupEditBox; + ATOM cPopupMenuHostWnd; + ATOM cPopupThreadManagerWnd; + ATOM cPopupPreviewBoxWndclass; + ATOM cPopupPlusDlgBox; +}; +extern GLOBAL_WND_CLASSES g_wndClass; + +#define ACT_ENABLE 0x00000001 +#define ACT_LARGE 0x00000002 +#define ACT_TEXT 0x00000004 +#define ACT_RIGHTICONS 0x00000008 +#define ACT_LEFTICONS 0x00000010 +#define ACT_DEF_NOGLOBAL 0x00000020 +#define ACT_DEF_KEEPWND 0x00000040 +#define ACT_DEF_IMONLY 0x00000080 + +#define ACT_DEF_MESSAGE 0x00010000 +#define ACT_DEF_DETAILS 0x00020000 +#define ACT_DEF_MENU 0x00040000 +#define ACT_DEF_ADD 0x00080000 +#define ACT_DEF_DISMISS 0x00100000 +#define ACT_DEF_PIN 0x00200000 +#define ACT_DEF_REPLY 0x00400000 +#define ACT_DEF_COPY 0x00800000 + +void LoadOptions(); + +//===== General Plugin ===== +extern HINSTANCE hInst; +extern HANDLE hMainThread; +//extern MNOTIFYLINK *notifyLink; //deprecatet +extern PLUGINLINK *pluginLink; +extern HANDLE hSemaphore; +extern BOOL closing; +extern HANDLE folderId; +extern UTF8_INTERFACE utfi; + +extern MTEXT_INTERFACE MText; +extern HANDLE htuText; +extern HANDLE htuTitle; + +extern BOOL gbPopupLoaded; +extern BOOL gbHppInstalled; +extern LPCSTR gszMetaProto; + + +//===== Brushes, Colours and Fonts ===== +extern HBITMAP hbmNoAvatar; + +//===== Options ===== +extern POPUPOPTIONS PopUpOptions; +extern bool OptionLoaded; +//extern SKINELEMENT *skin; +//extern SKINELEMENT *w_skin; +//extern SKINELEMENT *n_skin; + +//===== Plugin informations struct ===== +extern PLUGININFOEX pluginInfoEx; + +//===== Transparency & APIs which are not supported by every OS ===== +#ifndef DWLP_MSGRESULT +#define DWLP_MSGRESULT 0 +#endif +#ifndef WS_EX_LAYERED +#define WS_EX_LAYERED 0x00080000 +#endif +#ifndef LWA_COLORKEY +#define LWA_COLORKEY 0x00000001 +#endif +#ifndef LWA_ALPHA +#define LWA_ALPHA 0x00000002 +#endif +#ifndef ULW_OPAQUE +#define ULW_OPAQUE 0x00000004 +#endif +#ifndef AC_SRC_ALPHA +#define AC_SRC_ALPHA 0x01 +#endif +#ifndef INVALID_FILE_ATTRIBUTES +#define INVALID_FILE_ATTRIBUTES (DWORD (-1)) +#endif + +// MLU layer for ansi release +#if !defined(_UNICODE) +//===== DLLs ===== +extern HMODULE hUserDll; +extern HMODULE hMsimgDll; +extern HMODULE hKernelDll; +extern HMODULE hGdiDll; +extern HMODULE hDwmapiDll; + +extern BOOL (WINAPI *MySetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD); +extern BOOL (WINAPI *MyAnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags); +extern BOOL (WINAPI *MyGetMonitorInfo)(HMONITOR hMonitor, LPMONITORINFO lpmi); +extern BOOL (WINAPI *MyUpdateLayeredWindow) + (HWND hwnd, HDC hdcDST, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, + COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags); +extern HMONITOR (WINAPI* MyMonitorFromWindow)(HWND hWnd, DWORD dwFlags); +extern BOOL (WINAPI *MyTransparentBlt)(HDC, int, int, int, int, HDC, int, int, int, int, UINT); +extern BOOL (WINAPI *MyAlphaBlend)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION); + +extern BOOL (WINAPI *MyGetTextExtentPoint32W)(HDC, LPCWSTR, int, LPSIZE); +extern int (WINAPI *MyDrawTextW)(HDC, LPCWSTR, int, LPRECT, UINT); +extern int (WINAPI *MyDrawTextExW)(HDC, LPCWSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); +extern BOOL (WINAPI *MySetWindowTextW)(HWND, LPCWSTR); +extern LRESULT (WINAPI *MySendMessageW)(HWND, UINT, WPARAM, LPARAM); +extern LRESULT (WINAPI *MyCallWindowProcW)(WNDPROC, HWND, UINT, WPARAM, LPARAM); +extern HWND (WINAPI *MyCreateWindowExW)(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); + +#endif + +#define DWM_BB_ENABLE 0x00000001 +#define DWM_BB_BLURREGION 0x00000002 +#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 +struct DWM_BLURBEHIND +{ + DWORD dwFlags; + BOOL fEnable; + HRGN hRgnBlur; + BOOL fTransitionOnMaximized; +}; + +extern HRESULT (WINAPI *MyDwmEnableBlurBehindWindow)(HWND hWnd, DWM_BLURBEHIND *pBlurBehind); + +typedef struct TestStruct{ + int cbSize; +} TESTSIZE; + +// Generic Message Box for Errors +#define MSGERROR(text) MessageBox(NULL, text, _T(MODULNAME_LONG), MB_OK | MB_ICONERROR) +#define MSGINFO (text) MessageBox(NULL, text, _T(MODULNAME_LONG), MB_OK | MB_ICONINFORMATION) + +#endif // __config_h__ diff --git a/Popup/src/def_settings.h b/Popup/src/def_settings.h new file mode 100644 index 0000000..9fa02ff --- /dev/null +++ b/Popup/src/def_settings.h @@ -0,0 +1,156 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + +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. +*/ + +#ifndef __def_settings_h__ +#define __def_settings_h__ + +//===== Styles ===== +enum +{ + STYLE_FC_BEVELED, + STYLE_FC_FLAT, + + //ranges: + STYLE_FC_MIN = STYLE_FC_BEVELED, + STYLE_FC_MAX = STYLE_FC_FLAT +}; + +//===== Sizes ===== +enum +{ + STYLE_SZ_GAP = 4, + STYLE_SZ_TEXTH = 14, + STYLE_SZ_NAMEH = 14, + STYLE_SZ_TIMEW = 35, + STYLE_SZ_TIMEH = 14, + +// STYLE_SZ_CLOCKH = 13, +// STYLE_SZ_CLOCKW = 7, +// STYLE_SZ_CLOCK = 2 + 3 + 4 * STYLE_SZ_CLOCKW + 2, + + //Text and Name are style dependant. + STYLE_SZ_TEXTW_FLAT = 146, + STYLE_SZ_NAMEW_FLAT = 101, + STYLE_SZ_TEXTW_BEVELED = 125, + STYLE_SZ_NAMEW_BEVELED = 80, + + // border size + STYLE_SZ_BORDER_BEVELED = 2, + STYLE_SZ_BORDER_FLAT = 2 +}; + +//===== PopUp Positioning ===== +enum +{ + POS_UPPERLEFT, + POS_LOWERLEFT, + POS_LOWERRIGHT, + POS_UPPERRIGHT, + POS_CENTER, + + //ranges + POS_MINVALUE = POS_UPPERLEFT, + POS_MAXVALUE = POS_CENTER +}; + +//===== Spreading ===== +enum +{ + SPREADING_HORIZONTAL, + SPREADING_VERTICAL, + + SPREADING_MINVALUE = SPREADING_HORIZONTAL, + SPREADING_MAXVALUE = SPREADING_VERTICAL +}; + +//===== PopUp Options flags +enum +{ + SPK_NONE, + SPK_SMILEYADD, + SPK_MSL, + SPK_XEP, + SPK_NCONVERS +}; +enum +{ + TIMER_TIMETOLIVE = 26378, //My Birthday, send me something 8) + TIMER_TESTCHANGE = 60477, //You know who you are. + + ANIM_TIME = 250, + FADE_TIME = (ANIM_TIME), + FADE_STEP = 10, + + MN_MIRANDA = 0x01, + MN_ACTIVE = 0x02, + + UM_SETDLGITEMINT = 5674 +}; + +//Defaults: +enum +{ + SETTING_BACKCOLOUR_DEFAULT = RGB(173,206,247), + SETTING_TEXTCOLOUR_DEFAULT = RGB(0,0,0), + + SETTING_MONITOR_DEFAULT = MN_MIRANDA, + SETTING_USEMINIMUMWIDTH_DEFAULT = 1, + SETTING_USEMAXIMUMWIDTH_DEFAULT = 1, + SETTING_USINGTHREADS_DEFAULT = 1, + SETTING_MODULEISENABLED_DEFAULT = 1, + SETTING_MULTILINE_DEFAULT = 1, + SETTING_FADEINTIME_DEFAULT = (ANIM_TIME), + SETTING_FADEOUTTIME_DEFAULT = (ANIM_TIME), + SETTING_FADEOUTTIME_MIN = 0, + SETTING_FADEINTIME_MIN = 0, + SETTING_FADEOUTTIME_MAX = 10000, + SETTING_FADEINTIME_MAX = 10000, + + SETTING_LIFETIME_MIN = 1, + SETTING_LIFETIME_MAX = 60, + SETTING_LIFETIME_DEFAULT = 4, + SETTING_LIFETIME_INFINITE = -1, + + SETTING_ENLARGEMENT_MIN = 100, + SETTING_ENLARGEMENT_MAX = 200, + SETTING_ENLARGEMENT_DEFAULT = 120, + + SETTING_HISTORYSIZE_MAX = 100, + SETTING_HISTORYSIZE_DEFAULT = 20, + + SETTING_AVTSIZE_MIN = 16, + SETTING_AVTSIZE_MAX = 100, + SETTING_AVTSIZE_DEFAULT = 32, + + SETTING_MINIMUMWIDTH_MIN = 80, + SETTING_MINIMUMWIDTH_MAX = 160, + SETTING_MINIMUMWIDTH_DEFAULT= 110, + + SETTING_MAXIMUMWIDTH_MIN = 160, +// SETTING_MAXIMUMWIDTH_MAX = 640, + SETTING_MAXIMUMWIDTH_DEFAULT= 310, + + SETTING_SMILEPACKTYPE_DEFAULT = SPK_NONE +}; + +extern WORD SETTING_MAXIMUMWIDTH_MAX; + +#endif diff --git a/Popup/src/defs.h b/Popup/src/defs.h new file mode 100644 index 0000000..3ff8d09 --- /dev/null +++ b/Popup/src/defs.h @@ -0,0 +1,52 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/defs.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __defs_h__ +#define __defs_h__ + +#ifdef __cplusplus + // in C++ files we should define everything inside extren "C" + #define EXTERNC extern "C" + #define BEGIN_EXTERNC extern "C" { + #define END_EXTERNC }; + + // in C++ all exported function must be extern "C" + #define MIRAPI extern "C" __declspec(dllexport) +#else + #define EXTERNC + #define BEGIN_EXTERNC + #define END_EXTERNC + + #define MIRAPI __declspec(dllexport) +#endif + +#endif \ No newline at end of file diff --git a/Popup/src/effects.cpp b/Popup/src/effects.cpp new file mode 100644 index 0000000..64ac46b --- /dev/null +++ b/Popup/src/effects.cpp @@ -0,0 +1,94 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/effects.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +class MyTestEffect; +HANDLE hSquareFad; + +class MyTestEffect: public IPopupPlusEffect +{ +protected: + int w, h; + int alpha0, alpha1; + int frameCount; + int frame; + + int stage; + int alpha; + +public: + virtual void beginEffect(int w, int h, int alpha0, int alpha1, int frameCount) + { + this->w = w; + this->h = h; + this->alpha0 = alpha0; + this->alpha1 = alpha1; + this->frameCount = frameCount; + } + virtual void beginFrame(int frame) + { + this->frame = frame; + stage = (frame*2 > frameCount) ? 1 : 0; + if (stage == 0) + { + alpha = alpha0 + (alpha1 - alpha0) * frame * 2 / frameCount; + } else + { + alpha = alpha0 + (alpha1 - alpha0) * (frame * 2 - frameCount) / frameCount; + } + } + virtual int getPixelAlpha(int x, int y) + { + if (stage == 0) + { + if ((x/16+y/16) % 2) return alpha0; + return alpha; + } else + { + if ((x/16+y/16) % 2) return alpha; + return alpha1; + } + } + virtual void endFrame() {} + virtual void endEffect() {} + virtual void destroy() { delete this; } +}; + +//template static int svcCreateEffect(WPARAM, LPARAM) { return (int)(new T); } +static INT_PTR svcCreateEffect_MyTestEffect(WPARAM, LPARAM) { return (INT_PTR)(new MyTestEffect); } + +void PopupEfectsInitialize() +{ + hSquareFad = CreateServiceFunction(MS_POPUP_CREATEVFX "Square fading", svcCreateEffect_MyTestEffect); + CallService(MS_POPUP_REGISTERVFX, 0, (LPARAM)"Square fading"); +} diff --git a/Popup/src/effects.h b/Popup/src/effects.h new file mode 100644 index 0000000..6196719 --- /dev/null +++ b/Popup/src/effects.h @@ -0,0 +1,38 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/effects.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __effects_h__ +#define __effects_h__ + +void PopupEfectsInitialize(); + +#endif // __effects_h__ diff --git a/Popup/src/font.cpp b/Popup/src/font.cpp new file mode 100644 index 0000000..d9502ea --- /dev/null +++ b/Popup/src/font.cpp @@ -0,0 +1,154 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/font.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +PopupFonts fonts = {0}; + +void InitFonts() { + // Fonts + FontIDT fid = {0}; + fid.cbSize = sizeof(FontIDT); + lstrcpy(fid.group, _T(PU_FNT_AND_COLOR)); + strcpy(fid.dbSettingsGroup, PU_FNT_AND_COLOR_DB); + fid.flags = FIDF_DEFAULTVALID; + fid.deffontsettings.charset = DEFAULT_CHARSET; + fid.deffontsettings.size = -11; + lstrcpy(fid.backgroundGroup,_T(PU_FNT_AND_COLOR)); + lstrcpy(fid.backgroundName,_T(PU_COL_BACK_NAME)); + lstrcpy(fid.deffontsettings.szFace, _T("Tahoma")); + + lstrcpy(fid.name, _T(PU_FNT_NAME_TITLE)); + mir_snprintf(fid.prefix, sizeof(fid.prefix), PU_FNT_PREFIX, PU_FNT_NAME_TITLE); + fid.deffontsettings.style = DBFONTF_BOLD; + fid.deffontsettings.colour = RGB(0,0,0); + FontRegisterT(&fid); + + lstrcpy(fid.name, _T(PU_FNT_NAME_CLOCK)); + mir_snprintf(fid.prefix, sizeof(fid.prefix), PU_FNT_PREFIX, PU_FNT_NAME_CLOCK); + //fid.deffontsettings.style = DBFONTF_BOLD; + //fid.deffontsettings.colour = RGB(0,0,0); + FontRegisterT(&fid); + + lstrcpy(fid.name, _T(PU_FNT_NAME_TEXT)); + mir_snprintf(fid.prefix, sizeof(fid.prefix), PU_FNT_PREFIX, PU_FNT_NAME_TEXT); + fid.deffontsettings.style = 0; + //fid.deffontsettings.colour = RGB(0,0,0); + FontRegisterT(&fid); + + lstrcpy(fid.name, _T("Action")); + mir_snprintf(fid.prefix, sizeof(fid.prefix), PU_FNT_PREFIX, "Action"); + //fid.deffontsettings.style = 0; + fid.deffontsettings.colour = RGB(0,0,255); + FontRegisterT(&fid); + + lstrcpy(fid.name, _T("Hovered Action")); + mir_snprintf(fid.prefix, sizeof(fid.prefix), PU_FNT_PREFIX, "Hovered Action"); + fid.deffontsettings.style = DBFONTF_UNDERLINE; + //fid.deffontsettings.colour = RGB(0,0,255); + FontRegisterT(&fid); + + ColourIDT cid = {0}; + cid.cbSize = sizeof(ColourIDT); + lstrcpy(cid.group, _T(PU_FNT_AND_COLOR)); + strcpy(cid.dbSettingsGroup, PU_FNT_AND_COLOR_DB); + + lstrcpy(cid.name, _T(PU_COL_BACK_NAME)); + strcpy(cid.setting, PU_COL_BACK_SETTING); + cid.defcolour = SETTING_BACKCOLOUR_DEFAULT; + CallService(MS_COLOUR_REGISTERT, (WPARAM)&cid, 0); + + lstrcpy(cid.name, _T(PU_COL_AVAT_NAME)); + strcpy(cid.setting, PU_COL_AVAT_SETTING); + cid.defcolour = SETTING_TEXTCOLOUR_DEFAULT; + CallService(MS_COLOUR_REGISTERT, (WPARAM)&cid, 0); + + ReloadFonts(); +} + + +void ReloadFonts() +{ + if (fonts.title) DeleteObject(fonts.title); + if (fonts.clock) DeleteObject(fonts.clock); + if (fonts.text) DeleteObject(fonts.text); + if (fonts.action) DeleteObject(fonts.action); + if (fonts.actionHover) DeleteObject(fonts.actionHover); + + LOGFONT lf = {0}; + FontIDT fid = {0}; + fid.cbSize = sizeof(FontIDT); + lstrcpy(fid.group, _T(PU_FNT_AND_COLOR)); + + lstrcpy(fid.name, _T(PU_FNT_NAME_TITLE)); + fonts.clTitle = (COLORREF)CallService(MS_FONT_GETT, (WPARAM)&fid, (LPARAM)&lf); + fonts.title = CreateFontIndirect(&lf); + + lstrcpy(fid.name, _T(PU_FNT_NAME_CLOCK)); + fonts.clClock = (COLORREF)CallService(MS_FONT_GETT, (WPARAM)&fid, (LPARAM)&lf); + fonts.clock = CreateFontIndirect(&lf); + + lstrcpy(fid.name, _T(PU_FNT_NAME_TEXT)); + fonts.clText = (COLORREF)CallService(MS_FONT_GETT, (WPARAM)&fid, (LPARAM)&lf); + fonts.text = CreateFontIndirect(&lf); + + lstrcpy(fid.name, _T("Action")); + fonts.clAction = (COLORREF)CallService(MS_FONT_GETT, (WPARAM)&fid, (LPARAM)&lf); + fonts.action = CreateFontIndirect(&lf); + + lstrcpy(fid.name, _T("Hovered Action")); + fonts.clActionHover = (COLORREF)CallService(MS_FONT_GETT, (WPARAM)&fid, (LPARAM)&lf); + fonts.actionHover = CreateFontIndirect(&lf); + + ColourIDT cid = {0}; + cid.cbSize = sizeof(ColourIDT); + lstrcpy(cid.group, _T(PU_FNT_AND_COLOR)); + lstrcpy(cid.name, _T(PU_COL_BACK_NAME)); + fonts.clBack = (COLORREF)CallService(MS_COLOUR_GETT, (WPARAM)&cid, (LPARAM)&lf); + + lstrcpy(cid.group, _T(PU_FNT_AND_COLOR)); + lstrcpy(cid.name, _T(PU_COL_AVAT_NAME)); + fonts.clAvatarBorder = (COLORREF)CallService(MS_COLOUR_GETT, (WPARAM)&cid, (LPARAM)&lf); + + //update class popupps(only temp at this point, must rework) + char setting[256]; + for(int i = 0; i < gTreeData.getCount(); i++) { + if(gTreeData[i]->typ == 2) { + mir_snprintf(setting, 256, "%s/TextCol", gTreeData[i]->pupClass.pszName); + gTreeData[i]->colorText = gTreeData[i]->pupClass.colorText = + (COLORREF)DBGetContactSettingDword(0, PU_MODULCLASS, setting, (DWORD)fonts.clText); + mir_snprintf(setting, 256, "%s/BgCol", gTreeData[i]->pupClass.pszName); + gTreeData[i]->colorBack = gTreeData[i]->pupClass.colorBack = + (COLORREF)DBGetContactSettingDword(0, PU_MODULCLASS, setting, (DWORD)fonts.clBack/*pc->colorBack*/); + } + } +} diff --git a/Popup/src/font.h b/Popup/src/font.h new file mode 100644 index 0000000..db7b5d7 --- /dev/null +++ b/Popup/src/font.h @@ -0,0 +1,81 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/font.h $ +Revision : $Revision: 1623 $ +Last change on : $Date: 2010-06-24 18:47:07 +0300 (Чт, 24 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __font_h__ +#define __font_h__ + +//basic constants for all popup plugins +#define PU_FNT_AND_COLOR "Popups" //common main group for customice\font&color +#define PU_FNT_AND_COLOR_DB PU_COMMONMODUL //use eg strcpy(fid.dbSettingsGroup, PU_FNT_GROUP_DB); + +#define PU_FNT_PREFIX "fnt%s" //use eg mir_snprintf(fid.prefix, sizeof(fid.prefix), PU_FNT_PREFIX, PU_FNT_NAME_....); +#define PU_FNT_NAME_TITLE "Title" //use eg lstrcpy(fid.name, _T(FNT_NAME_....)) for FontIDT +#define PU_FNT_NAME_CLOCK "Clock" +#define PU_FNT_NAME_TEXT "Text" + +#define PU_COL_BACK_NAME "Background" +#define PU_COL_BACK_SETTING "ColourBg" +#define PU_COL_BORD_NAME "Border" +#define PU_COL_BORD_SETTING "ColourBorder" +#define PU_COL_SIDE_NAME "Sidebar" +#define PU_COL_SIDE_SETTING "ColourSidebar" +#define PU_COL_LINE_NAME "Title underline" +#define PU_COL_LINE_SETTING "ColourUnderline" +#define PU_COL_AVAT_NAME "Avatar Border" +#define PU_COL_AVAT_SETTING "ColourAvatarBorder" + +struct PopupFonts +{ + HFONT title; + HFONT text; + HFONT clock; + HFONT action; + HFONT actionHover; + + COLORREF clTitle; + COLORREF clText; + COLORREF clClock; + COLORREF clBack; + COLORREF clAction; + COLORREF clActionHover; + COLORREF clAvatarBorder; + +}; + +extern PopupFonts fonts; + +void InitFonts(); + +void ReloadFonts(); + + +#endif // __font_h__ diff --git a/Popup/src/formula.cpp b/Popup/src/formula.cpp new file mode 100644 index 0000000..37002c9 --- /dev/null +++ b/Popup/src/formula.cpp @@ -0,0 +1,177 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/formula.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +static inline bool myisspace(char ch) +{ + return (ch >= 0) && (ch <= 32); +} + +int Formula::eval_neq(char *&s, Args *args, bool *vars) const +{ + int left = eval_sum(s, args, vars); + while (*s) + { + if (myisspace(*s)) + { + ++s; + } else + if (*s == '<') + { + // this is needed due to side effects caused by min() macro... + int tmp = eval_sum(++s, args, vars); + left = min(left, tmp); + } else + if (*s == '>') + { + // this is needed due to side effects caused by max() macro... + int tmp = eval_sum(++s, args, vars); + left = max(left, tmp); + } else + { + break; + } + } + return left; +} + +int Formula::eval_sum(char *&s, Args *args, bool *vars) const +{ + int left = eval_mul(s, args, vars); + while (*s) + { + if (myisspace(*s)) + { + ++s; + } else + if (*s == '+') + { + left += eval_mul(++s, args, vars); + } else + if (*s == '-') + { + left -= eval_mul(++s, args, vars); + } else + { + break; + } + } + return left; +} + +int Formula::eval_mul(char *&s, Args *args, bool *vars) const +{ + int left = eval_atom(s, args, vars); + while (*s) + { + if (myisspace(*s)) + { + ++s; + } else + if(*s == '*') + { + left *= eval_atom(++s, args, vars); + } else + if(*s == '/') + { + if (int right = eval_atom(++s, args, vars)) + left /= right; + } else + if(*s == '%') + { + if (int right = eval_atom(++s, args, vars)) + left %= right; + } else + { + break; + } + } + return left; +} + +int Formula::eval_atom(char *&s, Args *args, bool *vars) const +{ + while (*s) + { + if (myisspace(*s)) + { + ++s; + } else + if (*s == '(') + { + int res = eval_neq(++s, args, vars); + if (*s == ')') + ++s; + return res; + } else + if ((*s == '+') || (*s == '-')) + { + int sign = 1; + if (*s == '-') + sign = -1; + return sign * eval_neq(++s, args, vars); + } else + if (*s == '!') + { + return !eval_neq(++s, args, vars); + } else + if ((*s >= '0') && (*s <= '9')) + { + int res = 0; + while ((*s >= '0') && (*s <= '9')) + res = res * 10 + *s++ - '0'; + return res; + } else + { + if (!args) + return 0; + char buf[1024]; + char *bufptr = buf; + while (((*s >= '0') && (*s <= '9')) || ((*s >= 'a') && (*s <= 'z')) || ((*s >= 'A') && (*s <= 'A')) || (*s == '_') || (*s == '.')) + *bufptr++ = *s++; + *bufptr = 0; + int res = args->get(buf); + if (vars) *vars = true; + return res; + } + } + return 0; +} + +int Formula::eval(Args *args, bool *vars) const +{ + if (vars) *vars = false; + char *s = m_str; + int res = eval_neq(s, args, vars); + return res; +} diff --git a/Popup/src/formula.h b/Popup/src/formula.h new file mode 100644 index 0000000..b0239c5 --- /dev/null +++ b/Popup/src/formula.h @@ -0,0 +1,98 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/formula.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __formula_h__ +#define __formula_h__ + +class Formula +{ +public: + class Args + { + private: + struct Item + { + char *name; + int value; + Item *next; + + Item(char *aName, int aValue, Item *aNext): value(aValue), next(aNext) { name = aName ? mir_strdup(aName) : 0; } + ~Item() { if (name) mir_free(name); } + }; + Item *items; + public: + Args():items(0){} + ~Args(){clear();} + void add(char *name, int value) + { + for (Item *p = items; p; p = p->next) + if (!lstrcmpA(p->name,name)) + { + p->value = value; + return; + } + items = new Item(name, value, items); + } + int get(char *name) + { + for (Item *p = items; p; p = p->next) + if (!lstrcmpA(p->name,name)) + return p->value; + return 0; + } + void clear() + { + while (items) + { + Item *p = items->next; + delete items; + items = p; + } + } + }; + +private: + char *m_str; + int eval_neq (char *&s, Args *args, bool *vars) const; + int eval_sum (char *&s, Args *args, bool *vars) const; + int eval_mul (char *&s, Args *args, bool *vars) const; + int eval_atom(char *&s, Args *args, bool *vars) const; + +public: + Formula():m_str(mir_strdup("")){} + Formula(char *s):m_str(mir_strdup(s)){} + ~Formula() {mir_free(m_str);} + void set(char *s){mir_free(m_str);m_str=mir_strdup(s);} + int eval(Args *args, bool *vars = 0) const; +}; + +#endif // __formula_h__ \ No newline at end of file diff --git a/Popup/src/headers.cpp b/Popup/src/headers.cpp new file mode 100644 index 0000000..abf3bad --- /dev/null +++ b/Popup/src/headers.cpp @@ -0,0 +1,34 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/headers.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + diff --git a/Popup/src/headers.h b/Popup/src/headers.h new file mode 100644 index 0000000..2174245 --- /dev/null +++ b/Popup/src/headers.h @@ -0,0 +1,190 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. +*/ + +/* +=============================================================================== + PopUp plugin + +This plugin notifies you when a contact changes his/hers status with a PopUp. +You can customize its look (style of popup, font, text...) and behaviour (the +position in the screen, the time to live, the action on a mouse click). + +File name: "headers.h" +This file has the purpose of becoming a precompiled header common to every +project file. + +Written by: Hrk (Luca Santarelli) +Updated by: Zazoo (Victor Pavlychko) + +Miranda IM can be found here: +http://www.miranda-im.org/ + +Miranda IM plugins and tools can be found here: +http://addons.miranda-im.org/ + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/headers.h $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef HEADERS_H +#define HEADERS_H + + // disable security warnings about "*_s" functions + #define _CRT_SECURE_NO_DEPRECATE + + // disable warnings about underscore in stdc functions + #pragma warning(disable: 4996) + + #define _WIN32_WINNT 0x0501 + #define WINVER 0x0500 + #define OEMRESOURCE + + #include + #include + #include + + //Standard headers + #include + #include + #include + #include + + //Windows headers + #include + #include + #include + +#ifdef ComboBox_SelectItemData + // use Workaround for MS bug ComboBox_SelectItemData; + #undef ComboBox_SelectItemData +#endif + + //Resources + #include "../resource.h" + + #define NOWIN2K + #define MIRANDA_VER 0x0900 + #define MIRANDA_CUSTOM_LP + + //Miranda API (see Miranda svn) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #undef DBGetContactSettingString + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + + // API for 3rd party plugins (\include_API folder) + // this folder contain always the latest API + #include + #include + #include + #include +// #include //deprecatet + #include + #include + #ifndef MTEXT_NOHELPERS + #define MTEXT_NOHELPERS + #endif // MTEXT_NOHELPERS + #include + #include + #include + #include + #include + #include //core define see miranda\include\ + + // API for 3rd party plugins (.\api folder) + // this folder contain spetial edition API (not latest API !!!) + #include "m_mathmodule.h" + #include "m_popup2.h" + + //PopUp common handlers + #include "defs.h" + #include "../version.h" + #include "config.h" + #include "common.h" + #include "def_settings.h" +// #include "notify_imp.h" //deprecatet + #include "opttree.h" +// #include "opt_old.h" //deprecatet + #include "opt_gen.h" +// #include "opt_notify.h" //deprecatet + #include "opt_skins.h" + #include "opt_contacts.h" + #include "opt_adv.h" + #include "history.h" + #include "services.h" + #include "srmm_menu.h" + #include "bitmap_funcs.h" + #include "icons.h" + #include "font.h" + #include "formula.h" + #include "skin.h" + #include "popup_thread.h" + #include "actions.h" + #include "notifications.h" + #include "opt_class.h" + #include "popup_wnd2.h" + #include "effects.h" +// #include "popup_queue.h" +// #include "popup_list.h" + + #include "avatars.h" + #include "avatars_simple.h" + #include "avatars_flash.h" + #include "avatars_gif.h" + + #include "popup_gdiplus.h" + +INT_PTR svcEnableDisableMenuCommand(WPARAM, LPARAM); +extern HANDLE hSquareFad; + +#endif //HEADERS_H diff --git a/Popup/src/history.cpp b/Popup/src/history.cpp new file mode 100644 index 0000000..baf5e17 --- /dev/null +++ b/Popup/src/history.cpp @@ -0,0 +1,550 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/history.cpp $ +Revision : $Revision: 1631 $ +Last change on : $Date: 2010-07-08 08:22:12 +0300 (Чт, 08 июл 2010) $ +Last change by : $Author: MPK $ + +=============================================================================== +*/ + +#include "headers.h" + +static POPUPDATA2 *popupHistory; +static int popupHistoryStart = 0; +static int popupHistorySize = 0; +static int popupHistoryBuffer = 100; + +#define UM_RESIZELIST (WM_USER+100) +#define UM_SELECTLAST (WM_USER+101) +#define UM_ADDITEM (WM_USER+102) +static HWND hwndHistory = NULL; + +static inline int getHistoryIndex(int idx) +{ + return (popupHistoryStart + idx) % popupHistoryBuffer; +} + +static inline POPUPDATA2 *getHistoryItem(int idx) +{ + return popupHistory + (popupHistoryStart + idx) % popupHistoryBuffer; +} + +static INT_PTR CALLBACK HistoryDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +void PopupHistoryLoad() +{ + popupHistoryBuffer = DBGetContactSettingWord(NULL, MODULNAME, "HistorySize", SETTING_HISTORYSIZE_DEFAULT); + popupHistory = new POPUPDATA2[popupHistoryBuffer]; +} + +void PopupHistoryResize() +{ + int i; + int toDelete = 0; + int toCopy = popupHistorySize; + if (popupHistoryBuffer == PopUpOptions.HistorySize) return; + if (hwndHistory) PostMessage(hwndHistory, WM_CLOSE, 0, 0); + POPUPDATA2 *oldPopupHistory = popupHistory; + int oldStart = popupHistoryStart; + int oldBuffer = popupHistoryBuffer; + popupHistory = new POPUPDATA2[PopUpOptions.HistorySize]; + popupHistoryStart = 0; + popupHistoryBuffer = PopUpOptions.HistorySize; + if(PopUpOptions.HistorySize < popupHistorySize){ //if old history bigger new one + toDelete = popupHistorySize - PopUpOptions.HistorySize; + toCopy = PopUpOptions.HistorySize; + popupHistorySize = PopUpOptions.HistorySize; + } + for(i = 0; i < toCopy; ++i){ //copy needed + popupHistory[i] = oldPopupHistory[(oldStart + toDelete + i)%oldBuffer]; + } + for(i = 0; i < toDelete; ++i){//free too old ones + POPUPDATA2 *ppd = &oldPopupHistory[(oldStart + i)%oldBuffer]; + if (ppd->flags & PU2_UNICODE) + { + mir_free(ppd->lpwzTitle); + mir_free(ppd->lpwzText); + } else + { + mir_free(ppd->lpzTitle); + mir_free(ppd->lpzText); + } + if (ppd->lpzSkin) mir_free(ppd->lpzSkin); + } + delete [] oldPopupHistory; +} + +void PopupHistoryUnload() +{ + for (int i = 0; i < popupHistorySize; ++i) + { + POPUPDATA2 *ppd = &popupHistory[getHistoryIndex(i)]; + if (ppd->flags & PU2_UNICODE) + { + mir_free(ppd->lpwzTitle); + mir_free(ppd->lpwzText); + } else + { + mir_free(ppd->lpzTitle); + mir_free(ppd->lpzText); + } + if (ppd->lpzSkin) mir_free(ppd->lpzSkin); + } + delete [] popupHistory; + popupHistory = NULL; +} + +void PopupHistoryAdd(POPUPDATA2 *ppdNew) +{ + if (!PopUpOptions.EnableHistory) + return; + + POPUPDATA2 *ppd; + if (popupHistorySize < popupHistoryBuffer) + { + ++popupHistorySize; + ppd = &popupHistory[getHistoryIndex(popupHistorySize-1)]; + } else + { + popupHistoryStart = (popupHistoryStart+1)%popupHistoryBuffer; + ppd = &popupHistory[getHistoryIndex(popupHistorySize-1)]; + if (ppd->flags & PU2_UNICODE) + { + mir_free(ppd->lpwzTitle); + mir_free(ppd->lpwzText); + } else + { + mir_free(ppd->lpzTitle); + mir_free(ppd->lpzText); + } + if (ppd->lpzSkin) mir_free(ppd->lpzSkin); + } + + *ppd = *ppdNew; + if (ppd->flags&PU2_UNICODE) + { + ppd->lpwzTitle = mir_wstrdup(ppd->lpwzTitle); + ppd->lpwzText = mir_wstrdup(ppd->lpwzText); + } else + { + ppd->lpzTitle = mir_strdup(ppd->lpzTitle); + ppd->lpzText = mir_strdup(ppd->lpzText); + } + if (ppd->lpzSkin) + { + ppd->lpzSkin = mir_strdup(ppd->lpzSkin); + } else + { + ppd->lpzSkin = NULL; + } + ppd->dwTimestamp = time(NULL); +// GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL,"HH':'mm", ppd->lpzTime, sizeof(ppd->lpzTime)); + if (hwndHistory) + PostMessage(hwndHistory, UM_ADDITEM, 0, (LPARAM)ppd); +} + +void PopupHistoryShow() +{ + if (!PopUpOptions.EnableHistory){ + MessageBox(NULL, TranslateT("Popup History is disabled"), TranslateT("Popup History message"), MB_OK); + return; + } + + if (hwndHistory) + { + ShowWindow(hwndHistory, SW_SHOW); + SetForegroundWindow(hwndHistory); + SetFocus(hwndHistory); + SetActiveWindow(hwndHistory); + } else + { + hwndHistory = CreateDialog(hInst, MAKEINTRESOURCE(IDD_HISTORY), NULL, HistoryDlgProc); + SetWindowText(hwndHistory, TranslateT("Popup History")); + //ShowWindow(hwndHistory, SW_SHOW); + } +} + +static INT_PTR CALLBACK HistoryDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int oldWidth = 0; + static int loadItem = -1; + + static enum { LOG_NONE, LOG_DEFAULT, LOG_HPP } logType = LOG_NONE; + static HWND hwndLog = NULL; + + switch (msg) + { + case WM_INITDIALOG: + { + oldWidth = 0; + HWND hwndList = GetDlgItem(hwnd, IDC_POPUP_LIST); + for (int i = 0; i < popupHistorySize; ++i) + ListBox_SetItemData(hwndList, ListBox_AddString(hwndList, _T("")), 0); + SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)IcoLib_GetIcon(ICO_HISTORY,0)); + SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)IcoLib_GetIcon(ICO_HISTORY,1)); + + if (gbHppInstalled && PopUpOptions.UseHppHistoryLog) + { + logType = LOG_HPP; + ShowWindow(GetDlgItem(hwnd, IDC_POPUP_LIST), SW_HIDE); + + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_CREATE; + ieWindow.dwFlags = 0; + ieWindow.dwMode = IEWM_MUCC; +// ieWindow.dwMode = IEWM_CHAT; + ieWindow.parent = hwnd; + ieWindow.x = 0; + ieWindow.y = 0; + ieWindow.cx = 100; + ieWindow.cy = 100; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); + hwndLog = ieWindow.hwnd; + ShowWindow(hwndLog, SW_SHOW); + + RECT rcLst; GetWindowRect(hwndList, &rcLst); + POINT pt; + pt.x = rcLst.left; + pt.y = rcLst.top; + ScreenToClient(hwnd, &pt); + + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_SETPOS; + ieWindow.parent = hwnd; + ieWindow.hwnd = hwndLog; + ieWindow.x = pt.x; + ieWindow.y = pt.y; + ieWindow.cx = rcLst.right-rcLst.left; + ieWindow.cy = rcLst.bottom-rcLst.top; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); + + IEVIEWEVENTDATA ieData; + + IEVIEWEVENT ieEvent; + ieEvent.cbSize = sizeof(ieEvent); + ieEvent.iType = IEE_LOG_MEM_EVENTS; + ieEvent.dwFlags = 0; + ieEvent.hwnd = hwndLog; + ieEvent.eventData = &ieData; + ieEvent.count = 1; + ieEvent.codepage = 0; + ieEvent.pszProto = NULL; + + for (int i = 0; i < popupHistorySize; ++i) + { + ieData.cbSize = sizeof(ieData); + ieData.iType = IEED_EVENT_SYSTEM; + ieData.dwFlags = 0; + ieData.color = getHistoryItem(i)->colorText; + if (getHistoryItem(i)->flags & PU2_UNICODE) + { + ieData.dwFlags |= IEEDF_UNICODE_TEXT|IEEDF_UNICODE_NICK; + ieData.pszNickW = getHistoryItem(i)->lpwzTitle; + ieData.pszTextW = getHistoryItem(i)->lpwzText; + ieData.pszText2W = NULL; + } else + { + ieData.dwFlags |= 0; + ieData.pszNick = getHistoryItem(i)->lpzTitle; + ieData.pszText = getHistoryItem(i)->lpzText; + ieData.pszText2 = NULL; + } + ieData.bIsMe = FALSE; + ieData.time = getHistoryItem(i)->dwTimestamp; + ieData.dwData = 0; + ieData.next = NULL; + CallService(MS_HPP_EG_EVENT, 0, (WPARAM)&ieEvent); + } + } else + { + logType = LOG_DEFAULT; + hwndLog = hwndList; + + ShowWindow(hwndLog, SW_SHOW); + } + + Utils_RestoreWindowPosition(hwnd, NULL, MODULNAME, "popupHistory_"); + + if (logType == LOG_DEFAULT) + { + SendMessage(hwnd, UM_RESIZELIST, 0, 0); + ListBox_SetTopIndex(hwndLog, popupHistorySize-1); + } + + return TRUE; + } + case WM_MEASUREITEM: + { + if (logType != LOG_DEFAULT) + return TRUE; + + LPMEASUREITEMSTRUCT lpmis; + lpmis = (LPMEASUREITEMSTRUCT) lParam; + if (lpmis->itemID == -1) + return FALSE; + lpmis->itemHeight = 50; + return TRUE; + } + case WM_DRAWITEM: + { + if (logType != LOG_DEFAULT) + return TRUE; + + LPDRAWITEMSTRUCT lpdis; + lpdis = (LPDRAWITEMSTRUCT) lParam; + if (lpdis->itemID == -1) + return FALSE; + + HWND hwndList = GetDlgItem(hwnd, lpdis->CtlID); + PopupWnd2 *wndPreview = (PopupWnd2 *)ListBox_GetItemData(hwndList, lpdis->itemID); + + if (!wndPreview) + { + RECT rc; GetWindowRect(hwndLog, &rc); + + if (rc.right-rc.left <= 30) + return FALSE; + + POPUPOPTIONS customOptions = PopUpOptions; + customOptions.DynamicResize = FALSE; + customOptions.MinimumWidth = customOptions.MaximumWidth = rc.right-rc.left-30; + + POPUPDATA2 *ppd = &popupHistory[getHistoryIndex(lpdis->itemID)]; + wndPreview = new PopupWnd2(ppd, &customOptions, true); + wndPreview->buildMText(); + wndPreview->update(); + + ListBox_SetItemData(hwndLog, lpdis->itemID, wndPreview); + ListBox_SetItemHeight(hwndLog, lpdis->itemID, wndPreview->getSize().cy+6); + } + + if (wndPreview) + { + if (lpdis->itemState & ODS_SELECTED) + { + HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + FillRect(lpdis->hDC, &lpdis->rcItem, hbr); + DeleteObject(hbr); + } else + { + HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); + FillRect(lpdis->hDC, &lpdis->rcItem, hbr); + DeleteObject(hbr); + } + + int width = wndPreview->getContent()->getWidth(); + int height = wndPreview->getContent()->getHeight(); +#if defined(_UNICODE) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + AlphaBlend(lpdis->hDC, lpdis->rcItem.left+5, lpdis->rcItem.top+3, width, height, + wndPreview->getContent()->getDC(), + 0, 0, width, height, bf); + } +#else + if (MyAlphaBlend) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + MyAlphaBlend(lpdis->hDC, lpdis->rcItem.left+5, lpdis->rcItem.top+3, width, height, + wndPreview->getContent()->getDC(), + 0, 0, width, height, bf); + } + else { + BitBlt(lpdis->hDC, + lpdis->rcItem.left+5, lpdis->rcItem.top+5, lpdis->rcItem.left+5+width, lpdis->rcItem.top+3+height, + wndPreview->getContent()->getDC(), + 0, 0, SRCCOPY); + } +#endif + } + + return TRUE; + } + case WM_DELETEITEM: + { + if (logType != LOG_DEFAULT) + return TRUE; + + DELETEITEMSTRUCT *lpdis = (DELETEITEMSTRUCT *)lParam; + PopupWnd2 *wnd = (PopupWnd2 *)ListBox_GetItemData(lpdis->hwndItem, lpdis->itemID); + if (wnd) delete wnd; + return TRUE; + } + case WM_SIZE: + { + RECT rcLst; GetClientRect(hwnd, &rcLst); + rcLst.left += 10; + rcLst.top += 10; + rcLst.right -= 10; + rcLst.bottom -= 10; + if (logType == LOG_HPP) + { +// POINT pt; +// pt.x = rcLst.left; +// pt.y = rcLst.top; +// ScreenToClient(hwnd, &pt); + SetWindowPos(hwndLog, NULL, + rcLst.left, rcLst.top, rcLst.right-rcLst.left, rcLst.bottom-rcLst.top, + SWP_NOZORDER|SWP_DEFERERASE|SWP_SHOWWINDOW); + + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_SETPOS; + ieWindow.parent = hwnd; + ieWindow.hwnd = hwndLog; + ieWindow.x = rcLst.left; + ieWindow.y = rcLst.top; + ieWindow.cx = rcLst.right-rcLst.left; + ieWindow.cy = rcLst.bottom-rcLst.top; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); + } else + if (logType == LOG_DEFAULT) + { + SetWindowPos(hwndLog, NULL, + rcLst.left, rcLst.top, rcLst.right-rcLst.left, rcLst.bottom-rcLst.top, + SWP_NOZORDER|SWP_DEFERERASE|SWP_SHOWWINDOW); + if (rcLst.right-rcLst.left != oldWidth) + { + oldWidth = rcLst.right-rcLst.left; + PostMessage(hwnd, UM_RESIZELIST, 0, 0); + } + } + return TRUE; + } + case UM_RESIZELIST: + { + if (logType != LOG_DEFAULT) + return TRUE; + + RECT rc; GetWindowRect(GetDlgItem(hwnd, IDC_POPUP_LIST), &rc); + + if (rc.right-rc.left <= 30) + return FALSE; + + for (int i = 0; i < popupHistorySize; ++i) + { + PopupWnd2 *wndPreview = (PopupWnd2 *)ListBox_GetItemData(hwndLog, i); + if (wndPreview) delete wndPreview; + + ListBox_SetItemData(hwndLog, i, 0); + ListBox_SetItemHeight(hwndLog, i, 50); + } + ScrollWindow(hwndLog, 0, 100000, NULL, NULL); + InvalidateRect(hwndLog, NULL, TRUE); + + return TRUE; + } + case UM_ADDITEM: + { + if (logType == LOG_HPP) + { + POPUPDATA2 *ppd = (POPUPDATA2 *)lParam; + + IEVIEWEVENTDATA ieData; + + IEVIEWEVENT ieEvent; + ieEvent.cbSize = sizeof(ieEvent); + ieEvent.iType = IEE_LOG_MEM_EVENTS; + ieEvent.dwFlags = 0; + ieEvent.hwnd = hwndLog; + ieEvent.eventData = &ieData; + ieEvent.count = 1; + ieEvent.codepage = 0; + ieEvent.pszProto = NULL; + + ieData.cbSize = sizeof(ieData); + ieData.dwFlags = 0; + ieData.iType = IEED_EVENT_SYSTEM; + ieData.color = ppd->colorText; + if (ppd->flags & PU2_UNICODE) + { + ieData.dwFlags |= IEEDF_UNICODE_TEXT|IEEDF_UNICODE_NICK; + ieData.pszNickW = ppd->lpwzTitle; + ieData.pszTextW = ppd->lpwzText; + ieData.pszText2W = NULL; + } else + { + ieData.dwFlags |= 0; + ieData.pszNick = ppd->lpzTitle; + ieData.pszText = ppd->lpzText; + ieData.pszText2 = NULL; + } + ieData.bIsMe = FALSE; + ieData.time = ppd->dwTimestamp; + ieData.dwData = 0; + ieData.next = NULL; + CallService(MS_HPP_EG_EVENT, 0, (WPARAM)&ieEvent); + } else + if(logType == LOG_DEFAULT) + { + if (popupHistorySize <= ListBox_GetCount(hwndLog)) + { + loadItem = 0; + PostMessage(hwnd, UM_RESIZELIST, 0, 0); + return TRUE; + } + ListBox_SetItemData(hwndLog, ListBox_AddString(hwndLog, _T("")), 0); +/* if (loadItem < 0) + { + loadItem = ListBox_GetCount(hwndList)-1; + SendMessage(hwnd, UM_RESIZEITEM, 0, 0); + }*/ + } + return TRUE; + } + case WM_CLOSE: + { + Utils_SaveWindowPosition(hwnd, NULL, MODULNAME, "popupHistory_"); + DestroyWindow(hwnd); + hwndHistory = NULL; + return TRUE; + } + case WM_DESTROY: + { + if (logType == LOG_HPP) + { + IEVIEWWINDOW ieWindow; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_DESTROY; + ieWindow.dwFlags = 0; + ieWindow.dwMode = IEWM_TABSRMM; + ieWindow.parent = hwnd; + ieWindow.hwnd = hwndLog; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); + } + } + } + return FALSE; //DefWindowProc(hwnd, msg, wParam, lParam); +} diff --git a/Popup/src/history.h b/Popup/src/history.h new file mode 100644 index 0000000..ee7d4f4 --- /dev/null +++ b/Popup/src/history.h @@ -0,0 +1,43 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/history.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __history_h__ +#define __history_h__ + +void PopupHistoryLoad(); +void PopupHistoryResize(); +void PopupHistoryUnload(); + +void PopupHistoryAdd(POPUPDATA2 *ppd); +void PopupHistoryShow(); + +#endif // __history_h__ diff --git a/Popup/src/icons.cpp b/Popup/src/icons.cpp new file mode 100644 index 0000000..cb6e87d --- /dev/null +++ b/Popup/src/icons.cpp @@ -0,0 +1,145 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/icons.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +typedef struct _ICODESC +{ + LPSTR pszName; + LPTSTR ptszDesc; + LPTSTR ptszSection; + BOOL bfromIconPack; + WORD idResource; + LPSTR pszIcon; + int size; +} ICODESC; + +static ICODESC icoDesc[] = +{ + //toolbar + { ICO_TB_POPUP_ON, _T("Popups are enabled"), _T(SECT_TOLBAR), 0, IDI_POPUP, NULL, 0 }, + { ICO_TB_POPUP_OFF, _T("Popups are disabled"), _T(SECT_TOLBAR), 0, IDI_NOPOPUP, NULL, 0 }, + //common popup + { ICO_POPUP_ON, _T("Popups are enabled"), _T(SECT_POPUP), 0, IDI_POPUP, NULL, 0 }, + { ICO_POPUP_OFF, _T("Popups are disabled"), _T(SECT_POPUP), 0, IDI_NOPOPUP, NULL, 0 }, + { ICO_FAV, _T("With \"favourite\" overlay"), _T(SECT_POPUP), 0, IDI_PU_FAVOURITE, NULL, 0 }, + { ICO_FULLSCREEN, _T("With \"fullscreen\" overlay"), _T(SECT_POPUP), 0, IDI_PU_FULLSCREEN, NULL, 0 }, + { ICO_HISTORY, _T("Popup History"), _T(SECT_POPUP), 0, IDI_HISTORY, NULL, -1 }, + //misc (register is done inside notification service) + //{ ICO_MISC_NOTIFY, _T("Notification"), _T(SECT_POPUP) _T(SECT_POPUP_MISC), 0, IDI_MB_INFO, NULL, 0 }, + //{ ICO_MISC_WARNING, _T("Warning"), _T(SECT_POPUP) _T(SECT_POPUP_MISC), 0, IDI_MB_WARN, NULL, 0 }, + //{ ICO_MISC_ERROR, _T("Error"), _T(SECT_POPUP) _T(SECT_POPUP_MISC), 0, IDI_MB_STOP, NULL, 0 }, + //option + { ICO_OPT_RELOAD, _T("Refresh skin list"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_RELOAD, NULL, 0 }, + { ICO_OPT_RESIZE, _T("Popup Placement"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_RESIZE, NULL, 0 }, + { ICO_OPT_OK, _T("OK"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_ACT_OK, NULL, 0 }, + { ICO_OPT_CANCEL, _T("Cancel"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_ACT_CLOSE, NULL, 0 }, + { ICO_OPT_GROUP, _T("Popup Group"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_OPT_GROUP, NULL, 0 }, + { ICO_OPT_DEF, _T("Show default"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_ACT_OK, NULL, 0 }, + { ICO_OPT_FAV, _T("Favorite Contact"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_OPT_FAVORITE, NULL, 0 }, + { ICO_OPT_FULLSCREEN, _T("Show in Fullscreen"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_OPT_FULLSCREEN, NULL, 0 }, + { ICO_OPT_BLOCK, _T("Blocked Contact"), _T(SECT_POPUP) _T(SECT_POPUP_OPT), 0, IDI_OPT_BLOCK, NULL, 0 }, + //action + { ICO_ACT_REPLY, _T("Quick Reply"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_REPLY, NULL, -1 }, + { ICO_ACT_PIN, _T("Pin Popup"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_PIN, NULL, -1 }, + { ICO_ACT_PINNED, _T("Pinned Popup"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_PINNED, NULL, -1 }, + { ICO_ACT_MESS, _T("Send Message"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_MESSAGE, NULL, -1 }, + { ICO_ACT_INFO, _T("User Details"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_INFO, NULL, -1 }, + { ICO_ACT_MENU, _T("Contact Menu"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_MENU, NULL, -1 }, + { ICO_ACT_ADD, _T("Add Contact Permanently"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_ADD, NULL, -1 }, + { ICO_ACT_CLOSE, _T("Dismiss Popup"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_CLOSE, NULL, -1 }, + { ICO_ACT_COPY, _T("Copy to clipboard"), _T(SECT_POPUP) _T(SECT_POPUP_ACT), 0, IDI_ACT_COPY, NULL, -1 } + +}; + +/** + * Returns a icon, identified by a name + * @param pszIcon - name of the icon + * @param big - bool big icon (default = false) + * @return: HICON if the icon is loaded, NULL otherwise + **/ +HICON IcoLib_GetIcon(LPCSTR pszIcon, bool big) +{ + return (pszIcon) ? (HICON)CallService(MS_SKIN2_GETICON, (WPARAM)big, (LPARAM) pszIcon) : NULL; +} + +void InitIcons() +{ + SKINICONDESC sid; + ZeroMemory(&sid, sizeof(sid)); + sid.cbSize = sizeof(sid); + sid.flags = SIDF_ALL_TCHAR; + TCHAR selfDLL[1024]; + GetModuleFileName(hInst, selfDLL, 1024); + + for(int i = 0; i < SIZEOF(icoDesc); i++){ + sid.pszName = icoDesc[i].pszName; + sid.ptszDescription = icoDesc[i].ptszDesc; // [TRANSLATED-BY-CORE] + sid.ptszSection = icoDesc[i].ptszSection; //must be always untranslatet !!!!! + + if(icoDesc[i].idResource==0){ + //use icon from icon lib + sid.hDefaultIcon = (HICON)CallService(MS_SKIN2_GETICON,0 , (LPARAM)icoDesc[i].pszIcon); + sid.ptszDefaultFile = NULL; + sid.iDefaultIndex = 0; + }else{ + //load and register from popup.dll + sid.hDefaultIcon = 0; + sid.ptszDefaultFile = selfDLL; + sid.iDefaultIndex = -icoDesc[i].idResource; + } + + switch (icoDesc[i].size){ + // small and big icons + case -1:{ + sid.cx = sid.cy = 0; + break; + } + // small icons (16x16) + case 0:{ + sid.cx = sid.cy = 16; + break; + } + // normal icons (32x32) + case 1:{ + sid.cx = sid.cy = 32; + break; + } + // custom icon size + default:{ + sid.cx = sid.cy = icoDesc[i].size; + break; + } + } + CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); + } +} \ No newline at end of file diff --git a/Popup/src/icons.h b/Popup/src/icons.h new file mode 100644 index 0000000..532e7ce --- /dev/null +++ b/Popup/src/icons.h @@ -0,0 +1,79 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/icons.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __icons_h__ +#define __icons_h__ + +//ICONS +#define SECT_TOLBAR "ToolBar" +#define SECT_POPUP MODULNAME_PLU +#define SECT_POPUP_ACT "/Actions" +#define SECT_POPUP_OPT "/Options" +#define SECT_POPUP_MISC "/Misc" + +#define ICO_TB_POPUP_ON "TBButton_popup_ToogleUp" +#define ICO_TB_POPUP_OFF "TBButton_popup_ToogleDOWN" +#define ICO_POPUP_ON MODULNAME"_enabled" +#define ICO_POPUP_OFF MODULNAME"_disabled" +#define ICO_FAV MODULNAME"_favourite" +#define ICO_FULLSCREEN MODULNAME"_fullscreen" +#define ICO_HISTORY MODULNAME"_history" + +#define ICO_MISC_NOTIFY MODULNAME"_Misc_Notification" +#define ICO_MISC_WARNING MODULNAME"_Misc_Warning" +#define ICO_MISC_ERROR MODULNAME"_Misc_Error" + +#define ICO_ACT_MESS MODULNAME"_act_message" +#define ICO_ACT_INFO MODULNAME"_act_info" +#define ICO_ACT_MENU MODULNAME"_act_menu" +#define ICO_ACT_ADD MODULNAME"_act_add" +#define ICO_ACT_REPLY MODULNAME"_act_reply" +#define ICO_ACT_PIN MODULNAME"_act_pin" +#define ICO_ACT_PINNED MODULNAME"_act_pinned" +#define ICO_ACT_CLOSE MODULNAME"_act_close" +#define ICO_ACT_COPY MODULNAME"_act_copy" + +#define ICO_OPT_RELOAD MODULNAME"_opt_reload" +#define ICO_OPT_RESIZE MODULNAME"_opt_resize" +#define ICO_OPT_GROUP MODULNAME"_opt_group" +#define ICO_OPT_OK MODULNAME"_opt_ok" +#define ICO_OPT_CANCEL MODULNAME"_opt_cancel" + +#define ICO_OPT_DEF MODULNAME"_opt_default" +#define ICO_OPT_FAV MODULNAME"_opt_favorite" +#define ICO_OPT_FULLSCREEN MODULNAME"_opt_fullscreen" +#define ICO_OPT_BLOCK MODULNAME"_opt_block" + +void InitIcons(); +HICON IcoLib_GetIcon(LPCSTR pszIcon, bool big=false); + +#endif // __icons_h__ diff --git a/Popup/src/main.cpp b/Popup/src/main.cpp new file mode 100644 index 0000000..41ad1b5 --- /dev/null +++ b/Popup/src/main.cpp @@ -0,0 +1,743 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/main.cpp $ +Revision : $Revision: 1652 $ +Last change on : $Date: 2010-07-15 20:48:21 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" +#include +#include + +WORD SETTING_MAXIMUMWIDTH_MAX = GetSystemMetrics(SM_CXSCREEN); + +#define MENUCOMMAND_HISTORY "PopUp/ShowHistory" +#define MENUCOMMAND_SVC "PopUp/EnableDisableMenuCommand" + + +//===== MessageBoxes ===== +//void MB(char*); //This one is for Debug purposes +//void Log(char*); //This one is used to notify the user +//void HigherLower(int, int); //Used for integer input boxes (out of bound values). +//void NotifyError(DWORD, char*, int, char*); //Used to notify an error giving some error codes to report. + +//===== Options ===== +static int OptionsInitialize(WPARAM,LPARAM); + +//===== Initializations ===== +static int OkToExit(WPARAM,LPARAM); +bool OptionLoaded = false; +int hLangpack = 0; + +//===== Global variables ===== +//===== DLLs ===== +HMODULE hUserDll = 0; +HMODULE hMsimgDll = 0; +HMODULE hKernelDll = 0; +HMODULE hGdiDll = 0; +HMODULE hDwmapiDll = 0; + +//===== User wnd class ===== +GLOBAL_WND_CLASSES g_wndClass = {0}; + +//===== MTextControl ==== +HANDLE htuText = NULL; +HANDLE htuTitle = NULL; + +//===== Menu item ===== +HANDLE hMenuRoot = NULL; +HANDLE hMenuItem = NULL; +HANDLE hMenuItemHistory = NULL; + +//==== ServiceFunctions Handles ==== +HANDLE hShowHistory = NULL; +HANDLE hTogglePopup = NULL; +HANDLE hGetStatus = NULL; + +//===== Event Handles ===== +HANDLE hOptionsInitialize; +//HANDLE hNotifyOptionsInitialize; deprecatet +HANDLE hModulesLoaded; +HANDLE hTTBLoaded; +HANDLE hTBLoaded; +HANDLE hOkToExit; +HANDLE hIconsChanged, hFontsChanged; +HANDLE hEventStatusChanged; //To automatically disable on status change. +int hTTButton = -1; +HANDLE hTButton = NULL; + +GLOBAL g_popup = {0}; + +static struct { + char *name; + INT_PTR (*func)(WPARAM, LPARAM); + HANDLE handle; +} popupServices[] = +{ + {MS_POPUP_ADDPOPUP, PopUp_AddPopUp, 0}, + {MS_POPUP_ADDPOPUPEX, PopUp_AddPopUpEx, 0}, + {MS_POPUP_ADDPOPUPW, PopUp_AddPopUpW, 0}, + {MS_POPUP_ADDPOPUP2, PopUp_AddPopUp2, 0}, + + {MS_POPUP_CHANGETEXT, PopUp_ChangeText, 0}, + {MS_POPUP_CHANGETEXTW, PopUp_ChangeTextW, 0}, + {MS_POPUP_CHANGE, PopUp_Change, 0}, + {MS_POPUP_CHANGEW, PopUp_ChangeW, 0}, + {MS_POPUP_CHANGEPOPUP2, PopUp_Change2, 0}, + + {MS_POPUP_GETCONTACT, PopUp_GetContact, 0}, + {MS_POPUP_GETPLUGINDATA, PopUp_GetPluginData, 0}, + {MS_POPUP_ISSECONDLINESHOWN, PopUp_IsSecondLineShown, 0}, + + {MS_POPUP_SHOWMESSAGE, PopUp_ShowMessage, 0}, + {MS_POPUP_SHOWMESSAGEW, PopUp_ShowMessageW, 0}, + {MS_POPUP_QUERY, PopUp_Query, 0}, + + {MS_POPUP_REGISTERACTIONS, PopUp_RegisterActions, 0}, + {MS_POPUP_REGISTERNOTIFICATION, PopUp_RegisterNotification, 0}, + + {MS_POPUP_UNHOOKEVENTASYNC, PopUp_UnhookEventAsync, 0}, + + {MS_POPUP_REGISTERVFX, PopUp_RegisterVfx, 0}, + + {MS_POPUP_REGISTERCLASS, PopUp_RegisterPopupClass, 0}, + {MS_POPUP_ADDPOPUPCLASS, PopUp_CreateClassPopup, 0}, + +}; + +//===== Options pages ===== +static int OptionsInitialize(WPARAM wParam,LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.position = 100000000; + odp.groupPosition = 910000000; + odp.flags = ODPF_TCHAR | ODPF_BOLDGROUPS; + odp.ptszTitle = LPGENT(MODULNAME_PLU); + + odp.ptszTab = LPGENT("General"); + odp.pfnDlgProc = DlgProcPopUpGeneral; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP_GENERAL); + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + odp.ptszTab = LPGENT("Classes"); + odp.pfnDlgProc = DlgProcOptsClasses; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_NOTIFICATIONS); + CallService( MS_OPT_ADDPAGE, wParam,(LPARAM)&odp ); + + odp.ptszTab = LPGENT("Actions"); + odp.pfnDlgProc = DlgProcPopupActions; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ACTIONS); + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + odp.ptszTab = LPGENT("Contacts"); + odp.pfnDlgProc = DlgProcContactOpts; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CONTACTS); + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + odp.ptszTab = LPGENT("Advanced"); + odp.pfnDlgProc = DlgProcPopUpAdvOpts; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP_ADVANCED); + odp.flags |= ODPF_EXPERTONLY; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + odp.ptszGroup = LPGENT("Skins"); + odp.ptszTab = LPGENT(MODULNAME_PLU); + odp.pfnDlgProc = DlgProcPopSkinsOpts; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SKIN2); + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + //Test page + //odp.ptszTab = LPGEN("General (old)"); + //odp.pfnDlgProc = DlgProcPopUpOpts; + //odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_POPUP); + //CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + return 0; +} + +static int FontsChanged(WPARAM wParam,LPARAM lParam) +{ + ReloadFonts(); + return 0; +} + +static int IconsChanged(WPARAM wParam,LPARAM lParam){ + LoadActions(); + + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + + if (PopUpOptions.ModuleIsEnabled == TRUE) { //The module is enabled. + //The action to do is "disable popups" (show disabled) and we must write "enable popup" in the new item. + mi.hIcon = IcoLib_GetIcon(ICO_POPUP_ON,0); + } + else { //The module is disabled. + //The action to do is enable popups (show enabled), then write "disable popup" in the new item. + mi.hIcon = IcoLib_GetIcon(ICO_POPUP_OFF,0); + } + mi.flags = CMIM_ICON; + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hMenuItem,(LPARAM)&mi); + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hMenuRoot,(LPARAM)&mi); + + mi.hIcon = IcoLib_GetIcon(ICO_HISTORY,0); + mi.flags = CMIM_ICON; + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hMenuItemHistory,(LPARAM)&mi); + + if (hTTButton >= 0) { + TTBButtonV2 btn = {0}; + btn.cbSize = sizeof(btn); + btn.pszServiceUp = btn.pszServiceDown = MENUCOMMAND_SVC; + btn.lParamUp = 1; + btn.lParamDown = 0; + btn.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP; + btn.name = Translate("Toggle Popups"); + btn.tooltipUp = Translate("Popups are disabled"); + btn.tooltipDn = Translate("Popups are enabled"); + btn.hIconUp = IcoLib_GetIcon(ICO_POPUP_OFF,0); + btn.hIconDn = IcoLib_GetIcon(ICO_POPUP_ON,0); + hTTButton = CallService(MS_TTB_SETBUTTONOPTIONS, MAKEWPARAM(TTBO_ALLDATA, hTTButton), (LPARAM)&btn); + } + + return 0; +} + +static int TTBLoaded(WPARAM wParam,LPARAM lParam){ + if (hTTButton < 0) { + TTBButtonV2 btn = {0}; + btn.cbSize = sizeof(btn); + btn.pszServiceUp = btn.pszServiceDown = MENUCOMMAND_SVC; + btn.lParamUp = 1; + btn.lParamDown = 0; + btn.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP; + btn.name = Translate("Toggle Popups"); + btn.tooltipUp = Translate("Popups are disabled"); + btn.tooltipDn = Translate("Popups are enabled"); + btn.hIconUp = IcoLib_GetIcon(ICO_POPUP_OFF,0); + btn.hIconDn = IcoLib_GetIcon(ICO_POPUP_ON,0); + hTTButton = CallService(MS_TTB_ADDBUTTON, (WPARAM)&btn, 0); + } + CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTTButton, PopUpOptions.ModuleIsEnabled?TTBST_RELEASED:TTBST_PUSHED); + return 0; +} + +//register Modern Toolbarbutton +static int ToolbarSet(WPARAM, LPARAM){ + if (hTButton == NULL){ + TBButton tbb = {0}; + tbb.cbSize = sizeof(TBButton); + tbb.pszButtonID = "PopupToogle"; + tbb.pszButtonName = Translate("Toggle Popups"); + tbb.pszServiceName = MENUCOMMAND_SVC; + tbb.pszTooltipUp = Translate("Popups are disabled"); + tbb.pszTooltipDn = Translate("Popups are enabled"); + tbb.hPrimaryIconHandle = (HANDLE)CallService(MS_SKIN2_GETICONHANDLE, 0, (LPARAM)ICO_TB_POPUP_OFF); + tbb.hSecondaryIconHandle = (HANDLE)CallService(MS_SKIN2_GETICONHANDLE, 0, (LPARAM)ICO_TB_POPUP_ON); + tbb.tbbFlags = TBBF_VISIBLE; + tbb.defPos = 10000; + hTButton = (HANDLE)CallService(MS_TB_ADDBUTTON,0, (LPARAM)&tbb); + } + CallService(MS_TB_SETBUTTONSTATEBYID, (WPARAM)"PopupToogle", PopUpOptions.ModuleIsEnabled?TBST_PUSHED:TBST_RELEASED); + return 0; +} + +//===== EnableDisableMenuCommand ===== +INT_PTR svcEnableDisableMenuCommand(WPARAM wp, LPARAM lp) +{ + int iResult = 0; + int iResultRoot = 0; + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + + if (PopUpOptions.ModuleIsEnabled) + { //The module is enabled. + //The action to do is "disable popups" (show disabled) and we must write "enable popup" in the new item. + PopUpOptions.ModuleIsEnabled = FALSE; + DBWriteContactSettingByte(NULL, MODULNAME, "ModuleIsEnabled", FALSE); + mi.ptszName = LPGENT("Enable &popup module"); + mi.hIcon = IcoLib_GetIcon(ICO_POPUP_OFF,0); + } else + { //The module is disabled. + //The action to do is enable popups (show enabled), then write "disable popup" in the new item. + PopUpOptions.ModuleIsEnabled = TRUE; + DBWriteContactSettingByte(NULL, MODULNAME, "ModuleIsEnabled", TRUE); + mi.ptszName = LPGENT("Disable &popup module"); + mi.hIcon = IcoLib_GetIcon(ICO_POPUP_ON,0); + } + mi.flags = CMIM_NAME | CMIM_ICON | CMIF_TCHAR; + iResult = CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hMenuItem,(LPARAM)&mi); + mi.flags = CMIM_ICON; + iResultRoot = CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hMenuRoot,(LPARAM)&mi); + TTBLoaded(0,0); + ToolbarSet(0,0); + if(iResult && iResultRoot) + return 1; + else + return 0; +} + +INT_PTR svcShowHistory(WPARAM, LPARAM) +{ + PopupHistoryShow(); + return 0; +} + +void InitMenuItems(void) { + CLISTMENUITEM mi={0}; + + // Common + mi.cbSize = sizeof(mi); + // support new genmenu style + mi.flags = CMIF_ROOTHANDLE|CMIF_TCHAR; + mi.hParentMenu = HGENMENU_ROOT; + + // Build main menu + mi.position = -1000000000 /*1000001*/; + mi.ptszName = LPGENT(MODULNAME_PLU); + mi.hIcon = IcoLib_GetIcon(PopUpOptions.ModuleIsEnabled ? ICO_POPUP_ON : ICO_POPUP_OFF ,0); + hMenuRoot = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi); + + // Add item to main menu + mi.hParentMenu = (HGENMENU)hMenuRoot; + + hTogglePopup = CreateServiceFunction(MENUCOMMAND_SVC, svcEnableDisableMenuCommand); + mi.ptszName = PopUpOptions.ModuleIsEnabled ? LPGENT("Disable &popup module") : LPGENT("Enable &popup module"); + mi.pszService = MENUCOMMAND_SVC; + hMenuItem = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); + + // Popup History + hShowHistory = CreateServiceFunction(MENUCOMMAND_HISTORY, svcShowHistory); + mi.position = 1000000000; + mi.popupPosition = 1999990000; + mi.ptszName = LPGENT("Popup History"); + mi.hIcon = IcoLib_GetIcon(ICO_HISTORY, 0); + mi.pszService = MENUCOMMAND_HISTORY; + hMenuItemHistory = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); + +} + +//===== GetStatus ===== +INT_PTR GetStatus(WPARAM wp, LPARAM lp) +{ + return PopUpOptions.ModuleIsEnabled; +} + +//register Updatersupport +void registerUpdate(){ + Update update = {0}; + char szVersion[16]; + update.cbSize = sizeof(Update); + update.szComponentName = pluginInfoEx.shortName; + update.pbVersion = (BYTE *)CreateVersionStringPluginEx(&pluginInfoEx, szVersion); + update.cpbVersion = (int)strlen((char *)update.pbVersion); + + update.szUpdateURL = __FLUpdateURL /*UPDATER_AUTOREGISTER*/; + update.szVersionURL = __FLVersionURL; + update.pbVersionPrefix = (BYTE *)__FLVersionPrefix; + update.cpbVersionPrefix = (int)strlen((char *)update.pbVersionPrefix); + + update.szBetaUpdateURL = __BetaUpdateURL; + update.szBetaVersionURL = __BetaVersionURL; + // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + update.pbBetaVersionPrefix = (BYTE *)__BetaVersionPrefix; + update.cpbBetaVersionPrefix = (int)strlen((char *)update.pbBetaVersionPrefix); + + update.szBetaChangelogURL = __BetaChangelogURL; + + CallService(MS_UPDATE_REGISTER, 0, (LPARAM) &update); +} + +//register Hotkey +void LoadHotkey(){ + HOTKEYDESC hk = {0}; + hk.cbSize = sizeof(hk); + hk.dwFlags = HKD_TCHAR; + hk.pszName = "Toggle Popups"; + hk.ptszDescription = LPGENT("Toggle Popups"); + hk.ptszSection = LPGENT(MODULNAME_PLU); + hk.pszService = MENUCOMMAND_SVC; + CallService(MS_HOTKEY_REGISTER, 0, (LPARAM) &hk); + + // 'Popup History' Hotkey + hk.pszName = "Popup History"; + hk.ptszDescription = LPGENT("Popup History"); + hk.pszService = MENUCOMMAND_HISTORY; + CallService(MS_HOTKEY_REGISTER, 0, (LPARAM) &hk); +} + +//menu +//Function which makes the initializations +static int ModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + //check if 'Icon Library Manager' and 'FontService' exist (load icon and font later) + if (!ServiceExists(MS_FONT_REGISTER) || !ServiceExists(MS_SKIN2_ADDICON)) { + LPTSTR msg = TranslateTS( + _T("This version of Popup Plus requires\r\n") + _T("'Icon Library Manager' and 'FontService'\r\n") + _T("modules.\r\n") + _T("\r\n") + _T("You always can download them at\r\n") + _T("http://addons.miranda-im.org/\r\n") + _T("\r\n") + _T("Do you want to visit Miranda IM homepage now?\r\n") ); + if (MessageBox(NULL, msg, _T("Popup Plus Error"), MB_YESNO|MB_ICONSTOP) == IDYES) + ShellExecute(NULL, _T("open"), _T("http://addons.miranda-im.org/"), NULL, NULL, SW_SHOWNORMAL); + return 0; + } + + //check if History++ is installed + gbHppInstalled = ServiceExists(MS_HPP_GETVERSION) && ServiceExists(MS_HPP_EG_WINDOW) && + (CallService(MS_HPP_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(1,5,0,112)); + //check if MText plugin is installed + if (MText.Register) { + htuText = MText.Register("PopUp Plus/Text", MTEXT_FANCY_DEFAULT); + htuTitle = MText.Register("PopUp Plus/Title",MTEXT_FANCY_DEFAULT); + } + else { + htuTitle = htuText = NULL; + } + // init meta contacts + INT_PTR ptr = CallService(MS_MC_GETPROTOCOLNAME, 0, 0); + if (ptr != CALLSERVICE_NOTFOUND) { + gszMetaProto = (LPCSTR)ptr; + } + + //check if OptionLoaded + if(!OptionLoaded){ + LoadOptions(); + } +/*/deprecatet stuff + notifyLink = ServiceExists(MS_NOTIFY_GETLINK) ? (MNOTIFYLINK *)CallService(MS_NOTIFY_GETLINK, 0, 0) : NULL; + LoadNotifyImp(); + hNotifyOptionsInitialize = HookEvent(ME_NOTIFY_OPT_INITIALISE, NotifyOptionsInitialize); + + HookEvent(ME_CONTACTSETTINGS_INITIALISE, ContactSettingsInitialise); +*/ + //Uninstalling purposes + if (ServiceExists("PluginSweeper/Add")) { + CallService("PluginSweeper/Add",(WPARAM)Translate(MODULNAME),(LPARAM)MODULNAME); + } + //load fonts / create hook + InitFonts(); + hFontsChanged = HookEvent(ME_FONT_RELOAD,FontsChanged); + + //load actions and notifications + LoadActions(); + LoadNotifications(); + //hook TopToolBar + hTTBLoaded = HookEvent(ME_TTB_MODULELOADED, TTBLoaded); + //Folder plugin support + LPTSTR pszPath = mir_a2t(MIRANDA_PATH "\\Skins\\PopUp"); + folderId = FoldersRegisterCustomPathT(MODULNAME_LONG, "Skins", pszPath); + mir_free(pszPath); + //load skin + skins.load(_T("dir")); + const PopupSkin *skin; + if (skin = skins.getSkin(PopUpOptions.SkinPack)) { + mir_free(PopUpOptions.SkinPack); + PopUpOptions.SkinPack = mir_tstrdup(skin->getName()); + skin->loadOpts(); + } + //init PopupEfects + PopupEfectsInitialize(); + //MessageAPI support + SrmmMenu_Load(); + //Hotkey + LoadHotkey(); + //Modern Toolbar support + if(ServiceExists(MS_TB_ADDBUTTON)) { + hTBLoaded = HookEvent(ME_TB_MODULELOADED, ToolbarSet); + ToolbarSet(0,0); + } + //Updater support + if(ServiceExists(MS_UPDATE_REGISTER)) registerUpdate(); + + gbPopupLoaded = TRUE; + return 0; +} + +//=== DllMain ===== +//DLL entry point, Required to store the instance handle +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst=hinstDLL; + return TRUE; +} + +//===== MirandaPluginInfo ===== +//Called by Miranda to get the information associated to this plugin. +//It only returns the PLUGININFOEX structure, without any test on the version +//@param mirandaVersion - The version of the application calling this function +MIRAPI PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + g_popup.MirVer = mirandaVersion; + +#if defined(_UNICODE) + pluginInfoEx.flags = UNICODE_AWARE; +#else + if (GetProcAddress(GetModuleHandle(_T("user32")), "DrawTextExW")) + pluginInfoEx.flags = 1; // dynamic UNICODE_AWARE +#endif + + return &pluginInfoEx; +} + +//Miranda PluginInterfaces +MIRAPI const MUUID *MirandaPluginInterfaces(void) +{ + static const MUUID interfaces[] = { MIID_POPUPS, MIID_LAST }; + return interfaces; +} + +//ME_SYSTEM_OKTOEXIT event +//called before the app goes into shutdown routine to make sure everyone is happy to exit +static int OkToExit(WPARAM wParam, LPARAM lParam) +{ + closing = TRUE; + StopPopupThread(); + return 0; +} + +//===== Load ===== +//Initializes the services provided and the link to those needed +//Called when the plugin is loaded into Miranda +MIRAPI int Load(PLUGINLINK *link) +{ + char ver[1024]; + pluginLink=link; + + g_popup.isOsUnicode = (GetVersion() & 0x80000000) == 0; + + CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM) sizeof(ver), (LPARAM) ver); + g_popup.isMirUnicode = strstr(ver, "Unicode") != NULL; + + hGetStatus = CreateServiceFunction(MS_POPUP_GETSTATUS, GetStatus); + + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, THREAD_SET_CONTEXT, FALSE, 0); + + mir_getLI (&li); + mir_getMMI (&mmi); + mir_getUTFI (&utfi); + mir_getMTI (&MText); + mir_getLP(&pluginInfoEx); + + #if defined(_DEBUG) + PopUpOptions.debug = DBGetContactSettingByte(NULL, MODULNAME, "debug", FALSE); + #else + PopUpOptions.debug = false; + #endif + LoadGDIPlus(); + + //Transparent and animation routines + OSVERSIONINFO osvi = { 0 }; + BOOL bResult = FALSE; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + bResult = GetVersionEx(&osvi); + +// MLU layer for ansi release +#if !defined(_UNICODE) + MySetLayeredWindowAttributes = 0; + MyUpdateLayeredWindow = 0; + MyAnimateWindow = 0; + MyDrawTextW = 0; + MyDrawTextExW = 0; + MySetWindowTextW = 0; + MySendMessageW = 0; + MyCallWindowProcW = 0; + MyCreateWindowExW = 0; + + MyGetMonitorInfo = 0; + MyMonitorFromWindow = 0; + + hUserDll = LoadLibrary(_T("user32.dll")); + if (hUserDll) { + MySetLayeredWindowAttributes = (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))GetProcAddress(hUserDll, "SetLayeredWindowAttributes"); + MyUpdateLayeredWindow = (BOOL (WINAPI *)(HWND, HDC, POINT *, SIZE *, HDC, POINT *, COLORREF, BLENDFUNCTION *, DWORD))GetProcAddress(hUserDll, "UpdateLayeredWindow"); + MyAnimateWindow = (BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(hUserDll,"AnimateWindow"); + MyDrawTextW = (int (WINAPI *)(HDC, LPCWSTR, int, LPRECT, UINT))GetProcAddress(hUserDll,"DrawTextW"); + MyDrawTextExW = (int (WINAPI*)(HDC,LPCWSTR,int,LPRECT,UINT,LPDRAWTEXTPARAMS))GetProcAddress(hUserDll,"DrawTextExW"); + MySetWindowTextW = (BOOL (WINAPI*)(HWND, LPCWSTR))GetProcAddress(hUserDll,"SetWindowTextW"); + MySendMessageW = (LRESULT (WINAPI *)(HWND, UINT, WPARAM, LPARAM))GetProcAddress(hUserDll,"SendMessageW"); + MyCallWindowProcW = (LRESULT (WINAPI *)(WNDPROC, HWND, UINT, WPARAM, LPARAM))GetProcAddress(hUserDll,"CallWindowProcW"); + MyCreateWindowExW = (HWND (WINAPI*)(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID))GetProcAddress(hUserDll,"CreateWindowExW"); + + if (LOWORD(GetVersion())!=4) { //Windows 98, ME, 2000, XP, and later support multimonitor configuration. + if (bResult) { + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { //2000 or XP + #ifdef UNICODE + MyGetMonitorInfo = (BOOL (WINAPI*)(HMONITOR,LPMONITORINFO))GetProcAddress(hUserDll,("GetMonitorInfoW")); + #else + MyGetMonitorInfo = (BOOL (WINAPI*)(HMONITOR,LPMONITORINFO))GetProcAddress(hUserDll,("GetMonitorInfoA")); + #endif //UNICODE + } else + { //98 or ME + // attempt to fix multimonitor on 9x + MyGetMonitorInfo = (BOOL (WINAPI*)(HMONITOR,LPMONITORINFO))GetProcAddress(hUserDll,("GetMonitorInfoA")); + if (!MyGetMonitorInfo) + MyGetMonitorInfo = (BOOL (WINAPI*)(HMONITOR,LPMONITORINFO))GetProcAddress(hUserDll,("GetMonitorInfo")); + } + } //There's no need for an else branch. + if (MyGetMonitorInfo) + MyMonitorFromWindow = (HMONITOR (WINAPI*)(HWND,DWORD))GetProcAddress(hUserDll, ("MonitorFromWindow")); + } + } + + hGdiDll = LoadLibrary(_T("gdi32.dll")); + if (hGdiDll) { + MyGetTextExtentPoint32W = (BOOL (WINAPI *)(HDC, LPCWSTR, int, LPSIZE))GetProcAddress(hGdiDll,"GetTextExtentPoint32W"); + } + else{ + MyGetTextExtentPoint32W = 0; + } + hMsimgDll = LoadLibrary(_T("msimg32.dll")); + MyAlphaBlend = 0; + MyTransparentBlt = 0; + if (hMsimgDll) + { + MyTransparentBlt = (BOOL (WINAPI *)(HDC, int, int, int, int, HDC, int, int, int, int, UINT)) + GetProcAddress(hMsimgDll, "TransparentBlt"); + MyAlphaBlend = (BOOL (WINAPI *)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION)) + GetProcAddress(hMsimgDll, "AlphaBlend"); + } +#endif + + hDwmapiDll = LoadLibrary(_T("dwmapi.dll")); + MyDwmEnableBlurBehindWindow = 0; + if (hDwmapiDll) { + MyDwmEnableBlurBehindWindow = (HRESULT (WINAPI *)(HWND, DWM_BLURBEHIND *)) + GetProcAddress(hDwmapiDll, "DwmEnableBlurBehindWindow"); + } + + PopupHistoryLoad(); + LoadPopupThread(); + if (!LoadPopupWnd2()) + { + MessageBox(0, TranslateTS( + _T("Error: I could not register the PopUp Window class.\r\n") + _T("The plugin will not operate.") + ), + _T(MODULNAME_LONG), MB_ICONSTOP|MB_OK); + return 0; //We couldn't register our Window Class, don't hook any event: the plugin will act as if it was disabled. + } + RegisterOptPrevBox(); + + // Register in DBEditor++ + DBVARIANT dbv; + if (DBGetContactSetting(NULL, "KnownModules", MODULNAME, &dbv)) + DBWriteContactSettingString(NULL, "KnownModules", pluginInfoEx.shortName, MODULNAME); + DBFreeVariant(&dbv); + + hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + hOptionsInitialize = HookEvent(ME_OPT_INITIALISE, OptionsInitialize); + hOkToExit = HookEvent(ME_SYSTEM_OKTOEXIT, OkToExit); +// hEventStatusChanged = HookEvent(ME_CLIST_STATUSMODECHANGE,StatusModeChanged); + + hbmNoAvatar = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_NOAVATAR)); + + if(!OptionLoaded){ + LoadOptions(); + } + + //Service Functions + for (int i = SIZEOF(popupServices); i--; ) + popupServices[i].handle = CreateServiceFunction(popupServices[i].name, popupServices[i].func); + + //load icons / create hook + InitIcons(); + hIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED,IconsChanged); + //add menu items + InitMenuItems(); + + return 0; +} + +//===== Unload ===== +//Prepare the plugin to stop +//Called by Miranda when it will exit or when the plugin gets deselected + +MIRAPI int Unload(void) +{ + int i; + + for (i = SIZEOF(popupServices); i--; ) + DestroyServiceFunction(popupServices[i].handle); + + SrmmMenu_Unload(); + + UnhookEvent(hOptionsInitialize); + UnhookEvent(hModulesLoaded); + UnhookEvent(hOkToExit); + UnhookEvent(hEventStatusChanged); + UnhookEvent(hIconsChanged); + UnhookEvent(hFontsChanged); + UnhookEvent(hTBLoaded); + + DestroyServiceFunction(hShowHistory); + DestroyServiceFunction(hTogglePopup); + DestroyServiceFunction(hGetStatus); + DestroyServiceFunction(hSquareFad); + + DeleteObject(fonts.title); + DeleteObject(fonts.clock); + DeleteObject(fonts.text); + DeleteObject(fonts.action); + DeleteObject(fonts.actionHover); + + DeleteObject(hbmNoAvatar); + + FreeLibrary(hDwmapiDll); + FreeLibrary(hUserDll); + FreeLibrary(hMsimgDll); +// FreeLibrary(hKernelDll); + FreeLibrary(hGdiDll); + + if(PopUpOptions.SkinPack) mir_free(PopUpOptions.SkinPack); + mir_free(PopUpOptions.Effect); + + OptAdv_UnregisterVfx(); + UnloadPopupThread(); + UnloadPopupWnd2(); + PopupHistoryUnload(); + + UnregisterClass (MAKEINTATOM(g_wndClass.cPopupWnd2),hInst); + UnregisterClassW(L"PopupEditBox",hInst); + UnregisterClass (MAKEINTATOM(g_wndClass.cPopupMenuHostWnd),hInst); + UnregisterClass (MAKEINTATOM(g_wndClass.cPopupThreadManagerWnd),hInst); + UnregisterClass (MAKEINTATOM(g_wndClass.cPopupPreviewBoxWndclass),hInst); + UnregisterClass (MAKEINTATOM(g_wndClass.cPopupPlusDlgBox),hInst); + + UnloadGDIPlus(); + + UnloadActions(); + + CloseHandle(hMainThread); + + return 0; +} diff --git a/Popup/src/notifications.cpp b/Popup/src/notifications.cpp new file mode 100644 index 0000000..89cf7d8 --- /dev/null +++ b/Popup/src/notifications.cpp @@ -0,0 +1,349 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/notifications.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +HANDLE g_hntfError, g_hntfWarning, g_hntfNotification; + +#define PopupNotificationData_SIGNATURE 0x11BEDA1A + + +int TreeDataSortFunc(const POPUPTREEDATA *p1, const POPUPTREEDATA *p2) +{ + if (int cmp = lstrcmp(p1->pszTreeRoot, p2->pszTreeRoot)) + return cmp; + return lstrcmp(p1->pszDescription, p2->pszDescription); + +} + +LIST gTreeData(20, TreeDataSortFunc); + +// interface +void LoadNotifications() +{ + POPUPNOTIFICATION notification = {0}; + notification.cbSize = sizeof(notification); + notification.actionCount = 0; + notification.lpActions = 0; + + lstrcpynA(notification.lpzGroup, "Misc", sizeof(notification.lpzName)); + lstrcpynA(notification.lpzName, "Warning", sizeof(notification.lpzName)); + notification.lchIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MB_WARN), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED); + notification.colorBack = RGB(210,210,150); + notification.colorText = RGB(0,0,0); + notification.iSeconds = 10; + g_hntfWarning = RegisterNotification(¬ification); + + lstrcpynA(notification.lpzGroup, "Misc", sizeof(notification.lpzName)); + lstrcpynA(notification.lpzName, "Notification", sizeof(notification.lpzName)); + notification.lchIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MB_INFO), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED); + notification.colorBack = RGB(230,230,230); + notification.colorText = RGB(0,0,0); + notification.iSeconds = 7; + g_hntfNotification = RegisterNotification(¬ification); + + lstrcpynA(notification.lpzGroup, "Misc", sizeof(notification.lpzName)); + lstrcpynA(notification.lpzName, "Error", sizeof(notification.lpzName)); + notification.lchIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MB_STOP), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED); + notification.colorBack = RGB(191,0,0); + notification.colorText = RGB(255,245,225); + notification.iSeconds = -1; + g_hntfError = RegisterNotification(¬ification); +} + +void UnloadTreeData() +{ + for (int i = 0; i < gTreeData.getCount(); ++i) { + if(gTreeData[i]->typ == 2) { + mir_free(gTreeData[i]->pupClass.pszName); + mir_free(gTreeData[i]->pupClass.pszDescription); + } + mir_free(gTreeData[i]->pszTreeRoot); + mir_free(gTreeData[i]->pszDescription); + } + gTreeData.destroy(); +} + +void SaveNotificationSettings(POPUPTREEDATA *ptd, char* szModul) +{ + if(ptd->typ == 1) { + char setting[2*MAXMODULELABELLENGTH]; + + mir_snprintf(setting, sizeof(setting), "{%s/%s}Timeout", + ptd->notification.lpzGroup, + ptd->notification.lpzName); + DBWriteContactSettingWord(NULL, szModul, setting, ptd->notification.iSeconds); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}enabled", + ptd->notification.lpzGroup, + ptd->notification.lpzName); + DBWriteContactSettingByte(NULL, szModul, setting, ptd->enabled); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}TimeoutVal", + ptd->notification.lpzGroup, + ptd->notification.lpzName); + DBWriteContactSettingWord(NULL, szModul, setting, ptd->timeoutValue); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}disableWhen", + ptd->notification.lpzGroup, + ptd->notification.lpzName); + DBWriteContactSettingByte(NULL, szModul, setting, ptd->disableWhen); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}leftAction", + ptd->notification.lpzGroup, + ptd->notification.lpzName); + DBWriteContactSettingString(NULL, szModul, setting, ptd->leftAction); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}rightAction", + ptd->notification.lpzGroup, + ptd->notification.lpzName); + DBWriteContactSettingString(NULL, szModul, setting, ptd->rightAction); + + for (int i = 0; i < ptd->notification.actionCount; ++i) + { + if (!lstrcmpA(ptd->leftAction, ptd->notification.lpActions[i].lpzTitle)) + { + DBCONTACTWRITESETTING dbcws = {0}; + dbcws.szModule = ptd->notification.lpActions[i].lpzLModule; + dbcws.szModule = ptd->notification.lpActions[i].lpzLSetting; + dbcws.value = ptd->notification.lpActions[i].dbvLData; + CallService(MS_DB_CONTACT_WRITESETTING, 0, (LPARAM)&dbcws); + } + if (!lstrcmpA(ptd->rightAction, ptd->notification.lpActions[i].lpzTitle)) + { + DBCONTACTWRITESETTING dbcws = {0}; + dbcws.szModule = ptd->notification.lpActions[i].lpzRModule; + dbcws.szModule = ptd->notification.lpActions[i].lpzRSetting; + dbcws.value = ptd->notification.lpActions[i].dbvRData; + CallService(MS_DB_CONTACT_WRITESETTING, 0, (LPARAM)&dbcws); + } + } + } +} + +void LoadNotificationSettings(POPUPTREEDATA *ptd, char* szModul) +{ + if(ptd->typ == 1) { + char setting[2*MAXMODULELABELLENGTH]; + char *szTmp = NULL; + + mir_snprintf(setting, sizeof(setting), "{%s/%s}enabled", ptd->notification.lpzGroup, ptd->notification.lpzName); + ptd->enabled = + (signed char)DBGetContactSettingByte(NULL, szModul, setting, TRUE); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}Timeout", ptd->notification.lpzGroup, ptd->notification.lpzName); + ptd->notification.iSeconds = + (signed char)DBGetContactSettingWord(NULL, szModul, setting, ptd->notification.iSeconds); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}TimeoutVal", ptd->notification.lpzGroup, ptd->notification.lpzName); + ptd->timeoutValue = + (signed char)DBGetContactSettingWord(NULL, szModul, setting, + ptd->notification.iSeconds ? ptd->notification.iSeconds : 0); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}disableWhen", ptd->notification.lpzGroup, ptd->notification.lpzName); + ptd->disableWhen = + DBGetContactSettingByte(NULL, szModul, setting, 0); + + mir_snprintf(setting, sizeof(setting), "{%s/%s}leftAction", ptd->notification.lpzGroup, ptd->notification.lpzName); + szTmp = DBGetContactSettingString(NULL, szModul, setting, ptd->notification.lpzLAction); + lstrcpynA(ptd->leftAction, szTmp, sizeof(ptd->leftAction)); + mir_free(szTmp); szTmp = NULL; + + mir_snprintf(setting, sizeof(setting), "{%s/%s}rightAction", ptd->notification.lpzGroup, ptd->notification.lpzName); + szTmp = DBGetContactSettingString(NULL, szModul, setting, ptd->notification.lpzRAction); + lstrcpynA(ptd->rightAction, szTmp, sizeof(ptd->rightAction)); + mir_free(szTmp); szTmp = NULL; + } +} + +HANDLE RegisterNotification(POPUPNOTIFICATION *notification) +{ + POPUPTREEDATA *ptd = (POPUPTREEDATA *)mir_alloc(sizeof(POPUPTREEDATA)); + ptd->signature = PopupNotificationData_SIGNATURE; + ptd->typ = 1; + ptd->pszTreeRoot = mir_a2t(notification->lpzGroup); + ptd->pszDescription = mir_a2t(notification->lpzName); + ptd->notification = *notification; + if (!ptd->notification.lpzLAction) ptd->notification.lpzLAction = POPUP_ACTION_NOTHING; + if (!ptd->notification.lpzRAction) ptd->notification.lpzRAction = POPUP_ACTION_DISMISS; + LoadNotificationSettings(ptd, "PopUpNotifications"); + + // ugly hack to make reset always possible + SaveNotificationSettings(ptd,"PopUpNotifications"); + + FontID fontid = {0}; + fontid.cbSize = sizeof(fontid); + mir_snprintf(fontid.group, sizeof(fontid.group), "%s/%s", PU_FNT_AND_COLOR, notification->lpzGroup); + lstrcpyA(fontid.dbSettingsGroup, "PopUpNotifications"); + fontid.flags = FIDF_DEFAULTVALID; + fontid.deffontsettings.charset = DEFAULT_CHARSET; + fontid.deffontsettings.colour = ptd->notification.colorText; + fontid.deffontsettings.size = -11; + lstrcpyA(fontid.deffontsettings.szFace, "MS Shell Dlg"); + fontid.deffontsettings.style = 0; + mir_snprintf(fontid.name, SIZEOF(fontid.name), "%s (colors only)", notification->lpzName); + mir_snprintf(fontid.prefix, SIZEOF(fontid.prefix), "{%s/%s}text", notification->lpzGroup, notification->lpzName); + fontid.deffontsettings.style = 0; + CallService(MS_FONT_REGISTER, (WPARAM)&fontid, 0); + + ColourID colourid = {0}; + colourid.cbSize = sizeof(colourid); + mir_snprintf(colourid.group, sizeof(colourid.group), "%s/%s", PU_FNT_AND_COLOR, notification->lpzGroup); + lstrcpyA(colourid.dbSettingsGroup, "PopUpNotifications"); + mir_snprintf(colourid.name, SIZEOF(colourid.name), "%s (colors only)", notification->lpzName); + mir_snprintf(colourid.setting, SIZEOF(colourid.setting), "{%s/%s}backColor", notification->lpzGroup, notification->lpzName); + colourid.defcolour = ptd->notification.colorBack; + CallService(MS_COLOUR_REGISTER, (WPARAM)&colourid, 0); + + char section[MAXMODULELABELLENGTH], setting[MAXMODULELABELLENGTH]; + mir_snprintf(section, sizeof(section), "PopUps/%s", notification->lpzGroup); + mir_snprintf(setting, sizeof(setting), "%s_%s_%s", MODULNAME, notification->lpzGroup, notification->lpzName); + + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(sid); + sid.pszSection = section; + sid.cx = sid.cy = 16; + sid.pszName = setting; + sid.pszDescription = notification->lpzName; + sid.hDefaultIcon = notification->lchIcon; + CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); + + gTreeData.insert(ptd); + return (HANDLE)ptd; +} + +HANDLE FindTreeData(LPTSTR group, LPTSTR name, BYTE typ) +{ + for(int i = 0; i < gTreeData.getCount(); i++) { + if( gTreeData[i]->typ == typ && + (!group || (_tcscmp(gTreeData[i]->pszTreeRoot, group) == 0)) && + (!name || (_tcscmp(gTreeData[i]->pszDescription, name) == 0)) ) + { + return gTreeData[i]; + } + } + return NULL; +} + +void FillNotificationData(POPUPDATA2 *ppd, DWORD *disableWhen) +{ + if (!IsValidNotification(ppd->lchNotification)) { + *disableWhen = 0; + return; + } + + POPUPTREEDATA *ptd = (POPUPTREEDATA *)ppd->lchNotification; + + ppd->iSeconds = ptd->timeoutValue; + *disableWhen = ptd->enabled ? ptd->disableWhen : 0xFFFFFFFF; + + LOGFONTA lf; //dummy to make FS happy (use LOGFONTA coz we use MS_FONT_GET) + FontID fontid = {0}; //use ansi version of fontID coz POPUPNOTIFICATION use char + fontid.cbSize = sizeof(fontid); + mir_snprintf(fontid.group, sizeof(fontid.group), "%s/%s", PU_FNT_AND_COLOR, ptd->notification.lpzGroup); + mir_snprintf(fontid.name, SIZEOF(fontid.name), "%s (colors only)", ptd->notification.lpzName); + ppd->colorText = (COLORREF)CallService(MS_FONT_GET, (WPARAM)&fontid, (LPARAM)&lf); + + ColourID colourid = {0}; //use ansi version of ColourID coz POPUPNOTIFICATION use char + colourid.cbSize = sizeof(colourid); + mir_snprintf(colourid.group, sizeof(colourid.group), "%s/%s", PU_FNT_AND_COLOR, ptd->notification.lpzGroup); + mir_snprintf(colourid.name, SIZEOF(colourid.name), "%s (colors only)", ptd->notification.lpzName); + ppd->colorBack = (COLORREF)CallService(MS_COLOUR_GET, (WPARAM)&colourid, 0); + + char setting[MAXMODULELABELLENGTH]; + mir_snprintf(setting, sizeof(setting), "%s_%s_%s", MODULNAME, ptd->notification.lpzGroup, ptd->notification.lpzName); + ppd->lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)setting); +} + +bool IsValidNotification(HANDLE hNotification) +{ + if (!hNotification) return false; + + bool res = false; + __try + { + if (((POPUPTREEDATA *)hNotification)->signature == PopupNotificationData_SIGNATURE) + res = true; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + res = false; + } + return res; +} + +bool PerformAction(HANDLE hNotification, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (!IsValidNotification(hNotification)) + return false; + + POPUPTREEDATA *ptd = (POPUPTREEDATA *)hNotification; + char *lpzAction = NULL; + switch (message) + { + case WM_LBUTTONUP: + case WM_COMMAND: + lpzAction = ptd->leftAction; + break; + + case WM_RBUTTONUP: + case WM_CONTEXTMENU: + lpzAction = ptd->rightAction; + break; + + default: + return false; + } + + if (!lstrcmpA(lpzAction, POPUP_ACTION_NOTHING)) + return true; + + if (!lstrcmpA(lpzAction, POPUP_ACTION_DISMISS)) + { + PUDeletePopUp(hwnd); + return true; + } + + for (int i = 0; i < ptd->notification.actionCount; ++i) + { + if (!(ptd->notification.lpActions[i].dwFlags&PNAF_CALLBACK)) + continue; + if (lstrcmpA(ptd->notification.lpActions[i].lpzTitle, lpzAction)) + continue; + + ptd->notification.lpActions[i].pfnCallback(hwnd, message, wparam, lparam, + ptd->notification.lpActions[i].dwCookie); + return true; + } + + return false; +} diff --git a/Popup/src/notifications.h b/Popup/src/notifications.h new file mode 100644 index 0000000..24e6a63 --- /dev/null +++ b/Popup/src/notifications.h @@ -0,0 +1,73 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/notifications.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __notifications_h__ +#define __notifications_h__ + +struct POPUPTREEDATA +{ + int cbSize; + DWORD signature; + LPTSTR pszTreeRoot; + LPTSTR pszDescription; + BYTE typ; + union { + POPUPNOTIFICATION notification; + POPUPCLASS pupClass; + }; + BYTE enabled; + DWORD disableWhen; + int timeoutValue; + char leftAction[MAXMODULELABELLENGTH]; + char rightAction[MAXMODULELABELLENGTH]; + COLORREF colorBack; //realy needet ?? + COLORREF colorText; //realy needet ?? +}; + +extern LIST gTreeData; +extern HANDLE g_hntfError, g_hntfWarning, g_hntfNotification; + +int TreeDataSortFunc(const POPUPTREEDATA *p1, const POPUPTREEDATA *p2); +HANDLE FindTreeData(LPTSTR group, LPTSTR name, BYTE typ); +void UnloadTreeData(); + +void LoadNotifications(); +HANDLE RegisterNotification(POPUPNOTIFICATION *notification); + +void FillNotificationData(POPUPDATA2 *ppd, DWORD *disableWhen); +bool PerformAction(HANDLE hNotification, HWND hwnd, UINT message, WPARAM wparal, LPARAM lparam); +bool IsValidNotification(HANDLE hNotification); + +void LoadNotificationSettings(POPUPTREEDATA *ptd, char* szModul); +void SaveNotificationSettings(POPUPTREEDATA *ptd, char* szModul); + +#endif // __notifications_h__ diff --git a/Popup/src/opt_adv.cpp b/Popup/src/opt_adv.cpp new file mode 100644 index 0000000..f8fcd5f --- /dev/null +++ b/Popup/src/opt_adv.cpp @@ -0,0 +1,762 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_adv.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +HWND hwndBox = NULL; + +INT_PTR CALLBACK AvatarTrackBarWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK AlphaTrackBarWndProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//effekt name for drop down box +LIST g_lstPopupVfx(5, _tcsicmp); +void OptAdv_RegisterVfx(char *name) { + g_lstPopupVfx.insert(mir_a2t(name)); +} + +void OptAdv_UnregisterVfx() { + for (int i = 0; i < g_lstPopupVfx.getCount(); ++i) + mir_free(g_lstPopupVfx[i]); + g_lstPopupVfx.destroy(); +} + +//Main Dialog Proc +void LoadOption_AdvOpts() { + //History + PopUpOptions.EnableHistory = DBGetContactSettingByte (NULL,MODULNAME, "EnableHistory", TRUE); + PopUpOptions.HistorySize = DBGetContactSettingWord (NULL,MODULNAME, "HistorySize", SETTING_HISTORYSIZE_DEFAULT); + PopUpOptions.UseHppHistoryLog = DBGetContactSettingByte (NULL,MODULNAME, "UseHppHistoryLog", TRUE); + //Avatars + PopUpOptions.avatarBorders = DBGetContactSettingByte (NULL,MODULNAME, "AvatarBorders", TRUE); + PopUpOptions.avatarPNGBorders = DBGetContactSettingByte (NULL,MODULNAME, "AvatarPNGBorders", FALSE); + PopUpOptions.avatarRadius = DBGetContactSettingByte (NULL,MODULNAME, "AvatarRadius", 2); + PopUpOptions.avatarSize = DBGetContactSettingWord (NULL,MODULNAME, "AvatarSize", SETTING_AVTSIZE_DEFAULT); + PopUpOptions.EnableAvatarUpdates = DBGetContactSettingByte (NULL,MODULNAME, "EnableAvatarUpdates", FALSE); + //Monitor + PopUpOptions.Monitor = DBGetContactSettingByte (NULL,MODULNAME, "Monitor", SETTING_MONITOR_DEFAULT); + //Transparency + PopUpOptions.Enable9xTransparency = DBGetContactSettingByte (NULL,MODULNAME, "EnableRegionTransparency", TRUE); + PopUpOptions.UseTransparency = DBGetContactSettingByte (NULL,MODULNAME, "UseTransparency", TRUE); + PopUpOptions.Alpha = DBGetContactSettingByte (NULL,MODULNAME, "Alpha", SETTING_ALPHA_DEFAULT); + PopUpOptions.OpaqueOnHover = DBGetContactSettingByte (NULL,MODULNAME, "OpaqueOnHover", TRUE); + //Effects + PopUpOptions.UseAnimations = DBGetContactSettingByte (NULL,MODULNAME, "UseAnimations", TRUE); + PopUpOptions.UseEffect = DBGetContactSettingByte (NULL,MODULNAME, "Fade", TRUE); + PopUpOptions.Effect = (LPTSTR)DBGetContactSettingStringX(NULL,MODULNAME, "Effect", "", DBVT_TCHAR); + PopUpOptions.FadeIn = DBGetContactSettingDword(NULL,MODULNAME, "FadeInTime", SETTING_FADEINTIME_DEFAULT); + PopUpOptions.FadeOut = DBGetContactSettingDword(NULL,MODULNAME, "FadeOutTime",SETTING_FADEOUTTIME_DEFAULT); + //other old stuff + PopUpOptions.MaxPopups = DBGetContactSettingWord (NULL,MODULNAME, "MaxPopups", 20); +} + +INT_PTR CALLBACK DlgProcPopUpAdvOpts(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + TCHAR tstr[64]; + static bool bDlgInit = false; //some controls send WM_COMMAND before or during WM_INITDIALOG + + switch (msg) { + case WM_INITDIALOG: { + HWND hCtrl = NULL; + + //Create preview box: + { + hwndBox = CreateWindowEx( + WS_EX_TOOLWINDOW|WS_EX_TOPMOST, // dwStyleEx + _T(BOXPREVIEW_WNDCLASS), // Class name + NULL, // Title + DS_SETFONT|DS_FIXEDSYS|WS_POPUP, // dwStyle + CW_USEDEFAULT, // x + CW_USEDEFAULT, // y + CW_USEDEFAULT, // Width + CW_USEDEFAULT, // Height + HWND_DESKTOP, // Parent + NULL, // menu handle + hInst, // Instance + (LPVOID)0); + ShowWindow(hwndBox, SW_HIDE); + } + //Group: History + { + CheckDlgButton(hwnd, IDC_ENABLE_HISTORY, PopUpOptions.EnableHistory); + SetDlgItemInt (hwnd, IDC_HISTORYSIZE, PopUpOptions.HistorySize, FALSE); + CheckDlgButton(hwnd, IDC_HPPLOG, PopUpOptions.UseHppHistoryLog); + + hCtrl = GetDlgItem(hwnd, IDC_SHOWHISTORY); + SendMessage(hCtrl, BUTTONSETASFLATBTN, 0, 0); + SendMessage(hCtrl, BUTTONADDTOOLTIP, (WPARAM)Translate("Popup History"), 0); + SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_HISTORY,0)); + + EnableWindow(GetDlgItem(hwnd, IDC_HISTORY_STATIC1), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_HISTORYSIZE), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_HISTORY_STATIC2), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_SHOWHISTORY), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_HPPLOG), PopUpOptions.EnableHistory && gbHppInstalled); + } + //Group: Avatars + { + //Borders + CheckDlgButton(hwnd, IDC_AVT_BORDER, PopUpOptions.avatarBorders); + CheckDlgButton(hwnd, IDC_AVT_PNGBORDER, PopUpOptions.avatarPNGBorders); + EnableWindow(GetDlgItem(hwnd, IDC_AVT_PNGBORDER), PopUpOptions.avatarBorders); + //Radius + SetDlgItemInt(hwnd, IDC_AVT_RADIUS, PopUpOptions.avatarRadius, FALSE); + SendDlgItemMessage(hwnd, IDC_AVT_RADIUS_SPIN,UDM_SETRANGE, 0, (LPARAM)MAKELONG((PopUpOptions.avatarSize / 2),0)); + //Size + SetWindowLongPtr(GetDlgItem(hwnd, IDC_AVT_SIZE_SLIDE), GWLP_USERDATA, GetWindowLongPtr(GetDlgItem(hwnd, IDC_AVT_SIZE_SLIDE), GWLP_WNDPROC)); + SetWindowLongPtr(GetDlgItem(hwnd, IDC_AVT_SIZE_SLIDE), GWLP_WNDPROC, (LONG_PTR)AvatarTrackBarWndProc); + + SendDlgItemMessage(hwnd, IDC_AVT_SIZE_SLIDE, TBM_SETRANGE,FALSE, + MAKELONG(SETTING_AVTSIZE_MIN, SETTING_AVTSIZE_MAX) ); + SendDlgItemMessage(hwnd, IDC_AVT_SIZE_SLIDE, TBM_SETPOS, TRUE, + max(PopUpOptions.avatarSize, SETTING_AVTSIZE_MIN)); + SetDlgItemInt(hwnd, IDC_AVT_SIZE, PopUpOptions.avatarSize, FALSE); + //Request avatars + CheckDlgButton(hwnd, IDC_AVT_REQUEST, PopUpOptions.EnableAvatarUpdates); + } + //Group: Monitor + { + BOOL bMonitor = 0; +#if defined(_UNICODE) + bMonitor = GetSystemMetrics(SM_CMONITORS)>1; +#else + if(MyGetMonitorInfo) { + //os support multimonitor, check if monitor > 1 + bMonitor = GetSystemMetrics(SM_CMONITORS)>1; + } +#endif + CheckDlgButton(hwnd, IDC_MIRANDAWND, bMonitor ? (PopUpOptions.Monitor == MN_MIRANDA) : TRUE); + CheckDlgButton(hwnd, IDC_ACTIVEWND, bMonitor ? (PopUpOptions.Monitor == MN_ACTIVE) : FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_GRP_MULTIMONITOR), bMonitor); + EnableWindow(GetDlgItem(hwnd, IDC_MULTIMONITOR_DESC), bMonitor); + EnableWindow(GetDlgItem(hwnd, IDC_MIRANDAWND), bMonitor); + EnableWindow(GetDlgItem(hwnd, IDC_ACTIVEWND), bMonitor); + } + //Group: Transparency + { + //9x/ME + CheckDlgButton(hwnd, IDC_TRANS_9X, PopUpOptions.Enable9xTransparency); + //EnableWindow(GetDlgItem(hwnd, IDC_TRANS_9X), !IsWinVer2000Plus()); + ShowWindow(GetDlgItem(hwnd, IDC_TRANS_9X), IsWinVer2000Plus() ? SW_HIDE : SW_SHOW); + //win2k+ + CheckDlgButton(hwnd, IDC_TRANS, PopUpOptions.UseTransparency); + SendDlgItemMessage(hwnd, IDC_TRANS_SLIDER, TBM_SETRANGE, FALSE, MAKELONG(1,255)); + SendDlgItemMessage(hwnd, IDC_TRANS_SLIDER, TBM_SETPOS, TRUE, PopUpOptions.Alpha); + SetWindowLongPtr(GetDlgItem(hwnd, IDC_TRANS_SLIDER), GWLP_USERDATA, GetWindowLongPtr(GetDlgItem(hwnd, IDC_TRANS_SLIDER), GWLP_WNDPROC)); + SetWindowLongPtr(GetDlgItem(hwnd, IDC_TRANS_SLIDER), GWLP_WNDPROC, (LONG_PTR)AlphaTrackBarWndProc); + wsprintf(tstr, _T("%d%%"), Byte2Percentile(PopUpOptions.Alpha)); + SetDlgItemText(hwnd, IDC_TRANS_PERCENT, tstr); + CheckDlgButton(hwnd, IDC_TRANS_OPAQUEONHOVER, PopUpOptions.OpaqueOnHover); + { +#if defined(_UNICODE) + BOOL how = TRUE; +#else + BOOL how = (BOOL)(MySetLayeredWindowAttributes); +#endif + EnableWindow(GetDlgItem(hwnd, IDC_TRANS) ,how); + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_TXT1) ,how && PopUpOptions.UseTransparency); + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_SLIDER) ,how && PopUpOptions.UseTransparency); + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_PERCENT) ,how && PopUpOptions.UseTransparency); + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_OPAQUEONHOVER) ,how && PopUpOptions.UseTransparency); + } + ShowWindow(GetDlgItem(hwnd, IDC_TRANS), IsWinVer2000Plus() ? SW_SHOW : SW_HIDE); + } + //Group: Effects + { + //Use Animations + CheckDlgButton(hwnd, IDC_USEANIMATIONS, PopUpOptions.UseAnimations); + //Fade + SetDlgItemInt (hwnd, IDC_FADEIN, PopUpOptions.FadeIn, FALSE); + SetDlgItemInt (hwnd, IDC_FADEOUT,PopUpOptions.FadeOut,FALSE); + UDACCEL aAccels[] = {{0,50},{1,100},{3,500}}; + SendDlgItemMessage(hwnd, IDC_FADEIN_SPIN, UDM_SETRANGE, 0, (LPARAM)MAKELONG(SETTING_FADEINTIME_MAX, SETTING_FADEINTIME_MIN)); + SendDlgItemMessage(hwnd, IDC_FADEIN_SPIN, UDM_SETACCEL, (WPARAM)SIZEOF(aAccels), (LPARAM)&aAccels); + SendDlgItemMessage(hwnd, IDC_FADEOUT_SPIN,UDM_SETRANGE, 0, (LPARAM)MAKELONG(SETTING_FADEOUTTIME_MAX,SETTING_FADEOUTTIME_MIN)); + SendDlgItemMessage(hwnd, IDC_FADEOUT_SPIN,UDM_SETACCEL, (WPARAM)SIZEOF(aAccels), (LPARAM)&aAccels); + + BOOL how = PopUpOptions.UseAnimations || PopUpOptions.UseEffect; + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_TXT1), how); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN), how); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_SPIN), how); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_TXT2), how); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_TXT1), how); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT), how); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_SPIN), how); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_TXT2), how); + //effects drop down + { + DWORD dwItem, dwActiveItem = 0; + +#if defined(_UNICODE) + BOOL how = TRUE; +#else + BOOL how = (BOOL)(MySetLayeredWindowAttributes) /*&& !PopUpOptions.UseAnimations*/; +#endif + EnableWindow(GetDlgItem(hwnd, IDC_EFFECT), how); + EnableWindow(GetDlgItem(hwnd, IDC_EFFECT_TXT), how); + + hCtrl = GetDlgItem(hwnd, IDC_EFFECT); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("No effect")) ,-2); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("Fade in/out")) ,-1); + dwActiveItem = (DWORD)PopUpOptions.UseEffect; + for (int i = 0; i < g_lstPopupVfx.getCount(); ++i) { + dwItem = ComboBox_AddString(hCtrl, TranslateTS(g_lstPopupVfx[i])); + ComboBox_SetItemData(hCtrl, dwItem, i); + if (PopUpOptions.UseEffect && !lstrcmp(g_lstPopupVfx[i], PopUpOptions.Effect)) + dwActiveItem = dwItem; + } + SendDlgItemMessage(hwnd, IDC_EFFECT, CB_SETCURSEL, dwActiveItem, 0); + } + } + + //later check stuff + { + SetDlgItemInt(hwnd, IDC_MAXPOPUPS, PopUpOptions.MaxPopups, FALSE); + } + + TranslateDialogDefault(hwnd); //do it on end of WM_INITDIALOG + bDlgInit = true; + }//end WM_INITDIALOG + return TRUE; + case WM_HSCROLL: { + UINT idCtrl = GetDlgCtrlID((HWND)lParam); + switch (idCtrl) { + case IDC_AVT_SIZE_SLIDE: + { + PopUpOptions.avatarSize = SendDlgItemMessage(hwnd,IDC_AVT_SIZE_SLIDE, TBM_GETPOS,0,0); + SetDlgItemInt(hwnd, IDC_AVT_SIZE ,PopUpOptions.avatarSize,FALSE); + SendDlgItemMessage(hwnd, IDC_AVT_RADIUS_SPIN,UDM_SETRANGE, 0, (LPARAM)MAKELONG((PopUpOptions.avatarSize / 2),0)); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_TRANS_SLIDER: + { + PopUpOptions.Alpha = (BYTE)SendDlgItemMessage(hwnd,IDC_TRANS_SLIDER, TBM_GETPOS, 0,0); + wsprintf(tstr, TranslateT("%d%%"), Byte2Percentile(PopUpOptions.Alpha)); + SetDlgItemText(hwnd, IDC_TRANS_PERCENT, tstr); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + default: + break; + }// end switch idCtrl + }//end WM_HSCROLL + break; + case WM_COMMAND: { + UINT idCtrl = LOWORD(wParam); + switch (HIWORD(wParam)) { + case BN_CLICKED: //Button controls + switch(idCtrl) { + case IDC_ENABLE_HISTORY: + { + PopUpOptions.EnableHistory = !PopUpOptions.EnableHistory; + EnableWindow(GetDlgItem(hwnd, IDC_HISTORY_STATIC1), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_HISTORYSIZE), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_HISTORY_STATIC2), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_SHOWHISTORY), PopUpOptions.EnableHistory); + EnableWindow(GetDlgItem(hwnd, IDC_HPPLOG), PopUpOptions.EnableHistory && gbHppInstalled); + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_SHOWHISTORY: + { + PopupHistoryShow(); + } + break; + case IDC_HPPLOG: + { + PopUpOptions.UseHppHistoryLog = !PopUpOptions.UseHppHistoryLog; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_AVT_BORDER: + { + PopUpOptions.avatarBorders = !PopUpOptions.avatarBorders; + EnableWindow(GetDlgItem(hwnd, IDC_AVT_PNGBORDER), PopUpOptions.avatarBorders); + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_AVT_PNGBORDER: + { + PopUpOptions.avatarPNGBorders = !PopUpOptions.avatarPNGBorders; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_AVT_REQUEST: + { + PopUpOptions.EnableAvatarUpdates = !PopUpOptions.EnableAvatarUpdates; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_MIRANDAWND: + { + PopUpOptions.Monitor = MN_MIRANDA; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_ACTIVEWND: + { + PopUpOptions.Monitor = MN_ACTIVE; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_TRANS_9X: + { + PopUpOptions.Enable9xTransparency = !PopUpOptions.Enable9xTransparency; + SendMessage(GetParent(hwnd), PSM_CHANGED,0,0); + } + break; + case IDC_TRANS: + { + PopUpOptions.UseTransparency = !PopUpOptions.UseTransparency; +#if defined(_UNICODE) + BOOL how = TRUE; +#else + BOOL how = (BOOL)(MySetLayeredWindowAttributes); +#endif + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_TXT1) ,how && PopUpOptions.UseTransparency); + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_SLIDER) ,how && PopUpOptions.UseTransparency); + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_PERCENT) ,how && PopUpOptions.UseTransparency); + EnableWindow(GetDlgItem(hwnd, IDC_TRANS_OPAQUEONHOVER) ,how && PopUpOptions.UseTransparency); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_TRANS_OPAQUEONHOVER: + { + PopUpOptions.OpaqueOnHover = !PopUpOptions.OpaqueOnHover; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_USEANIMATIONS: + { + PopUpOptions.UseAnimations = !PopUpOptions.UseAnimations; + BOOL enable = PopUpOptions.UseAnimations || PopUpOptions.UseEffect; + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_TXT1), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_SPIN), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_TXT2), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_TXT1), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_SPIN), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_TXT2), enable); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_PREVIEW: + { + PopUpPreview(); + } + break; + default: + break; + } + break; + case CBN_SELCHANGE: //ComboBox controls + switch(idCtrl) { + //lParam = Handle to the control + case IDC_EFFECT: + { + int iEffect = ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); + PopUpOptions.UseEffect = (iEffect != -2) ? TRUE : FALSE; + mir_free(PopUpOptions.Effect); + PopUpOptions.Effect = mir_tstrdup((iEffect >= 0) ? g_lstPopupVfx[iEffect] : _T("")); + + BOOL enable = PopUpOptions.UseAnimations || PopUpOptions.UseEffect; + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_TXT1), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_SPIN), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEIN_TXT2), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_TXT1), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_SPIN), enable); + EnableWindow(GetDlgItem(hwnd, IDC_FADEOUT_TXT2), enable); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + default: + break; + } + break; + case EN_CHANGE: //Edit controls change + if(!bDlgInit) break; + switch(idCtrl) { + //lParam = Handle to the control + case IDC_MAXPOPUPS: + { + int maxPop = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if(maxPop > 0){ + PopUpOptions.MaxPopups = maxPop; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + case IDC_HISTORYSIZE: + { + int histSize = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if( histSize > 0 && + histSize <= SETTING_HISTORYSIZE_MAX){ + PopUpOptions.HistorySize = histSize; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + case IDC_AVT_RADIUS: + { + int avtRadius = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if( avtRadius <= SETTING_AVTSIZE_MAX / 2 ){ + PopUpOptions.avatarRadius = avtRadius; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + case IDC_FADEIN: + { + int fadeIn = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if( fadeIn >= SETTING_FADEINTIME_MIN && + fadeIn <= SETTING_FADEINTIME_MAX ){ + PopUpOptions.FadeIn = fadeIn; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + case IDC_FADEOUT: + { + int fadeOut = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if( fadeOut >= SETTING_FADEOUTTIME_MIN && + fadeOut <= SETTING_FADEOUTTIME_MAX){ + PopUpOptions.FadeOut = fadeOut; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + default: + break; + }//end switch(idCtrl) + break; + case EN_KILLFOCUS: //Edit controls lost fokus + switch(idCtrl) { + //lParam = Handle to the control + case IDC_MAXPOPUPS: + { + int maxPop = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if(maxPop <= 0) + PopUpOptions.MaxPopups = 20; + if(maxPop != PopUpOptions.MaxPopups) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.MaxPopups, FALSE); + //ErrorMSG(1); + SetFocus((HWND)lParam); + } + } + break; + case IDC_HISTORYSIZE: + { + int histSize = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if(histSize <= 0) + PopUpOptions.HistorySize = SETTING_HISTORYSIZE_DEFAULT; + else if(histSize > SETTING_HISTORYSIZE_MAX) + PopUpOptions.HistorySize = SETTING_HISTORYSIZE_MAX; + if(histSize != PopUpOptions.HistorySize) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.HistorySize, FALSE); + ErrorMSG(1, SETTING_HISTORYSIZE_MAX); + SetFocus((HWND)lParam); + } + } + break; + case IDC_AVT_RADIUS: + { + int avtRadius = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if(avtRadius > SETTING_AVTSIZE_MAX / 2) + PopUpOptions.avatarRadius = SETTING_AVTSIZE_MAX / 2; + if(avtRadius != PopUpOptions.avatarRadius) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.avatarRadius, FALSE); + ErrorMSG(0, SETTING_AVTSIZE_MAX / 2); + SetFocus((HWND)lParam); + } + } + break; + case IDC_FADEIN: + { + int fade = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if(fade < SETTING_FADEINTIME_MIN) + PopUpOptions.FadeIn = SETTING_FADEINTIME_MIN; + else if(fade > SETTING_FADEINTIME_MAX) + PopUpOptions.FadeIn = SETTING_FADEINTIME_MAX; + if(fade != PopUpOptions.FadeIn) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.FadeIn, FALSE); + ErrorMSG(SETTING_FADEINTIME_MIN, SETTING_FADEINTIME_MAX); + SetFocus((HWND)lParam); + } + } + break; + case IDC_FADEOUT: + { + int fade = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if(fade < SETTING_FADEOUTTIME_MIN) + PopUpOptions.FadeOut = SETTING_FADEOUTTIME_MIN; + else if(fade > SETTING_FADEOUTTIME_MAX) + PopUpOptions.FadeOut = SETTING_FADEOUTTIME_MAX; + if(fade != PopUpOptions.FadeOut) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.FadeOut, FALSE); + ErrorMSG(SETTING_FADEOUTTIME_MIN, SETTING_FADEOUTTIME_MAX); + SetFocus((HWND)lParam); + } + } + break; + default: + break; + }//end switch(idCtrl) + break; + default: + break; + }// end switch (HIWORD(wParam)) + }//end WM_COMMAND + break; + case WM_NOTIFY: { + switch(((LPNMHDR)lParam)->idFrom) { + case 0: { + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + LoadOption_AdvOpts(); + return TRUE; + case PSN_APPLY: + { + //History + DBWriteContactSettingByte (NULL,MODULNAME, "EnableHistory", (BYTE)PopUpOptions.EnableHistory); + DBWriteContactSettingWord (NULL,MODULNAME, "HistorySize", PopUpOptions.HistorySize); + PopupHistoryResize(); + DBWriteContactSettingByte (NULL,MODULNAME, "UseHppHistoryLog", PopUpOptions.UseHppHistoryLog); + //Avatars + DBWriteContactSettingByte (NULL,MODULNAME, "AvatarBorders", PopUpOptions.avatarBorders); + DBWriteContactSettingByte (NULL,MODULNAME, "AvatarPNGBorders", PopUpOptions.avatarPNGBorders); + DBWriteContactSettingByte (NULL,MODULNAME, "AvatarRadius", PopUpOptions.avatarRadius); + DBWriteContactSettingWord (NULL,MODULNAME, "AvatarSize", PopUpOptions.avatarSize); + DBWriteContactSettingByte (NULL,MODULNAME, "EnableAvatarUpdates", PopUpOptions.EnableAvatarUpdates); + //Monitor + DBWriteContactSettingByte (NULL,MODULNAME, "Monitor", PopUpOptions.Monitor); + //Transparency + DBWriteContactSettingByte (NULL,MODULNAME, "EnableRegionTransparency", PopUpOptions.Enable9xTransparency); + DBWriteContactSettingByte (NULL,MODULNAME, "UseTransparency", PopUpOptions.UseTransparency); + DBWriteContactSettingByte (NULL,MODULNAME, "Alpha", PopUpOptions.Alpha); + DBWriteContactSettingByte (NULL,MODULNAME, "OpaqueOnHover", PopUpOptions.OpaqueOnHover); + + //Effects + DBWriteContactSettingByte (NULL,MODULNAME, "UseAnimations", PopUpOptions.UseAnimations); + DBWriteContactSettingByte (NULL,MODULNAME, "Fade", PopUpOptions.UseEffect); + DBWriteContactSettingTString(NULL, MODULNAME, "Effect", PopUpOptions.Effect); + DBWriteContactSettingDword(NULL,MODULNAME, "FadeInTime", PopUpOptions.FadeIn); + DBWriteContactSettingDword(NULL,MODULNAME, "FadeOutTime", PopUpOptions.FadeOut); + //other old stuff + DBWriteContactSettingWord (NULL,MODULNAME, "MaxPopups", (BYTE)PopUpOptions.MaxPopups); + } + return TRUE; + default: + break; + } + } + break; + default: + break; + } + }//end WM_NOTIFY + break; + case WM_DESTROY: + { + bDlgInit = false; + }//end WM_DESTROY + break; + default: + return FALSE; + }//end switch (msg) + return FALSE; +} + +INT_PTR CALLBACK AvatarTrackBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (!IsWindowEnabled(hwnd)) + return CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, msg, wParam, lParam); + + static int oldVal = -1; + switch (msg) { + case WM_MOUSEWHEEL: + case WM_KEYDOWN: + case WM_KEYUP: + { + if (!IsWindowVisible(hwndBox)) + break; + } + case WM_MOUSEMOVE: + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = HOVER_DEFAULT; + tme.hwndTrack = hwnd; + _TrackMouseEvent(&tme); + + int newVal = (BYTE)SendMessage(hwnd, TBM_GETPOS, 0, 0); + if (oldVal != newVal) { + if (oldVal < 0) { + SetWindowLongPtr(hwndBox, GWLP_USERDATA, 0); + } + RECT rc; GetWindowRect(hwnd, &rc); + SetWindowPos(hwndBox, NULL, + (rc.left+rc.right-newVal)/2, rc.bottom+2, newVal, newVal, + SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + + HRGN rgn = CreateRoundRectRgn(0, 0, newVal, newVal, 2 * PopUpOptions.avatarRadius, 2 * PopUpOptions.avatarRadius); + SetWindowRgn(hwndBox, rgn, TRUE); + InvalidateRect(hwndBox, NULL, FALSE); + oldVal = newVal; + } + } + break; + case WM_MOUSELEAVE: + { +/* + SetWindowLongPtr(hwndBox, GWLP_USERDATA, 2); + SetWindowPos(hwndBox, NULL, + 0, 0, 201, 201, + SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + + HRGN hrgnWindow, hrgnTmp, hrgnTmp2; + hrgnWindow = CreateRectRgn(0, 0, 201, 201); + hrgnTmp = CreateEllipticRgn(-90, -90, 90, 90); + SubtractRgn(hrgnWindow, hrgnWindow, hrgnTmp); + hrgnTmp = CreateEllipticRgn(112, -90, 292, 90); + SubtractRgn(hrgnWindow, hrgnWindow, hrgnTmp); + hrgnTmp = CreateEllipticRgn(-90, 112, 90, 292); + SubtractRgn(hrgnWindow, hrgnWindow, hrgnTmp); + hrgnTmp = CreateEllipticRgn(112, 112, 292, 292); + SubtractRgn(hrgnWindow, hrgnWindow, hrgnTmp); + + hrgnTmp = CreateRectRgn(5, 5, 196, 196); + hrgnTmp2 = CreateRoundRectRgn(89, 0, 113, 201, 8, 8); + UnionRgn(hrgnTmp, hrgnTmp, hrgnTmp2); + hrgnTmp2 = CreateRoundRectRgn(0, 89, 201, 113, 8, 8); + UnionRgn(hrgnTmp, hrgnTmp, hrgnTmp2); + IntersectRgn(hrgnWindow, hrgnWindow, hrgnTmp); + + SetWindowRgn(hwndBox, hrgnWindow, FALSE); + + if (MySetLayeredWindowAttributes) + { + SetWindowLong(hwndBox, GWL_EXSTYLE, GetWindowLong(hwndBox, GWL_EXSTYLE) | WS_EX_LAYERED); + MySetLayeredWindowAttributes(hwndBox, NULL, PopUpOptions.Alpha, LWA_ALPHA); + } +*/ + SetWindowRgn(hwndBox, NULL, TRUE); + ShowWindow(hwndBox, SW_HIDE); + oldVal = -1; + } + break; + default: + break; + } + return CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, msg, wParam, lParam); +} + +INT_PTR CALLBACK AlphaTrackBarWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (!IsWindowEnabled(hwnd)) + return CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, msg, wParam, lParam); + + static int oldVal = -1; + switch (msg) + { + case WM_MOUSEWHEEL: + case WM_KEYDOWN: + case WM_KEYUP: + { + if (!IsWindowVisible(hwndBox)) + break; + } + case WM_MOUSEMOVE: + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = HOVER_DEFAULT; + tme.hwndTrack = hwnd; + _TrackMouseEvent(&tme); + + int newVal = (BYTE)SendMessage(hwnd, TBM_GETPOS, 0, 0); + if (oldVal != newVal) + { +#if defined(_UNICODE) + if (oldVal < 0) + { + SetWindowLongPtr(hwndBox, GWLP_USERDATA, 1); + RECT rc; GetWindowRect(hwnd, &rc); + SetWindowPos(hwndBox, NULL, + (rc.left+rc.right-170)/2, rc.bottom+2, 170, 50, + SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + SetWindowRgn(hwndBox, NULL, TRUE); + } + SetWindowLong(hwndBox, GWL_EXSTYLE, GetWindowLong(hwndBox, GWL_EXSTYLE) | WS_EX_LAYERED); + SetLayeredWindowAttributes(hwndBox, NULL, newVal, LWA_ALPHA); +#else + if (MySetLayeredWindowAttributes) + { + if (oldVal < 0) + { + SetWindowLongPtr(hwndBox, GWLP_USERDATA, 1); + RECT rc; GetWindowRect(hwnd, &rc); + SetWindowPos(hwndBox, NULL, + (rc.left+rc.right-170)/2, rc.bottom+2, 170, 50, + SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + SetWindowRgn(hwndBox, NULL, TRUE); + } + SetWindowLong(hwndBox, GWL_EXSTYLE, GetWindowLong(hwndBox, GWL_EXSTYLE) | WS_EX_LAYERED); + MySetLayeredWindowAttributes(hwndBox, NULL, newVal, LWA_ALPHA); + } +#endif + oldVal = newVal; + } + break; + } + case WM_MOUSELEAVE: + { +#if defined(_UNICODE) + SetWindowLong(hwndBox, GWL_EXSTYLE, GetWindowLong(hwndBox, GWL_EXSTYLE) & ~WS_EX_LAYERED); + SetLayeredWindowAttributes(hwndBox, NULL, 255, LWA_ALPHA); +#else + if (MySetLayeredWindowAttributes) { + SetWindowLong(hwndBox, GWL_EXSTYLE, GetWindowLong(hwndBox, GWL_EXSTYLE) & ~WS_EX_LAYERED); + MySetLayeredWindowAttributes(hwndBox, NULL, 255, LWA_ALPHA); + } +#endif + ShowWindow(hwndBox, SW_HIDE); + oldVal = -1; + break; + } + } + return CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, msg, wParam, lParam); +} + diff --git a/Popup/src/opt_adv.h b/Popup/src/opt_adv.h new file mode 100644 index 0000000..0e3a26a --- /dev/null +++ b/Popup/src/opt_adv.h @@ -0,0 +1,45 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_adv.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __opt_adv_h__ +#define __opt_adv_h__ + +extern HWND hwndBox; + +void OptAdv_RegisterVfx(char *name); +void OptAdv_UnregisterVfx(); + +void LoadOption_AdvOpts(); +INT_PTR CALLBACK DlgProcPopUpAdvOpts(HWND, UINT, WPARAM, LPARAM); + + +#endif // __opt_adv_h__ diff --git a/Popup/src/opt_class.cpp b/Popup/src/opt_class.cpp new file mode 100644 index 0000000..b6376b8 --- /dev/null +++ b/Popup/src/opt_class.cpp @@ -0,0 +1,603 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== +part of this file is taken from SjE great YAPP plugin: +https://server.scottellis.com.au/svn/mim_plugs/yapp/options.cpp + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_class.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ +#include "headers.h" + +//--------------------------------------------------------------------------- +//Workaround for MS bug ComboBox_SelectItemData +int ComboBox_SelectItem(HWND hwndCtl, int indexStart, char* data) { + int i = 0; + for ( i ; i < ComboBox_GetCount(hwndCtl); i++) { + if(strcmp(data, (char*)ComboBox_GetItemData(hwndCtl, i))==0) { + ComboBox_SetCurSel (hwndCtl,i); + return i; + } + } + return CB_ERR; +} + +//--------------------------------------------------------------------------- +//some help function (not realy needed) +#define ComboBox_AddStringW(hwndCtl, lpwsz) ((int)(DWORD)MySendMessageW((HWND)(hwndCtl), CB_ADDSTRING, 0L, (LPARAM)(LPCWSTR)(lpwsz))) +#define ComboBox_SetTextW(hwndCtl, lpwsz) ((int)(DWORD)MySetWindowTextW((HWND)(hwndCtl), (LPCWSTR)(lpwsz))) + +//--------------------------------------------------------------------------- +//Dialog Proc +INT_PTR CALLBACK DlgProcOptsClasses(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + static TVITEM tvi = {0}; + static struct { + UINT idCtrl; + BYTE onTyp0; + BYTE onTyp1; + BYTE onTyp2; + } ctrlsAll[] = { + {IDC_TXT_TITLE1 ,0 ,1 ,1}, + {IDC_ENABLE ,0 ,1 ,1}, + + {IDC_TXT_TIMEOUT ,0 ,1 ,1}, + {IDC_TIMEOUT ,0 ,1 ,1}, + {IDC_TIMEOUT_SPIN ,0 ,1 ,1}, + {IDC_TXT_TIMEOUT_SEC ,0 ,1 ,1}, + {IDC_TXT_TIMEOUT_DEFAULT ,0 ,1 ,1}, + {IDC_TXT_TIMEOUT_INFINITE ,0 ,1 ,1}, + + {IDC_TXT_LACTION ,0 ,1 ,1}, + {IDC_LACTION ,0 ,1 ,1}, + + {IDC_TXT_RACTION ,0 ,1 ,1}, + {IDC_RACTION ,0 ,1 ,1}, + + {IDC_CHECKWINDOW ,0 ,0 ,0}, //may be delete ?? + + {IDC_TXT_TITLE3 ,0 ,1 ,0}, + {IDC_SOFFLINE ,0 ,1 ,0}, + {IDC_SONLINE ,0 ,1 ,0}, + {IDC_SAWAY ,0 ,1 ,0}, + {IDC_SNA ,0 ,1 ,0}, + {IDC_SOCCUPIED ,0 ,1 ,0}, + {IDC_SDND ,0 ,1 ,0}, + {IDC_SFREE4CHAT ,0 ,1 ,0}, + {IDC_SINVISIBLE ,0 ,1 ,0}, + {IDC_SPHONE ,0 ,1 ,0}, + {IDC_SLUNCH ,0 ,1 ,0}, + + {IDC_TXT_TITLE4 ,0 ,0 ,0}, + {IDC_SOFFLINE2 ,0 ,0 ,0}, + {IDC_SONLINE2 ,0 ,0 ,0}, + {IDC_SAWAY2 ,0 ,0 ,0}, + {IDC_SNA2 ,0 ,0 ,0}, + {IDC_SOCCUPIED2 ,0 ,0 ,0}, + {IDC_SDND2 ,0 ,0 ,0}, + {IDC_SFREE4CHAT2 ,0 ,0 ,0}, + {IDC_SINVISIBLE2 ,0 ,0 ,0}, + {IDC_SPHONE2 ,0 ,0 ,0}, + {IDC_SLUNCH2 ,0 ,0 ,0}, + + {IDC_ICO_INFO ,0 ,1 ,1}, + {IDC_TXT_COLORS ,0 ,1 ,1}, + {IDC_MORE ,0 ,1 ,1}, + + {IDC_PREVIEW ,0 ,1 ,1}, + }; + + static UINT ctrlsClass[] = { + IDC_TXT_TITLE1, /*IDC_TXT_TITLE3,*/ + IDC_TXT_TIMEOUT, IDC_TIMEOUT, + IDC_TIMEOUT_SPIN, IDC_TXT_TIMEOUT_SEC, + IDC_TXT_TIMEOUT_DEFAULT, IDC_TXT_TIMEOUT_INFINITE, + IDC_TXT_LACTION, IDC_LACTION, + IDC_TXT_RACTION, IDC_RACTION, + IDC_ICO_INFO, IDC_TXT_COLORS, + }; + + static UINT ctrlsEnable[] = { + IDC_TXT_TIMEOUT, IDC_TIMEOUT, IDC_TIMEOUT_SPIN, + IDC_TXT_TIMEOUT_SEC , IDC_TXT_TIMEOUT_DEFAULT, IDC_TXT_TIMEOUT_INFINITE, + IDC_TXT_LACTION, IDC_LACTION, + IDC_TXT_RACTION, IDC_RACTION, + /*IDC_CHECKWINDOW,*/ IDC_TXT_TITLE3, IDC_TXT_TITLE4, + IDC_ICO_INFO, IDC_TXT_COLORS, IDC_MORE, + + IDC_SOFFLINE, IDC_SONLINE, IDC_SAWAY, IDC_SNA, + IDC_SOCCUPIED, IDC_SDND, IDC_SFREE4CHAT, + IDC_SINVISIBLE, IDC_SPHONE, IDC_SLUNCH, + + IDC_SOFFLINE2, IDC_SONLINE2, IDC_SAWAY2, IDC_SNA2, + IDC_SOCCUPIED2, IDC_SDND2, IDC_SFREE4CHAT2, + IDC_SINVISIBLE2, IDC_SPHONE2, IDC_SLUNCH2, + }; + + static UINT ctrlsContact[] = { + /*IDC_CHECKWINDOW,*/ IDC_TXT_TITLE4, + IDC_SOFFLINE2, IDC_SONLINE2, IDC_SAWAY2, IDC_SNA2, + IDC_SOCCUPIED2, IDC_SDND2, IDC_SFREE4CHAT2, + IDC_SINVISIBLE2, IDC_SPHONE2, IDC_SLUNCH2, + }; + + static int titleIds[] = { + IDC_TXT_TITLE1, + IDC_TXT_TITLE3, + IDC_TXT_TITLE4, + }; + + static struct { + int idCtrl; + int iconId; + char *title; + DWORD statusFlag; + DWORD disableWhenFlag; + } statusButtons[] = { + {IDC_SOFFLINE, SKINICON_STATUS_OFFLINE, "Offline", PF2_IDLE, PF2_IDLE}, + {IDC_SONLINE, SKINICON_STATUS_ONLINE, "Online", PF2_ONLINE, PF2_ONLINE}, + {IDC_SAWAY, SKINICON_STATUS_AWAY, "Away", PF2_SHORTAWAY, PF2_SHORTAWAY}, + {IDC_SNA, SKINICON_STATUS_NA, "NA", PF2_LONGAWAY, PF2_LONGAWAY}, + {IDC_SOCCUPIED, SKINICON_STATUS_OCCUPIED, "Occupied", PF2_LIGHTDND, PF2_LIGHTDND}, + {IDC_SDND, SKINICON_STATUS_DND, "DND", PF2_HEAVYDND, PF2_HEAVYDND}, + {IDC_SFREE4CHAT, SKINICON_STATUS_FREE4CHAT, "Free for chat", PF2_FREECHAT, PF2_FREECHAT}, + {IDC_SINVISIBLE, SKINICON_STATUS_INVISIBLE, "Invisible", PF2_INVISIBLE, PF2_INVISIBLE}, + {IDC_SPHONE, SKINICON_STATUS_ONTHEPHONE, "On the phone", PF2_ONTHEPHONE, PF2_ONTHEPHONE}, + {IDC_SLUNCH, SKINICON_STATUS_OUTTOLUNCH, "Out to lunch", PF2_OUTTOLUNCH, PF2_OUTTOLUNCH}, + + {IDC_SOFFLINE2, SKINICON_STATUS_OFFLINE, "Offline", PF2_IDLE, PF2_IDLE<<16}, + {IDC_SONLINE2, SKINICON_STATUS_ONLINE, "Online", PF2_ONLINE, PF2_ONLINE<<16}, + {IDC_SAWAY2, SKINICON_STATUS_AWAY, "Away", PF2_SHORTAWAY, PF2_SHORTAWAY<<16}, + {IDC_SNA2, SKINICON_STATUS_NA, "NA", PF2_LONGAWAY, PF2_LONGAWAY<<16}, + {IDC_SOCCUPIED2, SKINICON_STATUS_OCCUPIED, "Occupied", PF2_LIGHTDND, PF2_LIGHTDND<<16}, + {IDC_SDND2, SKINICON_STATUS_DND, "DND", PF2_HEAVYDND, PF2_HEAVYDND<<16}, + {IDC_SFREE4CHAT2, SKINICON_STATUS_FREE4CHAT, "Free for chat", PF2_FREECHAT, PF2_FREECHAT<<16}, + {IDC_SINVISIBLE2, SKINICON_STATUS_INVISIBLE, "Invisible", PF2_INVISIBLE, PF2_INVISIBLE<<16}, + {IDC_SPHONE2, SKINICON_STATUS_ONTHEPHONE, "On the phone", PF2_ONTHEPHONE, PF2_ONTHEPHONE<<16}, + {IDC_SLUNCH2, SKINICON_STATUS_OUTTOLUNCH, "Out to lunch", PF2_OUTTOLUNCH, PF2_OUTTOLUNCH<<16}, + }; + + + switch ( msg ) { + case WM_INITDIALOG: + { + int i; + TranslateDialogDefault( hwnd ); + + //Treeview + HWND hwndTree = GetDlgItem(hwnd, IDC_TREE1); + { + int iconIndex = 0; + char iconName[MAXMODULELABELLENGTH]; + TCHAR itemName[MAXMODULELABELLENGTH]; + TreeView_DeleteAllItems(hwndTree); + //Treeview create image list + HIMAGELIST hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR|ILC_COLOR32|ILC_MASK, 5, num_classes+1); + ImageList_ReplaceIcon(hImgLst, -1, IcoLib_GetIcon(ICO_OPT_GROUP,0)); + TreeView_SetImageList(hwndTree, hImgLst, TVSIL_NORMAL); + + for (i = 0; i < gTreeData.getCount(); ++i) { + switch (gTreeData[i]->typ) { + case 1: //Treeview part for typ 1 (notification) + mir_snprintf(iconName, sizeof(iconName), "%s_"TCHAR_STR_PARAM"_"TCHAR_STR_PARAM, MODULNAME, gTreeData[i]->pszTreeRoot, gTreeData[i]->pszDescription); + iconIndex = ImageList_ReplaceIcon(hImgLst, -1, IcoLib_GetIcon(iconName)); + wsprintf(itemName, _T("%s/%s"), gTreeData[i]->pszTreeRoot, gTreeData[i]->pszDescription); + break; + case 2: //Treeview part typ 2 (popup class api) + iconIndex = ImageList_ReplaceIcon(hImgLst, -1, gTreeData[i]->pupClass.hIcon); + wsprintf(itemName, _T("%s/%s"), _T("CLASS Plugins")/*gTreeData[i]->pszTreeRoot*/, gTreeData[i]->pszDescription); + break; + default: + break; + } + OptTree_AddItem(hwndTree, itemName, (LPARAM)gTreeData[i], iconIndex); + } + OptTree_Translate(hwndTree); + } // end Treeview + + //Bold Title + for (i = 0; i < SIZEOF(titleIds); ++i) + { + LOGFONT lf; + GetObject((HFONT)SendDlgItemMessage(hwnd, titleIds[i], WM_GETFONT, 0, 0), sizeof(lf), &lf); + lf.lfWeight = FW_BOLD; + SendDlgItemMessage(hwnd, titleIds[i], WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), TRUE); + } + + //spindown for Timeout + SendDlgItemMessage(hwnd, IDC_TIMEOUT_SPIN, UDM_SETRANGE, 0, (LPARAM)MAKELONG(SETTING_LIFETIME_MAX, SETTING_LIFETIME_INFINITE)); + SetDlgItemInt(hwnd,IDC_TIMEOUT, (UINT)0, TRUE); + //status buttons + for (i = 0; i < SIZEOF(statusButtons); ++i) + { + SendDlgItemMessage(hwnd, statusButtons[i].idCtrl, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwnd, statusButtons[i].idCtrl, BUTTONSETASPUSHBTN, 0, 0); + SendDlgItemMessage(hwnd, statusButtons[i].idCtrl, BM_SETIMAGE, + IMAGE_ICON, (LPARAM)LoadSkinnedIcon(statusButtons[i].iconId)); + SendDlgItemMessage(hwnd, statusButtons[i].idCtrl, BUTTONADDTOOLTIP, + (WPARAM)Translate(statusButtons[i].title), 0); + } + //info icon + SendDlgItemMessage(hwnd, IDC_ICO_INFO, STM_SETICON, (WPARAM)IcoLib_GetIcon(ICO_MISC_NOTIFY,0), 0); + //more button + EnableWindow(GetDlgItem(hwnd, IDC_MORE), FALSE); + //preview button + ShowWindow(GetDlgItem(hwnd, IDC_CHECKWINDOW), SW_HIDE); + + SendMessage(hwnd, WM_USER, 0, 0); + + return TRUE; + } + case WM_USER: + { + int i; + HWND hTV = GetDlgItem(hwnd, IDC_TREE1); + //get TreeView selection + tvi.hItem = TreeView_GetSelection(hTV); + tvi.mask = TVIF_PARAM|TVIF_HANDLE|TVIF_TEXT; + if (tvi.hItem) TreeView_GetItem(hTV, &tvi); + SetWindowLongPtr(hwnd, GWLP_USERDATA, tvi.lParam); + + if (tvi.lParam) { + POPUPTREEDATA* ptd = (POPUPTREEDATA *)tvi.lParam; + HWND hCtrl = 0; + LPTSTR psztSelect = NULL; + int index = 0; + //combo left action (default) + { + hCtrl = GetDlgItem(hwnd, IDC_LACTION); + ComboBox_ResetContent(hCtrl); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT(POPUP_ACTION_DISMISS)),POPUP_ACTION_DISMISS); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT(POPUP_ACTION_NOTHING)),POPUP_ACTION_NOTHING); + } + //combo right action (default) + { + hCtrl = GetDlgItem(hwnd, IDC_RACTION); + ComboBox_ResetContent(hCtrl); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT(POPUP_ACTION_DISMISS)),POPUP_ACTION_DISMISS); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT(POPUP_ACTION_NOTHING)),POPUP_ACTION_NOTHING); + } + + //element typ1 (Notification) + if (ptd->typ == 1) { + LPTSTR psztAction = NULL; + //Timeout + SetDlgItemInt(hwnd,IDC_TIMEOUT, (UINT)ptd->timeoutValue, TRUE); + SendDlgItemMessage(hwnd, IDC_TIMEOUT_SPIN, UDM_SETRANGE, 0, (LPARAM)MAKELONG(250, -1)); + //combo left action (EXTRA) + hCtrl = GetDlgItem(hwnd, IDC_LACTION); + for (i = 0; i < ptd->notification.actionCount; ++i) { + psztAction = mir_a2t(ptd->notification.lpActions[i].lpzTitle); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateTS(psztAction)),ptd->notification.lpActions[i].lpzTitle); + mir_free(psztAction); psztAction = NULL; + } + //combo right action (EXTRA) + hCtrl = GetDlgItem(hwnd, IDC_RACTION); + psztAction = NULL; + for (i = 0; i < ptd->notification.actionCount; ++i) { + psztAction = mir_a2t(ptd->notification.lpActions[i].lpzTitle); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateTS(psztAction)),ptd->notification.lpActions[i].lpzTitle); + mir_free(psztAction); psztAction = NULL; + } + //enable all controls + for (i = 0; i < SIZEOF(ctrlsAll); ++i){ + ShowWindow(GetDlgItem(hwnd, ctrlsAll[i].idCtrl), ctrlsAll[i].onTyp1 ? SW_SHOW : SW_HIDE); + EnableWindow(GetDlgItem(hwnd, ctrlsAll[i].idCtrl), ctrlsAll[i].onTyp1); + } + //enable or disable controls ctrlsEnable + for (i = 0; i < SIZEOF(ctrlsEnable); ++i) + EnableWindow(GetDlgItem(hwnd, ctrlsEnable[i]), ptd->enabled ? TRUE : FALSE); + //show or hide controls ctrlsContact + for (i = 0; i < SIZEOF(ctrlsContact); ++i) + ShowWindow(GetDlgItem(hwnd, ctrlsContact[i]), ptd->notification.dwFlags&PNF_CONTACT ? SW_SHOW : SW_HIDE); + //statusButtons state + for (i = 0; i < SIZEOF(statusButtons); ++i) + CheckDlgButton(hwnd, statusButtons[i].idCtrl, ptd->disableWhen & statusButtons[i].disableWhenFlag ? TRUE : FALSE); + } + //element typ2 (CLASS Plugins) + else if (ptd->typ == 2) { + //Timeout + SetDlgItemInt(hwnd,IDC_TIMEOUT, (UINT)ptd->timeoutValue, TRUE); + SendDlgItemMessage(hwnd, IDC_TIMEOUT_SPIN, UDM_SETRANGE, 0, (LPARAM)MAKELONG(250, -1)); + //enable ctrls + for (i = 0; i < SIZEOF(ctrlsAll); ++i){ + ShowWindow(GetDlgItem(hwnd, ctrlsAll[i].idCtrl), ctrlsAll[i].onTyp2 ? SW_SHOW : SW_HIDE); + EnableWindow(GetDlgItem(hwnd, ctrlsAll[i].idCtrl), ctrlsAll[i].onTyp2); + } + } + //checkbox enable notify + CheckDlgButton(hwnd, IDC_ENABLE, ptd->enabled ? TRUE : FALSE); + //combo left action (SELECT) + hCtrl = GetDlgItem(hwnd, IDC_LACTION); + ComboBox_SelectItem (hCtrl, -1, ptd->leftAction); //use Workaround for MS bug ComboBox_SelectItemData + //combo right action (SELECT) + hCtrl = GetDlgItem(hwnd, IDC_RACTION); + ComboBox_SelectItem (hCtrl, -1, ptd->rightAction); //use Workaround for MS bug ComboBox_SelectItemData + } //end if (tvi.lParam) + else { + //enable / disable controls + for (int i = 0; i < SIZEOF(ctrlsAll); ++i) { + ShowWindow(GetDlgItem(hwnd, ctrlsAll[i].idCtrl), ctrlsAll[i].onTyp0 ? SW_SHOW : SW_HIDE); + EnableWindow(GetDlgItem(hwnd, ctrlsAll[i].idCtrl), ctrlsAll[i].onTyp0); + } + } + break; + } + case WM_COMMAND: + { + UINT idCtrl = LOWORD(wParam); + POPUPTREEDATA* ptd = (POPUPTREEDATA *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (!ptd) break; + switch (HIWORD(wParam)) { + int i; + case BN_CLICKED: //Button controls + switch(idCtrl) { + case IDC_ENABLE: + ptd->enabled = (BYTE)Button_GetCheck((HWND)lParam); + for (i = 0; i < SIZEOF(ctrlsEnable); ++i) + EnableWindow(GetDlgItem(hwnd, ctrlsEnable[i]), ptd->enabled); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IDC_PREVIEW: + { + POPUPDATA2 ppd = {0}; + ppd.cbSize = sizeof(ppd); + ppd.flags = PU2_TCHAR; + ppd.lptzTitle = ptd->pszDescription; + ppd.lptzText = TranslateT("Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!"); + ppd.iSeconds = ptd->timeoutValue; + ppd.colorBack = ptd->colorBack; + ppd.colorText = ptd->colorText; + POPUPTREEDATA *ptdPrev = NULL; + if(ptd->typ == 1) { + //we work with a copy for preview + ptdPrev = (POPUPTREEDATA *)mir_alloc(sizeof(POPUPTREEDATA)); + memcpy(ptdPrev, ptd, sizeof(POPUPTREEDATA)); + ptdPrev->enabled = ptd->enabled; + ptdPrev->timeoutValue = ptd->timeoutValue; + strcpy(ptdPrev->leftAction , ptd->leftAction); //geht noch nicht?? + strcpy(ptdPrev->rightAction , ptd->rightAction); //geht noch nicht?? + ptdPrev->disableWhen = ptd->disableWhen; + + ppd.lchNotification = (HANDLE)ptdPrev; + } + else if(ptd->typ == 2) { + ppd.lchIcon = ptd->pupClass.hIcon; + } + CallService(MS_POPUP_ADDPOPUP2, (WPARAM)&ppd, APF_NO_HISTORY); + mir_free(ptdPrev); ptdPrev = NULL; + } + break; + case IDC_MORE: + { + OPENOPTIONSDIALOG ood = {0}; + ood.cbSize = sizeof(OPENOPTIONSDIALOG); + ood.pszGroup = "Customize"; + ood.pszPage = "Fonts & Colors"; + CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood); + } + break; + case IDC_SOFFLINE: case IDC_SONLINE: case IDC_SAWAY: case IDC_SNA: case IDC_SOCCUPIED: + case IDC_SDND: case IDC_SFREE4CHAT: case IDC_SINVISIBLE: case IDC_SPHONE: case IDC_SLUNCH: + case IDC_SOFFLINE2: case IDC_SONLINE2: case IDC_SAWAY2: case IDC_SNA2: case IDC_SOCCUPIED2: + case IDC_SDND2: case IDC_SFREE4CHAT2: case IDC_SINVISIBLE2: case IDC_SPHONE2: case IDC_SLUNCH2: + { + ptd->disableWhen = 0; + for (i = 0; i < SIZEOF(statusButtons); ++i) { + if (IsDlgButtonChecked(hwnd, statusButtons[i].idCtrl)) + ptd->disableWhen |= statusButtons[i].disableWhenFlag; + if (idCtrl == statusButtons[i].idCtrl) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + default: + break; + } + break; + case CBN_SELCHANGE: //ComboBox controls + switch(idCtrl) { + //lParam = Handle to the control + case IDC_LACTION: + lstrcpynA(ptd->leftAction, + (char *)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)), + sizeof(ptd->leftAction)); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IDC_RACTION: + lstrcpynA(ptd->rightAction, + (char *)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)), + sizeof(ptd->rightAction)); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + default: + break; + } + break; + case EN_CHANGE: //Edit controls + switch(idCtrl) { + //lParam = Handle to the control + case IDC_TIMEOUT: + { + int seconds = GetDlgItemInt(hwnd, idCtrl, NULL, TRUE); + if ( seconds >= SETTING_LIFETIME_INFINITE && + seconds <= SETTING_LIFETIME_MAX && + seconds != ptd->timeoutValue) { + ptd->timeoutValue = seconds; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + default: + break; + } + break; + case EN_KILLFOCUS: //Edit controls lost fokus + switch(idCtrl) { + //lParam = Handle to the control + case IDC_TIMEOUT: + { + int seconds = GetDlgItemInt(hwnd, idCtrl, NULL, TRUE); + if (seconds > SETTING_LIFETIME_MAX) + ptd->timeoutValue = SETTING_LIFETIME_MAX; + else if (seconds < SETTING_LIFETIME_INFINITE) + ptd->timeoutValue = SETTING_LIFETIME_INFINITE; + if(seconds != ptd->timeoutValue) { + SetDlgItemInt(hwnd, idCtrl, ptd->timeoutValue, TRUE); + ErrorMSG(SETTING_LIFETIME_INFINITE, SETTING_LIFETIME_MAX); + SetFocus((HWND)lParam); + } + } + break; + default: + break; + }//end switch(idCtrl) + break; + default: + break; + } + break; + } + case WM_NOTIFY: + { + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + { + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + { + for(int i = 0; i < gTreeData.getCount(); ++i) { + switch (gTreeData[i]->typ) { + case 1: + LoadNotificationSettings(gTreeData[i], "PopUpNotifications"); + break; + case 2: //not finish + LoadClassSettings(gTreeData[i], PU_MODULCLASS); + gTreeData[i]->timeoutValue = gTreeData[i]->pupClass.iSeconds; + break; + default: + break; + } + } + return TRUE; + } + case PSN_APPLY: + { + for(int i = 0; i < gTreeData.getCount(); ++i) { + switch (gTreeData[i]->typ) { + case 1: + gTreeData[i]->notification.iSeconds = gTreeData[i]->timeoutValue; + SaveNotificationSettings(gTreeData[i],"PopUpNotifications"); + break; + case 2: //not finish + gTreeData[i]->pupClass.iSeconds = gTreeData[i]->timeoutValue; + SaveClassSettings(gTreeData[i],"PopUpCLASS"); + break; + default: + break; + } + } + return TRUE; + } + } + break; + } + + case IDC_TREE1: + { + switch (((LPNMHDR)lParam)->code) + { + case TVN_SELCHANGEDA: + case TVN_SELCHANGEDW: + { + PostMessage(hwnd, WM_USER, 0, 0); + break; + } + } + break; + } + } + break; + } + + case WM_DESTROY: + ZeroMemory(&tvi,sizeof(tvi)); + break; + + default: + return FALSE; + } + return FALSE; +} + +void LoadClassSettings(POPUPTREEDATA *ptd, char* szModul) +{ + char setting[2*MAXMODULELABELLENGTH]; + char *szTmp = NULL; + + mir_snprintf(setting, sizeof(setting), "%s/enabled", ptd->pupClass.pszName); + ptd->enabled = + (signed char)DBGetContactSettingByte(NULL, szModul, setting, TRUE); + + mir_snprintf(setting, sizeof(setting), "%s/Timeout", ptd->pupClass.pszName); + ptd->pupClass.iSeconds = + (signed char)DBGetContactSettingWord(NULL, szModul, setting, 0); + + mir_snprintf(setting, sizeof(setting), "%s/TimeoutVal", ptd->pupClass.pszName); + ptd->timeoutValue = + (signed char)DBGetContactSettingWord(NULL, szModul, setting, + ptd->pupClass.iSeconds ? ptd->pupClass.iSeconds : PopUpOptions.Seconds); + + mir_snprintf(setting, sizeof(setting), "%s/leftAction", ptd->pupClass.pszName); + szTmp = DBGetContactSettingString(NULL, szModul, setting, POPUP_ACTION_NOTHING); //standart ?? + lstrcpynA(ptd->leftAction, szTmp, sizeof(ptd->leftAction)); + mir_free(szTmp); szTmp = NULL; + + mir_snprintf(setting, sizeof(setting), "%s/rightAction", ptd->pupClass.pszName); + szTmp = DBGetContactSettingString(NULL, szModul, setting, POPUP_ACTION_DISMISS); //standart ?? + lstrcpynA(ptd->rightAction, szTmp, sizeof(ptd->rightAction)); + mir_free(szTmp); szTmp = NULL; + +} +void SaveClassSettings(POPUPTREEDATA *ptd, char* szModul) +{ + char setting[2*MAXMODULELABELLENGTH]; + + mir_snprintf(setting, sizeof(setting), "%s/enabled", ptd->pupClass.pszName); + DBWriteContactSettingByte(NULL, szModul, setting, ptd->enabled); + + mir_snprintf(setting, sizeof(setting), "%s/Timeout", ptd->pupClass.pszName); + DBWriteContactSettingWord(NULL, szModul, setting, ptd->pupClass.iSeconds); + + mir_snprintf(setting, sizeof(setting), "%s/TimeoutVal",ptd->pupClass.pszName); + DBWriteContactSettingWord(NULL, szModul, setting, ptd->timeoutValue); + + mir_snprintf(setting, sizeof(setting), "%s/leftAction",ptd->pupClass.pszName); + DBWriteContactSettingString(NULL, szModul, setting, ptd->leftAction); + + mir_snprintf(setting, sizeof(setting), "%s/rightAction",ptd->pupClass.pszName); + DBWriteContactSettingString(NULL, szModul, setting, ptd->rightAction); +} diff --git a/Popup/src/opt_class.h b/Popup/src/opt_class.h new file mode 100644 index 0000000..245409a --- /dev/null +++ b/Popup/src/opt_class.h @@ -0,0 +1,41 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_class.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __opt_class_h__ +#define __opt_class_h__ + +void LoadClassSettings(POPUPTREEDATA *ptd, char* szModul); +void SaveClassSettings(POPUPTREEDATA *ptd, char* szModul); + +INT_PTR CALLBACK DlgProcOptsClasses(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif // __opt_class_h__ diff --git a/Popup/src/opt_contacts.cpp b/Popup/src/opt_contacts.cpp new file mode 100644 index 0000000..582a85a --- /dev/null +++ b/Popup/src/opt_contacts.cpp @@ -0,0 +1,175 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_contacts.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +static void sttResetListOptions(HWND hwndList); +static void sttSetAllContactIcons(HWND hwndList); + +INT_PTR CALLBACK DlgProcContactOpts(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwnd); + + SendMessage(GetDlgItem(hwnd, IDC_ICO_AUTO), STM_SETICON, (WPARAM)IcoLib_GetIcon(ICO_OPT_DEF,0), 0); + SendMessage(GetDlgItem(hwnd, IDC_ICO_FAVORITE), STM_SETICON, (WPARAM)IcoLib_GetIcon(ICO_OPT_FAV,0), 0); + SendMessage(GetDlgItem(hwnd, IDC_ICO_FULLSCREEN), STM_SETICON, (WPARAM)IcoLib_GetIcon(ICO_OPT_FULLSCREEN,0), 0); + SendMessage(GetDlgItem(hwnd, IDC_ICO_BLOCK), STM_SETICON, (WPARAM)IcoLib_GetIcon(ICO_OPT_BLOCK,0), 0); + + HIMAGELIST hIml = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), + (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK,5,5); + ImageList_AddIcon(hIml, LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT)); + ImageList_AddIcon(hIml, IcoLib_GetIcon(ICO_OPT_DEF,0)); + ImageList_AddIcon(hIml, IcoLib_GetIcon(ICO_OPT_FAV,0)); + ImageList_AddIcon(hIml, IcoLib_GetIcon(ICO_OPT_FULLSCREEN,0)); + ImageList_AddIcon(hIml, IcoLib_GetIcon(ICO_OPT_BLOCK,0)); + SendDlgItemMessage(hwnd, IDC_LIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hIml); + SendDlgItemMessage(hwnd, IDC_LIST, CLM_SETEXTRACOLUMNS, 4 /*SIZEOF(sttIcons)*/, 0); + sttResetListOptions(GetDlgItem(hwnd, IDC_LIST)); + sttSetAllContactIcons(GetDlgItem(hwnd, IDC_LIST)); + + break; + } + + case WM_NOTIFY: + { + switch(((LPNMHDR)lParam)->idFrom) + { + case IDC_LIST: + { + switch (((LPNMHDR)lParam)->code) + { + case CLN_NEWCONTACT: + case CLN_LISTREBUILT: + sttSetAllContactIcons(GetDlgItem(hwnd,IDC_LIST)); + break; + case CLN_OPTIONSCHANGED: + sttResetListOptions(GetDlgItem(hwnd,IDC_LIST)); + break; + case NM_CLICK: + { + HANDLE hItem; + NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam; + DWORD hitFlags; + int iImage; + + if(nm->iColumn==-1) break; + hItem=(HANDLE)SendDlgItemMessage(hwnd,IDC_LIST,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(nm->pt.x,nm->pt.y)); + if(hItem==NULL) break; + if(!(hitFlags&CLCHT_ONITEMEXTRA)) break; + + iImage=SendDlgItemMessage(hwnd,IDC_LIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn,0)); + if (iImage != 0xFF) + { + for (int i = 0; i < 4 /*SIZEOF(sttIcons)*/; ++i) + //hIml element [0] = SKINICON_OTHER_SMALLDOT + //hIml element [1..5] = IcoLib_GetIcon(....) ~ old sttIcons + SendDlgItemMessage(hwnd, IDC_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, (i==nm->iColumn)?i+1:0)); + } +/* + { + while (hItem=(HANDLE)SendDlgItemMessage(hwnd,IDC_LIST,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem)) + { + for (int i = 0; i < SIZEOF(sttIcons); ++i) + SendDlgItemMessage(hwnd, IDC_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, (i==nm->iColumn)?i+1:0)); + hItem = (HANDLE)SendDlgItemMessage(hwnd,IDC_LIST,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem); + } + } +*/ + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + } + } + break; + } + + case 0: + { + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + HWND hwndList = GetDlgItem(hwnd, IDC_LIST); + for (HANDLE hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)) + { + HANDLE hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0); + for (int i = 0; i < 4 /*SIZEOF(sttIcons)*/; ++i) + { + if (SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(i,0))) + { + DBWriteContactSettingByte(hContact, MODULNAME, "ShowMode", i); + break; + } + } + } + return TRUE; + } + } + break; + } + } + break; + } + } + + return FALSE; +} + +static void sttResetListOptions(HWND hwndList) +{ + SendMessage(hwndList,CLM_SETBKBITMAP,0,(LPARAM)(HBITMAP)NULL); + SendMessage(hwndList,CLM_SETBKCOLOR,GetSysColor(COLOR_WINDOW),0); + SendMessage(hwndList,CLM_SETGREYOUTFLAGS,0,0); + SendMessage(hwndList,CLM_SETLEFTMARGIN,4,0); + SendMessage(hwndList,CLM_SETINDENT,20,0); + SendMessage(hwndList,CLM_SETHIDEEMPTYGROUPS,1,0); + for(int i=0;i<=FONTID_MAX;i++) + SendMessage(hwndList,CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT)); +} + +static void sttSetAllContactIcons(HWND hwndList) +{ + for (HANDLE hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); hContact; + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)) + { + HANDLE hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0); + DWORD dwMode = DBGetContactSettingByte(hContact, MODULNAME, "ShowMode", 0); + for (int i = 0; i < 4 /*SIZEOF(sttIcons)*/; ++i) + //hIml element [0] = SKINICON_OTHER_SMALLDOT + //hIml element [1..5] = IcoLib_GetIcon(....) ~ old sttIcons + SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, (dwMode==i)?i+1:0)); + } +} diff --git a/Popup/src/opt_contacts.h b/Popup/src/opt_contacts.h new file mode 100644 index 0000000..222b97c --- /dev/null +++ b/Popup/src/opt_contacts.h @@ -0,0 +1,46 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_contacts.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __opt_contacts_h__ +#define __opt_contacts_h__ + +enum +{ + PU_SHOWMODE_AUTO, + PU_SHOWMODE_FAVORITE, + PU_SHOWMODE_FULLSCREEN, + PU_SHOWMODE_BLOCK +}; + +INT_PTR CALLBACK DlgProcContactOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif // __opt_contacts_h__ diff --git a/Popup/src/opt_gen.cpp b/Popup/src/opt_gen.cpp new file mode 100644 index 0000000..109598e --- /dev/null +++ b/Popup/src/opt_gen.cpp @@ -0,0 +1,761 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_gen.cpp $ +Revision : $Revision: 1628 $ +Last change on : $Date: 2010-06-30 03:42:27 +0300 (Ср, 30 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +INT_PTR CALLBACK PositionBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Helper for Status Tree +static int CountStatusModes(DWORD flags) +{ + int res = 0; + if (flags & PF2_ONLINE) ++res; + if (flags & PF2_INVISIBLE) ++res; + if (flags & PF2_SHORTAWAY) ++res; + if (flags & PF2_LONGAWAY) ++res; + if (flags & PF2_LIGHTDND) ++res; + if (flags & PF2_HEAVYDND) ++res; + if (flags & PF2_FREECHAT) ++res; + if (flags & PF2_OUTTOLUNCH) ++res; + if (flags & PF2_ONTHEPHONE) ++res; + if (res) ++res; // Offline + return res; +} + +int AddStatusMode (OPTTREE_OPTION *options, int pos, LPTSTR prefix, DWORD flag) +{ + if (!flag) return pos; + options[pos].dwFlag = flag; + options[pos].groupId = OPTTREE_CHECK; + options[pos].pszOptionName = (LPTSTR)mir_alloc(sizeof(TCHAR)*lstrlen(prefix)+32); + options[pos].pszSettingName = mir_tstrdup(prefix); + options[pos].iconIndex = 0; + + lstrcpy(options[pos].pszOptionName, prefix); + switch (flag) + { + case PF2_IDLE: lstrcat(options[pos].pszOptionName, _T("/Offline")); break; + case PF2_ONLINE: lstrcat(options[pos].pszOptionName, _T("/Online")); break; + case PF2_INVISIBLE: lstrcat(options[pos].pszOptionName, _T("/Invisible")); break; + case PF2_SHORTAWAY: lstrcat(options[pos].pszOptionName, _T("/Away")); break; + case PF2_LONGAWAY: lstrcat(options[pos].pszOptionName, _T("/NA")); break; + case PF2_LIGHTDND: lstrcat(options[pos].pszOptionName, _T("/Occupied")); break; + case PF2_HEAVYDND: lstrcat(options[pos].pszOptionName, _T("/DND")); break; + case PF2_FREECHAT: lstrcat(options[pos].pszOptionName, _T("/Free for chat")); break; + case PF2_OUTTOLUNCH:lstrcat(options[pos].pszOptionName, _T("/Out to lunch")); break; + case PF2_ONTHEPHONE:lstrcat(options[pos].pszOptionName, _T("/On the phone")); break; + } + return pos+1; +} + +int AddStatusModes(OPTTREE_OPTION *options, int pos, LPTSTR prefix, DWORD flags) +{ + pos = AddStatusMode(options, pos, prefix, PF2_IDLE); + pos = AddStatusMode(options, pos, prefix, flags&PF2_ONLINE); + pos = AddStatusMode(options, pos, prefix, flags&PF2_INVISIBLE); + pos = AddStatusMode(options, pos, prefix, flags&PF2_SHORTAWAY); + pos = AddStatusMode(options, pos, prefix, flags&PF2_LONGAWAY); + pos = AddStatusMode(options, pos, prefix, flags&PF2_LIGHTDND); + pos = AddStatusMode(options, pos, prefix, flags&PF2_HEAVYDND); + pos = AddStatusMode(options, pos, prefix, flags&PF2_FREECHAT); + pos = AddStatusMode(options, pos, prefix, flags&PF2_OUTTOLUNCH); + pos = AddStatusMode(options, pos, prefix, flags&PF2_ONTHEPHONE); + return pos; +} + + +//Main Dialog Proc +void LoadOption_General() { + //Seconds + PopUpOptions.InfiniteDelay = DBGetContactSettingByte(NULL, MODULNAME, "InfiniteDelay", FALSE); + PopUpOptions.Seconds = DBGetContactSettingRangedWord(NULL, MODULNAME, "Seconds", + SETTING_LIFETIME_DEFAULT, SETTING_LIFETIME_MIN, SETTING_LIFETIME_MAX); + PopUpOptions.LeaveHovered = DBGetContactSettingByte(NULL, MODULNAME, "LeaveHovered", TRUE); + //Dynamic Resize + PopUpOptions.DynamicResize = DBGetContactSettingByte(NULL, MODULNAME, "DynamicResize", FALSE); + PopUpOptions.UseMinimumWidth = DBGetContactSettingByte(NULL, MODULNAME, "UseMinimumWidth", TRUE); + PopUpOptions.MinimumWidth = DBGetContactSettingWord(NULL, MODULNAME, "MinimumWidth", 160); + PopUpOptions.UseMaximumWidth = DBGetContactSettingByte(NULL, MODULNAME, "UseMaximumWidth", TRUE); + PopUpOptions.MaximumWidth = DBGetContactSettingWord(NULL, MODULNAME, "MaximumWidth", 300); + //Position + PopUpOptions.Position = DBGetContactSettingRangedByte(NULL, MODULNAME, "Position", + POS_LOWERRIGHT, POS_MINVALUE, POS_MAXVALUE); + //Configure popup area + PopUpOptions.gapTop = DBGetContactSettingWord(NULL, MODULNAME, "gapTop", 5); + PopUpOptions.gapBottom = DBGetContactSettingWord(NULL, MODULNAME, "gapBottom", 5); + PopUpOptions.gapLeft = DBGetContactSettingWord(NULL, MODULNAME, "gapLeft", 5); + PopUpOptions.gapRight = DBGetContactSettingWord(NULL, MODULNAME, "gapRight", 5); + PopUpOptions.spacing = DBGetContactSettingWord(NULL, MODULNAME, "spacing", 5); + //Spreading + PopUpOptions.Spreading = DBGetContactSettingRangedByte(NULL, MODULNAME, "Spreading", + SPREADING_VERTICAL, SPREADING_MINVALUE, SPREADING_MAXVALUE); + //miscellaneous + PopUpOptions.ReorderPopUps = DBGetContactSettingByte(NULL, MODULNAME, "ReorderPopUps", TRUE); + PopUpOptions.ReorderPopUpsWarning = DBGetContactSettingByte(NULL, MODULNAME, "ReorderPopUpsWarning", TRUE); + //disable When + PopUpOptions.ModuleIsEnabled = DBGetContactSettingByte(NULL, MODULNAME, "ModuleIsEnabled", TRUE); + PopUpOptions.DisableWhenFullscreen = DBGetContactSettingByte(NULL, MODULNAME, "DisableWhenFullscreen", TRUE); + //new status options (done inside WM_INITDIALOG) + //Debug (done inside LoadOptions()) +} + +INT_PTR CALLBACK DlgProcPopUpGeneral(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + static bool bDlgInit = false; //some controls send WM_COMMAND before or during WM_INITDIALOG + + static OPTTREE_OPTION *statusOptions = NULL; + static int statusOptionsCount = 0; + if (statusOptions) { + int index; + if (OptTree_ProcessMessage(hwnd, msg, wParam, lParam, &index, IDC_STATUSES, statusOptions, statusOptionsCount)) + return TRUE; + } + + switch (msg) { + case WM_INITDIALOG: { + HWND hCtrl = NULL; + + //Seconds of delay + { + CheckDlgButton(hwnd, IDC_INFINITEDELAY, PopUpOptions.InfiniteDelay); + CheckDlgButton(hwnd, IDC_LEAVEHOVERED, PopUpOptions.LeaveHovered); + EnableWindow(GetDlgItem(hwnd, IDC_SECONDS), !PopUpOptions.InfiniteDelay); + EnableWindow(GetDlgItem(hwnd, IDC_SECONDS_STATIC1), !PopUpOptions.InfiniteDelay); + EnableWindow(GetDlgItem(hwnd, IDC_SECONDS_STATIC2), !PopUpOptions.InfiniteDelay); + EnableWindow(GetDlgItem(hwnd, IDC_LEAVEHOVERED), !PopUpOptions.InfiniteDelay); + SetDlgItemInt(hwnd, IDC_SECONDS, PopUpOptions.Seconds, FALSE); + SendDlgItemMessage(hwnd, IDC_SECONDS_SPIN, UDM_SETRANGE, 0, (LPARAM)MAKELONG(SETTING_LIFETIME_MAX, SETTING_LIFETIME_MIN)); + } + + //Dynamic Resize + { + CheckDlgButton(hwnd, IDC_DYNAMICRESIZE, PopUpOptions.DynamicResize); + SetDlgItemText(hwnd, IDC_USEMAXIMUMWIDTH, PopUpOptions.DynamicResize ? _T("Maximum width"): _T("Width")); + //Minimum Width + CheckDlgButton(hwnd, IDC_USEMINIMUMWIDTH, PopUpOptions.UseMinimumWidth); + SendDlgItemMessage(hwnd, IDC_MINIMUMWIDTH_SPIN, UDM_SETRANGE, 0, (LPARAM)MAKELONG( + SETTING_MAXIMUMWIDTH_MAX, + SETTING_MINIMUMWIDTH_MIN) ); + SetDlgItemInt(hwnd, IDC_MINIMUMWIDTH, PopUpOptions.MinimumWidth, FALSE); + //Maximum Width + PopUpOptions.UseMaximumWidth = PopUpOptions.DynamicResize ? PopUpOptions.UseMaximumWidth : TRUE; + CheckDlgButton(hwnd, IDC_USEMAXIMUMWIDTH, PopUpOptions.UseMaximumWidth); + SendDlgItemMessage(hwnd, IDC_MAXIMUMWIDTH_SPIN, UDM_SETRANGE, 0, (LPARAM)MAKELONG( + SETTING_MAXIMUMWIDTH_MAX, + SETTING_MINIMUMWIDTH_MIN) ); + SetDlgItemInt(hwnd, IDC_MAXIMUMWIDTH, PopUpOptions.MaximumWidth, FALSE); + //And finally let's enable/disable them. + EnableWindow(GetDlgItem(hwnd, IDC_USEMINIMUMWIDTH), PopUpOptions.DynamicResize); + EnableWindow(GetDlgItem(hwnd, IDC_MINIMUMWIDTH), PopUpOptions.DynamicResize && PopUpOptions.UseMinimumWidth); + EnableWindow(GetDlgItem(hwnd, IDC_MINIMUMWIDTH_SPIN), PopUpOptions.DynamicResize && PopUpOptions.UseMinimumWidth); + EnableWindow(GetDlgItem(hwnd, IDC_MAXIMUMWIDTH), PopUpOptions.UseMaximumWidth); + EnableWindow(GetDlgItem(hwnd, IDC_MAXIMUMWIDTH_SPIN), PopUpOptions.UseMaximumWidth); + } + //Position combobox. + { + hCtrl = GetDlgItem(hwnd, IDC_WHERE); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("upper left corner")) ,POS_UPPERLEFT); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("lower left corner")) ,POS_LOWERLEFT); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("lower right corner")) ,POS_LOWERRIGHT); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("upper right corner")) ,POS_UPPERRIGHT); + SendDlgItemMessage(hwnd, IDC_WHERE, CB_SETCURSEL, (PopUpOptions.Position) , 0); + } + //Configure popup area + { + hCtrl = GetDlgItem(hwnd, IDC_CUSTOMPOS); + SendMessage(hCtrl, BUTTONSETASFLATBTN, 0, 0); + SendMessage(hCtrl, BUTTONADDTOOLTIP, (WPARAM)_T("Popup Area"), BATF_TCHAR); + SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_OPT_RESIZE,0)); + } + //Spreading combobox + { + hCtrl = GetDlgItem(hwnd, IDC_LAYOUT); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("horizontal")) ,SPREADING_HORIZONTAL); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("vertical")) ,SPREADING_VERTICAL); + SendDlgItemMessage(hwnd, IDC_LAYOUT, CB_SETCURSEL, (PopUpOptions.Spreading), 0); + } + //miscellaneous + { + CheckDlgButton(hwnd, IDC_REORDERPOPUPS, PopUpOptions.ReorderPopUps); + } + //Popup enabled + { + CheckDlgButton(hwnd, IDC_POPUPENABLED, PopUpOptions.ModuleIsEnabled?BST_UNCHECKED:BST_CHECKED); + CheckDlgButton(hwnd, IDC_DISABLEINFS, PopUpOptions.DisableWhenFullscreen); + EnableWindow(GetDlgItem(hwnd, IDC_DISABLEINFS), PopUpOptions.ModuleIsEnabled); + EnableWindow(GetDlgItem(hwnd, IDC_STATUSES), PopUpOptions.ModuleIsEnabled); + } + //new status options + { + int protocolCount = 0; + int i; + PROTOCOLDESCRIPTOR **protocols; + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&protocolCount, (LPARAM)&protocols); + DWORD globalFlags = 0; + for (i = 0; i < protocolCount; ++i) { + if (protocols[i]->type != PROTOTYPE_PROTOCOL) + continue; + DWORD protoFlags = CallProtoService(protocols[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0); + globalFlags |= protoFlags; + statusOptionsCount += CountStatusModes(protoFlags); + } + statusOptionsCount += CountStatusModes(globalFlags); + + statusOptions = new OPTTREE_OPTION[statusOptionsCount]; + + int pos = 0; + pos = AddStatusModes(statusOptions, pos, _T("Global Status"), globalFlags); + for (i = 0; i < protocolCount; ++i) { + if (protocols[i]->type != PROTOTYPE_PROTOCOL) + continue; + DWORD protoFlags = CallProtoService(protocols[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0); + if (!CountStatusModes(protoFlags)) + continue; + TCHAR prefix[128]; + wsprintf(prefix, _T("Protocol Status/%hs"), protocols[i]->szName); + pos = AddStatusModes(statusOptions, pos, prefix, protoFlags); + } + + int index; + OptTree_ProcessMessage(hwnd, msg, wParam, lParam, &index, IDC_STATUSES, statusOptions, statusOptionsCount); + + char prefix[128]; + LPTSTR pszSettingName = NULL; + for (i = 0; i < protocolCount; ++i) { + if (protocols[i]->type != PROTOTYPE_PROTOCOL) + continue; + DWORD protoFlags = CallProtoService(protocols[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0); + if (!CountStatusModes(protoFlags)) + continue; + + mir_snprintf(prefix, sizeof(prefix), "Protocol Status/%s", protocols[i]->szName); + pszSettingName = mir_a2t(prefix); + OptTree_SetOptions(hwnd, IDC_STATUSES, statusOptions, statusOptionsCount, + DBGetContactSettingDword(NULL, MODULNAME, prefix, 0), + pszSettingName); + mir_free(pszSettingName); pszSettingName = NULL; + } + OptTree_SetOptions(hwnd, IDC_STATUSES, statusOptions, statusOptionsCount, + DBGetContactSettingDword(NULL, MODULNAME, "Global Status", 0), + _T("Global Status")); + } + //Debug + { + #if defined(_DEBUG) + CheckDlgButton(hwnd, IDC_DEBUG, PopUpOptions.debug); + ShowWindow(GetDlgItem(hwnd, IDC_DEBUG), SW_SHOW); + #endif + } + + TranslateDialogDefault(hwnd); //do it on end of WM_INITDIALOG + bDlgInit = true; + }//end WM_INITDIALOG + return TRUE; + case WM_COMMAND: { + UINT idCtrl = LOWORD(wParam); + switch (HIWORD(wParam)) { + case BN_CLICKED: //Button controls + switch(idCtrl) { + case IDC_INFINITEDELAY: + { + PopUpOptions.InfiniteDelay = !PopUpOptions.InfiniteDelay; + EnableWindow(GetDlgItem(hwnd, IDC_SECONDS),!PopUpOptions.InfiniteDelay); + EnableWindow(GetDlgItem(hwnd, IDC_SECONDS_STATIC1), !PopUpOptions.InfiniteDelay); + EnableWindow(GetDlgItem(hwnd, IDC_SECONDS_STATIC2), !PopUpOptions.InfiniteDelay); + EnableWindow(GetDlgItem(hwnd, IDC_LEAVEHOVERED), !PopUpOptions.InfiniteDelay); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_LEAVEHOVERED: + { + PopUpOptions.LeaveHovered = !PopUpOptions.LeaveHovered; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_DYNAMICRESIZE: + { + PopUpOptions.DynamicResize=!PopUpOptions.DynamicResize; + EnableWindow(GetDlgItem(hwnd, IDC_USEMINIMUMWIDTH), PopUpOptions.DynamicResize); + EnableWindow(GetDlgItem(hwnd, IDC_MINIMUMWIDTH), PopUpOptions.DynamicResize && PopUpOptions.UseMinimumWidth); + EnableWindow(GetDlgItem(hwnd, IDC_MINIMUMWIDTH_SPIN), PopUpOptions.DynamicResize && PopUpOptions.UseMinimumWidth); + SetDlgItemText(hwnd, IDC_USEMAXIMUMWIDTH, PopUpOptions.DynamicResize ? TranslateT("Maximum width"): TranslateT("Width")); + if(!PopUpOptions.DynamicResize) { + PopUpOptions.UseMaximumWidth = TRUE; + CheckDlgButton(hwnd, IDC_USEMAXIMUMWIDTH, BST_CHECKED); + EnableWindow(GetDlgItem(hwnd, IDC_USEMAXIMUMWIDTH), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_MAXIMUMWIDTH), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_MAXIMUMWIDTH_SPIN), TRUE); + } + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_USEMINIMUMWIDTH: + { + PopUpOptions.UseMinimumWidth= !PopUpOptions.UseMinimumWidth; + EnableWindow(GetDlgItem(hwnd, IDC_MINIMUMWIDTH), PopUpOptions.UseMinimumWidth); + EnableWindow(GetDlgItem(hwnd, IDC_MINIMUMWIDTH_SPIN), PopUpOptions.UseMinimumWidth); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_USEMAXIMUMWIDTH: + { + PopUpOptions.UseMaximumWidth= Button_GetCheck((HWND)lParam); + if(!PopUpOptions.DynamicResize) { //ugly - set always on if DynamicResize = off + CheckDlgButton(hwnd, idCtrl, BST_CHECKED); + PopUpOptions.UseMaximumWidth = TRUE; + } + EnableWindow(GetDlgItem(hwnd, IDC_MAXIMUMWIDTH), PopUpOptions.UseMaximumWidth); + EnableWindow(GetDlgItem(hwnd, IDC_MAXIMUMWIDTH_SPIN), PopUpOptions.UseMaximumWidth); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_CUSTOMPOS: + { + RECT rcButton, rcBox; + HWND hwndBox = CreateDialog(hInst, MAKEINTRESOURCE(IDD_POSITION), NULL, PositionBoxDlgProc); + GetWindowRect((HWND)lParam, &rcButton); + GetWindowRect(hwndBox, &rcBox); + MoveWindow(hwndBox, + rcButton.right-(rcBox.right-rcBox.left) + 15, + rcButton.bottom + 3, + rcBox.right-rcBox.left, + rcBox.bottom-rcBox.top, + FALSE); +#if defined(_UNICODE) + SetWindowLongPtr(hwndBox, GWL_EXSTYLE, GetWindowLongPtr(hwndBox, GWL_EXSTYLE)|WS_EX_LAYERED); + SetLayeredWindowAttributes(hwndBox, NULL, 0, LWA_ALPHA); + ShowWindow(hwndBox, SW_SHOW); + for (int i = 0; i <= 255; i += 15) { + SetLayeredWindowAttributes(hwndBox, NULL, i, LWA_ALPHA); + UpdateWindow(hwndBox); + Sleep(1); + } + SetWindowLongPtr(hwndBox, GWL_EXSTYLE, GetWindowLongPtr(hwndBox, GWL_EXSTYLE)&~WS_EX_LAYERED); +#else + if (MySetLayeredWindowAttributes) { + SetWindowLongPtr(hwndBox, GWL_EXSTYLE, GetWindowLongPtr(hwndBox, GWL_EXSTYLE)|WS_EX_LAYERED); + MySetLayeredWindowAttributes(hwndBox, NULL, 0, LWA_ALPHA); + ShowWindow(hwndBox, SW_SHOW); + for (int i = 0; i <= 255; i += 15) { + MySetLayeredWindowAttributes(hwndBox, NULL, i, LWA_ALPHA); + UpdateWindow(hwndBox); + Sleep(1); + } + SetWindowLongPtr(hwndBox, GWL_EXSTYLE, GetWindowLongPtr(hwndBox, GWL_EXSTYLE)&~WS_EX_LAYERED); + } +#endif + ShowWindow(hwndBox, SW_SHOW); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_REORDERPOPUPS: + { + PopUpOptions.ReorderPopUps = !PopUpOptions.ReorderPopUps; + PopUpOptions.ReorderPopUpsWarning = PopUpOptions.ReorderPopUps ? + DBGetContactSettingByte(NULL, MODULNAME, "ReorderPopUpsWarning", TRUE) : TRUE; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + case IDC_POPUPENABLED: + {//PopUpOptions.ModuleIsEnabled is set and store by EnableDisable menu service !!!!!! + int chk = IsDlgButtonChecked(hwnd, IDC_POPUPENABLED); + if (PopUpOptions.ModuleIsEnabled&&chk || !PopUpOptions.ModuleIsEnabled&&!chk) + svcEnableDisableMenuCommand(0,0); + EnableWindow(GetDlgItem(hwnd, IDC_STATUSES), PopUpOptions.ModuleIsEnabled); + EnableWindow(GetDlgItem(hwnd, IDC_DISABLEINFS), PopUpOptions.ModuleIsEnabled); + } + break; + case IDC_DISABLEINFS: + { + PopUpOptions.DisableWhenFullscreen = !PopUpOptions.DisableWhenFullscreen; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + #if defined(_DEBUG) //DEBUG + case IDC_DEBUG: + PopUpOptions.debug = (BYTE)Button_GetCheck((HWND)lParam); + //The following line is dangerous, but useful for my debug purposes. + //MySetLayeredWindowAttributes = (BOOL)!MySetLayeredWindowAttributes; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + #endif //DEBUG + case IDC_PREVIEW: + { + PopUpPreview(); + } + break; + default: + break; + } + break; + case CBN_SELCHANGE: //ComboBox controls + switch(idCtrl) { + //lParam = Handle to the control + case IDC_WHERE: + PopUpOptions.Position = ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IDC_LAYOUT: + PopUpOptions.Spreading = ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + default: + break; + } + break; + case EN_CHANGE: //Edit controls change + if(!bDlgInit) break; + switch(idCtrl) { + //lParam = Handle to the control + case IDC_SECONDS: + { + int seconds = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if ( seconds >= SETTING_LIFETIME_MIN && + seconds <= SETTING_LIFETIME_MAX && + seconds != PopUpOptions.Seconds) { + PopUpOptions.Seconds = seconds; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + case IDC_MINIMUMWIDTH: + { + int temp = GetDlgItemInt(hwnd, IDC_MINIMUMWIDTH, NULL, FALSE); + if ( temp >= SETTING_MINIMUMWIDTH_MIN && + temp <= SETTING_MAXIMUMWIDTH_MAX && + temp != PopUpOptions.MinimumWidth) { + PopUpOptions.MinimumWidth = temp; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + case IDC_MAXIMUMWIDTH: + { + int temp = GetDlgItemInt(hwnd, IDC_MAXIMUMWIDTH, NULL, FALSE); + if ( temp >= SETTING_MINIMUMWIDTH_MIN && + temp <= SETTING_MAXIMUMWIDTH_MAX && + temp != PopUpOptions.MaximumWidth) { + PopUpOptions.MaximumWidth = temp; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + default: + break; + }//end switch(idCtrl) + break; + case EN_KILLFOCUS: //Edit controls lost fokus + switch(idCtrl) { + //lParam = Handle to the control + case IDC_SECONDS: + { + int seconds = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if (seconds > SETTING_LIFETIME_MAX) + PopUpOptions.Seconds = SETTING_LIFETIME_MAX; + else if (seconds < SETTING_LIFETIME_MIN) + PopUpOptions.Seconds = SETTING_LIFETIME_MIN; + if(seconds != PopUpOptions.Seconds) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.Seconds, FALSE); + ErrorMSG(SETTING_LIFETIME_MIN, SETTING_LIFETIME_MAX); + SetFocus((HWND)lParam); + } + } + break; + case IDC_MINIMUMWIDTH: + { + int temp = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if (temp < SETTING_MINIMUMWIDTH_MIN) + PopUpOptions.MinimumWidth = SETTING_MINIMUMWIDTH_MIN; + else if(temp > SETTING_MAXIMUMWIDTH_MAX) + PopUpOptions.MinimumWidth = SETTING_MAXIMUMWIDTH_MAX; + if(temp != PopUpOptions.MinimumWidth) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.MinimumWidth, FALSE); + ErrorMSG(SETTING_MINIMUMWIDTH_MIN, SETTING_MAXIMUMWIDTH_MAX); + SetFocus((HWND)lParam); + break; + } + if (temp > PopUpOptions.MaximumWidth) { + PopUpOptions.MaximumWidth = min(temp, SETTING_MAXIMUMWIDTH_MAX); + SetDlgItemInt(hwnd, IDC_MAXIMUMWIDTH, PopUpOptions.MaximumWidth, FALSE); + } + } + break; + case IDC_MAXIMUMWIDTH: + { + int temp = GetDlgItemInt(hwnd, idCtrl, NULL, FALSE); + if (temp >= SETTING_MAXIMUMWIDTH_MAX) + PopUpOptions.MaximumWidth = SETTING_MAXIMUMWIDTH_MAX; + else if(temp < SETTING_MINIMUMWIDTH_MIN) + PopUpOptions.MaximumWidth = SETTING_MINIMUMWIDTH_MIN; + if(temp != PopUpOptions.MaximumWidth) { + SetDlgItemInt(hwnd, idCtrl, PopUpOptions.MaximumWidth, FALSE); + ErrorMSG(SETTING_MINIMUMWIDTH_MIN, SETTING_MAXIMUMWIDTH_MAX); + SetFocus((HWND)lParam); + break; + } + if (temp < PopUpOptions.MinimumWidth) { + PopUpOptions.MinimumWidth = max(temp, SETTING_MINIMUMWIDTH_MIN); + SetDlgItemInt(hwnd, IDC_MINIMUMWIDTH, PopUpOptions.MinimumWidth, FALSE); + } + } + break; + default: + break; + }//end switch(idCtrl) + break; + default: + break; + }// end switch (HIWORD(wParam)) + }//end WM_COMMAND + break; + case WM_NOTIFY: { + switch(((LPNMHDR)lParam)->idFrom) { + case 0: { + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + LoadOption_General(); + return TRUE; + case PSN_APPLY: { + //Seconds + DBWriteContactSettingByte(NULL, MODULNAME, "InfiniteDelay", PopUpOptions.InfiniteDelay); + DBWriteContactSettingWord(NULL, MODULNAME, "Seconds", (WORD)PopUpOptions.Seconds); + DBWriteContactSettingByte(NULL, MODULNAME, "LeaveHovered", PopUpOptions.LeaveHovered); + //Dynamic Resize + DBWriteContactSettingByte(NULL, MODULNAME, "DynamicResize", PopUpOptions.DynamicResize); + DBWriteContactSettingByte(NULL, MODULNAME, "UseMinimumWidth", PopUpOptions.UseMinimumWidth); + DBWriteContactSettingWord(NULL, MODULNAME, "MinimumWidth", PopUpOptions.MinimumWidth); + DBWriteContactSettingByte(NULL, MODULNAME, "UseMaximumWidth", PopUpOptions.UseMaximumWidth); + DBWriteContactSettingWord(NULL, MODULNAME, "MaximumWidth", PopUpOptions.MaximumWidth); + //Position + DBWriteContactSettingByte(NULL, MODULNAME, "Position", (BYTE)PopUpOptions.Position); + //Configure popup area + DBWriteContactSettingWord(NULL, MODULNAME, "gapTop", (WORD)PopUpOptions.gapTop); + DBWriteContactSettingWord(NULL, MODULNAME, "gapBottom", (WORD)PopUpOptions.gapBottom); + DBWriteContactSettingWord(NULL, MODULNAME, "gapLeft", (WORD)PopUpOptions.gapLeft); + DBWriteContactSettingWord(NULL, MODULNAME, "gapRight", (WORD)PopUpOptions.gapRight); + DBWriteContactSettingWord(NULL, MODULNAME, "spacing", (WORD)PopUpOptions.spacing); + //Spreading + DBWriteContactSettingByte(NULL, MODULNAME, "Spreading", (BYTE)PopUpOptions.Spreading); + //miscellaneous + //DBWriteContactSettingByte(NULL, MODULNAME, "ReorderPopUps", PopUpOptions.ReorderPopUps); + Check_ReorderPopUps(hwnd); //this save also PopUpOptions.ReorderPopUps + //disable When + DBWriteContactSettingByte(NULL, MODULNAME, "DisableWhenFullscreen", PopUpOptions.DisableWhenFullscreen); + //new status options + { + int protocolCount; + PROTOCOLDESCRIPTOR **protocols; + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&protocolCount, (LPARAM)&protocols); + + char prefix[128]; + LPTSTR pszSettingName = NULL; + for (int i = 0; i < protocolCount; ++i) + { + if (protocols[i]->type != PROTOTYPE_PROTOCOL) + continue; + + mir_snprintf(prefix, sizeof(prefix), "Protocol Status/%s", protocols[i]->szName); + pszSettingName = mir_a2t(prefix); + DBWriteContactSettingDword(NULL, MODULNAME, prefix, + OptTree_GetOptions(hwnd, IDC_STATUSES, statusOptions, statusOptionsCount, pszSettingName)); + mir_free(pszSettingName); pszSettingName = NULL; + } + DBWriteContactSettingDword(NULL, MODULNAME, "Global Status", + OptTree_GetOptions(hwnd, IDC_STATUSES, statusOptions, statusOptionsCount, _T("Global Status"))); + } + //Debug + #if defined(_DEBUG) + DBWriteContactSettingByte(NULL, MODULNAME, "debug", PopUpOptions.debug); + #endif + + }//end PSN_APPLY: + return TRUE; + default: + break; + } + } + break; + case IDC_MINIMUMWIDTH_SPIN: + { + LPNMUPDOWN lpnmud = (LPNMUPDOWN) lParam; + int temp = lpnmud->iPos + lpnmud->iDelta; + if (temp > PopUpOptions.MaximumWidth) { + PopUpOptions.MaximumWidth = min(temp, SETTING_MAXIMUMWIDTH_MAX); + SetDlgItemInt(hwnd, IDC_MAXIMUMWIDTH, PopUpOptions.MaximumWidth, FALSE); + } + } + break; + case IDC_MAXIMUMWIDTH_SPIN: + { + LPNMUPDOWN lpnmud = (LPNMUPDOWN) lParam; + int temp = lpnmud->iPos + lpnmud->iDelta; + if (temp < PopUpOptions.MinimumWidth) { + PopUpOptions.MinimumWidth = max(temp, SETTING_MINIMUMWIDTH_MIN); + SetDlgItemInt(hwnd, IDC_MINIMUMWIDTH, PopUpOptions.MinimumWidth, FALSE); + } + } + break; + default: + break; + } + }//end WM_NOTIFY + break; + case WM_DESTROY: { + if (statusOptions) { + for (int i = 0; i < statusOptionsCount; ++i) { + mir_free(statusOptions[i].pszOptionName); + mir_free(statusOptions[i].pszSettingName); + } + delete [] statusOptions; + statusOptions = NULL; + statusOptionsCount = 0; + bDlgInit = false; + } + }//end WM_DESTROY + break; + default: + return FALSE; + }//end switch (msg) + return FALSE; +} + +void ErrorMSG(int minValue, int maxValue) { + TCHAR str[128]; + wsprintf(str, TranslateT("You cannot specify a value lower than %d and higher than %d."), minValue, maxValue); + MSGERROR(str); +} + +void Check_ReorderPopUps(HWND hwnd) { + if (!PopUpOptions.ReorderPopUps && PopUpOptions.ReorderPopUpsWarning) + { + int res = MessageBox(hwnd, + TranslateTS( + _T("'Reorder Popups' option is currently diabled.\r\n") + _T("This may cause misaligned popups when used with\r\n") + _T("avatars and text replacement (mainly NewStatusNotify).\r\n") + _T("\r\n") + _T("Do you want to enable popup reordering now?\r\n") + ), + TranslateT("Popup Plus Warning"), MB_ICONEXCLAMATION|MB_YESNOCANCEL); + + switch (res) + { + case IDYES: + PopUpOptions.ReorderPopUps = TRUE; + //Reset warning for next option change !!! + PopUpOptions.ReorderPopUpsWarning = TRUE; + break; + case IDNO: + PopUpOptions.ReorderPopUps = FALSE; + PopUpOptions.ReorderPopUpsWarning = FALSE; + break; + default: + return; + } + } + DBWriteContactSettingByte(NULL, MODULNAME, "ReorderPopUps", PopUpOptions.ReorderPopUps); + DBWriteContactSettingByte(NULL, MODULNAME, "ReorderPopUpsWarning", PopUpOptions.ReorderPopUpsWarning); + if(hwnd) CheckDlgButton(hwnd, IDC_REORDERPOPUPS, PopUpOptions.ReorderPopUps); +} + +void ThemeDialogBackground(HWND hwnd) { + if (IsWinVerXPPlus()) { + static HMODULE hThemeAPI = NULL; + if (!hThemeAPI) hThemeAPI = GetModuleHandleA("uxtheme"); + if (hThemeAPI) { + HRESULT (STDAPICALLTYPE *MyEnableThemeDialogTexture)(HWND,DWORD) = (HRESULT (STDAPICALLTYPE*)(HWND,DWORD))GetProcAddress(hThemeAPI,"EnableThemeDialogTexture"); + if (MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture(hwnd,0x00000002|0x00000004); //0x00000002|0x00000004=ETDT_ENABLETAB + } + } +} + +INT_PTR CALLBACK PositionBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HFONT hFontTitle = 0; + switch (msg) + { + case WM_INITDIALOG: + ThemeDialogBackground(hwndDlg); + + LOGFONT lf; + GetObject((HFONT)SendMessage(GetDlgItem(hwndDlg, IDC_TITLE), WM_GETFONT, 0, 0), sizeof(lf), &lf); + lf.lfWeight = FW_BOLD; + lf.lfHeight *= 1.2; + hFontTitle = CreateFontIndirect(&lf); + SendMessage(GetDlgItem(hwndDlg, IDC_TITLE), WM_SETFONT, (WPARAM)hFontTitle, TRUE); + + SendMessage(GetDlgItem(hwndDlg, IDOK), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwndDlg, IDOK), BUTTONADDTOOLTIP, (WPARAM)_T("OK"), BATF_TCHAR); + SendMessage(GetDlgItem(hwndDlg, IDOK), BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_OPT_OK,0)); + + SendMessage(GetDlgItem(hwndDlg, IDCANCEL), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwndDlg, IDCANCEL), BUTTONADDTOOLTIP, (WPARAM)_T("Cancel"), BATF_TCHAR); + SendMessage(GetDlgItem(hwndDlg, IDCANCEL), BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_OPT_CANCEL,0)); + + SetDlgItemInt(hwndDlg, IDC_TXT_TOP, PopUpOptions.gapTop, FALSE); + SetDlgItemInt(hwndDlg, IDC_TXT_BOTTOM, PopUpOptions.gapBottom, FALSE); + SetDlgItemInt(hwndDlg, IDC_TXT_LEFT, PopUpOptions.gapLeft, FALSE); + SetDlgItemInt(hwndDlg, IDC_TXT_RIGHT, PopUpOptions.gapRight, FALSE); + SetDlgItemInt(hwndDlg, IDC_TXT_SPACING, PopUpOptions.spacing, FALSE); + + TranslateDialogDefault(hwndDlg); + break; + case WM_COMMAND: + if ((LOWORD(wParam)) == IDOK) + { + PopUpOptions.gapTop = GetDlgItemInt(hwndDlg, IDC_TXT_TOP, NULL, FALSE); + PopUpOptions.gapBottom = GetDlgItemInt(hwndDlg, IDC_TXT_BOTTOM, NULL, FALSE); + PopUpOptions.gapLeft = GetDlgItemInt(hwndDlg, IDC_TXT_LEFT, NULL, FALSE); + PopUpOptions.gapRight = GetDlgItemInt(hwndDlg, IDC_TXT_RIGHT, NULL, FALSE); + PopUpOptions.spacing = GetDlgItemInt(hwndDlg, IDC_TXT_SPACING, NULL, FALSE); + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + } else + if ((LOWORD(wParam)) == IDCANCEL) + { + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + case WM_ACTIVATE: + if (wParam == WA_INACTIVE) + { + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + case WM_DESTROY: + DeleteObject(hFontTitle); + break; + } + return FALSE; +} diff --git a/Popup/src/opt_gen.h b/Popup/src/opt_gen.h new file mode 100644 index 0000000..1f61f6b --- /dev/null +++ b/Popup/src/opt_gen.h @@ -0,0 +1,43 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_gen.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __opt_gen_h__ +#define __opt_gen_h__ + +void LoadOption_General(); +void Check_ReorderPopUps(HWND hwnd = 0); +INT_PTR CALLBACK DlgProcPopUpGeneral(HWND, UINT, WPARAM, LPARAM); + +void ErrorMSG(int minValue, int maxValue); + + +#endif // __opt_gen_h__ diff --git a/Popup/src/opt_skins.cpp b/Popup/src/opt_skins.cpp new file mode 100644 index 0000000..d91efe5 --- /dev/null +++ b/Popup/src/opt_skins.cpp @@ -0,0 +1,695 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_skins.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +static volatile bool gPreviewOk = false; +static PopupWnd2 *wndPreview = NULL; + +INT_PTR CALLBACK BoxPreviewWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +void RegisterOptPrevBox() +{ + DWORD err; + WNDCLASSEX wcl; + wcl.cbSize = sizeof(wcl); + wcl.lpfnWndProc = (WNDPROC)BoxPreviewWndProc; + wcl.style = IsWinVerXPPlus() ? CS_DROPSHADOW : 0; + wcl.cbClsExtra = 0; + wcl.cbWndExtra = 0; + wcl.hInstance = hInst; + wcl.hIcon = NULL; + wcl.hCursor = LoadCursor(NULL, IDC_ARROW); + wcl.hbrBackground = NULL; //(HBRUSH)GetStockObject(LTGRAY_BRUSH); + wcl.lpszMenuName = NULL; + wcl.lpszClassName = _T(BOXPREVIEW_WNDCLASS); + wcl.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_POPUP), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + g_wndClass.cPopupPreviewBoxWndclass = RegisterClassEx(&wcl); + err = GetLastError(); + if (!g_wndClass.cPopupPreviewBoxWndclass) { + TCHAR msg[1024]; + wsprintf(msg, TranslateT("Failed to register %s class."),wcl.lpszClassName); + MSGERROR(msg); + } + + // register custom class for dialog box with drop-shadow attribute + // "#32770" stays for class name of default system dialog box + GetClassInfoEx(hInst, _T("#32770"), &wcl); + wcl.hInstance = hInst; + wcl.lpszClassName = _T("PopupPlusDlgBox"); + wcl.style |= IsWinVerXPPlus() ? CS_DROPSHADOW : 0; + g_wndClass.cPopupPlusDlgBox = RegisterClassEx(&wcl); + err = GetLastError(); + if (!g_wndClass.cPopupPlusDlgBox) { + TCHAR msg[1024]; + wsprintf(msg, TranslateT("Failed to register %s class."),wcl.lpszClassName); + MSGERROR(msg); + } +} + +static void updatePreviewImage(HWND hwndBox) +{ + gPreviewOk = false; + + POPUPDATA2 ppd; + ZeroMemory(&ppd, sizeof(ppd)); + ppd.cbSize = sizeof(ppd); + ppd.flags = PU2_TCHAR; + ppd.lchIcon = LoadSkinnedIcon(SKINICON_STATUS_ONLINE); + ppd.lptzTitle = TranslateT("Skin preview"); + ppd.lptzText = TranslateT("Just take a look at this skin... ;)"); + + POPUPOPTIONS customOptions = PopUpOptions; + customOptions.DynamicResize = FALSE; + customOptions.MinimumWidth = customOptions.MaximumWidth = 250; + + if (wndPreview) delete wndPreview; + wndPreview = new PopupWnd2(&ppd, &customOptions, true); + wndPreview->buildMText(); + wndPreview->update(); + gPreviewOk = true; + + InvalidateRect(hwndBox, NULL, TRUE); +} + +static void DrawPreview(HWND hwnd, HDC hdc) +{ + RECT rc; + HBRUSH hbr; + + BITMAPINFO bi; + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = 8; + bi.bmiHeader.biHeight = -8; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + HBITMAP hBmpBrush = (HBITMAP)CreateDIBSection(0, &bi, DIB_RGB_COLORS, 0, 0, 0); + HDC dcBmp = CreateCompatibleDC(0); + HBITMAP hBmpSave = (HBITMAP)SelectObject(dcBmp, hBmpBrush); + hbr = CreateSolidBrush(RGB(0xcc, 0xcc, 0xcc)); + SetRect(&rc, 0, 0, 8, 8); + FillRect(dcBmp, &rc, hbr); + DeleteObject(hbr); + hbr = CreateSolidBrush(RGB(0xff, 0xff, 0xff)); + SetRect(&rc, 4, 0, 8, 4); + FillRect(dcBmp, &rc, hbr); + SetRect(&rc, 0, 4, 4, 8); + FillRect(dcBmp, &rc, hbr); + DeleteObject(hbr); + SelectObject(dcBmp, hBmpSave); + DeleteDC(dcBmp); + + GetClientRect(hwnd, &rc); + hbr = CreatePatternBrush(hBmpBrush); + SetBrushOrgEx(hdc, 1, 1, 0); + FillRect(hdc, &rc, hbr); + DeleteObject(hbr); + DeleteObject(hBmpBrush); + + if (gPreviewOk) + { + int width = min(rc.right, wndPreview->getContent()->getWidth()); + int height = min(rc.bottom, wndPreview->getContent()->getHeight()); + int left = (rc.right - width) / 2; + int top = (rc.bottom - height) / 2; + +#if defined(_UNICODE) + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + AlphaBlend(hdc, left, top, width, height, + wndPreview->getContent()->getDC(), + 0, 0, width, height, bf); +#else + if (MyAlphaBlend) { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + MyAlphaBlend(hdc, left, top, width, height, + wndPreview->getContent()->getDC(), + 0, 0, width, height, bf); + } + else { + BitBlt(hdc, + left, top, left+width, top+height, + wndPreview->getContent()->getDC(), + 0, 0, SRCCOPY); + } +#endif + } + + FrameRect(hdc, &rc, GetStockBrush(LTGRAY_BRUSH)); +} + +static WNDPROC WndProcPreviewBoxSave; +LRESULT CALLBACK WndProcPreviewBox(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (!wndPreview) + return CallWindowProc(WndProcPreviewBoxSave, hwnd, msg, wParam, lParam); + + switch (msg) + { + case WM_PAINT: + { + if (GetUpdateRect(hwnd, 0, FALSE)) + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + DrawPreview(hwnd, hdc); + EndPaint(hwnd, &ps); + return 0; + } + } + + case WM_PRINT: + case WM_PRINTCLIENT: + { + HDC hdc = (HDC)wParam; + DrawPreview(hwnd, hdc); + return 0; + } + } + return CallWindowProc(WndProcPreviewBoxSave, hwnd, msg, wParam, lParam); +} + +int SkinOptionList_AddSkin(OPTTREE_OPTION* &options, int *OptionsCount, int pos, DWORD *dwGlobalOptions) { + const PopupSkin *skin = 0; + LPTSTR pszName = NULL; + if (skin = skins.getSkin(PopUpOptions.SkinPack)) { + for (int i = 1; i <= 10; i++) { + if(!skin->getFlagName(i)) + continue; + *OptionsCount += 1; + options = (OPTTREE_OPTION*)mir_realloc(options,sizeof(OPTTREE_OPTION)*(*OptionsCount)); + options[pos].dwFlag = (DWORD)(1 << (i-1)); + options[pos].groupId = OPTTREE_CHECK; + options[pos].iconIndex = 0; + options[pos].pszSettingName = mir_tstrdup(_T("Skin options")); + options[pos].pszOptionName = (LPTSTR)mir_alloc(sizeof(TCHAR)*( + lstrlen(options[pos].pszSettingName)+ + lstrlenA(skin->getFlagName(i)) +10 )); + wsprintf(options[pos].pszOptionName,_T("%s/%hs"), options[pos].pszSettingName, skin->getFlagName(i)); + options[pos].bState = skin->getFlag(i) ? TRUE : FALSE; + options[pos].Data = i; //skin flag index + *dwGlobalOptions |= skin->getFlag(i) ? (1 << (i-1)) : 0; + pos++; + } + } + return pos; +} + +int SkinOptionList_AddMain(OPTTREE_OPTION* &options, int *OptionsCount, int pos, DWORD *dwGlobalOptions) { + BOOL bCheck; + LPTSTR mainOption [] = { + LPGENT("Show clock"), + LPGENT("Drop shadow effect (Windows XP+)"), + LPGENT("Drop shadow effect (Windows XP+)/non rectangular"), + LPGENT("Enable Aero Glass (Vista+)"), + LPGENT("Use Windows colours"), + LPGENT("Use advanced text render")}; + for (int i = 0; i < SIZEOF(mainOption); i++) { + bCheck = 0; + switch (i) { + case 0: + *dwGlobalOptions |= PopUpOptions.DisplayTime ? (1 << i) : 0; + bCheck = PopUpOptions.DisplayTime; + break; + case 1: + if(!IsWinVerXPPlus()) continue; + *dwGlobalOptions |= PopUpOptions.DropShadow ? (1 << i) : 0; + bCheck = PopUpOptions.DropShadow; + break; + case 2: + if(!IsWinVerXPPlus()) continue; + *dwGlobalOptions |= PopUpOptions.EnableFreeformShadows ? (1 << i) : 0; + bCheck = PopUpOptions.EnableFreeformShadows; + break; + case 3: + if(!MyDwmEnableBlurBehindWindow) continue; + *dwGlobalOptions |= PopUpOptions.EnableAeroGlass ? (1 << i) : 0; + bCheck = PopUpOptions.EnableAeroGlass; + break; + case 4: + *dwGlobalOptions |= PopUpOptions.UseWinColors ? (1 << i) : 0; + bCheck = PopUpOptions.UseWinColors; + break; + case 5: + if(!(htuText&&htuTitle)) continue; + *dwGlobalOptions |= PopUpOptions.UseMText ? (1 << i) : 0; + bCheck = PopUpOptions.UseMText; + break; + default: + break; + } + *OptionsCount += 1; + options = (OPTTREE_OPTION*)mir_realloc(options,sizeof(OPTTREE_OPTION)*(*OptionsCount)); + options[pos].dwFlag = (1 << i); + options[pos].groupId = OPTTREE_CHECK; + options[pos].iconIndex = 0; + options[pos].pszSettingName = mir_tstrdup(_T("Global settings")); + options[pos].pszOptionName = (LPTSTR)mir_alloc(sizeof(TCHAR)*( + lstrlen(options[pos].pszSettingName)+ + lstrlen(mainOption[i]) + 10)); + wsprintf(options[pos].pszOptionName,_T("%s/%s"), options[pos].pszSettingName, mainOption[i]); + options[pos].bState = bCheck; + pos++; + } + return pos; +} + +bool SkinOptionList_Update (OPTTREE_OPTION* &options, int *OptionsCount, HWND hwndDlg) { + if (options) { + int index = -1; + OptTree_ProcessMessage(hwndDlg, WM_DESTROY, 0, 0, &index, IDC_SKIN_LIST_OPT, options, *OptionsCount); + for (int i = 0; i < *OptionsCount; ++i) { + mir_free(options[i].pszOptionName); + mir_free(options[i].pszSettingName); + } + mir_free(options); + options = NULL; + *OptionsCount = 0; + } + int pos = 0; + //add "Global options" + DWORD dwGlobalOptions = 0; + pos = SkinOptionList_AddMain(options, OptionsCount, pos, &dwGlobalOptions); + //add "Skin options" + DWORD dwSkinOptions = 0; + pos = SkinOptionList_AddSkin(options, OptionsCount, pos, &dwSkinOptions); + //generate treeview + int index = -1; + OptTree_ProcessMessage(hwndDlg, WM_INITDIALOG, 0, 0, &index, IDC_SKIN_LIST_OPT, options, *OptionsCount); + + //check "Skin options" state + char prefix[128]; + mir_snprintf(prefix, sizeof(prefix),"skin."TCHAR_STR_PARAM, PopUpOptions.SkinPack); + OptTree_SetOptions(hwndDlg, IDC_SKIN_LIST_OPT, options, *OptionsCount, + DBGetContactSettingDword(NULL, MODULNAME, prefix, dwSkinOptions), _T("Skin options")); + + //check "Global Settings" + OptTree_SetOptions(hwndDlg, IDC_SKIN_LIST_OPT, options, *OptionsCount, + dwGlobalOptions, _T("Global settings")); + + return true; +} + +void LoadOption_Skins() { + //skin pack + PopUpOptions.SkinPack = (LPTSTR)DBGetContactSettingStringX(NULL,MODULNAME, "SkinPack", "* Popup Classic",DBVT_TCHAR); + //more Skin options + PopUpOptions.DisplayTime = DBGetContactSettingByte(NULL,MODULNAME, "DisplayTime", TRUE); + PopUpOptions.DropShadow = DBGetContactSettingByte(NULL,MODULNAME, "DropShadow", TRUE); + PopUpOptions.EnableFreeformShadows = DBGetContactSettingByte(NULL,MODULNAME, "EnableShadowRegion", 1); + PopUpOptions.EnableAeroGlass = DBGetContactSettingByte(NULL,MODULNAME, "EnableAeroGlass", 1); + PopUpOptions.UseWinColors = DBGetContactSettingByte(NULL,MODULNAME, "UseWinColors", FALSE); + PopUpOptions.UseMText = DBGetContactSettingByte(NULL,MODULNAME, "UseMText", TRUE); +} + +INT_PTR CALLBACK DlgProcPopSkinsOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static bool bDlgInit = false; //some controls send WM_COMMAND before or during WM_INITDIALOG + static HANDLE hhkFontsReload = 0; + static OPTTREE_OPTION *skinOptions = NULL; + static int skinOptionsCount = 0; + + if (skinOptions) { + int index = -1; + OptTree_ProcessMessage(hwndDlg, msg, wParam, lParam, &index, IDC_SKIN_LIST_OPT, skinOptions, skinOptionsCount); + if (index != -1) { + if(lstrcmp(skinOptions[index].pszSettingName, _T("Skin options")) == 0) { + const PopupSkin *skin = 0; + if (skin = skins.getSkin(PopUpOptions.SkinPack)) { + skin->setFlag(skinOptions[index].Data, skinOptions[index].bState ? true : false); + } + } + else if (lstrcmp(skinOptions[index].pszSettingName, _T("Global settings")) == 0) { + switch (skinOptions[index].dwFlag) { + case (1 << 0): + PopUpOptions.DisplayTime = skinOptions[index].bState; + break; + case (1 << 1): + PopUpOptions.DropShadow = skinOptions[index].bState; + break; + case (1 << 2): + PopUpOptions.EnableFreeformShadows = skinOptions[index].bState; + break; + case (1 << 3): + PopUpOptions.EnableAeroGlass = skinOptions[index].bState; + break; + case (1 << 4): + PopUpOptions.UseWinColors = skinOptions[index].bState; + break; + case (1 << 5): + PopUpOptions.UseMText = skinOptions[index].bState; + break; + default: + break; + } + } + updatePreviewImage(GetDlgItem(hwndDlg, IDC_PREVIEWBOX)); + return FALSE; + } + } + + switch (msg) { + case WM_INITDIALOG: + { + HWND hCtrl = NULL; + DWORD dwIndex = 0; + + //Skin List + hCtrl = GetDlgItem(hwndDlg, IDC_SKINLIST); + ListBox_ResetContent(hCtrl); + LPTSTR Temp = NULL; + for (const Skins::SKINLIST *sl = skins.getSkinList(); sl; sl = sl->next) + { + dwIndex = ListBox_AddString(hCtrl, sl->name); + ListBox_SetItemData(hCtrl, dwIndex, sl->name); + } + ListBox_SetCurSel(hCtrl, ListBox_FindString(hCtrl, 0, PopUpOptions.SkinPack)); + + //Skin List reload button + SendMessage(GetDlgItem(hwndDlg, IDC_BTN_RELOAD), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwndDlg, IDC_BTN_RELOAD), BM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon(ICO_OPT_RELOAD,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_BTN_RELOAD), BUTTONADDTOOLTIP, (WPARAM)Translate("Refresh List"), 0); + + //Skin Option List + SkinOptionList_Update (skinOptions, &skinOptionsCount, hwndDlg); + + //PreviewBox + WndProcPreviewBoxSave = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PREVIEWBOX), GWLP_WNDPROC, (LONG_PTR)WndProcPreviewBox); + updatePreviewImage(GetDlgItem(hwndDlg, IDC_PREVIEWBOX)); + + //hooks + hhkFontsReload = HookEventMessage(ME_FONT_RELOAD, hwndDlg, WM_USER); + + TranslateDialogDefault(hwndDlg); + bDlgInit = true; + } + return TRUE; + + case WM_USER: + { + updatePreviewImage(GetDlgItem(hwndDlg, IDC_PREVIEWBOX)); + } + return TRUE; + + case WM_COMMAND: { + HWND hCtrl = NULL; + UINT idCtrl = LOWORD(wParam); + switch (HIWORD(wParam)) { + case BN_KILLFOCUS: //Button controls + case BN_SETFOCUS: //Button controls + return TRUE; + break; + case BN_CLICKED: //Button controls + switch(idCtrl) + { + case IDC_PREVIEW: + { + PopUpPreview(); + } + break; + case IDC_BTN_RELOAD: + { + LPTSTR Temp = NULL; + DWORD dwIndex = 0; + TCHAR szNewSkin[128]; + LPTSTR pszOldSkin = mir_tstrdup(PopUpOptions.SkinPack); + skins.load(_T("")); + hCtrl = GetDlgItem(hwndDlg, IDC_SKINLIST); + ListBox_ResetContent(hCtrl); + for (const Skins::SKINLIST *sl = skins.getSkinList(); sl; sl = sl->next) + { + dwIndex = ListBox_AddString(hCtrl, sl->name); + ListBox_SetItemData(hCtrl, dwIndex, sl->name); + } + ListBox_SetCurSel(hCtrl, ListBox_FindString(hCtrl, 0, PopUpOptions.SkinPack)); + //make shure we have select skin (ListBox_SetCurSel may be fail) + ListBox_GetText(hCtrl, ListBox_GetCurSel(hCtrl), &szNewSkin); + if(lstrcmp(pszOldSkin, szNewSkin) != 0) { + mir_free(PopUpOptions.SkinPack); + PopUpOptions.SkinPack = mir_tstrdup(szNewSkin); + } + mir_free(pszOldSkin); + + const PopupSkin *skin = 0; + if (skin = skins.getSkin(PopUpOptions.SkinPack)) { + //update Skin Option List from reload SkinPack + bDlgInit = false; + bDlgInit = SkinOptionList_Update (skinOptions, &skinOptionsCount, hwndDlg); + } + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + }//end IDC_BTN_RELOAD: + break; + case IDC_GETSKINS: + CallService(MS_UTILS_OPENURL,0,(LPARAM)"http://addons.miranda-im.org/index.php?action=display&id=72"); + break; + default: + break; + }//end switch(idCtrl) + updatePreviewImage(GetDlgItem(hwndDlg, IDC_PREVIEWBOX)); + break; + case CBN_SELCHANGE: //combo box controls + switch(idCtrl) { + case IDC_SKINLIST: { + //Skin list change + mir_free(PopUpOptions.SkinPack); + PopUpOptions.SkinPack = mir_tstrdup((TCHAR *)SendDlgItemMessage( + hwndDlg, + IDC_SKINLIST, + LB_GETITEMDATA, + (WPARAM)SendDlgItemMessage(hwndDlg, IDC_SKINLIST, LB_GETCURSEL,(WPARAM)0,(LPARAM)0), + (LPARAM)0) ); + const PopupSkin *skin = 0; + if (skin = skins.getSkin(PopUpOptions.SkinPack)) { + mir_free(PopUpOptions.SkinPack); + PopUpOptions.SkinPack = mir_tstrdup(skin->getName()); + + //update Skin Option List + bDlgInit = false; + bDlgInit = SkinOptionList_Update (skinOptions, &skinOptionsCount, hwndDlg); + } + updatePreviewImage(GetDlgItem(hwndDlg, IDC_PREVIEWBOX)); + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + default: + break; + }//end switch(idCtrl) + break; + default: + break; + }//end switch (HIWORD(wParam)) + break; + }// end WM_COMMAND + return FALSE; + + case WM_NOTIFY: { + if(!bDlgInit) return FALSE; + switch (((LPNMHDR)lParam)->idFrom) { + case 0: { + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + LoadOption_Skins(); + return TRUE; + case PSN_APPLY: + { //skin pack + DBWriteContactSettingTString(NULL, MODULNAME, "SkinPack", PopUpOptions.SkinPack); + //skin options + const PopupSkin *skin = 0; + if (skin = skins.getSkin(PopUpOptions.SkinPack)) + skin->saveOpts(); + skins.freeAllButActive(); + //more Skin options + DBWriteContactSettingByte(NULL, MODULNAME, "DisplayTime", PopUpOptions.DisplayTime); + DBWriteContactSettingByte(NULL, MODULNAME, "DropShadow", PopUpOptions.DropShadow); + DBWriteContactSettingByte(NULL, MODULNAME, "EnableShadowRegion", PopUpOptions.EnableFreeformShadows); + DBWriteContactSettingByte(NULL, MODULNAME, "EnableAeroGlass", PopUpOptions.EnableAeroGlass); + DBWriteContactSettingByte(NULL, MODULNAME, "UseMText", PopUpOptions.UseMText); + }//end PSN_APPLY: + return TRUE; + default: + break; + }//switch (((LPNMHDR)lParam)->code) + }// end case 0: + break; + default: + break; + }//end switch (((LPNMHDR)lParam)->idFrom) + }//end WM_NOTIFY: + return FALSE; + + case WM_DESTROY: + { + if (wndPreview) { + delete wndPreview; + wndPreview = NULL; + gPreviewOk = false; + } + if (hhkFontsReload) UnhookEvent(hhkFontsReload); + if (skinOptions) { + for (int i = 0; i < skinOptionsCount; ++i) { + mir_free(skinOptions[i].pszOptionName); + mir_free(skinOptions[i].pszSettingName); + } + mir_free(skinOptions); + skinOptions = NULL; + skinOptionsCount = 0; + } + } + return TRUE; + + default: + break; + }//end switch (msg) + return FALSE; +} + +static void BoxPreview_OnPaint(HWND hwnd, HDC mydc, int mode) +{ + switch (mode) + { + case 0: + { // Avatar + HDC hdcAvatar = CreateCompatibleDC(mydc); + HBITMAP hbmSave = (HBITMAP)SelectObject(hdcAvatar, hbmNoAvatar); + RECT rc; + GetClientRect(hwnd, &rc); + BITMAP bmp; + GetObject(hbmNoAvatar, sizeof(bmp), &bmp); + StretchBlt(mydc, 0, 0, rc.right, rc.bottom, hdcAvatar, 0, 0, abs(bmp.bmWidth), abs(bmp.bmHeight), SRCCOPY); + SelectObject(hdcAvatar, hbmSave); + DeleteDC(hdcAvatar); + HRGN rgn = CreateRoundRectRgn(0, 0, rc.right, rc.bottom, 2 * PopUpOptions.avatarRadius, 2 * PopUpOptions.avatarRadius); + FrameRgn(mydc, rgn, (HBRUSH)GetStockObject(BLACK_BRUSH), 1, 1); + DeleteObject(rgn); + break; + } + case 1: + { // Opacity + RECT rc; + HBRUSH hbr = CreateSolidBrush(fonts.clBack); + HFONT hfnt = (HFONT)SelectObject(mydc, fonts.title); + GetClientRect(hwnd, &rc); + FillRect(mydc, &rc, hbr); + DrawIconEx(mydc, 10, (rc.bottom-rc.top-16)/2, IcoLib_GetIcon(ICO_POPUP_ON,0), 16, 16, 0, hbr, DI_NORMAL); + SetBkMode(mydc, TRANSPARENT); + GetClientRect(hwnd, &rc); + rc.left += 30; // 10+16+4 -- icon + rc.right -= (rc.right-rc.left)/3; + rc.bottom -= (rc.bottom-rc.top)/3; + DrawText(mydc, _T(MODULNAME_LONG), lstrlen(_T(MODULNAME_LONG)), &rc, DT_CENTER|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER); + GetClientRect(hwnd, &rc); + rc.left += 30; // 10+16+4 -- icon + rc.left += (rc.right-rc.left)/3; + rc.top += (rc.bottom-rc.top)/3; + DrawText(mydc, _T(MODULNAME_LONG), lstrlen(_T(MODULNAME_LONG)), &rc, DT_CENTER|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER); + GetClientRect(hwnd, &rc); + FrameRect(mydc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); + SelectObject(mydc, hfnt); + DeleteObject(hbr); + break; + } + case 2: + { // Position + RECT rc; + HBRUSH hbr; + hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); + GetClientRect(hwnd, &rc); + FillRect(mydc, &rc, hbr); + DeleteObject(hbr); + + hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + GetClientRect(hwnd, &rc); + rc.right -= 100; + rc.top += 100; + FillRect(mydc, &rc, hbr); + DeleteObject(hbr); + + HPEN hpen = (HPEN)SelectObject(mydc, CreatePen(PS_DOT, 1, RGB(0,0,0))); + MoveToEx(mydc, 0, 100, NULL); + LineTo (mydc, 201, 100); + MoveToEx(mydc, 100, 0, NULL); + LineTo (mydc, 100, 201); + DeleteObject(SelectObject(mydc, hpen)); + + HRGN hrgn = CreateRectRgn(0,0,0,0); + GetWindowRgn(hwnd, hrgn); + FrameRgn(mydc, hrgn, (HBRUSH)GetStockObject(BLACK_BRUSH), 1, 1); + DeleteObject(hrgn); + + break; + } + } +} + +INT_PTR CALLBACK BoxPreviewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_PAINT: + { + if (GetUpdateRect(hwnd, 0, FALSE)) + { + PAINTSTRUCT ps; + HDC mydc = BeginPaint(hwnd, &ps); + BoxPreview_OnPaint(hwnd, mydc, GetWindowLongPtr(hwnd, GWLP_USERDATA)); + EndPaint(hwnd, &ps); + return TRUE; + } + break; + } + + case WM_PRINT: + case WM_PRINTCLIENT: + { + HDC mydc = (HDC)wParam; + BoxPreview_OnPaint(hwnd, mydc, GetWindowLongPtr(hwnd, GWLP_USERDATA)); + return TRUE; + } + + case WM_LBUTTONDOWN: + { + ReleaseCapture(); + SendMessage(hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0); + return TRUE; + } + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} diff --git a/Popup/src/opt_skins.h b/Popup/src/opt_skins.h new file mode 100644 index 0000000..4e06893 --- /dev/null +++ b/Popup/src/opt_skins.h @@ -0,0 +1,46 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opt_skins.h $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __opt_skins_h__ +#define __opt_skins_h__ + +#ifndef CS_DROPSHADOW +#define CS_DROPSHADOW 0x00020000 +#endif +#define BOXPREVIEW_WNDCLASS "PopupPreviewBoxWndclass" + +void RegisterOptPrevBox(); + +void LoadOption_Skins(); +INT_PTR CALLBACK DlgProcPopSkinsOpts(HWND, UINT, WPARAM, LPARAM); + +#endif // __opt_skins_h__ diff --git a/Popup/src/opttree.cpp b/Popup/src/opttree.cpp new file mode 100644 index 0000000..d6d81c8 --- /dev/null +++ b/Popup/src/opttree.cpp @@ -0,0 +1,442 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opttree.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +static void OptTree_TranslateItem(HWND hwndTree, HTREEITEM hItem) +{ + union + { + char ansi[128]; + WCHAR unicode[64]; + } buf; + +#if defined(_UNICODE) + TVITEMW tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_TEXT; + tvi.hItem = hItem; + tvi.pszText = buf.unicode; + tvi.cchTextMax = SIZEOF(buf.unicode); + SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&tvi); + tvi.pszText = TranslateW(tvi.pszText); + tvi.cchTextMax = lstrlenW(tvi.pszText); + SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&tvi); + +#else + if (g_popup.isOsUnicode && MySendMessageW) + { + TVITEMW tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_TEXT; + tvi.hItem = hItem; + tvi.pszText = buf.unicode; + tvi.cchTextMax = SIZEOF(buf.unicode); + MySendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&tvi); + tvi.pszText = TranslateW(tvi.pszText); + tvi.cchTextMax = lstrlenW(tvi.pszText); + MySendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&tvi); + } + else { + TVITEMA tvi = {0}; + tvi.mask = TVIF_HANDLE|TVIF_TEXT; + tvi.hItem = hItem; + tvi.pszText = buf.ansi; + tvi.cchTextMax = SIZEOF(buf.ansi); + SendMessageA(hwndTree, TVM_GETITEMA, 0, (LPARAM)&tvi); + tvi.pszText = Translate(tvi.pszText); + tvi.cchTextMax = lstrlenA(tvi.pszText); + SendMessageA(hwndTree, TVM_SETITEMA, 0, (LPARAM)&tvi); + } +#endif +} + +void OptTree_Translate(HWND hwndTree) +{ + HTREEITEM hItem = TreeView_GetRoot(hwndTree); + while (hItem) + { + OptTree_TranslateItem(hwndTree, hItem); + + HTREEITEM hItemTmp = 0; + if (hItemTmp = TreeView_GetChild(hwndTree, hItem)) + { + hItem = hItemTmp; + } else + if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem)) + { + hItem = hItemTmp; + } else + { + while (1) + { + if (!(hItem = TreeView_GetParent(hwndTree, hItem))) break; + if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem)) + { + hItem = hItemTmp; + break; + } + } + } + } +} + +HTREEITEM OptTree_FindNamedTreeItemAt(HWND hwndTree, HTREEITEM hItem, const TCHAR *name) +{ + TVITEM tvi = {0}; + TCHAR str[MAX_PATH]; + + if (hItem) + tvi.hItem = TreeView_GetChild(hwndTree, hItem); + else + tvi.hItem = TreeView_GetRoot(hwndTree); + + if (!name) + return tvi.hItem; + + tvi.mask = TVIF_TEXT; + tvi.pszText = str; + tvi.cchTextMax = MAX_PATH; + + while (tvi.hItem) + { + TreeView_GetItem(hwndTree, &tvi); + + if (!lstrcmp(tvi.pszText, name)) + return tvi.hItem; + + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } + return NULL; +} + +HTREEITEM OptTree_AddItem(HWND hwndTree, LPTSTR name, LPARAM lParam, int iconIndex) +{ + TCHAR itemName[1024]; + + TCHAR* sectionName; + int sectionLevel = 0; + + HTREEITEM hSection = NULL, result = NULL; + lstrcpy(itemName, name); + sectionName = itemName; + + while (sectionName) + { + // allow multi-level tree + TCHAR* pItemName = sectionName; + HTREEITEM hItem; + + if (sectionName = _tcschr(sectionName, '/')) + { + // one level deeper + *sectionName = 0; + sectionName++; + } + + hItem = OptTree_FindNamedTreeItemAt(hwndTree, hSection, pItemName); + if (!sectionName || !hItem) + { + if (!hItem) + { + TVINSERTSTRUCT tvis = {0}; + + tvis.hParent = hSection; + tvis.hInsertAfter = TVI_LAST;//TVI_SORT; + tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE; + tvis.item.pszText = pItemName; + tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED; + if (sectionName) + { + tvis.item.lParam = 0; + tvis.item.iImage = tvis.item.iSelectedImage = -1; + } else + { + tvis.item.lParam = lParam; + tvis.item.iImage = tvis.item.iSelectedImage = iconIndex; + tvis.item.mask |= TVIF_IMAGE|TVIF_SELECTEDIMAGE; + } + hItem = TreeView_InsertItem(hwndTree, &tvis); + if (!sectionName) + result = hItem; + } + } + sectionLevel++; + hSection = hItem; + } + + return result; +} + +BOOL OptTree_ProcessMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, int *result, int idcTree, OPTTREE_OPTION *options, int optionCount) +{ + enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED }; + + HWND hwndTree = GetDlgItem(hwnd, idcTree); + switch (msg) + { + case WM_INITDIALOG: + { + int indx; + TCHAR itemName[1024]; + HIMAGELIST hImgLst; + + TreeView_SelectItem(hwndTree, NULL); + TreeView_DeleteAllItems(hwndTree); + + hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR|ILC_COLOR32|ILC_MASK, 5, 1); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_POPUP), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED)); + if (g_popup.MirVer >= PLUGIN_MAKE_VERSION(0,7,0,2)) + { + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_TICK)); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_NOTICK)); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_TICK)); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_NOTICK)); + } else + { + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPT_CHECK_ON), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED)); // check buttons + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPT_CHECK_OFF), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED)); // check buttons + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPT_CHECK_ON), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED)); // check buttons + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPT_CHECK_OFF), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED)); // check buttons +// ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPT_RADIO_ON), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED)); // radio buttons +// ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPT_RADIO_OFF), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR|LR_SHARED)); // radio buttons + } + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN)); + ImageList_ReplaceIcon(hImgLst, -1, (HICON)LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT)); + TreeView_SetImageList(hwndTree, hImgLst, TVSIL_NORMAL); + + /* build options tree. based on code from IcoLib */ + for (indx = 0; indx < optionCount; indx++) + { + TCHAR* sectionName; + int sectionLevel = 0; + + HTREEITEM hSection = NULL; + lstrcpy(itemName, options[indx].pszOptionName); + sectionName = itemName; + + while (sectionName) + { + // allow multi-level tree + TCHAR* pItemName = sectionName; + HTREEITEM hItem; + + if (sectionName = _tcschr(sectionName, '/')) + { + // one level deeper + *sectionName = 0; + sectionName++; + } + + hItem = OptTree_FindNamedTreeItemAt(hwndTree, hSection, pItemName); + if (!sectionName || !hItem) + { + if (!hItem) + { + TVINSERTSTRUCT tvis = {0}; + + tvis.hParent = hSection; + tvis.hInsertAfter = TVI_LAST;//TVI_SORT; + tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvis.item.pszText = pItemName; + tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED; + if (sectionName) + { + tvis.item.lParam = -1; + tvis.item.state |= TVIS_BOLD; + tvis.item.stateMask |= TVIS_BOLD; + tvis.item.iImage = tvis.item.iSelectedImage = IMG_GRPOPEN; + } else + { + tvis.item.lParam = indx; + if (options[indx].groupId == OPTTREE_CHECK) + { + tvis.item.iImage = tvis.item.iSelectedImage = IMG_NOCHECK; + } else + { + tvis.item.iImage = tvis.item.iSelectedImage = IMG_NORCHECK; + } + } + hItem = TreeView_InsertItem(hwndTree, &tvis); + if (!sectionName) + options[indx].hItem = hItem; + } + } + sectionLevel++; + hSection = hItem; + } + } + + OptTree_Translate(hwndTree); + ShowWindow(hwndTree, SW_SHOW); + TreeView_SelectItem(hwndTree, OptTree_FindNamedTreeItemAt(hwndTree, 0, NULL)); + break; + } + + case WM_DESTROY: + { + ImageList_Destroy(TreeView_GetImageList(hwndTree, TVSIL_NORMAL)); + break; + } + + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR)lparam; + if (lpnmhdr->idFrom != idcTree) break; + switch (lpnmhdr->code) + { + case NM_CLICK: + { + TVHITTESTINFO hti; + hti.pt.x=(short)LOWORD(GetMessagePos()); + hti.pt.y=(short)HIWORD(GetMessagePos()); + ScreenToClient(lpnmhdr->hwndFrom,&hti.pt); + if(TreeView_HitTest(lpnmhdr->hwndFrom,&hti)) + { + if(hti.flags&TVHT_ONITEMICON) + { + TVITEM tvi; + tvi.mask=TVIF_HANDLE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem=hti.hItem; + TreeView_GetItem(lpnmhdr->hwndFrom,&tvi); + switch (tvi.iImage) + { + case IMG_GRPOPEN: + tvi.iImage = tvi.iSelectedImage = IMG_GRPCLOSED; + TreeView_Expand(lpnmhdr->hwndFrom, tvi.hItem, TVE_COLLAPSE); + break; + case IMG_GRPCLOSED: + tvi.iImage = tvi.iSelectedImage = IMG_GRPOPEN; + TreeView_Expand(lpnmhdr->hwndFrom, tvi.hItem, TVE_EXPAND); + break; + + case IMG_CHECK: + tvi.iImage = tvi.iSelectedImage = IMG_NOCHECK; + *result = tvi.lParam; + options[tvi.lParam].bState = FALSE; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IMG_NOCHECK: + tvi.iImage = tvi.iSelectedImage = IMG_CHECK; + *result = tvi.lParam; + options[tvi.lParam].bState = TRUE; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IMG_NORCHECK: + { + int i; + for (i = 0; i < optionCount; ++i) + { + if (options[i].groupId == options[tvi.lParam].groupId) + { + TVITEM tvi_tmp; + tvi_tmp.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi_tmp.hItem = options[i].hItem; + tvi_tmp.iImage = tvi_tmp.iSelectedImage = IMG_NORCHECK; + TreeView_SetItem(lpnmhdr->hwndFrom, &tvi_tmp); + } + } + tvi.iImage = tvi.iSelectedImage = IMG_RCHECK; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + } + } + TreeView_SetItem(lpnmhdr->hwndFrom,&tvi); + } + } + break; + } + + case TVN_ITEMEXPANDED: + { + LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)lparam; + TVITEM tvi; + tvi.mask=TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem = lpnmtv->itemNew.hItem; + tvi.iImage = tvi.iSelectedImage = + (lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED; + TreeView_SetItem(lpnmhdr->hwndFrom,&tvi); + break; + } + } + break; + } + } + return FALSE; +} + +DWORD OptTree_GetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, LPTSTR pszSettingName) +{ + enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED }; + + HWND hwndTree = GetDlgItem(hwnd, idcTree); + DWORD result = 0; + int i; + for (i = 0; i < optionCount; ++i) + { + if ((!options[i].pszSettingName && !pszSettingName) || + (options[i].pszSettingName && pszSettingName && !lstrcmp(options[i].pszSettingName, pszSettingName))) + { + TVITEM tvi; + tvi.mask = TVIF_HANDLE|TVIF_IMAGE; + tvi.hItem = options[i].hItem; + TreeView_GetItem(hwndTree, &tvi); + if ((tvi.iImage == IMG_CHECK) || (tvi.iImage == IMG_RCHECK)) + result |= options[i].dwFlag; + } + } + return result; +} + +void OptTree_SetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, DWORD dwOptions, LPTSTR pszSettingName) +{ + enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED }; + + HWND hwndTree = GetDlgItem(hwnd, idcTree); + int i; + for (i = 0; i < optionCount; ++i) + { + if ((!options[i].pszSettingName && !pszSettingName) || + (options[i].pszSettingName && pszSettingName && !lstrcmp(options[i].pszSettingName, pszSettingName))) + { + TVITEM tvi; + tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem = options[i].hItem; + if (options[i].groupId == OPTTREE_CHECK) + { + tvi.iImage = tvi.iSelectedImage = (dwOptions & options[i].dwFlag) ? IMG_CHECK : IMG_NOCHECK; + } else + { + tvi.iImage = tvi.iSelectedImage = (dwOptions & options[i].dwFlag) ? IMG_RCHECK : IMG_NORCHECK; + } + TreeView_SetItem(hwndTree, &tvi); + } + } +} diff --git a/Popup/src/opttree.h b/Popup/src/opttree.h new file mode 100644 index 0000000..8718ca8 --- /dev/null +++ b/Popup/src/opttree.h @@ -0,0 +1,57 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/opttree.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __opttree_h__ +#define __opttree_h__ + +#define OPTTREE_CHECK 0 + +typedef struct { + int iconIndex; + LPTSTR pszOptionName; + int groupId; + DWORD dwFlag; + HTREEITEM hItem; + LPTSTR pszSettingName; + BOOL bState; + int Data; //free for use (depend on data) +} OPTTREE_OPTION; + +BOOL OptTree_ProcessMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL *result, int idcTree, OPTTREE_OPTION *options, int optionCount); +DWORD OptTree_GetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, LPTSTR pszSettingName = NULL); +void OptTree_SetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, DWORD dwOptions, LPTSTR pszSettingName = NULL); + +void OptTree_Translate(HWND hwndTree); +HTREEITEM OptTree_FindNamedTreeItemAt(HWND hwndTree, HTREEITEM hItem, LPCTSTR name); +HTREEITEM OptTree_AddItem(HWND hwndTree, LPTSTR name, LPARAM lParam = 0, int iconIndex = -1); + +#endif // __opttree_h__ diff --git a/Popup/src/popup_gdiplus.cpp b/Popup/src/popup_gdiplus.cpp new file mode 100644 index 0000000..ab1c3b2 --- /dev/null +++ b/Popup/src/popup_gdiplus.cpp @@ -0,0 +1,229 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/popup_gdiplus.cpp $ +Revision : $Revision: 1622 $ +Last change on : $Date: 2010-06-23 23:32:21 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +/* 99% of this code was adopted from clist_modern by FYR */ + +#include "headers.h" + +#undef Translate + +// fix for old SDK and new GDI+ +#define ULONG_PTR unsigned long + +#include "gdiplus.h" + +DWORD g_gdiplusToken; +bool gbGdiPlusLoaded; + +void LoadGDIPlus() +{ + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + gbGdiPlusLoaded = false; + __try { + if (g_gdiplusToken == 0) + Gdiplus::GdiplusStartup(&g_gdiplusToken, &gdiplusStartupInput, NULL); + } + __except ( EXCEPTION_EXECUTE_HANDLER ) { + gbGdiPlusLoaded = false; + } +} + +void UnloadGDIPlus() +{ + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + __try { + if (g_gdiplusToken && gbGdiPlusLoaded) + Gdiplus::GdiplusShutdown(g_gdiplusToken); + } + __except ( EXCEPTION_EXECUTE_HANDLER ) { + // do nothing + } + gbGdiPlusLoaded = true; + g_gdiplusToken = 0; +} + +using namespace Gdiplus; + +///////////////////////////////////////////////////////////////////////////////// +// GDIPlus_IsAnimatedGIF and GDIPlus_ExtractAnimatedGIF +// based on routine from http://www.codeproject.com/vcpp/gdiplus/imageexgdi.asp +// + +HBITMAP SkinEngine_CreateDIB32(int cx, int cy) +{ + BITMAPINFO RGB32BitsBITMAPINFO; + UINT * ptPixels; + HBITMAP DirectBitmap; + + if ( cx < 0 || cy < 0 ) { + return NULL; + } + + ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO)); + RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + RGB32BitsBITMAPINFO.bmiHeader.biWidth=cx;//bm.bmWidth; + RGB32BitsBITMAPINFO.bmiHeader.biHeight=cy;//bm.bmHeight; + RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1; + RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; + // pointer used for direct Bitmap pixels access + + + DirectBitmap = CreateDIBSection(NULL, + (BITMAPINFO *)&RGB32BitsBITMAPINFO, + DIB_RGB_COLORS, + (void **)&ptPixels, + NULL, 0); + if ((DirectBitmap == NULL || ptPixels == NULL) && cx!= 0 && cy!=0) + { + ; + } + else + { + memset(ptPixels,0,cx*cy*4); + } + return DirectBitmap; +} + + +BOOL GDIPlus_IsAnimatedGIF(char * szName) +{ + int nFrameCount=0; + WCHAR * temp= mir_a2u(szName); + Image image(temp); + mir_free(temp); + UINT count = 0; + + count = image.GetFrameDimensionsCount(); + GUID* pDimensionIDs = new GUID[count]; + + // Get the list of frame dimensions from the Image object. + image.GetFrameDimensionsList(pDimensionIDs, count); + + // Get the number of frames in the first dimension. + nFrameCount = image.GetFrameCount(&pDimensionIDs[0]); + + delete []pDimensionIDs; + + return (BOOL) (nFrameCount > 1) && image.GetWidth() && image.GetHeight(); +} + +void GDIPlus_GetGIFSize(char * szName, int * width, int * height) +{ + WCHAR * temp= mir_a2u(szName); + Image image(temp); + mir_free(temp); + + *width = image.GetWidth(); + *height = image.GetHeight(); +} + +void GDIPlus_ExtractAnimatedGIF(char * szName, int width, int height, HBITMAP * pBitmap, int ** pframesDelay, int * pframesCount, SIZE * pSizeAvatar) +{ + int nFrameCount=0; + WCHAR * temp = mir_a2u(szName); + Bitmap image(temp); + mir_free(temp); + PropertyItem * pPropertyItem; + + UINT count = 0; + + count = image.GetFrameDimensionsCount(); + GUID* pDimensionIDs = new GUID[count]; + + // Get the list of frame dimensions from the Image object. + image.GetFrameDimensionsList(pDimensionIDs, count); + + // Get the number of frames in the first dimension. + nFrameCount = image.GetFrameCount(&pDimensionIDs[0]); + + // Assume that the image has a property item of type PropertyItemEquipMake. + // Get the size of that property item. + int nSize = image.GetPropertyItemSize(PropertyTagFrameDelay); + + // Allocate a buffer to receive the property item. + pPropertyItem = (PropertyItem*) mir_alloc(nSize); + + image.GetPropertyItem(PropertyTagFrameDelay, nSize, pPropertyItem); + + int clipWidth; + int clipHeight; + int imWidth=image.GetWidth(); + int imHeight=image.GetHeight(); + float xscale=(float)width/imWidth; + float yscale=(float)height/imHeight; + xscale=min(xscale,yscale); + clipWidth=(int)(xscale*imWidth+.5); + clipHeight=(int)(xscale*imHeight+.5); + + HBITMAP hBitmap=SkinEngine_CreateDIB32(clipWidth*nFrameCount, height); + HDC hdc=CreateCompatibleDC(NULL); + HBITMAP oldBmp=(HBITMAP)SelectObject(hdc,hBitmap); + Graphics graphics(hdc); + ImageAttributes attr; + ColorMatrix ClrMatrix = + { + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, ((float)255)/255, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f + }; + //attr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap); + graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic); + + int * delays=(int*)mir_alloc(nFrameCount*sizeof(int)); + memset(delays,0,nFrameCount*sizeof(int)); + + for (int i=1; ivalue)[i-1] * 10; + delays[i-1]=(int)lPause; + } + SelectObject(hdc,oldBmp); + DeleteDC(hdc); + mir_free(pPropertyItem); + pPropertyItem = NULL; + delete []pDimensionIDs; + if (pBitmap && pframesDelay && pframesCount && pSizeAvatar) + { + *pBitmap=hBitmap; + *pframesDelay=delays; + *pframesCount=nFrameCount; + pSizeAvatar->cx=clipWidth; + pSizeAvatar->cy=clipHeight; + } + GdiFlush(); +} diff --git a/Popup/src/popup_gdiplus.h b/Popup/src/popup_gdiplus.h new file mode 100644 index 0000000..b84700c --- /dev/null +++ b/Popup/src/popup_gdiplus.h @@ -0,0 +1,42 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/popup_gdiplus.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ +#ifndef __popup_gdiplus_h__ +#define __popup_gdiplus_h__ + +void LoadGDIPlus(); +void UnloadGDIPlus(); + +BOOL GDIPlus_IsAnimatedGIF(char * szName); +void GDIPlus_GetGIFSize(char * szName, int * width, int * height); +void GDIPlus_ExtractAnimatedGIF(char * szName, int width, int height, HBITMAP * pBitmap, int ** pframesDelay, int * pframesCount, SIZE * pSizeAvatar); + +#endif // __popup_gdiplus_h__ diff --git a/Popup/src/popup_thread.cpp b/Popup/src/popup_thread.cpp new file mode 100644 index 0000000..2376653 --- /dev/null +++ b/Popup/src/popup_thread.cpp @@ -0,0 +1,372 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/popup_thread.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" +#include +//#include + +// globals +//static unsigned idPopupThread = 0; +static int gIdleRequests = 0; +static bool gTerminating = false; +static HANDLE hThreadMutex = NULL; +static HWND gHwndManager = 0; +static int gLockCount = 0; +static volatile int nPopups = 0; + +//typedef std::list PopupList; +typedef LIST PopupList; +static PopupList popupList(3); + +// forwards +enum +{ // message id's + UTM_PT_FIRST = WM_USER+1607, + UTM_STOP_THREAD, + UTM_ADD_WINDOW, + UTM_UPDATE_WINDOW, + UTM_REMOVE_WINDOW, + UTM_REQUEST_IDLE, + UTM_LOCK_QUEUE, + UTM_UNLOCK_QUEUE, + UTM_REQUEST_REMOVE +}; +static void __cdecl PopupThread(void *arg); + +// interface +void LoadPopupThread() +{ + hThreadMutex = CreateMutex(NULL, FALSE, NULL); + _beginthread(PopupThread, 0, NULL); +// _beginthreadex(NULL, 0, PopupThread, NULL, 0, &idPopupThread); +} + +void StopPopupThread() +{ + PostMessage(gHwndManager, UTM_STOP_THREAD, 0, 0); +} + +void UnloadPopupThread() +{ +// We won't waint for thread to exit, Miranda's thread unsind mechanism will do that for us. + WaitForSingleObject(hThreadMutex, INFINITE); + CloseHandle(hThreadMutex); +} + +void PopupThreadLock() +{ + PostMessage(gHwndManager, UTM_LOCK_QUEUE, 0, 0); +} + +void PopupThreadUnlock() +{ + PostMessage(gHwndManager, UTM_UNLOCK_QUEUE, 0, 0); +} + +bool PopupThreadIsFull() +{ +// char buf[128]; +// wsprintf(buf, "%d, %d", nPopups, PopUpOptions.MaxPopups); +// MessageBoxA(NULL, buf, "Popup Plus", MB_OK); + return nPopups >= PopUpOptions.MaxPopups; +} + +bool PopupThreadAddWindow(PopupWnd2 *wnd) +{ + PostMessage(gHwndManager, UTM_ADD_WINDOW, 0, (LPARAM)wnd); + return true; +} + +bool PopupThreadRemoveWindow(PopupWnd2 *wnd) +{ + PostMessage(gHwndManager, UTM_REMOVE_WINDOW, 0, (LPARAM)wnd); + return true; +} + +bool PopupThreadUpdateWindow(PopupWnd2 *wnd) +{ + PostMessage(gHwndManager, UTM_UPDATE_WINDOW, 0, (LPARAM)wnd); + return true; +} + +bool PopupThreadRequestRemoveWindow(PopupWnd2 *wnd) +{ + PostMessage(gHwndManager, UTM_REQUEST_REMOVE, 0, (LPARAM)wnd); + return true; +} + +bool UpdatePopupPosition(PopupWnd2 *prev, PopupWnd2 *wnd) +{ + if (!wnd) return false; + if (!PopUpOptions.ReorderPopUps && wnd->isPositioned()) return false; + + int POPUP_SPACING = PopUpOptions.spacing; + + POINT pos; + SIZE prevSize = {0}, curSize = wnd->getSize(); + if (prev) prevSize = prev->getSize(); + + RECT rc; +// SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); + +#if !defined(_UNICODE) + //Win95 or NT don't have the support for multi monitor. + if (!MyGetMonitorInfo) { + SystemParametersInfo(SPI_GETWORKAREA,0,&rc,0); + } + //Windows 98/ME/2000/XP do have it. + else +#endif + if (GetSystemMetrics(SM_CMONITORS)==1) { //we have only one monitor (cant check it together with 1.if) + SystemParametersInfo(SPI_GETWORKAREA,0,&rc,0); + } + else { //Multimonitor stuff (we have more then 1) + HMONITOR hMonitor = NULL; + HWND hWnd = NULL; + MONITORINFOEX mnti; // = { 0 }; + + if (PopUpOptions.Monitor == MN_MIRANDA) + hWnd = (HWND)CallService(MS_CLUI_GETHWND,0,0); + else // PopUpOptions.Monitor == MN_ACTIVE + hWnd = GetForegroundWindow(); + + mnti.cbSize = sizeof(MONITORINFOEX); + +#if defined(_UNICODE) + hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY); + if (GetMonitorInfo(hMonitor, (LPMONITORINFO)&mnti) == TRUE) //It worked +#else + hMonitor = MyMonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY); + if (MyGetMonitorInfo(hMonitor, (LPMONITORINFO)&mnti) == TRUE) //It worked +#endif + CopyMemory(&rc, &(mnti.rcWork), sizeof(RECT)); + else + SystemParametersInfo(SPI_GETWORKAREA,0,&rc,0); + } + + rc.left += PopUpOptions.gapLeft - POPUP_SPACING; + rc.right -= PopUpOptions.gapRight - POPUP_SPACING; + rc.top += PopUpOptions.gapTop - POPUP_SPACING; + rc.bottom -= PopUpOptions.gapBottom - POPUP_SPACING; + if (PopUpOptions.Spreading == SPREADING_VERTICAL) + { + switch (PopUpOptions.Position) + { + case POS_UPPERLEFT: + pos.x = rc.left + POPUP_SPACING; + pos.y = (prev ? (prev->getPosition().y + prev->getSize().cy) : rc.top) + POPUP_SPACING; + break; + case POS_LOWERLEFT: + pos.x = rc.left + POPUP_SPACING; + pos.y = (prev ? prev->getPosition().y : rc.bottom) - wnd->getSize().cy - POPUP_SPACING; + break; + case POS_LOWERRIGHT: + pos.x = rc.right - wnd->getSize().cx - POPUP_SPACING; + pos.y = (prev ? prev->getPosition().y : rc.bottom) - wnd->getSize().cy - POPUP_SPACING; + break; + case POS_UPPERRIGHT: + pos.x = rc.right - wnd->getSize().cx - POPUP_SPACING; + pos.y = (prev ? (prev->getPosition().y + prev->getSize().cy) : rc.top) + POPUP_SPACING; + break; + } + } else + // if (PopUpOptions.Spreading == SPREADING_HORIZONTAL) + { + switch (PopUpOptions.Position) + { + case POS_UPPERLEFT: + pos.x = (prev ? (prev->getPosition().x + prev->getSize().cx) : rc.left) + POPUP_SPACING; + pos.y = rc.top + POPUP_SPACING; + break; + case POS_LOWERLEFT: + pos.x = (prev ? (prev->getPosition().x + prev->getSize().cx) : rc.left) + POPUP_SPACING; + pos.y = rc.bottom - wnd->getSize().cy - POPUP_SPACING; + break; + case POS_LOWERRIGHT: + pos.x = (prev ? prev->getPosition().x : rc.right) - wnd->getSize().cx - POPUP_SPACING; + pos.y = rc.bottom - wnd->getSize().cy - POPUP_SPACING; + break; + case POS_UPPERRIGHT: + pos.x = (prev ? prev->getPosition().x : rc.right) - wnd->getSize().cx - POPUP_SPACING; + pos.y = rc.top + POPUP_SPACING; + break; + } + } + wnd->setPosition(pos); + return true; +} + +void RepositionPopups() +{ + PopupWnd2 *prev = 0; + if (PopUpOptions.ReorderPopUps) + { + for (int i = 0; i < popupList.getCount(); ++i) + { + UpdatePopupPosition(prev, popupList[i]); + prev = popupList[i]; + } + } +} + +static LRESULT CALLBACK PopupThreadManagerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PopupWnd2 *wnd = NULL; + if (message == UTM_ADD_WINDOW || + message == UTM_UPDATE_WINDOW || + message == UTM_REMOVE_WINDOW || + message == UTM_REQUEST_REMOVE) + { + if (!(wnd = (PopupWnd2 *)lParam)) + return 0; + } + switch (message) + { + case UTM_STOP_THREAD: + { + gTerminating = true; + if (DBGetContactSettingByte(NULL, MODULNAME, "FastExit", 0)) + for (int i = 0; i < popupList.getCount(); ++i) + PUDeletePopUp(popupList[i]->getHwnd()); + PostQuitMessage(0); + break; + } + case UTM_ADD_WINDOW: + { + if (gTerminating) break; + UpdatePopupPosition(popupList.getCount() ? popupList[popupList.getCount()-1] : 0, wnd); + popupList.insert(wnd); + ++nPopups; + wnd->callMethodAsync(&PopupWnd2::m_show, 0); + break; + } + case UTM_UPDATE_WINDOW: + { + RepositionPopups(); + break; + } + case UTM_REQUEST_REMOVE: + { + if ((PopUpOptions.LeaveHovered && gLockCount) || (wnd && wnd->isLocked())) + { + wnd->updateTimer(); + } else + { + PostMessage(wnd->getHwnd(), WM_CLOSE, 0, 0); + } + break; + } + case UTM_REMOVE_WINDOW: + { + // popupList.remove(ptr) would be nicer, but it requires sortFunc :( + for (int i = 0; i < popupList.getCount(); ++i) + if (popupList[i] == wnd) + { + popupList.remove(i); + RepositionPopups(); + --nPopups; + delete wnd; + break; + } + break; + } + case UTM_LOCK_QUEUE: + { + ++gLockCount; + break; + } + case UTM_UNLOCK_QUEUE: + { + if (--gLockCount < 0) + gLockCount = 0; + break; + } + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + +// thread func +static void __cdecl PopupThread(void *arg) +{ + // grab the mutex + if (WaitForSingleObject(hThreadMutex, INFINITE) != WAIT_OBJECT_0) + { // other thread is already running + _endthread(); + return; + } + + // Increment Miranda thread counter + CallService(MS_SYSTEM_THREAD_PUSH, 0, 0); + + // Create manager window + DWORD err; + WNDCLASSEX wcl; + wcl.cbSize = sizeof(wcl); + wcl.lpfnWndProc = PopupThreadManagerWndProc; + wcl.style = 0; + wcl.cbClsExtra = 0; + wcl.cbWndExtra = 0; + wcl.hInstance = hInst; + wcl.hIcon = NULL; + wcl.hCursor = LoadCursor(NULL, IDC_ARROW); + wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); + wcl.lpszMenuName = NULL; + wcl.lpszClassName = _T("PopupThreadManagerWnd"); + wcl.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_POPUP), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + g_wndClass.cPopupThreadManagerWnd = RegisterClassEx(&wcl); + err = GetLastError(); + if (!g_wndClass.cPopupThreadManagerWnd) { + TCHAR msg[1024]; + wsprintf(msg, TranslateT("Failed to register %s class."),wcl.lpszClassName); + MSGERROR(msg); + } + + gHwndManager = CreateWindow(_T("PopupThreadManagerWnd"), NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hInst, NULL); + SetWindowPos(gHwndManager, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_HIDEWINDOW); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + ReleaseMutex(hThreadMutex); + + // Decrement Miranda thread counter + CallService(MS_SYSTEM_THREAD_POP, 0, 0); + + // Ok, now we can kill this thread + _endthread(); + + return; +} diff --git a/Popup/src/popup_thread.h b/Popup/src/popup_thread.h new file mode 100644 index 0000000..98e9c75 --- /dev/null +++ b/Popup/src/popup_thread.h @@ -0,0 +1,52 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/popup_thread.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __popup_thread_h__ +#define __popup_thread_h__ + +void LoadPopupThread(); +void StopPopupThread(); +void UnloadPopupThread(); + +void PopupThreadLock(); +void PopupThreadUnlock(); + +class PopupWnd2; + +bool PopupThreadIsFull(); +bool PopupThreadAddWindow(PopupWnd2 *wnd); +bool PopupThreadRemoveWindow(PopupWnd2 *wnd); +bool PopupThreadUpdateWindow(PopupWnd2 *wnd); + +bool PopupThreadRequestRemoveWindow(PopupWnd2 *wnd); + +#endif // __popup_thread_h__ diff --git a/Popup/src/popup_wnd2.cpp b/Popup/src/popup_wnd2.cpp new file mode 100644 index 0000000..785c0e7 --- /dev/null +++ b/Popup/src/popup_wnd2.cpp @@ -0,0 +1,1945 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/popup_wnd2.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" +#include "bitmap_funcs.h" +#include + +#define POPUP_WNDCLASS "PopupWnd2" + +#ifndef CS_DROPSHADOW +#define CS_DROPSHADOW 0x00020000 +#endif + +#define ULW_ALPHA 0x00000002 +#define AC_SRC_ALPHA 0x01 + +#define POPUP_TIMER 1607 +#define AVATAR_TIMER 1608 +#define CURSOR_TIMER 1609 + +#define UM_AVATARCHANGED (WM_USER+0x300) +#define UM_MENUDONE (WM_USER+0x301) +#define UM_SHOWMENU (WM_USER+0x302) + +HWND ghwndMenuHost = NULL; + +void WindowThread(void *arg); + +LRESULT CALLBACK MenuHostWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +bool LoadPopupWnd2() +{ + bool res = true; + DWORD err; + + WNDCLASSEX wcl; + wcl.cbSize = sizeof(wcl); + wcl.lpfnWndProc = PopupWnd2::WindowProc; + wcl.style = 0; + wcl.cbClsExtra = 0; + wcl.cbWndExtra = 0; + wcl.hInstance = hInst; + wcl.hIcon = NULL; + wcl.hCursor = LoadCursor(NULL, IDC_ARROW); + wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); + wcl.lpszMenuName = NULL; + wcl.lpszClassName = _T(POPUP_WNDCLASS); + wcl.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_POPUP), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + g_wndClass.cPopupWnd2 = RegisterClassEx(&wcl); + err = GetLastError(); + if (!g_wndClass.cPopupWnd2) { + res = false; + TCHAR msg[1024]; + wsprintf(msg, TranslateT("Failed to register %s class."),wcl.lpszClassName); + MessageBox(NULL, msg, _T(MODULNAME_LONG), MB_ICONSTOP|MB_OK); + } + + // register custom class for edit box with drop-shadow attribute + if (IsWinVerXPPlus()) + { + #if defined(_UNICODE) || defined(_WIN64) + #define MyRegisterClassExW RegisterClassExW + #define MyGetClassInfoExW GetClassInfoExW + #else + ATOM (WINAPI *MyRegisterClassExW)(CONST WNDCLASSEXW *); + MyRegisterClassExW = (ATOM (WINAPI *)(CONST WNDCLASSEXW *))GetProcAddress(hUserDll, "RegisterClassExW"); + BOOL (WINAPI *MyGetClassInfoExW)(HINSTANCE, LPCWSTR, LPWNDCLASSEXW); + MyGetClassInfoExW = (BOOL (WINAPI *)(HINSTANCE, LPCWSTR, LPWNDCLASSEXW))GetProcAddress(hUserDll, "GetClassInfoExW"); + #endif + WNDCLASSEXW wclw = {0}; + wclw.cbSize = sizeof(wclw); + if (!MyGetClassInfoExW(NULL, L"EDIT", &wclw)) + MSGERROR(TranslateT("Failed to GetClassInfoExW from EDIT class.")); + wclw.hInstance = hInst; + wclw.lpszClassName = L"PopupEditBox"; + wclw.style |= CS_DROPSHADOW; + g_wndClass.cPopupEditBox = MyRegisterClassExW(&wclw); + err = GetLastError(); + if (!g_wndClass.cPopupEditBox) { + TCHAR msg[2048]; + wsprintf(msg, _T("Failed to register custom edit box window class.\r\n\r\ncbSize: %i\r\nstyle: %p\r\nlpfnWndProc: %i\r\ncbClsExtra: %i\r\ncbWndExtra: %i\r\nhInstance: %i\r\nhIcon: %i\r\nhCursor: %i\r\nhbrBackground: %i\r\nlpszMenuName: %s\r\nlpszClassName: %s\r\nhIconSm: %i\r\n"), + wclw.cbSize, //UINT cbSize; + wclw.style, //UINT style; + wclw.lpfnWndProc, //WNDPROC lpfnWndProc; + wclw.cbClsExtra, //int cbClsExtra; + wclw.cbWndExtra, //int cbWndExtra; + wclw.hInstance, //HINSTANCE hInstance; + wclw.hIcon, //HICON hIcon; + wclw.hCursor, //HCURSOR hCursor; + wclw.hbrBackground, //HBRUSH hbrBackground; + wclw.lpszMenuName, //LPCWSTR lpszMenuName; + wclw.lpszClassName, //LPCWSTR lpszClassName; + wclw.hIconSm //HICON hIconSm; + ); + + MSGERROR(msg); + } + } + + ZeroMemory(&wcl, sizeof(wcl)); + wcl.cbSize = sizeof(wcl); + wcl.lpfnWndProc = MenuHostWndProc; + wcl.style = 0; + wcl.cbClsExtra = 0; + wcl.cbWndExtra = 0; + wcl.hInstance = hInst; + wcl.hIcon = NULL; + wcl.hCursor = LoadCursor(NULL, IDC_ARROW); + wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); + wcl.lpszMenuName = NULL; + wcl.lpszClassName = _T("PopupMenuHostWnd"); + wcl.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_POPUP), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + g_wndClass.cPopupMenuHostWnd = RegisterClassEx(&wcl); + err = GetLastError(); + if (!g_wndClass.cPopupMenuHostWnd) { + res = false; + TCHAR msg[1024]; + wsprintf(msg, TranslateT("Failed to register %s class."),wcl.lpszClassName); + MSGERROR(msg); + } + + ghwndMenuHost = CreateWindow(_T("PopupMenuHostWnd"), NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hInst, NULL); + SetWindowPos(ghwndMenuHost, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_HIDEWINDOW); + + INITCOMMONCONTROLSEX iccex; + iccex.dwICC = ICC_WIN95_CLASSES; + iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCommonControlsEx(&iccex); + + res = res && ghwndMenuHost; + + return res; +} + +void UnloadPopupWnd2() +{ + DestroyWindow(ghwndMenuHost); +} + +PopupWnd2::PopupWnd2(POPUPDATA2 *ppd, POPUPOPTIONS *theCustomOptions, bool renderOnly) +{ + m_signature = POPUP_OBJECT_SIGNARURE; + + m_lockCount = 0; + m_hbmAvatar = NULL; + m_avatar = NULL; + m_textType = TT_NONE; + m_options = theCustomOptions ? theCustomOptions : &PopUpOptions; + m_lpzSkin = NULL; + m_customPopup = false; + m_lpwzTitle = m_lpwzText = NULL; + m_lpzTitle = m_lpzText = NULL; + m_mtTitle = m_mtText = NULL; + m_hfnText = fonts.text; + m_hfnTitle = fonts.title; + m_hwnd = m_hwndToolTip = NULL; + m_bPositioned = m_bIsHovered = /*m_bIdleRequested =*/ m_bWindowCreated = m_bFade = m_bSlide = m_bDestroy = false; + m_bmp = m_bmpBase = m_bmpAnimate = NULL; + m_avatarFrameDelay = 0; + m_hhkAvatarChanged = NULL; + m_actions = NULL; + m_actionCount = 0; + m_bIsPinned = false; + updateData(ppd); + if (!renderOnly) + startThread(); +} + + +PopupWnd2::~PopupWnd2() +{ + m_signature = 0; + + if (m_lpzSkin) mir_free(m_lpzSkin); + if (m_hwnd) SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); + if (m_bmp) delete m_bmp; + if (m_bmpBase) delete m_bmpBase; + if (m_bmpAnimate) delete m_bmpAnimate; + mir_free(m_lpzText); mir_free(m_lpzTitle); + mir_free(m_lpwzText); mir_free(m_lpwzTitle); + if (m_mtText) MText.Destroy(m_mtText); + if (m_mtTitle) MText.Destroy(m_mtTitle); + if (m_avatar) delete m_avatar; + if (m_actions) delete [] m_actions; +} + +void PopupWnd2::startThread() +{ + _beginthread(WindowThread, 0, this); +} + +void PopupWnd2::create() +{ + m_hwnd = CreateWindowEx( + WS_EX_TRANSPARENT| // prevents unwanted clicks + WS_EX_TOOLWINDOW|WS_EX_TOPMOST, // dwStyleEx + _T(POPUP_WNDCLASS), // Class name + NULL, // Title + DS_SETFONT|DS_FIXEDSYS|WS_POPUP, // dwStyle + CW_USEDEFAULT, // x + CW_USEDEFAULT, // y + CW_USEDEFAULT, // Width + CW_USEDEFAULT, // Height + HWND_DESKTOP, // Parent + NULL, // menu handle + hInst, // Instance + (LPVOID)this); + + // Shadows + if (IsWinVerXPPlus()) + { + ULONG_PTR style = GetClassLongPtr(m_hwnd, GCL_STYLE); + if (m_options->DropShadow && !(style & CS_DROPSHADOW)) { + style |= CS_DROPSHADOW; + } + else if (!m_options->DropShadow && (style & CS_DROPSHADOW)){ + style &= ~CS_DROPSHADOW; + } + SetClassLongPtr(m_hwnd, GCL_STYLE, style); + } + + // tooltips + m_hwndToolTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + m_hwnd, NULL, hInst, NULL); + SetWindowPos(m_hwndToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + m_bWindowCreated = true; + update(); +} + +void PopupWnd2::updateLayered(BYTE opacity) +{ + if (!m_hwnd) return; +#if defined(_UNICODE) + if (SetWindowLong(m_hwnd, GWL_EXSTYLE, GetWindowLong(m_hwnd, GWL_EXSTYLE) | WS_EX_LAYERED)) { + RECT rc; GetWindowRect(m_hwnd, &rc); + POINT ptDst = {rc.left, rc.top}; + POINT ptSrc = {0, 0}; + + BLENDFUNCTION blend; + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + blend.SourceConstantAlpha = opacity; //m_options->UseTransparency ? opacity : 255; + blend.AlphaFormat = AC_SRC_ALPHA; + + UpdateLayeredWindow(m_hwnd, NULL, &ptDst, &m_sz, + m_bmpAnimate ? m_bmpAnimate->getDC() : m_bmp->getDC(), + &ptSrc, 0xffffffff, &blend, ULW_ALPHA); + + UpdateWindow(m_hwnd); + } +#else + if (MyUpdateLayeredWindow) { + if (SetWindowLong(m_hwnd, GWL_EXSTYLE, GetWindowLong(m_hwnd, GWL_EXSTYLE) | WS_EX_LAYERED)) + { + RECT rc; GetWindowRect(m_hwnd, &rc); + POINT ptDst = {rc.left, rc.top}; + POINT ptSrc = {0, 0}; + + BLENDFUNCTION blend; + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + blend.SourceConstantAlpha = opacity; //m_options->UseTransparency ? opacity : 255; + blend.AlphaFormat = AC_SRC_ALPHA; + + MyUpdateLayeredWindow(m_hwnd, NULL, &ptDst, &m_sz, + m_bmpAnimate ? m_bmpAnimate->getDC() : m_bmp->getDC(), + &ptSrc, 0xffffffff, &blend, ULW_ALPHA); + + UpdateWindow(m_hwnd); + } + } +#endif +} + +SIZE PopupWnd2::measure() +{ + const PopupSkin *skin = skins.getSkin(m_lpzSkin?m_lpzSkin:m_options->SkinPack); + if (!skin) return m_sz; + + MyBitmap bmpTmp(1,1); + skin->measure(bmpTmp.getDC(), this, m_options->UseMaximumWidth ? m_options->MaximumWidth : SETTING_MAXIMUMWIDTH_MAX, m_options); + return m_sz; +} + +void PopupWnd2::update() +{ + const PopupSkin *skin = skins.getSkin(m_lpzSkin?m_lpzSkin:m_options->SkinPack); + if (!skin) return; + + // update avatar + fixAvatar(); + + // destroy content bitmap so animate() can reallocate it if needed + if (m_bmp) + { + delete m_bmp; + m_bmp = NULL; + } + + // measure popup + if (m_bmpBase) delete m_bmpBase; + if (m_bmpAnimate) delete m_bmpAnimate; + m_bmpBase = new MyBitmap(1,1); + skin->measure(m_bmpBase->getDC(), this, m_options->UseMaximumWidth ? m_options->MaximumWidth : SETTING_MAXIMUMWIDTH_MAX, m_options); + + // render popup + m_bmpBase->allocate(m_sz.cx, m_sz.cy); + HDC hdc = m_bmpBase->getDC(); + if (!skin) return; + SetBkMode(hdc, TRANSPARENT); + skin->display(m_bmpBase, this, m_options->UseMaximumWidth ? m_options->MaximumWidth : SETTING_MAXIMUMWIDTH_MAX, m_options, + PopupSkin::DF_STATIC); + if (*m_time && skin->useInternalClock()) + { + SetTextColor(hdc, m_clClock); + HFONT hfnSave = (HFONT)SelectObject(m_bmpBase->getDC(), fonts.clock); + SIZE sz; GetTextExtentPoint32A(m_bmpBase->getDC(), m_time, lstrlenA(m_time), &sz); + m_bmpBase->Draw_TextA(m_time, this->m_sz.cx - sz.cx - STYLE_SZ_GAP - skin->getRightGap(), STYLE_SZ_GAP); + SelectObject(m_bmpBase->getDC(), hfnSave); + } + + m_bReshapeWindow = true; + + animate(); +} + +void PopupWnd2::animate() +{ + const PopupSkin *skin = skins.getSkin(m_lpzSkin?m_lpzSkin:m_options->SkinPack); + if (!skin) return; + + if (m_avatar->isAnimated() || m_actionCount) + { + if (!m_bmp) m_bmp = new MyBitmap(m_bmpBase->getWidth(), m_bmpBase->getHeight()); + m_bmp->Draw(m_bmpBase, 0, 0, m_bmpBase->getWidth(), m_bmpBase->getHeight()); + skin->display(m_bmp, this, m_options->UseMaximumWidth ? m_options->MaximumWidth : SETTING_MAXIMUMWIDTH_MAX, m_options, PopupSkin::DF_ANIMATE); + } else + if (m_bmpBase) + { + if (m_bmp) delete m_bmp; + m_bmp = m_bmpBase; + m_bmpBase = NULL; + } + + // update layered window if supported + updateLayered((m_options->UseTransparency && !(m_bIsHovered && m_options->OpaqueOnHover)) ? m_options->Alpha : 255); + + if (m_bReshapeWindow) + { + m_bReshapeWindow = false; +#if defined(_UNICODE) + if (m_hwnd && m_bmp && m_options->DropShadow && PopUpOptions.EnableFreeformShadows /*DoWeNeedRegionForThisSkin()*/) + SetWindowRgn(m_hwnd, m_bmp->buildOpaqueRgn(skin->getShadowRegionOpacity()), FALSE); +#else + if (!MyUpdateLayeredWindow && m_hwnd && m_bmp && PopUpOptions.Enable9xTransparency) + SetWindowRgn(m_hwnd, m_bmp->buildOpaqueRgn(skin->getLegacyRegionOpacity()), FALSE); + + if (MyUpdateLayeredWindow && m_hwnd && m_bmp && m_options->DropShadow && PopUpOptions.EnableFreeformShadows /*DoWeNeedRegionForThisSkin()*/) + SetWindowRgn(m_hwnd, m_bmp->buildOpaqueRgn(skin->getShadowRegionOpacity()), FALSE); +#endif + + if (MyDwmEnableBlurBehindWindow && PopUpOptions.EnableAeroGlass) + { + DWM_BLURBEHIND bb = {0}; + bb.dwFlags = DWM_BB_ENABLE|DWM_BB_BLURREGION; + bb.fEnable = TRUE; + bb.hRgnBlur = m_bmp->buildOpaqueRgn(254, false); + MyDwmEnableBlurBehindWindow(m_hwnd, &bb); + } + + // update tooltips + for (int i = 0; i < m_actionCount; ++i) + { + char *title = strchr(m_actions[i].actionA.lpzTitle, '/'); + if (title) title++; + else title = m_actions[i].actionA.lpzTitle; + AddTooltipTranslated(m_hwndToolTip, m_hwnd, i, m_actions[i].rc, title); + } + +// if (!customPopup && hwnd /*&& IsWindowVisible(hwnd)*/) +// PopupThreadUpdateWindow(this); + } +} + +void PopupWnd2::show() +{ + if ((m_options->UseEffect || (m_options->UseAnimations && !m_customPopup)) && m_options->FadeIn) + { + IPopupPlusEffect *effect = NULL; + m_bSlide = m_bFade = false; + DWORD dwTime, dwTime0 = GetTickCount(); + DWORD dwTime1 = dwTime0 + m_options->FadeIn; + if (m_options->UseEffect) + { + m_bFade = true; + m_btAlpha0 = 0; + m_btAlpha1 = m_options->UseTransparency ? m_options->Alpha : 255; + updateLayered(m_btAlpha0); + + if (*PopUpOptions.Effect) + { + char vfxService[128]; + mir_snprintf(vfxService, sizeof(vfxService), "PopUp/Vfx/"TCHAR_STR_PARAM, PopUpOptions.Effect); + if (ServiceExists(vfxService)) + if (effect = (IPopupPlusEffect *)CallService(vfxService, 0, 0)) + { + effect->beginEffect(m_bmp->getWidth(), m_bmp->getHeight(), m_btAlpha0, m_btAlpha1, dwTime1-dwTime0); + m_bmpAnimate = new MyBitmap(m_bmp->getWidth(), m_bmp->getHeight()); + } + } + } else + { + updateLayered(m_options->UseTransparency ? m_options->Alpha : 255); + } + if (m_options->UseAnimations && !m_customPopup) + { + m_bSlide = true; + m_ptPosition0 = m_pos; + m_ptPosition1 = m_pos; + if (m_options->Position == POS_LOWERLEFT || m_options->Position == POS_UPPERLEFT) + m_ptPosition0.x -= m_sz.cx + 2 * 5; + else + m_ptPosition0.x += m_sz.cx + 2 * 5; + SetWindowPos(m_hwnd, 0, m_ptPosition0.x, m_ptPosition0.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + } else + { + SetWindowPos(m_hwnd, 0, m_pos.x, m_pos.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + } + while ((dwTime = GetTickCount()) < dwTime1) + { + if (m_bFade) + { + if (effect) + { + effect->beginFrame(dwTime - dwTime0); + m_bmpAnimate->Draw(m_bmp, 0, 0, m_bmp->getWidth(), m_bmp->getHeight()); + for (int row = 0; row < m_bmpAnimate->getHeight(); ++row) + { + unsigned char *pixel = (unsigned char *)m_bmpAnimate->getRow(row); + for (int col = 0; col < m_bmpAnimate->getWidth(); ++col) + { + WORD alphaLevel = effect->getPixelAlpha(col, row); + pixel[0] = (pixel[0] * alphaLevel) >> 8; + pixel[1] = (pixel[1] * alphaLevel) >> 8; + pixel[2] = (pixel[2] * alphaLevel) >> 8; + pixel[3] = (pixel[3] * alphaLevel) >> 8; + pixel += 4; + } + } + effect->endFrame(); + updateLayered(255); + } else + { + updateLayered(m_btAlpha0 + (m_btAlpha1 - m_btAlpha0) * int(dwTime - dwTime0) / m_options->FadeIn); + } + } + if (m_bSlide) + SetWindowPos(m_hwnd, 0, + (int)m_ptPosition0.x + ((int)m_ptPosition1.x - (int)m_ptPosition0.x) * int(dwTime - dwTime0) / (int)m_options->FadeIn, + (int)m_ptPosition0.y + ((int)m_ptPosition1.y - (int)m_ptPosition0.y) * int(dwTime - dwTime0) / (int)m_options->FadeIn, + 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + UpdateWindow(m_hwnd); + Sleep(1); + } + + if (effect) + { + effect->endEffect(); + effect->destroy(); + delete m_bmpAnimate; + m_bmpAnimate = NULL; + } + } + + m_bSlide = m_bFade = false; + + updateLayered((m_options->UseTransparency && !(m_bIsHovered && m_options->OpaqueOnHover)) ? m_options->Alpha : 255); + //updateLayered(m_options->UseTransparency ? m_options->Alpha : 255); + SetWindowPos(m_hwnd, 0, m_pos.x, m_pos.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); +} + +void PopupWnd2::hide() +{ + if ((m_options->UseEffect || (m_options->UseAnimations && !m_customPopup)) && m_options->FadeOut) + { + m_bDestroy = true; + IPopupPlusEffect *effect = NULL; + m_bFade = m_bSlide = false; + DWORD dwTime, dwTime0 = GetTickCount(); + DWORD dwTime1 = dwTime0 + m_options->FadeOut; + if (m_options->UseEffect) + { + m_bFade = true; + m_btAlpha0 = m_options->UseTransparency ? m_options->Alpha : 255; + m_btAlpha1 = 0; + updateLayered(m_btAlpha0); + + if (*PopUpOptions.Effect) + { + char vfxService[128]; + mir_snprintf(vfxService, sizeof(vfxService), "PopUp/Vfx/"TCHAR_STR_PARAM, PopUpOptions.Effect); + if (ServiceExists(vfxService)) + if (effect = (IPopupPlusEffect *)CallService(vfxService, 0, 0)) + { + effect->beginEffect(m_bmp->getWidth(), m_bmp->getHeight(), m_btAlpha0, m_btAlpha1, dwTime1-dwTime0); + m_bmpAnimate = new MyBitmap(m_bmp->getWidth(), m_bmp->getHeight()); + } + } + } + if (m_options->UseAnimations && !m_customPopup) + { + m_bSlide = true; + m_ptPosition0 = m_pos; + m_ptPosition1 = m_pos; + if (m_options->Position == POS_LOWERLEFT || m_options->Position == POS_UPPERLEFT) + m_ptPosition1.x -= m_sz.cx + 2 * 5; + else + m_ptPosition1.x += m_sz.cx + 2 * 5; + SetWindowPos(m_hwnd, 0, m_ptPosition0.x, m_ptPosition0.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + } + while ((dwTime = GetTickCount()) < dwTime1) + { + if (m_bFade) + { + if (effect) + { + effect->beginFrame(dwTime - dwTime0); + m_bmpAnimate->Draw(m_bmp, 0, 0, m_bmp->getWidth(), m_bmp->getHeight()); + for (int row = 0; row < m_bmpAnimate->getHeight(); ++row) + { + unsigned char *pixel = (unsigned char *)m_bmpAnimate->getRow(row); + for (int col = 0; col < m_bmpAnimate->getWidth(); ++col) + { + WORD alphaLevel = effect->getPixelAlpha(col, row); + pixel[0] = (pixel[0] * alphaLevel) >> 8; + pixel[1] = (pixel[1] * alphaLevel) >> 8; + pixel[2] = (pixel[2] * alphaLevel) >> 8; + pixel[3] = (pixel[3] * alphaLevel) >> 8; + pixel += 4; + } + } + effect->endFrame(); + updateLayered(255); + } else + { + updateLayered((int)m_btAlpha0 + ((int)m_btAlpha1 - (int)m_btAlpha0) * int(dwTime - dwTime0) / (int)m_options->FadeOut); + } + } + if (m_bSlide) + SetWindowPos(m_hwnd, 0, + (int)m_ptPosition0.x + ((int)m_ptPosition1.x - (int)m_ptPosition0.x) * int(dwTime - dwTime0) / (int)m_options->FadeOut, + (int)m_ptPosition0.y + ((int)m_ptPosition1.y - (int)m_ptPosition0.y) * int(dwTime - dwTime0) / (int)m_options->FadeOut, + 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW); + UpdateWindow(m_hwnd); + Sleep(1); + } + + if (effect) + { + effect->endEffect(); + effect->destroy(); + delete m_bmpAnimate; + m_bmpAnimate = NULL; + } + } + + SetWindowPos(m_hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_HIDEWINDOW); + DestroyWindow(m_hwnd); +// hwnd = 0; +} + +bool __forceinline isTextEmpty(char *text) +{ + if (!text) + return true; + while (*text) + if (!isspace(BYTE(*text++))) + return false; + return true; +} + +bool __forceinline isTextEmpty(WCHAR *text) +{ + if (!text) + return true; + while (*text) + if (!iswspace(*text++)) + return false; + return true; +} + +void PopupWnd2::fixDefaults() +{ + if (m_options->UseWinColors) + { + m_clBack = GetSysColor(COLOR_BTNFACE); + m_clText = GetSysColor(COLOR_WINDOWTEXT); + m_clTitle = GetSysColor(COLOR_WINDOWTEXT); + m_clClock = GetSysColor(COLOR_WINDOWTEXT); + } else + if ((m_clBack == (COLORREF)NULL) && (m_clText == (COLORREF)NULL)) + { + m_clTitle = fonts.clTitle; + m_clBack = fonts.clBack; + m_clText = fonts.clText; + m_clClock = fonts.clClock; + } else + { + m_clClock = m_clTitle; + } + + if (!m_iTimeout) + { + m_iTimeout = m_options->InfiniteDelay ? -1 : m_options->Seconds; + } + + m_hContactPassed = m_hContact; + if (m_hContact) + { + if (!CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)m_hContact, 0)) + m_hContact = NULL; + } + + switch (m_textType) + { + case TT_ANSI: + m_bTextEmpty = ::isTextEmpty(m_lpzText); + break; + + case TT_UNICODE: + m_bTextEmpty = ::isTextEmpty(m_lpwzText); + break; + + default: + m_bTextEmpty = false; + break; + } +} + +void PopupWnd2::fixAvatar() +{ + if (m_avatar && !m_avatar->isValid()) + delete m_avatar; + + if (m_hbmAvatar) + { + m_avatar = new SimpleAvatar(m_hbmAvatar, true); + } else + { + m_avatar = PopupAvatar::create(m_hContact); + } +} + +int PopupWnd2::fixActions(POPUPACTION *theActions, int count) +{ + bool isIm = (m_hContact && + (CallProtoService( + (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)m_hContact, 0), + PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM)) ? true : false; + +// bool enableDefault = (isIm || !(PopUpOptions.actions&ACT_DEF_IMONLY)) ? true : false; + bool enableDefaultGen = (m_hContact || !(PopUpOptions.actions&ACT_DEF_NOGLOBAL)) ? true : false; + bool enableDefaultUsr = (isIm || m_hContact && !(PopUpOptions.actions&ACT_DEF_IMONLY)) ? true : false; + bool iconSize = PopUpOptions.actions&ACT_LARGE ? TRUE : FALSE; + + if (PopUpOptions.actions&ACT_ENABLE) + { + if (enableDefaultUsr && isIm && IsActionEnabled("General/Quick reply")) ++m_actionCount; + if (enableDefaultUsr && isIm && IsActionEnabled("General/Send message")) ++m_actionCount; + if (enableDefaultUsr && IsActionEnabled("General/User details")) ++m_actionCount; + if (enableDefaultUsr && IsActionEnabled("General/Contact menu")) ++m_actionCount; + if (enableDefaultUsr && DBGetContactSettingByte(m_hContact, "CList", "NotOnList", 0) && IsActionEnabled("General/Add permanently")) ++m_actionCount; + if (enableDefaultGen && (m_iTimeout != -1) && IsActionEnabled("General/Pin popup")) ++m_actionCount; + if (enableDefaultGen && IsActionEnabled("General/Dismiss popup")) ++m_actionCount; + if (enableDefaultGen && IsActionEnabled("General/Copy to clipboard")) ++m_actionCount; + + int iAction = fixActions(theActions, count, m_actionCount); + + if (enableDefaultUsr && isIm && IsActionEnabled("General/Quick reply")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = IcoLib_GetIcon(ICO_ACT_REPLY,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/Quick reply"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_REPLY; + ++iAction; + } + if (enableDefaultUsr && isIm && IsActionEnabled("General/Send message")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = IcoLib_GetIcon(ICO_ACT_MESS,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/Send message"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_MESSAGE; + ++iAction; + } + if (enableDefaultUsr && IsActionEnabled("General/User details")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = IcoLib_GetIcon(ICO_ACT_INFO,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/User details"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_DETAILS; + ++iAction; + } + if (enableDefaultUsr && IsActionEnabled("General/Contact menu")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = IcoLib_GetIcon(ICO_ACT_MENU,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/Contact menu"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_MENU; + ++iAction; + } + if (enableDefaultUsr && DBGetContactSettingByte(m_hContact, "CList", "NotOnList", 0) && IsActionEnabled("General/Add permanently")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = IcoLib_GetIcon(ICO_ACT_ADD,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/Add permanently"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_ADD; + ++iAction; + } + if (enableDefaultGen && (m_iTimeout != -1) && IsActionEnabled("General/Pin popup")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = m_bIsPinned ? IcoLib_GetIcon(ICO_ACT_PINNED,iconSize) : IcoLib_GetIcon(ICO_ACT_PIN,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/Pin popup"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_PIN; + ++iAction; + } + if (enableDefaultGen && IsActionEnabled("General/Dismiss popup")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = IcoLib_GetIcon(ICO_ACT_CLOSE,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/Dismiss popup"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_DISMISS; + ++iAction; + } + if (enableDefaultGen && IsActionEnabled("General/Copy to clipboard")) + { + m_actions[iAction].actionA.cbSize = sizeof(POPUPACTION); + m_actions[iAction].actionA.lchIcon = IcoLib_GetIcon(ICO_ACT_COPY,iconSize); + lstrcpyA(m_actions[iAction].actionA.lpzTitle, "General/Copy to clipboard"); + m_actions[iAction].actionA.wParam = 0; + m_actions[iAction].actionA.lParam = ACT_DEF_COPY; + ++iAction; + } + } + + return m_actionCount; +} + +int PopupWnd2::fixActions(POPUPACTION *theActions, int count, int additional) +{ + m_actionCount = 0; + if (m_actions) delete [] m_actions; + m_actions = NULL; + + int i; + + m_actionCount = additional; + for (i = 0; i < count; ++i) + if ((theActions[i].flags&PAF_ENABLED) && IsActionEnabled(&theActions[i])) + ++m_actionCount; + + m_actions = new ActionInfo[m_actionCount]; + int iAction = 0; + + for (i = 0; i < count; ++i) + if ((theActions[i].flags&PAF_ENABLED) && IsActionEnabled(&theActions[i])) + { + m_actions[iAction].actionA = theActions[i]; + ++iAction; + } + + return iAction; +} + +void PopupWnd2::updateData(POPUPDATA *ppd) +{ + m_hContact = ppd->lchContact; + + m_clBack = ppd->colorBack; + m_clClock = m_clTitle = m_clText = ppd->colorText; + m_iTimeout = m_options->DisplayTime; + + mir_free(m_lpzText); mir_free(m_lpzTitle); + mir_free(m_lpwzText); mir_free(m_lpwzTitle); + if (m_textType == TT_NONE) m_textType = TT_ANSI; + m_lpzTitle = mir_strdup(ppd->lpzContactName); + m_lpzText = mir_strdup(ppd->lpzText); + m_lpwzTitle = m_lpwzText = NULL; +// mtTitle = mtText = NULL; + // hfnTitle, hfnText; + m_hIcon = ppd->lchIcon; + + m_PluginData = ppd->PluginData; + m_PluginWindowProc = ppd->PluginWindowProc; + + if (m_options->DisplayTime) + GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL,"HH':'mm", m_time, SIZEOF(m_time)); + else m_time[0] = 0; + + fixDefaults(); + + if (m_textType == TT_MTEXT) buildMText(); +} + +void PopupWnd2::updateData(POPUPDATAEX_V2 *ppd) +{ + m_hContact = ppd->lchContact; + + m_clBack = ppd->colorBack; + m_clClock = m_clTitle = m_clText = ppd->colorText; + m_iTimeout = ppd->iSeconds ? ppd->iSeconds : m_options->Seconds; + + if (m_textType == TT_NONE) m_textType = TT_ANSI; + mir_free(m_lpzText); mir_free(m_lpzTitle); + mir_free(m_lpwzText); mir_free(m_lpwzTitle); + m_lpzTitle = mir_strdup(ppd->lpzContactName); + m_lpzText = mir_strdup(ppd->lpzText); + m_lpwzTitle = m_lpwzText = NULL; +// mtTitle = mtText = NULL; + // hfnTitle, hfnText; + m_hIcon = ppd->lchIcon; + m_hNotification = ppd->hNotification; + + m_PluginData = ppd->PluginData; + m_PluginWindowProc = ppd->PluginWindowProc; + + if (m_options->DisplayTime) + GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL,"HH':'mm", m_time, SIZEOF(m_time)); + else m_time[0] = 0; + + fixDefaults(); + fixActions(ppd->lpActions, ppd->actionCount); + + if (m_textType == TT_MTEXT) buildMText(); +} + +void PopupWnd2::updateData(POPUPDATAW_V2 *ppd) +{ + m_hContact = ppd->lchContact; + + m_clBack = ppd->colorBack; + m_clClock = m_clTitle = m_clText = ppd->colorText; + m_iTimeout = ppd->iSeconds ? ppd->iSeconds : m_options->Seconds; + + if (m_textType == TT_NONE) m_textType = TT_UNICODE; + mir_free(m_lpzText); mir_free(m_lpzTitle); + mir_free(m_lpwzText); mir_free(m_lpwzTitle); + m_lpzTitle = m_lpzText = NULL; + m_lpwzTitle = mir_wstrdup(ppd->lpwzContactName); + m_lpwzText = mir_wstrdup(ppd->lpwzText); +// mtTitle = mtText = NULL; + // hfnTitle, hfnText; + m_hIcon = ppd->lchIcon; + m_hNotification = ppd->hNotification; + + m_PluginData = ppd->PluginData; + m_PluginWindowProc = ppd->PluginWindowProc; + + if (m_options->DisplayTime) + GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL,"HH':'mm", m_time, SIZEOF(m_time)); + else m_time[0] = 0; + + fixDefaults(); + fixActions(ppd->lpActions, ppd->actionCount); + + if (m_textType == TT_MTEXT) buildMText(); +} + +void PopupWnd2::updateData(POPUPDATA2 *ppd) +{ + m_hContact = ppd->lchContact; + + m_clBack = ppd->colorBack; + m_clClock = m_clTitle = m_clText = ppd->colorText; + m_iTimeout = ppd->iSeconds; + + mir_free(m_lpzText); mir_free(m_lpzTitle); + mir_free(m_lpwzText); mir_free(m_lpwzTitle); + if (ppd->flags&PU2_UNICODE) + { + if (m_textType == TT_NONE) m_textType = TT_UNICODE; + m_lpzTitle = m_lpzText = NULL; + m_lpwzTitle = mir_wstrdup(ppd->lpwzTitle); + m_lpwzText = mir_wstrdup(ppd->lpwzText); + m_lpzTitle = m_lpzText = NULL; + } else + { + if (m_textType == TT_NONE) m_textType = TT_ANSI; + m_lpzTitle = mir_strdup(ppd->lpzTitle); + m_lpzText = mir_strdup(ppd->lpzText); + m_lpwzTitle = m_lpwzText = NULL; + } + + m_hIcon = ppd->lchIcon; + m_hNotification = ppd->lchNotification; + + m_PluginData = ppd->PluginData; + m_PluginWindowProc = ppd->PluginWindowProc; + m_customPopup = (ppd->flags & PU2_CUSTOM_POPUP)!= 0; + + m_hbmAvatar = ppd->hbmAvatar; + m_lpzSkin = mir_a2t(ppd->lpzSkin); + + if (m_options->DisplayTime) + { + if (ppd->dwTimestamp) + { + DBTIMETOSTRING dbtts; + dbtts.szFormat = "t"; + dbtts.szDest = m_time; + dbtts.cbDest = SIZEOF(m_time); + CallService(MS_DB_TIME_TIMESTAMPTOSTRING, (WPARAM)ppd->dwTimestamp, (LPARAM)&dbtts); + } else + { + GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL,"HH':'mm", m_time, SIZEOF(m_time)); + } + } + else m_time[0] = 0; + + fixDefaults(); + fixActions(ppd->lpActions, ppd->actionCount); + + if (m_textType == TT_MTEXT) buildMText(); +} + +void PopupWnd2::buildMText() +{ + if (!(htuText && htuTitle && PopUpOptions.UseMText)) + return; + + if (m_mtText) MText.Destroy(m_mtText); + if (m_mtTitle)MText.Destroy(m_mtTitle); + m_mtText = m_mtTitle = NULL; + + if (m_lpwzText && m_lpwzTitle) { + m_textType = TT_MTEXT; + m_mtText = MText.CreateW(htuText, m_lpwzText); + m_mtTitle = MText.CreateW(htuTitle,m_lpwzTitle); + } + else if (m_lpzText && m_lpzTitle) { + m_textType = TT_MTEXT; + if (ServiceExists(MS_TEXT_CREATEW)) { + LOGFONT lf; + LPWSTR lpwzBuf = NULL; + + GetObject(m_hfnText, sizeof(lf), &lf); + lpwzBuf = mir_a2u(m_lpzText); + m_mtText = MText.CreateW(htuText, lpwzBuf); + mir_free(lpwzBuf); lpwzBuf = NULL; + + GetObject(m_hfnTitle, sizeof(lf), &lf); + lpwzBuf = mir_a2u(m_lpzTitle); + m_mtTitle = MText.CreateW(htuTitle, lpwzBuf); + mir_free(lpwzBuf); lpwzBuf = NULL; + } + else { + m_mtText = MText.Create(htuText, m_lpzText); + m_mtTitle = MText.Create(htuTitle,m_lpzTitle); + } + } +} + +void PopupWnd2::updateText(char *text) +{ + if (m_lpzText) + { + mir_free(m_lpzText); + m_lpzText = mir_strdup(text); + if (m_textType == TT_MTEXT) + buildMText(); + } + m_bTextEmpty = ::isTextEmpty(m_lpzText); +} + +void PopupWnd2::updateText(WCHAR *text) +{ + if (m_lpwzText) + { + mir_free(m_lpwzText); + m_lpwzText = mir_wstrdup(text); + if (m_textType == TT_MTEXT) + buildMText(); + } + m_bTextEmpty = ::isTextEmpty(m_lpwzText); +} + +void PopupWnd2::updateTitle(char *title) +{ + if (m_lpzTitle) + { + mir_free(m_lpzTitle); + m_lpzTitle = mir_strdup(title); + if (m_textType == TT_MTEXT) + buildMText(); + } +} + +void PopupWnd2::updateTitle(WCHAR *title) +{ + if (m_lpwzTitle) + { + mir_free(m_lpwzTitle); + m_lpwzTitle = mir_wstrdup(title); + if (m_textType == TT_MTEXT) + buildMText(); + } +} + +void PopupWnd2::updateTimer() +{ + KillTimer(m_hwnd, POPUP_TIMER); + if (m_iTimeout > 0) + SetTimer(m_hwnd, POPUP_TIMER, 1000, 0); +} + +LRESULT CALLBACK NullWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_COMMAND: + case WM_CONTEXTMENU: + PUDeletePopUp(hwnd); + break; + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + +struct ReplyEditData +{ + HWND hwndPopup; + HANDLE hContact; + WNDPROC oldWndProc; +}; + +bool IsMsgServiceNameW(HANDLE hContact) { + if (g_popup.isMirUnicode) { + char szServiceName[100]; + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto == NULL) + return false; + + mir_snprintf(szServiceName, sizeof(szServiceName), "%s%sW", szProto, PSS_MESSAGE); + if (ServiceExists(szServiceName)) + return true; + } + return false; +} + +BOOL IsUtfSendAvailable(HANDLE hContact) +{ + char* szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if(szProto == NULL) return FALSE; + //check for MetaContact and get szProto from subcontact + if(strcmp(szProto, gszMetaProto)==0) { + HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETDEFAULTCONTACT, (WPARAM)hContact, 0); + if(!hSubContact) return FALSE; + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hSubContact, 0); + } + return(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF) ? TRUE : FALSE; +} + +void AddMessageToDB(HANDLE hContact, char *msg, int flag/*bool utf*/) +{ + DBEVENTINFO dbei = {0}; + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = DBEF_SENT | ((flag&PREF_UTF)==PREF_UTF ? DBEF_UTF : 0); + dbei.szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + dbei.timestamp = time(NULL); + if(g_popup.isOsUnicode && !((flag&PREF_UTF)==PREF_UTF) && (flag&PREF_UNICODE)==PREF_UNICODE) + dbei.cbBlob = (lstrlenW((LPWSTR)msg) + 1)*sizeof(WCHAR/*TCHAR*/); + else + dbei.cbBlob = lstrlenA(msg) + 1; + dbei.pBlob = (PBYTE)msg; + CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); +} + +LRESULT CALLBACK ReplyEditWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + ReplyEditData *dat = (ReplyEditData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + WNDPROC oldWndProc = dat ? dat->oldWndProc : NULL; + + switch (message) + { +/* + case WM_ERASEBKGND: + { + HDC hdc = (HDC)wParam; + RECT rc; GetClientRect(hwnd, &rc); + FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW)); + SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); + DrawText(hdc, "Quick Reply", -1, &rc, DT_BOTTOM|DT_RIGHT|DT_SINGLELINE); + return TRUE; + } +*/ + case WM_KEYDOWN: + { + switch (wParam) + { + case VK_RETURN: + { + char *buf = NULL; + int flag = 0; + bool bSendW = IsMsgServiceNameW(dat->hContact); + //if (g_popup.isMirUnicode) + if (IsWindowUnicode(hwnd)) + { + WCHAR msg[2048]; + LPWSTR bufW = NULL; +#if defined(_UNICODE) + SendMessageW(hwnd, WM_GETTEXT, SIZEOF(msg), (LPARAM)msg); +#else + MySendMessageW(hwnd, WM_GETTEXT, SIZEOF(msg), (LPARAM)msg); +#endif + if(wcslen(msg)==0){ + DestroyWindow(hwnd); + return 0; + } + // we have unicode message, check if it is possible and reasonable to send it as unicode + if (IsUtfSendAvailable(dat->hContact)) { + buf = mir_utf8encodeW(msg); + flag = PREF_UTF; + } + else if(bSendW){ + bufW = mir_wstrdup(msg) /*mir_tstrdup(msg)*/; + buf = (char*)bufW; + flag = PREF_UNICODE /*PREF_TCHAR*/; + } + else { + buf = mir_u2a(msg); + flag = 0; + } + } + else { + char msg[2048]; + GetWindowTextA(hwnd, msg, SIZEOF(msg)); + if(strlen(msg)==0){ + DestroyWindow(hwnd); + return 0; + } + // we have message, check if it is possible and reasonable to send it as unicode + if ( IsUtfSendAvailable( dat->hContact )) { + buf = mir_utf8encode(msg); + flag = PREF_UTF; + } + else { + buf = mir_strdup(msg) /*mir_tstrdup(msg)*/; + flag = 0 /*PREF_TCHAR*/; + } + } + + CallContactService(dat->hContact, bSendW ? (PSS_MESSAGE"W"):PSS_MESSAGE, flag, (LPARAM)buf); + AddMessageToDB(dat->hContact, buf, flag); + mir_free(buf); + + DestroyWindow(hwnd); + return 0; + } + case VK_ESCAPE: + { + DestroyWindow(hwnd); + return 0; + } + } + break; + } + + case WM_ACTIVATE: + if (wParam == WA_INACTIVE) + DestroyWindow(hwnd); + break; + + case WM_DESTROY: + PopupThreadUnlock(); + if (!(PopUpOptions.actions&ACT_DEF_KEEPWND)) + PUDeletePopUp(dat->hwndPopup); + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)dat->oldWndProc); + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + mir_free(dat); + } + + if (oldWndProc) + { +#if defined(_UNICODE) + return CallWindowProcW(oldWndProc, hwnd, message, wParam, lParam); +#else + if (IsWindowUnicode(hwnd) && MyCallWindowProcW) + return MyCallWindowProcW(oldWndProc, hwnd, message, wParam, lParam); + return CallWindowProc(oldWndProc, hwnd, message, wParam, lParam); +#endif + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + +LRESULT CALLBACK PopupWnd2::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CREATE: + { +// show(); + return DefWindowProc(m_hwnd, message, wParam, lParam); + break; + } + + case UM_INITPOPUP: + { + if (!m_customPopup) PopupThreadAddWindow(this); + if (m_iTimeout > 0) SetTimer(m_hwnd, POPUP_TIMER, m_iTimeout*1000, 0); + if (m_hContact && !m_hbmAvatar && PopUpOptions.EnableAvatarUpdates) + m_hhkAvatarChanged = HookEventMessage(ME_AV_AVATARCHANGED, m_hwnd, UM_AVATARCHANGED); + if (m_avatar->activeFrameDelay() > 0) SetTimer(m_hwnd, AVATAR_TIMER, m_avatar->activeFrameDelay(), 0); + + // prevent unwanted clicks, but allow wanted :) + GetCursorPos(&m_ptPrevCursor); + SetTimer(m_hwnd, CURSOR_TIMER, 500, NULL); + + break; + } + + case UM_POPUPSHOW: + { + POINT pt; pt.x = wParam; pt.y = lParam; + setPosition(pt); + show(); + break; + } + + case UM_AVATARCHANGED: + { + if ((HANDLE)wParam == m_hContact) + { + m_avatar->invalidate(); + update(); + if (m_avatar->activeFrameDelay() > 0) SetTimer(m_hwnd, AVATAR_TIMER, m_avatar->activeFrameDelay(), 0); + } + break; + } + + case UM_POPUPACTION: + { + if (wParam != 0) break; + switch (lParam) + { + case ACT_DEF_MESSAGE: + CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)m_hContact, 0); + if (!(PopUpOptions.actions&ACT_DEF_KEEPWND)) + PUDeletePopUp(m_hwnd); + break; + + case ACT_DEF_REPLY: + { + if (!m_customPopup) PopupThreadLock(); + //RECT rc = renderInfo.textRect; + //MapWindowPoints(hwnd, NULL, (LPPOINT)&rc, 2); + RECT rc; GetWindowRect(m_hwnd, &rc); +#if defined(_UNICODE) + HWND hwndEditBox = CreateWindowExW(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, + g_wndClass.cPopupEditBox ? L"PopupEditBox" : L"EDIT", + NULL, + WS_BORDER|WS_POPUP|WS_VISIBLE|ES_AUTOVSCROLL|ES_LEFT|ES_MULTILINE|ES_NOHIDESEL|ES_WANTRETURN, + rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInst, NULL); +#else + HWND hwndEditBox = 0; + if(MyCreateWindowExW && g_popup.isMirUnicode) { + //create unicode window only if miranda is unicode + //coz many protocol make trouble with unicode text on utf8 send inside ansi release + hwndEditBox = MyCreateWindowExW(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, + g_wndClass.cPopupEditBox ? L"PopupEditBox" : L"EDIT", + NULL, + WS_BORDER|WS_POPUP|WS_VISIBLE|ES_AUTOVSCROLL|ES_LEFT|ES_MULTILINE|ES_NOHIDESEL|ES_WANTRETURN, + rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInst, NULL); + } + else { + hwndEditBox = CreateWindowExA(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, + g_wndClass.cPopupEditBox ? "PopupEditBox" : "EDIT", + NULL, + WS_BORDER|WS_POPUP|WS_VISIBLE|ES_AUTOVSCROLL|ES_LEFT|ES_MULTILINE|ES_NOHIDESEL|ES_WANTRETURN, + rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInst, NULL); + } +#endif + ReplyEditData *dat = (ReplyEditData *)mir_alloc(sizeof(ReplyEditData)); + dat->oldWndProc = (WNDPROC)GetWindowLongPtr(hwndEditBox, (LONG_PTR)GWLP_WNDPROC); + dat->hwndPopup = m_hwnd; + dat->hContact = m_hContact; + if(IsWindowUnicode(hwndEditBox)) { +#if defined(_UNICODE) + SendMessageW(hwndEditBox, WM_SETFONT, (WPARAM)fonts.text, TRUE); +#else + MySendMessageW(hwndEditBox, WM_SETFONT, (WPARAM)fonts.text, TRUE); +#endif + SetWindowLongPtrW(hwndEditBox, GWLP_USERDATA, (LONG_PTR)dat); + SetWindowLongPtrW(hwndEditBox, GWLP_WNDPROC, (LONG_PTR)ReplyEditWndProc); + } + else { + SendMessageA(hwndEditBox, WM_SETFONT, (WPARAM)fonts.text, TRUE); + SetWindowLongPtrA(hwndEditBox, GWLP_USERDATA, (LONG_PTR)dat); + SetWindowLongPtrA(hwndEditBox, GWLP_WNDPROC, (LONG_PTR)ReplyEditWndProc); + } + SetFocus(hwndEditBox); + break; + } + + case ACT_DEF_DETAILS: + CallServiceSync(MS_USERINFO_SHOWDIALOG, (WPARAM)m_hContact, 0); + if (!(PopUpOptions.actions&ACT_DEF_KEEPWND)) + PUDeletePopUp(m_hwnd); + break; + case ACT_DEF_MENU: + { + lock(); + PostMessage(ghwndMenuHost, UM_SHOWMENU, (WPARAM)m_hwnd, (LPARAM)m_hContact); + break; + } + case ACT_DEF_ADD: + { + ADDCONTACTSTRUCT acs = {0}; + acs.handle = m_hContact; + acs.handleType = HANDLE_CONTACT; + acs.szProto = 0; + CallServiceSync(MS_ADDCONTACT_SHOW, NULL, (LPARAM)&acs); + if (!(PopUpOptions.actions&ACT_DEF_KEEPWND)) + PUDeletePopUp(m_hwnd); + break; + } + case ACT_DEF_PIN: + { + if (m_bIsPinned) + { + SetTimer(m_hwnd, POPUP_TIMER, m_iTimeout*1000, NULL); + } else + { + KillTimer(m_hwnd, POPUP_TIMER); + } + m_bIsPinned = !m_bIsPinned; + bool iconSize = PopUpOptions.actions&ACT_LARGE ? TRUE : FALSE; + PUModifyActionIcon(m_hwnd, wParam, lParam, m_bIsPinned ? IcoLib_GetIcon(ICO_ACT_PINNED,iconSize) : IcoLib_GetIcon(ICO_ACT_PIN,iconSize)); + break; + } + case ACT_DEF_DISMISS: + PUDeletePopUp(m_hwnd); + break; + case ACT_DEF_COPY: + { + #ifdef UNICODE + #define CF_TCHAR CF_UNICODETEXT + #else + #define CF_TCHAR CF_TEXT + #endif + HGLOBAL clipbuffer; + static TCHAR * buffer, *text; + char* sztext; + if ((this->m_lpwzText) || (this->m_lpwzTitle)) + { + text = (TCHAR*)mir_alloc((_tcslen(this->m_lpwzText) + _tcslen(this->m_lpwzTitle)+3)*sizeof(TCHAR)); + mir_sntprintf(text, _tcslen(this->m_lpwzText) + _tcslen(this->m_lpwzTitle)+3, _T("%s\n\n%s"), this->m_lpwzTitle, this->m_lpwzText); + } + else if ((this->m_lpzText) || (this->m_lpzTitle)) + { + sztext = (char*)mir_alloc((lstrlenA(this->m_lpzText) + lstrlenA(this->m_lpzTitle)+3)*sizeof(char)); + mir_snprintf(sztext, lstrlenA(this->m_lpzText) + lstrlenA(this->m_lpzTitle)+3, "%s\n\n%s", this->m_lpzTitle, this->m_lpzText); + text = mir_a2t(sztext); + } + OpenClipboard(m_hwnd); + EmptyClipboard(); + clipbuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (lstrlen(text)+1) * sizeof(TCHAR)); + buffer = (TCHAR *)GlobalLock(clipbuffer); + lstrcpy(buffer, text); + GlobalUnlock(clipbuffer); + SetClipboardData(CF_TCHAR, clipbuffer); + CloseClipboard(); + if (sztext) + mir_free(text); + PUDeletePopUp(m_hwnd); + break; + } + } + break; + } + + case UM_POPUPMODIFYACTIONICON: + { + LPPOPUPACTIONID actionId = (LPPOPUPACTIONID)wParam; + for (int i = 0; i < m_actionCount; ++i) + if ((m_actions[i].actionA.wParam == actionId->wParam) && + (m_actions[i].actionA.lParam == actionId->lParam)) + { + m_actions[i].actionA.lchIcon = (HICON)lParam; + animate(); + break; + } + + break; + } + + case UM_MENUDONE: + { + unlock(); + if (!(PopUpOptions.actions&ACT_DEF_KEEPWND)) + PUDeletePopUp(m_hwnd); + break; + } +/* + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS *wp = (WINDOWPOS *)lParam; + if (!bIsHovered) + { + RECT rc; SetRect(&rc, wp->x, wp->y, wp->x + wp->cx, wp->y + wp->cy); + GetCursorPos(&ptPrevCursor); + + if (PtInRect(&rc, ptPrevCursor)) + { + SetWindowLongPtr(hwnd, GWLP_EXSTYLE, GetWindowLongPtr(hwnd, GWLP_EXSTYLE) | WS_EX_TRANSPARENT); + SetTimer(hwnd, CURSOR_TIMER, 500, NULL); + } + } + break; + } +*/ + case WM_LBUTTONUP: + { + int i; + for (i = 0; i < m_actionCount; ++i) + if (m_actions[i].hover) + { + SendMessage(m_hwnd, UM_POPUPACTION, m_actions[i].actionA.wParam, m_actions[i].actionA.lParam); + break; + } + + if (i == m_actionCount) + { + if(PopUpOptions.overrideLeft!=false && (m_hContact!=NULL || PopUpOptions.overrideLeft == 5 || PopUpOptions.overrideLeft == 6)){ + switch (PopUpOptions.overrideLeft){ + default: + case 1:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_MESSAGE); break; + case 2:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_REPLY); break; + case 3:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_DETAILS); break; + case 4:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_MENU); break; + case 5:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_DISMISS); break; + case 6:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_PIN); break; + case 7:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_COPY); break; + } + }else{ + lock(); + if (!PerformAction(m_hNotification, m_hwnd, message, wParam, lParam)) + SendMessage(m_hwnd, WM_COMMAND, 0, 0); + unlock(); + } + } + break; + } + + case WM_MBUTTONUP: + { + if(PopUpOptions.overrideMiddle!=false && (m_hContact!=NULL || PopUpOptions.overrideMiddle == 5 || PopUpOptions.overrideMiddle == 6)){ + switch (PopUpOptions.overrideMiddle){ + default: + case 1:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_MESSAGE); break; + case 2:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_REPLY); break; + case 3:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_DETAILS); break; + case 4:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_MENU); break; + case 5:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_DISMISS); break; + case 6:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_PIN); break; + case 7:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_COPY); break; + } + } + break; + } + + case WM_CONTEXTMENU: + { + if(PopUpOptions.overrideRight!=false && (m_hContact!=NULL || PopUpOptions.overrideRight == 5 || PopUpOptions.overrideRight == 6)){ + switch (PopUpOptions.overrideRight){ + default: + case 1:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_MESSAGE); break; + case 2:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_REPLY); break; + case 3:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_DETAILS); break; + case 4:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_MENU); break; + case 5:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_DISMISS); break; + case 6:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_PIN); break; + case 7:SendMessage(m_hwnd, UM_POPUPACTION,0, ACT_DEF_COPY); break; + } + return TRUE; + }else{ + lock(); + if (PerformAction(m_hNotification, m_hwnd, message, wParam, lParam)) + { + unlock(); + return TRUE; + } + unlock(); + } + } +/* + case WM_RBUTTONUP: + { + SendMessage(hwnd, WM_CONTEXTMENU, 0, 0); + break; + } +*/ + case WM_TIMER: + { + switch (wParam) + { + case POPUP_TIMER: + { + KillTimer(m_hwnd, POPUP_TIMER); + if (!m_customPopup) + { + PopupThreadRequestRemoveWindow(this); + } else + { + if (isLocked()) + { + updateTimer(); + } else + { + PostMessage(m_hwnd, WM_CLOSE, 0, 0); + } + } + break; + } + + case AVATAR_TIMER: + { + int newDelay = m_avatar->activeFrameDelay(); + animate(); + if ((newDelay <= 0) || (newDelay != m_avatarFrameDelay)) KillTimer(m_hwnd, AVATAR_TIMER); + if (newDelay > 0) { + SetTimer(m_hwnd, AVATAR_TIMER, newDelay, 0); + m_avatarFrameDelay = newDelay; + } + break; + } + + case CURSOR_TIMER: + { + POINT pt; GetCursorPos(&pt); + if (abs(pt.x-m_ptPrevCursor.x) + abs(pt.y-m_ptPrevCursor.y) > 4) + { + SetWindowLong(m_hwnd, GWL_EXSTYLE, GetWindowLong(m_hwnd, GWL_EXSTYLE) & ~WS_EX_TRANSPARENT); + KillTimer(m_hwnd, CURSOR_TIMER); + } + break; + } + } + + break; + } + + case UM_DESTROYPOPUP: + { + KillTimer(m_hwnd, POPUP_TIMER); + KillTimer(m_hwnd, AVATAR_TIMER); + KillTimer(m_hwnd, CURSOR_TIMER); + PostMessage(m_hwnd, WM_CLOSE, 0, 0); + break; + } + + case UM_CHANGEPOPUP: + { + switch (wParam) + { + case CPT_TEXT: updateText((char *)lParam); mir_free((void *)lParam); break; + case CPT_TEXTW: updateText((WCHAR *)lParam); mir_free((void *)lParam); break; + case CPT_TITLE: updateTitle((char *)lParam); mir_free((void *)lParam); break; + case CPT_TITLEW: updateTitle((WCHAR *)lParam); mir_free((void *)lParam); break; + case CPT_DATA: updateData((POPUPDATA *)lParam); mir_free((void *)lParam); break; + case CPT_DATAEX: updateData((POPUPDATAEX_V2 *)lParam); mir_free((void *)lParam); break; + case CPT_DATAW: updateData((POPUPDATAW_V2 *)lParam); mir_free((void *)lParam); break; + } + update(); + break; + } + + case UM_CALLMETHOD: + { + MethodPtr *method_copy = (MethodPtr *)wParam; + (this->*(*method_copy))(lParam); + delete method_copy; + break; + } + + case WM_PAINT: + { + if (GetUpdateRect(m_hwnd, 0, FALSE)) + { + PAINTSTRUCT ps; + HDC mydc = BeginPaint(m_hwnd, &ps); + BitBlt(mydc, 0, 0, m_sz.cx, m_sz.cy, m_bmp->getDC(), 0, 0, SRCCOPY); + EndPaint(m_hwnd, &ps); + return 0; + } + break; + } + + case WM_PRINT: + case WM_PRINTCLIENT: + { + HDC mydc = (HDC)wParam; + BitBlt(mydc, 0, 0, m_sz.cx, m_sz.cy, m_bmp->getDC(), 0, 0, SRCCOPY); + break; + } + + case WM_MOUSEMOVE: + { + const PopupSkin *skin = skins.getSkin(m_lpzSkin?m_lpzSkin:m_options->SkinPack); + if (skin) + if (skin->onMouseMove(this, LOWORD(lParam), HIWORD(lParam))) + animate(); + + if (m_bIsHovered) break; + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.dwHoverTime = HOVER_DEFAULT; + tme.hwndTrack = m_hwnd; + _TrackMouseEvent(&tme); + if (!m_customPopup) PopupThreadLock(); +#if defined(_UNICODE) + if (m_options->OpaqueOnHover) + updateLayered(255); +#else + if (MySetLayeredWindowAttributes && m_options->OpaqueOnHover) + updateLayered(255); +#endif + m_bIsHovered = true; + break; + } + case WM_MOUSELEAVE: + { + const PopupSkin *skin = skins.getSkin(m_lpzSkin?m_lpzSkin:m_options->SkinPack); + if (skin) + if (skin->onMouseMove(this, LOWORD(lParam), HIWORD(lParam))) + animate(); + + if (!m_bIsHovered) break; +#if defined(_UNICODE) + if (m_options->OpaqueOnHover) + updateLayered(m_options->UseTransparency ? m_options->Alpha : 255); +#else + if (MySetLayeredWindowAttributes && m_options->OpaqueOnHover) + updateLayered(m_options->UseTransparency ? m_options->Alpha : 255); +#endif + if (!m_customPopup) PopupThreadUnlock(); + m_bIsHovered = false; + break; + } + + case WM_CLOSE: + { + hide(); + return TRUE; + } + + case WM_DESTROY: + { + if (m_bIsHovered) + { + if (!m_customPopup) PopupThreadUnlock(); + m_bIsHovered = false; + } + if (m_hhkAvatarChanged) + PopUp_UnhookEventAsync((WPARAM)m_hwnd, (LPARAM)m_hhkAvatarChanged); + SendMessage(m_hwnd, UM_FREEPLUGINDATA, 0, 0); + SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); + m_hwnd = 0; + + DestroyWindow(m_hwndToolTip); + + if (!m_customPopup) + { + // we can't access "this" pointer after followint line! + PopupThreadRemoveWindow(this); + } else + { + delete this; + } + + PostQuitMessage(0); + return TRUE; + } +/* + case WM_WINDOWPOSCHANGING: +// case WM_WINDOWPOSCHANGED: + { + WINDOWPOS *wp = (WINDOWPOS *)lParam; + wp->flags |= SWP_NOACTIVATE; // block focus stealing + + if (!(wp->flags & SWP_NOZORDER)) + { + if ((wp->hwndInsertAfter == HWND_BOTTOM) || + (wp->hwndInsertAfter == HWND_NOTOPMOST) || + (wp->hwndInsertAfter == HWND_TOP)) + { + wp->hwndInsertAfter == HWND_TOPMOST; + } else + if (wp->hwndInsertAfter != HWND_TOPMOST) + { + HWND hwndAbove = GetWindow(wp->hwndInsertAfter, GW_HWNDPREV); + if (hwndAbove) + { + char buf[64]; + GetClassName(hwndAbove, buf, sizeof(buf)); + buf[sizeof(buf)-1] = 0; + + if (lstrcmp(buf, POPUP_WNDCLASS)) + wp->hwndInsertAfter == HWND_TOPMOST; + } + } + } + + // this allows us to reduce message traffic + return 0; + } +*/ + } + + if (m_PluginWindowProc && !closing) + { + lock(); + + // some plugins use cdecl instead of stdcall + // this is an attempt to fix them + BOOL result; + + result = m_PluginWindowProc(this->m_hwnd, message, wParam, lParam); +/* + DWORD esp_in, esp_out, esp_fixed; + __asm + { + push ecx + mov [esp_in], esp + push [lParam] + push [wParam] + push [message] + mov ecx, [this] + push [ecx+hwnd] + call [ecx+PluginWindowProc] + mov [result], eax + mov [esp_out], esp + cmp esp, [esp_in] ; check it + jz lbl_stack_fix_end + pop ecx ; fix stack + pop ecx + pop ecx + pop ecx +lbl_stack_fix_end: ; end of stack fix hack + mov [esp_fixed], esp + pop ecx + } + +#ifndef POPUP_NO_STACK_WARNING + if (esp_in != esp_out) + { + HANDLE hBadModule = 0; + char szBadModule[64] = {0}; + + // plugin enumeration from the core + char exe[MAX_PATH]; + char search[MAX_PATH]; + char *p = 0; + // get miranda's exe path + GetModuleFileNameA(NULL, exe, SIZEOF(exe)); + // find the last \ and null it out, this leaves no trailing slash + p = strrchr(exe, '\\'); + if ( p ) *p=0; + // create the search filter + mir_snprintf(search,SIZEOF(search),"%s\\Plugins\\*.dll", exe); + { + // FFFN will return filenames for things like dot dll+ or dot dllx + HANDLE hFind=INVALID_HANDLE_VALUE; + WIN32_FIND_DATAA ffd; + hFind = FindFirstFileA(search, &ffd); + if ( hFind != INVALID_HANDLE_VALUE ) + { + do + { + if ( !(ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) ) + { + HMODULE hModule = GetModuleHandleA(ffd.cFileName); + if (((char *)PluginWindowProc > (char *)hModule) && + (((char *)PluginWindowProc - (char *)hModule) < ((char *)PluginWindowProc - (char *)hBadModule))) + { + hBadModule = hModule; + lstrcpynA(szBadModule, ffd.cFileName, sizeof(szBadModule)); + } + } + } while ( FindNextFileA(hFind, &ffd) ); + FindClose(hFind); + } + } + +#ifdef POPUP_STACK_WARNING_MSGBOX + char buf[256]; + mir_snprintf(buf, sizeof(buf), + "Some plugin passed callback with invalid calling\r\n" + "convention and caused stack corruption\r\n" + "Module name: %s\r\n" + "PluginWindowProc: %x\r\n" + "ESP Before: %d\r\n" + "ESP After: %d\r\n" + "ESP Fixed: %d", + szBadModule, + PluginWindowProc, + esp_in, esp_out, esp_fixed); + + MessageBox(NULL, buf, _T("Popup Plus stack check"), MB_ICONSTOP|MB_OK); +#else + strcat(exe, "\\popup_stack.log"); + FILE *f = fopen(exe,"a"); + fprintf(f, + "Module name: %s; PluginWindowProc: 0x%x; ESP Before: %d; ESP After: %d; ESP Fixed: %d\n", + szBadModule, + PluginWindowProc, + esp_in, esp_out, esp_fixed); + fclose(f); +#endif // _DEBUG + } +#endif // POPUP_NO_STACK_WARNING +*/ + unlock(); + return result; + } + + return NullWindowProc(this->m_hwnd, message, wParam, lParam); +} + +LRESULT CALLBACK PopupWnd2::WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PopupWnd2 *wnd = 0; + if (message == WM_CREATE) + { + LPCREATESTRUCT cs = (LPCREATESTRUCT)lParam; + wnd = (PopupWnd2 *)cs->lpCreateParams; + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wnd); + } else + { + wnd = (PopupWnd2 *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + } + if (wnd) return wnd->WindowProc(message, wParam, lParam); + return DefWindowProc(hwnd, message, wParam, lParam); +} + +void WindowThread(void *arg) +{ + CallService(MS_SYSTEM_THREAD_PUSH, 0, 0); + OleInitialize(NULL); // we may need OLE in this thread for smiley substitution + + PopupWnd2 *wnd = (PopupWnd2 *)arg; + wnd->buildMText(); + wnd->create(); + PostMessage(wnd->getHwnd(), UM_INITPOPUP, 0, 0); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + CallService(MS_SYSTEM_THREAD_POP, 0, 0); + _endthread(); +} + +// Menu Host +LRESULT CALLBACK MenuHostWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hContact = NULL; + + switch (message) + { + case UM_SHOWMENU: + { + hContact = (HANDLE)lParam; + POINT pt = {0}; + HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,(WPARAM)hContact,0); + GetCursorPos(&pt); + HWND hwndSave = GetForegroundWindow(); + SetForegroundWindow(hwnd); + TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwnd, NULL); + SetForegroundWindow(hwndSave); + DestroyMenu(hMenu); + PostMessage((HWND)wParam, UM_MENUDONE, 0, 0); + break; + } + + case WM_COMMAND: + { + // do not call PluginWindowProc if menu item was clicked. prevent auto-closing... + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)hContact)) + return DefWindowProc(hwnd, message, wParam, lParam); + break; + } + + case WM_MEASUREITEM: + return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); + + case WM_DRAWITEM: + return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} diff --git a/Popup/src/popup_wnd2.h b/Popup/src/popup_wnd2.h new file mode 100644 index 0000000..8c5fd96 --- /dev/null +++ b/Popup/src/popup_wnd2.h @@ -0,0 +1,273 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/popup_wnd2.h $ +Revision : $Revision: 1620 $ +Last change on : $Date: 2010-06-23 21:31:05 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __popup_wnd2_h__ +#define __popup_wnd2_h__ + +#define UM_CALLMETHOD (WM_USER+2048) + +class PopupAvatar; + +#define POPUP_OBJECT_SIGNARURE 0x0B1A11BE + +class PopupWnd2 +{ +public: + typedef LRESULT (PopupWnd2::*MethodPtr)(LPARAM lParam); + enum TextType {TT_NONE, TT_ANSI, TT_UNICODE, TT_MTEXT}; + + struct ActionInfo + { + POPUPACTION actionA; + RECT rc; + bool hover; + + ActionInfo(): hover(false) {} + }; + + DWORD m_signature; + +private: + // style + COLORREF m_clBack, m_clText, m_clTitle, m_clClock; + int m_iTimeout; + + // content + TextType m_textType; + char *m_lpzTitle, *m_lpzText; + WCHAR *m_lpwzTitle, *m_lpwzText; + HANDLE m_mtTitle, m_mtText; + bool m_bTextEmpty; + HFONT m_hfnTitle, m_hfnText; + HICON m_hIcon; + HBITMAP m_hbmAvatar; + char m_time[2+1+2+1]; + ActionInfo* m_actions; + int m_actionCount; + HANDLE m_hNotification; + + // other data + Formula::Args m_args; + HANDLE m_hContact, m_hContactPassed; + WNDPROC m_PluginWindowProc; + void *m_PluginData; + + // the window + LPTSTR m_lpzSkin; + bool m_customPopup; + HWND m_hwnd, m_hwndToolTip; + bool m_bPositioned; + POINT m_pos; + SIZE m_sz; + MyBitmap *m_bmpBase, *m_bmp, *m_bmpAnimate; + PopupAvatar *m_avatar; + int m_avatarFrameDelay; + bool m_bReshapeWindow; + HANDLE m_hhkAvatarChanged; + bool m_bIsPinned; + + // show & hide +// bool m_bIdleRequested; + bool m_bFade; +// DWORD m_dwTmFade0, m_dwTmFade1; + BYTE m_btAlpha0, m_btAlpha1; + bool m_bSlide; +// DWORD m_dwTmSlide0, m_dwTmSlide1; + POINT m_ptPosition0, m_ptPosition1; + bool m_bDestroy; + bool m_bIsHovered; + + // prevent unwanted clicks + POINT m_ptPrevCursor; + + // system + POPUPOPTIONS *m_options; + DWORD m_lockCount; + + PopupSkin::RenderInfo m_renderInfo; + + void fixDefaults(); + void fixAvatar(); + int fixActions(POPUPACTION *theActions, int count); + int fixActions(POPUPACTION *theActions, int count, int additional); + +public: +// PopupWnd2(POPUPDATA *ppd, POPUPOPTIONS *theCustomOptions=NULL, bool renderOnly=false); +// PopupWnd2(POPUPDATAEX_V2 *ppd, POPUPOPTIONS *theCustomOptions=NULL, bool renderOnly=false); +// PopupWnd2(POPUPDATAW_V2 *ppd, POPUPOPTIONS *theCustomOptions=NULL, bool renderOnly=false); + PopupWnd2(POPUPDATA2 *ppd, POPUPOPTIONS *theCustomOptions=NULL, bool renderOnly=false); +// PopupWnd2(HANDLE hNtf, POPUPOPTIONS *theCustomOptions=NULL, bool renderOnly=false); + ~PopupWnd2(); + + void startThread(); + + void create(); + void updateLayered(BYTE opacity); + SIZE measure(); + void update(); + void animate(); + + void show(); + void hide(); + void idle(); + + DWORD lock() { return ++m_lockCount; } + DWORD unlock() { return m_lockCount = m_lockCount ? m_lockCount-1 : 0; } + bool isLocked() { return m_lockCount != 0; } + + void updateData(POPUPDATA *ppd); + void updateData(POPUPDATAEX_V2 *ppd); + void updateData(POPUPDATAW_V2 *ppd); + void updateData(POPUPDATA2 *ppd); +// void updateData(HANDLE hNtf); + void buildMText(); + void updateText(char *text); + void updateText(WCHAR *text); + void updateTitle(char *title); + void updateTitle(WCHAR *title); + + void updateTimer(); + + MyBitmap *getContent() { return m_bmp; } + + COLORREF getTextColor() { return m_clText; } + COLORREF getTitleColor() { return m_clTitle; } + COLORREF getClockColor() { return m_clClock; } + COLORREF getBackColor() { return m_clBack; } + + bool isTextEmpty() { return m_bTextEmpty; } + TextType getTextType() { return m_textType; } + char *getTextA() { return m_lpzText; } + WCHAR *getTextW() { return m_lpwzText; } + HANDLE getTextM() { return m_mtText; } + char *getTitleA() { return m_lpzTitle; } + WCHAR *getTitleW() { return m_lpwzTitle; } + HANDLE getTitleM() { return m_mtTitle; } + + int getActionCount() { return m_actionCount; } + ActionInfo *getActions() { return m_actions; } + + char *getTime() { return m_time; } + HICON getIcon() { return m_hIcon; } + HANDLE getContact() { return m_hContact; } + HANDLE getContactPassed() { return m_hContactPassed; } + int getTimeout() { return m_iTimeout; } +// HBITMAP getAvatar() { return hbmAvatar; } + PopupAvatar *getAvatar() { return m_avatar; } + HWND getHwnd() { return m_hwnd; } + void *getData() { return m_PluginData; } + + Formula::Args *getArgs() { return &m_args; } + PopupSkin::RenderInfo *getRenderInfo() { return &m_renderInfo; } + + SIZE getSize() { return m_sz; } + void setSize(SIZE sz) + { + this->m_sz = sz; + if (m_hwnd) + { + SetWindowPos(m_hwnd, 0, 0, 0, sz.cx, sz.cy, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING); + if (!m_customPopup) + PopupThreadUpdateWindow(this); + } + } + bool isPositioned() { return m_bPositioned; } + POINT getPosition() { return m_pos; } + POINT getRealPosition() { return POINT(); } + void setPosition(POINT pt) + { + m_bPositioned = true; + m_pos = pt; + if (m_bSlide) + { + m_ptPosition1 = pt; + } else + { + SetWindowPos(m_hwnd, 0, pt.x, pt.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING); + } + } + + // Thread-related methods + void callMethodAsync(MethodPtr method, LPARAM lParam) + { + // we can't pass MethodPtr via WPARAM because it's size can differ! well, it's still 4 bytes on msvc but + // on gcc we will get 8 bytes... + MethodPtr *method_copy = new MethodPtr; *method_copy = method; + PostMessage(m_hwnd, UM_CALLMETHOD, (WPARAM)method_copy, (LPARAM)lParam); + } + void callMethodSync(MethodPtr method, LPARAM lParam) + { + // we can't pass MethodPtr via WPARAM because it's size can differ! well, it's still 4 bytes on msvc but + // on gcc we will get 8 bytes... + MethodPtr *method_copy = new MethodPtr; *method_copy = method; + SendMessage(m_hwnd, UM_CALLMETHOD, (WPARAM)method_copy, (LPARAM)lParam); + } + + LRESULT m_updateData_POPUPDATA(LPARAM arg) { updateData((POPUPDATA *)arg); update(); return 0; } + LRESULT m_updateData_POPUPDATAEX_V2(LPARAM arg) { updateData((POPUPDATAEX_V2 *)arg); update(); return 0; } + LRESULT m_updateData_POPUPDATAW_V2(LPARAM arg) { updateData((POPUPDATAW_V2 *)arg); update(); return 0; } + LRESULT m_updateData_POPUPDATA2(LPARAM arg) { updateData((POPUPDATA2 *)arg); update(); return 0; } +// LRESULT m_updateData_HNOTIFY(LPARAM arg) { updateData((HANDLE)arg); update(); return 0; } + LRESULT m_updateText(LPARAM arg) { updateText((char *)arg); update(); return 0; } + LRESULT m_updateTextW(LPARAM arg) { updateText((WCHAR *)arg); update(); return 0; } + LRESULT m_updateTitle(LPARAM arg) { updateTitle((char *)arg); update(); return 0; } + LRESULT m_updateTitleW(LPARAM arg) { updateTitle((WCHAR *)arg); update(); return 0; } + LRESULT m_show(LPARAM arg) { show(); return 0; } + LRESULT m_hide(LPARAM arg) { hide(); return 0; } + + // window related stuff + LRESULT CALLBACK WindowProc(UINT, WPARAM, LPARAM); + static LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); + + // window creation flag + volatile bool m_bWindowCreated; +}; + +bool LoadPopupWnd2(); +void UnloadPopupWnd2(); + +static inline bool IsValidPopupObject(PopupWnd2 *wnd) +{ + bool res = false; + __try + { + if (wnd->m_signature == POPUP_OBJECT_SIGNARURE) + res = true; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + res = false; + } + return res; +} + +#endif // __popup_wnd2_h__ diff --git a/Popup/src/services.cpp b/Popup/src/services.cpp new file mode 100644 index 0000000..48f1919 --- /dev/null +++ b/Popup/src/services.cpp @@ -0,0 +1,675 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/services.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +int num_classes = 0; //for core class api support + +// isWorkstationLocked() code from core +bool isWorkstationLocked() +{ + bool rc = false; + + if (OpenInputDesktop != NULL) { + HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); + if (hDesk == NULL) + rc = true; + else if (CloseDesktop != NULL) + CloseDesktop(hDesk); + } + return rc; +} + +// isFullScreen() code from core +static bool isFullScreen() +{ + RECT rcScreen = {0}; + + rcScreen.right = GetSystemMetrics(SM_CXSCREEN); + rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN); + + if (MonitorFromWindow != NULL) + { + HMONITOR hMon = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONEAREST); + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hMon, &mi)) + rcScreen = mi.rcMonitor; + } + + HWND hWndDesktop = GetDesktopWindow(); + HWND hWndShell = GetShellWindow(); + + // check foregroundwindow + HWND hWnd = GetForegroundWindow(); + if (hWnd && hWnd != hWndDesktop && hWnd != hWndShell) + { + TCHAR tszClassName[128] = _T(""); + GetClassName(hWnd, tszClassName, SIZEOF(tszClassName)); + if (_tcscmp(tszClassName, _T("WorkerW"))) + { + RECT rect, rectw, recti; + GetWindowRect(hWnd, &rectw); + + GetClientRect(hWnd, &rect); + ClientToScreen(hWnd, (LPPOINT)&rect); + ClientToScreen(hWnd, (LPPOINT)&rect.right); + + if (EqualRect(&rect, &rectw) && IntersectRect(&recti, &rect, &rcScreen) && + EqualRect(&recti, &rcScreen)) + return true; + } + } + + return false; +} + +//===== PopUp/AddPopUp +INT_PTR PopUp_AddPopUp(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + POPUPDATA *ppd = (POPUPDATA*)wParam; + if (!ppd) return -1; + + POPUPDATA2 ppd2 = {0}; + ppd2.cbSize = sizeof(ppd2); + ppd2.flags = PU2_ANSI; + ppd2.lchContact = ppd->lchContact; + ppd2.lchIcon = ppd->lchIcon; + ppd2.lpzTitle = ppd->lpzContactName; + ppd2.lpzText = ppd->lpzText; + ppd2.colorBack = ppd->colorBack; + ppd2.colorText = ppd->colorText; + ppd2.PluginWindowProc = ppd->PluginWindowProc; + ppd2.PluginData = ppd->PluginData; + ppd2.iSeconds = PopUpOptions.Seconds; + return PopUp_AddPopUp2((WPARAM)&ppd2, lParam); +/* + PopupWnd2 *wnd = new PopupWnd2(ppd); + + if (lParam & APF_RETURN_HWND) + { + while (!wnd->bWindowCreated) Sleep(1); + return (int)wnd->getHwnd(); + } + + return 1; +*/ +} + +//===== PopUp/AddPopUpEx +INT_PTR PopUp_AddPopUpEx(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + POPUPDATAEX_V2 *ppd = (POPUPDATAEX_V2*)wParam; + if (!ppd) return -1; + + POPUPDATA2 ppd2 = {0}; + ppd2.cbSize = sizeof(ppd2); + ppd2.flags = PU2_ANSI; + ppd2.lchContact = ppd->lchContact; + ppd2.lchIcon = ppd->lchIcon; + ppd2.lpzTitle = ppd->lpzContactName; + ppd2.lpzText = ppd->lpzText; + ppd2.colorBack = ppd->colorBack; + ppd2.colorText = ppd->colorText; + ppd2.PluginWindowProc = ppd->PluginWindowProc; + ppd2.PluginData = ppd->PluginData; + ppd2.iSeconds = ppd->iSeconds; + + if (lParam&APF_NEWDATA) + { + ppd2.lchNotification = ppd->hNotification; + ppd2.actionCount = ppd->actionCount; + ppd2.lpActions = ppd->lpActions; +// ppd2.hbmAvatar = ppd->hbmAvatar; + } + + return PopUp_AddPopUp2((WPARAM)&ppd2, lParam); + +/* + if (lParam & APF_RETURN_HWND) + { + while (!wnd->bWindowCreated) Sleep(1); + return (int)wnd->getHwnd(); + } + + return 1; +*/ +} + +//===== PopUp/AddPopupW +INT_PTR PopUp_AddPopUpW(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + POPUPDATAW_V2 *ppd = (POPUPDATAW_V2*)wParam; + if (!ppd) return -1; + + POPUPDATA2 ppd2 = {0}; + ppd2.cbSize = sizeof(ppd2); + ppd2.flags = PU2_UNICODE; + ppd2.lchContact = ppd->lchContact; + ppd2.lchIcon = ppd->lchIcon; + ppd2.lpwzTitle = ppd->lpwzContactName; + ppd2.lpwzText = ppd->lpwzText; + ppd2.colorBack = ppd->colorBack; + ppd2.colorText = ppd->colorText; + ppd2.PluginWindowProc = ppd->PluginWindowProc; + ppd2.PluginData = ppd->PluginData; + ppd2.iSeconds = ppd->iSeconds; + ppd2.lchNotification = ppd->hNotification; + + if (lParam&APF_NEWDATA) + { + ppd2.actionCount = ppd->actionCount; + ppd2.lpActions = ppd->lpActions; +// ppd2.hbmAvatar = ppd->hbmAvatar; + } + + return PopUp_AddPopUp2((WPARAM)&ppd2, lParam); + +/* + if (lParam & APF_RETURN_HWND) + { + while (!wnd->bWindowCreated) Sleep(1); + return (int)wnd->getHwnd(); + } + + return 1; +*/ +} + +//===== PopUp/AddPopup2 +static __forceinline DWORD Proto_Status2Flag_My(DWORD status) +{ + if (DWORD res = Proto_Status2Flag(status)) + return res; + return PF2_IDLE; +} + +INT_PTR PopUp_AddPopUp2(WPARAM wParam, LPARAM lParam) +{ + /* NOTE: we will return 0 instead of -1 since tabSRMM stops using popup after first failure :/ */ + + if (!gbPopupLoaded) return -1; + + POPUPDATA2 *ppdIn = (POPUPDATA2 *)wParam; + if (!ppdIn) return -1; + + POPUPDATA2 ppdFixed = {0}; + POPUPDATA2 *ppd = &ppdFixed; + CopyMemory(ppd, ppdIn, min(ppdIn->cbSize, sizeof(POPUPDATA2))); + + DWORD disableWhen; + FillNotificationData(ppd, &disableWhen); + + if (!(lParam&APF_NO_HISTORY)) + PopupHistoryAdd(ppd); + + if (PopupThreadIsFull()) + return -1; + + #ifdef _DEBUG + char temp[128]; + OutputDebugStringA("isWorkstationLocked: \t"); + OutputDebugStringA(isWorkstationLocked() ? "true":"false"); + OutputDebugStringA("\n"); + #endif + + if (isWorkstationLocked()) + return -1; + + // Check if contact handle is valid. + char *proto = NULL; + if (ppd->lchContact) + proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ppd->lchContact, 0); + + BYTE bShowMode = proto ? DBGetContactSettingByte(ppd->lchContact, MODULNAME, "ShowMode", PU_SHOWMODE_AUTO) : PU_SHOWMODE_AUTO; + + if (bShowMode == PU_SHOWMODE_BLOCK) + return -1; + + if (bShowMode != PU_SHOWMODE_FAVORITE) + { + if (!PopUpOptions.ModuleIsEnabled) + return -1; + #ifdef _DEBUG + itoa(PopUpOptions.DisableWhenFullscreen,temp,10); + OutputDebugStringA("PopUpOptions.DisableWhenFullscreen: \t"); + OutputDebugStringA(temp); + OutputDebugStringA("\n"); + itoa(bShowMode,temp,10); + OutputDebugStringA("bShowMode: \t"); + OutputDebugStringA(temp); + OutputDebugStringA("\n"); + OutputDebugStringA("isFullScreen: \t"); + OutputDebugStringA(isFullScreen() ? "true":"false"); + OutputDebugStringA("\n"); + #endif + + if (PopUpOptions.DisableWhenFullscreen && (bShowMode != PU_SHOWMODE_FULLSCREEN) && isFullScreen()) + return -1; + + if (DBGetContactSettingDword(NULL, MODULNAME, "Global Status", 0) & + Proto_Status2Flag_My(CallService(MS_CLIST_GETSTATUSMODE, 0, 0))) + return -1; + + if ((disableWhen & 0x0000FFFF) & Proto_Status2Flag_My(CallService(MS_CLIST_GETSTATUSMODE, 0, 0))) + return -1; + + if (proto) + { + char prefix[128]; + mir_snprintf(prefix, sizeof(prefix), "Protocol Status/%s", (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ppd->lchContact, 0)); + if (DBGetContactSettingDword(NULL, MODULNAME, prefix, 0) & + Proto_Status2Flag_My(CallProtoService(proto, PS_GETSTATUS, 0, 0))) + return -1; + if (((disableWhen >> 16) & 0xFFFF0000) & Proto_Status2Flag_My(CallProtoService(proto, PS_GETSTATUS, 0, 0))) + return -1; + } + } + + if (lParam&APF_CUSTOM_POPUP) + ppd->flags |= PU2_CUSTOM_POPUP; + PopupWnd2 *wnd = new PopupWnd2(ppd, NULL, false); + + if (lParam & APF_RETURN_HWND) + { + while (!wnd->m_bWindowCreated) Sleep(1); + return (INT_PTR)wnd->getHwnd(); + } + + return 0; +} + +//===== PopUp/GetContact +INT_PTR PopUp_GetContact(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + HWND hwnd = (HWND)wParam; + PopupWnd2 *wnd = (PopupWnd2 *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (wnd && IsValidPopupObject(wnd)) return (INT_PTR)wnd->getContactPassed(); + return (INT_PTR)(-1); +} + +//===== PopUp/GetPluginData +INT_PTR PopUp_GetPluginData(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + HWND hwnd = (HWND)wParam; + PopupWnd2 *wnd = (PopupWnd2 *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (wnd && IsValidPopupObject(wnd)) return (INT_PTR)wnd->getData(); + return (INT_PTR)(-1); +} + +//===== PopUp/IsSecondLineShown +INT_PTR PopUp_IsSecondLineShown(WPARAM wParam, LPARAM lParam) +{ + return 1; +} + +//===== PopUp/ChangeText +INT_PTR PopUp_ChangeText(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + if (!wParam) return -1; + PopupWnd2 *wnd = (PopupWnd2 *)GetWindowLongPtr((HWND)wParam, GWLP_USERDATA); + if (!wnd || !IsValidPopupObject(wnd)) return -1; + wnd->callMethodSync(&PopupWnd2::m_updateText, lParam); +/* + char *str = (char *)mir_alloc(sizeof(char) * (strlen((char *)lParam) + 1)); + strcpy(str, (char *)lParam); + PostMessage((HWND)wParam, UM_CHANGEPOPUP, CPT_TEXT, (LPARAM)str); +*/ + return 0; +} + +//===== PopUp/ChangeTextW +INT_PTR PopUp_ChangeTextW(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + if (!wParam) return -1; + PopupWnd2 *wnd = (PopupWnd2 *)GetWindowLongPtr((HWND)wParam, GWLP_USERDATA); + if (!wnd || !IsValidPopupObject(wnd)) return -1; + wnd->callMethodSync(&PopupWnd2::m_updateTextW, lParam); +/* + WCHAR *str = (WCHAR *)mir_alloc(sizeof(WCHAR) * (wcslen((WCHAR *)lParam) + 1)); + wcscpy(str, (WCHAR *)lParam); + PostMessage((HWND)wParam, UM_CHANGEPOPUP, CPT_TEXTW, (LPARAM)str); +*/ + return 0; +} + +//===== PopUp/Change +INT_PTR PopUp_Change(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + if (!wParam) return -1; + PopupWnd2 *wnd = (PopupWnd2 *)GetWindowLongPtr((HWND)wParam, GWLP_USERDATA); + if (!wnd || !IsValidPopupObject(wnd)) return -1; + wnd->callMethodSync(&PopupWnd2::m_updateData_POPUPDATAEX_V2, lParam); +/* + POPUPDATAEX_V2 *ppdx = (POPUPDATAEX_V2 *)mir_alloc(sizeof(POPUPDATAEX_V2)); + memcpy(ppdx, (POPUPDATAEX_V2 *)lParam, sizeof(POPUPDATAEX_V2)); + PostMessage((HWND)wParam, UM_CHANGEPOPUP, CPT_DATA, (LPARAM)ppdx); +*/ + return 0; +} + +//===== PopUp/ChangeW +INT_PTR PopUp_ChangeW(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + if (!wParam) return -1; + PopupWnd2 *wnd = (PopupWnd2 *)GetWindowLongPtr((HWND)wParam, GWLP_USERDATA); + if (!wnd || !IsValidPopupObject(wnd)) return -1; + wnd->callMethodSync(&PopupWnd2::m_updateData_POPUPDATAW_V2, lParam); +/* + POPUPDATAW_V2 *ppdw = (POPUPDATAW_V2 *)mir_alloc(sizeof(POPUPDATAW_V2)); + memcpy(ppdw, (POPUPDATAW_V2 *)lParam, sizeof(POPUPDATAW_V2)); + PostMessage((HWND)wParam, UM_CHANGEPOPUP, CPT_DATA, (LPARAM)ppdw); +*/ + return 0; +} + +//===== PopUp/Change2 +INT_PTR PopUp_Change2(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + if (!wParam) return -1; + PopupWnd2 *wnd = (PopupWnd2 *)GetWindowLongPtr((HWND)wParam, GWLP_USERDATA); + if (!wnd || IsValidPopupObject(wnd)) return -1; + wnd->callMethodSync(&PopupWnd2::m_updateData_POPUPDATA2, lParam); + return 0; +} + +//===== PopUp/ShowMessage +INT_PTR PopUp_ShowMessage(WPARAM wParam, LPARAM lParam) { + if(!gbPopupLoaded || !wParam || !lParam) return -1; + if(closing) return 0; + + POPUPDATA2 ppd2 = {0}; + ppd2.cbSize = sizeof(ppd2); + ppd2.flags = PU2_ANSI; + ppd2.lpzText = (char*)wParam; + switch (lParam&0x7fffffff) { + case SM_ERROR: + ppd2.lchIcon = IcoLib_GetIcon(ICO_MISC_ERROR,0); + ppd2.colorBack = RGB(191,0,0); + ppd2.colorText = RGB(255,245,225); + ppd2.lchNotification = g_hntfError; + ppd2.lpzTitle = Translate("Error"); + break; + case SM_WARNING: + ppd2.lchIcon = IcoLib_GetIcon(ICO_MISC_WARNING,0); + ppd2.colorBack = RGB(210,210,150); + ppd2.colorText = RGB(0,0,0); + ppd2.lchNotification = g_hntfWarning; + ppd2.lpzTitle = Translate("Warning"); + break; + case SM_NOTIFY: + ppd2.lchIcon = IcoLib_GetIcon(ICO_MISC_NOTIFY,0); + ppd2.colorBack = RGB(230,230,230); + ppd2.colorText = RGB(0,0,0); + ppd2.lchNotification = g_hntfNotification; + ppd2.lpzTitle = Translate("Notify"); + break; + default: //No no no... you must give me a good value. + return -1; + } + return PopUp_AddPopUp2((WPARAM)&ppd2, (LPARAM)((lParam&0x80000000)?APF_NO_HISTORY:0)); +} + +INT_PTR PopUp_ShowMessageW(WPARAM wParam, LPARAM lParam) { + if(!gbPopupLoaded || !wParam || !lParam) return -1; + if(closing) return 0; + + POPUPDATA2 ppd2 = {0}; + ppd2.cbSize = sizeof(ppd2); + ppd2.flags = PU2_UNICODE; + ppd2.lpwzText = (WCHAR*)wParam; + switch (lParam&0x7fffffff) { + case SM_ERROR: + ppd2.lchIcon = IcoLib_GetIcon(ICO_MISC_ERROR,0); + ppd2.colorBack = RGB(191,0,0); + ppd2.colorText = RGB(255,245,225); + ppd2.lchNotification = g_hntfError; + ppd2.lpwzTitle = TranslateW(L"Error"); + break; + case SM_WARNING: + ppd2.lchIcon = IcoLib_GetIcon(ICO_MISC_WARNING,0); + ppd2.colorBack = RGB(210,210,150); + ppd2.colorText = RGB(0,0,0); + ppd2.lchNotification = g_hntfWarning; + ppd2.lpwzTitle = TranslateW(L"Warning"); + break; + case SM_NOTIFY: + ppd2.lchIcon = IcoLib_GetIcon(ICO_MISC_NOTIFY,0); + ppd2.colorBack = RGB(230,230,230); + ppd2.colorText = RGB(0,0,0); + ppd2.lchNotification = g_hntfNotification; + ppd2.lpwzTitle = TranslateW(L"Notify"); + break; + default: //No no no... you must give me a good value. + return -1; + } + return PopUp_AddPopUp2((WPARAM)&ppd2, (LPARAM)((lParam&0x80000000)?APF_NO_HISTORY:0)); +} + +//===== PopUp/Query +INT_PTR PopUp_Query(WPARAM wParam, LPARAM lParam) +{ + if (!gbPopupLoaded) return -1; + + if (closing) + return 0; + + switch (wParam) { + case PUQS_ENABLEPOPUPS: { + if (PopUpOptions.ModuleIsEnabled) return 1; //They're already ON!!! + else { //Module was disabled. + svcEnableDisableMenuCommand(0,0); + return 0; + } + } + case PUQS_DISABLEPOPUPS: { + if (!(PopUpOptions.ModuleIsEnabled)) return 1; //They're already OFF!!! + else { + svcEnableDisableMenuCommand(0,0); + return 0; + } + } + case PUQS_GETSTATUS: + return (PopUpOptions.ModuleIsEnabled); + default: + return -1; + } + return 0; +} + + +//===== PopUp/RegisterActions +INT_PTR PopUp_RegisterActions(WPARAM wParam, LPARAM lParam) +{ + LPPOPUPACTION actions = (LPPOPUPACTION)wParam; + for (int i = 0; i < lParam; ++i) + RegisterAction(&actions[i]); + return 0; +} + + +INT_PTR PopUp_RegisterNotification(WPARAM wParam, LPARAM lParam) +{ + return (INT_PTR)RegisterNotification((LPPOPUPNOTIFICATION)wParam); +} + + +//===== PopUp/UnhookEventAsync +struct SafeUnhookEventParam +{ + HWND hwndPopup; + HANDLE hEvent; +}; + +static void CALLBACK SafeUnhookEventFunc(ULONG_PTR dwParam) +{ + UnhookEvent(((SafeUnhookEventParam *)dwParam)->hEvent); + PostMessage(((SafeUnhookEventParam *)dwParam)->hwndPopup, UM_POPUPUNHOOKCOMPLETE, 0, + (LPARAM)((SafeUnhookEventParam *)dwParam)->hEvent); + delete (SafeUnhookEventParam *)dwParam; +} + +INT_PTR PopUp_UnhookEventAsync(WPARAM wParam, LPARAM lParam) +{ + SafeUnhookEventParam *param = new SafeUnhookEventParam; + param->hwndPopup = (HWND)wParam; + param->hEvent = (HANDLE)lParam; + QueueUserAPC(SafeUnhookEventFunc, hMainThread, (ULONG_PTR)param); + return 0; +} + +//===== PopUp/RegisterVfx (effekt name for drop down box) +INT_PTR PopUp_RegisterVfx(WPARAM wParam, LPARAM lParam) +{ + OptAdv_RegisterVfx((char *)lParam); + return 0; +} + +//===== PopUp/RegisterClass (for core class api support) +INT_PTR PopUp_RegisterPopupClass(WPARAM wParam, LPARAM lParam) { + char setting[256]; + POPUPCLASS *pc = (POPUPCLASS *)lParam; + POPUPTREEDATA *ptd = (POPUPTREEDATA *)mir_alloc(sizeof(POPUPTREEDATA)); + memset(ptd,0,sizeof(POPUPTREEDATA)); + ptd->cbSize = sizeof(POPUPTREEDATA); + ptd->signature = 0/*PopupNotificationData_SIGNATURE*/; + ptd->typ = 2; + memcpy(&ptd->pupClass, pc, sizeof(POPUPCLASS)); + ptd->pszTreeRoot = mir_a2t(pc->pszName); + ptd->pupClass.pszName = mir_strdup(pc->pszName); + if(pc->flags & PCF_UNICODE) { + ptd->pupClass.pwszDescription = mir_wstrdup(pc->pwszDescription); + ptd->pszDescription = mir_u2t(pc->pwszDescription); + } + else { + ptd->pupClass.pszDescription = mir_strdup (pc->pszDescription); + ptd->pszDescription = mir_a2t(pc->pszDescription); + } + LoadClassSettings(ptd, PU_MODULCLASS); + + //we ignore pc->colorText and use fonts.text as default (if no setting found in DB) + mir_snprintf(setting, 256, "%s/TextCol", ptd->pupClass.pszName); + ptd->pupClass.colorText = (COLORREF)DBGetContactSettingDword(NULL, PU_MODULCLASS, setting, fonts.clText/*pc->colorText*/); + FontID fid = {0}; + fid.cbSize = sizeof(FontID); + mir_snprintf(fid.group, sizeof(fid.group), "%s/%s", PU_FNT_AND_COLOR, ptd->pupClass.pszName); + strcpy(fid.dbSettingsGroup, PU_MODULCLASS); + fid.flags = FIDF_DEFAULTVALID; + fid.deffontsettings.charset = DEFAULT_CHARSET; + fid.deffontsettings.size = -11; + strcpy(fid.deffontsettings.szFace, "Verdana"); + strcpy(fid.name, PU_FNT_NAME_TEXT); + strcpy(fid.prefix, setting); + mir_snprintf(fid.prefix, sizeof(fid.prefix), "%s/Text", ptd->pupClass.pszName); // result is "%s/TextCol" + fid.deffontsettings.style = 0; + fid.deffontsettings.colour = fonts.clText; + CallService(MS_FONT_REGISTER, (WPARAM)&fid, 0); + + //we ignore pc->colorBack and use fonts.clBack as default (if no setting found in DB) + mir_snprintf(setting, 256, "%s/BgCol", ptd->pupClass.pszName); + ptd->pupClass.colorBack = (COLORREF)DBGetContactSettingDword(NULL, PU_MODULCLASS, setting, (DWORD)fonts.clBack/*pc->colorBack*/); + ColourID cid = {0}; + cid.cbSize = sizeof(ColourID); + mir_snprintf(cid.group, sizeof(cid.group), "%s/%s", PU_FNT_AND_COLOR, ptd->pupClass.pszName); + strcpy(cid.dbSettingsGroup, PU_MODULCLASS); + strcpy(cid.name, PU_COL_BACK_NAME); + mir_snprintf(cid.setting, sizeof(cid.setting), "%s/BgCol", ptd->pupClass.pszName); + cid.defcolour = fonts.clBack; + CallService(MS_COLOUR_REGISTER, (WPARAM)&cid, 0); + + gTreeData.insert(ptd); + num_classes++; + + return 0; +} + +//===== PopUp/AddPopupClass (for core class api support) +INT_PTR PopUp_CreateClassPopup(WPARAM wParam, LPARAM lParam) { + int ret = 1; + POPUPDATACLASS *pdc = (POPUPDATACLASS *)lParam; + if(pdc->cbSize != sizeof(POPUPDATACLASS)) return ret; + + POPUPCLASS *pc = NULL; + POPUPTREEDATA *ptd = NULL; + + if(wParam) pc = (POPUPCLASS *)wParam; + else { + LPTSTR group = mir_a2t(pdc->pszClassName); + ptd = (POPUPTREEDATA *)FindTreeData(group, NULL, 2); + if(ptd) pc = &ptd->pupClass; + } + if(pc) { + POPUPDATA2 ppd2 = {0}; + ppd2.cbSize = sizeof(POPUPDATA2); + ppd2.colorBack = pc->colorBack; + ppd2.colorText = pc->colorText; + ppd2.lchIcon = pc->hIcon; + ppd2.iSeconds = pc->iSeconds; + ppd2.PluginWindowProc = pc->PluginWindowProc; + if(pc->flags & PCF_UNICODE) { + ppd2.flags = PU2_UNICODE; + ppd2.lpwzTitle = (WCHAR*)pdc->pwszTitle; + ppd2.lpwzText = (WCHAR*)pdc->pwszText; + } + else { + ppd2.flags = PU2_ANSI; + ppd2.lpzTitle = (char *)pdc->pszTitle; + ppd2.lpzText = (char *)pdc->pszText; + } + ppd2.lchContact = pdc->hContact; + ppd2.PluginData = pdc->PluginData; + + ret = PopUp_AddPopUp2((WPARAM)&ppd2, 0); + } + return ret!=0 ? 1 : 0; +} + diff --git a/Popup/src/services.h b/Popup/src/services.h new file mode 100644 index 0000000..462d203 --- /dev/null +++ b/Popup/src/services.h @@ -0,0 +1,67 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/services.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __services_h__ +#define __services_h__ + +extern int num_classes; //for core class api support + +INT_PTR PopUp_AddPopUp(WPARAM, LPARAM); +INT_PTR PopUp_AddPopUpW(WPARAM, LPARAM); + +INT_PTR PopUp_AddPopUpEx(WPARAM, LPARAM); +INT_PTR PopUp_AddPopUp2(WPARAM, LPARAM); + +INT_PTR PopUp_GetContact(WPARAM, LPARAM); +INT_PTR PopUp_IsSecondLineShown(WPARAM, LPARAM); + +INT_PTR PopUp_ChangeText(WPARAM, LPARAM); +INT_PTR PopUp_ChangeTextW(WPARAM, LPARAM); + +INT_PTR PopUp_Change(WPARAM, LPARAM); +INT_PTR PopUp_ChangeW(WPARAM, LPARAM); +INT_PTR PopUp_Change2(WPARAM, LPARAM); + +INT_PTR PopUp_ShowMessage(WPARAM, LPARAM); +INT_PTR PopUp_ShowMessageW(WPARAM, LPARAM); + +INT_PTR PopUp_Query(WPARAM, LPARAM); +INT_PTR PopUp_GetPluginData(WPARAM, LPARAM); +INT_PTR PopUp_RegisterActions(WPARAM wParam, LPARAM lParam); +INT_PTR PopUp_RegisterNotification(WPARAM wParam, LPARAM lParam); +INT_PTR PopUp_UnhookEventAsync(WPARAM wParam, LPARAM lParam); +INT_PTR PopUp_RegisterVfx(WPARAM wParam, LPARAM lParam); + +INT_PTR PopUp_RegisterPopupClass(WPARAM wParam, LPARAM lParam); +INT_PTR PopUp_CreateClassPopup(WPARAM wParam, LPARAM lParam); + +#endif // __services_h__ diff --git a/Popup/src/skin.cpp b/Popup/src/skin.cpp new file mode 100644 index 0000000..d3847f6 --- /dev/null +++ b/Popup/src/skin.cpp @@ -0,0 +1,1518 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/skin.cpp $ +Revision : $Revision: 1651 $ +Last change on : $Date: 2010-07-15 20:31:06 +0300 (Чт, 15 июл 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +#include +#include +#include + +// PopupSkin +PopupSkin::PopupSkin(LPCTSTR aName) +{ + for (int i = 0; i < 32; i++) + m_flag_names[i] = NULL; + m_elements = 0; + m_name = aName ? mir_tstrdup(aName) : NULL; +} + +PopupSkin::~PopupSkin() +{ + if (m_name) mir_free(m_name); + for (int i = 0; i < 32; i++) + mir_free(m_flag_names[i]); + freeSkin(m_elements); +} + +SIZE PopupSkin::measureAction(HDC hdc, POPUPACTION *act) const +{ + SIZE sz = {0}; + if (!(PopUpOptions.actions&ACT_ENABLE)) + return sz; + + if (PopUpOptions.actions&ACT_LARGE) + { + sz.cx = sz.cy = 32; + } else + { + sz.cx = sz.cy = 16; + } + + if (PopUpOptions.actions&ACT_TEXT) + { + char *name = strchr(act->lpzTitle, '/'); + if (!name) name = act->lpzTitle; + else ++name; + + SIZE szText, szSpace; + +#if defined(_UNICODE) + LPWSTR wname = mir_a2u(name); + WCHAR *str = TranslateW(wname); + GetTextExtentPoint32W(hdc, str, lstrlenW(str), &szText); + mir_free(wname); + GetTextExtentPoint32W(hdc, L" ", 1, &szSpace); +#else + if (g_popup.isOsUnicode && MyGetTextExtentPoint32W) { + LPWSTR wname = mir_a2u(name); + WCHAR *str = TranslateW(wname); + MyGetTextExtentPoint32W(hdc, str, lstrlenW(str), &szText); + mir_free(wname); + } + else { + char *str = Translate(name); + GetTextExtentPoint32A(hdc, str, lstrlenA(str), &szText); + } + GetTextExtentPoint32A(hdc, " ", 1, &szSpace); +#endif + sz.cy = max(sz.cy, szText.cy); + sz.cx += szSpace.cx; + sz.cx += szText.cx; + sz.cy += 2; + } else + { + sz.cx += 4; + sz.cy += 4; + } + + return sz; +} + +SIZE PopupSkin::measureActionBar(HDC hdc, PopupWnd2 *wnd) const +{ + SIZE sz = {0}; + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.action); + for (int i = 0; i < wnd->getActionCount(); ++i) + { + SIZE szAction = measureAction(hdc, &wnd->getActions()[i].actionA); + + if (PopUpOptions.actions & ACT_TEXT) + { + sz.cx = max(sz.cx, szAction.cx); + sz.cy += szAction.cy; + } else + { + sz.cx += szAction.cx; + sz.cy = max(sz.cy, szAction.cy); + } + } + SelectObject(hdc, hFntSave); + return sz; +} + +void PopupSkin::drawAction(MyBitmap *bmp, POPUPACTION *act, int x, int y, bool hover) const +{ + if (!(PopUpOptions.actions&ACT_ENABLE)) + return; + + bmp->DrawIcon(act->lchIcon, + (PopUpOptions.actions&ACT_TEXT) ? x : (x+2), + y+2, + (PopUpOptions.actions&ACT_LARGE) ? 32 : 16, + (PopUpOptions.actions&ACT_LARGE) ? 32 : 16); + + if (PopUpOptions.actions&ACT_TEXT) + { + char *name = strchr(act->lpzTitle, '/'); + if (!name) name = act->lpzTitle; + else ++name; + + SIZE szText, szSpace; + + HFONT hFntSave = (HFONT)SelectObject(bmp->getDC(), hover ? fonts.actionHover : fonts.action); + SetTextColor(bmp->getDC(), hover ? fonts.clActionHover : fonts.clAction); + SetBkMode(bmp->getDC(), TRANSPARENT); + + GetTextExtentPoint32A(bmp->getDC(), " ", 1, &szSpace); + +#if defined(_UNICODE) + LPWSTR wname = mir_a2u(name); + WCHAR *str = TranslateW(wname); + GetTextExtentPoint32W(bmp->getDC(), str, lstrlenW(str), &szText); + bmp->Draw_TextW(str, + (PopUpOptions.actions&ACT_LARGE) ? (x+szSpace.cx+32) : (x+szSpace.cx+16), + max( + y+2, + y+2 + (((PopUpOptions.actions&ACT_LARGE) ? 32 : 16) - szText.cy)/2 + )); + mir_free(wname); +#else + if (g_popup.isOsUnicode && MyGetTextExtentPoint32W) + { + LPWSTR wname = mir_a2u(name); + WCHAR *str = TranslateW(wname); + MyGetTextExtentPoint32W(bmp->getDC(), str, lstrlenW(str), &szText); + bmp->Draw_TextW(str, + (PopUpOptions.actions&ACT_LARGE) ? (x+szSpace.cx+32) : (x+szSpace.cx+16), + max( + y+2, + y+2 + (((PopUpOptions.actions&ACT_LARGE) ? 32 : 16) - szText.cy)/2 + )); + mir_free(wname); + } + else { + char *str = Translate(name); + GetTextExtentPoint32A(bmp->getDC(), str, lstrlenA(str), &szText); + bmp->Draw_TextA(str, + (PopUpOptions.actions&ACT_LARGE) ? (x+szSpace.cx+32) : (x+szSpace.cx+16), + max( + y+2, + y+2 + (((PopUpOptions.actions&ACT_LARGE) ? 32 : 16) - szText.cy)/2 + )); + } +#endif + SelectObject(bmp->getDC(), hFntSave); + } + else { + if (hover) + { + RECT rc; + rc.left = x; + rc.top = y; + rc.right = x + ((PopUpOptions.actions&ACT_LARGE) ? 32 : 16) + 4; + rc.bottom = y + ((PopUpOptions.actions&ACT_LARGE) ? 32 : 16) + 4; + bmp->saveAlpha(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + HBRUSH hbr = CreateSolidBrush(fonts.clActionHover); + FrameRect(bmp->getDC(), &rc, hbr); + DeleteObject(hbr); + bmp->restoreAlpha(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + } + } +} + +void PopupSkin::drawActionBar(MyBitmap *bmp, PopupWnd2 *wnd, int x, int y) const +{ + for (int i = 0; i < wnd->getActionCount(); ++i) + { + SIZE szAction = measureAction(bmp->getDC(), &wnd->getActions()[i].actionA); + drawAction(bmp, &wnd->getActions()[i].actionA, x, y, wnd->getActions()[i].hover); + + wnd->getActions()[i].rc.left = x; + wnd->getActions()[i].rc.top = y; + wnd->getActions()[i].rc.right = x + szAction.cx; + wnd->getActions()[i].rc.bottom = y + szAction.cy; + + if (PopUpOptions.actions & ACT_TEXT) + { + y += szAction.cy; + } else + { + x += szAction.cx; + } + } +} + +void PopupSkin::measure(HDC hdc, PopupWnd2 *wnd, int maxw, POPUPOPTIONS *options) const +{ + if (!m_elements) return; + + SKINELEMENT *head = NULL; + + int STYLE_SZ_CLOCK = 0; + if (!this->useInternalClock()) + for (head = m_elements; head; head = head->next) + if ((head->type&ST_TYPEMASK) == ST_CLOCK) + break; + if (head && head->myBmp) + {//layerd clock + SIZE szNew; + szNew.cx = head->clocksize[CLOCK_LEFT]+head->clocksize[CLOCK_RIGHT]; + szNew.cy = head->myBmp->getHeight(); + for (char *p = wnd->getTime(); *p; p++) + { + if (*p == ':') + { + szNew.cx += head->clocksize[CLOCK_SEPARATOR]; + } else + if ((*p >= '0') && (*p <= '9')) + { + szNew.cx += head->clocksize[CLOCK_DIGITS+*p-'0']; + } + } + wnd->getArgs()->add("clock.width",szNew.cx); + wnd->getArgs()->add("clock.height",szNew.cy); + STYLE_SZ_CLOCK = szNew.cx; + } else + {//normal clock + HFONT hfnSave = (HFONT)SelectObject(hdc, fonts.clock); + SIZE sz; GetTextExtentPoint32A(hdc, wnd->getTime(), lstrlenA(wnd->getTime()), &sz); + SelectObject(hdc, hfnSave); + wnd->getArgs()->add("clock.width",sz.cx+2*STYLE_SZ_GAP); + wnd->getArgs()->add("clock.height",sz.cy); + STYLE_SZ_CLOCK = sz.cx+2*STYLE_SZ_GAP; + } + + wnd->getArgs()->clear(); + wnd->getArgs()->add("options.avatarsize", PopUpOptions.avatarSize); + wnd->getArgs()->add("window.width", maxw); + wnd->getArgs()->add("window.maxwidth", maxw); + + for (int i = 0; i < 32; ++i) + { + char buf[10]; + wsprintfA(buf, "opt%d", i); + wnd->getArgs()->add(buf, (m_flags&(1L<flag_mask) != (head->flags & head->flag_mask)) + { + head = head->next; + continue; + } + + SIZE szNew = {0,0}; + switch (head->type & ST_TYPEMASK) + { + case ST_TEXT: + { + int tmp = head->fw.eval(wnd->getArgs()); + // this is used to measure and layout text + wnd->getRenderInfo()->textw = tmp ? tmp : (maxw - head->fx.eval(wnd->getArgs())); + szNew.cx = wnd->getRenderInfo()->textw; + if (wnd->isTextEmpty()) + { + szNew.cx = szNew.cy = 0; + } else + { + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.text); + switch (wnd->getTextType()) + { + case PopupWnd2::TT_ANSI: + { + RECT rc; SetRect(&rc, 0, 0, szNew.cx, 0); + DrawTextExA(hdc, wnd->getTextA(), lstrlenA(wnd->getTextA()), &rc, + DT_CALCRECT|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + szNew.cx = rc.right; + szNew.cy = rc.bottom; + break; + } + case PopupWnd2::TT_UNICODE: + { +#if defined(_UNICODE) + RECT rc; SetRect(&rc, 0, 0, szNew.cx, 0); + DrawTextExW(hdc, wnd->getTextW(), lstrlenW(wnd->getTextW()), &rc, + DT_CALCRECT|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + szNew.cx = rc.right; + szNew.cy = rc.bottom; +#else + if (g_popup.isOsUnicode && MyDrawTextExW) + { + RECT rc; SetRect(&rc, 0, 0, szNew.cx, 0); + MyDrawTextExW(hdc, wnd->getTextW(), lstrlenW(wnd->getTextW()), &rc, + DT_CALCRECT|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + szNew.cx = rc.right; + szNew.cy = rc.bottom; + } +#endif + break; + } + case PopupWnd2::TT_MTEXT: + { + MText.Measure(hdc, &szNew, wnd->getTextM()); + break; + } + } + SelectObject(hdc, hFntSave); + } + + wnd->getRenderInfo()->texth = szNew.cy; + + SIZE szActions = measureActionBar(hdc, wnd); + wnd->getRenderInfo()->actw = szActions.cx; + if (szActions.cy) + { + szNew.cx = max(szNew.cx, szActions.cx); + szNew.cy += szActions.cy; + szNew.cy += 3; + } + + wnd->getRenderInfo()->realtextw = szNew.cx; + + if (szNew.cx > maxw - head->fx.eval(wnd->getArgs())) + szNew.cx = maxw - head->fx.eval(wnd->getArgs()); + wnd->getArgs()->add("text.width", szNew.cx); + wnd->getArgs()->add("text.height", szNew.cy); + + break; + } + + case ST_TITLE: + { + int tmp = head->fw.eval(wnd->getArgs()); + // this is used to measure and layout text + wnd->getRenderInfo()->titlew = tmp ? tmp : (maxw - head->fx.eval(wnd->getArgs()) - STYLE_SZ_CLOCK); + szNew.cx = wnd->getRenderInfo()->titlew; + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.title); + switch (wnd->getTextType()) + { + case PopupWnd2::TT_ANSI: + { + RECT rc; SetRect(&rc, 0, 0, szNew.cx, 0); + DrawTextExA(hdc, wnd->getTitleA(), lstrlenA(wnd->getTitleA()), &rc, + DT_CALCRECT|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + szNew.cx = rc.right; + szNew.cy = rc.bottom; + break; + } + case PopupWnd2::TT_UNICODE: + { +#if defined(_UNICODE) + RECT rc; SetRect(&rc, 0, 0, szNew.cx, 0); + DrawTextExW(hdc, wnd->getTitleW(), lstrlenW(wnd->getTitleW()), &rc, + DT_CALCRECT|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + szNew.cx = rc.right; + szNew.cy = rc.bottom; +#else + if (g_popup.isOsUnicode && MyDrawTextExW) + { + RECT rc; SetRect(&rc, 0, 0, szNew.cx, 0); + MyDrawTextExW(hdc, wnd->getTitleW(), lstrlenW(wnd->getTitleW()), &rc, + DT_CALCRECT|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + szNew.cx = rc.right; + szNew.cy = rc.bottom; + } +#endif + break; + } + case PopupWnd2::TT_MTEXT: + { + MText.Measure(hdc, &szNew, wnd->getTitleM()); + break; + } + } + SelectObject(hdc, hFntSave); + if (szNew.cx > maxw - head->fx.eval(wnd->getArgs()) - STYLE_SZ_CLOCK) + szNew.cx = maxw - head->fx.eval(wnd->getArgs()) - STYLE_SZ_CLOCK; + szNew.cx += STYLE_SZ_CLOCK; + wnd->getArgs()->add("title.width", szNew.cx); + wnd->getArgs()->add("title.height", szNew.cy); + break; + } + + case ST_ICON: + szNew.cx = szNew.cy = 16; + wnd->getArgs()->add("icon.width",16); + wnd->getArgs()->add("icon.height",16); + break; + + case ST_BITMAP: +// szNew.cx = szNew.cy = 0; + GetBmpSize(head->hbm, &szNew); + break; + + case ST_MYBITMAP: + szNew.cx = head->myBmp->getWidth(); + szNew.cy = head->myBmp->getHeight(); + break; + + case ST_AVATAR: + wnd->getRenderInfo()->hasAvatar = false; + szNew.cx = szNew.cy = 0; + if (wnd->getAvatar()) + { + szNew.cx = wnd->getAvatar()->getWidth(); + szNew.cy = wnd->getAvatar()->getHeight(); + wnd->getArgs()->add("avatarbitmap.width",max(1,szNew.cx)); + wnd->getArgs()->add("avatarbitmap.height",max(1,szNew.cy)); + wnd->getRenderInfo()->hasAvatar = true; + } + break; + + case ST_CLOCK: + if (head && head->myBmp) + { + szNew.cx = head->clocksize[CLOCK_LEFT]+head->clocksize[CLOCK_RIGHT]; + szNew.cy = head->myBmp->getHeight(); + for (char *p = wnd->getTime(); *p; p++) + { + if (*p == ':') + { + szNew.cx += head->clocksize[CLOCK_SEPARATOR]; + } else + if ((*p >= '0') && (*p <= '9')) + { + szNew.cx += head->clocksize[CLOCK_DIGITS+*p-'0']; + } + } + wnd->getArgs()->add("clock.width",szNew.cx); + wnd->getArgs()->add("clock.height",szNew.cy); + } else + { + HFONT hfnSave = (HFONT)SelectObject(hdc, fonts.clock); + SIZE sz; GetTextExtentPoint32A(hdc, wnd->getTime(), lstrlenA(wnd->getTime()), &sz); + SelectObject(hdc, hfnSave); + wnd->getArgs()->add("clock.width",sz.cx+2*STYLE_SZ_GAP); + wnd->getArgs()->add("clock.height",sz.cy); + } + break; + } + + if (head->proportional && szNew.cx && szNew.cy && (((head->fw.eval(wnd->getArgs()) > 0) && !head->fh.eval(wnd->getArgs())) || (!head->fw.eval(wnd->getArgs()) && (head->fh.eval(wnd->getArgs()) > 0)))) + { + if (head->fw.eval(wnd->getArgs())) + { + szNew.cy = szNew.cy * head->fw.eval(wnd->getArgs()) / szNew.cx; + szNew.cx = head->fw.eval(wnd->getArgs()); + } else + { + szNew.cx = szNew.cx * head->fh.eval(wnd->getArgs()) / szNew.cy; + szNew.cy = head->fh.eval(wnd->getArgs()); +// szNew.cx = head->fx.eval(wnd->getArgs()) + szNew.cx * head->fh.eval(wnd->getArgs()) / szNew.cy; +// szNew.cy = head->fy.eval(wnd->getArgs()) + head->fh.eval(wnd->getArgs()); + } + } + + if ((head->type & ST_TYPEMASK) == ST_AVATAR) + { + wnd->getArgs()->add("avatar.width",szNew.cx); + wnd->getArgs()->add("avatar.height",szNew.cy); + + szNew.cy += 2; + } + + if (!head->fw.eval(wnd->getArgs())) + szNew.cx += head->fx.eval(wnd->getArgs()); + else + if (head->fw.eval(wnd->getArgs()) > 0) + szNew.cx = head->fx.eval(wnd->getArgs()) + head->fw.eval(wnd->getArgs()); + else + szNew.cx = 0; + + if (!head->fh.eval(wnd->getArgs())) + szNew.cy += head->fy.eval(wnd->getArgs()); + else + if (head->fh.eval(wnd->getArgs()) > 0) + szNew.cy = head->fy.eval(wnd->getArgs()) + head->fh.eval(wnd->getArgs()); + else + szNew.cy = 0; + + if (head->fx.eval(wnd->getArgs()) >= 0 && szNew.cx > sz.cx) sz.cx = szNew.cx; + if (head->fy.eval(wnd->getArgs()) >= 0 && szNew.cy > sz.cy) sz.cy = szNew.cy; + + head = head->next; + } +// if (pw->title_height > 20) +// sz.cy += pw->title_height - 20; + + sz.cx += m_right_gap; + sz.cy += m_bottom_gap; + + int tmp; + + if (tmp = m_fw.eval(wnd->getArgs())) sz.cx = tmp; + if (tmp = m_fh.eval(wnd->getArgs())) sz.cy = tmp; + + if (options->DynamicResize) + { + if (options->UseMinimumWidth && sz.cx < options->MinimumWidth) + sz.cx = options->MinimumWidth; + } else + { + sz.cx = options->MaximumWidth; + } + + wnd->getArgs()->add("window.width",sz.cx); + wnd->getArgs()->add("window.height",sz.cy); + wnd->setSize(sz); +} + +void PopupSkin::display(MyBitmap *bmp, PopupWnd2 *wnd, int maxw, POPUPOPTIONS *options, DWORD drawFlags) const +{ + if (!m_elements) return; + + HDC hdc = bmp->getDC(); + SKINELEMENT *head = NULL; + + int STYLE_SZ_CLOCK = 0; + if (!this->useInternalClock()) + for (head = m_elements; head; head = head->next) + if ((head->type&ST_TYPEMASK) == ST_CLOCK) + break; + if (head && head->myBmp) + { + SIZE szNew; + szNew.cx = head->clocksize[CLOCK_LEFT]+head->clocksize[CLOCK_RIGHT]; + szNew.cy = head->myBmp->getHeight(); + for (char *p = wnd->getTime(); *p; p++) + { + if (*p == ':') + { + szNew.cx += head->clocksize[CLOCK_SEPARATOR]; + } else + if ((*p >= '0') && (*p <= '9')) + { + szNew.cx += head->clocksize[CLOCK_DIGITS+*p-'0']; + } + } + STYLE_SZ_CLOCK = szNew.cx; + } else + { + HFONT hfnSave = (HFONT)SelectObject(hdc, fonts.clock); + SIZE sz; GetTextExtentPoint32A(hdc, wnd->getTime(), lstrlenA(wnd->getTime()), &sz); + SelectObject(hdc, hfnSave); + STYLE_SZ_CLOCK = sz.cx + 2*STYLE_SZ_GAP; + } + + + head = m_elements; + + SIZE sz; + SIZE szWnd = wnd->getSize(); + SIZE pos; + bool actionsRendered = false; + while (head) + { + if ((head->type&ST_TYPEMASK) == ST_AVATAR) + { + if (wnd->getAvatar()->isAnimated() && !(drawFlags&DF_ANIMATE)) + { + head = head->next; + continue; + } + if (!wnd->getAvatar()->isAnimated() && !(drawFlags&DF_STATIC)) + { + head = head->next; + continue; + } + } else + if ((head->type&ST_TYPEMASK) == ST_TEXT) + { + if (!wnd->getActionCount() && !(drawFlags&DF_STATIC)) + { + head = head->next; + continue; + } + } else + if (!(drawFlags&DF_STATIC)) + { + head = head->next; + continue; + } + + if ((head->type&ST_BADPOS) || ((m_flags & head->flag_mask) != (head->flags & head->flag_mask))) + { + head = head->next; + continue; + } + + int hShift = 0; + switch (head->type & ST_TYPEMASK) + { + case ST_TEXT: + { + if (head->textColor != (COLORREF)0xffffffff) + SetTextColor(hdc, head->textColor); + else + SetTextColor(hdc, wnd->getTextColor()); + + POINT pos; + pos.x = head->fx.eval(wnd->getArgs()); + pos.y = head->fy.eval(wnd->getArgs()); + SIZE sz; + sz.cx = wnd->getRenderInfo()->textw; + sz.cy = 1000; + + SetRect(&wnd->getRenderInfo()->textRect, pos.x, pos.y, + pos.x + wnd->getRenderInfo()->realtextw, + pos.y + wnd->getRenderInfo()->texth); + + if ((drawFlags&DF_STATIC) && !wnd->isTextEmpty()) + { + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.text); + bmp->saveAlpha(); + switch (wnd->getTextType()) + { + case PopupWnd2::TT_ANSI: + { + RECT rc; SetRect(&rc, pos.x, pos.y, pos.x+sz.cx, pos.y+sz.cy); + DrawTextExA(hdc, wnd->getTextA(), lstrlenA(wnd->getTextA()), &rc, + DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + break; + } + case PopupWnd2::TT_UNICODE: + { +#if defined(_UNICODE) + RECT rc; SetRect(&rc, pos.x, pos.y, pos.x+sz.cx, pos.y+sz.cy); + DrawTextExW(hdc, wnd->getTextW(), lstrlenW(wnd->getTextW()), &rc, + DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); +#else + if (g_popup.isOsUnicode && MyDrawTextExW) + { + RECT rc; SetRect(&rc, pos.x, pos.y, pos.x+sz.cx, pos.y+sz.cy); + MyDrawTextExW(hdc, wnd->getTextW(), lstrlenW(wnd->getTextW()), &rc, + DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + } +#endif + break; + } + case PopupWnd2::TT_MTEXT: + { + MText.Display(hdc, pos, sz, wnd->getTextM()); + break; + } + } + SelectObject(hdc, hFntSave); + bmp->restoreAlpha(); + } + + if (!actionsRendered && (drawFlags&DF_ANIMATE)) + { + int textAreaWidth = head->fw.eval(wnd->getArgs()); + if (textAreaWidth <= 0) textAreaWidth = wnd->getRenderInfo()->realtextw; + + drawActionBar(bmp, wnd, + DBGetContactSettingByte(NULL, MODULNAME, "CenterActions", 0) ? + (pos.x + (textAreaWidth - wnd->getRenderInfo()->actw)/2) : + (PopUpOptions.actions&ACT_RIGHTICONS) ? + (pos.x + textAreaWidth - wnd->getRenderInfo()->actw) : + // else + pos.x, + pos.y + wnd->getRenderInfo()->texth + 3); + + actionsRendered = true; + } + + + break; + } + + case ST_TITLE: + { + if (head->textColor != (COLORREF)0xffffffff) + SetTextColor(hdc, head->textColor); + else + SetTextColor(hdc, wnd->getTitleColor()); + + bmp->saveAlpha(); + POINT pos; + pos.x = head->fx.eval(wnd->getArgs()); + pos.y = head->fy.eval(wnd->getArgs()); + SIZE sz; + sz.cx = wnd->getRenderInfo()->titlew; + sz.cy = 1000; + + switch (wnd->getTextType()) + { + case PopupWnd2::TT_ANSI: + { + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.title); + RECT rc; SetRect(&rc, pos.x, pos.y, pos.x+sz.cx, pos.y+sz.cy); + DrawTextExA(hdc, wnd->getTitleA(), lstrlenA(wnd->getTitleA()), &rc, + DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + SelectObject(hdc, hFntSave); + break; + } + case PopupWnd2::TT_UNICODE: + { +#if defined(_UNICODE) + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.title); + RECT rc; SetRect(&rc, pos.x, pos.y, pos.x+sz.cx, pos.y+sz.cy); + DrawTextExW(hdc, wnd->getTitleW(), lstrlenW(wnd->getTitleW()), &rc, + DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + SelectObject(hdc, hFntSave); +#else + if (g_popup.isOsUnicode && MyDrawTextExW) + { + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.title); + RECT rc; SetRect(&rc, pos.x, pos.y, pos.x+sz.cx, pos.y+sz.cy); + MyDrawTextExW(hdc, wnd->getTitleW(), lstrlenW(wnd->getTitleW()), &rc, + DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK/*|DT_RTLREADING*/, NULL); + SelectObject(hdc, hFntSave); + } +#endif + break; + } + case PopupWnd2::TT_MTEXT: + { + HFONT hFntSave = (HFONT)SelectObject(hdc, fonts.title); + MText.Display(hdc, pos, sz, wnd->getTitleM()); + SelectObject(hdc, hFntSave); + break; + } + } + + bmp->restoreAlpha(); + break; + } + + case ST_ICON: + bmp->DrawIcon(wnd->getIcon(), head->fx.eval(wnd->getArgs()), head->fy.eval(wnd->getArgs()), 16, 16); + break; + + case ST_MYBITMAP: + sz.cx = head->myBmp->getWidth(); + sz.cy = head->myBmp->getHeight(); +/* + if (head->fh.eval(wnd->getArgs()) > 0) + sz.cy = head->fh.eval(wnd->getArgs()); + else + if (head->fh.eval(wnd->getArgs()) < 0) + sz.cy = szWnd.cy - head->fy.eval(wnd->getArgs()) + head->fh.eval(wnd->getArgs()); + + if (head->fw.eval(wnd->getArgs()) > 0) + sz.cx = head->fw.eval(wnd->getArgs()); + else + if (head->fw.eval(wnd->getArgs()) < 0) + sz.cx = szWnd.cx - head->fx.eval(wnd->getArgs()) + head->fw.eval(wnd->getArgs()); +*/ + if (head->proportional && sz.cx && sz.cy && (((head->fw.eval(wnd->getArgs()) > 0) && !head->fh.eval(wnd->getArgs())) || (!head->fw.eval(wnd->getArgs()) && (head->fh.eval(wnd->getArgs()) > 0)))) + { + if (head->fw.eval(wnd->getArgs())) + { + sz.cy = sz.cy * head->fw.eval(wnd->getArgs()) / sz.cx; + sz.cx = head->fw.eval(wnd->getArgs()); + } else + { + sz.cx = sz.cx * head->fh.eval(wnd->getArgs()) / sz.cy; + sz.cy = head->fh.eval(wnd->getArgs()); + } + } else + { + if (head->fh.eval(wnd->getArgs()) > 0) + sz.cy = head->fh.eval(wnd->getArgs()); + else + if (head->fh.eval(wnd->getArgs()) < 0) + sz.cy = szWnd.cy - head->fy.eval(wnd->getArgs()) + head->fh.eval(wnd->getArgs()) + 1; + if (head->fw.eval(wnd->getArgs()) > 0) + sz.cx = head->fw.eval(wnd->getArgs()); + else + if (head->fw.eval(wnd->getArgs()) < 0) + sz.cx = szWnd.cx - head->fx.eval(wnd->getArgs()) + head->fw.eval(wnd->getArgs()) + 1; + } + + bool vars; + pos.cx = ((head->fx.eval(wnd->getArgs(), &vars) < 0) && !vars) ? szWnd.cx + head->fx.eval(wnd->getArgs()) : head->fx.eval(wnd->getArgs()); + pos.cy = ((head->fy.eval(wnd->getArgs(), &vars) < 0) && !vars) ? szWnd.cy + head->fy.eval(wnd->getArgs()) : head->fy.eval(wnd->getArgs()); + + if (head->type & ST_MONO) + { + COLORREF back = wnd->getBackColor(); + if (head->type & ST_BLEND) + { + bmp->BlendColorized(head->myBmp, pos.cx, pos.cy, sz.cx, sz.cy, back); + } else + { + bmp->DrawColorized(head->myBmp, pos.cx, pos.cy, sz.cx, sz.cy, back); + } + } else + { + if (head->type & ST_BLEND) + { + bmp->Blend(head->myBmp, pos.cx, pos.cy, sz.cx ,sz.cy); + } else + { + bmp->Draw(head->myBmp, pos.cx, pos.cy, sz.cx ,sz.cy); + } + } + break; + + case ST_AVATAR: + { + if (!wnd->getAvatar()) break; + + sz.cx = wnd->getAvatar()->getWidth(); + sz.cy = wnd->getAvatar()->getHeight(); + + if (head->proportional && sz.cx && sz.cy && (((head->fw.eval(wnd->getArgs()) > 0) && !head->fh.eval(wnd->getArgs())) || (!head->fw.eval(wnd->getArgs()) && (head->fh.eval(wnd->getArgs()) > 0)))) + { + if (head->fw.eval(wnd->getArgs())) + { + sz.cy = sz.cy * head->fw.eval(wnd->getArgs()) / sz.cx; + sz.cx = head->fw.eval(wnd->getArgs()); + } else + { + sz.cx = sz.cx * head->fh.eval(wnd->getArgs()) / sz.cy; + sz.cy = head->fh.eval(wnd->getArgs()); + } + } else + { + if (head->fh.eval(wnd->getArgs()) > 0) + sz.cy = head->fh.eval(wnd->getArgs()); + else + if (head->fh.eval(wnd->getArgs()) < 0) + sz.cy = szWnd.cy - head->fy.eval(wnd->getArgs()) + head->fh.eval(wnd->getArgs()); + + if (head->fw.eval(wnd->getArgs()) > 0) + sz.cx = head->fw.eval(wnd->getArgs()); + else + if (head->fw.eval(wnd->getArgs()) < 0) + sz.cx = szWnd.cx - head->fx.eval(wnd->getArgs()) + head->fw.eval(wnd->getArgs()); + } + + pos.cx = head->fx.eval(wnd->getArgs()) < 0 ? szWnd.cx + head->fx.eval(wnd->getArgs()) - sz.cx : head->fx.eval(wnd->getArgs()); + pos.cy = head->fy.eval(wnd->getArgs()) < 0 ? szWnd.cy + head->fy.eval(wnd->getArgs()) - sz.cy : head->fy.eval(wnd->getArgs()); + + wnd->getAvatar()->draw(bmp, pos.cx, pos.cy, sz.cx, sz.cy, options); + break; + } + + case ST_CLOCK: + { + if (!options->DisplayTime) + break; + + COLORREF back = wnd->getBackColor(); + int x = head->fx.eval(wnd->getArgs()); + int y = head->fy.eval(wnd->getArgs()); + if (head->myBmp) + { + int sy = head->myBmp->getHeight(); + if (head->type & ST_MONO) + bmp->BlendPartColorized(head->myBmp, head->clockstart[CLOCK_LEFT], 0, head->clocksize[CLOCK_LEFT], sy, x, y, head->clocksize[CLOCK_LEFT], sy, back); + else + bmp->BlendPart(head->myBmp, head->clockstart[CLOCK_LEFT], 0, head->clocksize[CLOCK_LEFT], sy, x, y, head->clocksize[CLOCK_LEFT], sy); + x += head->clocksize[CLOCK_LEFT]; + for (char *p = wnd->getTime(); *p; p++) + { + int clock_idx = -1; + if (*p == ':') + { + clock_idx = CLOCK_SEPARATOR; + } else + if ((*p >= '0') && (*p <= '9')) + { + clock_idx = CLOCK_DIGITS + *p - '0'; + } + + if (clock_idx >= 0) + { + if (head->type & ST_MONO) + bmp->BlendPartColorized(head->myBmp, head->clockstart[clock_idx], 0, head->clocksize[clock_idx], sy, x, y, head->clocksize[clock_idx], sy, back); + else + bmp->BlendPart(head->myBmp, head->clockstart[clock_idx], 0, head->clocksize[clock_idx], sy, x, y, head->clocksize[clock_idx], sy); + x += head->clocksize[clock_idx]; + } + } + if (head->type & ST_MONO) + bmp->BlendPartColorized(head->myBmp, head->clockstart[CLOCK_RIGHT], 0, head->clocksize[CLOCK_RIGHT], sy, x, y, head->clocksize[CLOCK_RIGHT], sy, back); + else + bmp->BlendPart(head->myBmp, head->clockstart[CLOCK_RIGHT], 0, head->clocksize[CLOCK_RIGHT], sy, x, y, head->clocksize[CLOCK_RIGHT], sy); + x += head->clocksize[CLOCK_RIGHT]; + } else + { + SetTextColor(hdc, wnd->getClockColor()); + HFONT hfnSave = (HFONT)SelectObject(bmp->getDC(), fonts.clock); + SIZE sz; GetTextExtentPoint32A(bmp->getDC(), wnd->getTime(), lstrlenA(wnd->getTime()), &sz); + bmp->Draw_TextA(wnd->getTime(), x, y); + SelectObject(bmp->getDC(), hfnSave); + } + break; + } + } + head = head->next; + } + +} + +bool PopupSkin::onMouseMove(PopupWnd2 *wnd, int x, int y) const +{ + POINT pt; + pt.x = x; + pt.y = y; + + bool res = false; + bool hovered = false; + + for (int i = 0; i < wnd->getActionCount(); ++i) + { + bool hover = PtInRect(&wnd->getActions()[i].rc, pt) ? true : false; + hovered |= hover; + if (wnd->getActions()[i].hover != hover) + { + wnd->getActions()[i].hover = hover; + res = true; + } + } + + SetCursor(LoadCursor(NULL, hovered ? IDC_HAND : IDC_ARROW)); + + return res; +} + +bool PopupSkin::onMouseLeave(PopupWnd2 *wnd) const +{ + bool res = false; + + for (int i = 0; i < wnd->getActionCount(); ++i) + { + if (wnd->getActions()[i].hover) + { + wnd->getActions()[i].hover = false; + res = true; + } + } + + SetCursor(LoadCursor(NULL, IDC_ARROW)); + + return res; +} + +void PopupSkin::loadOptions(std::istream &f) +{ + char *buf = new char[1024]; + while (!f.eof()) + { + f >> buf; + if (*buf == '#') + { + f.ignore(1024, '\n'); + continue; + } + if (!strcmp(buf, "option")) + { + int id, val; + f >> id >> val; + f.getline(buf, 1024); + id--; + if (m_flag_names[id]) + mir_free(m_flag_names[id]); + char *p = buf; + while (isspace(*p)) + p++; + char *q = p + lstrlenA(p) - 1; + while ((q >= p) && isspace(*q)) + *q-- = 0; + m_flag_names[id] = mir_strdup(p); + if (val) + m_flags |= 1 << id; + else + m_flags &= ~(1 << id); + } else + if (!strcmp(buf, "end")) + { + break; + } + } + delete [] buf; +} + +bool PopupSkin::load(LPCTSTR dir) +{ + for (int i = 0; i < 32; i++) + { + if (m_flag_names[i]) + { + mir_free(m_flag_names[i]); + m_flag_names[i] = NULL; + } + } + m_flags = 0; + + if (!_tcsncmp(_T("res:"), dir, 4)) + { // resource + loadSkin(dir+4, _T("Skin")); + } else + { // filesystem + // skin info + TCHAR dir_save[1024]; + GetCurrentDirectory(1024, dir_save); + SetCurrentDirectory(dir); + + std::ifstream theFile; + theFile.open("popupskin.config", std::ios::in); + if (theFile) + { + loadOptions(theFile); + theFile.close(); + } + + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFile(_T("*.popupskin"), &ffd); + while (hFind != INVALID_HANDLE_VALUE) + { + loadSkin(ffd.cFileName); + break; + if (!FindNextFile(hFind, &ffd)) + break; + } + FindClose(hFind); + + SetCurrentDirectory(dir_save); + } + + loadOpts(); + + return true; +} + +void PopupSkin::loadSkin(std::istream &f) +{ + m_bottom_gap = m_right_gap = 0; + m_legacy_region_opacity = 64; + m_shadow_region_opacity = 1; + m_popup_version = 0; + m_internalClock = true; + + SKINELEMENT *head = new SKINELEMENT; + m_elements = head; + head->type = ST_NOTHING; + head->next = NULL; + + while (!f.eof()) + { + char buf[1024]; + f >> buf; +// fscanf(f, "%s", buf); + + if (!*buf) + continue; + + if (*buf == '#' || *buf == ';') + { + f.ignore(1024, '\n'); + continue; + } + + if (!lstrcmpA(buf,"popup-version")) + { + f >> m_popup_version; + m_popup_version = PLUGIN_MAKE_VERSION((m_popup_version/1000000)%100, (m_popup_version/10000)%100, (m_popup_version/100)%100, (m_popup_version/1)%100); + if (!isCompatible()) + break; + } else + if (!lstrcmpA(buf,"padding-right")) + { + f >> m_right_gap; + } else + if (!lstrcmpA(buf,"padding-bottom")) + { + f >> m_bottom_gap; + } else + if (!lstrcmpA(buf,"shadow-region-opacity")) + { + f >> m_shadow_region_opacity; + } else + if (!lstrcmpA(buf,"legacy-region-opacity")) + { + f >> m_legacy_region_opacity; + } else + if (!lstrcmpA(buf,"w")) + { + f.getline(buf, 1024); + m_fw.set(buf); + } else + if (!lstrcmpA(buf,"h")) + { + f.getline(buf, 1024); + m_fh.set(buf); + } else + if (!lstrcmpA(buf,"object")) + { + head->next = loadObject(f); + if (head->next && ((head->next->type & ST_TYPEMASK) == ST_CLOCK)) + m_internalClock = false; + head = head->next; + head->next = NULL; + } else + if (!lstrcmpA(buf,"options")) + { + loadOptions(f); + } + } + + + head = m_elements; + m_elements = m_elements->next; + delete head; +} + +void PopupSkin::loadSkin(LPCTSTR fn) +{ + if(!fn) return; +#if defined (_UNICODE) && _MSC_VER <= 1200 + char* temp= mir_t2a(fn); + std::ifstream theFile; + theFile.open(temp, std::ios::in); + mir_free(temp); +#else + std::ifstream theFile; + theFile.open(fn, std::ios::in); +#endif + if (!theFile) return; + loadSkin(theFile); + theFile.close(); +} + +void PopupSkin::loadSkin(LPCTSTR lpName, LPCTSTR lpType) +{ + HRSRC hRes = FindResource(hInst, lpName, lpType); +// DWORD ResSize = SizeofResource(hInst,hRes); + HRSRC hResLoad = (HRSRC)LoadResource(hInst, hRes); + char *lpResLock = (char *)LockResource(hResLoad); +// lpResLock [ResSize] = 0; + std::istringstream stream(lpResLock); + loadSkin(stream); + UnlockResource(lpResLock); + FreeResource(hRes); +} + +PopupSkin::SKINELEMENT *PopupSkin::loadObject(std::istream &f) +{ +// char pth[1024]; +// GetSkinPath(pth,1024); + + SKINELEMENT *element = new SKINELEMENT; +// element->x = element->y = element->w = element->h = 0; + element->proportional = 0; + element->type = ST_NOTHING|ST_BADPOS; + element->next = NULL; + element->flag_mask = 0; + element->flags = 0; + element->myBmp = NULL; + + while (!f.eof()) + { + char buf[1024]; + f >> buf; + + if (!*buf) + continue; + + if (*buf == '#' || *buf == ';') + { + f.ignore(1024, '\n'); + continue; + } + + if (!lstrcmpA(buf,"type")) + { + f >> buf; + if (!lstrcmpA(buf,"icon")) + element->type = ( element->type & ~ST_TYPEMASK ) | ST_ICON; + else + if (!lstrcmpA(buf,"bitmap")) + element->type = ( element->type & ~ST_TYPEMASK ) | ST_MYBITMAP; + else + if (!lstrcmpA(buf,"text")) + { + element->type = ( element->type & ~ST_TYPEMASK ) | ST_TEXT; + element->textColor = (COLORREF)0xffffffff; + element->hfn = 0; + } + else + if (!lstrcmpA(buf,"title")) + { + element->type = ( element->type & ~ST_TYPEMASK ) | ST_TITLE; + element->textColor = (COLORREF)0xffffffff; + element->hfn = 0; + } else + if (!lstrcmpA(buf,"avatar")) + { + element->type = ( element->type & ~ST_TYPEMASK ) | ST_AVATAR; + } else + if (!lstrcmpA(buf,"clock")) + { + element->type = ( element->type & ~ST_TYPEMASK ) | ST_CLOCK; + } + } else + if (!lstrcmpA(buf,"source")) + { + f >> buf; +// fscanf(f, "%*[\x01-\x20]%[^\n]", buf); +// if ( (element->type & ST_TYPEMASK ) == ST_BITMAP) +// element->hbm = LoadImageFromFile(buf); +// else + if (((element->type & ST_TYPEMASK) == ST_MYBITMAP) || ((element->type & ST_TYPEMASK) == ST_CLOCK)) + { + char *alpha = mir_strdup(buf); + alpha[strlen(alpha)-1] = 'a'; + element->myBmp = new MyBitmap(buf,alpha); + mir_free(alpha); + } + } else + if (!lstrcmpA(buf,"mono")) + { + element->type |= ST_MONO; + } else + if (!lstrcmpA(buf,"layer")) + { + element->type |= ST_BLEND; + } else + if (!lstrcmpA(buf,"proportional")) + { + f >> element->proportional; + } else + if (!lstrcmpA(buf,"x")) + { + f.getline(buf, 1024); + element->fx.set(buf); + element->type &= ~ST_BADPOS; + } else + if (!lstrcmpA(buf,"y")) + { + f.getline(buf, 1024); + element->fy.set(buf); + element->type &= ~ST_BADPOS; + } else + if (!lstrcmpA(buf,"w")) + { + f.getline(buf, 1024); + element->fw.set(buf); + } else + if (!lstrcmpA(buf,"h")) + { + f.getline(buf, 1024); + element->fh.set(buf); + } else + if (!lstrcmpA(buf,"ifset")) + { + int id; + f >> id; id--; + element->flag_mask |= 1 << id; + element->flags |= 1 << id; + } else + if (!lstrcmpA(buf,"ifnotset")) + { + int id; + f >> id; id--; + element->flag_mask |= 1 << id; + element->flags &= ~(1 << id); + } else + if (!lstrcmpA(buf,"color")) + { + if (((element->type & ST_TYPEMASK) != ST_TEXT) && + ((element->type & ST_TYPEMASK) != ST_TITLE)) continue; + + int r,g,b; + f >> r >> g >> b; + element->textColor = RGB(r,g,b); + } else + if (!lstrcmpA(buf,"clocksize")) + { + element->clockstart[0]=0; + f >> element->clocksize[0]; + for (int i = 1; i < CLOCK_ITEMS; i++) + { + element->clockstart[i]=element->clockstart[i-1]+element->clocksize[i-1]; + f >> element->clocksize[i]; + } + } else + if (!lstrcmpA(buf,"end")) + { + break; + } + } + return element; +} + +void PopupSkin::freeSkin(SKINELEMENT *head) +{ + while (head) + { + SKINELEMENT *next = head->next; + + if ((head->type & ST_TYPEMASK) == ST_BITMAP) + DeleteObject(head->hbm); + if ((head->type & ST_TYPEMASK) == ST_MYBITMAP) + delete head->myBmp; + if (((head->type & ST_TYPEMASK) == ST_CLOCK) && head->myBmp) + delete head->myBmp; + + delete head; + head = next; + } +} + +void PopupSkin::saveOpts() const +{ + char buf[128]; +#if defined( _UNICODE ) + mir_snprintf(buf, sizeof(buf), "skin.%.120S", m_name); +#else + mir_snprintf(buf, sizeof(buf), "skin.%.120s", m_name); +#endif + DBWriteContactSettingDword(NULL, MODULNAME, buf, m_flags); +} + +void PopupSkin::loadOpts() const +{ + char buf[128]; +#if defined( _UNICODE ) + mir_snprintf(buf, sizeof(buf), "skin.%.120S", m_name); +#else + mir_snprintf(buf, sizeof(buf), "skin.%.120s", m_name); +#endif + m_flags = DBGetContactSettingDword(NULL, MODULNAME, buf, m_flags); +} + +// Skins +Skins skins; + +Skins::Skins() +{ + m_skins = 0; +} + +Skins::~Skins() +{ + while (m_skins) + { + SKINLIST *next = m_skins->next; + delete m_skins->skin; + delete [] m_skins->dir; + mir_free(m_skins->name); // this is allocated with mir_strdup() + delete m_skins; + m_skins = next; + } +} + +bool Skins::load(LPCTSTR dir1) +{ + while (m_skins) + { + SKINLIST *next = m_skins->next; + mir_free(m_skins->name); + delete [] m_skins->dir; + delete m_skins->skin; + delete m_skins; + m_skins = next; + } + + SKINLIST *skin = new SKINLIST; + skin->next = m_skins; + m_skins = skin; + m_skins->name = mir_tstrdup(_T("* Popup Classic")); + m_skins->dir = new TCHAR[1024]; + lstrcpy(m_skins->dir, _T("res:classic.popupskin")); + m_skins->skin = 0; + + TCHAR dir[1024]={'\0'}; + + if (ServiceExists(MS_FOLDERS_GET_PATH)) { + if (FoldersGetCustomPathT(folderId, dir, 1024, NULL) != 0) + return false; + } + else { + GetModuleFileName(hInst,dir,1024); + dir[lstrlen(dir)-18] = 0; + lstrcat(dir,_T("\\skins\\popup")); + DWORD fa = GetFileAttributes(dir); + if ((fa==INVALID_FILE_ATTRIBUTES) || !(fa&FILE_ATTRIBUTE_DIRECTORY)) + return false; + } + + TCHAR dir_save[1024]; + GetCurrentDirectory(1024, dir_save); + SetCurrentDirectory(dir); + + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFile(_T("*.*"), &ffd); + while (hFind != INVALID_HANDLE_VALUE) + { + if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && lstrcmp(_T("."), ffd.cFileName) && lstrcmp(_T(".."), ffd.cFileName)) + { + SetCurrentDirectory(ffd.cFileName); + + SKINLIST *skin = new SKINLIST; + skin->next = m_skins; + m_skins = skin; + m_skins->name = mir_tstrdup(ffd.cFileName); + m_skins->dir = new TCHAR[1024]; + GetCurrentDirectory(1024, m_skins->dir); + m_skins->skin = 0; + + SetCurrentDirectory(_T("..")); + } + + if (!FindNextFile(hFind, &ffd)) + break; + } + FindClose(hFind); + + SetCurrentDirectory(dir_save); + + return true; +} + +const PopupSkin *Skins::getSkin(LPCTSTR name) +{ + SKINLIST *any = 0; + for (SKINLIST *p = m_skins; p; p = p->next) + { + if (!lstrcmp(p->name, _T("* Popup Classic")) || !any) + any = p; + if (!lstrcmpi(p->name, name)) + { + any = p; + break; + } + } + + if (any && any->skin) + return any->skin; + if (!any) + return 0; + + any->skin = new PopupSkin(any->name); + any->skin->load(any->dir); + + if (!any->skin->isCompatible()) + MessageBox(NULL, + TranslateTS( + _T("The skin you are trying to load is designed\r\n") + _T("for newer version of Popup Plus. And will not\r\n") + _T("display properly.\r\n") + _T("\r\n") + _T("Please choose another skin.") ), + _T(MODULNAME_LONG), MB_ICONSTOP|MB_OK); + + return any->skin; +} + +void Skins::loadActiveSkin() +{ + for (SKINLIST *p = m_skins; p; p = p->next) + if (!lstrcmpi(p->name, PopUpOptions.SkinPack)) + { + if (p->skin) + break; + + p->skin = new PopupSkin(p->name); + p->skin->load(p->dir); + break; + } +} + +void Skins::freeAllButActive() +{ + for (SKINLIST *p = m_skins; p; p = p->next) + if (lstrcmpi(p->name, PopUpOptions.SkinPack)) + { + delete p->skin; + p->skin = NULL; + } +} diff --git a/Popup/src/skin.h b/Popup/src/skin.h new file mode 100644 index 0000000..8cc7171 --- /dev/null +++ b/Popup/src/skin.h @@ -0,0 +1,203 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/skin.h $ +Revision : $Revision: 1620 $ +Last change on : $Date: 2010-06-23 21:31:05 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __skin_h__ +#define __skin_h__ + +#include +#include + +class MyBitmap; +class PopupWnd2; + +class PopupSkin +{ +public: + enum + { + ST_TYPEMASK = 0x07, + ST_NOTHING = 0x00, + ST_ICON = 0x01, + ST_TEXT = 0x02, + ST_TITLE = 0x03, + ST_BITMAP = 0x04, + ST_MYBITMAP = 0x05, + ST_AVATAR = 0x06, + ST_CLOCK = 0x07, + + ST_STRETCH = 0x08, + ST_MONO = 0x10, + ST_BLEND = 0x20, + ST_BADPOS = 0x40 + }; + + enum + { + DF_STATIC = 0x01, + DF_ANIMATE = 0x02, + DF_ALL = 0xff + }; + + enum + { + // left, separator, digits, am/pm, right + CLOCK_LEFT = 0, + CLOCK_SEPARATOR = 1, + CLOCK_DIGITS = 2, + CLOCK_AM = 12, + CLOCK_PM = 13, + CLOCK_RIGHT = 14, + CLOCK_ITEMS = 1+1+10+2+1 + }; + + struct SKINELEMENT + { + int type; + union + { + HICON hic; + HBITMAP hbm; + MyBitmap *myBmp; + struct + { + COLORREF textColor; + HFONT hfn; +// int textw; + }; + }; + unsigned long flags; + unsigned long flag_mask; + Formula fx, fy, fw, fh; + int clocksize[CLOCK_ITEMS]; + int clockstart[CLOCK_ITEMS]; + int proportional; + SKINELEMENT *next; + }; + + struct RenderInfo + { + bool hasAvatar; + int titlew, textw; + int realtextw, texth; + int actw; + RECT textRect; + }; + +private: + LPTSTR m_name; + int m_bottom_gap, m_right_gap; + int m_legacy_region_opacity, m_shadow_region_opacity; + int m_popup_version; + bool m_internalClock; + Formula m_fw, m_fh; + SKINELEMENT *m_elements; + char *m_flag_names[32]; + mutable unsigned long m_flags; + + void loadOptions(std::istream &f); + SKINELEMENT *loadObject(std::istream &f); + void loadSkin(std::istream &f); + void loadSkin(LPCTSTR fn); + void loadSkin(LPCTSTR lpName, LPCTSTR lpType); + + void freeSkin(SKINELEMENT *head); + + SIZE measureAction(HDC hdc, POPUPACTION *act) const; + SIZE measureActionBar(HDC hdc, PopupWnd2 *wnd) const; + void drawAction(MyBitmap *bmp, POPUPACTION *act, int x, int y, bool hover) const; + void drawActionBar(MyBitmap *bmp, PopupWnd2 *wnd, int x, int y) const; + +public: + PopupSkin(LPCTSTR aName = 0); + ~PopupSkin(); + + void measure(HDC hdc, PopupWnd2 *wnd, int maxw, POPUPOPTIONS *options) const; + void display(MyBitmap *bmp, PopupWnd2 *wnd, int maxw, POPUPOPTIONS *options, DWORD drawFlags=DF_ALL) const; + bool onMouseMove(PopupWnd2 *wnd, int x, int y) const; + bool onMouseLeave(PopupWnd2 *wnd) const; + + bool load(LPCTSTR dir); // load skin from current directory + + SKINELEMENT *getSubSkin() { return m_elements; } + int getBottomGap() const { return m_bottom_gap; } + int getRightGap() const { return m_right_gap; } + int useInternalClock() const { return m_internalClock; } + int getLegacyRegionOpacity() const { return m_legacy_region_opacity; } + int getShadowRegionOpacity() const { return m_shadow_region_opacity; } + bool isCompatible() const { return (DWORD) m_popup_version <= (DWORD) pluginInfoEx.version; } + + const LPTSTR getName() const { return m_name; } + + const char *getFlagName(int id) const { return m_flag_names[id-1]; } + bool getFlag(int id) const { return (m_flags & (1 << (id-1))) != 0; } + void setFlag(int id, bool val) const + { + if (val) + m_flags |= 1 << (id-1); + else + m_flags &= ~(1 << (id-1)); + } + + void saveOpts() const; + void loadOpts() const; +}; + +class Skins +{ +public: + struct SKINLIST + { + PopupSkin *skin; + LPTSTR dir; + LPTSTR name; + SKINLIST *next; + }; + +private: + SKINLIST *m_skins; + +public: + Skins(); + ~Skins(); + + bool load(LPCTSTR dir); + const PopupSkin *getSkin(LPCTSTR name); + + const SKINLIST *getSkinList() const { return m_skins; } + + void loadActiveSkin(); + void freeAllButActive(); +}; + +extern Skins skins; + +#endif diff --git a/Popup/src/srmm_menu.cpp b/Popup/src/srmm_menu.cpp new file mode 100644 index 0000000..398d500 --- /dev/null +++ b/Popup/src/srmm_menu.cpp @@ -0,0 +1,171 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/srmm_menu.cpp $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#include "headers.h" + +/************************************************************************************* + === how does this work === + We have four icons -- one for each mode. and we do hide/show them depending + on current active mode for user. +*************************************************************************************/ + +static HANDLE hDialogsList = NULL; +static HANDLE hIconPressed=0,hWindowEvent=0; + +static int SrmmMenu_ProcessEvent(WPARAM wParam, LPARAM lParam); +static int SrmmMenu_ProcessIconClick(WPARAM wParam, LPARAM lParam); + + +void SrmmMenu_Load() +{ + if (ServiceExists(MS_MSG_ADDICON)) + { + StatusIconData sid = {0}; + sid.cbSize = sizeof(sid); + sid.szModule = MODULNAME; + sid.flags = 0; + + sid.dwId = 0; + sid.szTooltip = Translate("Popup Mode: Auto"); + sid.hIcon = sid.hIconDisabled = IcoLib_GetIcon(ICO_POPUP_ON,0); + CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid); + + sid.dwId = 1; + sid.szTooltip = Translate("Popup Mode: Favourite"); + sid.hIcon = sid.hIconDisabled = IcoLib_GetIcon(ICO_FAV,0); + CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid); + + sid.dwId = 2; + sid.szTooltip = Translate("Popup Mode: Ignore fullscreen"); + sid.hIcon = sid.hIconDisabled = IcoLib_GetIcon(ICO_FULLSCREEN,0); + CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid); + + sid.dwId = 3; + sid.szTooltip = Translate("Popup Mode: Block contact"); + sid.hIcon = sid.hIconDisabled = IcoLib_GetIcon(ICO_POPUP_OFF,0); + CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid); + + hIconPressed = HookEvent(ME_MSG_ICONPRESSED, SrmmMenu_ProcessIconClick); + hWindowEvent = HookEvent(ME_MSG_WINDOWEVENT, SrmmMenu_ProcessEvent); +/* + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + SrmmMenu_UpdateIcon(hContact); + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } +*/ + } +} + +void SrmmMenu_Unload() +{ + UnhookEvent(hIconPressed); + UnhookEvent(hWindowEvent); +} + +static void SrmmMenu_UpdateIcon(HANDLE hContact) +{ + if (!hContact) return; + + int mode = DBGetContactSettingByte(hContact, MODULNAME, "ShowMode", PU_SHOWMODE_AUTO); + + StatusIconData sid = {0}; + sid.cbSize = sizeof(sid); + sid.szModule = MODULNAME; + + for (int i = 0; i < 4; ++i) + { + sid.dwId = i; + sid.flags = (i == mode) ? 0 : MBF_HIDDEN; + CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid); + } +} + +static int SrmmMenu_ProcessEvent(WPARAM wParam, LPARAM lParam) +{ + MessageWindowEventData *event = (MessageWindowEventData *)lParam; + + if ( event->uType == MSG_WINDOW_EVT_OPEN ) + { + if (!hDialogsList) + hDialogsList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + + WindowList_Add(hDialogsList, event->hwndWindow, event->hContact); + SrmmMenu_UpdateIcon(event->hContact); + } + else if ( event->uType == MSG_WINDOW_EVT_CLOSING ) + { + if (hDialogsList) + WindowList_Remove(hDialogsList, event->hwndWindow); + } + + return 0; +} + +static int SrmmMenu_ProcessIconClick(WPARAM wParam, LPARAM lParam) +{ + StatusIconClickData *sicd = (StatusIconClickData *)lParam; + if (lstrcmpA(sicd->szModule, MODULNAME)) return 0; + + HANDLE hContact = (HANDLE)wParam; + if (!hContact) return 0; + + int mode = DBGetContactSettingByte(hContact, MODULNAME, "ShowMode", PU_SHOWMODE_AUTO); + + if (sicd->flags&MBCF_RIGHTBUTTON) + { + HMENU hMenu = CreatePopupMenu(); + + AppendMenu(hMenu, MF_STRING, 1+PU_SHOWMODE_AUTO, TranslateT("Auto")); + AppendMenu(hMenu, MF_STRING, 1+PU_SHOWMODE_FAVORITE, TranslateT("Favourite")); + AppendMenu(hMenu, MF_STRING, 1+PU_SHOWMODE_FULLSCREEN, TranslateT("Ignore fullscreen")); + AppendMenu(hMenu, MF_STRING, 1+PU_SHOWMODE_BLOCK, TranslateT("Block")); + + CheckMenuItem(hMenu, 1+mode, MF_BYCOMMAND|MF_CHECKED); + + mode = TrackPopupMenu(hMenu, TPM_RETURNCMD, sicd->clickLocation.x, sicd->clickLocation.y, 0, WindowList_Find(hDialogsList, hContact), NULL); + + if (mode) + { + DBWriteContactSettingByte(hContact, MODULNAME, "ShowMode", mode-1); + SrmmMenu_UpdateIcon(hContact); + } + } else + { + DBWriteContactSettingByte(hContact, MODULNAME, "ShowMode", + (mode == PU_SHOWMODE_AUTO) ? PU_SHOWMODE_BLOCK : PU_SHOWMODE_AUTO); + SrmmMenu_UpdateIcon(hContact); + } + + return 0; +} diff --git a/Popup/src/srmm_menu.h b/Popup/src/srmm_menu.h new file mode 100644 index 0000000..e9e8ef4 --- /dev/null +++ b/Popup/src/srmm_menu.h @@ -0,0 +1,39 @@ +/* +Popup Plus plugin for Miranda IM + +Copyright © 2002 Luca Santarelli, + © 2004-2007 Victor Pavlychko + © 2010 MPK + © 2010 Merlin_de + +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. + +=============================================================================== + +File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/srmm_menu.h $ +Revision : $Revision: 1610 $ +Last change on : $Date: 2010-06-23 00:55:13 +0300 (Ср, 23 июн 2010) $ +Last change by : $Author: Merlin_de $ + +=============================================================================== +*/ + +#ifndef __srmm_menu_h__ +#define __srmm_menu_h__ + +void SrmmMenu_Load(); +void SrmmMenu_Unload(); + +#endif // __srmm_menu_h__ -- cgit v1.2.3