Событие MouseDown с использованием динамических кнопок в Delphi - PullRequest
1 голос
/ 05 августа 2011

Я динамически создаю кнопки из массива, который динамически загружается.Я храню часть необходимой информации в подсказке кнопок.

    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, для этого нужно также объявить каждую кнопку в форме, чтобы я мог создавать и компилировать.использовать событие mousedown, не объявляя компонент заранее?Appdata - это отдельный pas-файл, содержащий всю необходимую информацию о каждом приложении, если кому-то интересно.

Также, пожалуйста, прости мой довольно ужасный код, я знаю, что он может использовать много работы.

Ответы [ 4 ]

4 голосов
/ 05 августа 2011

Я согласен, что вы не должны использовать свойство 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 кнопки нажимаются при отпускании кнопки мыши, а не при ее нажатии.

2 голосов
/ 05 августа 2011

Событием 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 голосов
/ 05 августа 2011

Я не уверен, что полностью понимаю проблему, но из того, что я до сих пор понял, вам, вероятно, нужно сделать что-то вроде этого:

…
sApp := TSpeedButton(Sender).Hint
…

всякий раз, когда / где вам нужно получить информацию Hint в обработчике.

0 голосов
/ 05 августа 2011

Не используйте подсказки для хранения информации, вместо этого используйте компонент Тег свойство в качестве индекса для вашего массива информационных данных!

EDIT:

Когда вы создаете кнопку, вы также назначаете данные кнопки кнопке 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 index,

...