(特別な条件に基づいて)ユーザーがページコントロールでタブを開くかどうかを制限したい。つまり、ユーザーはタブをクリックできますが、表示されません。代わりに、メッセージが彼に「he don't have the access right to see such tab
」と表示されます。
どのイベントでチェックコードを書く必要があり、(TPageControl
コンポーネントの)どのタブプロパティがユーザーにそのようなタブへの入力を許可/ブロックしますか?
(特別な条件に基づいて)ユーザーがページコントロールでタブを開くかどうかを制限したい。つまり、ユーザーはタブをクリックできますが、表示されません。代わりに、メッセージが彼に「he don't have the access right to see such tab
」と表示されます。
どのイベントでチェックコードを書く必要があり、(TPageControl
コンポーネントの)どのタブプロパティがユーザーにそのようなタブへの入力を許可/ブロックしますか?
理想的な世界では、ページの変更をブロックするためにイベントから設定AllowChange
します。ただし、ユーザーが選択しようとしているページを内部から見分ける方法が見つからないため、これは実行可能ではないようです。False
OnChanging
OnChanging
基礎となるWindows通知を見ても、ほとんど希望がないようです。通知はコントロールを識別しますTCN_SELCHANGING
が、私が知る限り、関係するページについては何も述べていません。
私が思いつくことができる最善の方法はOnChanging
、現在アクティブなページをメモしてから、でハードワークを実行することですOnChange
。選択したページが望ましくないものに変更された場合は、元に戻します。
procedure TForm1.PageControl1Changing(Sender: TObject; var AllowChange: Boolean);
begin
FPreviousPageIndex := PageControl1.ActivePageIndex;
end;
procedure TForm1.PageControl1Change(Sender: TObject);
begin
if PageControl1.ActivePageIndex=1 then begin
PageControl1.ActivePageIndex := FPreviousPageIndex;
Beep;
end;
end;
私が知っているかなり厄介ですが、それは働くことの美徳を持っています!
このOnChanging
イベントでは、どのタブが選択されているかを判断できません。これは、Windows 自体がその情報を報告しないためです。ただし、TPageControl.WindowProc
プロパティをサブクラス化して、に送信されるメッセージをTPageControl
処理する前にインターセプトすることができます。マウス メッセージを使用して、どのタブが直接クリックされているかを判断し (TPageControl.IndexOfTabAt()
メソッドを参照)、キーボード メッセージを使用して左/右矢印の押下を検出し、アクティブなタブに隣接しているタブを特定します (TPageControl.FindNextPage()
メソッドを参照)。
OnChanging
ページ コントロールのイベントを使用します。
procedure TForm1.PageControl1Changing(Sender: TObject; var AllowChange: Boolean);
begin
if (self.PageControl1.TabIndex= 1)and
(NotAllowUser = 'SomePerson') then
begin
AllowChange:= False;
ShowMessage('Person not allow for this Tab');
end;
end;
OK、PageControle1.TabIndex は activepageindex であり、選択したいものではありません。クリックしたページを取得するにはどうすればよいですか。
procedure TForm1.PageControl1Changing(Sender: TObject; var AllowChange: Boolean);
var
P: TPoint;
NewTabIndex: Integer;
begin
P := PageControl1.ScreenToClient(Mouse.CursorPos);
NewTabIndex := PageControl1.IndexOfTabAt(P.X, P.y);
if (NewTabIndex= 1) then
begin
AllowChange:= false;
Beep
end;
end;
新しい試み
TMyPageControl = Class(TPageControl)
private
FNewTabSheet: TTabSheet;
FOnMyChanging: TMyTabChangingEvent;
procedure SetOnMyChanging(const Value: TMyTabChangingEvent);
procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
protected
function CanChange: Boolean; Override;
public
property OnMyChanging: TMyTabChangingEvent read FOnMyChanging write SetOnMyChanging;
End;
{ TMyPageControl }
function TMyPageControl.CanChange: Boolean;
begin
Result := True;
if Assigned(FOnMyChanging) then FOnMyChanging(Self, FNewTabSheet ,Result);
end;
procedure TMyPageControl.CMDialogKey(var Message: TCMDialogKey);
begin
if (Focused or Windows.IsChild(Handle, Windows.GetFocus)) and
(Message.CharCode = VK_TAB) and (GetKeyState(VK_CONTROL) < 0) then
begin
FNewTabSheet := FindNextPage(ActivePage, GetKeyState(VK_SHIFT) >= 0,True);
SelectNextPage(GetKeyState(VK_SHIFT) >= 0);
Message.Result := 1;
end else
inherited;
end;
procedure TMyPageControl.CNNotify(var Message: TWMNotify);
var
P: TPoint;
NewTabIndex: Integer;
begin
with Message do
case NMHdr.code of
TCN_SELCHANGE:
Change;
TCN_SELCHANGING:
begin
Result := 1;
P := self.ScreenToClient(Mouse.CursorPos);
NewTabIndex := self.IndexOfTabAt(P.X, P.y);
FNewTabSheet:= self.Pages[NewTabIndex];
if CanChange then Result := 0;
end;
end;
end;
procedure TMyPageControl.SetOnMyChanging(const Value: TMyTabChangingEvent);
begin
FOnMyChanging := Value;
end;
場合によっては、次のような方法で不要な TabSheet を非表示にすることをお勧めします。
TabSheetNN.TabVisible:=Somecondition;
これらのタブへの切り替えを防止しようとするよりも。確かに、OnChanging イベントの Sender が TPageControl ではなく TabSheet である方がよいでしょう。