TabControlのタブを任意の場所に作成する。

解決


武田  2006-01-15 08:37:28  No: 19632

皆様にいつもお世話になっております。本年もよろしくお願いいたします。
環境はWinXP  Delphi6  Personalです。
MDIフォームにWebBrowserを使ってタブブラウザを作成しています。
var
  Child: TformWebBrowser;
・・・・
Child := TformWebBrowser.Create(Application);
Child.WebBrowser1.Navigate(URL);//ナビゲート
でサイトを次々に開とTabControlに右端にタブが追加されていきますが。
途中の適当なタブをアクティブにしておいて、アクティブにしたタブの右隣に新しいタブを追加する(途中に新しいタブが作成される)方法を模索していますがうまくいません。
うまく説明できませんが、任意のタブをアクティブにしてその右隣に新しいタブが開かれるようにしたい。
TabControl1.Tabs[ TabControl1.TabIndex ]で、アクティブタブのindexNoを得て解決しようとしているのですがうまくいきません。
方法がありましたらご指導をお願いいたします。m(_ _)m


わからんちん  2006-01-15 14:56:36  No: 19633

こんなのではダメなんでしょうか?

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TabControl1 do
  begin
    Tabs.Insert(TabIndex + 1, 'New Tab');
    TabIndex := TabIndex + 1;  // 必要があれば
  end;
end;


武田  2006-01-15 21:34:36  No: 19634

わからんちんさん、早速のご指導有り難うございます。
確かに、複数のタブが開いているとき任意のタブをアクティブにしておいてクリックすると右隣に新しいタブができますが、
Child := TformWebBrowser.Create(Application);
Child.WebBrowser1.Navigate(URL);//ナビゲート
で新しいURLを開くとき右隣に開きたいのですが、ナビゲートの時のタブを作成するのはどこで制御しているのでしょうか。
いろいろやってみましたが力不足でできませんでした。
説明がうまくできませんが、任意のタブをアクティブにして、その右隣に新しいナビゲートしたサイトを開きたいのですが。
できましたら、もう少しご助言をいただけたら幸いです。m(_ _)m。


わからんちん  2006-01-15 22:39:27  No: 19635

どちらかと言うと、データ管理の方法・・・な感じですが、
当方、D4 なので、Web アプリができないんですが、
Child を TList で管理してみたらいかがでしょうか?
あるいは、TStringList のほうがいいかも知れません。
URL を文字列リストで、Child を Object で・・・。
ちとあやふやですが、使用には型キャストが必要かもしれません。

-----D4 Help -----------------------------------
TStringList.Insert

Insert メソッドは,リスト内の Index が指定する位置に文字列を挿入します。

procedure Insert(Index: Integer; const S: string); override;

Insert を呼び出すと,リスト内の Index パラメータが指定する位置に
 S パラメータで指定する文字列を追加できます。
Index が 0 の場合に文字列はリストの先頭に挿入され,
Index が 1 の場合に文字列はリストの 2 番目の位置に挿入され,
というふうに順次対応します。
文字列が関連付けられたオブジェクトを持つ場合,
かわりに InsertObject メソッドを使います。
----------------------------------------------------

この用途では、自分なら、TPageControl を使うシーンかなぁと
思ったりしていますが・・・。
タブを選択するたびにWeb Page にアクセスしてるのでしょうか?
(キャッシュなのかも知れませんが・・)


武田  2006-01-17 09:28:09  No: 19636

わからんちん様、再度のご指導有り難うございます。
タブを選択するたびにWeb Page にアクセスしてるのでしょうか?
は何にもしていません(自動だと思います)。
ご指摘の方法をヒントにして、研究してみます。
有り難うございました。m(_ _)m


通りすがらない  2006-01-17 10:23:05  No: 19637

TStringListとかTListとか使う必要なし。
TabControl.TabsがTStrings型であるから・・・

TabControl.Tabs.Add(タブに表示する文字列, 
    Child(TformWebBrowser.Createしたやつ))
