【发布时间】:2022-01-04 22:21:16
【问题描述】:
一些简单的测试代码试图从一个TMainMenu 复制到另一个。我正在制作上下文相关的主菜单。
如果你想重新创建,我已经包含了cpp、h 和 dfm。
此代码有 3 个TMainMenus 设置和 2 个按钮。一个按钮从TMainMenu2 复制到TMainMenu1,另一个按钮从TMainMenu3 复制到TMainMenu1。我发现菜单正在被复制,但看起来就像 MainForm 上的子菜单。
主文件
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
TMenuItem *CloneMenuItem(TMenuItem *Src)
{
if (Src) {
TMenuItem *mi = new TMenuItem(Src->Owner);
mi->Caption = Src->Caption;
mi->OnClick = Src->OnClick;
mi->Tag = Src->Tag;
mi->Checked = Src->Checked;
mi->RadioItem = Src->RadioItem;
for(int i = 0; i < Src->Count; i++) {
TMenuItem *c = CloneMenuItem(Src->Items[i]);
if (c)
mi->Add(c);
}
return mi;
}
return 0;
}
void CopyMenu(TMenu *Dst, TMenu *Src)
{
Dst->Items->Clear();
for(int i = 0; i < Src->Items->Count; i++) {
TMenuItem *mi = CloneMenuItem(&Src->Items[i]);
Dst->Items->Add(mi);
}
}
void CopyMenu(TMainMenu *Dst, TMenu *Src)
{
#ifdef debug
// just to try and see wtf is going on. Gives exception?!?
String s1,s2,s3,s4;
for(int i = 0; i < Dst->Items->Count; i++) {
s4 = s3; s3 = s2; s2 = s1;
s1 = Dst->Items[i].Caption;
}
#else
Dst->Items->Clear();
#endif
for(int i = 0; i < Src->Items->Count; i++) {
TMenuItem *mi = CloneMenuItem(&Src->Items[i]);
Dst->Items->Add(mi);
// Dst->Items->Add(mi);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
CopyMenu(MainMenu1, MainMenu2);
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button2Click(TObject *Sender)
{
CopyMenu(MainMenu1, MainMenu3);
}
//---------------------------------------------------------------------------
头文件
//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.Menus.hpp>
//---------------------------------------------------------------------------
class TForm2 : public TForm
{
__published: // IDE-managed Components
TMainMenu *MainMenu1;
TMainMenu *MainMenu2;
TMenuItem *MainMenu11;
TMenuItem *MainMenu1Sub11;
TMenuItem *MainMenu1Sub21;
TMainMenu *MainMenu3;
TMenuItem *MainMenu21;
TMenuItem *MainMenu2Sub11;
TMenuItem *MainMenu2Sub21;
TMenuItem *MainMenu31;
TMenuItem *MainMenu3Sub11;
TButton *Button1;
TButton *Button2;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm2(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif
DFM 文件
object Form2: TForm2
Left = 0
Top = 0
Caption = 'Form2'
ClientHeight = 345
ClientWidth = 499
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -24
Font.Name = 'Segoe UI'
Font.Style = []
Menu = MainMenu1
PixelsPerInch = 192
TextHeight = 32
object Button1: TButton
Left = 24
Top = 160
Width = 417
Height = 50
Margins.Left = 6
Margins.Top = 6
Margins.Right = 6
Margins.Bottom = 6
Caption = 'Set MainMenu to MainMenu2'
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 24
Top = 232
Width = 417
Height = 50
Margins.Left = 6
Margins.Top = 6
Margins.Right = 6
Margins.Bottom = 6
Caption = 'Set MainMenu to MainMenu3'
TabOrder = 1
OnClick = Button2Click
end
object MainMenu1: TMainMenu
Left = 48
Top = 24
object MainMenu11: TMenuItem
Caption = 'MainMenu1'
object MainMenu1Sub11: TMenuItem
Caption = 'MainMenu1->Sub1'
end
object MainMenu1Sub21: TMenuItem
Caption = 'MainMenu1->Sub2'
end
end
end
object MainMenu2: TMainMenu
Left = 200
Top = 24
object MainMenu21: TMenuItem
Caption = 'MainMenu2'
object MainMenu2Sub11: TMenuItem
Caption = 'MainMenu2->Sub1'
end
object MainMenu2Sub21: TMenuItem
Caption = 'MainMenu2->Sub2'
end
end
end
object MainMenu3: TMainMenu
Left = 360
Top = 32
object MainMenu31: TMenuItem
Caption = 'MainMenu3'
object MainMenu3Sub11: TMenuItem
Caption = 'MainMenu3->Sub1'
end
end
end
end
【问题讨论】:
-
TMenuItem *mi = new TMenuItem(Src->Owner);看起来很可疑。新菜单项不应该归新菜单所有吗? -
在两个
CopyMenu()重载中,CloneMenuItem(&Src->Items[i])都是错误的。Src是TMenu和TMenu::Items不是数组(即不可索引),因此当i > 0时,由于您访问无效内存而发生坏事。您将TMenu::Items与TMenuItem::Items[]混淆了,后者是一个数组(好吧,无论如何都是可索引的)。您需要改用CloneMenuItem(Src->Items->Items[i])。Dst->Items[i]也有同样的问题。 -
谢谢雷米,就是这样。你是互联网上最有用的人!
标签: c++ c++builder vcl