4

我想限制用户(基于特殊条件)在页面控件中打开或不打开选项卡。即,用户可以单击选项卡,但不会向他显示。相反,一条消息将向他显示“ he don't have the access right to see such tab”。

在什么事件上我应该编写检查代码,以及(TPageControl组件的)哪个选项卡属性将允许/阻止用户进入这样的选项卡?

4

4 回答 4

7

在理想的世界中,您将设置AllowChangeFalseOnChanging事件中阻止页面更改。但是,这似乎不可行,因为我无法从内部辨别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;

我知道相当混乱,但它具有工作的优点!

于 2011-12-05T11:06:48.617 回答
3

OnChanging事件不允许您确定正在选择哪个选项卡,因为 Windows 本身不报告该信息。但是,您可以做的是将属性子类化以在处理消息之前TPageControl.WindowProc拦截发送到的消息。TPageControl使用鼠标消息来确定直接单击哪个选项卡(查看TPageControl.IndexOfTabAt()方法),并使用键盘消息检测左/右箭头按下以确定哪个选项卡与活动选项卡相邻(查看TPageControl.FindNextPage()方法)。

于 2011-12-05T19:29:40.580 回答
1

使用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;

好的,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;
于 2011-12-05T10:57:02.897 回答
0

Sometimes it is better just to hide unwanted TabSheets with something like this:

TabSheetNN.TabVisible:=Somecondition;

than trying to prevent switching to these tabs. Sure, it would be better if Sender in OnChanging event will be TabSheet , not TPageControl.

于 2014-07-24T16:38:17.493 回答