개별 탭의 닫기를위한 탭 콘트롤 사용자 정의
-
03-07-2019 - |
문제
내 시나리오는 다음과 같습니다.
C#의 winforms 응용 프로그램을 작업중인 Tabcontrol의 메인 페이지 안에 버튼이있는 버튼이있어 클릭 할 때마다 다른 탭 페이지를 생성합니다. 각각의 새로운 탭 페이지에는 사용자 컨트롤로 정의 된 레이아웃이 포함됩니다.
내 질문은 다음과 같습니다.
사용자가 런타임에 동적으로 생성 된 탭 중 하나를 닫을 수 있도록하려면 어떻게해야합니까?
Tabcontrol 자체를 수정하여 각 탭에 특정 탭에 작은 'x'가 있도록하는 방법은 특정 탭을 닫으려면 사용자가 클릭 할 수있는 방법을 어떻게 수정할 수 있습니까? (Firefox와 마찬가지로)
사용자 컨트롤 내부의 버튼을 대신 탭을 닫으려면 탭 콘트롤의 선택된 index 속성을 사용자 컨트롤에 어떻게 노출시킬 수 있습니까?
해결책
1 년 전에 파생 된 탭 컨트롤을 만들었습니다. 나는 길이가 약 700 줄이고 매우 지저분한 코딩 되었기 때문에 여기에 소스를 게시하지 않을 것입니다. 어쩌면 코드를 정리 한 다음 여기에서 출시 할 시간을 찾을 수 있습니다. 지금은 건축 방식을 간단히 설명하겠습니다.
각 탭 페이지에는 'X'아이콘이 있습니다. 왼쪽 제목과 탭 페이지의 탭 페이지는 드래그 앤 드롭으로 재주문을 지원하고 여러 탭 컨트롤 사이에 이동합니다.
탭 페이지에서 아이콘을 얻는 쉬운 방법을 선택합니다. 탭 컨트롤에는 TabControl.ImageList
속성과 탭 페이지에는 a가 있습니다 TabPage.ImageIndex
재산. 그래서 방금 이미지 목록에 3 개의 아이콘을 추가했습니다 - 정상, 호버, 누르기 - 마우스 이벤트를 처리했습니다.
와 함께 TabControl.GetTabRect()
마우스가 특정 탭 페이지에 있는지 여부를 테스트하고 일부 수학을 통해 아이콘 위에 있는지 여부를 찾을 수 있습니다. 그런 다음 마우스 버튼 상태에 따라 아이콘을 변경하고 버튼을 누르면 마우스 아래의 탭 페이지를 제거하면됩니다.
이 솔루션의 주요 문제는 마우스가 아이콘 위에 있는지 계산하는 것이 탭 페이지와 관련하여 아이콘이 어디에 있는지 알아야하며 새로운 Windows 버전으로 변경 될 수 있다는 것입니다. 그리고 아이콘은 제목의 왼쪽에 있지만 너무 나쁘지는 않습니다.
다른 팁
이 코드를 찾았고 나에게 매우 도움이되었습니다.
private void tabControl_MouseUp(object sender, MouseEventArgs e)
{
// check if the right mouse button was pressed
if(e.Button == MouseButtons.Right)
{
// iterate through all the tab pages
for(int i = 0; i < tabControl1.TabCount; i++)
{
// get their rectangle area and check if it contains the mouse cursor
Rectangle r = tabControl1.GetTabRect(i);
if (r.Contains(e.Location))
{
// show the context menu here
System.Diagnostics.Debug.WriteLine("TabPressed: " + i);
}
}
}
}
다음을 수행했습니다. TabPage
무대, 나는 a toolStrip
ToolStrip ts = new ToolStrip();
ts.Dock = DockStyle.Top;
ts.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
그런 다음 작성하십시오 X
버튼을 추가하고 추가하십시오 toolstrip
ToolStripButton ToolStripButton = new ToolStripButton("X");
ts.Items.Add(ToolStripButton);
클릭 할 때 이벤트를 만듭니다 X
단추
ToolStripButton.Click += new EventHandler(ToolStripButton_Click);
추가하다 toolstrip
~로 tabpage
tabControl1.TabPages[curenttabpage].Controls.Add(ts);
지금 용 ToolStripButton_Click
다음과 같다:
void ToolStripButton_Click(object sender, EventArgs e)
{
ToolStripButton t = (ToolStripButton)(sender);
ToolStrip ts = t.Owner;
TabPage tb = (TabPage)
(ts.Parent);tabControl1.TabPages.Remove(tb);
}
어쩌면 원하는대로는 아니지만 잘 작동합니다.
비슷한 설정을 만들었습니다.
런타임에 탭 페이지에 추가되는 각 컨트롤은 내가 만든 특수 기본 컨트롤에서 파생됩니다. 이 기본 제어에는 닫기 버튼이 있습니다 (Safe to Close Flag와 같은 다른 기능과 함께).
내 기본 제어에서 사용중인 탭 코드 닫기 :
TabPage tabpage = (TabPage)this.Parent;
TabControl tabControl = (TabControl)tabpage.Parent;
tabControl.TabPages.Remove(parent);
나는 이것이 오래된 스레드라는 것을 알고 있지만 나는 이것을 찾았다 링크 그러면 배열에서 탭을 "숨길"할 수있게 한 다음 런타임에 원하는 탭을 다시로드 할 수 있습니다. 나는 그것을 쉽게 찾을 수있는 장소에 이것을 더 추가했다.
이 코드는 Throgh가 중간 마우스로 탭 컨트롤을 닫는 데 도움이 될 수 있습니다.
private void tabControl1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != System.Windows.Forms.MouseButtons.Middle)
return;
for (int i = 0; i < MainTabControl.TabPages.Count; i++)
{
if (this.MainTabControl.GetTabRect(i).Contains(e.Location))
{
this.MainTabControl.TabPages.RemoveAt(i);
return;
}
}
}
작동합니다!
TabPage tabpage = (TabPage)this.Parent;
TabControl tabControl = (TabControl)tabpage.Parent;
tabControl.TabPages.Remove(tabpage);