I am dynamically creating buttons from an array that is dynamically loaded. I am storing a piece of needed information in the buttons hint.
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;
Where my issue arises is on the mouse down event. I want to somehow use the information stored in the buttons hint property to trigger the needed action. You can see what I am trying to in the left click and where I am coming from in the right click. Designing the right click way would require me to put in ~80 it also requires that I declare each button on the form so that I can build and compile.
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;
Can anyone point me in a direction to dynamically use the mousedown event without declaring the component ahead of time? Appdata is a separate pas file containing all the needed information on each application in case anyone is wondering.
Also please forgive my rather horrendous code, I know it could use a lot of work.
I agree that you should not use the
Hintproperty. Not least because you may at some point in time wish to use theHintproperty for something else. I am also somewhat dubious of solutions that useTag.I think I would use an instance of
TDictionary<TSpeedButton,TAppPaths>to map between buttons and the application details. Here I’m imagining thatTAppPathsis a record containing two strings, one for the left click and one for the right click, e.g.For sake of argument, let us suppose that this instance is called
ButtonDetails.When ever you add a new button you write code like this:
Then in the form’s mouse event handler you write it like this:
And now
AppPathshas both paths ready for you to use.This idea can easily be extended to include as much information as you like in the
TAppPathsrecord.As an aside, I think you should be handling
MouseUprather thanMouseDownsince in Windows, buttons are clicked when you release the mouse button rather than when you press it.