/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2010 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. 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 "..\..\core\commonheaders.h" #include "genmenu.h" #define STR_SEPARATOR _T("-----------------------------------") extern bool bIconsDisabled; extern int DefaultImageListColorDepth; long handleCustomDraw(HWND hWndTreeView, LPNMTVCUSTOMDRAW pNMTVCD); void RebuildProtoMenus(int); struct OrderData { int dragging; HTREEITEM hDragItem; int iInitMenuValue; }; typedef struct tagMenuItemOptData { TCHAR* name; TCHAR* defname; char* uniqname; int pos; boolean show; DWORD isSelected; int id; PMO_IntMenuItem pimi; } MenuItemOptData, *lpMenuItemOptData; static BOOL GetCurrentMenuObjectID(HWND hwndDlg, int* result) { TVITEM tvi; HWND hTree = GetDlgItem(hwndDlg, IDC_MENUOBJECTS); HTREEITEM hti = TreeView_GetSelection(hTree); if (hti == NULL) return FALSE; tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = hti; TreeView_GetItem(hTree, &tvi); *result = (int)tvi.lParam; return TRUE; } static int SaveTree(HWND hwndDlg) { TVITEM tvi; int count; TCHAR idstr[100]; char menuItemName[256], DBString[256], MenuNameItems[256]; int menupos; int MenuObjectId, runtimepos; TIntMenuObject* pimo; MenuItemOptData* iod; HWND hTree = GetDlgItem(hwndDlg, IDC_MENUITEMS); if ( !GetCurrentMenuObjectID(hwndDlg, &MenuObjectId)) return 0; tvi.hItem = TreeView_GetRoot(hTree); tvi.cchTextMax = 99; tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE; tvi.pszText = idstr; count = 0; menupos = GetMenuObjbyId(MenuObjectId); if (menupos == -1) return -1; pimo = g_menus[menupos]; mir_snprintf(MenuNameItems, sizeof(MenuNameItems), "%s_Items", pimo->Name); runtimepos = 100; while (tvi.hItem != NULL) { TreeView_GetItem(hTree, &tvi); iod = (MenuItemOptData*)tvi.lParam; if (iod->pimi) { GetMenuItemName(iod->pimi, menuItemName, sizeof(menuItemName)); mir_snprintf(DBString, SIZEOF(DBString), "%s_visible", menuItemName); DBWriteContactSettingByte(NULL, MenuNameItems, DBString, iod->show); mir_snprintf(DBString, SIZEOF(DBString), "%s_pos", menuItemName); DBWriteContactSettingDword(NULL, MenuNameItems, DBString, runtimepos); mir_snprintf(DBString, SIZEOF(DBString), "%s_name", menuItemName); if (lstrcmp(iod->name, iod->defname) != 0) DBWriteContactSettingTString(NULL, MenuNameItems, DBString, iod->name); else DBDeleteContactSetting(NULL, MenuNameItems, DBString); runtimepos += 100; } if (iod->name && !_tcscmp(iod->name, STR_SEPARATOR) && iod->show) runtimepos += SEPARATORPOSITIONINTERVAL; tvi.hItem = TreeView_GetNextSibling(hTree, tvi.hItem); count++; } return 1; } static int BuildMenuObjectsTree(HWND hwndDlg) { TVINSERTSTRUCT tvis; HWND hTree = GetDlgItem(hwndDlg, IDC_MENUOBJECTS); int i; tvis.hParent = NULL; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; TreeView_DeleteAllItems(hTree); if (g_menus.getCount() == 0) return FALSE; for (i=0; i < g_menus.getCount(); i++) { if (g_menus[i]->id == (int)hStatusMenuObject || !g_menus[i]->m_bUseUserDefinedItems) continue; tvis.item.lParam = (LPARAM)g_menus[i]->id; tvis.item.pszText = Langpack_PcharToTchar(g_menus[i]->Name); tvis.item.iImage = tvis.item.iSelectedImage = TRUE; TreeView_InsertItem(hTree, &tvis); mir_free(tvis.item.pszText); } return 1; } static int sortfunc(const void *a, const void *b) { lpMenuItemOptData *sd1, *sd2; sd1 = (lpMenuItemOptData *)a; sd2 = (lpMenuItemOptData *)b; if ((*sd1)->pos > (*sd2)->pos) return 1; if ((*sd1)->pos < (*sd2)->pos) return -1; return 0; } static int InsertSeparator(HWND hwndDlg) { MenuItemOptData *PD; TVINSERTSTRUCT tvis = {0}; TVITEM tvi = {0}; HTREEITEM hti = {0}; HWND hMenuTree = GetDlgItem(hwndDlg, IDC_MENUITEMS); hti = TreeView_GetSelection(hMenuTree); if (hti == NULL) return 1; tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_TEXT; tvi.hItem = hti; if (TreeView_GetItem(hMenuTree, &tvi) == FALSE) return 1; PD = (MenuItemOptData*)mir_alloc(sizeof(MenuItemOptData)); ZeroMemory(PD, sizeof(MenuItemOptData)); PD->id = -1; PD->name = mir_tstrdup(STR_SEPARATOR); PD->show = TRUE; PD->pos = ((MenuItemOptData *)tvi.lParam)->pos-1; tvis.item.lParam = (LPARAM)(PD); tvis.item.pszText = PD->name; tvis.item.iImage = tvis.item.iSelectedImage = PD->show; tvis.hParent = NULL; tvis.hInsertAfter = hti; tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; TreeView_InsertItem(hMenuTree, &tvis); return 1; } static void FreeTreeData(HWND hwndDlg) { HTREEITEM hItem = TreeView_GetRoot(GetDlgItem(hwndDlg, IDC_MENUITEMS)); while (hItem != NULL) { TVITEM tvi; tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = hItem; TreeView_GetItem(GetDlgItem(hwndDlg, IDC_MENUITEMS), &tvi); { MenuItemOptData* O = (MenuItemOptData *)tvi.lParam; if (O->name) mir_free(O->name); if (O->defname) mir_free(O->defname); if (O->uniqname) mir_free(O->uniqname); mir_free(O); } tvi.lParam = 0; TreeView_SetItem(GetDlgItem(hwndDlg, IDC_MENUITEMS), &tvi); hItem = TreeView_GetNextSibling(GetDlgItem(hwndDlg, IDC_MENUITEMS), hItem); } } static int BuildTree(HWND hwndDlg, int MenuObjectId, BOOL bReread) { char menuItemName[256], MenuNameItems[256]; char buf[256]; FreeTreeData(hwndDlg); TreeView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_MENUITEMS)); int menupos = GetMenuObjbyId(MenuObjectId); if (menupos == -1) return FALSE; TIntMenuObject* pimo = g_menus[menupos]; if (pimo->m_items.first == NULL) return FALSE; mir_snprintf(MenuNameItems, sizeof(MenuNameItems), "%s_Items", pimo->Name); int count = 0; { for (PMO_IntMenuItem p = pimo->m_items.first; p != NULL; p = p->next) if (p->mi.root == (HGENMENU)-1 || p->mi.root == NULL) count++; } lpMenuItemOptData *PDar = (lpMenuItemOptData*)mir_alloc(sizeof(lpMenuItemOptData)*count); count = 0; { for (PMO_IntMenuItem p = pimo->m_items.first; p != NULL; p = p->next) { if (p->mi.root != (HGENMENU)-1 && p->mi.root != NULL) continue; MenuItemOptData *PD = (MenuItemOptData*)mir_calloc(sizeof(MenuItemOptData)); GetMenuItemName(p, menuItemName, sizeof(menuItemName)); { DBVARIANT dbv; mir_snprintf(buf, SIZEOF(buf), "%s_name", menuItemName); if ( !DBGetContactSettingTString(NULL, MenuNameItems, buf, &dbv)) { PD->name = mir_tstrdup(dbv.ptszVal); DBFreeVariant(&dbv); } else PD->name = mir_tstrdup(GetMenuItemText(p)); } PD->pimi = p; PD->defname = mir_tstrdup(GetMenuItemText(p)); mir_snprintf(buf, SIZEOF(buf), "%s_visible", menuItemName); PD->show = DBGetContactSettingByte(NULL, MenuNameItems, buf, 1); if (bReread) { mir_snprintf(buf, SIZEOF(buf), "%s_pos", menuItemName); PD->pos = DBGetContactSettingDword(NULL, MenuNameItems, buf, 1); } else PD->pos = (PD->pimi) ? PD->pimi->originalPosition : 0; PD->id = p->iCommand; if (p->UniqName) PD->uniqname = mir_strdup(p->UniqName); PDar[ count ] = PD; count++; } } qsort(PDar, count, sizeof(lpMenuItemOptData), sortfunc); SendDlgItemMessage(hwndDlg, IDC_MENUITEMS, WM_SETREDRAW, FALSE, 0); int lastpos = 0; bool first = TRUE; TVINSERTSTRUCT tvis; tvis.hParent = NULL; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; for (int i=0; i < count; i++) { if (PDar[i]->pos - lastpos >= SEPARATORPOSITIONINTERVAL) { MenuItemOptData *PD = (MenuItemOptData*)mir_calloc(sizeof(MenuItemOptData)); PD->id = -1; PD->name = mir_tstrdup(STR_SEPARATOR); PD->pos = PDar[i]->pos - 1; PD->show = TRUE; tvis.item.lParam = (LPARAM)PD; tvis.item.pszText = PD->name; tvis.item.iImage = tvis.item.iSelectedImage = PD->show; SendDlgItemMessage(hwndDlg, IDC_MENUITEMS, TVM_INSERTITEM, 0, (LPARAM)&tvis); } tvis.item.lParam = (LPARAM)PDar[i]; tvis.item.pszText = PDar[i]->name; tvis.item.iImage = tvis.item.iSelectedImage = PDar[i]->show; HTREEITEM hti = (HTREEITEM)SendDlgItemMessage(hwndDlg, IDC_MENUITEMS, TVM_INSERTITEM, 0, (LPARAM)&tvis); if (first) { TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_MENUITEMS), hti); first = FALSE; } lastpos = PDar[i]->pos; } SendDlgItemMessage(hwndDlg, IDC_MENUITEMS, WM_SETREDRAW, TRUE, 0); mir_free(PDar); ShowWindow(GetDlgItem(hwndDlg, IDC_NOTSUPPORTWARNING), (pimo->m_bUseUserDefinedItems) ? SW_HIDE : SW_SHOW); EnableWindow(GetDlgItem(hwndDlg, IDC_MENUITEMS), pimo->m_bUseUserDefinedItems); EnableWindow(GetDlgItem(hwndDlg, IDC_INSERTSEPARATOR), pimo->m_bUseUserDefinedItems); return 1; } static void RebuildCurrent(HWND hwndDlg) { int MenuObjectID; if (GetCurrentMenuObjectID(hwndDlg, &MenuObjectID)) BuildTree(hwndDlg, MenuObjectID, TRUE); } static void ResetMenuItems(HWND hwndDlg) { int MenuObjectID; if (GetCurrentMenuObjectID(hwndDlg, &MenuObjectID)) BuildTree(hwndDlg, MenuObjectID, FALSE); } static HTREEITEM MoveItemAbove(HWND hTreeWnd, HTREEITEM hItem, HTREEITEM hInsertAfter) { TVITEM tvi = { 0 }; tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = hItem; if ( !SendMessage(hTreeWnd, TVM_GETITEM, 0, (LPARAM)&tvi)) return NULL; if (hItem && hInsertAfter) { TVINSERTSTRUCT tvis; TCHAR name[128]; if (hItem == hInsertAfter) return hItem; tvis.item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvis.item.stateMask = 0xFFFFFFFF; tvis.item.pszText = name; tvis.item.cchTextMax = sizeof(name); tvis.item.hItem = hItem; tvis.item.iImage = tvis.item.iSelectedImage = ((MenuItemOptData*)tvi.lParam)->show; if ( !SendMessage(hTreeWnd, TVM_GETITEM, 0, (LPARAM)&tvis.item)) return NULL; if ( !TreeView_DeleteItem(hTreeWnd, hItem)) return NULL; tvis.hParent = NULL; tvis.hInsertAfter = hInsertAfter; return TreeView_InsertItem(hTreeWnd, &tvis); } return NULL; } WNDPROC MyOldWindowProc = NULL; LRESULT CALLBACK LBTNDOWNProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_LBUTTONDOWN && !(GetKeyState(VK_CONTROL)&0x8000)) { TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(lParam); hti.pt.y = (short)HIWORD(lParam); // ClientToScreen(hwndDlg, &hti.pt); // ScreenToClient(GetDlgItem(hwndDlg, IDC_MENUITEMS), &hti.pt); TreeView_HitTest(hwnd, &hti); if (hti.flags&TVHT_ONITEMLABEL) { /// LabelClicked Set/unset selection TVITEM tvi; HWND tvw = hwnd; tvi.mask = TVIF_HANDLE|TVIF_PARAM; tvi.hItem = hti.hItem; TreeView_GetItem(tvw, &tvi); if ( !((MenuItemOptData *)tvi.lParam)->isSelected) { /* is not Selected*/ // reset all selection except current HTREEITEM hit; hit = TreeView_GetRoot(tvw); if (hit) do { TVITEM tvi = {0}; tvi.mask = TVIF_HANDLE|TVIF_PARAM; tvi.hItem = hit; TreeView_GetItem(tvw, &tvi); if (hti.hItem != hit) ((MenuItemOptData *)tvi.lParam)->isSelected = 0; else ((MenuItemOptData *)tvi.lParam)->isSelected = 1; TreeView_SetItem(tvw, &tvi); } while (hit = TreeView_GetNextSibling(tvw, hit)); } } } return CallWindowProc(MyOldWindowProc, hwnd, uMsg, wParam, lParam); } static INT_PTR CALLBACK GenMenuOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { struct OrderData *dat = (struct OrderData*)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MENUITEMS), GWLP_USERDATA); LPNMHDR hdr; switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); dat = (struct OrderData*)mir_alloc(sizeof(struct OrderData)); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MENUITEMS), GWLP_USERDATA, (LONG_PTR)dat); dat->dragging = 0; dat->iInitMenuValue = DBGetContactSettingByte(NULL, "CList", "MoveProtoMenus", TRUE); MyOldWindowProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MENUITEMS), GWLP_WNDPROC); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MENUITEMS), GWLP_WNDPROC, (LONG_PTR)&LBTNDOWNProc); { HIMAGELIST himlCheckBoxes; himlCheckBoxes = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16) | ILC_MASK, 2, 2); ImageList_AddIcon_IconLibLoaded(himlCheckBoxes, SKINICON_OTHER_NOTICK); ImageList_AddIcon_IconLibLoaded(himlCheckBoxes, SKINICON_OTHER_TICK); TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_MENUOBJECTS), himlCheckBoxes, TVSIL_NORMAL); TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_MENUITEMS), himlCheckBoxes, TVSIL_NORMAL); } CheckDlgButton(hwndDlg, dat->iInitMenuValue ? IDC_RADIO2 : IDC_RADIO1, TRUE); CheckDlgButton(hwndDlg, IDC_DISABLEMENUICONS, bIconsDisabled); BuildMenuObjectsTree(hwndDlg); return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DBLCLK) { switch (LOWORD(wParam)) { case IDC_INSERTSEPARATOR: InsertSeparator(hwndDlg); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); break; case IDC_RESETMENU: ResetMenuItems(hwndDlg); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); break; case IDC_DISABLEMENUICONS: case IDC_RADIO1: case IDC_RADIO2: SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); break; case IDC_GENMENU_DEFAULT: { TVITEM tvi; HTREEITEM hti; MenuItemOptData *iod; hti = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_MENUITEMS)); if (hti == NULL) break; tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM; tvi.hItem = hti; TreeView_GetItem(GetDlgItem(hwndDlg, IDC_MENUITEMS), &tvi); iod = (MenuItemOptData *)tvi.lParam; if (iod->name && _tcsstr(iod->name, STR_SEPARATOR)) break; if (iod->name) mir_free(iod->name); iod->name = mir_tstrdup(iod->defname); SaveTree(hwndDlg); RebuildCurrent(hwndDlg); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); } break; case IDC_GENMENU_SET: { TVITEM tvi; TCHAR buf[256]; MenuItemOptData *iod; HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_MENUITEMS)); if (hti == NULL) break; tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM; tvi.hItem = hti; SendDlgItemMessage(hwndDlg, IDC_MENUITEMS, TVM_GETITEM, 0, (LPARAM)&tvi); iod = (MenuItemOptData *)tvi.lParam; if (iod->name && _tcsstr(iod->name, STR_SEPARATOR)) break; ZeroMemory(buf, sizeof(buf)); GetDlgItemText(hwndDlg, IDC_GENMENU_CUSTOMNAME, buf, SIZEOF(buf)); if (iod->name) mir_free(iod->name); iod->name = mir_tstrdup(buf); SaveTree(hwndDlg); RebuildCurrent(hwndDlg); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); } break; } } break; case WM_NOTIFY: hdr = (LPNMHDR)lParam; switch(hdr->idFrom) { case 0: if (hdr->code == PSN_APPLY) { bIconsDisabled = IsDlgButtonChecked(hwndDlg, IDC_DISABLEMENUICONS) != 0; DBWriteContactSettingByte(NULL, "CList", "DisableMenuIcons", bIconsDisabled); SaveTree(hwndDlg); int iNewMenuValue = IsDlgButtonChecked(hwndDlg, IDC_RADIO1) ? 0 : 1; if (iNewMenuValue != dat->iInitMenuValue) { RebuildProtoMenus(iNewMenuValue); dat->iInitMenuValue = iNewMenuValue; } RebuildCurrent(hwndDlg); } break; case IDC_MENUOBJECTS: if (hdr->code == TVN_SELCHANGEDA) RebuildCurrent(hwndDlg); break; case IDC_MENUITEMS: switch (hdr->code) { case NM_CUSTOMDRAW: { int i = handleCustomDraw(GetDlgItem(hwndDlg, IDC_MENUITEMS), (LPNMTVCUSTOMDRAW) lParam); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, i); return TRUE; } case TVN_BEGINDRAGA: SetCapture(hwndDlg); dat->dragging = 1; dat->hDragItem = ((LPNMTREEVIEW)lParam)->itemNew.hItem; TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_MENUITEMS), dat->hDragItem); break; case NM_CLICK: { TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(GetMessagePos()); hti.pt.y = (short)HIWORD(GetMessagePos()); ScreenToClient(hdr->hwndFrom, &hti.pt); if (TreeView_HitTest(hdr->hwndFrom, &hti)) { if (hti.flags&TVHT_ONITEMICON) { TVITEM tvi; tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM; tvi.hItem = hti.hItem; TreeView_GetItem(hdr->hwndFrom, &tvi); tvi.iImage = tvi.iSelectedImage = !tvi.iImage; ((MenuItemOptData *)tvi.lParam)->show = tvi.iImage; TreeView_SetItem(hdr->hwndFrom, &tvi); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); //all changes take effect in runtime //ShowWindow(GetDlgItem(hwndDlg, IDC_BUTTONORDERTREEWARNING), SW_SHOW); } /*--------MultiSelection----------*/ if (hti.flags&TVHT_ONITEMLABEL) { /// LabelClicked Set/unset selection TVITEM tvi; HWND tvw = hdr->hwndFrom; tvi.mask = TVIF_HANDLE|TVIF_PARAM; tvi.hItem = hti.hItem; TreeView_GetItem(tvw, &tvi); if (GetKeyState(VK_CONTROL)&0x8000) { if (((MenuItemOptData *)tvi.lParam)->isSelected) ((MenuItemOptData *)tvi.lParam)->isSelected = 0; else ((MenuItemOptData *)tvi.lParam)->isSelected = 1; //current selection order++. TreeView_SetItem(tvw, &tvi); } else if (GetKeyState(VK_SHIFT)&0x8000) { ; // shifted click } else { // reset all selection except current HTREEITEM hit; hit = TreeView_GetRoot(tvw); if (hit) do { TVITEM tvi = {0}; tvi.mask = TVIF_HANDLE|TVIF_PARAM; tvi.hItem = hit; TreeView_GetItem(tvw, &tvi); if (hti.hItem != hit) ((MenuItemOptData *)tvi.lParam)->isSelected = 0; else ((MenuItemOptData *)tvi.lParam)->isSelected = 1; TreeView_SetItem(tvw, &tvi); } while (hit = TreeView_GetNextSibling(tvw, hit)); } } } break; } case TVN_SELCHANGING: { LPNMTREEVIEW pn; pn = (LPNMTREEVIEW) lParam; //((MenuItemOptData *)(pn->itemNew.lParam))->isSelected = 1; /*if (pn->action == NotKeyPressed) { remove all selection } */ } case TVN_SELCHANGEDA: { TVITEM tvi; HTREEITEM hti; MenuItemOptData *iod; SetDlgItemTextA(hwndDlg, IDC_GENMENU_CUSTOMNAME, ""); SetDlgItemTextA(hwndDlg, IDC_GENMENU_SERVICE, ""); EnableWindow(GetDlgItem(hwndDlg, IDC_GENMENU_CUSTOMNAME), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_GENMENU_DEFAULT), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_GENMENU_SET), FALSE); hti = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_MENUITEMS)); if (hti == NULL) break; tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM; tvi.hItem = hti; TreeView_GetItem(GetDlgItem(hwndDlg, IDC_MENUITEMS), &tvi); if (tvi.lParam == 0) break; iod = (MenuItemOptData *)tvi.lParam; if (iod->name && _tcsstr(iod->name, STR_SEPARATOR)) break; SetDlgItemText(hwndDlg, IDC_GENMENU_CUSTOMNAME, iod->name); if (iod->pimi->submenu.first == NULL && iod->uniqname) SetDlgItemTextA(hwndDlg, IDC_GENMENU_SERVICE, iod->uniqname); EnableWindow(GetDlgItem(hwndDlg, IDC_GENMENU_DEFAULT), lstrcmp(iod->name, iod->defname) != 0); EnableWindow(GetDlgItem(hwndDlg, IDC_GENMENU_SET), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_GENMENU_CUSTOMNAME), TRUE); break; } break; } } break; case WM_MOUSEMOVE: if ( !dat || !dat->dragging) break; { TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(lParam); hti.pt.y = (short)HIWORD(lParam); ClientToScreen(hwndDlg, &hti.pt); ScreenToClient(GetDlgItem(hwndDlg, IDC_MENUITEMS), &hti.pt); TreeView_HitTest(GetDlgItem(hwndDlg, IDC_MENUITEMS), &hti); if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT)) { HTREEITEM it = hti.hItem; hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg, IDC_MENUITEMS))/2; TreeView_HitTest(GetDlgItem(hwndDlg, IDC_MENUITEMS), &hti); if ( !(hti.flags&TVHT_ABOVE)) TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_MENUITEMS), hti.hItem, 1); else TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_MENUITEMS), it, 0); } else { if (hti.flags&TVHT_ABOVE) SendDlgItemMessage(hwndDlg, IDC_MENUITEMS, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); if (hti.flags&TVHT_BELOW) SendDlgItemMessage(hwndDlg, IDC_MENUITEMS, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_MENUITEMS), NULL, 0); } } break; case WM_LBUTTONUP: if ( !dat->dragging) break; TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_MENUITEMS), NULL, 0); dat->dragging = 0; ReleaseCapture(); { TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(lParam); hti.pt.y = (short)HIWORD(lParam); ClientToScreen(hwndDlg, &hti.pt); ScreenToClient(GetDlgItem(hwndDlg, IDC_MENUITEMS), &hti.pt); hti.pt.y-=TreeView_GetItemHeight(GetDlgItem(hwndDlg, IDC_MENUITEMS))/2; TreeView_HitTest(GetDlgItem(hwndDlg, IDC_MENUITEMS), &hti); if (hti.flags&TVHT_ABOVE) hti.hItem = TVI_FIRST; if (dat->hDragItem == hti.hItem) break; dat->hDragItem = NULL; if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT) || (hti.hItem == TVI_FIRST)) { HWND tvw; HTREEITEM * pSIT; HTREEITEM FirstItem = NULL; UINT uITCnt, uSic; tvw = GetDlgItem(hwndDlg, IDC_MENUITEMS); uITCnt = TreeView_GetCount(tvw); uSic = 0; if (uITCnt) { pSIT = (HTREEITEM *)mir_alloc(sizeof(HTREEITEM)*uITCnt); if (pSIT) { HTREEITEM hit; hit = TreeView_GetRoot(tvw); if (hit) do { TVITEM tvi = {0}; tvi.mask = TVIF_HANDLE|TVIF_PARAM; tvi.hItem = hit; TreeView_GetItem(tvw, &tvi); if (((MenuItemOptData *)tvi.lParam)->isSelected) { pSIT[uSic] = tvi.hItem; uSic++; } }while (hit = TreeView_GetNextSibling(tvw, hit)); // Proceed moving { UINT i; HTREEITEM insertAfter; insertAfter = hti.hItem; for (i=0; inmcd.dwDrawStage) { case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW; case CDDS_ITEMPREPAINT: { HTREEITEM hItem = (HTREEITEM) pNMTVCD->nmcd.dwItemSpec; TCHAR buf[255]; TVITEM tvi = {0}; int k = 0; tvi.mask = TVIF_HANDLE |TVIF_PARAM|TVIS_SELECTED|TVIF_TEXT|TVIF_IMAGE; tvi.stateMask = TVIS_SELECTED; tvi.hItem = hItem; tvi.pszText = (LPTSTR)(&buf); tvi.cchTextMax = 254; TreeView_GetItem(hWndTreeView, &tvi); if (((MenuItemOptData *)tvi.lParam)->isSelected) { pNMTVCD->clrTextBk = GetSysColor(COLOR_HIGHLIGHT); pNMTVCD->clrText = GetSysColor(COLOR_HIGHLIGHTTEXT); } else { pNMTVCD->clrTextBk = GetSysColor(COLOR_WINDOW); pNMTVCD->clrText = GetSysColor(COLOR_WINDOWTEXT); } /* At this point, you can change the background colors for the item and any subitems and return CDRF_NEWFONT. If the list-view control is in report mode, you can simply return CDRF_NOTIFYSUBITEMREDRAW to customize the item's subitems individually */ if (tvi.iImage == -1) { HBRUSH br; SIZE sz; RECT rc; k = 1; GetTextExtentPoint32(pNMTVCD->nmcd.hdc, tvi.pszText, lstrlen(tvi.pszText), &sz); if (sz.cx+3>pNMTVCD->nmcd.rc.right-pNMTVCD->nmcd.rc.left) rc = pNMTVCD->nmcd.rc; else SetRect(&rc, pNMTVCD->nmcd.rc.left, pNMTVCD->nmcd.rc.top, pNMTVCD->nmcd.rc.left+sz.cx+3, pNMTVCD->nmcd.rc.bottom); br = CreateSolidBrush(pNMTVCD->clrTextBk); SetTextColor(pNMTVCD->nmcd.hdc, pNMTVCD->clrText); SetBkColor(pNMTVCD->nmcd.hdc, pNMTVCD->clrTextBk); FillRect(pNMTVCD->nmcd.hdc, &rc, br); DeleteObject(br); DrawText(pNMTVCD->nmcd.hdc, tvi.pszText, lstrlen(tvi.pszText), &pNMTVCD->nmcd.rc, DT_LEFT|DT_VCENTER|DT_NOPREFIX); } return CDRF_NEWFONT|(k?CDRF_SKIPDEFAULT:0); } } return 0; } INT_PTR CALLBACK ProtocolOrderOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); int GenMenuOptInit(WPARAM wParam, LPARAM) { OPTIONSDIALOGPAGE odp = { 0 }; odp.cbSize = sizeof(odp); odp.hInstance = hInst; odp.pszGroup = LPGEN("Customize"); odp.position = -1000000000; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENMENU); odp.pszTitle = LPGEN("Menus"); odp.pfnDlgProc = GenMenuOpts; odp.flags = ODPF_BOLDGROUPS; Options_AddPage(wParam, &odp); odp.position = -10000000; odp.groupPosition = 1000000; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_PROTOCOLORDER); odp.pszTitle = LPGEN("Accounts"); odp.pfnDlgProc = ProtocolOrderOpts; odp.flags = ODPF_BOLDGROUPS|ODPF_EXPERTONLY; Options_AddPage(wParam, &odp); return 0; }