summaryrefslogtreecommitdiff
path: root/protocols/Weather/src/weather_mwin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Weather/src/weather_mwin.cpp')
-rw-r--r--protocols/Weather/src/weather_mwin.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/protocols/Weather/src/weather_mwin.cpp b/protocols/Weather/src/weather_mwin.cpp
new file mode 100644
index 0000000000..a240b01421
--- /dev/null
+++ b/protocols/Weather/src/weather_mwin.cpp
@@ -0,0 +1,364 @@
+/*
+Weather Protocol plugin for Miranda IM
+Copyright (c) 2012 Miranda NG team
+Copyright (c) 2006-2009 Boris Krasnovskiy All Rights Reserved
+Copyright (c) 2002-2006 Calvin Che
+
+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; version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+
+#define MS_TOOLTIP_SHOWTIP "mToolTip/ShowTip"
+#define MS_TOOLTIP_HIDETIP "mToolTip/HideTip"
+
+static MWindowList hMwinWindowList;
+static HANDLE hFontHook;
+
+HGENMENU hMwinMenu;
+
+typedef struct
+{
+ MCONTACT hContact;
+ HWND hAvt;
+ BOOL haveAvatar;
+} MWinDataType;
+
+#define WM_REDRAWWIN (WM_USER + 17369)
+
+static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ MWinDataType *data = (MWinDataType*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_CREATE:
+ data = (MWinDataType*)mir_calloc(sizeof(MWinDataType));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data);
+
+ data->hContact = (DWORD_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams;
+ data->hAvt = CreateWindow(AVATAR_CONTROL_CLASS, TEXT(""), WS_CHILD,
+ 0, 0, opt.AvatarSize, opt.AvatarSize, hwnd, nullptr, g_plugin.getInst(), nullptr);
+ if (data->hAvt) SendMessage(data->hAvt, AVATAR_SETCONTACT, 0, (LPARAM)data->hContact);
+ break;
+
+ case WM_DESTROY:
+ mir_free(data);
+ break;
+
+ case WM_CONTEXTMENU:
+ {
+ POINT pt;
+ GetCursorPos(&pt);
+ HMENU hMenu = Menu_BuildContactMenu(data->hContact);
+ TrackPopupMenu(hMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, nullptr);
+ DestroyMenu(hMenu);
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ {
+ TRACKMOUSEEVENT tme = { 0 };
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.hwndTrack = hwnd;
+ tme.dwFlags = TME_QUERY;
+ TrackMouseEvent(&tme);
+
+ if (tme.dwFlags == 0) {
+ tme.dwFlags = TME_HOVER | TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ tme.dwHoverTime = CallService(MS_CLC_GETINFOTIPHOVERTIME, 0, 0);
+ TrackMouseEvent(&tme);
+ }
+ }
+ break;
+
+ case WM_MOUSEHOVER:
+ {
+ POINT pt;
+ CLCINFOTIP ti = { 0 };
+
+ GetCursorPos(&pt);
+ GetWindowRect(hwnd, &ti.rcItem);
+
+ ti.cbSize = sizeof(ti);
+ ti.hItem = (HANDLE)data->hContact;
+ ti.ptCursor = pt;
+ ti.isTreeFocused = 1;
+ CallService(MS_TOOLTIP_SHOWTIP, 0, (LPARAM)&ti);
+ }
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ BriefInfo(data->hContact, 0);
+ break;
+
+ case WM_COMMAND: //Needed by the contact's context menu
+ if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, data->hContact))
+ break;
+ return FALSE;
+
+ case WM_MEASUREITEM: //Needed by the contact's context menu
+ return Menu_MeasureItem(lParam);
+
+ case WM_DRAWITEM: //Needed by the contact's context menu
+ return Menu_DrawItem(lParam);
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == NM_AVATAR_CHANGED) {
+ BOOL newava = CallService(MS_AV_GETAVATARBITMAP, data->hContact, 0) != 0;
+ if (newava != data->haveAvatar) {
+ LONG_PTR style = GetWindowLongPtr(data->hAvt, GWL_STYLE);
+ data->haveAvatar = newava;
+ SetWindowLongPtr(data->hAvt, GWL_STYLE, newava ? (style | WS_VISIBLE) : (style & ~WS_VISIBLE));
+ RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE);
+ }
+ }
+ break;
+
+ case WM_REDRAWWIN:
+ if (data->hAvt != nullptr) MoveWindow(data->hAvt, 0, 0, opt.AvatarSize, opt.AvatarSize, TRUE);
+ RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
+ break;
+
+ case WM_PAINT:
+ {
+ RECT r, rc;
+
+ if (GetUpdateRect(hwnd, &r, FALSE)) {
+ int picSize = opt.AvatarSize;
+ HICON hIcon = nullptr;
+
+ if (!data->haveAvatar) {
+ int statusIcon = g_plugin.getWord(data->hContact, "Status");
+
+ picSize = GetSystemMetrics(SM_CXICON);
+ hIcon = Skin_LoadProtoIcon(MODULENAME, statusIcon, true);
+ if ((INT_PTR)hIcon == CALLSERVICE_NOTFOUND) {
+ picSize = GetSystemMetrics(SM_CXSMICON);
+ hIcon = Skin_LoadProtoIcon(MODULENAME, statusIcon);
+ }
+ }
+
+ LOGFONT lfnt, lfnt1;
+ COLORREF clr = g_plugin.getDword("ColorMwinFrame", GetSysColor(COLOR_3DFACE));
+ COLORREF fntc = Font_GetW(_A2W(MODULENAME), LPGENW("Frame Font"), &lfnt);
+ COLORREF fntc1 = Font_GetW(_A2W(MODULENAME), LPGENW("Frame Title Font"), &lfnt1);
+
+ ptrW tszInfo(db_get_wsa(data->hContact, WEATHERCONDITION, "WeatherInfo"));
+
+ GetClientRect(hwnd, &rc);
+
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+
+ if (ServiceExists(MS_SKIN_DRAWGLYPH)) {
+ SKINDRAWREQUEST rq;
+ memset(&rq, 0, sizeof(rq));
+ rq.hDC = hdc;
+ rq.rcDestRect = rc;
+ rq.rcClipRect = rc;
+
+ mir_strcpy(rq.szObjectID, "Main,ID=WeatherFrame");
+ CallService(MS_SKIN_DRAWGLYPH, (WPARAM)&rq, 0);
+ }
+
+ if (clr != 0xFFFFFFFF) {
+ HBRUSH hBkgBrush = CreateSolidBrush(clr);
+ FillRect(hdc, &rc, hBkgBrush);
+ DeleteObject(hBkgBrush);
+ }
+
+ if (!data->haveAvatar)
+ DrawIconEx(hdc, 1, 1, hIcon, 0, 0, 0, nullptr, DI_NORMAL);
+
+ SetBkMode(hdc, TRANSPARENT);
+
+ HFONT hfnt = CreateFontIndirect(&lfnt1);
+ HFONT hfntold = (HFONT)SelectObject(hdc, hfnt);
+
+ wchar_t *nick = Clist_GetContactDisplayName(data->hContact);
+
+ SIZE fontSize;
+ GetTextExtentPoint32(hdc, L"|", 1, &fontSize);
+
+ rc.top += 1;
+ rc.left += picSize + fontSize.cx;
+
+ SetTextColor(hdc, fntc1);
+ DrawText(hdc, nick, -1, &rc, DT_LEFT | DT_EXPANDTABS);
+
+ rc.top += fontSize.cy;
+
+ SelectObject(hdc, hfntold);
+ DeleteObject(hfnt);
+
+ if (tszInfo) {
+ HFONT hFont = CreateFontIndirect(&lfnt);
+ HFONT hFontOld = (HFONT)SelectObject(hdc, hFont);
+
+ SetTextColor(hdc, fntc);
+ DrawText(hdc, tszInfo, -1, &rc, DT_LEFT | DT_EXPANDTABS);
+
+ SelectObject(hdc, hFontOld);
+ DeleteObject(hFont);
+ }
+ EndPaint(hwnd, &ps);
+ IcoLib_ReleaseIcon(hIcon);
+ }
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return(TRUE);
+}
+
+static void addWindow(MCONTACT hContact)
+{
+ DBVARIANT dbv;
+ if (g_plugin.getWString(hContact, "Nick", &dbv))
+ return;
+
+ wchar_t winname[512];
+ mir_snwprintf(winname, L"Weather: %s", dbv.pwszVal);
+ db_free(&dbv);
+
+ HWND hWnd = CreateWindow(L"WeatherFrame", L"", WS_CHILD | WS_VISIBLE,
+ 0, 0, 10, 10, g_clistApi.hwndContactList, nullptr, g_plugin.getInst(), (void*)hContact);
+ WindowList_Add(hMwinWindowList, hWnd, hContact);
+
+ CLISTFrame Frame = { 0 };
+ Frame.szName.w = winname;
+ Frame.hIcon = LoadIconEx("main", FALSE);
+ Frame.cbSize = sizeof(Frame);
+ Frame.hWnd = hWnd;
+ Frame.align = alBottom;
+ Frame.Flags = F_VISIBLE | F_NOBORDER | F_UNICODE;
+ Frame.height = 32;
+ int frameID = g_plugin.addFrame(&Frame);
+
+ g_plugin.setDword(hContact, "mwin", frameID);
+ db_set_b(hContact, "CList", "Hidden", TRUE);
+}
+
+void removeWindow(MCONTACT hContact)
+{
+ DWORD frameId = g_plugin.getDword(hContact, "mwin");
+
+ WindowList_Remove(hMwinWindowList, WindowList_Find(hMwinWindowList, hContact));
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0);
+
+ g_plugin.setDword(hContact, "mwin", 0);
+ db_unset(hContact, "CList", "Hidden");
+}
+
+void UpdateMwinData(MCONTACT hContact)
+{
+ HWND hwnd = WindowList_Find(hMwinWindowList, hContact);
+ if (hwnd != nullptr)
+ RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
+}
+
+INT_PTR Mwin_MenuClicked(WPARAM wParam, LPARAM)
+{
+ BOOL addwnd = WindowList_Find(hMwinWindowList, wParam) == nullptr;
+ if (addwnd)
+ addWindow(wParam);
+ else
+ removeWindow(wParam);
+ return 0;
+}
+
+int BuildContactMenu(WPARAM wparam, LPARAM)
+{
+ int flags = g_plugin.getDword(wparam, "mwin") ? CMIF_CHECKED : 0;
+ Menu_ModifyItem(hMwinMenu, nullptr, INVALID_HANDLE_VALUE, flags);
+ return 0;
+}
+
+int RedrawFrame(WPARAM, LPARAM)
+{
+ WindowList_Broadcast(hMwinWindowList, WM_REDRAWWIN, 0, 0);
+ return 0;
+}
+
+void InitMwin(void)
+{
+ if (!ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ return;
+
+ hMwinWindowList = WindowList_Create();
+
+ WNDCLASS wndclass;
+ wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = wndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_plugin.getInst();
+ wndclass.hIcon = nullptr;
+ wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wndclass.hbrBackground = nullptr; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = nullptr;
+ wndclass.lpszClassName = L"WeatherFrame";
+ RegisterClass(&wndclass);
+
+ ColourIDW colourid = {};
+ mir_strcpy(colourid.dbSettingsGroup, MODULENAME);
+ mir_strcpy(colourid.setting, "ColorMwinFrame");
+ mir_wstrcpy(colourid.name, LPGENW("Frame Background"));
+ mir_wstrcpy(colourid.group, _A2W(MODULENAME));
+ colourid.defcolour = GetSysColor(COLOR_3DFACE);
+ g_plugin.addColor(&colourid);
+
+ FontIDW fontid = {};
+ fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID;
+ mir_strcpy(fontid.dbSettingsGroup, MODULENAME);
+ mir_wstrcpy(fontid.group, _A2W(MODULENAME));
+ mir_wstrcpy(fontid.name, LPGENW("Frame Font"));
+ mir_strcpy(fontid.setting, "fnt0");
+
+ HDC hdc = GetDC(nullptr);
+ fontid.deffontsettings.size = -13;
+ ReleaseDC(nullptr, hdc);
+
+ fontid.deffontsettings.charset = DEFAULT_CHARSET;
+ mir_wstrcpy(fontid.deffontsettings.szFace, L"Verdana");
+ mir_wstrcpy(fontid.backgroundGroup, _A2W(MODULENAME));
+ mir_wstrcpy(fontid.backgroundName, LPGENW("Frame Background"));
+ g_plugin.addFont(&fontid);
+
+ fontid.deffontsettings.style = DBFONTF_BOLD;
+ mir_wstrcpy(fontid.name, LPGENW("Frame Title Font"));
+ mir_strcpy(fontid.setting, "fnt1");
+ g_plugin.addFont(&fontid);
+
+ for (auto &hContact : Contacts(MODULENAME))
+ if (g_plugin.getDword(hContact, "mwin"))
+ addWindow(hContact);
+
+ hFontHook = HookEvent(ME_FONT_RELOAD, RedrawFrame);
+}
+
+void DestroyMwin(void)
+{
+ for (auto &hContact : Contacts(MODULENAME)) {
+ DWORD frameId = g_plugin.getDword(hContact, "mwin");
+ if (frameId)
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0);
+ }
+ UnregisterClass(L"WeatherFrame", g_plugin.getInst());
+ WindowList_Destroy(hMwinWindowList);
+ UnhookEvent(hFontHook);
+}