GacUI学习(一)之高仿系统记事本(二)
转载请注明来源:
上篇《GacUI学习(一)之高仿系统记事本(一)》已经将全局排版布局搞定了,本篇将创建菜单,并进行处理菜单事件。
记事本菜单主要有文件、编辑、格式、查看、帮助这五个,故可以在TextBoxEditorWindow类中添加一个GuiToolstripMenuBar类型的主菜单(MainMenu)用来放置五个GuiToolstripButton类型的菜单,然后每个GuiToolstripButton类的菜单里面再次添加相应的GuiToolstripButton类的子菜单。具体代码如下
1 private: 2 3 //GuiControls 4 GuiToolstripMenuBar* MainMenu; //主菜单 5 GuiToolstripButton* FileMenu; //"文件"菜单 6 GuiToolstripButton* NewMenu; //"新建"菜单 7 GuiToolstripButton* OpenMenu; //"打开"菜单 8 GuiToolstripButton* SaveMenu; //"保存"菜单 9 GuiToolstripButton* SaveAsMenu; //"另存为"菜单 10 GuiToolstripButton* SetPageMenu; //"页面设置"菜单 11 GuiToolstripButton* PrintMenu; //"打印"菜单 12 GuiToolstripButton* ExitMenu; //"退出"菜单 13 14 GuiToolstripButton* EditMenu; //"编辑"菜单 15 GuiToolstripButton* UndoMenu; //"撤销"菜单 16 GuiToolstripButton* CutMenu; //"剪切"菜单 17 GuiToolstripButton* CopyMenu; //"复制"菜单 18 GuiToolstripButton* PasteMenu; //"粘贴"菜单 19 GuiToolstripButton* DeleteMenu; //"删除"菜单 20 GuiToolstripButton* FindMenu; //"查找"菜单 21 GuiToolstripButton* FindNextMenu; //"查找下一个"菜单 22 GuiToolstripButton* ReplaceMenu; //"替换"菜单 23 GuiToolstripButton* GotoMenu; //"转到"菜单 24 GuiToolstripButton* SelectAllMenu; //"全选"菜单 25 GuiToolstripButton* DateMenu; //"时间/日期"菜单 26 27 GuiToolstripButton* FormatMenu; //"格式"菜单 28 GuiToolstripButton* AutoWrapMenu; //"自动换行" 29 GuiToolstripButton* FontTypeMenu; //"字体" 30 31 GuiToolstripButton* ViewMenu; //"查看"菜单 32 GuiToolstripButton* StatusBarMenu; //"状态栏" 33 34 GuiToolstripButton* HelpMenu; //"帮助"菜单 35 GuiToolstripButton* AboutMenu; //"关于" 36 37 GuiMultilineTextBox* MainTextBox; //最主要的一个多行编辑框
具体意义可以参见注释,因为菜单事件最后会设计中间的编辑框(MainTextBox)的操作,所以我们本篇也将创建出中间的编辑框。按照从上往下的顺序,先创建菜单,同样在构造函数中
1 //下面自创一个菜单栏 2 { 3 GuiCellComposition* MainMenuCell = new GuiCellComposition; 4 table->AddChild(MainMenuCell); 5 MainMenuCell->SetSite(0, 0, 1, 1); 6 7 //创建主菜单 8 GuiToolstripMenuBar* MainMenu = g::NewMenuBar(); 9 MainMenu->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 10 MainMenu->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 11 12 MainMenuCell->AddChild(MainMenu->GetBoundsComposition()); 13 //文件菜单 14 { 15 FileMenu = g::NewMenuBarButton(); 16 FileMenu->SetText(L"文件(F)"); 17 FileMenu->SetAlt(L"F"); 18 MainMenu->GetToolstripItems().Add(FileMenu); 19 20 //文件子菜单 21 { 22 //"新建"菜单项 23 NewMenu = g::NewMenuItemButton(); 24 NewMenu->SetText(L"新建(M)"); 25 NewMenu->SetAlt(L"N"); 26 NewMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::NewMenu_OnClicked); 27 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(NewMenu); 28 //"打开"菜单项 29 OpenMenu = g::NewMenuItemButton(); 30 OpenMenu->SetText(L"打开(O)..."); 31 OpenMenu->SetAlt(L"O"); 32 OpenMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::OpenMenu_OnClicked); 33 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(OpenMenu); 34 //"保存"菜单项 35 SaveMenu = g::NewMenuItemButton(); 36 SaveMenu->SetText(L"保存(S)"); 37 SaveMenu->SetAlt(L"S"); 38 SaveMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::SaveMenu_OnClicked); 39 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(SaveMenu); 40 //"另存为"菜单 41 SaveAsMenu = g::NewMenuItemButton(); 42 SaveAsMenu->SetText(L"另存为(A)..."); 43 SaveAsMenu->SetAlt(L"A"); 44 SaveAsMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::SaveAsMenu_OnClicked); 45 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(SaveAsMenu); 46 //分割条 47 GuiControl* FileSplitter1 = g::NewMenuSplitter(); 48 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(FileSplitter1); 49 //"页面设置"菜单 50 SetPageMenu = g::NewMenuItemButton(); 51 SetPageMenu->SetText(L"页面设置(U)..."); 52 SetPageMenu->SetAlt(L"U"); 53 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(SetPageMenu); 54 //"打印"菜单 55 PrintMenu = g::NewMenuItemButton(); 56 PrintMenu->SetText(L"打印(P)..."); 57 PrintMenu->SetAlt(L"P"); 58 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(PrintMenu); 59 //分割条 60 GuiControl* FileSplitter2 = g::NewMenuSplitter(); 61 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(FileSplitter2); 62 //"退出"菜单项 63 ExitMenu = g::NewMenuItemButton(); 64 ExitMenu->SetText(L"退出(X)"); 65 ExitMenu->SetAlt(L"X"); 66 ExitMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::ExitMenu_OnClicked); 67 FileMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(ExitMenu); 68 } 69 } 70 71 //编辑菜单 72 { 73 EditMenu = g::NewMenuBarButton(); 74 EditMenu->SetText(L"编辑(E)"); 75 EditMenu->SetAlt(L"E"); 76 MainMenu->GetToolstripItems().Add(EditMenu); 77 78 //编辑子菜单 79 { 80 //"撤销"菜单 81 UndoMenu = g::NewMenuItemButton(); 82 UndoMenu->SetText(L"撤销(U)"); 83 UndoMenu->SetAlt(L"U"); 84 UndoMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::UndoMenu_OnClicked); 85 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(UndoMenu); 86 87 GuiControl* EditSplitter1 = g::NewMenuSplitter(); 88 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(EditSplitter1); 89 90 //"剪切"菜单 91 CutMenu = g::NewMenuItemButton(); 92 CutMenu->SetText(L"剪切(T)"); 93 CutMenu->SetAlt(L"T"); 94 CutMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::CutMenu_OnClicked); 95 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(CutMenu); 96 97 //"复制"菜单 98 CopyMenu = g::NewMenuItemButton(); 99 CopyMenu->SetText(L"复制(C)"); 100 CopyMenu->SetAlt(L"C"); 101 CopyMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::CopyMenu_OnClicked); 102 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(CopyMenu); 103 104 //"粘贴"菜单 105 PasteMenu = g::NewMenuItemButton(); 106 PasteMenu->SetText(L"粘贴(P)"); 107 PasteMenu->SetAlt(L"P"); 108 PasteMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::PasteMenu_OnClicked); 109 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(PasteMenu); 110 111 //"删除"菜单 112 DeleteMenu = g::NewMenuItemButton(); 113 DeleteMenu->SetText(L"删除(L)"); 114 DeleteMenu->SetAlt(L"L"); 115 DeleteMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::DeleteMenu_OnClicked); 116 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(DeleteMenu); 117 118 GuiControl* EditSplitter2 = g::NewMenuSplitter(); 119 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(EditSplitter2); 120 121 //查找 122 FindMenu = g::NewMenuItemButton(); 123 FindMenu->SetText(L"查找(F)..."); 124 FindMenu->SetAlt(L"F"); 125 FindMenu->SetShortcutText(L"Ctrl+F"); 126 127 FindMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::FindMenu_OnClicked); 128 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(FindMenu); 129 130 //查找下一个 131 FindNextMenu = g::NewMenuItemButton(); 132 FindNextMenu->SetText(L"查找下一个(N)"); 133 FindNextMenu->SetAlt(L"N"); 134 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(FindNextMenu); 135 136 //替换 137 ReplaceMenu = g::NewMenuItemButton(); 138 ReplaceMenu->SetText(L"替换(R)..."); 139 ReplaceMenu->SetAlt(L"R"); 140 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(ReplaceMenu); 141 142 //转到 143 GotoMenu = g::NewMenuItemButton(); 144 GotoMenu->SetText(L"转到(G)..."); 145 GotoMenu->SetAlt(L"G"); 146 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(GotoMenu); 147 148 GuiControl* EditSplitter3 = g::NewMenuSplitter(); 149 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(EditSplitter3); 150 151 //全选 152 SelectAllMenu = g::NewMenuItemButton(); 153 SelectAllMenu->SetText(L"全选(A)"); 154 SelectAllMenu->SetAlt(L"A"); 155 SelectAllMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::SelectAllMenu_OnClicked); 156 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(SelectAllMenu); 157 158 //时间/日期 159 DateMenu = g::NewMenuItemButton(); 160 DateMenu->SetText(L"时间/日期(D)"); 161 DateMenu->SetAlt(L"D"); 162 DateMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::DateMenu_OnClicked); 163 EditMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(DateMenu); 164 } 165 } 166 167 //"格式"菜单 168 { 169 FormatMenu = g::NewMenuBarButton(); 170 FormatMenu->SetText(L"格式(O)"); 171 FormatMenu->SetAlt(L"O"); 172 MainMenu->GetToolstripItems().Add(FormatMenu); 173 174 //格式子菜单 175 { 176 //自动换行 177 AutoWrapMenu = g::NewMenuItemButton(); 178 AutoWrapMenu->SetText(L"自动换行(W)"); 179 AutoWrapMenu->SetAlt(L"W"); 180 FormatMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(AutoWrapMenu); 181 182 //字体 183 FontTypeMenu = g::NewMenuItemButton(); 184 FontTypeMenu->SetText(L"字体(F)..."); 185 FontTypeMenu->SetAlt(L"F"); 186 FormatMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(FontTypeMenu); 187 } 188 } 189 190 //"查看"菜单 191 { 192 ViewMenu = g::NewMenuBarButton(); 193 ViewMenu->SetText(L"查看(V)"); 194 ViewMenu->SetAlt(L"V"); 195 MainMenu->GetToolstripItems().Add(ViewMenu); 196 197 //查看子菜单 198 { 199 StatusBarMenu = g::NewMenuItemButton(); 200 StatusBarMenu->SetText(L"状态栏(S)"); 201 StatusBarMenu->SetAlt(L"S"); 202 203 ViewMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(StatusBarMenu); 204 } 205 } 206 207 //"帮助"菜单 208 { 209 HelpMenu = g::NewMenuBarButton(); 210 HelpMenu->SetText(L"帮助(H)"); 211 HelpMenu->SetAlt(L"H"); 212 MainMenu->GetToolstripItems().Add(HelpMenu); 213 214 //帮助子菜单 215 { 216 AboutMenu = g::NewMenuItemButton(); 217 AboutMenu->SetText(L"关于GacTextBox"); 218 AboutMenu->SetAlt(L"A"); 219 HelpMenu->EnsureToolstripSubMenu()->GetToolstripItems().Add(AboutMenu); 220 } 221 } 222 }
按照上篇所述,创建菜单项,首先要创建一个GuiCellComposition,然后将此GuiCellComposition添加到前面创建的table里面,并SetSite()到第一行第一列,因为table本身就只有一列,故设置此GuiCellComposition占据一列。值得一提的是当我们把一个控件或者一个排版布局添加到它的父时,GacUI为自行处理控件,并管理对应的内存,所以此处我们直接new出类,然后添加,后面不需要delete,否则会造成二次delete。GacUI已经处理了常见的快捷键,所以创建菜单时,可以直接在对应的菜单上面SetAlt()即可设置Alt+快捷键。
上面的代码其实没有写完,只实现了对部分菜单的事件处理。对于菜单以及没有用到的按钮类,基本事件就是鼠标点击(Click),此处正是用了Clicked事件,然后将事件与对应的 MenuName_OnClick()“链接”起来,eg:
UndoMenu->Clicked.AttachMethod(this, &TextBoxEditorWindow::UndoMenu_OnClicked);
此处的UndoMenu_OnClicked即为我们自定义的一个事件处理函数,此函数有固定格式,用到了模板,本人对C++模板几乎完全不懂,故不作说明,此处可以固定为
void Func(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
以此类推,对应的代码如下:
1 void TextBoxEditorWindow::UpdateEditMenuStatus() 2 { 3 UndoMenu->SetEnabled(MainTextBox->CanUndo()); 4 CutMenu->SetEnabled(MainTextBox->CanCut()); 5 CopyMenu->SetEnabled(MainTextBox->CanCopy()); 6 PasteMenu->SetEnabled(MainTextBox->CanPaste()); 7 DeleteMenu->SetEnabled(MainTextBox->CanCut()); 8 9 } 10 11 void TextBoxEditorWindow::window_OnClipboardUpdated(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 12 { 13 UpdateEditMenuStatus(); 14 } 15 16 void TextBoxEditorWindow::NewMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 17 { 18 GetCurrentController()->DialogService()->ShowMessageBox(this->GetNativeWindow(), 19 L"功能暂未实现!", 20 L"GacTextBox", 21 INativeDialogService::DisplayOK, 22 INativeDialogService::DefaultFirst, 23 INativeDialogService::IconInformation, 24 INativeDialogService::ModalWindow); 25 } 26 27 void TextBoxEditorWindow::OpenMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 28 { 29 GuiOpenFileDialog* OpenFile = new GuiOpenFileDialog; 30 OpenFile->SetFilter(L"文本文档(*.txt)|*.txt|所有文件(*.*)|*.*"); 31 OpenFile->SetDefaultExtension(L"txt"); 32 this->AddComponent(OpenFile); 33 34 if (OpenFile->ShowDialog()) 35 { 36 CurrentFilePath = OpenFile->GetFileName(); 37 this->SelectOpenModeComboBox->SetSelectedIndex(0); 38 //默认以Ansi方式读取文件 39 WString OpenFileData = ReadFileByAnsi(CurrentFilePath); 40 //WString OpenFileData = ReadFileByUTF8(CurrentFilePath); 41 //WString OpenFileData = ReadFileByUTF16LE(CurrentFilePath); 42 43 MainTextBox->SetText(OpenFileData); 44 WString WindowsTitle = CurrentFilePath + L" -GacTextBox"; 45 this->SetText(WindowsTitle); 46 } 47 48 this->RemoveComponent(OpenFile); 49 delete OpenFile; 50 } 51 52 void TextBoxEditorWindow::SaveMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 53 { 54 //如果MainTextBox内容发生改变,点击保存按钮才有反应 55 if (bIsTextChanged == true) 56 { 57 //如果CurrentPath为空,则表明没有打开文件 58 if (CurrentFilePath.Length() == 0) 59 { 60 GuiSaveFileDialog* SaveFile = new GuiSaveFileDialog; 61 SaveFile->SetFilter(L"文本文档(*.txt)|*.txt|所有文件(*.*)|*.*"); 62 SaveFile->SetDefaultExtension(L"txt"); 63 SaveFile->SetTitle(L"保存"); 64 this->AddComponent(SaveFile); 65 66 if (SaveFile->ShowDialog()) 67 { 68 CurrentFilePath = SaveFile->GetFileName(); 69 } 70 else 71 return; 72 this->RemoveComponent(SaveFile); 73 delete SaveFile; 74 } 75 76 bool bResult; 77 if (CurrentEncoding == L"UTF8") 78 { 79 bResult = WriteFileByUTF8(CurrentFilePath, MainTextBox->GetText()); 80 } 81 else if (CurrentEncoding == L"UTF16LE") 82 { 83 bResult = WriteFileByUTF16LE(CurrentFilePath, MainTextBox->GetText()); 84 } 85 else 86 { 87 bResult = WriteFileByAnsi(CurrentFilePath, MainTextBox->GetText()); 88 } 89 90 this->SetText(CurrentFilePath + L" -GacTextBox"); 91 } 92 } 93 94 void TextBoxEditorWindow::SaveAsMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 95 { 96 GuiSaveFileDialog* SaveFile = new GuiSaveFileDialog; 97 SaveFile->SetFilter(L"文本文档(*.txt)|*.txt|所有文件(*.*)|*.*"); 98 SaveFile->SetDefaultExtension(L"txt"); 99 SaveFile->SetTitle(L"保存"); 100 SaveFile->SetOptions(INativeDialogService::FileDialogPromptOverwriteFile); 101 this->AddComponent(SaveFile); 102 103 if (SaveFile->ShowDialog()) 104 { 105 CurrentFilePath = SaveFile->GetFileName(); 106 } 107 else 108 return; 109 this->RemoveComponent(SaveFile); 110 delete SaveFile; 111 112 bool bResult; 113 if (CurrentEncoding == L"UTF8") 114 { 115 bResult = WriteFileByUTF8(CurrentFilePath, MainTextBox->GetText()); 116 } 117 else if (CurrentEncoding == L"UTF16LE") 118 { 119 bResult = WriteFileByUTF16LE(CurrentFilePath, MainTextBox->GetText()); 120 } 121 else 122 { 123 bResult = WriteFileByAnsi(CurrentFilePath, MainTextBox->GetText()); 124 } 125 126 127 /* 128 stream::FileStream* SaveFileStream = new stream::FileStream(CurrentFilePath, stream::FileStream::WriteOnly); 129 if (!SaveFileStream->IsAvailable()) 130 { 131 GetCurrentController()->DialogService()->ShowMessageBox(this->GetNativeWindow(), 132 L"保存文件失败!", 133 L"GacTextBox", 134 INativeDialogService::DisplayOK, 135 INativeDialogService::DefaultFirst, 136 INativeDialogService::IconInformation, 137 INativeDialogService::ModalWindow); 138 return; 139 } 140 141 SaveFileStream->Write((void*)(MainTextBox->GetText().Buffer()), 142 MainTextBox->GetText().Length()); 143 delete SaveFileStream; 144 */ 145 this->SetText(CurrentFilePath + L" -GacTextBox"); 146 147 } 148 149 void TextBoxEditorWindow::ExitMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 150 { 151 PostQuitMessage(0); 152 } 153 154 void TextBoxEditorWindow::UndoMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 155 { 156 MainTextBox->Undo(); 157 } 158 159 void TextBoxEditorWindow::PasteMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 160 { 161 MainTextBox->Paste(); 162 MainTextBox->SetFocus(); 163 } 164 165 void TextBoxEditorWindow::CopyMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 166 { 167 MainTextBox->Copy(); 168 MainTextBox->SetFocus(); 169 } 170 171 void TextBoxEditorWindow::CutMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 172 { 173 MainTextBox->Cut(); 174 MainTextBox->SetFocus(); 175 } 176 177 void TextBoxEditorWindow::DeleteMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 178 { 179 MainTextBox->SetSelectionText(L""); 180 MainTextBox->SetFocus(); 181 } 182 183 void TextBoxEditorWindow::SelectAllMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 184 { 185 MainTextBox->SelectAll(); 186 MainTextBox->SetFocus(); 187 } 188 189 void TextBoxEditorWindow::FindMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 190 { 191 FindTextWindow* findtextwindow = new FindTextWindow; 192 findtextwindow->GetNativeWindow()->SetParent(this->GetNativeWindow()); 193 findtextwindow->MoveToScreenCenter(); 194 findtextwindow->Show(); 195 196 } 197 198 void TextBoxEditorWindow::DateMenu_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments) 199 { 200 SYSTEMTIME systime; 201 GetLocalTime(&systime); 202 wchar_t *szTimeW = new wchar_t[20]; 203 memset(szTimeW, NULL, 20 * sizeof(wchar_t)); 204 swprintf_s(szTimeW, 20, L"%4d/%02d/%02d %02d:%02d", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute); 205 206 WString TimeStrW = szTimeW; 207 MainTextBox->SetSelectionText(TimeStrW); 208 delete[] szTimeW; 209 }
由于此程序没有写完,所以此代码也不是完整的,待我完成整个程序后再更新