(*----------------------------------- Action用ショートカットキーカスタマイズコンポーネント 00/06/02 午後 07:42 00/06/05 午前 10:07 Assignをちゃんと実装してみました。 01/04/11 ActionListのショートカットキーを保存復帰する WriteActionListData/ReadActionListData を実装しました。 01/04/13 WriteActionListData/ReadActionListDataを綺麗に実装 01/09/17 マウスホイールの挙動で変な動作が起きるので THotKeyをGridにFitさせるのをやめる //-----------------------------------*) (*----------------------------------- 使い方 まず、ショートカットキーをカスタマイズするためには どのアクションがショートカットキーカスタマイズ可能/不可能なのか を決める必要があります。 2つ方法があります。 ◇まず一つは プロパティを増やしたアクションのTCanCustomizeActionを ActionListに登録しておき ShortCutTypeOnDlg プロパティを設定する事です プロパティは TShortCutTypeOnDlg = (stHide, stCustomize, stReadOnly); このように定義されているので、Actionの値によってそれぞれ カスタマイズダイアログ上で [表示されない/カスタマイズ可能/表示はされるがカスタマイズ不可能] という動作になります。 ◇もう一つの方法は TShortCutCustomizeDlgの CustomizeTag/ReadOnlyTag プロパティの値を 0以外、例えば CustomizeTag:=1 ReadOnlyTag:=2 としておきます。 普通のTAction(TCustomizeAction)のTagプロパティが 0のままだとダイアログに表示されない 1にしておくとカスタマイズ可能, 2にしておくとダイアログに表示されるがカスタマイズ不可能 という機能を持たせる事が出来ます。 そしてショートカットキーカスタマイズダイアログを if ShortCutCustomizeDlg1.Execute then begin ShortCutCustomizeDlg1.Reflect; end; のように呼び出すと、 アプリケーション動作中にアクションのショートカットキーが 変更されるでしょう。 注意: ・ダイアログに表示されるActionの順番はActionListの順番どおりになるので  ActionListの"(すべてのアクション)"項目でActionの並び替えをしておいてください //-----------------------------------*) unit ShortCutCustomizeDlg; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ActnList, Grids, StdCtrls, Buttons, ComCtrls, Menus, IniFiles, GridScrollBar, GridColFit, FormMinMaxInfo; type {アクションのプロパティ} TShortCutTypeOnDlg = (stHide, stCustomize, stReadOnly); TShortCutTypeOnDlgs = set of TShortCutTypeOnDlg; {プロパティを増やしただけのアクション>登録} TCanCustomizeAction = class(TAction) private FShortCutTypeOnDlg: TShortCutTypeOnDlg; public procedure Assign(Source: TPersistent); override; published property ShortCutTypeOnDlg: TShortCutTypeOnDlg read FShortCutTypeOnDlg write FShortCutTypeOnDlg; end; {ダイアログ本体の非Visualコンポ>登録} TShortCutCustomizeDlg = class(TComponent) private FActionList: TActionList; FCustomizeTag: LongInt; FReadOnlyTag: LongInt; FSourceActList: TList; FDlgBufferActList: TList; {↑ショートカットキー重複チェックリスト} procedure SetCustomizeTag(const Value: LongInt); procedure SetReadOnlyTag(const Value: LongInt); procedure SetActionList(const Value: TActionList); function ActionType(SourceAction: TCustomAction): TShortCutTypeOnDlg; protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function Execute: Boolean; procedure Reflect; procedure WriteActionListData(Ini: TCustomIniFile; ShortCutTypeOnDlgs: TShortCutTypeOnDlgs); procedure ReadActionListData(Ini: TCustomIniFile; ShortCutTypeOnDlgs: TShortCutTypeOnDlgs); published property ActionList: TActionList read FActionList write SetActionList; property CustomizeTag: LongInt read FCustomizeTag write SetCustomizeTag; property ReadOnlyTag: LongInt read FReadOnlyTag write SetReadOnlyTag; end; {ダイアログForm} TShortCutCustomizeDlgForm = class(TForm) StringGrid1: TStringGrid; OkBBtn: TBitBtn; CancelBBtn: TBitBtn; HotKey1: THotKey; ScrollBar1: TScrollBar; Label1: TLabel; Button1: TButton; FormMinMaxInfo1: TFormMinMaxInfo; procedure FormResize(Sender: TObject); procedure ScrollBar1Change(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure HotKey1Enter(Sender: TObject); procedure HotKey1Exit(Sender: TObject); procedure Button1Click(Sender: TObject); procedure ScrollBar1Enter(Sender: TObject); private FScrBarFitAct: TAction; //ScrollBarをGridにFitさせるためのAction FHotkeyUpdateAct: TAction; //Hotkeyの内容をGridと連動させるAction FDesignGridColWidths1: TDesignGridColWidth; //列幅調整用 FShowActItemList: TList; //ダイアログ表示用のAction管理List procedure ScrBarActFitUpdate(Sender: TObject); procedure HotKeyUpdateActUpdate(Sender: TObject); procedure RowSetAction( Action1: TCanCustomizeAction; RowIndex: Integer); public property CustomizeActList: TList read FShowActItemList write FShowActItemList; end; procedure Register; var ShortCutCustomizeDlgForm: TShortCutCustomizeDlgForm; implementation {$R *.DFM} function DoubleShortcutKeyCheck(TargetList: TList): Boolean; overload; forward; function DoubleShortCutKeyCheck(TargetList: TList; AbsolutionIndex: Integer; CheckShortCutKey: TShortCut): Boolean; overload; forward; procedure Register; begin RegisterActions('', [TCanCustomizeAction], nil); //アクションの登録 RegisterComponents('Samples', [TShortCutCustomizeDlg]); //コンポーネントの登録 end; {↓Gridの行のタイトルや行数を定義している定数} type TGridRow = (grActionName, grCategory, grHint, grShortcut, grCustomize); const GridRowTitles: array[TGridRow] of String = ('アクション名','カテゴリ','ヒント','ショートカット','カスタマイズ'); {------------------------------- //ActionListのデータを保存/復帰する関数 WriteActionListData ReadActionListData 機能: ActionListのカスタマイズで設定したショートカットキーの データを保存復帰します。 引数説明: Ini: CustomIniFile派生の何かを指定する ShortCutTypeOnDlg: 特定のShortcutTypeOnDlgのActionだけ データ入出力する事にした 備考: 履歴: 2001/04/11 //------------------------------} procedure TShortCutCustomizeDlg.ReadActionListData( Ini: TCustomIniFile; ShortCutTypeOnDlgs: TShortCutTypeOnDlgs); var i: Integer; ShortCutStr: String; Action1: TCustomAction; begin if Assigned(FActionList)=False then Exit; with Ini do for i := 0 to FActionList.ActionCount-1 do begin if not (FActionList.Actions[i] is TCustomAction) then continue; {↑ショートカットキーを持たないActionなら無視} Action1 := TCustomAction(FActionList.Actions[i]); if not (ActionType(Action1) in ShortCutTypeOnDlgs) then continue; {↑ShortcutTypeOnDlgが一致しないActionは無視} ShortCutStr := ShortCutToText( Action1.ShortCut ); ShortCutStr := ReadString( FActionList.Name, Action1.Name, ShortCutStr); Action1.ShortCut := TextToShortCut(ShortCutStr); end; end; procedure TShortCutCustomizeDlg.WriteActionListData( Ini: TCustomIniFile; ShortCutTypeOnDlgs: TShortCutTypeOnDlgs); var i: Integer; ShortCutStr: String; Action1: TCustomAction; begin if Assigned(FActionList)=False then Exit; with Ini do for i := 0 to FActionList.ActionCount-1 do begin if not (FActionList.Actions[i] is TCustomAction) then continue; {↑ショートカットキーを持たないActionなら無視} Action1 := TCustomAction(FActionList.Actions[i]); if not (ActionType(Action1) in ShortCutTypeOnDlgs) then continue; {↑ShortcutTypeOnDlgが一致しないActionは無視} ShortCutStr := ShortCutToText( Action1.ShortCut ); WriteString( FActionList.Name, Action1.Name, ShortCutStr); end; end; //------------------------------ //////////////////////////////////////////////////////////// { TCanCustomizeAction } //////////////////////////////////////////////////////////// procedure TCanCustomizeAction.Assign(Source: TPersistent); begin if Source is TCanCustomizeAction then begin Self.FShortCutTypeOnDlg := TCanCustomizeAction(Source).ShortCutTypeOnDlg; end; if Source is TContainedAction then begin Self.Category := TContainedAction(Source).Category; end; inherited Assign(Source); end; //////////////////////////////////////////////////////////// { TShortCutCustomizeDlg } //////////////////////////////////////////////////////////// constructor TShortCutCustomizeDlg.Create(AOwner: TComponent); begin inherited Create(AOwner); FSourceActList := TList.Create; FDlgBufferActList := TList.Create; end; destructor TShortCutCustomizeDlg.Destroy; var i: Integer; begin for i := 0 to FDlgBufferActList.Count - 1 do begin TCanCustomizeAction(FDlgBufferActList.Items[i]).Free; end; FDlgBufferActList.Free; {↑内部に実体があるためにすべてをクリアしてから削除} FSourceActList.Free; {↑内部に実体はないために普通に削除} inherited; end; //------------------------------- //ActionListが途中で破棄された場合の処理(Tips) {プロパティコンポが削除された時はここに通知される} procedure TShortCutCustomizeDlg.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; case Operation of opInsert: begin if not (csLoading in ComponentState) and (ActionList = nil) and (AComponent.Owner = Self.Owner) and (AComponent is TActionList) then ActionList := TActionList(AComponent); end; opRemove: begin if (Operation = opRemove) and (AComponent = ActionList) then ActionList := nil; end; end; end; procedure TShortCutCustomizeDlg.SetActionList(const Value: TActionList); begin if FActionList <> Value then begin FActionList := Value; if FActionList <> nil then FActionList.FreeNotification(Self); {もしコンポーネントが削除されていたら通知するコード(Tips)} end; end; //------------------------------- //プロパティ procedure TShortCutCustomizeDlg.SetCustomizeTag(const Value: LongInt); begin if (Value <> 0) and (FReadOnlyTag = Value) then begin raise Exception.Create('ReadOnlyTagと同じ値はとれません'); end else FCustomizeTag := Value; end; procedure TShortCutCustomizeDlg.SetReadOnlyTag(const Value: LongInt); begin if (Value <> 0) and (FCustomizeTag = Value) then begin raise Exception.Create('CustomizeTagと同じ値はとれません'); end else FReadOnlyTag := Value; end; //------------------------------- //Executeメソッド function TShortCutCustomizeDlg.Execute: Boolean; var i: Integer; AddCanCustomizeAct: TCanCustomizeAction; AddShowActItemOnDlg: TCanCustomizeAction; begin if FActionList = nil then begin Result := false; exit; end; for i := 0 to FDlgBufferActList.Count - 1 do begin TCanCustomizeAction(FDlgBufferActList.Items[i]).Free; end; FDlgBufferActList.Clear; {↑FDlgBufferActListの内容物をすべて破棄} FSourceActList.Clear; {↓Dlg側で保持しておくべきActionを生成} AddCanCustomizeAct := nil; for i := 0 to FActionList.ActionCount - 1 do begin {条件によってDlg側で保持しておくべきActionに含めるか否か} {↓カスタマイズ可能Actionで属性がstHideじゃないとき} if (FActionList.Actions[i] is TCanCustomizeAction) and (TCanCustomizeAction(FActionList.Actions[i]).ShortCutTypeOnDlg <> stHide) then begin AddCanCustomizeAct := TCanCustomizeAction.Create(Self); with AddCanCustomizeAct do begin Assign( TCanCustomizeAction(FActionList.Actions[i])); end; end else {↓普通のActionでFCustomizeTagが0以外で一致するとき} if (not (FActionList.Actions[i] is TCanCustomizeAction)) and (FActionList.Actions[i].Tag = FCustomizeTag) and (FCustomizeTag <> 0) then begin AddCanCustomizeAct := TCanCustomizeAction.Create(Self); with AddCanCustomizeAct do begin Assign( TCanCustomizeAction(FActionList.Actions[i])); ShortCutTypeOnDlg := stCustomize; {↑CustomizeTagならCustomize属性} end; end else {↓普通のActionでFReadOnlyTagが0以外で一致するとき} if (not (FActionList.Actions[i] is TCanCustomizeAction)) and (FActionList.Actions[i].Tag = FReadOnlyTag) and (FReadOnlyTag <> 0) then begin AddCanCustomizeAct := TCanCustomizeAction.Create(Self); with AddCanCustomizeAct do begin Assign( TCanCustomizeAction(FActionList.Actions[i])); ShortCutTypeOnDlg := stReadOnly; {↑ReadOnlyTagならReadOnly属性} end; end else Continue; {↑条件外のときはスキップする} {↓Dlg側でCanCustomizeActionを保持} FDlgBufferActList.Add(AddCanCustomizeAct); FSourceActList.Add(FActionList.Actions[i]); end; //for {↓ダイアログFormに配置すべきCanCustomizeActionが無ければ開かない} if FDlgBufferActList.Count = 0 then begin Result := false; exit; end; {↓取得したAction中に重複するショートカットがあればエラー} if DoubleShortcutKeyCheck(FDlgBufferActList)= false then begin raise Exception.Create('ショートカットキーの重複があるようです'); Result := false; exit; end; {この段階でDlg側には表示すべきActionのデータしか持っていない 表示の必要のないデータは保持しない} ShortCutCustomizeDlgForm := TShortCutCustomizeDlgForm.Create(Self.Owner); with ShortCutCustomizeDlgForm do try {↓ここでDlg→Formにパラメータを渡す} for i := 0 to FDlgBufferActList.Count - 1 do begin AddShowActItemOnDlg := TCanCustomizeAction.Create(ShortCutCustomizeDlgForm); AddShowActItemOnDlg.Assign(TCanCustomizeAction(FDlgBufferActList.Items[i])); FShowActItemList.Add(AddShowActItemOnDlg); end; StringGrid1.RowCount := FShowActItemList.Count + 1; for i := 1 to StringGrid1.RowCount - 1 do begin {Gridのi行目をセット} RowSetAction( TCanCustomizeAction(FShowActItemList.Items[i-1]) , i); end; case ShortCutCustomizeDlgForm.ShowModal of mrOk: begin {↓ここでDlg←Formにパラメータを渡す} for i := 0 to FDlgBufferActList.Count - 1 do begin TCanCustomizeAction(FDlgBufferActList.Items[i]).ShortCut := TCanCustomizeAction(FShowActItemList.Items[i]).ShortCut; {↑ShortCutだけ反映する} end; Result := true; end else begin Result := false; end; end; finally ShortCutCustomizeDlgForm.Free; end; end; //------------------------------- //Reflect(反映)メソッド //設定されたショートカットキーをActionに反映する procedure TShortCutCustomizeDlg.Reflect; var i, j: Integer; begin for i := 0 to FDlgBufferActList.Count - 1 do begin for j := 0 to FActionList.ActionCount - 1 do begin if FSourceActList.Items[i] = FActionList.Actions[j] then begin TCustomAction(FActionList.Actions[j]).ShortCut := TCanCustomizeAction(FDlgBufferActList.Items[i]).ShortCut; {↑反映するのはショートカットキーの設定だけ} end; end; //for j end; //for i end; (*φ(.. )メモメモ 行いたい機能としては if ShortCutCustomizeDlg.Execute then begin ShortCutCustomize.Reflect; end; これでショートカットが反映するといいと思う。 ということは、自ずとコーディングが決まってくるが Execute内部でFormの生成破棄を行うので Form側にデータを持っていてもReflect出来ない ということはDlg側にデータを持っておく必要がある。 Dlg側にはどのアクションとどのショートカットキーが 結びついているかという情報が必要 Actionの中の一部をListで管理するべき Form側にはStringGrid(もしくはListView)に表示するために Caption、Hint、ShortCutのプロパは必要 Dlg側で持っているListのItemと同数のItemが必要 ListViewではAutoSizeが可能だが StringGridでは今のところ不可能なので、考慮しなければいけない Execute内では ・ActionListから該当ActionをDlgListに登録  ActionのShortCutTypeOnDlgかCustomizeTag,ReadOnlyTagの設定による ・DlgFormを生成 ・DlgListからDlgFormListに必要な情報をコピー ・DlgFormをShowModalで開く ・ModalResultがOKになるならDlgFormListからDlgListに情報をコピー ・DlgFormを破棄 Reflect内では ・DlgListに何か残っている事を確認して ・それを元のActionに反映する。 *) //////////////////////////////////////////////////////////// { TShortCutCustomizeDlgForm } //////////////////////////////////////////////////////////// (*----------------------------------- //------------------------------- //指定したGridのセルに指定コンポを合わせる関数 procedure SetStrGridCompo(CellControl: TControl; BaseStrGrid: TStringGrid; SetCol, SetRow: Integer); var Rect1: TRect; begin with BaseStrGrid do begin CopyRect(Rect1, CellRect( SetCol, SetRow)); Rect1.TopLeft := CellControl.Parent.ScreenToClient(BaseStrGrid.ClientToScreen(Rect1.TopLeft)); Rect1.BottomRight := CellControl.Parent.ScreenToClient(BaseStrGrid.ClientToScreen(Rect1.BottomRight)); CellControl.BringToFront; with Rect1 do CellControl.SetBounds(Left, Top, Right-Left, Bottom-Top); end; end; //-----------------------------------*) //------------------------------- //起動・終了 procedure TShortCutCustomizeDlgForm.FormCreate(Sender: TObject); begin Self.Icon.Handle := HICON(nil); {↓GridColFitの処理} StrGridAutoSize1Initialize( StringGrid1, FDesignGridColWidths1); {↓GridScrollBarの処理} FScrBarFitAct := TAction.Create(Self); FScrBarFitAct.OnUpdate := ScrBarActFitUpdate; ScrollBar1.Action := FScrBarFitAct; (*----------------------------------- THotKeyをGridにFitするのはやめる {↓FitHotkeyの処理} FHotkeyFitAct := TAction.Create(Self); FHotkeyFitAct.OnUpdate := HotKeyActFitUpdate; HotKey1.Action := FHotkeyFitAct; //-----------------------------------*) {↓HotkeyをGridに連動させる} FHotkeyUpdateAct := TAction.Create(Self); FHotkeyUpdateAct.OnUpdate := HotKeyUpdateActUpdate; HotKey1.Action := FHotkeyUpdateAct; {ダイアログ表示用のAction管理List} FShowActItemList := TList.Create; StringGrid1.DoubleBuffered := true; {0行目の文字列をセット} RowSetAction(nil, 0); end; procedure TShortCutCustomizeDlgForm.FormDestroy(Sender: TObject); var i: Integer; begin FScrBarFitAct.Free; FHotkeyUpdateAct.Free; for i := 0 to FShowActItemList.Count - 1 do begin TObject(FShowActItemList.Items[i]).Free; end; FShowActItemList.Free; end; {------------------------------- //THotKeyをGridの選択部分と連動させる 機能: 備考: 履歴: 2001/09/17 //------------------------------} procedure TShortCutCustomizeDlgForm.HotKeyUpdateActUpdate(Sender: TObject); const HotKeyFitColIndex: Integer = ord(grShortcut); begin {↓StringGridにフォーカスがあるならショートカットを反映する} if ActiveControl = StringGrid1 then HotKey1.HotKey := TCanCustomizeAction(FShowActItemList.Items[StringGrid1.Row-1]).ShortCut; if (TCanCustomizeAction(FShowActItemList.Items[StringGrid1.Row-1]) .ShortCutTypeOnDlg = stCustomize) then begin HotKey1.Enabled := true; end else HotKey1.Enabled := false; end; //------------------------------ (*----------------------------------- THotKeyをGridにFitするのはやめる //------------------------------- //コンポをセルにフィットさせるUpdate処理 procedure TShortCutCustomizeDlgForm.HotKeyActFitUpdate(Sender: TObject); const HotKeyFitColIndex: Integer = ord(grShortcut); begin {↓HotKey1にフォーカスがあったらショートカットの反映を止める} if ActiveControl <> HotKey1 then HotKey1.HotKey := TCanCustomizeAction(FShowActItemList.Items[StringGrid1.Row-1]).ShortCut; SetStrGridCompo(HotKey1, StringGrid1, HotKeyFitColIndex, StringGrid1.Row); {↑ここでTHotKeyをgrShortcutの列に固定して表示させている} with StringGrid1 do begin if ((TopRow <= Row) and (Row < TopRow+VisibleRowCount)) and ((LeftCol <= HotKeyFitColIndex) and (HotKeyFitColIndex < LeftCol+VisibleColCount )) then begin HotKey1.Visible := true; end else HotKey1.Visible := false; if (TCanCustomizeAction(FShowActItemList.Items[StringGrid1.Row-1]) .ShortCutTypeOnDlg = stCustomize) then begin HotKey1.Enabled := true; end else HotKey1.Enabled := false; end; end; //-----------------------------------*) //------------------------------- //スクロールバーをグリッドにフィットさせるUpdate処理 procedure TShortCutCustomizeDlgForm.ScrBarActFitUpdate(Sender: TObject); begin {↓GridScrollBarの処理} ScrollBarFitGrid(StringGrid1, ScrollBar1); GridSetScrollBox(StringGrid1, ScrollBar1); end; //------------------------------- //HotKeyEnter・Exitイベント procedure TShortCutCustomizeDlgForm.HotKey1Enter(Sender: TObject); begin HotKey1.Action := nil; end; {↑Enterした後にActionが関連付いていると ↓Enabled=falseになるのでActionを解除しておく} procedure TShortCutCustomizeDlgForm.HotKey1Exit(Sender: TObject); begin HotKey1.Action := FHotkeyUpdateAct; end; //------------------------------- //割り当てボタン procedure TShortCutCustomizeDlgForm.Button1Click(Sender: TObject); begin if DoubleShortCutKeyCheck(FShowActItemList, StringGrid1.Row-1, Hotkey1.Hotkey) = false then begin ShowMessage('ショートカットキーに重複があります'+#13+ '入力しなおしてください'); try Self.ActiveControl := HotKey1; except end; end else begin TCanCustomizeAction(FShowActItemList.Items[StringGrid1.Row-1]).ShortCut := HotKey1.HotKey; StringGrid1.Cells[ord(grShortcut), StringGrid1.Row] := ShortCutToText(HotKey1.HotKey); end; end; //------------------------------- //リサイズイベント procedure TShortCutCustomizeDlgForm.FormResize(Sender: TObject); begin {↓GridColFitの処理} StrGridAutoSize1( StringGrid1, FDesignGridColWidths1); {↓GridScrollBarの処理} ScrBarActFitUpdate(nil); (*----------------------------------- THotKeyをGridにFitするのはやめる {↓HotkeyFitの処理} HotKeyActFitUpdate(nil) //-----------------------------------*) end; //------------------------------- //ScrollBarChangeイベント procedure TShortCutCustomizeDlgForm.ScrollBar1Change(Sender: TObject); begin {↓GridScrollBarの処理} ScrollPosSetGridTopRow(StringGrid1, ScrollBar1); end; //------------------------------- //DrawCellイベント procedure TShortCutCustomizeDlgForm.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin (*----------------------------------- THotKeyをGridにFitするのはやめる HotKeyActFitUpdate(nil); {↑UpdateイベントはVisible=falseだと動作しないので 一度消えた時のために、ここで動作させておく} //-----------------------------------*) end; //------------------------------- //ショートカットキーが重複していないかのチェックを行う {trueならOK、falseならOut} {ShortCut=0というのはショートカットキー定義無しの事だから その場合は重複しても仕方ない} {リスト内の相互のショートカットを判定する} function DoubleShortcutKeyCheck(TargetList: TList): Boolean; overload; var i, j: Integer; begin Result := true; for i := 0 to TargetList.Count - 1 do begin for j := i+1 to TargetList.Count - 1 do begin if (TCustomAction(TargetList.Items[i]).ShortCut = TCustomAction(TargetList.Items[j]).ShortCut) and (TCustomAction(TargetList.Items[i]).ShortCut <> 0) then begin Result := false; Break; end; end; end; end; {リスト内の特定の番号のショートカット以外を判定する} function DoubleShortCutKeyCheck(TargetList: TList; AbsolutionIndex: Integer; CheckShortCutKey: TShortCut): Boolean; overload; var i: Integer; begin Result := true; for i := 0 to TargetList.Count - 1 do begin if (TCustomAction(TargetList.Items[i]).ShortCut = CheckShortCutKey) and (CheckShortCutKey <> 0) and (i <> AbsolutionIndex) then begin Result := false; Break; end; end; end; {------------------------------- //アクションの種類を調べます 機能: カスタマイズ可能アクションと普通のアクションに対して その種類(stHide, stCustomize, stReadOnly)を調べます 戻り値: TShortCutTypeOnDlg 履歴: 2001/04/13 //------------------------------} function TShortCutCustomizeDlg.ActionType( SourceAction: TCustomAction): TShortCutTypeOnDlg; begin {↓カスタマイズ可能アクションならShortCutTypeOnDlgプロパを返す} if (SourceAction is TCanCustomizeAction) then begin Result := TCanCustomizeAction(SourceAction).ShortCutTypeOnDlg; end else {↓普通のアクションでタグが一致するのなら} if (FCustomizeTag <> 0) and (SourceAction.Tag = FCustomizeTag) then begin Result := stCustomize; end else if (FReadOnlyTag <> 0) and (SourceAction.Tag = FReadOnlyTag) then begin Result := stReadOnly; end else begin {↓普通のアクションでタグが一致しなければ} Result := stHide; end; end; //------------------------------ {------------------------------- //グリッドにActionのパラメータをセットします。 引数説明: Action1: 対象アクション 処理: 1.エラーチェック 2.0行ならヘッダ項目指定 3.普通の行ならそれぞれの列に値をセット 備考: 履歴: 2001/04/13 //------------------------------} procedure TShortCutCustomizeDlgForm.RowSetAction( Action1: TCanCustomizeAction; RowIndex: Integer); var i: Integer; begin if RowIndex = 0 then begin {0行目の文字列をセット} for i := 0 to StringGrid1.ColCount-1 do begin StringGrid1.Rows[0].Strings[i] := GridRowTitles[TGridRow(i)]; end; // StringGrid1.Rows[0].CommaText := // 'アクション名,カテゴリ,ヒント,ショートカットキー,カスタマイズ' end else if (1<=RowIndex) and (RowIndex<=StringGrid1.RowCount) then begin with StringGrid1.Rows[RowIndex] do begin Strings[ord(grActionName)]:= Action1.Caption; Strings[ord(grCategory)] := Action1.Category; Strings[ord(grHint)] := Action1.Hint; Strings[ord(grShortcut)] := ShortCutToText(Action1.ShortCut); case Action1.ShortCutTypeOnDlg of stCustomize: Strings[ord(grCustomize)] := '可能'; stReadOnly: Strings[ord(grCustomize)] := '不可'; else raise Exception.Create('アクションの種類が間違っています'); end; end; end else raise Exception.Create('列指定が間違っています'); end; //------------------------------ //------------------------------- //ScrollbarにFocusを与えない procedure TShortCutCustomizeDlgForm.ScrollBar1Enter(Sender: TObject); begin try StringGrid1.SetFocus; except end; end; end.