/* 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. */ #include "headers.h" WORD SETTING_MAXIMUMWIDTH_MAX = GetSystemMetrics(SM_CXSCREEN); #define MENUCOMMAND_HISTORY "Popup/ShowHistory" #define MENUCOMMAND_SVC "Popup/EnableDisableMenuCommand" HANDLE hEventNotify; //===== 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); void UpgradeDb(); //===== 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; HANDLE htuTitle; //===== Menu item ===== HGENMENU hMenuRoot; HGENMENU hMenuItem; HGENMENU hMenuItemHistory; //===== Event Handles ===== HANDLE hTTButton; //===== Options pages ===== static int OptionsInitialize(WPARAM wParam, LPARAM) { OPTIONSDIALOGPAGE odp = { sizeof(odp) }; odp.position = 100000000; odp.groupPosition = 910000000; odp.hInstance = hInst; odp.flags = ODPF_BOLDGROUPS; odp.pszTitle = MODULNAME_PLU; odp.pszTab = LPGEN("General"); odp.pfnDlgProc = DlgProcPopupGeneral; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP_GENERAL); Options_AddPage(wParam, &odp); odp.pszTab = LPGEN("Classes"); odp.pfnDlgProc = DlgProcOptsClasses; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_NOTIFICATIONS); Options_AddPage(wParam, &odp); odp.pszTab = LPGEN("Actions"); odp.pfnDlgProc = DlgProcPopupActions; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ACTIONS); Options_AddPage(wParam, &odp); odp.pszTab = LPGEN("Contacts"); odp.pfnDlgProc = DlgProcContactOpts; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CONTACTS); Options_AddPage(wParam, &odp); odp.pszTab = LPGEN("Advanced"); odp.pfnDlgProc = DlgProcPopupAdvOpts; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP_ADVANCED); Options_AddPage(wParam, &odp); odp.pszGroup = LPGEN("Skins"); odp.pszTab = LPGEN(MODULNAME_PLU); odp.pfnDlgProc = DlgProcPopSkinsOpts; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SKIN2); Options_AddPage(wParam, &odp); return 0; } static int FontsChanged(WPARAM, LPARAM) { ReloadFonts(); return 0; } static int IconsChanged(WPARAM, LPARAM) { LoadActions(); CLISTMENUITEM mi = { 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; Menu_ModifyItem(hMenuItem, &mi); Menu_ModifyItem(hMenuRoot, &mi); mi.hIcon = IcoLib_GetIcon(ICO_HISTORY, 0); mi.flags = CMIM_ICON; Menu_ModifyItem(hMenuItemHistory, &mi); return 0; } static int TTBLoaded(WPARAM, LPARAM) { TTBButton ttb = { sizeof(ttb) }; ttb.pszService = MENUCOMMAND_SVC; ttb.lParamUp = 1; ttb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP | TTBBF_ASPUSHBUTTON; if (PopupOptions.ModuleIsEnabled) ttb.dwFlags |= TTBBF_PUSHED; ttb.name = LPGEN("Toggle Popups"); ttb.hIconHandleUp = Skin_GetIconHandle(ICO_TB_POPUP_OFF); ttb.hIconHandleDn = Skin_GetIconHandle(ICO_TB_POPUP_ON); ttb.pszTooltipUp = LPGEN("Enable Popups"); ttb.pszTooltipDn = LPGEN("Disable Popups"); hTTButton = TopToolbar_AddButton(&ttb); return 0; } //===== EnableDisableMenuCommand ===== INT_PTR svcEnableDisableMenuCommand(WPARAM, LPARAM) { CLISTMENUITEM mi = { 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; db_set_b(NULL, MODULNAME, "ModuleIsEnabled", FALSE); mi.ptszName = LPGENT("Enable Popups"); 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; db_set_b(NULL, MODULNAME, "ModuleIsEnabled", TRUE); mi.ptszName = LPGENT("Disable Popups"); mi.hIcon = IcoLib_GetIcon(ICO_POPUP_ON,0); } mi.flags = CMIM_NAME | CMIM_ICON | CMIF_TCHAR; Menu_ModifyItem(hMenuItem, &mi); mi.flags = CMIM_ICON; Menu_ModifyItem(hMenuRoot, &mi); if (hTTButton) CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTTButton, (PopupOptions.ModuleIsEnabled) ? TTBST_PUSHED : TTBST_RELEASED); return 0; } INT_PTR svcShowHistory(WPARAM, LPARAM) { PopupHistoryShow(); return 0; } void InitMenuItems(void) { CLISTMENUITEM mi = { 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 = Menu_AddMainMenuItem(&mi); // Add item to main menu mi.hParentMenu = (HGENMENU)hMenuRoot; CreateServiceFunction(MENUCOMMAND_SVC, svcEnableDisableMenuCommand); mi.ptszName = PopupOptions.ModuleIsEnabled ? LPGENT("Disable Popups") : LPGENT("Enable Popups"); mi.pszService = MENUCOMMAND_SVC; hMenuItem = Menu_AddMainMenuItem(&mi); // Popup History 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 = Menu_AddMainMenuItem(&mi); } //===== GetStatus ===== INT_PTR GetStatus(WPARAM, LPARAM) { return PopupOptions.ModuleIsEnabled; } //register Hotkey void LoadHotkey() { HOTKEYDESC hk = { sizeof(hk) }; hk.dwFlags = HKD_TCHAR; hk.pszName = "Toggle Popups"; hk.ptszDescription = LPGENT("Toggle Popups"); hk.ptszSection = LPGENT(MODULNAME_PLU); hk.pszService = MENUCOMMAND_SVC; Hotkey_Register(&hk); // 'Popup History' Hotkey hk.pszName = "Popup History"; hk.ptszDescription = LPGENT("Popup History"); hk.pszService = MENUCOMMAND_HISTORY; Hotkey_Register(&hk); } //menu //Function which makes the initializations static int ModulesLoaded(WPARAM,LPARAM) { //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(); //Uninstalling purposes if (ServiceExists("PluginSweeper/Add")) CallService("PluginSweeper/Add", (WPARAM)Translate(MODULNAME), (LPARAM)MODULNAME); //load fonts / create hook InitFonts(); HookEvent(ME_FONT_RELOAD, FontsChanged); //load actions and notifications LoadActions(); LoadNotifications(); //hook TopToolBar HookEvent(ME_TTB_MODULELOADED, TTBLoaded); //Folder plugin support folderId = FoldersRegisterCustomPathT(LPGEN("Skins"), LPGEN("Popup Plus"), MIRANDA_PATHT _T("\\Skins\\Popup")); //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(); 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) { return &pluginInfoEx; } //ME_SYSTEM_PRESHUTDOWN event //called before the app goes into shutdown routine to make sure everyone is happy to exit static int OkToExit(WPARAM, 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(void) { DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, THREAD_SET_CONTEXT, FALSE, 0); mir_getMTI(&MText); mir_getLP(&pluginInfoEx); CreateServiceFunction(MS_POPUP_GETSTATUS, GetStatus); #if defined(_DEBUG) PopupOptions.debug = db_get_b(NULL, MODULNAME, "debug", FALSE); #else PopupOptions.debug = false; #endif LoadGDIPlus(); //Transparent and animation routines hDwmapiDll = LoadLibrary(_T("dwmapi.dll")); MyDwmEnableBlurBehindWindow = 0; if (hDwmapiDll) MyDwmEnableBlurBehindWindow = (HRESULT (WINAPI *)(HWND, DWM_BLURBEHIND *))GetProcAddress(hDwmapiDll, "DwmEnableBlurBehindWindow"); PopupHistoryLoad(); LoadPopupThread(); if (!LoadPopupWnd2()) { MessageBox(0, TranslateT("Error: I could not register the Popup Window class.\r\nThe 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++ UpgradeDb(); db_set_s(NULL, "KnownModules", pluginInfoEx.shortName, MODULNAME); HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); HookEvent(ME_OPT_INITIALISE, OptionsInitialize); HookEvent(ME_SYSTEM_PRESHUTDOWN, OkToExit); hbmNoAvatar = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_NOAVATAR)); if (!OptionLoaded) LoadOptions(); //Service Functions hEventNotify = CreateHookableEvent(ME_POPUP_FILTER); CreateServiceFunction(MS_POPUP_ADDPOPUP, Popup_AddPopup); CreateServiceFunction(MS_POPUP_ADDPOPUPW, Popup_AddPopupW); CreateServiceFunction(MS_POPUP_ADDPOPUP2, Popup_AddPopup2); CreateServiceFunction(MS_POPUP_CHANGETEXTW, Popup_ChangeTextW); CreateServiceFunction(MS_POPUP_CHANGEW, Popup_ChangeW); CreateServiceFunction(MS_POPUP_CHANGEPOPUP2, Popup_Change2); CreateServiceFunction(MS_POPUP_GETCONTACT, Popup_GetContact); CreateServiceFunction(MS_POPUP_GETPLUGINDATA, Popup_GetPluginData); CreateServiceFunction(MS_POPUP_ISSECONDLINESHOWN, Popup_IsSecondLineShown); CreateServiceFunction(MS_POPUP_SHOWMESSAGE, Popup_ShowMessage); CreateServiceFunction(MS_POPUP_SHOWMESSAGEW, Popup_ShowMessageW); CreateServiceFunction(MS_POPUP_QUERY, Popup_Query); CreateServiceFunction(MS_POPUP_REGISTERACTIONS, Popup_RegisterActions); CreateServiceFunction(MS_POPUP_REGISTERNOTIFICATION, Popup_RegisterNotification); CreateServiceFunction(MS_POPUP_UNHOOKEVENTASYNC, Popup_UnhookEventAsync); CreateServiceFunction(MS_POPUP_REGISTERVFX, Popup_RegisterVfx); CreateServiceFunction(MS_POPUP_REGISTERCLASS, Popup_RegisterPopupClass); CreateServiceFunction(MS_POPUP_UNREGISTERCLASS, Popup_UnregisterPopupClass); CreateServiceFunction(MS_POPUP_ADDPOPUPCLASS, Popup_CreateClassPopup); //load icons / create hook InitIcons(); 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) { DeleteObject(fonts.title); DeleteObject(fonts.clock); DeleteObject(fonts.text); DeleteObject(fonts.action); DeleteObject(fonts.actionHover); DeleteObject(hbmNoAvatar); FreeLibrary(hDwmapiDll); FreeLibrary(hUserDll); FreeLibrary(hMsimgDll); FreeLibrary(hGdiDll); DestroyHookableEvent(hEventNotify); 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(); UnloadTreeData(); CloseHandle(hMainThread); return 0; }