protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; e.Graphics.CompositingQuality = CompositingQuality.HighQuality; e.Graphics.DrawLine(new Pen(this.TabBottomLineColor), new Point(0, this.Height - 1), new Point(this.Width, this.Height - 1)); // 判断重绘区域大小,解决由最小化还原后,无法绘制Tab的问题 if (currPaintTh == null || e.ClipRectangle.Size.Width > TabHeader.Left_Offset) { // 被选中的Tab 需要处于顶层,因此最后绘制 TabHeader thSelected = null; foreach (TabHeader th in lstTabHeader) { if (th.Selected) { thSelected = th; } else { th.DrawAll(e.Graphics, th.Rect); } } // 最后绘制 if (thSelected != null) { thSelected.DrawAll(e.Graphics, thSelected.Rect); } } else { // 绘制完整的TabHeader,如果仅绘制指定区域,可能会出现白色背景 currPaintTh.DrawAll(e.Graphics, currPaintTh.Rect); currPaintTh = null; } }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Button == System.Windows.Forms.MouseButtons.Left && thMouseDown != null) { //Win32API.OutputDebugStringA(string.Format("e.Button == System.Windows.Forms.MouseButtons.Left && thMouseDown != null")); if (!slided) { if (Math.Abs(e.X - pMouseDown.X) > 15) { slided = true; } } else { btnAddNew.Visible = false; Point newPos = thMouseDown.Rect.Location; newPos.X += e.Location.X - pMouseDown.X; // 是否在父窗体范围内移动 if (newPos.X < 0) { newPos.X = 0; } //防止将标签拖动到窗口右上角控制按钮区域 if (newPos.X > (this.Width - this.ControlBoxWidth - thMouseDown.Rect.Width)) { newPos.X = this.Width - this.ControlBoxWidth - thMouseDown.Rect.Width; } // 判断移动方向,向左或向右 if (e.Location.X - pMouseDown.X > 0) { // 判断是否已经是最后一个Tab if (thMouseDown.TabIndex != lstTabHeader.Count - 1) { TabHeader thRight = lstTabHeader[thMouseDown.TabIndex + 1]; // 向右移动时,判断是否与后一Tab 交换位置:当前Tab的 Right ,超过后一Tab 位置的一半 if (newPos.X + tabWidth > thRight.Rect.X + tabWidth / 2) { thRight.TabIndex--; thMouseDown.TabIndex++; lstTabHeader.Sort(); } } } else { // 判断是否已经是第0个Tab if (thMouseDown.TabIndex != 0) { TabHeader thLeft = lstTabHeader[thMouseDown.TabIndex - 1]; // 向右移动时,判断是否与后一Tab 交换位置:当前Tab的 Right ,超过后一Tab 位置的一半 if (newPos.X < thLeft.Rect.X + tabWidth / 2) { thLeft.TabIndex++; thMouseDown.TabIndex--; lstTabHeader.Sort(); } } } thMouseDown.Rect.X = newPos.X; pMouseDown = e.Location; this.Invalidate(); } } if (e.Button == System.Windows.Forms.MouseButtons.Left && bolMouseDownNothing) { //Win32API.OutputDebugStringA(string.Format("e.Button == System.Windows.Forms.MouseButtons.Left && bolMouseDownNothing")); //这里会导致窗口位置移动,BUG //Win32API.OutputDebugStringA(string.Format("没有选中标签,当前坐标为:X:{0},Y:{1}", pMouseDown.X, pMouseDown.Y)); if (this.Parent != null) { //Win32API.OutputDebugStringA(string.Format("当前控件的父控件为:{0},Handle为:{1}", this.Parent, this.Parent.Handle)); Form tmpForm = this.Parent as Form; if (tmpForm != null) { tmpForm.Location = new Point(tmpForm.Location.X + e.X - pMouseDown.X, tmpForm.Location.Y + e.Y - pMouseDown.Y);; } } } else { //判断当前标签是否是鼠标悬停 pMouseMove = e.Location; //thMouseMove = null; //Win32API.OutputDebugStringA( string.Format("当前鼠标坐标为X:{0}, y{1}", pMouseMove.X,pMouseMove.Y) ); try { foreach (TabHeader th in lstTabHeader) { //如果当前标签有鼠标悬停 if (th.HitTest(pMouseMove)) { //如果当前标签是已经选择的标签,跳过 if (!th.Selected) { th.Hovered = true; //thMouseMove = th; } else { th.Hovered = false; } //将当前标签的标题作为ToolTip显示 if (th.TitleHitTest(pMouseMove)) { //判断当前标签的有鼠标悬停 if (toolTip1 != null) { if (!toolTip1.GetToolTip(this).Equals(th.Title)) { toolTip1.SetToolTip(this, th.Title); } } } else { if (toolTip1 != null) { toolTip1.Hide(this); } } } else { th.Hovered = false; } //Win32API.OutputDebugStringA(string.Format("标签是否选择:{0} , 是否鼠标悬停:{1}!", th.Selected, th.Hovered)); } } catch (Exception ex) { } this.Invalidate(); } }
/// <summary> /// 销毁一个标签释放标签中的对象 /// </summary> /// <param name="tab"></param> private void DeleteOneTab(TabHeader tab) { try { int intTabIndex = -1; intTabIndex = tab.TabIndex; //如果当前关闭的标签的客户端主窗口句柄不等于IntPtr.Zero,则关闭 if (tab.ClientHandle != IntPtr.Zero) { //发送消息,让子进程退出 //Win32API.CloseWindow(tab.ClientHandle); int ret = Win32API.PostMessageA(tab.ClientHandle, Win32API.WM_CLOSE, 0, 0); //int ret = Win32API.DestroyWindow(tab.ClientHandle); //Win32API.OutputDebugStringA( string.Format("发送API命令Win32API.PostMessageA给{0},返回值:{1},LastErrorCode:{2}", tab.ClientHandle, ret, Win32API.GetLastError() )); } // //从标签列表中移除当前选择的标签(标签上的关闭按钮被点击) lstTabHeader.Remove(tab); tab.Dispose(); //重新计算剩余标签的宽度 widthCalculate(false); //重置所有标签为未选中状态,并重新设置标签编号 for (int i = 0; i < lstTabHeader.Count; i++) { lstTabHeader[i].TabIndex = i; lstTabHeader[i].Selected = false; } //如果关闭了标签,则激活该标签右侧的标签,如果为0或<0,不激活 try { //OutputDebugStringA(string.Format("当前删除的标签索引{0}", intTabIndex)); //至少有3个标签0,1,2,删除1号,2号成了1号 if (lstTabHeader.Count > 1) { //如果当前删除的标签号是最后一个标签,则激活左侧的标签 if (lstTabHeader.Count == intTabIndex) { intTabIndex = intTabIndex - 1; } lstTabHeader[intTabIndex].Selected = true; thMouseDownPublic = lstTabHeader[intTabIndex]; if (thMouseDownPublic.ClientHandle != IntPtr.Zero) { //显示到最前面 Win32API.MoveWindow(thMouseDownPublic.ClientHandle, 0, 0, pnlWebBrowser.Width, pnlWebBrowser.Height, 1); Win32API.ShowWindow(thMouseDownPublic.ClientHandle, 1); } } //至少有2个标签0,1,删除1号,直接激活0号 else if (lstTabHeader.Count == 1) { //OutputDebugStringA(string.Format("当前删除的标签索引条件:intTabIndex == 0")); lstTabHeader[0].Selected = true; thMouseDownPublic = lstTabHeader[0]; if (thMouseDownPublic.ClientHandle != IntPtr.Zero) { //显示到最前面 Win32API.MoveWindow(thMouseDownPublic.ClientHandle, 0, 0, pnlWebBrowser.Width, pnlWebBrowser.Height, 1); Win32API.ShowWindow(thMouseDownPublic.ClientHandle, 1); } } } catch (Exception ex) { //OutputDebugStringA(string.Format("切换标签时发生了错误:{0}", ex.Message )); } lstTabHeader.Sort(); this.Invalidate(); } catch (Exception ex) { // } }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); thMouseDown = null; //Win32API.OutputDebugStringA(string.Format("OnMouseDown 按键为:{0} ,{1}次点击!", e.Button, e.Clicks )); if (e.Button == System.Windows.Forms.MouseButtons.Left && e.Clicks == 1) { pMouseDown = e.Location; bolDbClickedFlag = false; PublicModule.IsHeadDbClicked = false; foreach (TabHeader th in lstTabHeader) { if (th.HitTest(pMouseDown)) { thMouseDown = th; thMouseDown.Selected = true; thMouseDownPublic = th; break; } } //切换当前标签页的浏览器控件到前台显示 try { if (thMouseDown != null) { //利用子进程的Handle,让其显示 if (thMouseDown.ClientHandle != IntPtr.Zero) { //发送消息,让它显示到前台 Win32API.MoveWindow(thMouseDown.ClientHandle, 0, 0, pnlWebBrowser.Width, pnlWebBrowser.Height, 1); Win32API.ShowWindow(thMouseDown.ClientHandle, 1); } //重新设置消息 try { //FormMain tmpForm = pnlWebBrowser.Parent as FormMain; if (tempFormMain != null && thPreviousMouseDown != thMouseDown) { string strcommand = string.Format("/cmd:getstatus,{0}", thMouseDown.ClientName); tempFormMain.SendToClient(strcommand, thMouseDown.ClientName); Win32API.OutputDebugStringA(string.Format("发消息 /cmd:getstatus 给{0}", thMouseDown.ClientName)); } } catch (Exception ex) { string errmessage = string.Format("发送命令/cmd:getstatus到客户端{0},发生错误{1}", thMouseDown.ClientName, ex.Message); Win32API.OutputDebugStringA(errmessage); } } } catch (Exception ex) { //do something } if (thMouseDown != null) { //选中了标签 bolMouseDownNothing = false; foreach (TabHeader th in lstTabHeader) { if (th != thMouseDown) { th.Selected = false; if (th.ClientHandle != IntPtr.Zero) { Win32API.ShowWindow(th.ClientHandle, 0); } } } this.Invalidate(); } else { //移动窗口 bolMouseDownNothing = true; } //记录当前标签有无变更,如果没变更,不做下一步操作 thPreviousMouseDown = thMouseDown; } else if (e.Button == System.Windows.Forms.MouseButtons.Left && e.Clicks == 2) { //双击 bolDbClickedFlag = true; //双击标签,并不是按下非标签区域,置为False,壁纸还原时位置在鼠标点击位置 bolMouseDownNothing = false; PublicModule.IsHeadDbClicked = true; //判断当前点击位置是否有标签 pMouseDown = e.Location; //遍历所有标签,进行点击测试 foreach (TabHeader th in lstTabHeader) { if (th.HitTest(pMouseDown)) { thMouseDown = th; thMouseDown.Selected = th.Selected; break; } } // if (thMouseDown != null) { if (DbClickCloseTab) { //如果当前选择了标签,并且标签数量大于1个(编号从0开始) //OutputDebugStringA(string.Format("当前标签总数:{0}", lstTabHeader.Count)); if (thMouseDown != null && lstTabHeader.Count > 1) { // DeleteOneTab(thMouseDown); } } return; } //Win32API.OutputDebugStringA(string.Format("没有选中标签,当前坐标为:X:{0},Y:{1}", pMouseDown.X, pMouseDown.Y)); //Win32API.OutputDebugStringA("双击标签栏的空白区域!"); if (tempFormMain != null) { if (tempFormMain.WindowState == FormWindowState.Normal) { //Win32API.OutputDebugStringA( string.Format("主窗口的left:{0},top:{1}", oldLocation.X, oldLocation.Y) ); tempFormMain.WindowState = FormWindowState.Maximized; tempFormMain.HideBorder = true; cbtnMaximized.StateImage = Resources.res_mask4; } else if (tempFormMain.WindowState == FormWindowState.Maximized) { tempFormMain.WindowState = FormWindowState.Normal; tempFormMain.HideBorder = false; cbtnMaximized.StateImage = Resources.max_mask4; //Win32API.OutputDebugStringA(string.Format("主窗口的left:{0},top:{1}", tmpForm.Location.X, tmpForm.Location.Y )); } else { tempFormMain.WindowState = FormWindowState.Normal; tempFormMain.HideBorder = false; } } if (this.Parent != null) { //Win32API.OutputDebugStringA(string.Format("当前控件的父控件为:{0},Handle为:{1}", this.Parent, this.Parent.Handle)); //Form tmpForm = this.Parent as Form; //if (tmpForm != null) //{ // if (tmpForm.WindowState == FormWindowState.Normal) // { // //Win32API.OutputDebugStringA( string.Format("主窗口的left:{0},top:{1}", oldLocation.X, oldLocation.Y) ); // tmpForm.WindowState = FormWindowState.Maximized; // cbtnMaximized.StateImage = Resources.res_mask4; // } // else if (tmpForm.WindowState == FormWindowState.Maximized) // { // tmpForm.WindowState = FormWindowState.Normal; // cbtnMaximized.StateImage = Resources.max_mask4; // //Win32API.OutputDebugStringA(string.Format("主窗口的left:{0},top:{1}", tmpForm.Location.X, tmpForm.Location.Y )); // } // else // { // tmpForm.WindowState = FormWindowState.Normal; // } //} } } }
public int CompareTo(object o) { TabHeader th = o as TabHeader; return(this.tabIndex.CompareTo(th.TabIndex)); }