如何允许或禁止用户在页面控件中输入制表符?

4

我希望能够根据特定条件限制用户是否可以打开页面控件中的选项卡。也就是说,用户可以点击选项卡,但是不会显示给他。相反,会向他显示一个消息,提示“他没有权限查看此选项卡”。

在哪个事件中编写检查代码?TPageControl组件的哪个选项卡属性可以允许/阻止用户进入该选项卡?


4
如果用户无法看到内容,为什么一开始要显示这个选项卡呢? - whosrdaddy
你可以详细说明一下当前发生的情况吗?这样我们就可以为你的任务建议最佳的安全和GUI标准。 - Marcus Adams
当然,我正在设计一个员工屏幕,其中包含个人信息,他的合同信息和家庭信息,每个标签都不同。因此,具有特权的超级用户可以查看合同信息,但是其他特权较低的用户只能查看家庭信息并编辑它,但不能查看他的合同信息(如薪水,津贴等)。如果您有更好的设计,请告诉我,这将拯救我的生命(和我的工作)。谢谢大家。 - Amanda
5个回答

7
在理想的情况下,您应该在 OnChanging 事件中将 AllowChange 设置为 False 以阻止页面更改。 但是,这似乎不可行,因为我找不到任何方法可以从 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;

相当混乱,但它的好处在于可行!

如果您在代码中更改活动页面索引,例如self.PageControl1.ActivePageIndex:= 1;,则不起作用。 - Ravaut123
4
@Ravaut123,确实不会出现这种情况。由于您控制编写的代码,因此避免出现这样的错误应该很容易。 - David Heffernan

3
OnChanging事件无法确定哪个选项卡正在被选择,因为Windows本身不会报告该信息。但是,您可以子类化TPageControl.WindowProc属性以拦截发送到TPageControl的消息,然后再处理它们。使用鼠标消息直接确定点击了哪个选项卡(查看TPageControl.IndexOfTabAt()方法),并使用键盘消息检测左/右箭头按键以确定活动选项卡旁边的选项卡(查看TPageControl.FindNextPage()方法)。

2
使用页面控件的 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;

好的,PageControl1.TabIndex是当前选中的页而不是我想要选择的那一页。我该如何获取所点击的页面。

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;

1
很遗憾,这不起作用,因为TabIndex是当前选定的页面,而不是用户正在尝试选择的页面。 - David Heffernan
3
@Ravault - 当标签按钮处于活动状态时,也可以使用Ctrl+Tab或箭头切换到新标签页。 - Sertac Akyuz
@Sertac你知道我们寻求的信息是否可以在TVN_SELCHANGING中获得吗? - David Heffernan
2
@David - 不,我同意你在答案中的评估。不过我不喜欢这个解决方案... <g> - Sertac Akyuz
我认为仍然有一些挑剔的箭头,但是好的观点已经被接受了,可以派生一个新的控件来解决问题。 - Sertac Akyuz
显示剩余3条评论

1
您可以在TPageControl的OnChanging事件中显示选项卡并有效地禁用更改。您需要做的就是将AllowChange变量设置为False。
procedure TForm1.PageControl1(Sender: TObject; var AllowChange: Boolean); 
begin
    AllowChange := MyCondition;
    if MyCondition
        ShowMessage('User doesn''t have permission to see this tab.');
end

0
有时候最好的方法就是使用类似这样的代码来隐藏不需要的选项卡:
TabSheetNN.TabVisible:=Somecondition;

与其试图阻止切换到这些选项卡,不如将OnChanging事件中的Sender设置为TabSheet,而非TPageControl,这样会更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接