我从动态加载的数组动态创建按钮。我在按钮提示中存储了一条所需信息。
procedure TForm3.CreateAppButton(sBtnCapt: string);
var
hIcon: THandle;
nIconId: DWORD;
Icon: TIcon;
NewButton: TSpeedButton;
PicConvert: TBitmap;
sPathNew: string;
AppData: TAppDetails;
begin
AppData := TAppDetails.Create(sBtnCapt);
NewButton := TSpeedButton.Create(self);
with NewButton do
begin
Width := 67;
Height := 50;
Left := (Width + 5) * (self.ControlCount - 1);
Top := 5;
Parent := self;
Caption := AppData.Caption;
Name := AppData.ButtonName;
Font.Size := 7;
// extract a 16x16 icon for display on the buttom
sPathNew := '';
sPathNew := sPath + AppData.Exe;
if PrivateExtractIcons(PChar(sPathNew), 0, 16, 16, @hIcon, @nIconId, 1, LR_LOADFROMFILE)
<> 0 then
try
PicConvert := TBitmap.Create;
Icon := TIcon.Create;
try
Icon.Handle := hIcon;
PicConvert.Width := Icon.Width;
PicConvert.Height := Icon.Height;
PicConvert.Canvas.Draw(0, 0, Icon);
Glyph := PicConvert;
finally
Icon.Free;
PicConvert.Free;
end;
finally
DestroyIcon(hIcon);
end;
OnMouseDown := btnMouseDown;
Hint := AppData.Exe;
ShowHint := False;
Layout := blGlyphTop;
AppData.Free;
end;
end;
我的问题出现在鼠标按下事件上。我想以某种方式使用按钮提示属性中存储的信息来触发所需的操作。你可以看到我在左键单击中尝试的内容以及右键单击的来源。设计正确的单击方式需要我输入~80它还要求我声明表单上的每个按钮,以便我可以构建和编译。
procedure TForm3.btnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
sApp: string;
AppData: TAppDetails;
begin
sApp := '';
if Button = mbLeft then
begin
sApp := btnFoo.Hint;
ShellExecute(self.Handle, 'open', PChar(sApp), nil, nil, SW_SHOWNORMAL);
end
else if Button = mbRight then
begin
if Sender = btnCC3 then
begin
sApp := 'CaseClaims3.exe';
end
else if Sender = btnODBC then
begin
sApp := 'ODBCMgr.exe';
end
else if Sender = btnCredMaint then
begin
sApp := 'CreditorMaint';
end;
AppData := TAppDetails.Create(sApp);
ShellExecute(self.Handle, 'open', PChar(AppData.Wiki), nil, nil, SW_SHOWNORMAL);
AppData.Free;
end;
end;
有人能指出我在没有提前声明组件的情况下动态使用mousedown事件的方向吗? Appdata是一个单独的pas文件,包含每个应用程序所需的所有信息,以防有人想知道。
另外请原谅我可怕的代码,我知道它可以用很多工作。
答案 0 :(得分:4)
我同意您不应使用Hint
属性。尤其是因为您可能在某个时间点希望将Hint
属性用于其他内容。我也有点怀疑使用Tag
的解决方案。
我想我会使用TDictionary<TSpeedButton,TAppPaths>
的实例在按钮和应用程序详细信息之间进行映射。在这里,我想象TAppPaths
是一个包含两个字符串的记录,一个用于左键单击,另一个用于右键单击,例如。
TAppPaths= record
Left: string;
Right: string;
end;
为了论证,让我们假设这个实例叫做ButtonDetails
。
当您添加新按钮时,您可以编写如下代码:
AppPaths.Left := AppDetails.Exe;
AppPaths.Right := AppDetails.SomeOtherFunction;
ButtonDetails.Add(NewButton, AppPaths);
然后在表单的鼠标事件处理程序中,您可以这样写:
AppPaths := ButtonDetails[Sender as TSpeedButton];
现在AppPaths
已准备好让您使用这两条路径。
可以轻松扩展此提示,以便在TAppPaths
记录中包含尽可能多的信息。
顺便说一句,我认为您应该处理MouseUp
而不是MouseDown
,因为在Windows中,当您松开鼠标按钮而不是按下按钮时,会单击按钮。
答案 1 :(得分:2)
事件的Sender
是按钮,所以将“appData”保存到按钮的标签中(当你创建它时),然后在鼠标事件中使用它,即
procedure TForm3.CreateAppButton(sBtnCapt: string);
...
begin
AppData := TAppDetails.Create(sBtnCapt);
with NewButton do
begin
Tag := NativeInt(AppData);
...
end;
//AppData.Free; // NB! do not free here!
end;
procedure TForm3.btnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;X, Y: Integer);
var AppData: TAppDetails;
begin
...
else if Button = mbRight then
begin
AppData := TAppDetails((Sender as TSpeedButton).Tag);
// use the appData
ShellExecute(self.Handle, 'open', PChar(AppData.Wiki), nil, nil, SW_SHOWNORMAL);
//AppData.Free; // NB! do not free here!
end;
end;
procedure TForm3.DeleteAppButton(aBtn: TSpeedButton);
begin
TAppDetails(aBtn.Tag).Free;
aBtn.Free;
end;
请注意,当释放按钮时,您必须将保存的对象释放到按钮的标记中(除非在应用程序终止之前不释放按钮,然后您不必担心它不是好的样式)
答案 2 :(得分:2)
我不确定我是否完全理解这个问题,但是从目前为止我收集的内容来看,你可能需要这样做:
…
sApp := TSpeedButton(Sender).Hint
…
随时随地需要检索处理程序中的Hint
信息。
答案 3 :(得分:0)
不要使用提示来存储信息,而是使用组件标记属性作为信息数据数组的索引!
编辑:
当您创建按钮时,您还将按钮数据分配到按钮Tag,如:
TButtonData =record
InfoStr1: string;
InfoStr2: string;
a : cardinal;
//...
end;
TButtonDataAr = array of TButtonData;
var
ButtonDataAr: TButtonDataAr;
创建按钮时...
SetLength(ButtonDataAr, Length(ButtonDataAr) + 1);
ButtonDataAr[Length(ButtonDataAr)].InfoStr1 = 'TEST';
Button[n].Tag := Length(ButtonDataAr); //Set array index as Tag
如果您想从发件人那里检索信息,只需将标记作为 ButtonDataAr 索引,