で、追加しておけば、タブとChildの連携はとれる。
当然、選択タブのお隣に追加であれば、InsertObjectだがね。

Tabのクリック時には、タブインデックスが確実にわかるので、
TForm(TabControl.Tabs.Objects[TabControl.TabIndex]).Show;
で表示切替可能。

同様に、Screen.ActiveFormChange で、
for i := 0 to Tabs.Count -1 do begin  
  if Tabs.Objects[i] = ActiveになったForm then begin
    TabIndex := i;
    Break;
  end;
end;
これで、フォームが変わったときにタブを切り替えることが可能。

TStringsの継承クラスでは、Objectsプロパティが非常に便利。


Mr.XRAY  URL  2006-01-17 10:26:39  No: 19638

これは,TabContrlの使い方の問題です.
TabControlは,PageControlと違い,ページは一つかありません.したがって,

>Child := TformWebBrowser.Create(Application);

のような使い方はできません.この使い方はPageControlの場合です.
(新しいURLを表示する度にWebBrowserを破棄して,新規作成する場合は別です)
サンプルを書きましたので,試してみて下さい.
PageControlを使用する方が制御が簡単です.リソースが心配ならば別ですが.

//=============================================================================
//  TabControlにURLの内容を表示する例
//  新規プロジェクトに,TabControlを配置,AlignをalClientにする
//  Tabsプロパティ(TStrings)でタブを3つ作成(名前はなんでもいい)
//  TabControl上に,WebBrowserを配置,AlignをAlClientにする.
//  PopUpMenuを一つ配置し,[新規タブ]の名前で一つだけメニューを作成する.
//
//  presented by Mr.XRAY  2006.1.17
//=============================================================================
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  OleCtrls, SHDocVw, ComCtrls, Menus, StdCtrls;

