/* Quick Messages plugin for Miranda IM Copyright (C) 2008 Danil Mozhar 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 3 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, see . */ #include "stdafx.h" int g_iOPButtonsCount; BOOL bNeedRestart = FALSE; BOOL drag = FALSE, bOptionsInit = TRUE; HTREEITEM hDragItem = nullptr; HWND hButtonsList = nullptr; HWND hMenuTree = nullptr; HWND hwndEdit = nullptr; HWND g_opHdlg = nullptr, g_varhelpDlg = nullptr; INT_PTR CALLBACK HelpDlgProc(HWND hdlg, UINT msg, WPARAM, LPARAM lparam) { switch (msg) { case WM_INITDIALOG: { LOGFONT logFont; HFONT hFont; RECT rc; g_varhelpDlg = hdlg; TranslateDialogDefault(hdlg); hFont = (HFONT)SendDlgItemMessage(hdlg, IDC_STATICTITLE, WM_GETFONT, 0, 0); GetObject(hFont, sizeof logFont, &logFont); logFont.lfWeight = FW_BOLD; hFont = CreateFontIndirect(&logFont); SendDlgItemMessage(hdlg, IDC_STATICTITLE, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_STATICTITLE2, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_VARTEXT, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_VARCLIP, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_VARPUNAME, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_VARPLNAME, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_VARCNAME, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_VARCFNAME, WM_SETFONT, (WPARAM)hFont, 0); SendDlgItemMessage(hdlg, IDC_VARCLNAME, WM_SETFONT, (WPARAM)hFont, 0); GetWindowRect(g_opHdlg, &rc); SetWindowPos(hdlg, nullptr, rc.left, rc.top, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE); } break; case WM_LBUTTONDOWN: PostMessage(hdlg, WM_NCLBUTTONDOWN, HTCAPTION, lparam); break; case WM_CLOSE: case WM_DESTROY: DestroyWindow(g_varhelpDlg); g_varhelpDlg = nullptr; break; default: return FALSE; } return TRUE; } static LRESULT CALLBACK LabelEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_GETDLGCODE: return DLGC_WANTALLKEYS; } return mir_callNextSubclass(hwnd, LabelEditSubclassProc, msg, wParam, lParam); } static LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HWND hParent = GetParent(hwnd); switch (msg) { case WM_GETDLGCODE: return DLGC_WANTALLKEYS | DLGC_HASSETSEL; case WM_SETFOCUS: PostMessage(hwnd, EM_SETSEL, 0, -1); break; case WM_KEYDOWN: if (wParam == VK_RETURN) { if (hwnd == GetDlgItem(hParent, IDC_BUTTONNAME)) SendMessage(hParent, WM_COMMAND, IDC_BLISTADD, 0); else SendMessage(hParent, WM_COMMAND, IDC_MTREEADD, 0); } break; } return mir_callNextSubclass(hwnd, EditSubclassProc, msg, wParam, lParam); } void SetMenuEntryProperties(HWND hdlg) { TVITEM tvi; HTREEITEM hItem = nullptr; int pos = 0; if (TreeView_GetCount(hButtonsList) && (tvi.hItem = TreeView_GetSelection(hButtonsList))) { tvi.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem(hButtonsList, &tvi); if (tvi.lParam) { ListData* ld = (ListData*)tvi.lParam; wchar_t szValue[256]; GetDlgItemText(hdlg, IDC_RCLICKVALUE, szValue, _countof(szValue)); if (mir_wstrlen(szValue)) { if (ld->ptszOPQValue && (ld->ptszOPQValue != ld->ptszQValue)) mir_free(ld->ptszOPQValue); ld->ptszOPQValue = mir_wstrdup(szValue); } ld->bIsOpServName = IsDlgButtonChecked(hdlg, IDC_ISSERVNAME2); } } tvi.hItem = nullptr; if (TreeView_GetCount(hMenuTree) && (tvi.hItem = TreeView_GetSelection(hMenuTree))) { tvi.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem(hMenuTree, &tvi); if (tvi.lParam) { ButtonData *bd = (ButtonData*)tvi.lParam; wchar_t szValue[256]; GetDlgItemText(hdlg, IDC_MENUVALUE, szValue, _countof(szValue)); if (mir_wstrlen(szValue)) { if (mir_wstrlen(bd->pszOpValue) && (bd->pszOpValue != bd->pszValue)) mir_free(bd->pszOpValue); bd->pszOpValue = mir_wstrdup(szValue); } bd->bOpInQMenu = IsDlgButtonChecked(hdlg, IDC_INQMENU); bd->bIsOpServName = IsDlgButtonChecked(hdlg, IDC_ISSERVNAME); } tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = TreeView_GetRoot(hMenuTree); } while (tvi.hItem) { TreeView_GetItem(hMenuTree, &tvi); ButtonData *bd = (ButtonData*)tvi.lParam; bd->dwOPPos = pos++; if (hItem = TreeView_GetChild(hMenuTree, tvi.hItem)) { bd->fEntryOpType &= ~QMF_EX_CHILD; if (bd->pszOpValue) { mir_free(bd->pszOpValue); bd->pszOpValue = nullptr; } tvi.hItem = hItem; continue; } else { if (bd->fEntryOpType&QMF_EX_SEPARATOR) { if (bd->pszOpValue) { mir_free(bd->pszOpValue); bd->pszOpValue = nullptr; } } else { if (!bd->pszOpValue) bd->pszOpValue = mir_wstrdup(LPGENW("Enter Value")); } if (TreeView_GetParent(hMenuTree, tvi.hItem)) bd->fEntryOpType |= QMF_EX_CHILD; else bd->fEntryOpType &= ~QMF_EX_CHILD; if (!(hItem = TreeView_GetNextSibling(hMenuTree, tvi.hItem))) tvi.hItem = TreeView_GetNextSibling(hMenuTree, TreeView_GetParent(hMenuTree, tvi.hItem)); else tvi.hItem = hItem; } } } void SaveMenuTree() { int iBl = 0, i = 0, k = 0; int iBtd = g_iButtonsCount; BOOL bDeleted = FALSE; char szMEntry[256] = { '\0' }; wchar_t strbuf[256]; HTREEITEM hti = nullptr; TVITEM tvi; g_iButtonsCount = TreeView_GetCount(hButtonsList); tvi.pszText = strbuf; tvi.cchTextMax = _countof(strbuf); tvi.mask = TVIF_HANDLE | TVIF_TEXT; tvi.hItem = TreeView_GetRoot(hButtonsList); TreeView_GetItem(hButtonsList, &tvi); li_ZeroQuickList(QuickList); BalanceButtons(iBtd, g_iButtonsCount); while (ButtonsList[iBl]) { SortedList * sl = nullptr; ListData* ld = ButtonsList[iBl]; if (!ld->sl) break; sl = ld->sl; if (ld->dwOPFlags&QMF_DELETNEEDED) { bDeleted = (ld->dwOPFlags&QMF_NEW) ? FALSE : TRUE; if (bDeleted) CleanSettings(ld->dwPos, -1); DestroyButton(iBl); continue; } if (ld->ptszQValue != ld->ptszOPQValue) { if (ld->ptszQValue) mir_free(ld->ptszQValue); ld->ptszQValue = (ld->ptszOPQValue) ? ld->ptszOPQValue : nullptr; } if (ld->ptszButtonName) mir_free(ld->ptszButtonName); if (iBl > 0) if (hti = TreeView_GetNextSibling(hButtonsList, hti ? hti : tvi.hItem)) { tvi.hItem = hti; TreeView_GetItem(hButtonsList, &tvi); } ld->ptszButtonName = mir_wstrdup(tvi.pszText); if (ld->ptszQValue) { mir_snprintf(szMEntry, "ButtonValue_%u", iBl); db_set_ws(NULL, PLGNAME, szMEntry, ld->ptszQValue); } if (((ld->dwOPFlags & QMF_NEW) || (ld->dwOPFlags & QMF_RENAMED) || bDeleted)) { BBButton bb = {}; bb.pszModuleName = PLGNAME; bb.dwButtonID = iBl; bb.pwszTooltip = ld->ptszButtonName; Srmm_ModifyButton(&bb); } mir_snprintf(szMEntry, "ButtonName_%u", iBl); db_set_ws(NULL, PLGNAME, szMEntry, ld->ptszButtonName); ld->dwOPFlags = 0; ld->dwPos = iBl; ld->bIsServName = ld->bIsOpServName; mir_snprintf(szMEntry, "RCEntryIsServiceName_%u", iBl); db_set_b(NULL, PLGNAME, szMEntry, ld->bIsServName); bDeleted = FALSE; qsort(sl->items, sl->realCount, sizeof(ButtonData *), sstSortButtons); for (i = 0; i < sl->realCount; i++) { ButtonData * bd = (ButtonData *)sl->items[i]; if (bd->dwOPFlags & QMF_DELETNEEDED) { RemoveMenuEntryNode(sl, i--); continue; } bd->bIsServName = bd->bIsOpServName; bd->bInQMenu = bd->bOpInQMenu; bd->dwPos = bd->dwOPPos; bd->fEntryType = bd->fEntryOpType; bd->dwOPFlags = 0; if (bd->pszName != bd->pszOpName) { if (bd->pszName) mir_free(bd->pszName); bd->pszName = bd->pszOpName ? bd->pszOpName : nullptr; } if (bd->pszValue != bd->pszOpValue) { if (bd->pszValue) mir_free(bd->pszValue); bd->pszValue = bd->pszOpValue ? bd->pszOpValue : nullptr; } if (bd->bInQMenu) { QuickData* qd = (QuickData *)mir_alloc(sizeof(QuickData)); qd->dwPos = k++; qd->fEntryType = bd->fEntryType; qd->bIsService = bd->bIsServName; qd->ptszValue = bd->pszValue; qd->ptszValueName = bd->pszName; List_InsertPtr(QuickList, qd); } SaveModuleSettings(iBl, bd); } CleanSettings(iBl, sl->realCount); iBl++; } db_set_b(NULL, PLGNAME, "ButtonsCount", (BYTE)g_iButtonsCount); } void RestoreModuleData() { int iBl = 0, i = 0; while (ButtonsList[iBl]) { SortedList * sl = nullptr; ListData* ld = ButtonsList[iBl]; if (!(sl = ld->sl)) break; if (ld->dwOPFlags&QMF_NEW) { DestroyButton(iBl); continue; } if (ld->ptszQValue != ld->ptszOPQValue) { if (ld->ptszOPQValue) mir_free(ld->ptszOPQValue); ld->ptszOPQValue = (ld->ptszQValue) ? ld->ptszQValue : nullptr; } ld->bIsOpServName = ld->bIsServName; ld->dwOPFlags = 0; qsort(sl->items, sl->realCount, sizeof(ButtonData *), sstSortButtons); for (i = 0; i < sl->realCount; i++) { ButtonData *bd = (ButtonData *)sl->items[i]; if (bd->dwOPFlags & QMF_NEW) { RemoveMenuEntryNode(sl, i--); continue; } bd->bIsOpServName = bd->bIsServName; bd->bOpInQMenu = bd->bInQMenu; bd->dwOPPos = bd->dwPos; bd->fEntryOpType = bd->fEntryType; bd->dwOPFlags = 0; if (bd->pszName != bd->pszOpName) { if (bd->pszOpName) mir_free(bd->pszOpName); bd->pszOpName = bd->pszName ? bd->pszName : nullptr; } if (bd->pszValue != bd->pszOpValue) { if (bd->pszOpValue) mir_free(bd->pszOpValue); bd->pszOpValue = bd->pszValue ? bd->pszValue : nullptr; } } iBl++; } } static int BuildMenuTree(HWND hToolBarTree, SortedList * sl) { TVINSERTSTRUCT tvis; int i; HTREEITEM hParent = nullptr; tvis.hParent = nullptr; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = TVIF_PARAM | TVIF_TEXT; TreeView_DeleteAllItems(hToolBarTree); if (!sl) return 1; qsort(sl->items, sl->realCount, sizeof(ButtonData *), sstOpSortButtons); for (i = 0; i < sl->realCount; i++) { ButtonData * bd = (ButtonData *)sl->items[i]; if (bd->dwOPFlags & QMF_DELETNEEDED) continue; tvis.item.lParam = (LPARAM)bd; tvis.item.pszText = bd->pszOpName; if (bd->fEntryOpType == 0) tvis.hParent = nullptr; hParent = TreeView_InsertItem(hToolBarTree, &tvis); if (tvis.hParent) TreeView_Expand(hMenuTree, tvis.hParent, TVE_EXPAND); if (!bd->pszOpValue&&bd->fEntryOpType == 0) tvis.hParent = hParent; } return 1; } static int BuildButtonsList(HWND hToolBarTree) { TVINSERTSTRUCT tvis; int i = 0; tvis.hParent = nullptr; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = TVIF_PARAM | TVIF_TEXT; TreeView_DeleteAllItems(hToolBarTree); //for(i=0;iptszButtonName; TreeView_InsertItem(hToolBarTree, &tvis); i++; } return 1; } /////////////////////////////////// //From UserInfoEx by DeathAxe // void MoveItem(HTREEITEM hItem, HTREEITEM hInsertAfter, BOOLEAN bAsChild) { TVINSERTSTRUCT tvis; //wchar_t strbuf[128]; HTREEITEM hParent, hChild, hNewItem; if (!hItem || !hInsertAfter) return; if (hItem == hInsertAfter) return; switch ((ULONG_PTR)hInsertAfter) { case TVI_ROOT: case TVI_FIRST: case TVI_LAST: hParent = NULL; bAsChild = FALSE; break; default: hParent = TreeView_GetParent(hMenuTree, hInsertAfter); break; } // do not move a parent next to its own children! if (hItem == hParent) return; // prepare the insert structure { wchar_t strbuf[128]; tvis.item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT; tvis.item.pszText = strbuf; tvis.item.cchTextMax = _countof(strbuf); tvis.item.hItem = hItem; TreeView_GetItem(hMenuTree, &tvis.item); } // item should be inserted as the first child of an existing root item if (bAsChild) { tvis.hParent = hInsertAfter; tvis.hInsertAfter = (bAsChild == 2) ? TVI_LAST : TVI_FIRST; } // item should be inserted after an existing item else { tvis.hParent = hParent; tvis.hInsertAfter = hInsertAfter; } // insert the item if (!(hNewItem = TreeView_InsertItem(hMenuTree, &tvis))) return; // move children hInsertAfter = hNewItem; while (hChild = TreeView_GetChild(hMenuTree, hItem)) { MoveItem(hChild, hInsertAfter, 2); } // delete old tree TreeView_DeleteItem(hMenuTree, hItem); TreeView_SelectItem(hMenuTree, hNewItem); //TreeView_Expand( hMenuTree, hNewItem, TVE_EXPAND ); } /////// INT_PTR CALLBACK OptionsProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_INITDIALOG: { DWORD style; g_opHdlg = hdlg; bOptionsInit = TRUE; TranslateDialogDefault(hdlg); if (g_iButtonsCount != db_get_b(NULL, PLGNAME, "ButtonsCount", 0)) { LOGFONT logFont; HFONT hFont; bNeedRestart = TRUE; EnableWindow(GetDlgItem(hdlg, IDC_BUTTONSLIST), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_BLISTADD), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_BLISTREMOVE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_MENUTREE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_MTREEADD), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_MTREEREMOVE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_RCLICKVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_BUTTONNAME), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_INQMENU), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_MENUNAME), FALSE); ShowWindow(GetDlgItem(hdlg, IDC_WARNING), SW_SHOW); hFont = (HFONT)SendDlgItemMessage(hdlg, IDC_WARNING, WM_GETFONT, 0, 0); GetObject(hFont, sizeof(logFont), &logFont); logFont.lfWeight = FW_BOLD; hFont = CreateFontIndirect(&logFont); SendDlgItemMessage(hdlg, IDC_WARNING, WM_SETFONT, (WPARAM)hFont, 0); break; } g_iOPButtonsCount = g_iButtonsCount; hButtonsList = GetDlgItem(hdlg, IDC_BUTTONSLIST); hMenuTree = GetDlgItem(hdlg, IDC_MENUTREE); style = GetWindowLongPtr(hButtonsList, GWL_STYLE); style |= TVS_NOHSCROLL; SetWindowLongPtr(hButtonsList, GWL_STYLE, style); style = GetWindowLongPtr(hMenuTree, GWL_STYLE); style |= TVS_NOHSCROLL; SetWindowLongPtr(hMenuTree, GWL_STYLE, style); BuildButtonsList(hButtonsList); if (!TreeView_GetCount(hButtonsList)) EnableWindow(GetDlgItem(hdlg, IDC_RCLICKVALUE), FALSE); mir_subclassWindow(GetDlgItem(hdlg, IDC_BUTTONNAME), EditSubclassProc); mir_subclassWindow(GetDlgItem(hdlg, IDC_MENUNAME), EditSubclassProc); EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_INQMENU), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), FALSE); CheckDlgButton(hdlg, IDC_RAUTOSEND, (g_bRClickAuto = db_get_b(NULL, PLGNAME, "RClickAuto", 0)) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hdlg, IDC_LAUTOSEND, (g_bLClickAuto = db_get_b(NULL, PLGNAME, "LClickAuto", 0)) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hdlg, IDC_ENABLEQUICKMENU, (g_bQuickMenu = db_get_b(NULL, PLGNAME, "QuickMenu", 1)) ? BST_CHECKED : BST_UNCHECKED); bOptionsInit = FALSE; }break; case WM_LBUTTONUP: if (drag) { TVHITTESTINFO hti; HTREEITEM htiAfter = nullptr; ButtonData* bd = nullptr; TVITEM tvi; RECT rc; BYTE height; BOOLEAN bAsChild = FALSE; TreeView_SetInsertMark(hMenuTree, NULL, 0); ReleaseCapture(); SetCursor(LoadCursor(nullptr, IDC_ARROW)); hti.pt.x = (SHORT)LOWORD(lparam); hti.pt.y = (SHORT)HIWORD(lparam); ClientToScreen(hdlg, &hti.pt); ScreenToClient(hMenuTree, &hti.pt); TreeView_HitTest(hMenuTree, &hti); if (TreeView_GetParent(hMenuTree, hti.hItem) && TreeView_GetChild(hMenuTree, hDragItem)) break; if (TreeView_GetChild(hMenuTree, hti.hItem) && TreeView_GetChild(hMenuTree, hDragItem)) break; if (hti.flags & TVHT_ABOVE) { htiAfter = TVI_FIRST; } else if (hti.flags & (TVHT_NOWHERE | TVHT_BELOW)) { htiAfter = TVI_LAST; } else if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) { // check where over the item, the pointer is if (!TreeView_GetItemRect(hMenuTree, hti.hItem, &rc, FALSE)) { drag = 0; break; } height = (BYTE)(rc.bottom - rc.top); if (hti.pt.y - (height / 3) < rc.top) { HTREEITEM hItem = hti.hItem; if (!(hti.hItem = TreeView_GetPrevSibling(hMenuTree, hItem))) { if (!(hti.hItem = TreeView_GetParent(hMenuTree, hItem))) htiAfter = TVI_FIRST; else bAsChild = TRUE; } } else if (hti.pt.y + (height / 3) <= rc.bottom) { bAsChild = TRUE; } } if (TreeView_GetChild(hMenuTree, hDragItem) && bAsChild) break; if (hti.hItem) { tvi.hItem = hti.hItem; tvi.mask = TVIF_PARAM | TVIF_HANDLE; TreeView_GetItem(hMenuTree, &tvi); if ((bd = (ButtonData*)tvi.lParam) && (bd->fEntryOpType&QMF_EX_SEPARATOR)) bAsChild = FALSE; } if (TreeView_GetParent(hMenuTree, hti.hItem)) bAsChild = FALSE; MoveItem(hDragItem, htiAfter ? htiAfter : hti.hItem, bAsChild); SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); drag = 0; } break; case WM_MOUSEMOVE: if (!drag) break; { TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(lparam); hti.pt.y = (short)HIWORD(lparam); ClientToScreen(hdlg, &hti.pt); ScreenToClient(hMenuTree, &hti.pt); TreeView_HitTest(hMenuTree, &hti); if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) { RECT rc; if (TreeView_GetItemRect(hMenuTree, hti.hItem, &rc, FALSE)) { BYTE height = (BYTE)(rc.bottom - rc.top); if (hti.pt.y - (height / 3) < rc.top) { SetCursor(LoadCursor(nullptr, IDC_ARROW)); TreeView_SetInsertMark(hMenuTree, hti.hItem, 0); } else if (hti.pt.y + (height / 3) > rc.bottom) { SetCursor(LoadCursor(nullptr, IDC_ARROW)); TreeView_SetInsertMark(hMenuTree, hti.hItem, 1); } else { TreeView_SetInsertMark(hMenuTree, NULL, 0); SetCursor(LoadCursor(GetModuleHandle(nullptr), MAKEINTRESOURCE(183))); } } } else { if (hti.flags & TVHT_ABOVE) SendMessage(hMenuTree, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); if (hti.flags & TVHT_BELOW) SendMessage(hMenuTree, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); TreeView_SetInsertMark(hMenuTree, NULL, 0); } } break; case WM_DESTROY: if (g_varhelpDlg) DestroyWindow(g_varhelpDlg); g_varhelpDlg = nullptr; break; case WM_NOTIFY: switch (((LPNMHDR)lparam)->idFrom) { case 0: if (((LPNMHDR)lparam)->code == PSN_APPLY) { if (!bNeedRestart) { SetMenuEntryProperties(hdlg); SaveMenuTree(); } db_set_b(NULL, PLGNAME, "RClickAuto", (BYTE)(g_bRClickAuto = IsDlgButtonChecked(hdlg, IDC_RAUTOSEND))); db_set_b(NULL, PLGNAME, "LClickAuto", (BYTE)(g_bLClickAuto = IsDlgButtonChecked(hdlg, IDC_LAUTOSEND))); db_set_b(NULL, PLGNAME, "QuickMenu", (BYTE)(g_bQuickMenu = IsDlgButtonChecked(hdlg, IDC_ENABLEQUICKMENU))); return 1; } else if (((LPNMHDR)lparam)->code == PSN_RESET) { if (!bNeedRestart) RestoreModuleData(); return 1; } break; case IDC_MENUTREE: switch (((LPNMHDR)lparam)->code) { case TVN_KEYDOWN: { TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)((LPNMHDR)lparam); if (pTVKeyDown->wVKey == VK_F2) TreeView_EditLabel(hMenuTree, TreeView_GetSelection(hMenuTree)); else if (pTVKeyDown->wVKey == VK_DELETE) SendMessage(hdlg, WM_COMMAND, IDC_MTREEREMOVE, 0); }break; case TVN_BEGINLABELEDIT: hwndEdit = TreeView_GetEditControl(hMenuTree); mir_subclassWindow(hwndEdit, LabelEditSubclassProc); break; case TVN_ENDLABELEDIT: { TVITEM tvi; ButtonData* bd = nullptr; wchar_t strbuf[256]; wchar_t szLabel[256]; tvi.pszText = strbuf; tvi.cchTextMax = _countof(strbuf); tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM; tvi.hItem = TreeView_GetSelection(hMenuTree); TreeView_GetItem(hMenuTree, &tvi); GetWindowText(hwndEdit, szLabel, _countof(szLabel)); hwndEdit = nullptr; if (!mir_wstrlen(szLabel)) break; if (bd = (ButtonData*)tvi.lParam) { if (!mir_wstrcmp(szLabel, L"---")) { if (TreeView_GetChild(hMenuTree, tvi.hItem)) break; else { bd->fEntryOpType = QMF_EX_SEPARATOR; EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), FALSE); SetDlgItemText(hdlg, IDC_MENUVALUE, L""); } } else { bd->fEntryOpType &= ~QMF_EX_SEPARATOR; EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), TRUE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), TRUE); SetDlgItemText(hdlg, IDC_MENUVALUE, bd->pszOpValue/*?bd->pszOpValue:bd->pszValue*/); } bd->pszOpName = mir_wstrdup(szLabel); tvi.pszText = szLabel; TreeView_SetItem(hMenuTree, &tvi); SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); } } break; case NM_KILLFOCUS: TreeView_EndEditLabelNow(hButtonsList, 1); break; case TVN_BEGINDRAG: SetCapture(hdlg); drag = 1; hDragItem = ((LPNMTREEVIEW)lparam)->itemNew.hItem; TreeView_SelectItem(hMenuTree, hDragItem); break; case TVN_SELCHANGING: { HTREEITEM hti = TreeView_GetSelection(hMenuTree); if (hti == nullptr) break; TVITEM tvi; tvi.hItem = hti; tvi.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem(hMenuTree, &tvi); if (tvi.lParam == 0) break; ButtonData *bd = (ButtonData*)tvi.lParam; if (bd) { wchar_t szValue[256]; GetDlgItemText(hdlg, IDC_MENUVALUE, szValue, _countof(szValue)); if (mir_wstrlen(szValue)) { if (bd->pszOpValue && (bd->pszOpValue != bd->pszValue)) mir_free(bd->pszOpValue); bd->pszOpValue = mir_wstrdup(szValue); } bd->bOpInQMenu = IsDlgButtonChecked(hdlg, IDC_INQMENU); bd->bIsOpServName = IsDlgButtonChecked(hdlg, IDC_ISSERVNAME); } } break; case TVN_SELCHANGED: { HTREEITEM hti = TreeView_GetSelection(hMenuTree); if (hti == nullptr) break; TVITEM tvi; tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = hti; TreeView_GetItem(hMenuTree, &tvi); ButtonData *bd = (ButtonData*)tvi.lParam; if (bd) { if (!TreeView_GetChild(hMenuTree, tvi.hItem) && !(bd->fEntryOpType&QMF_EX_SEPARATOR)) { EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), TRUE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), TRUE); EnableWindow(GetDlgItem(hdlg, IDC_INQMENU), TRUE); SetDlgItemText(hdlg, IDC_MENUVALUE, bd->pszOpValue/*?bd->pszOpValue:bd->pszValue*/); } else { EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), FALSE); if (!(bd->fEntryOpType&QMF_EX_SEPARATOR)) EnableWindow(GetDlgItem(hdlg, IDC_INQMENU), FALSE); SetDlgItemText(hdlg, IDC_MENUVALUE, L""); } CheckDlgButton(hdlg, IDC_INQMENU, bd->bOpInQMenu ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hdlg, IDC_ISSERVNAME, bd->bIsOpServName ? BST_CHECKED : BST_UNCHECKED); } } } break; case IDC_BUTTONSLIST: switch (((LPNMHDR)lparam)->code) { case TVN_KEYDOWN: { TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)((LPNMHDR)lparam); if (pTVKeyDown->wVKey == VK_F2) TreeView_EditLabel(hButtonsList, TreeView_GetSelection(hButtonsList)); else if (pTVKeyDown->wVKey == VK_DELETE) SendMessage(hdlg, WM_COMMAND, IDC_BLISTREMOVE, 0); }break; case TVN_BEGINLABELEDIT: hwndEdit = TreeView_GetEditControl(hButtonsList); mir_subclassWindow(hwndEdit, LabelEditSubclassProc); break; case TVN_ENDLABELEDIT: { TVITEM tvi; wchar_t strbuf[128]; wchar_t szLabel[128]; tvi.pszText = strbuf; tvi.cchTextMax = _countof(strbuf); tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM; tvi.hItem = TreeView_GetSelection(hButtonsList); TreeView_GetItem(hButtonsList, &tvi); GetWindowText(hwndEdit, szLabel, _countof(szLabel)); hwndEdit = nullptr; if (!mir_wstrlen(szLabel)) break; tvi.pszText = szLabel; ((ListData*)tvi.lParam)->dwOPFlags |= QMF_RENAMED; TreeView_SetItem(hButtonsList, &tvi); SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); } break; case TVN_SELCHANGING: SetMenuEntryProperties(hdlg); break; case TVN_SELCHANGED: { HTREEITEM hti = TreeView_GetSelection(hButtonsList); if (hti == nullptr || !TreeView_GetCount(hButtonsList)) { EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_INQMENU), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME2), FALSE); SetDlgItemText(hdlg, IDC_MENUVALUE, L""); break; } TVITEM tvi; tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = hti; TreeView_GetItem(hButtonsList, &tvi); if (tvi.lParam == 0) break; BuildMenuTree(hMenuTree, (SortedList *)((ListData*)tvi.lParam)->sl); SetDlgItemText(hdlg, IDC_MENUVALUE, L""); EnableWindow(GetDlgItem(hdlg, IDC_RCLICKVALUE), TRUE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME2), TRUE); CheckDlgButton(hdlg, IDC_ISSERVNAME2, ((ListData*)tvi.lParam)->bIsOpServName ? BST_CHECKED : BST_UNCHECKED); if (((ListData*)tvi.lParam)->ptszOPQValue) SetDlgItemText(hdlg, IDC_RCLICKVALUE, ((ListData*)tvi.lParam)->ptszOPQValue); else SetDlgItemText(hdlg, IDC_RCLICKVALUE, L""); } break; } break; } break; case WM_COMMAND: switch (LOWORD(wparam)) { case IDC_VARHELP: if (!g_varhelpDlg) g_varhelpDlg = CreateDialog(hinstance, MAKEINTRESOURCE(IDD_HELPDIALOG), nullptr, HelpDlgProc); else //ShowWindow(g_varhelpDlg,SW_SHOWDEFAULT); SetWindowPos(g_varhelpDlg, nullptr, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); break; case IDC_BLISTADD: { TVINSERTSTRUCT tvis; ListData* ld = nullptr; wchar_t namebuff[MAX_PATH] = { '\0' }; int count = TreeView_GetCount(hButtonsList); if (count > 10) break; if (g_iOPButtonsCount == 99) { MessageBox(nullptr, TranslateT("Congratulation!\r\nYou have clicked this button 100 times!\r\nThere was access violation at this point...\r\nAnd now function for freeing resources must be called...\r\nBut no! there's only break :D"), TranslateT("You win!"), MB_OK); break; } ld = (ListData *)mir_alloc(sizeof(ListData)); ButtonsList[g_iOPButtonsCount++] = ld; ld->sl = List_Create(0, 1); ld->dwOPFlags = QMF_NEW; ld->bIsOpServName = 0; ld->ptszButtonName = nullptr; ld->ptszOPQValue = nullptr; ld->ptszQValue = nullptr; tvis.hParent = nullptr; tvis.hInsertAfter = TVI_LAST; GetDlgItemText(hdlg, IDC_BUTTONNAME, namebuff, _countof(namebuff)); tvis.item.mask = TVIF_PARAM | TVIF_TEXT; tvis.item.pszText = (mir_wstrlen(namebuff)) ? namebuff : TranslateT("New Button"); tvis.item.lParam = (LPARAM)ld; TreeView_SelectItem(hButtonsList, TreeView_InsertItem(hButtonsList, &tvis)); }break; case IDC_BLISTREMOVE: { TVITEM tvi; ListData* ld; if (!(tvi.hItem = TreeView_GetSelection(hButtonsList))) break; tvi.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem(hButtonsList, &tvi); ld = (ListData*)tvi.lParam; ld->dwOPFlags |= QMF_DELETNEEDED; TreeView_DeleteItem(hButtonsList, tvi.hItem); if (!TreeView_GetCount(hButtonsList)) { TreeView_DeleteAllItems(hMenuTree); EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_RCLICKVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_INQMENU), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME2), FALSE); SetDlgItemText(hdlg, IDC_MENUVALUE, L""); SetDlgItemText(hdlg, IDC_RCLICKVALUE, L""); } }break; case IDC_MTREEADD: { TVINSERTSTRUCT tvis; TVITEM tvi; ButtonData *bd = nullptr; SortedList *sl = nullptr; wchar_t namebuff[MAX_PATH] = { '\0' }; if (!TreeView_GetCount(hButtonsList)) break; if (!(tvi.hItem = TreeView_GetSelection(hButtonsList))) break; bd = (ButtonData *)mir_alloc(sizeof(ButtonData)); memset(bd, 0, sizeof(ButtonData)); GetDlgItemText(hdlg, IDC_MENUNAME, namebuff, _countof(namebuff)); bd->dwOPPos = TreeView_GetCount(hMenuTree) - 1; bd->pszOpName = mir_wstrlen(namebuff) ? mir_wstrdup(namebuff) : mir_wstrdup(TranslateT("New Menu Entry")); bd->pszOpValue = mir_wstrdup(bd->pszOpName); bd->fEntryOpType = !mir_wstrcmp(namebuff, L"---") ? QMF_EX_SEPARATOR : 0; bd->dwOPFlags = QMF_NEW; bd->pszName = nullptr; bd->pszValue = nullptr; tvi.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem(hButtonsList, &tvi); sl = ((ListData*)tvi.lParam)->sl; List_InsertPtr(sl, bd); tvis.hParent = nullptr; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = TVIF_PARAM | TVIF_TEXT; tvis.item.pszText = bd->pszOpName; tvis.item.lParam = (LPARAM)bd; TreeView_SelectItem(hMenuTree, TreeView_InsertItem(hMenuTree, &tvis)); }break; case IDC_MTREEREMOVE: { TVITEM tvi; TVINSERTSTRUCT tvis; HTREEITEM hti = nullptr; ButtonData *bd = nullptr; tvi.mask = TVIF_HANDLE | TVIF_PARAM; if (!(tvi.hItem = TreeView_GetSelection(hMenuTree))) break; TreeView_GetItem(hMenuTree, &tvi); hti = tvi.hItem; bd = (ButtonData*)tvi.lParam; bd->dwOPFlags |= QMF_DELETNEEDED; if (tvi.hItem = TreeView_GetChild(hMenuTree, tvi.hItem)) { wchar_t strbuf[128]; while (tvi.hItem) { tvis.hInsertAfter = hti; tvi.pszText = strbuf; tvi.cchTextMax = _countof(strbuf); tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT; TreeView_GetItem(hMenuTree, &tvi); tvis.hParent = nullptr; tvis.item = tvi; TreeView_InsertItem(hMenuTree, &tvis); tvi.hItem = TreeView_GetNextSibling(hMenuTree, tvi.hItem); } } TreeView_DeleteItem(hMenuTree, hti); if (!TreeView_GetCount(hMenuTree)) { EnableWindow(GetDlgItem(hdlg, IDC_MENUVALUE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ISSERVNAME), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_INQMENU), FALSE); SetDlgItemText(hdlg, IDC_MENUVALUE, L""); } }break; } break; case WM_CLOSE: EndDialog(hdlg, 0); return 0; } if (HIWORD(wparam) == BN_CLICKED && GetFocus() == (HWND)lparam) SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); else if ((HIWORD(wparam) == EN_CHANGE) && (GetFocus() == (HWND)lparam)) if (!bOptionsInit) SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); return 0; } int OptionsInit(WPARAM wparam, LPARAM) { OPTIONSDIALOGPAGE odp = { 0 }; odp.position = 940000000; odp.hInstance = hinstance; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); odp.szTitle.a = LPGEN("Quick Messages"); odp.pfnDlgProc = OptionsProc; odp.szGroup.a = LPGEN("Message sessions"); odp.flags = ODPF_BOLDGROUPS; Options_AddPage(wparam, &odp); return 0; }