2011-08-05 9 views
1

動的にロードされる配列からボタンを動的に作成しています。ボタンのヒントに必要な情報を保存しています。Delphiの動的ボタンを使用するMouseDownイベント

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ファイルです。

また、私のかなり恐ろしいコードを許してください、私はそれが多くの仕事を使用することができます知っている。

答えて

4

私はHintプロパティを使用しないことに同意します。何らかの時点で、Hintプロパティを他のものに使用したい場合があるためです。私はまた、Tagを使用する解決策にいくらか疑念を抱いています。

TDictionary<TSpeedButton,TAppPaths>のインスタンスを使用して、ボタンとアプリケーションの詳細をマッピングすると思います。ここでは、TAppPathsが、左クリック用と右クリック用の2つの文字列を含むレコードであると想像しています。

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レコードに好きなだけ多くの情報を含めるように簡単に拡張できます。

Windowsでは、ボタンを押したときではなく、マウスボタンを離したときにボタンがクリックされたため、MouseDownではなく、MouseUpを処理する必要があります。

+0

いつものように大きなアドバイス – JamesW

0

ヒントを使用して情報を保存しないでください。代わりに、タグタグを情報データ配列のインデックスとして使用してください。

EDIT:

のようにボタンのタグにしても、ボタンデータを割り当てるよりも、あなたがボタンを作成している:あなたはボタンを割り当てる作成するときに

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インデックス、

+0

OK、それは意味がありますが、それはmousedownの問題を解決しません。私はまだそれぞれのbtnの可能性についてif-thenを宣言することなく、mousedownの正しい情報を得ることができる必要があります。 – JamesW

+0

OKコードサンプルを追加しました。:) –

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; 

。なお、ボタンが解放されたときに、ボタンのタグに保存したオブジェクトを解放する必要があります(ボタンが解放されるまでボタンが解放されない限り、それは良いスタイルではありませんが、心配する必要はありません)。

+0

Object to Casting Tagを嫌うのではなく、 。 XE2のためにNativeInt -readyを使用するための+1!注意:D2007でNativeIntを使用しないでください。 –

+1

+1しかし、クラスヘルパーはより洗練されたIMHOになります。 – ComputerSaysNo

2

私は問題を完全に理解していないが、私はこれまで集めたものから、あなたはおそらくこのような何かを実行する必要があります。

… 
sApp := TSpeedButton(Sender).Hint 
… 

/あなたがHintを取得する必要がどこにいつでもハンドラ内の情報

+0

ありがとうございます。私が最初にこの問題に取り組み始めたとき、私はSender(ヒント)を使用しようとしていましたが、これを試すとは思わなかった。しかし、私は他の人が正しいと思うし、これを解決する良い方法があればヒントを使うべきではない。 – JamesW

+0

@JamesW:間違いなく。人々が直前の問題よりも広範な問題に集中する必要はあまりありません。そして、このサイトが、私が現在手ごろなものよりも(特にデルファイで)問題を解決する方法をよりよく理解することを学ぶことができる多くの人々を認めていることを知っていることは大きな慰めです。 –

関連する問題