//*********************************************************************************************** void CBCGPMenuPage::OnDestroy() { UpdateData (); CBCGPPopupMenu::m_AnimationType = m_iMenuAnimationType == m_wndMenuAnimations.GetCount () - 1 ? CBCGPPopupMenu::SYSTEM_DEFAULT_ANIMATION : (CBCGPPopupMenu::ANIMATION_TYPE) m_iMenuAnimationType; if (m_pMenuBar != NULL) { m_pMenuBar->m_pMenuPage = NULL; //------------------------------ // Save the selected menu state: //------------------------------ if (m_hmenuSelected != NULL) { m_pMenuBar->OnChangeHot (-1); // To close and save all popups g_menuHash.SaveMenuBar (m_hmenuSelected, m_pMenuBar); } //-------------------------- // Restore the current menu: //-------------------------- if (m_hmenuCurr != NULL) { m_pMenuBar->CreateFromMenu (m_hmenuCurr); } } //------------------------------------ // Release the context menu resources: //------------------------------------ if (m_pContextMenu != NULL) { m_pContextMenu->GetMenuBar ()->SendMessage (WM_CANCELMODE); SaveMenu (); m_pContextMenu->SendMessage (WM_CLOSE); } //-------------------------- // Update shdows appearance: //-------------------------- CBCGPMenuBar::EnableMenuShadows (m_bMenuShadows); CPropertyPage::OnDestroy(); }
//************************************************************************************************ void CBCGMenuPage::CloseContextMenu (CBCGPopupMenu* pMenu) { if (m_pContextMenu == NULL) { return; } ASSERT(m_pContextMenu == pMenu); SaveMenu (); if (m_pContextMenu != NULL) { m_pContextMenu = NULL; m_wndContextMenus.SetCurSel (0); m_wndResetMenuButton.EnableWindow (FALSE); } m_uiContextMenuResId = 0; }
// обработка единичного меню int UserMenu::ProcessSingleMenu(DList<UserMenuItem> *Menu, int MenuPos, DList<UserMenuItem> *MenuRoot, const string& MenuFileName, const wchar_t *Title) { for (;;) { int NumLine=0, ExitCode, FuncPos[24]; UserMenuItem *CurrentMenuItem = nullptr; // очистка F-хоткеев for (size_t I=0 ; I < ARRAYSIZE(FuncPos) ; I++) FuncPos[I]=-1; string strName,strShortName; CtrlObject->Cp()->ActivePanel->GetCurName(strName,strShortName); /* $ 24.07.2000 VVM + При показе главного меню в заголовок добавляет тип - FAR/Registry */ string strMenuTitle; if (Title && *Title) { strMenuTitle = Title; } else { switch (MenuMode) { case MM_LOCAL: strMenuTitle = MSG(MLocalMenuTitle); break; case MM_GLOBAL: strMenuTitle = MSG(MMainMenuTitle); strMenuTitle += L" ("; strMenuTitle += MSG(MMainMenuGlobal); strMenuTitle += L")"; break; default: strMenuTitle = MSG(MMainMenuTitle); strMenuTitle += L" ("; strMenuTitle += MSG(MMainMenuUser); strMenuTitle += L")"; } } { VMenu UserMenu(strMenuTitle,nullptr,0,ScrY-4); UserMenu.SetFlags(VMENU_WRAPMODE); UserMenu.SetHelp(L"UserMenu"); UserMenu.SetPosition(-1,-1,0,0); UserMenu.SetBottomTitle(MSG(MMainMenuBottomTitle)); MenuNeedRefresh=true; while (!UserMenu.Done()) { if (MenuNeedRefresh) { UserMenu.Hide(); // спрячем // "изнасилуем" (перезаполним :-) NumLine=FillUserMenu(UserMenu,Menu,MenuPos,FuncPos,strName,strShortName); // заставим манагер менюхи корректно отрисовать ширину и // высоту, а заодно и скорректировать вертикальные позиции UserMenu.SetPosition(-1,-1,-1,-1); UserMenu.Show(); MenuNeedRefresh=false; } int Key=UserMenu.ReadInput(); MenuPos=UserMenu.GetSelectPos(); void* userdata = UserMenu.GetUserData(nullptr, 0, MenuPos); CurrentMenuItem = userdata? *static_cast<UserMenuItem**>(userdata):nullptr; if ((unsigned int)Key>=KEY_F1 && (unsigned int)Key<=KEY_F24) { int FuncItemPos; if ((FuncItemPos=FuncPos[Key-KEY_F1])!=-1) { UserMenu.Modal::SetExitCode(FuncItemPos); continue; } } else if (Key == L' ') // исключаем пробел из "хоткеев"! continue; switch (Key) { /* $ 24.08.2001 VVM + Стрелки вправо/влево открывают/закрывают подменю соответственно */ case KEY_RIGHT: case KEY_NUMPAD6: case KEY_MSWHEEL_RIGHT: if (CurrentMenuItem && CurrentMenuItem->Submenu) UserMenu.SetExitCode(MenuPos); break; case KEY_LEFT: case KEY_NUMPAD4: case KEY_MSWHEEL_LEFT: if (Title && *Title) UserMenu.SetExitCode(-1); break; case KEY_NUMDEL: case KEY_DEL: if (CurrentMenuItem) DeleteMenuRecord(Menu,CurrentMenuItem); break; case KEY_INS: case KEY_F4: case KEY_SHIFTF4: case KEY_NUMPAD0: { bool bNew = Key == KEY_INS || Key == KEY_NUMPAD0; if (!bNew && !CurrentMenuItem) break; EditMenu(Menu,CurrentMenuItem,bNew); break; } case KEY_CTRLUP: case KEY_RCTRLUP: case KEY_CTRLDOWN: case KEY_RCTRLDOWN: { int Pos=UserMenu.GetSelectPos(); if (Pos!=UserMenu.GetItemCount()-1 && CurrentMenuItem) { if (!((Key==KEY_CTRLUP || Key==KEY_RCTRLUP) && !Pos) && !((Key==KEY_CTRLDOWN || Key==KEY_RCTRLDOWN) && Pos==UserMenu.GetItemCount()-2)) { MenuModified = MenuNeedRefresh = true; if (Key==KEY_CTRLUP || Key==KEY_RCTRLUP) { Menu->MoveBefore(Menu->Prev(CurrentMenuItem),CurrentMenuItem); MenuPos--; } else { Menu->MoveAfter(Menu->Next(CurrentMenuItem),CurrentMenuItem); MenuPos++; } } } } break; case KEY_ALTF4: // редактировать все меню case KEY_RALTF4: { File MenuFile; (*FrameManager)[0]->Unlock(); { ConsoleTitle *OldTitle=new ConsoleTitle; SaveMenu(MenuFileName); FileEditor ShellEditor(MenuFileName,CP_UNICODE,FFILEEDIT_DISABLEHISTORY,-1,-1,nullptr); delete OldTitle; ShellEditor.SetDynamicallyBorn(false); FrameManager->EnterModalEV(); FrameManager->ExecuteModal(); FrameManager->ExitModalEV(); if (!ShellEditor.IsFileChanged() || (!MenuFile.Open(MenuFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING))) { return 0; } } MenuRoot->Clear(); GetFileString GetStr(MenuFile); MenuFileToList(MenuRoot, MenuFile, GetStr); MenuFile.Close(); MenuModified=true; UserMenu.Hide(); return 0; // Закрыть меню } /* $ 28.06.2000 tran выход из пользовательского меню по ShiftF10 из любого уровня вложенности просто задаем ExitCode -1, и возвращаем FALSE - по FALSE оно и выйдет откуда угодно */ case KEY_SHIFTF10: //UserMenu.SetExitCode(-1); return EC_CLOSE_MENU; case KEY_SHIFTF2: // Показать главное меню return(EC_MAIN_MENU); case KEY_BS: // Показать меню из родительского каталога только в MM_LOCAL режиме if (MenuMode == MM_LOCAL) return EC_PARENT_MENU; default: UserMenu.ProcessInput(); if (MenuPos!=UserMenu.GetSelectPos()) { MenuPos=UserMenu.GetSelectPos(); userdata = UserMenu.GetUserData(nullptr, 0, MenuPos); CurrentMenuItem = userdata? *static_cast<UserMenuItem**>(userdata):nullptr; } if (Key == KEY_F1) MenuNeedRefresh=true; break; } // switch(Key) } // while (!UserMenu.Done()) ExitCode=UserMenu.Modal::GetExitCode(); if (ExitCode<0 || ExitCode>=NumLine || !CurrentMenuItem) return EC_CLOSE_LEVEL; // вверх на один уровень void* userdata = UserMenu.GetUserData(nullptr, 0, ExitCode); CurrentMenuItem = userdata? *static_cast<UserMenuItem**>(userdata):nullptr; if (!CurrentMenuItem) return EC_CLOSE_LEVEL; // вверх на один уровень } if (CurrentMenuItem->Submenu) { /* $ 20.08.2001 VVM + При вложенных меню показывает заголовки предыдущих */ string strSubMenuLabel = CurrentMenuItem->strLabel; SubstFileName(strSubMenuLabel,strName,strShortName,nullptr,nullptr,nullptr,nullptr,TRUE); apiExpandEnvironmentStrings(strSubMenuLabel, strSubMenuLabel); size_t pos; if (strSubMenuLabel.Pos(pos,L'&')) strSubMenuLabel.LShift(1,pos); string strSubMenuTitle; if (Title && *Title) { strSubMenuTitle = Title; strSubMenuTitle += L" -> "; strSubMenuTitle += strSubMenuLabel; } else { strSubMenuTitle = strSubMenuLabel; } /* $ 14.07.2000 VVM ! Если закрыли подменю, то остаться. Инече передать управление выше */ MenuPos = ProcessSingleMenu(CurrentMenuItem->Menu, 0, MenuRoot, MenuFileName, strSubMenuTitle); if (MenuPos!=EC_CLOSE_LEVEL) return MenuPos; MenuPos = ExitCode; continue; } /* $ 01.05.2001 IS Отключим до лучших времен */ //int LeftVisible,RightVisible,PanelsHidden=0; string strCmdLineDir; CtrlObject->CmdLine->GetCurDir(strCmdLineDir); string strOldCmdLine; CtrlObject->CmdLine->GetString(strOldCmdLine); int OldCmdLineCurPos = CtrlObject->CmdLine->GetCurPos(); int OldCmdLineLeftPos = CtrlObject->CmdLine->GetLeftPos(); intptr_t OldCmdLineSelStart, OldCmdLineSelEnd; CtrlObject->CmdLine->GetSelection(OldCmdLineSelStart,OldCmdLineSelEnd); CtrlObject->CmdLine->LockUpdatePanel(TRUE); // Цикл исполнения команд меню (CommandX) for (string *str=CurrentMenuItem->Commands.First(); str; str=CurrentMenuItem->Commands.Next(str)) { string strCommand = *str; string strListName, strAnotherListName; string strShortListName, strAnotherShortListName; if (!((!StrCmpNI(strCommand,L"REM",3) && IsSpaceOrEos(strCommand.At(3))) || !StrCmpNI(strCommand,L"::",2))) { /* Осталось корректно обработать ситуацию, например: if exist !#!\!^!.! far:edit < diff -c -p !#!\!^!.! !\!.! Т.е. сначала "вычислить" кусок "if exist !#!\!^!.!", ну а если выполнится, то делать дальше. Или еще пример, if exist ..\a.bat D:\FAR\170\DIFF.MY\mkdiff.bat !?&Номер патча?! ЭТО выполняется всегда, т.к. парсинг всей строки идет, а надо проверить фазу "if exist ..\a.bat", а уж потом делать выводы... */ //if(ExtractIfExistCommand(Command)) { /* $ 01.05.2001 IS Отключим до лучших времен */ /* if (!PanelsHidden) { LeftVisible=CtrlObject->Cp()->LeftPanel->IsVisible(); RightVisible=CtrlObject->Cp()->RightPanel->IsVisible(); CtrlObject->Cp()->LeftPanel->Hide(); CtrlObject->Cp()->RightPanel->Hide(); CtrlObject->Cp()->LeftPanel->SetUpdateMode(FALSE); CtrlObject->Cp()->RightPanel->SetUpdateMode(FALSE); PanelsHidden=TRUE; } */ //; int PreserveLFN=SubstFileName(strCommand, strName, strShortName, &strListName, &strAnotherListName, &strShortListName, &strAnotherShortListName, FALSE, strCmdLineDir); bool ListFileUsed=!strListName.IsEmpty()||!strAnotherListName.IsEmpty()||!strShortListName.IsEmpty()||!strAnotherShortListName.IsEmpty(); if (ExtractIfExistCommand(strCommand)) { PreserveLongName PreserveName(strShortName,PreserveLFN); RemoveExternalSpaces(strCommand); if (!strCommand.IsEmpty()) { bool isSilent=false; if (strCommand.At(0) == L'@') { strCommand.LShift(1); isSilent=true; } ProcessOSAliases(strCommand); // TODO: Ахтунг. В режиме isSilent имеем проблемы с командами, которые выводят что-то на экран // Здесь необходимо переделка, например, перед исполнением подсунуть временный экранный буфер, а потом его содержимое подсунуть в ScreenBuf... if (!isSilent) { CtrlObject->CmdLine->ExecString(strCommand,FALSE, 0, 0, ListFileUsed); } else { SaveScreen SaveScr; CtrlObject->Cp()->LeftPanel->CloseFile(); CtrlObject->Cp()->RightPanel->CloseFile(); Execute(strCommand,TRUE, 0, 0, 0, ListFileUsed, true); } } } } } // strCommand != "REM" if (!strListName.IsEmpty()) apiDeleteFile(strListName); if (!strAnotherListName.IsEmpty()) apiDeleteFile(strAnotherListName); if (!strShortListName.IsEmpty()) apiDeleteFile(strShortListName); if (!strAnotherShortListName.IsEmpty()) apiDeleteFile(strAnotherShortListName); } // while (1) CtrlObject->CmdLine->LockUpdatePanel(FALSE); if (!strOldCmdLine.IsEmpty()) // восстановим сохраненную командную строку { CtrlObject->CmdLine->SetString(strOldCmdLine, FrameManager->IsPanelsActive()); CtrlObject->CmdLine->SetCurPos(OldCmdLineCurPos, OldCmdLineLeftPos); CtrlObject->CmdLine->Select(OldCmdLineSelStart, OldCmdLineSelEnd); } /* $ 01.05.2001 IS Отключим до лучших времен */ /* if (PanelsHidden) { CtrlObject->Cp()->LeftPanel->SetUpdateMode(TRUE); CtrlObject->Cp()->RightPanel->SetUpdateMode(TRUE); CtrlObject->Cp()->LeftPanel->Update(UPDATE_KEEP_SELECTION); CtrlObject->Cp()->RightPanel->Update(UPDATE_KEEP_SELECTION); if (RightVisible) CtrlObject->Cp()->RightPanel->Show(); if (LeftVisible) CtrlObject->Cp()->LeftPanel->Show(); } */ /* $ 14.07.2000 VVM ! Закрыть меню */ /* $ 25.04.2001 DJ - сообщаем, что была выполнена команда (нужно перерисовать панели) */ return EC_COMMAND_SELECTED; } }
void UserMenu::ProcessUserMenu(bool ChoiceMenuType) { // Путь к текущему каталогу с файлом LocalMenuFileName string strMenuFilePath; CtrlObject->CmdLine->GetCurDir(strMenuFilePath); // по умолчанию меню - это FarMenu.ini MenuMode = MM_LOCAL; MenuModified = MenuNeedRefresh = false; if (ChoiceMenuType) { int EditChoice=Message(0,3,MSG(MUserMenuTitle),MSG(MChooseMenuType),MSG(MChooseMenuMain),MSG(MChooseMenuLocal),MSG(MCancel)); if (EditChoice<0 || EditChoice==2) return; if (!EditChoice) { MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; } } // основной цикл обработки bool FirstRun=true; int ExitCode = 0; while ((ExitCode != EC_CLOSE_LEVEL) && (ExitCode != EC_CLOSE_MENU) && (ExitCode != EC_COMMAND_SELECTED)) { string strMenuFileFullPath = strMenuFilePath; AddEndSlash(strMenuFileFullPath); strMenuFileFullPath += LocalMenuFileName; Menu.Clear(); // Пытаемся открыть файл на локальном диске File MenuFile; bool FileOpened = PathCanHoldRegularFile(strMenuFilePath) ? MenuFile.Open(strMenuFileFullPath,GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING) : false; if (FileOpened) { GetFileString GetStr(MenuFile); MenuFileToList(&Menu, MenuFile, GetStr); MenuFile.Close(); } else if (MenuMode != MM_USER) { // Файл не открылся. Смотрим дальше. if (MenuMode == MM_GLOBAL) // был в %FARHOME%? { MenuMode = MM_USER; strMenuFilePath = Opt.ProfilePath; continue; } else if (!ChoiceMenuType) { if (!FirstRun) { // подымаемся выше... if(!IsRootPath(strMenuFilePath)) { size_t pos; if (FindLastSlash(pos,strMenuFilePath)) { strMenuFilePath.SetLength(pos--); continue; } } } FirstRun = false; MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; continue; } } int PrevMacroMode=CtrlObject->Macro.GetMode(); int _CurrentFrame=FrameManager->GetCurrentFrame()->GetType(); CtrlObject->Macro.SetMode(MACRO_USERMENU); // вызываем меню ExitCode=ProcessSingleMenu(&Menu, 0, &Menu, strMenuFileFullPath); if (_CurrentFrame == FrameManager->GetCurrentFrame()->GetType()) //??? CtrlObject->Macro.SetMode(PrevMacroMode); // ...запишем изменения обратно в файл SaveMenu(strMenuFileFullPath); // что было после вызова меню? switch (ExitCode) { // Показать меню родительского каталога case EC_PARENT_MENU: { if (MenuMode == MM_LOCAL) { if(!IsRootPath(strMenuFilePath)) { size_t pos; if (FindLastSlash(pos,strMenuFilePath)) { strMenuFilePath.SetLength(pos--); continue; } } MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; } else { MenuMode = MM_USER; strMenuFilePath = Opt.ProfilePath; } break; } // Показать главное меню case EC_MAIN_MENU: { // $ 14.07.2000 VVM: Shift+F2 переключает Главное меню/локальное в цикле switch (MenuMode) { case MM_LOCAL: MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; break; case MM_GLOBAL: MenuMode = MM_USER; strMenuFilePath = Opt.ProfilePath; break; default: // MM_USER CtrlObject->CmdLine->GetCurDir(strMenuFilePath); MenuMode=MM_LOCAL; } break; } } } if (FrameManager->IsPanelsActive() && (ExitCode == EC_COMMAND_SELECTED || MenuModified)) ShellUpdatePanels(CtrlObject->Cp()->ActivePanel,FALSE); }
//************************************************************************************************ void CBCGPMenuPage::OnSelchangeContextMenuList() { m_wndResetMenuButton.EnableWindow (FALSE); if (g_pContextMenuManager == NULL) { return; } m_uiContextMenuResId = 0; //---------------------------------------- // First, save and close the current menu: //---------------------------------------- if (m_pContextMenu != NULL) { SaveMenu (); CBCGPPopupMenu* pMenu = m_pContextMenu; m_pContextMenu = NULL; pMenu->SendMessage (WM_CLOSE); } if (m_wndContextMenus.GetCurSel () <= 0) { //-------------------------------------- // No is menu selected, nothing to do... //-------------------------------------- return; } UpdateData (); HMENU hMenu = g_pContextMenuManager->GetMenuByName ( m_strContextMenuName, &m_uiContextMenuResId); if (hMenu == NULL) { MessageBeep ((UINT) -1); return; } HMENU hmenuPopup = ::GetSubMenu (hMenu, 0); if (hmenuPopup == NULL) { ASSERT (FALSE); return; } m_pContextMenu = new CBCGPPopupMenu (this, m_strContextMenuName); ASSERT (m_pContextMenu != NULL); if (!globalData.bIsWindowsNT4) { m_pContextMenu->SetAutoDestroy (FALSE); } if (!m_pContextMenu->Create (GetTopLevelFrame (), m_ptMenuLastPos.x, m_ptMenuLastPos.y, hmenuPopup)) { AfxMessageBox (_T("Can't create context menu!")); } else { m_wndResetMenuButton.EnableWindow (); } }