type
  TForm1 = class(TForm)
    TabControl1: TTabControl;
    WebBrowser1: TWebBrowser;
    PopupMenu1: TPopupMenu;
    N1: TMenuItem;
    procedure FormShow(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure WebBrowser1DocumentComplete(Sender: TObject;
      const pDisp: IDispatch; var URL: OleVariant);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//=============================================================================
//  フォームを表示したら,とりあえずデフォルトのURLを表示
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
var
     AUrl: String;
begin
     AUrl:='http://homepage2.nifty.com/Mr_XRAY/';
     WebBrowser1.Navigate(AUrl);
end;
//=============================================================================
//  あるタブをクリックしてアクティブにし,そのポップアップメニューの[新規タブ]
//  をクリックしたら,右に新規にタブを作成し,別のURLを表示
//  TabControlはPageControlと違い,ページが一つしかないとこに注意
//=============================================================================
procedure TForm1.N1Click(Sender: TObject);
var
     ActiveTabNo: Integer;
     AUrl: String;
begin
     ActiveTabNo:=TabControl1.TabIndex;
     TabControl1.Tabs.Insert(ActiveTabNo+1,'読込み中');
     TabControl1.TabIndex:=ActiveTabNo+1;
     AUrl:='http://blog.so-net.ne.jp/bousyo/';
     WebBrowser1.Navigate(AUrl);
end;
//=============================================================================
//  WebBrowserに文書が表示されたら
//  現在アクティブなタブIndexを取得して,そのタブにUrlのLocaltionNameを表示
//=============================================================================
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
     ActiveTabNo: Integer;
begin
     ActiveTabNo:=TabControl1.TabIndex;
     TabControl1.Tabs.Strings[ActiveTabNo]:=WebBrowser1.LocationName;
end;

end.


わからんちん  2006-01-17 17:12:14  No: 19639

>TStringsの継承クラスでは、Objectsプロパティが非常に便利。

なるほど、了解了解。  ちょっとうっかりしてました。これの操作が
必要かも・・ですね。


通りすがらない  2006-01-17 17:55:00  No: 19640

もしかして・・・
自分は、MDIアプリで、メインフォームにはTabControl置いて、
MDIChildで、HPの表示であると考えているのに対し、
わからんちんさん、Mr.XRAY さんは、SDIアプリで、TabControl ないし 
PageControl で各TabにHP表示を行うと考えている?

> タブを選択するたびにWeb Page にアクセスしてるのでしょうか?
この発言も、SDIアプリと考え、TabControlでは1枚分しかブラウザが用意できないから・・・ですよね?

> Child := TformWebBrowser.Create(Application);
こんな書き方しているから、MDIアプリと思ったのだけど、違うのかい? > スレ主さん


Mr.XRAY  URL  2006-01-17 21:19:44  No: 19641

>自分は、MDIアプリで、メインフォームにはTabControl置いて、
>MDIChildで、HPの表示であると考えているのに対し、
---  以下、略  ---

なるほど。でも本人が手順をきちんと書いてないので、どうしても推測が
入るので...  勘弁して下さい。


Mr.XRAY  URL  2006-01-18 03:14:26  No: 19642

> Child := TformWebBrowser.Create(Application);

ここで気づくべきでした.
私は,MDIで,各々のChildFormにタブを使うのだ思っていました.
http://delphi.sakura.vg/lesson26.html

こういうやつですね.多分.


武田  2006-01-21 23:40:32  No: 19643

通りすがらない 様、Mr.XRAY  様、わからんちん様、大勢の先達者の方々にご指導いただき有り難うございました。
その後、いろいろやりましたが、やっぱり解決できないので、最後に頼るのはここのBBSを検索してみようと戻ったら、大勢の先輩方のご指導があるのを知りビックしました。

私めの説明が悪いため、先輩方を混乱させましたことをお詫びいたします。
最初の質問の時、どう表現したらいいか曖昧になりましたが、http://delphi.sakura.vg/lesson26.htmlを参考
にMDIアプリ?(新規作成→その他→プロジェクト→MDIアプリケーションで作成しました)フォームにTabControlをおいてページを開いていく(子ウィンドウは右端に追加される)プログラムです。
今、現時点では通りすがらない様の述べられているのがニュアンス的に合致しているのではと思いますので、これから挑戦してみます。
非常に助かりました。感謝いたします。m(_ _)m


武田  2006-02-03 01:35:16  No: 19644

できました。
わからんちん様、通りすがらない様、Mr.XRAY様(ご指導順)誠に有り難うございました。
その後悪戦苦闘しておりました。とりあえずButtonクリックで動くようになりましたが・・・。
ところが、http://delphi.sakura.vg/index2.htmlのタブブラウザを参考に作成したタブブラウザですから、子ウィンドウに表示していく方式のため通常は
Child := TformWebBrowser.Create(Application);
Child.WebBrowser1.Navigate(URL);
で表示してくれますがそのほか、Google検索から、お気に入りから、新規作成から表示、いろいろなケースで画面表示するものですから、どの部分でコンとローするべきか解りませんでした。
結局WebBrowserを貼り付けてある子ウィンドウになるフォームのOnCreateに
procedure TformWebBrowser.FormCreate(Sender: TObject);
var    ActiveNo :integer; //現在のアクティブタブの番号
begin
    ActiveNo:= formMain.TabControl1.TabIndex;
    if ActiveNo<>-1 then    
        formMain.TabControl1.Tabs.InsertObject(ActiveNo+1,'',TObject(Self))
    else
        formMain.TabControl1.Tabs.AddObject('',TObject(Self));//画面が何もないとき
end;
フォーカス?は
procedure TformWebBrowser.FormActivate(Sender: TObject);
    formMain.TabControl1.TabIndex := formMain.TabControl1.Tabs.IndexOfObject(TObject(Self));
のようにして常にアクティブタブの右隣に新しいウィンドウタブを開くことができました。
新しいタブを削除したら元の左側タブに戻る。
これは、小生が長年Sleipnirで設定していた動きで、どうしても実現したかったものでした。
皆様のご指導を参考に目的が達成できたことを感謝いたします。結果のご報告まで。m(_ _)m


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加