📄 outlookbar.cs
字号:
Point pt = new Point(0,0);
// Set clip region so that we don't draw outside the viewport
Rectangle viewPortRect = GetViewPortRect();
if ( targetRect != Rectangle.Empty )
viewPortRect = targetRect;
Region clippingRegion = new Region(viewPortRect);
g.Clip = clippingRegion;
// Clip the arrow buttons
g.ExcludeClip(downArrowRect);
g.ExcludeClip(upArrowRect);
Color textColor = band.TextColor;
Color backColor = band.Background;
Color highLight = band.Background;
if ( ColorUtil.UsingCustomColor )
{
backColor = ColorUtil.VSNetControlColor;
highLight = ColorUtil.VSNetControlColor;
}
if ( hot )
{
backColor = ColorUtil.VSNetSelectionColor;
highLight = ColorUtil.VSNetBorderColor;
}
if ( pressed ) backColor = ColorUtil.VSNetPressedColor;
if ( band.IconView == IconView.Large && band.LargeImageList != null )
{
Size largeImageSize = band.LargeImageList.ImageSize;
pt.X = itemRect.Left + (viewPortRect.Width - largeImageSize.Width) / 2;
pt.Y = itemRect.Top;
Rectangle iconRect = new Rectangle(pt, largeImageSize);
using ( Brush b = new SolidBrush(backColor) )
{
iconRect.Inflate(2,2);
if ( backgroundBitmap != null )
{
g.DrawImage(backgroundBitmap, iconRect, iconRect, GraphicsUnit.Pixel);
// If we have a background bitmap, draw the item background
// only during the hot state
if ( hot)
{
g.FillRectangle(b, iconRect.Left, iconRect.Top,
iconRect.Width, iconRect.Height);
}
}
else
{
// If we don't have a background, always draw the
// item backgound
g.FillRectangle(b, iconRect.Left, iconRect.Top,
iconRect.Width, iconRect.Height);
}
using ( Pen p = new Pen(highLight) )
{
if ( backgroundBitmap == null || hot == true )
{
g.DrawRectangle(p, iconRect.Left, iconRect.Top, iconRect.Width-1, iconRect.Height-1);
}
}
}
// I dont' use the image list to do the drawing because cliping does not work
if ( band.Items[index].ImageIndex != -1 && band.LargeImageList != null )
{
// Only if we have a valid image index
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(band.LargeImageList.Images[band.Items[index].ImageIndex], pt);
g.SmoothingMode = SmoothingMode.Default;
}
// Draw the label
int top = itemRect.Top + largeImageSize.Height + Y_LARGEICON_LABEL_OFFSET;
Size textSize = GetLabelSize(g, band, index);
int left = itemRect.Left + (viewPortRect.Width - textSize.Width) / 2;
using ( Brush b = new SolidBrush(textColor) )
{
g.DrawString(band.Items[index].Text, Font, b, new Point(left, top));
}
// Reset clip region to the whole rectangle so that the arrows can be painted
clippingRegion.Dispose();
g.Clip = new Region(viewPortRect);
}
else if ( band.IconView == IconView.Small && band.SmallImageList != null )
{
Size smallImageSize = band.SmallImageList.ImageSize;
pt.X = itemRect.Left;
pt.Y = itemRect.Top + (itemRect.Height - smallImageSize.Height)/2;
Rectangle iconRect = new Rectangle(pt, smallImageSize);
using ( Brush b = new SolidBrush(backColor) )
{
iconRect.Inflate(1,1);
if ( backgroundBitmap != null )
{
g.DrawImage(backgroundBitmap, iconRect, iconRect, GraphicsUnit.Pixel);
// If we have a background bitmap, draw the item background
// only during the hot state
if ( hot)
{
g.FillRectangle(b, iconRect.Left, iconRect.Top,
iconRect.Width, iconRect.Height);
}
}
else
{
// If we don't have a background, always draw the
// item backgound
g.FillRectangle(b, iconRect.Left, iconRect.Top,
iconRect.Width, iconRect.Height);
}
using ( Pen p = new Pen(highLight) )
{
if ( backgroundBitmap == null || hot == true )
{
g.DrawRectangle(p, iconRect.Left, iconRect.Top, iconRect.Width-1, iconRect.Height-1);
}
}
}
// I dont' use the image list to do the drawing because cliping does not work
if ( band.Items[index].ImageIndex != -1 && band.SmallImageList != null )
{
// Only if we have a valid image index
g.DrawImage(band.SmallImageList.Images[band.Items[index].ImageIndex], pt);
}
// Draw the label
Size labelSize = GetLabelSize(g, band, index);
pt.X = pt.X + smallImageSize.Width + X_SMALLICON_LABEL_OFFSET;
pt.Y = itemRect.Top + (itemRect.Height - labelSize.Height)/2;
using ( Brush b = new SolidBrush(textColor) )
{
g.DrawString(band.Items[index].Text, Font, b, pt);
}
}
}
void AnimateScroll(int From, int To)
{
if ( currentBandIndex == -1 || bands.Count == 0 ) return;
OutlookBarBand band = bands[currentBandIndex];
// Make sure we are whithin bounds
Debug.Assert(From >= 0 && From < bands.Count);
Debug.Assert(To >= 0 && To < bands.Count);
// Get needed dimensions
Rectangle viewPortRect = GetViewPortRect();
Rectangle headerRect = new Rectangle(0, 0, viewPortRect.Width, BAND_HEADER_HEIGHT);
Rectangle drawingRect = new Rectangle(0, 0, viewPortRect.Width, viewPortRect.Height + headerRect.Height * 2);
// Use straight GDI to do the drawing
IntPtr hDC = WindowsAPI.GetDC(Handle);
IntPtr hDCFrom = WindowsAPI.CreateCompatibleDC(hDC);
IntPtr hDCTo = WindowsAPI.CreateCompatibleDC(hDC);
IntPtr bmFrom = WindowsAPI.CreateCompatibleBitmap(hDC, drawingRect.Width, drawingRect.Height);
IntPtr bmTo = WindowsAPI.CreateCompatibleBitmap(hDC, drawingRect.Width, drawingRect.Height);
// Select in the drawing surface
IntPtr hOldFromBitmap = WindowsAPI.SelectObject(hDCFrom, bmFrom);
IntPtr hOldToBitmap = WindowsAPI.SelectObject(hDCTo, bmTo);
// Draw in the memory device context
Graphics gHeaderDC;
if ( To > From )
gHeaderDC = Graphics.FromHdc(hDCTo);
else
gHeaderDC = Graphics.FromHdc(hDCFrom);
DrawBandBitmap(hDCFrom, bands[From], From, drawingRect);
DrawBandBitmap(hDCTo, bands[To], To, drawingRect);
DrawHeader(gHeaderDC, To, new Rectangle(drawingRect.Left, drawingRect.Top,
drawingRect.Width, drawingRect.Top + BAND_HEADER_HEIGHT), Border3DStyle.RaisedInner);
Rectangle rectFrom = GetHeaderRect(From);
Rectangle rectTo = GetHeaderRect(To);
int headerHeight = rectFrom.Height;
// Do the animation with the bitmaps
if ( To > From)
{
for (int y = rectTo.Top - headerHeight; y > rectFrom.Bottom; y -= headerHeight)
{
// Draw From bitmap
WindowsAPI.BitBlt(hDC, viewPortRect.Left ,rectFrom.Bottom + 1,
viewPortRect.Width, y - rectFrom.Bottom - 1, hDCFrom, 0 , 0, (int)PatBltTypes.SRCCOPY);
// Draw To Bitmap
WindowsAPI.BitBlt(hDC, viewPortRect.Left, y, viewPortRect.Width,
viewPortRect.Bottom - y + headerHeight, hDCTo, 0, 0, (int)PatBltTypes.SRCCOPY);
Thread.Sleep(animationSpeed);
}
}
else
{
Rectangle rcTo = new Rectangle(viewPortRect.Left,
viewPortRect.Bottom, viewPortRect.Width, viewPortRect.Bottom - headerHeight);
for (int y = rectFrom.Top + 1; y < rcTo.Top - headerHeight; y += headerHeight)
{
// Draw To Bitmap
WindowsAPI.BitBlt(hDC, viewPortRect.Left, rectFrom.Top, viewPortRect.Width,
y - rectFrom.Top - 1, hDCTo, 0, 0, (int)PatBltTypes.SRCCOPY);
// Draw From bitmap
WindowsAPI.BitBlt(hDC, viewPortRect.Left , y,
viewPortRect.Width, viewPortRect.Bottom - y, hDCFrom, 0 , 0, (int)PatBltTypes.SRCCOPY);
Thread.Sleep(animationSpeed);
}
}
// Cleanup
WindowsAPI.ReleaseDC(Handle, hDC);
WindowsAPI.DeleteDC(hDCFrom);
WindowsAPI.DeleteDC(hDCTo);
WindowsAPI.SelectObject(hDCFrom, bmFrom);
WindowsAPI.SelectObject(hDCTo, bmTo);
WindowsAPI.DeleteObject(bmFrom);
WindowsAPI.DeleteObject(bmTo);
}
void DrawBandBitmap(IntPtr hDC, OutlookBarBand band, int bandIndex, Rectangle drawingRect)
{
// Don't do GDI+ calls since you cannot mix them with GDI calls
if ( !HasChild(bandIndex))
{
Color cb = band.Background;
IntPtr brush = WindowsAPI.CreateSolidBrush(ColorUtil.RGB(cb.R, cb.G, cb.B));
RECT rect;
rect.left = drawingRect.Left;
rect.top = drawingRect.Top;
rect.right = drawingRect.Left + drawingRect.Width;
rect.bottom = drawingRect.Top + drawingRect.Height;
WindowsAPI.FillRect(hDC, ref rect, brush);
WindowsAPI.DeleteObject(brush);
}
if ( HasChild(bandIndex) )
{
// Paint child control into memory device context
Control child = bands[bandIndex].ChildControl;
bool visible = child.Visible;
child.Visible = true;
// Change viewport if needed
POINT pt = new POINT();
WindowsAPI.SendMessage( child.Handle,
(int)Msg.WM_ERASEBKGND, (int)hDC, 0);
WindowsAPI.SendMessage( child.Handle,
(int)Msg.WM_PAINT, (int)hDC, 0);
if ( !visible) child.Visible = false;
}
else
{
DrawItems(Graphics.FromHdc(hDC), drawingRect, bands[bandIndex]);
}
}
bool HasChild()
{
// Flag that tell us if the current band
// has a child window
Control childControl = null;
if ( currentBandIndex != -1 && bands.Count > 0)
{
OutlookBarBand band = bands[currentBandIndex];
childControl = band.ChildControl;
}
return childControl != null;
}
bool HasChild(int index)
{
// Flag that tell us if the current band
// has a child window
Control childControl = null;
if ( index != -1 && bands.Count > 0 && index >= 0 && index < bands.Count)
{
OutlookBarBand band = bands[index];
childControl = band.ChildControl;
}
return childControl != null;
}
void GetVisibleRange(Graphics g, out int first, out int last)
{
first = firstItem;
last = 0;
OutlookBarBand band = bands[currentBandIndex];
Rectangle rc = GetViewPortRect();
Rectangle itemRect;
for ( int i = firstItem; i < band.Items.Count; i++ )
{
itemRect = GetItemRect(g, band, i, Rectangle.Empty);
if ( itemRect.Bottom > rc.Bottom )
{
last = i-1;
break;
}
else
{
last = i;
}
}
}
Size GetItemSize(Graphics g, OutlookBarBand band, int itemIndex, ItemSizeType itemSizeType)
{
Size iconSize = new Size(0,0);
Size labelSize = new Size(0,0);
if ( itemSizeType == ItemSizeType.Icon || itemSizeType == ItemSizeType.All )
{
iconSize = GetIconSize(band);
if (itemSizeType == ItemSizeType.Icon)
return iconSize;
}
if ( itemSizeType == ItemSizeType.Label || itemSizeType == ItemSizeType.All )
{
labelSize = GetLabelSize(g, band, itemIndex);
if ( itemSizeType == ItemSizeType.Label )
return labelSize;
}
if ( itemSizeType == ItemSizeType.All )
{
if ( band.IconView == IconView.Small )
return new Size(iconSize.Width + labelSize.Width + X_SMALLICON_LABEL_OFFSET,
iconSize.Height > labelSize.Height?iconSize.Height:labelSize.Height);
else
return new Size(iconSize.Width>labelSize.Width?iconSize.Width:labelSize.Width, iconSize.Height +
labelSize.Height + Y_LARGEICON_LABEL_OFFSET + Y_LARGEICON_SPACING);
}
return new Size(0,0);
}
Size GetIconSize(OutlookBarBand band)
{
if ( band.IconView == IconView.Large && band.LargeImageList != null )
return band.LargeImageList.ImageSize;
else if ( band.IconView == IconView.Small && band.SmallImageList != null )
return band.SmallImageList.ImageSize;
return new Size(0,0);
}
Size GetLabelSize(Graphics g, OutlookBarBand band, int itemIndex)
{
Size textSize = new Size(0,0);
if ( band.IconView == IconView.Large )
{
// Calculate text rectangle including word breaks if needed
Rectangle rect = GetViewPortRect();
Rectangle textRect = Rectangle.FromLTRB(rect.Left, rect.Top, rect.Width, rect.Top);
// The TextUtil function is going to call GDI, but the Graphics object
// is already being used by GDI+. Pass a null reference so that the TextUtil
// function uses the Screen Device to calculate the text size
if ( band.Items[itemIndex].Text != null )
{
textSize = TextUtil.GetTextSize(null, band.Items[itemIndex].Text,
Font, ref textRect, DrawTextFormatFlags.DT_CALCRECT |
DrawTextFormatFlags.DT_CENTER|DrawTextFormatFlags.DT_WORDBREAK);
}
return textSize;
}
else
{
// Same as above
// Calculate text rectangle single line
if ( band.Items[itemIndex].Text != null )
{
textSize = TextUtil.GetTextSize(null, band.Items[itemIndex].Text, Font);
}
return textSize;
}
}
Rectangle GetIconRect(int index)
{
Rectangle viewPortRect = GetViewPortRect();
OutlookBarBand band = bands[currentBandIndex];
Debug.Assert(band != null);
Size imageSize = Size.Empty;
Rectangle itemRect = Rectangle.Empty;
Point pt = new Point(0,0);
using ( Graphics g = Graphics.FromHwnd(Handle) )
{
itemRect = GetItemRect(g, band, index, Rectangle.Empty);
}
if ( band.IconView == IconView.Small )
{
if ( band.SmallImageList != null )
{
imageSize = band.SmallImageList.ImageSize;
pt.X = itemRect.Left;
pt.Y = itemRect.Top + (itemRect.Height - imageSize.Height)/2;
}
return new Rectangle(pt, imageSize);
}
else
{
if ( band.LargeImageList != null )
{
imageSize = band.LargeImageList.ImageSize;
pt.X = itemRect.Left + (viewPortRect.Width - imageSize.Width) / 2;
pt.Y = itemRect.Top;
}
return new Rectangle(pt, imageSize);
}
}
Rectangle GetLabelRect(int index)
{
Rectangle viewPortRect = GetViewPortRect();
OutlookBarBand band = bands[currentBandIndex];
Debug.Assert(band != null);
Size imageSize = Size.Empty;
Rectangle itemRect = Rectangle.Empty;
Size labelSize = Size.Empty;
Point pt = new Point(0,0);
using ( Graphics g = Graphics.FromHwnd(Handle) )
{
itemRect = GetItemRect(g, band, index, Rectangle.Empty);
labelSize = GetLabelSize(g, band, index);
}
if ( band.IconView == IconView.Small )
{
if ( band.SmallImageList != null )
{
imageSize = band.SmallImageList.ImageSize;
// Don't include the offset between the icon and the label
// so that we don't leave a miss hit gap
pt.X = itemRect.Left + imageSize.Width;
pt.Y = itemRect.Top + (itemRect.Height - labelSize.Height)/2;
}
return new Rectangle(pt.X, pt.Y , labelSize.Width + X_SMALLICON_LABEL_OFFSET+2 , labelSize.Height);
}
else
{
if ( band.LargeImageList != null )
{
imageSize = band.LargeImageList.ImageSize;
pt.X = itemRect.Left + (viewPortRect.Width - labelSize.Width) / 2;
// Don't include the offset between the icon and the label
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -