ThemeClearlooks.cs :  » 2.6.4-mono-.net-core » System.Windows.Forms » System » Windows » Forms » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Windows.Forms 
System.Windows.Forms » System » Windows » Forms » ThemeClearlooks.cs
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Copyright (c) 2006 Alexander Olk
//
// Authors:
//  Alexander Olk, alex.olk@googlemail.com
//
//  based on ThemeWin32Classic
//
//    - You can activate this Theme with export MONO_THEME=clearlooks
//
// This theme tries to match clearlooks theme
//
// TODO:  
//  - if an other control draws over a ScrollBar button you can see artefacts on the rounded edges 
//    (maybe use theme backcolor, but that looks ugly on a white background, need to find a way to get the backcolor of the parent control)
//  - more correct drawing of disabled controls

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;

namespace System.Windows.Forms{
  internal class ThemeClearlooks : ThemeWin32Classic {
    public override Version Version {
      get {
        return new Version( 0, 0, 0, 2 );
      }
    }
    
    static readonly Color theme_back_color = Color.FromArgb( 239, 235, 231 );
    
    static readonly Color gradient_first_color = Color.FromArgb( 250, 248, 247 );
    static readonly Color gradient_second_color = Color.FromArgb( 226, 219, 212 );
    static readonly Color gradient_second_color_nr2 = Color.FromArgb( 234, 229, 224 );
    static readonly Color pressed_gradient_first_color = Color.FromArgb( 217, 207, 202 );
    static readonly Color pressed_gradient_second_color = Color.FromArgb( 199, 193, 187 );
    static readonly Color border_normal_dark_color = Color.FromArgb( 129, 117, 106 );
    static readonly Color border_normal_light_color = Color.FromArgb( 158, 145, 131 );
    static readonly Color border_pressed_dark_color = Color.FromArgb( 109, 103, 98 );
    static readonly Color border_pressed_light_color = Color.FromArgb( 120, 114, 107 );
    static readonly Color button_outer_border_dark_color = Color.FromArgb( 232, 226, 220 );
    static readonly Color button_outer_border_light_color = Color.FromArgb( 250, 248, 247 ); 
    static readonly Color inner_border_dark_color = Color.FromArgb( 226, 219, 212 );
    static readonly Color pressed_inner_border_dark_color = Color.FromArgb( 192, 181, 169 );
    static readonly Color edge_top_inner_color = Color.FromArgb( 206, 200, 194 );
    static readonly Color edge_bottom_inner_color = Color.FromArgb( 215, 209, 202 );
    static readonly Color button_edge_top_outer_color = Color.FromArgb( 237, 233, 228 );
    static readonly Color button_edge_bottom_outer_color = Color.FromArgb( 243, 239, 236 );
    static readonly Color button_focus_color = Color.FromArgb( 101, 94, 86 );
    static readonly Color button_mouse_entered_second_gradient_color = Color.FromArgb( 230, 226, 219 );
    
    static readonly Color scrollbar_background_color = Color.FromArgb( 209, 200, 191 );
    static readonly Color scrollbar_border_color = Color.FromArgb( 170, 156, 143 );
    static readonly Color scrollbar_gradient_first_color = Color.FromArgb( 248, 247, 245 );
    static readonly Color scrollbar_gradient_second_color = Color.FromArgb( 234, 229, 224 );
    
    new static readonly Color arrow_color = Color.FromArgb( 16, 16, 16 );
    
    static readonly Color tab_border_color = Color.FromArgb( 166, 151, 138 );
    static readonly Color tab_not_selected_gradient_first_color = Color.FromArgb( 227, 223, 220 );
    static readonly Color tab_not_selected_gradient_second_color = Color.FromArgb( 214, 209, 204 );
    static readonly Color tab_selected_gradient_first_color = Color.FromArgb( 243, 239, 236 );
    static readonly Color tab_selected_gradient_second_color = Color.FromArgb( 234, 228, 223 );
    static readonly Color tab_edge_color = Color.FromArgb( 200, 196, 191 );
    static readonly Color tab_inner_border_color = Color.FromArgb( 221, 212, 205 );
    static readonly Color tab_top_border_focus_color = Color.FromArgb( 70, 91, 110 );
    static readonly Color tab_focus_color = Color.FromArgb( 105, 147, 185 );
    
    static readonly Color menuitem_gradient_first_color = Color.FromArgb( 98, 140, 178 );
    static readonly Color menuitem_gradient_second_color = Color.FromArgb( 81, 113, 142 );
    static readonly Color menuitem_border_color = Color.FromArgb( 80, 112, 141 );
    static readonly Color menu_separator_color = Color.FromArgb( 219, 211, 203 );
    static readonly Color menu_background_color = Color.FromArgb( 248, 245, 242 );
    static readonly Color menu_border_color = Color.FromArgb( 141, 122, 104 );
    static readonly Color menu_inner_border_color = Color.FromArgb( 236, 228, 221 );
    
    static readonly Color combobox_border_color = Color.FromArgb( 159, 146, 132 );
    static readonly Color combobox_focus_border_color = Color.FromArgb( 70, 91, 110 );
    //static readonly Color combobox_focus_inner_border_color = Color.FromArgb( 167, 198, 225 );
    static readonly Color combobox_button_second_gradient_color = Color.FromArgb( 226, 220, 213 );
    
    static readonly Color progressbar_edge_dot_color = Color.FromArgb( 219, 212, 205 );
    static readonly Color progressbar_inner_border_color = Color.FromArgb( 139, 176, 209 );
    static readonly Color progressbar_first_gradient_color = Color.FromArgb( 104, 146, 184 );
    static readonly Color progressbar_second_gradient_color = Color.FromArgb( 91, 133, 172 );
    
    static readonly Color checkbox_inner_boder_color = Color.FromArgb( 237, 234, 231 );
    static readonly Color checkbox_pressed_inner_boder_color = Color.FromArgb( 203, 196, 189 );
    static readonly Color checkbox_pressed_backcolor = Color.FromArgb( 212, 207, 202 );
    
    static readonly Color trackbar_second_gradient_color = Color.FromArgb( 114, 154, 190 );
    static readonly Color trackbar_third_gradient_color = Color.FromArgb( 130, 168, 202 );
    static readonly Color trackbar_inner_first_gradient_color = Color.FromArgb( 238, 233, 229 );
    static readonly Color trackbar_inner_second_gradient_color = Color.FromArgb( 223, 215, 208 );
    static readonly Color trackbar_inner_pressed_second_gradient_color = Color.FromArgb( 224, 217, 210 );
    
    //static readonly Color disabled_color_foreground = Color.FromArgb( 182, 180, 173 );
    
    static readonly Color active_caption = Color.FromArgb( 85, 152, 215 );
    
    static readonly Color radio_button_border_circle_color = Color.FromArgb( 126, 118, 105 );
    static readonly Color radio_button_dot_color = Color.FromArgb( 94, 160, 221 );
    
    const int SEPARATOR_HEIGHT = 7;
    const int MENU_TAB_SPACE = 8;    // Pixels added to the width of an item because of a tab
    const int MENU_BAR_ITEMS_SPACE = 8;  // Space between menu bar items
    
    static Color control_parent_backcolor;
    
    #region  Principal Theme Methods
    public ThemeClearlooks( ) {
      ColorControl = theme_back_color;
    }
    
    public override Color DefaultControlBackColor {
      get { return theme_back_color; }
    }
    
    public override Color DefaultWindowBackColor {
      get { return theme_back_color; }      
    }
    
    public override Color ColorControl {
      get { return theme_back_color;}
    }
    
    public override Color ColorHighlight {
      get { return menuitem_gradient_first_color; }
    }
    
    public override Color ColorActiveCaption {
      get { return active_caption; }
    }
    
    public override Size Border3DSize {
      get {
        return new Size( 3, 3 );
      }
    }
    
    public override Color ColorInfo {
      get { return Color.FromArgb (255, 255, 191); }
    }
    
    static readonly Color info_border_color = Color.FromArgb (218, 178, 85);
#if NET_2_0
    static readonly Color info_second_color = Color.FromArgb (220, 220, 160);
#endif  
    public override Image Images(UIIcon index, int size) {
      switch (index) {
      case UIIcon.PlacesRecentDocuments:
        if (XplatUI.RunningOnUnix)
          return MimeIconEngine.GetIconForMimeTypeAndSize( "recently/recently", new Size(size, size) );
        else
          return base.Images (UIIcon.PlacesRecentDocuments, size);
      case UIIcon.PlacesDesktop:
        if (XplatUI.RunningOnUnix)
          return MimeIconEngine.GetIconForMimeTypeAndSize( "desktop/desktop", new Size(size, size) );
        else
          return base.Images (UIIcon.PlacesDesktop, size);
      case UIIcon.PlacesPersonal:
        if (XplatUI.RunningOnUnix)
          return MimeIconEngine.GetIconForMimeTypeAndSize( "directory/home", new Size(size, size) );
        else
          return base.Images (UIIcon.PlacesPersonal, size);
      case UIIcon.PlacesMyComputer:
        if (XplatUI.RunningOnUnix)
          return MimeIconEngine.GetIconForMimeTypeAndSize( "workplace/workplace", new Size(size, size) );
        else
          return base.Images (UIIcon.PlacesMyComputer, size);
      case UIIcon.PlacesMyNetwork:
        if (XplatUI.RunningOnUnix)
          return MimeIconEngine.GetIconForMimeTypeAndSize( "network/network", new Size(size, size) );
        else
          return base.Images (UIIcon.PlacesMyNetwork, size);
        
        // Icons for message boxes
      case UIIcon.MessageBoxError:    return base.Images (UIIcon.MessageBoxError, size);
      case UIIcon.MessageBoxInfo:    return base.Images (UIIcon.MessageBoxInfo, size);
      case UIIcon.MessageBoxQuestion:    return base.Images (UIIcon.MessageBoxQuestion, size);
      case UIIcon.MessageBoxWarning:    return base.Images (UIIcon.MessageBoxWarning, size);
        
        // misc Icons
      case UIIcon.NormalFolder:
        if (XplatUI.RunningOnUnix)
          return MimeIconEngine.GetIconForMimeTypeAndSize( "inode/directory", new Size(size, size) );
        else
          return base.Images (UIIcon.NormalFolder, size);
        
      default: {
          throw new ArgumentException("Invalid Icon type requested", "index");
        }
      }
    }
    #endregion  // Internal Methods
    
    #region ButtonBase
    protected override void ButtonBase_DrawButton( ButtonBase button, Graphics dc ) {
      dc.FillRectangle( ResPool.GetSolidBrush( button.BackColor ), button.ClientRectangle );
      
      Color first_gradient_color = gradient_first_color;
      Color second_gradient_color = gradient_second_color;
      
      if (((button is CheckBox) && (((CheckBox)button).check_state == CheckState.Checked)) ||
          ((button is RadioButton) && (((RadioButton)button).check_state == CheckState.Checked))) {
        first_gradient_color = button.is_entered ? gradient_second_color : pressed_gradient_first_color;
        second_gradient_color = button.is_entered  ? gradient_second_color : pressed_gradient_second_color;
      } else
      if (!button.is_enabled) {
        button.is_entered = false;
      } else
      if (button.is_entered) {
        if (!button.is_pressed) {
          first_gradient_color = Color.White;
          second_gradient_color = button_mouse_entered_second_gradient_color;
        } else {
          first_gradient_color = pressed_gradient_first_color;
          second_gradient_color = pressed_gradient_second_color;
        }
      }
      
      bool paint_acceptbutton_black_border = false;
      Form form = button.TopLevelControl as Form;
      
      if (form != null && (form.AcceptButton == button as IButtonControl))
        paint_acceptbutton_black_border = true;
      
      CL_Draw_Button(dc, button.ClientRectangle, button.FlatStyle,
            button.is_entered, button.is_enabled, button.is_pressed,
            first_gradient_color, second_gradient_color,
            paint_acceptbutton_black_border);
    }

    private void CL_Draw_Button(Graphics dc, Rectangle buttonRectangle, FlatStyle flat_style,
                 bool is_entered, bool is_enabled, bool is_pressed,
                 Color first_gradient_color, Color second_gradient_color,
                 bool paint_acceptbutton_black_border)
    {
      Rectangle lgbRectangle = new Rectangle (buttonRectangle.X + 3, buttonRectangle.Y + 3,
                is_pressed ? buttonRectangle.Width - 5 : buttonRectangle.Width - 6,
                buttonRectangle.Height - 6);
      
      if (flat_style != FlatStyle.Popup || ((flat_style == FlatStyle.Popup) && is_entered)) {
        LinearGradientBrush lgbr;
        if (flat_style == FlatStyle.Flat) {
          lgbr = new LinearGradientBrush (new Point (buttonRectangle.X, buttonRectangle.Y + 3),
                       new Point (buttonRectangle.X, buttonRectangle.Bottom - 3),
                       second_gradient_color, first_gradient_color);
        } else {
          lgbr = new LinearGradientBrush  (new Point (buttonRectangle.X, buttonRectangle.Y + 3),
                  new Point (buttonRectangle.X, buttonRectangle.Bottom - 3),
                  first_gradient_color, second_gradient_color);
        }
        dc.FillRectangle (lgbr, lgbRectangle);
        lgbr.Dispose ();
        
        Point[] points_top = {
          new Point (buttonRectangle.X + 2, buttonRectangle.Y + 2),
          new Point (buttonRectangle.X + 3, buttonRectangle.Y + 1),
          new Point (buttonRectangle.Right - 4, buttonRectangle.Y + 1),
          new Point (buttonRectangle.Right - 3 , buttonRectangle.Y + 2)
        };
        
        Point[] points_bottom = {
          new Point (buttonRectangle.X + 2, buttonRectangle.Bottom - 3),
          new Point (buttonRectangle.X + 3, buttonRectangle.Bottom - 2),
          new Point (buttonRectangle.Right - 4, buttonRectangle.Bottom - 2),
          new Point (buttonRectangle.Right - 3, buttonRectangle.Bottom - 3)
        };
        
        Point[] points_top_outer = {
          new Point (buttonRectangle.X + 1, buttonRectangle.Y + 1),
          new Point (buttonRectangle.X + 2, buttonRectangle.Y),
          new Point (buttonRectangle.Right - 3, buttonRectangle.Y),
          new Point (buttonRectangle.Right - 2 , buttonRectangle.Y + 1)
        };
        
        Point[] points_bottom_outer = {
          new Point (buttonRectangle.X + 1, buttonRectangle.Bottom - 2),
          new Point (buttonRectangle.X + 2, buttonRectangle.Bottom - 1),
          new Point (buttonRectangle.Right - 3, buttonRectangle.Bottom - 1),
          new Point (buttonRectangle.Right - 2, buttonRectangle.Bottom - 2)
        };
        
        Pen pen = null; 
        
        // normal border
        if (is_enabled) { 
          Color top_color = Color.Black;
          Color bottom_color = Color.Black;
          
          if (!paint_acceptbutton_black_border) {
            top_color = is_pressed ? border_pressed_dark_color : border_normal_dark_color;
            bottom_color = is_pressed ? border_pressed_light_color : border_normal_light_color;
          }
          
          pen = ResPool.GetPen (top_color);
          dc.DrawLines (pen, points_top);
          pen = ResPool.GetPen (bottom_color);
          dc.DrawLines (pen, points_bottom);
          
          using (LinearGradientBrush lgbr2 = new LinearGradientBrush (new Point (buttonRectangle.X, buttonRectangle.Y + 3),
                            new Point (buttonRectangle.X, buttonRectangle.Bottom - 3),
                            top_color, bottom_color)) {
            using (Pen lgbrpen = new Pen (lgbr2)) {
              dc.DrawLine (lgbrpen, buttonRectangle.X + 1, buttonRectangle.Y + 3, buttonRectangle.X + 1, buttonRectangle.Bottom - 3);
              dc.DrawLine (lgbrpen, buttonRectangle.Right - 2, buttonRectangle.Y + 3, buttonRectangle.Right - 2, buttonRectangle.Bottom - 3);
            }
          }
        } else {
          Point[] points_button_complete = {
            new Point (buttonRectangle.X + 1, buttonRectangle.Y + 3),
            new Point (buttonRectangle.X + 3, buttonRectangle.Y + 1),
            new Point (buttonRectangle.Right - 4, buttonRectangle.Y + 1),
            new Point (buttonRectangle.Right - 2, buttonRectangle.Y + 3),
            new Point (buttonRectangle.Right - 2, buttonRectangle.Bottom - 4),
            new Point (buttonRectangle.Right - 4, buttonRectangle.Bottom - 2),
            new Point (buttonRectangle.X + 3, buttonRectangle.Bottom - 2),
            new Point (buttonRectangle.X + 1, buttonRectangle.Bottom - 4),
            new Point (buttonRectangle.X + 1, buttonRectangle.Y + 3)
          };
          
          pen = ResPool.GetPen (pressed_inner_border_dark_color);
          dc.DrawLines (pen, points_button_complete);
        }
        
        // outer border
        pen = ResPool.GetPen (button_outer_border_dark_color);
        dc.DrawLines (pen, points_top_outer);
        pen = ResPool.GetPen (button_outer_border_light_color);
        dc.DrawLines (pen, points_bottom_outer);
        
        using (LinearGradientBrush lgbr2 = new LinearGradientBrush (new Point (buttonRectangle.X, buttonRectangle.Y + 2),
                          new Point (buttonRectangle.X, buttonRectangle.Bottom - 1),
                          button_outer_border_dark_color, button_outer_border_light_color)) {
          using (Pen lgbrpen = new Pen(lgbr2)) {
            dc.DrawLine (lgbrpen, buttonRectangle.X, buttonRectangle.Y + 2, buttonRectangle.X, buttonRectangle.Bottom - 3);
            dc.DrawLine (lgbrpen, buttonRectangle.Right - 1, buttonRectangle.Y + 2, buttonRectangle.Right - 1, buttonRectangle.Bottom - 3);
          }
        }
        
        // inner border
        pen = ResPool.GetPen (is_pressed ? pressed_inner_border_dark_color : inner_border_dark_color);
        if (!is_pressed) {
          dc.DrawLine (pen, buttonRectangle.Right - 3, buttonRectangle.Y + 3, buttonRectangle.Right - 3, buttonRectangle.Bottom - 4);
        }
        dc.DrawLine (pen, buttonRectangle.X + 3, buttonRectangle.Bottom - 3, buttonRectangle.Right - 4, buttonRectangle.Bottom - 3);
        pen = ResPool.GetPen (is_pressed ? pressed_inner_border_dark_color : Color.White);
        dc.DrawLine (pen, buttonRectangle.X + 2, buttonRectangle.Y + 3, buttonRectangle.X + 2, buttonRectangle.Bottom - 4);
        dc.DrawLine (pen, buttonRectangle.X + 3 , buttonRectangle.Y + 2, buttonRectangle.Right - 4, buttonRectangle.Y + 2);
        
        // edges
        pen = ResPool.GetPen (edge_top_inner_color);
        dc.DrawLine (pen, buttonRectangle.X + 1, buttonRectangle.Y + 2, buttonRectangle.X + 2, buttonRectangle.Y + 1);
        dc.DrawLine (pen, buttonRectangle.Right - 3, buttonRectangle.Y + 1, buttonRectangle.Right - 2, buttonRectangle.Y + 2);
        
        pen = ResPool.GetPen (button_edge_top_outer_color);
        dc.DrawLine (pen, buttonRectangle.X, buttonRectangle.Y + 1, buttonRectangle.X + 1, buttonRectangle.Y);
        dc.DrawLine (pen, buttonRectangle.Right - 2, buttonRectangle.Y, buttonRectangle.Right - 1, buttonRectangle.Y + 1);
        
        pen = ResPool.GetPen (edge_bottom_inner_color);
        dc.DrawLine (pen, buttonRectangle.X + 1, buttonRectangle.Bottom - 3, buttonRectangle.X + 2, buttonRectangle.Bottom - 2);
        dc.DrawLine (pen, buttonRectangle.Right - 2, buttonRectangle.Bottom - 3, buttonRectangle.Right - 3, buttonRectangle.Bottom - 2);
        
        pen = ResPool.GetPen (button_edge_bottom_outer_color);
        dc.DrawLine (pen, buttonRectangle.X, buttonRectangle.Bottom - 2, buttonRectangle.X + 1, buttonRectangle.Bottom - 1);
        dc.DrawLine (pen, buttonRectangle.Right - 1, buttonRectangle.Bottom - 2, buttonRectangle.Right - 2, buttonRectangle.Bottom - 1);
      }
    }
    
    protected override void ButtonBase_DrawFocus( ButtonBase button, Graphics dc ) {
      
      if ( !button.is_enabled || button.FlatStyle == FlatStyle.Popup )
        return;
      
      Pen pen = ResPool.GetPen( button_focus_color );
      DashStyle old_dash_style = pen.DashStyle;
      pen.DashStyle = DashStyle.Dot;
      
      Rectangle focus_rect = new Rectangle( button.ClientRectangle.X + 4, button.ClientRectangle.Y + 4, button.ClientRectangle.Width - 9, button.ClientRectangle.Height - 9 );
      
      dc.DrawRectangle( pen, focus_rect );
      
      pen.DashStyle = old_dash_style;
    }
    
    // FIXME: remove if libgdiplus DrawOrMeasureString is fixed
    protected override void ButtonBase_DrawText( ButtonBase button, Graphics dc ) {
      if ( !( button is CheckBox ) && !( button is RadioButton ) ) {
        Rectangle buttonRectangle = button.ClientRectangle;
        Rectangle text_rect = Rectangle.Inflate( buttonRectangle, -4, -4 );
        
        string text = button.Text;
        
        if ( text.Length > 1 ) {
          SizeF sizef = dc.MeasureString( text, button.Font, text_rect.Width, button.text_format );
          
          if ( (int)sizef.Width > text_rect.Width - 3 ) {
            for ( int i = 1; i < text.Length + 1; i++ ) {
              sizef = dc.MeasureString( text.Substring( 0, i ), button.Font, text_rect.Width, button.text_format );
              
              if ( (int)sizef.Width > text_rect.Width - 3 ) {
                text = text.Substring( 0, i - 1 );
                break;
              }
            }
          }
        }
        
        if ( button.is_pressed ) {
          text_rect.X++;
          text_rect.Y++;
        }
        
        if ( button.is_enabled ) {          
          dc.DrawString( text, button.Font, ResPool.GetSolidBrush( button.ForeColor ), text_rect, button.text_format );
        } else {
          if ( button.FlatStyle == FlatStyle.Flat || button.FlatStyle == FlatStyle.Popup ) {
            dc.DrawString( text, button.Font, ResPool.GetSolidBrush( ControlPaint.DarkDark( this.ColorControl ) ), text_rect, button.text_format );
          } else {
            CPDrawStringDisabled( dc, text, button.Font, ColorControlText, text_rect, button.text_format );
          }
        }
      }
    }
    #endregion  // ButtonBase
    
    #region Menus
    public override void DrawMenuItem( MenuItem item, DrawItemEventArgs e ) {
      StringFormat string_format;
      Rectangle rect_text = e.Bounds;
      
      if ( item.Visible == false )
        return; 
      
      if ( item.MenuBar ) {
        string_format = string_format_menu_menubar_text;
      } else {
        string_format = string_format_menu_text;
      }
      
      if ( item.Separator ) {
        e.Graphics.DrawLine( ResPool.GetPen( menu_separator_color ),
                e.Bounds.X, e.Bounds.Y + 1, e.Bounds.X + e.Bounds.Right - 4, e.Bounds.Y + 1 );
        
        e.Graphics.DrawLine( ResPool.GetPen( Color.White ),
                e.Bounds.X, e.Bounds.Y + 2, e.Bounds.X + e.Bounds.Right - 4, e.Bounds.Y + 2 );
        
        return;
      }
      
      if ( !item.MenuBar )
        rect_text.X += MenuCheckSize.Width;
      
      if ( item.BarBreak ) { /* Draw vertical break bar*/
        Rectangle rect = e.Bounds;
        rect.Y++;
              rect.Width = 3;
              rect.Height = item.MenuHeight - 6;
        
        e.Graphics.DrawLine( ResPool.GetPen( menu_separator_color ),
                rect.X, rect.Y , rect.X, rect.Y + rect.Height );
        
        e.Graphics.DrawLine( ResPool.GetPen( ColorControlLight ),
                rect.X + 1, rect.Y , rect.X + 1, rect.Y + rect.Height );
      }
      
      Color color_text = ColorMenuText;
      Color color_back;
      
      /* Draw background */
      Rectangle rect_back = e.Bounds;
      rect_back.X++;
      rect_back.Width -= 2;
      
      if ( ( e.State & DrawItemState.Selected ) == DrawItemState.Selected ) {
        color_text = ColorHighlightText;
        color_back = item.MenuBar ? theme_back_color : menu_background_color;
        
        using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( rect_back.X, rect_back.Y + 1 ), new Point( rect_back.X, rect_back.Bottom - 1 ), menuitem_gradient_first_color, menuitem_gradient_second_color ) ) {
          e.Graphics.FillRectangle( lgbr, rect_back.X + 1, rect_back.Y + 1, rect_back.Width - 1, rect_back.Height - 1 );
        }
        
        rect_back.Height--;
        Pen tmp_pen = ResPool.GetPen( menuitem_border_color );
        e.Graphics.DrawLine( tmp_pen, rect_back.X + 1, rect_back.Y, rect_back.Right - 1, rect_back.Y );
        e.Graphics.DrawLine( tmp_pen, rect_back.Right, rect_back.Y + 1, rect_back.Right, rect_back.Bottom - 1 );
        e.Graphics.DrawLine( tmp_pen, rect_back.Right - 1, rect_back.Bottom, rect_back.X + 1, rect_back.Bottom );
        e.Graphics.DrawLine( tmp_pen, rect_back.X, rect_back.Bottom - 1, rect_back.X, rect_back.Y + 1 );
      } else {
        color_text = ColorMenuText;
        color_back = item.MenuBar ? theme_back_color : menu_background_color;
        
        e.Graphics.FillRectangle( ResPool.GetSolidBrush( color_back ), rect_back );
      }
      
      if ( item.Enabled ) {
        e.Graphics.DrawString( item.Text, e.Font,
                  ResPool.GetSolidBrush( color_text ),
                  rect_text, string_format );
        
        if ( !item.MenuBar && item.Shortcut != Shortcut.None && item.ShowShortcut ) {
          string str = item.GetShortCutText( );
          Rectangle rect = rect_text;
          rect.X = item.XTab;
          rect.Width -= item.XTab;
          
          e.Graphics.DrawString( str, e.Font, ResPool.GetSolidBrush( color_text ),
                    rect, string_format_menu_shortcut );
        }
      } else {
        ControlPaint.DrawStringDisabled( e.Graphics, item.Text, e.Font,
                Color.Black, rect_text, string_format );
      }
      
      /* Draw arrow */
      if ( item.MenuBar == false && item.IsPopup ) {
        int cx = MenuCheckSize.Width;
        int cy = MenuCheckSize.Height;
        using ( Bitmap  bmp = new Bitmap( cx, cy ) ) {
          using ( Graphics dc = Graphics.FromImage( bmp ) ) {
            SmoothingMode old_smoothing_mode = dc.SmoothingMode;
            dc.SmoothingMode = SmoothingMode.AntiAlias;
            
            Rectangle rect_arrow = new Rectangle( 0, 0, cx, cy );
            ControlPaint.DrawMenuGlyph( dc, rect_arrow, MenuGlyph.Arrow );
            bmp.MakeTransparent( );
            
            if ( item.Enabled ) {
              e.Graphics.DrawImage( bmp, e.Bounds.X + e.Bounds.Width - cx,
                       e.Bounds.Y + ( ( e.Bounds.Height - cy ) / 2 ) );
            } else {
              ControlPaint.DrawImageDisabled( e.Graphics, bmp, e.Bounds.X + e.Bounds.Width - cx,
                           e.Bounds.Y + ( ( e.Bounds.Height - cy ) / 2 ),  color_back );
            }
            
            dc.SmoothingMode = old_smoothing_mode;
          }
        }
      }
      
      /* Draw checked or radio */
      if ( item.MenuBar == false && item.Checked ) {
        
        Rectangle area = e.Bounds;
        int cx = MenuCheckSize.Width;
        int cy = MenuCheckSize.Height;
        using ( Bitmap bmp = new Bitmap( cx, cy ) ) {
          using ( Graphics gr = Graphics.FromImage( bmp ) ) {
            Rectangle rect_arrow = new Rectangle( 0, 0, cx, cy );
            
            if ( item.RadioCheck )
              ControlPaint.DrawMenuGlyph( gr, rect_arrow, MenuGlyph.Bullet );
            else
              ControlPaint.DrawMenuGlyph( gr, rect_arrow, MenuGlyph.Checkmark );
            
            bmp.MakeTransparent( );
            e.Graphics.DrawImage( bmp, area.X, e.Bounds.Y + ( ( e.Bounds.Height - cy ) / 2 ) );
          }
        }
      }
    }
    
    public override void DrawPopupMenu( Graphics dc, Menu menu, Rectangle cliparea, Rectangle rect ) {
      
      dc.FillRectangle( ResPool.GetSolidBrush
           ( menu_background_color ), cliparea );
      
      /* Draw menu borders */
      dc.DrawRectangle( ResPool.GetPen( menu_border_color ), rect.X, rect.Y, rect.Width - 1, rect.Height - 1 );
      
      // inner border
      Pen tmp_pen = ResPool.GetPen( Color.White );
      dc.DrawLine( tmp_pen, rect.X + 1, rect.Y + 1, rect.Right - 2, rect.Y + 1 );
      dc.DrawLine( tmp_pen, rect.X + 1, rect.Y + 2, rect.X + 1, rect.Bottom - 2 );
      
      tmp_pen = ResPool.GetPen( menu_inner_border_color );
      dc.DrawLine( tmp_pen, rect.Right - 2, rect.Y + 2, rect.Right - 2, rect.Bottom - 2 );
      dc.DrawLine( tmp_pen, rect.Right - 3, rect.Bottom - 2, rect.X + 2, rect.Bottom - 2 );
      
      for ( int i = 0; i < menu.MenuItems.Count; i++ )
        if ( cliparea.IntersectsWith( menu.MenuItems[ i ].bounds ) ) {
          MenuItem item = menu.MenuItems[ i ];
          item.MenuHeight = menu.Height;
          item.PerformDrawItem( new DrawItemEventArgs( dc, MenuFont,
                        item.bounds, i, item.Status ) );
        }
    }
    #endregion // Menus
    
    #region ProgressBar
    public override void DrawProgressBar( Graphics dc, Rectangle clip_rect, ProgressBar ctrl ) {
      Rectangle  client_area = ctrl.client_area;
      int    barpos_pixels;
      Rectangle bar = ctrl.client_area;
      
      barpos_pixels = ( ( ctrl.Value - ctrl.Minimum ) * client_area.Width ) / ( ctrl.Maximum - ctrl.Minimum );
      
      bar.Width = barpos_pixels + 1;
      
      // Draw bar background
      dc.FillRectangle( ResPool.GetSolidBrush( menu_separator_color ), ctrl.ClientRectangle.X + 1, ctrl.ClientRectangle.Y + 1, ctrl.ClientRectangle.Width - 2, ctrl.ClientRectangle.Height - 2 );
      
      /* Draw border */
      Pen tmp_pen = ResPool.GetPen( progressbar_edge_dot_color );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Y, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Y + 1 );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Bottom - 1, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Bottom - 2 );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Y, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Y + 1 );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Bottom - 1, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Bottom - 2 );
      
      tmp_pen = ResPool.GetPen( scrollbar_border_color );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X + 1, ctrl.ClientRectangle.Y, ctrl.ClientRectangle.Right - 2, ctrl.ClientRectangle.Y );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Y + 1, ctrl.ClientRectangle.Right - 1, ctrl.ClientRectangle.Bottom - 2 );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X + 1, ctrl.ClientRectangle.Bottom - 1, ctrl.ClientRectangle.Right - 2, ctrl.ClientRectangle.Bottom - 1 );
      dc.DrawLine( tmp_pen, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Y + 1, ctrl.ClientRectangle.X, ctrl.ClientRectangle.Bottom - 2 );
      
      if ( barpos_pixels <= 0 )
        return;
      
      if ((bar.Width - 2) <= 0 || (bar.Height - 1) <= 0)
        return;
      
      // Draw bar
      dc.DrawRectangle( ResPool.GetPen( combobox_focus_border_color ), bar.X - 1, bar.Y - 1, bar.Width, bar.Height + 1 );
      tmp_pen = ResPool.GetPen( progressbar_inner_border_color );
      dc.DrawLine( tmp_pen, bar.X, bar.Y, bar.Right - 2, bar.Y );
      dc.DrawLine( tmp_pen, bar.X, bar.Y, bar.X, bar.Bottom - 1 );
      
      using ( Bitmap bmp = new Bitmap( bar.Width - 2, bar.Height - 1 ) ) {
        using ( Graphics gr = Graphics.FromImage( bmp ) ) {
          gr.FillRectangle( ResPool.GetSolidBrush( tab_focus_color ), 0, 0, bmp.Width, bmp.Height );
          
          LinearGradientBrush lgbr = new LinearGradientBrush( new Rectangle( 0, 0, bmp.Height, bmp.Height ), progressbar_first_gradient_color, progressbar_second_gradient_color, 0.0f, true );
          
          lgbr.RotateTransform( 45.0f, MatrixOrder.Append );
          
          float pen_width = bmp.Height / 2;
          
          Pen pen = new Pen( lgbr, pen_width );
          
          int add = bmp.Height + (int)pen.Width / 2;
          
          int x_top = 0;
          int x_bottom = - bmp.Height;
          
          while ( x_bottom < bmp.Width ) {
            gr.DrawLine( pen, x_top, 0, x_bottom, bmp.Height );
            x_top += add;
            x_bottom += add;
          }
          pen.Dispose( );
          lgbr.Dispose( );
        }
        
        dc.DrawImage( bmp, bar.X + 1, bar.Y + 1 );
      }
    }
    #endregion  // ProgressBar
    
    #region RadioButton
    
    // renders a radio button with the Flat and Popup FlatStyle
    protected override void DrawFlatStyleRadioButton (Graphics dc, Rectangle rectangle, RadioButton radio_button)
    {
      if (radio_button.Enabled) {
        // draw the outer flatstyle arcs
        if (radio_button.FlatStyle == FlatStyle.Flat) {
          dc.DrawArc (ResPool.GetPen (radio_button.ForeColor), rectangle, 0, 359);
          
          // fill in the area depending on whether or not the mouse is hovering
          if (radio_button.is_entered && radio_button.Capture) {
            dc.FillPie (ResPool.GetSolidBrush (ControlPaint.Light (radio_button.BackColor)), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
          } else {
            dc.FillPie (ResPool.GetSolidBrush (ControlPaint.LightLight (radio_button.BackColor)), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
          }
        } else {
          // must be a popup radio button
          // fill the control
          dc.FillPie (ResPool.GetSolidBrush (ControlPaint.LightLight (radio_button.BackColor)), rectangle, 0, 359);
          
          if (radio_button.is_entered || radio_button.Capture) {
            // draw the popup 3d button knob
            dc.DrawArc (ResPool.GetPen (ControlPaint.Light (radio_button.BackColor)), rectangle.X+1, rectangle.Y+1, rectangle.Width-2, rectangle.Height-2, 0, 359);
            
            dc.DrawArc (ResPool.GetPen (ControlPaint.Dark (radio_button.BackColor)), rectangle, 135, 180);
            dc.DrawArc (ResPool.GetPen (ControlPaint.LightLight (radio_button.BackColor)), rectangle, 315, 180);
            
          } else {
            // just draw lighter flatstyle outer circle
            dc.DrawArc (ResPool.GetPen (ControlPaint.Dark (this.ColorControl)), rectangle, 0, 359);            
          }                    
        }
      } else {
        // disabled
        // fill control background color regardless of actual backcolor
        dc.FillPie (ResPool.GetSolidBrush (this.ColorControl), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
        // draw the ark as control dark
        dc.DrawArc (ResPool.GetPen (ControlPaint.Dark(this.ColorControl)), rectangle, 0, 359);
      }
      
      // draw the check
      if (radio_button.Checked) {
        SmoothingMode old_smoothing_mode = dc.SmoothingMode;
        dc.SmoothingMode = SmoothingMode.AntiAlias;
        
        CL_Draw_RadioButton_Dot (dc, rectangle, true, false);
        
        dc.SmoothingMode = old_smoothing_mode;
      }
    }
    #endregion  // RadioButton
    
    #region ScrollBar
    public override void DrawScrollBar( Graphics dc, Rectangle clip, ScrollBar bar ) {
      int    scrollbutton_width = bar.scrollbutton_width;
      int    scrollbutton_height = bar.scrollbutton_height;
      Rectangle  first_arrow_area;
      Rectangle  second_arrow_area;      
      Rectangle  thumb_pos;
      
      thumb_pos = bar.ThumbPos;
      
      if ( bar.vert ) {
        first_arrow_area = new Rectangle( 0, 0, bar.Width, scrollbutton_height + 1 );
        bar.FirstArrowArea = first_arrow_area;
        
        second_arrow_area = new Rectangle( 0, bar.ClientRectangle.Height - scrollbutton_height - 1, bar.Width, scrollbutton_height + 1 );
        bar.SecondArrowArea = second_arrow_area;
        
        thumb_pos.Width = bar.Width;
        bar.ThumbPos = thumb_pos;

        Pen pen;
        /* Background, upper track */
        Rectangle UpperTrack = new Rectangle (0, 0, bar.ClientRectangle.Width, bar.ThumbPos.Top);
        if (clip.IntersectsWith (UpperTrack))
          dc.FillRectangle (ResPool.GetSolidBrush (scrollbar_background_color), UpperTrack);
          pen = ResPool.GetPen (scrollbar_border_color);
          dc.DrawLine (pen, UpperTrack.X, UpperTrack.Y, UpperTrack.X, UpperTrack.Bottom - 1);
          dc.DrawLine (pen, UpperTrack.Right - 1, UpperTrack.Y, UpperTrack.Right - 1, UpperTrack.Bottom - 1);

        /* Background, lower track */
        Rectangle LowerTrack = new Rectangle (0, bar.ThumbPos.Bottom, bar.ClientRectangle.Width, bar.ClientRectangle.Height - bar.ThumbPos.Bottom);
        if (clip.IntersectsWith (LowerTrack))
          dc.FillRectangle (ResPool.GetSolidBrush (scrollbar_background_color), LowerTrack);
          pen = ResPool.GetPen (scrollbar_border_color);
          dc.DrawLine (pen, LowerTrack.X, LowerTrack.Y, LowerTrack.X, LowerTrack.Bottom - 1);
          dc.DrawLine (pen, LowerTrack.Right - 1, LowerTrack.Y, LowerTrack.Right - 1, LowerTrack.Bottom - 1);

        /* Buttons */
        if ( clip.IntersectsWith( first_arrow_area ) )
          CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Up, bar.firstbutton_state );
        if ( clip.IntersectsWith( second_arrow_area ) )
          CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Down, bar.secondbutton_state );
      } else {
        first_arrow_area = new Rectangle( 0, 0, scrollbutton_width + 1, bar.Height );
        bar.FirstArrowArea = first_arrow_area;
        
        second_arrow_area = new Rectangle( bar.ClientRectangle.Width - scrollbutton_width - 1, 0, scrollbutton_width + 1, bar.Height );
        bar.SecondArrowArea = second_arrow_area;
        
        thumb_pos.Height = bar.Height;
        bar.ThumbPos = thumb_pos;

        Pen pen;
        //Background, left track
        Rectangle LeftTrack = new Rectangle (0, 0, bar.ThumbPos.Left, bar.ClientRectangle.Height);
        if (clip.IntersectsWith (LeftTrack))
          dc.FillRectangle (ResPool.GetSolidBrush (scrollbar_background_color), LeftTrack);
          pen = ResPool.GetPen (scrollbar_border_color);
          dc.DrawLine (pen, LeftTrack.X, LeftTrack.Y, LeftTrack.Right - 1, LeftTrack.Y);
          dc.DrawLine (pen, LeftTrack.X, LeftTrack.Bottom - 1, LeftTrack.Right - 1, LeftTrack.Bottom - 1);

        //Background, right track
        Rectangle RightTrack = new Rectangle (bar.ThumbPos.Right, 0, bar.ClientRectangle.Width - bar.ThumbPos.Right, bar.ClientRectangle.Height);
        if (clip.IntersectsWith (RightTrack))
          dc.FillRectangle (ResPool.GetSolidBrush (scrollbar_background_color), RightTrack);
          pen = ResPool.GetPen (scrollbar_border_color);
          dc.DrawLine (pen, RightTrack.X, RightTrack.Y, RightTrack.Right - 1, RightTrack.Y);
          dc.DrawLine (pen, RightTrack.X, RightTrack.Bottom - 1, RightTrack.Right - 1, RightTrack.Bottom - 1);          
        
        /* Buttons */
        if ( clip.IntersectsWith( first_arrow_area ) )
          CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Left, bar.firstbutton_state );
        if ( clip.IntersectsWith( second_arrow_area ) )
          CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Right, bar.secondbutton_state );
      }
      
      /* Thumb */
      ScrollBar_DrawThumb( bar, thumb_pos, clip, dc );        
    }
    
    protected override void ScrollBar_DrawThumb( ScrollBar bar, Rectangle thumb_pos, Rectangle clip, Graphics dc ) {
      if ( bar.Enabled && thumb_pos.Width > 0 && thumb_pos.Height > 0 && clip.IntersectsWith( thumb_pos ) )
        DrawScrollBarThumb( dc, thumb_pos, bar );
    }
    #endregion  // ScrollBar
    
    #region StatusBar
    protected override void DrawStatusBarPanel( Graphics dc, Rectangle area, int index,
                 Brush br_forecolor, StatusBarPanel panel ) {
      int border_size = 3; // this is actually const, even if the border style is none
      
      area.Height -= border_size;
      if ( panel.BorderStyle != StatusBarPanelBorderStyle.None ) {
        dc.DrawRectangle( ResPool.GetPen( pressed_inner_border_dark_color ), area );
      }
      
      if ( panel.Style == StatusBarPanelStyle.OwnerDraw ) {
        StatusBarDrawItemEventArgs e = new StatusBarDrawItemEventArgs(
          dc, panel.Parent.Font, area, index, DrawItemState.Default,
          panel, panel.Parent.ForeColor, panel.Parent.BackColor );
        panel.Parent.OnDrawItemInternal( e );
        return;
      }
      
      int left = area.Left;
      if ( panel.Icon != null ) {
        left += 2;
        dc.DrawIcon( panel.Icon, left, area.Top );
        left += panel.Icon.Width;
      }
      
      if ( panel.Text == String.Empty )
        return;
      
      string text = panel.Text;
      StringFormat string_format = new StringFormat( );
      string_format.Trimming = StringTrimming.Character;
      string_format.FormatFlags = StringFormatFlags.NoWrap;
      
      if ( text[ 0 ] == '\t' ) {
        string_format.Alignment = StringAlignment.Center;
        text = text.Substring( 1 );
        if ( text[ 0 ] == '\t' ) {
          string_format.Alignment = StringAlignment.Far;
          text = text.Substring( 1 );
        }
      }
      
      int x = left + border_size;
      int y = border_size + 2;
      Rectangle r = new Rectangle( x, y,
                area.Right - x - border_size,
                area.Bottom - y - border_size );
      
      dc.DrawString( text, panel.Parent.Font, br_forecolor, r, string_format );
    }
    #endregion  // StatusBar
    
    // FIXME: regions near the borders don't get filled with the correct backcolor
    // TODO: TabAlignment.Left and TabAlignment.Bottom
    public override void DrawTabControl( Graphics dc, Rectangle area, TabControl tab ) {
      if (tab.Parent != null)
        dc.FillRectangle( ResPool.GetSolidBrush( tab.Parent.BackColor ), area );
      else
        dc.FillRectangle( ResPool.GetSolidBrush( tab.BackColor ), area );
      Rectangle panel_rect = TabControlGetPanelRect( tab );
      
      if ( tab.Appearance == TabAppearance.Normal ) {
        
        switch ( tab.Alignment ) {
          case TabAlignment.Top:
            // inner border...
            Pen pen = ResPool.GetPen( Color.White );
            
            dc.DrawLine( pen, panel_rect.Left + 1, panel_rect.Top, panel_rect.Left + 1, panel_rect.Bottom - 1 );
            dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Top , panel_rect.Right - 2, panel_rect.Top );
            
            pen = ResPool.GetPen( tab_inner_border_color );
            dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Top + 1, panel_rect.Right - 2, panel_rect.Bottom - 2 );
            dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Bottom - 1, panel_rect.Left + 2, panel_rect.Bottom - 1 );
            
            // border
            pen = ResPool.GetPen( tab_border_color );
            
            dc.DrawLine( pen, panel_rect.Left, panel_rect.Top - 1, panel_rect.Right - 1, panel_rect.Top - 1 );
            dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Top - 1, panel_rect.Right - 1, panel_rect.Bottom - 2 );
            dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Bottom - 2, panel_rect.Right - 3, panel_rect.Bottom );
            dc.DrawLine( pen, panel_rect.Right - 3, panel_rect.Bottom, panel_rect.Left + 2, panel_rect.Bottom );
            dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Bottom, panel_rect.Left, panel_rect.Bottom - 2 );
            dc.DrawLine( pen, panel_rect.Left, panel_rect.Bottom - 2, panel_rect.Left, panel_rect.Top - 1 );
            break;
            
            // FIXME: the size of the tab page is to big to draw the upper inner white border
          case TabAlignment.Right:
            // inner border...
            pen = ResPool.GetPen( Color.White );
            
            dc.DrawLine( pen, panel_rect.Left + 1, panel_rect.Top + 1, panel_rect.Left + 1, panel_rect.Bottom - 1 );
            dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Top + 1 , panel_rect.Right - 2, panel_rect.Top + 1 );
            
            pen = ResPool.GetPen( tab_inner_border_color );
            dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Top + 1, panel_rect.Right - 2, panel_rect.Bottom - 2 );
            dc.DrawLine( pen, panel_rect.Right - 2, panel_rect.Bottom - 1, panel_rect.Left + 2, panel_rect.Bottom - 1 );
            
            // border
            pen = ResPool.GetPen( tab_border_color );
            
            dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Top, panel_rect.Right - 1, panel_rect.Top );
            dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Top, panel_rect.Right - 1, panel_rect.Bottom );
            dc.DrawLine( pen, panel_rect.Right - 1, panel_rect.Bottom, panel_rect.Left + 2, panel_rect.Bottom );
            dc.DrawLine( pen, panel_rect.Left + 2, panel_rect.Bottom, panel_rect.Left, panel_rect.Bottom - 2 );
            dc.DrawLine( pen, panel_rect.Left, panel_rect.Bottom - 2, panel_rect.Left, panel_rect.Top + 2 );
            dc.DrawLine( pen, panel_rect.Left, panel_rect.Top + 2, panel_rect.Left + 2, panel_rect.Top );
            break;
        }
      }
      
      if (tab.Alignment == TabAlignment.Top) {
        for (int r = tab.TabPages.Count; r > 0; r--) {
          for (int i = tab.SliderPos; i < tab.TabPages.Count; i++) {
            if (i == tab.SelectedIndex)
              continue;
            if (r != tab.TabPages [i].Row)
              continue;
            Rectangle rect = tab.GetTabRect (i);
            if (!rect.IntersectsWith (area))
              continue;
            DrawTab (dc, tab.TabPages [i], tab, rect, false);
          }
        }
      } else {
        for (int r = 0; r < tab.TabPages.Count; r++) {
          for (int i = tab.SliderPos; i < tab.TabPages.Count; i++) {
            if (i == tab.SelectedIndex)
              continue;
            if (r != tab.TabPages [i].Row)
              continue;
            Rectangle rect = tab.GetTabRect (i);
            if (!rect.IntersectsWith (area))
              continue;
            DrawTab (dc, tab.TabPages [i], tab, rect, false);
          }
        }
      }
      
      if (tab.SelectedIndex != -1 && tab.SelectedIndex >= tab.SliderPos) {
        Rectangle rect = tab.GetTabRect (tab.SelectedIndex);
        if (rect.IntersectsWith (area))
          DrawTab (dc, tab.TabPages [tab.SelectedIndex], tab, rect, true);
      }
      
      if (tab.ShowSlider) {
        Rectangle right = TabControlGetRightScrollRect (tab);
        Rectangle left = TabControlGetLeftScrollRect (tab);
        CPDrawScrollButton (dc, right, ScrollButton.Right, tab.RightSliderState);
        CPDrawScrollButton (dc, left, ScrollButton.Left, tab.LeftSliderState);
      }
    }
    
    protected virtual int DrawTab (Graphics dc, TabPage page, TabControl tab, Rectangle bounds, bool is_selected)
    {
      int FlatButtonSpacing = 8;
      Rectangle interior;
      int res = bounds.Width;
      
      if (page.BackColor != tab_selected_gradient_second_color)
        page.BackColor = tab_selected_gradient_second_color;
      
      // we can't fill the background right away because the bounds might be adjusted if the tab is selected
      
      StringFormat string_format = new StringFormat ();
      
      if (tab.Appearance == TabAppearance.Buttons || tab.Appearance == TabAppearance.FlatButtons) {
        dc.FillRectangle (ResPool.GetSolidBrush (tab_selected_gradient_second_color), bounds);
        
        // Separators
        if (tab.Appearance == TabAppearance.FlatButtons) {
          int width = bounds.Width;
          bounds.Width += (FlatButtonSpacing - 2);
          res = bounds.Width;
          CPDrawBorder3D (dc, bounds, Border3DStyle.Etched, Border3DSide.Right);
          bounds.Width = width;
        }
        
        if (is_selected) {
          CPDrawBorder3D (dc, bounds, Border3DStyle.Sunken, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom);
        } else if (tab.Appearance != TabAppearance.FlatButtons) {
          CPDrawBorder3D (dc, bounds, Border3DStyle.Raised, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom);
        }
        
        interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 4, bounds.Height - 4);
        
        string_format.Alignment = StringAlignment.Center;
        string_format.LineAlignment = StringAlignment.Center;
        string_format.FormatFlags = StringFormatFlags.NoWrap;
      } else {
        Color tab_first_color = is_selected ? tab_selected_gradient_first_color : tab_not_selected_gradient_first_color;
        Color tab_second_color = is_selected ? tab_selected_gradient_second_color : tab_not_selected_gradient_second_color;
        
        switch (tab.Alignment) {
        case TabAlignment.Top:
          
          Rectangle tab_interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 2, bounds.Height - 3);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left + 2, bounds.Top + 2), new Point (bounds.Left + 2, bounds.Bottom), tab_first_color, tab_second_color)) {
            dc.FillRectangle (lgbr, tab_interior);
          }
          
          // edges
          Pen tmp_pen = ResPool.GetPen (tab_edge_color);
          dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 1, bounds.Left + 1, bounds.Top);
          dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Top, bounds.Right, bounds.Top + 1);
          
          // inner border
          tmp_pen = ResPool.GetPen (Color.White);
          dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Left + 1, bounds.Top + 1);
          dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 1, bounds.Right - 1, bounds.Top + 1);
          
          // border
          tmp_pen = ResPool.GetPen (border_pressed_dark_color);
          dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 2, bounds.Left + 2, bounds.Top);
          dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top, bounds.Right - 2, bounds.Top);
          dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top, bounds.Right, bounds.Top + 2);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Left, bounds.Bottom - 1), border_pressed_dark_color, border_pressed_light_color)) {
            int diff = is_selected ? 3 : 2;
            using (Pen lgbrpen = new Pen (lgbr)) {
              dc.DrawLine (lgbrpen, bounds.Left, bounds.Top + 2, bounds.Left, bounds.Bottom - diff);
              dc.DrawLine (lgbrpen, bounds.Right, bounds.Top + 2, bounds.Right, bounds.Bottom - diff);
            }
          }
          
          if (page.Focused) {
            tmp_pen = ResPool.GetPen (tab_focus_color);
            dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top  + 2, bounds.Right - 1, bounds.Top + 2);
            dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 1, bounds.Right - 2, bounds.Top + 1);
            
            tmp_pen = ResPool.GetPen (tab_top_border_focus_color);
            dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 2, bounds.Left + 2, bounds.Top);
            dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top, bounds.Right - 2, bounds.Top);
            dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top, bounds.Right, bounds.Top + 2);
          }
          
          interior = new Rectangle (bounds.Left + 4, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8);
          
          string_format.Alignment = StringAlignment.Center;
          string_format.LineAlignment = StringAlignment.Center;
          string_format.FormatFlags = StringFormatFlags.NoWrap;
          
          break;
          
        case TabAlignment.Bottom:
          
          tab_interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 2, bounds.Height - 3);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left + 2, bounds.Top + 2), new Point (bounds.Left + 2, bounds.Bottom - 1), tab_first_color, tab_second_color)) {
            dc.FillRectangle (lgbr, tab_interior);
          }
          
          // edges
          tmp_pen = ResPool.GetPen (tab_edge_color);
          dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 1, bounds.Left + 1, bounds.Bottom);
          dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom, bounds.Right, bounds.Bottom - 1);
          
          // inner border
          tmp_pen = ResPool.GetPen (Color.White);
          dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Left + 1, bounds.Top + 2);
          dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom - 1, bounds.Right - 1, bounds.Bottom - 1);
          
          // border
          tmp_pen = ResPool.GetPen (border_pressed_dark_color);
          dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 2, bounds.Left + 2, bounds.Bottom);
          dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom, bounds.Right - 2, bounds.Bottom);
          dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Bottom, bounds.Right, bounds.Bottom - 2);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Left, bounds.Bottom - 1), border_pressed_light_color, border_pressed_dark_color)) {
            int diff = is_selected ? 3 : 2;
            using (Pen lgbrpen = new Pen (lgbr)) {
              dc.DrawLine (lgbrpen, bounds.Left, bounds.Top + 2, bounds.Left, bounds.Bottom - 1 - diff);
              dc.DrawLine (lgbrpen, bounds.Right, bounds.Top + 2, bounds.Left, bounds.Bottom - 1 - diff);
            }
          }
          
          if (page.Focused) {
            tmp_pen = ResPool.GetPen (tab_focus_color);
            dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Right - 1, bounds.Bottom - 2);
            dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom - 1);
            
            tmp_pen = ResPool.GetPen (tab_top_border_focus_color);
            dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 2, bounds.Left + 2, bounds.Bottom);
            dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Bottom, bounds.Right - 2, bounds.Bottom);
            dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Bottom, bounds.Right, bounds.Bottom - 2);
          }
          
          interior = new Rectangle (bounds.Left + 4, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8);
          
          string_format.Alignment = StringAlignment.Center;
          string_format.LineAlignment = StringAlignment.Center;
          string_format.FormatFlags = StringFormatFlags.NoWrap;
          
          break;
          
        case TabAlignment.Left:
          
          int w_diff = is_selected ? 2 : 0;
          
          tab_interior = new Rectangle (bounds.Left + 2, bounds.Top + 2, bounds.Width - 2 - w_diff, bounds.Height - 2);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left + 2, bounds.Top + 2), new Point (bounds.Right - w_diff, bounds.Top + 2), tab_first_color, tab_second_color)) {
            dc.FillRectangle (lgbr, tab_interior);
          }
          
          // edges
          tmp_pen = ResPool.GetPen (tab_edge_color);
          dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top, bounds.Left, bounds.Top + 1);
          dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 1, bounds.Left + 1, bounds.Bottom);
          
          // inner border
          tmp_pen = ResPool.GetPen (Color.White);
          dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 1, bounds.Right - 3, bounds.Top + 1);
          dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top + 2, bounds.Left + 1, bounds.Bottom - 2);
          
          // border
          tmp_pen = ResPool.GetPen (border_pressed_dark_color);
          dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top, bounds.Left, bounds.Top + 2);
          dc.DrawLine (tmp_pen, bounds.Left, bounds.Top + 2, bounds.Left, bounds.Bottom - 2);
          dc.DrawLine (tmp_pen, bounds.Left, bounds.Bottom - 2, bounds.Left + 2, bounds.Bottom);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Right - 2, bounds.Top + 2), border_pressed_dark_color, border_pressed_light_color)) {
            int diff = is_selected ? 3 : 1;
            
            using (Pen lgbrpen = new Pen (lgbr)) {
              dc.DrawLine (lgbrpen, bounds.Left + 2, bounds.Top, bounds.Right - diff, bounds.Left + 2);
              dc.DrawLine (lgbrpen, bounds.Left + 2, bounds.Bottom, bounds.Right - diff, bounds.Left + 2);
            }
          }
          
          if (page.Focused) {
            tmp_pen = ResPool.GetPen (tab_focus_color);
            dc.DrawLine (tmp_pen, bounds.Left + 3, bounds.Top + 1, bounds.Left + 3, bounds.Bottom - 1);
            dc.DrawLine (tmp_pen, bounds.Left + 2, bounds.Top + 2, bounds.Left + 2, bounds.Bottom - 2);
            
            tmp_pen = ResPool.GetPen (tab_top_border_focus_color);
            dc.DrawLine (tmp_pen, bounds.Left + 3, bounds.Top, bounds.Left + 1, bounds.Top + 2);
            dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Top + 2, bounds.Left + 1, bounds.Bottom - 2);
            dc.DrawLine (tmp_pen, bounds.Left + 1, bounds.Bottom - 2, bounds.Left + 3, bounds.Bottom);
          }
          
          interior = new Rectangle (bounds.Left + 2, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8);
          
          string_format.Alignment = StringAlignment.Center;
          string_format.LineAlignment = StringAlignment.Center;
          string_format.FormatFlags = StringFormatFlags.NoWrap;
          string_format.FormatFlags = StringFormatFlags.DirectionVertical;
          
          break;
          
        default:
          // TabAlignment.Right
          
          tab_interior = new Rectangle (bounds.Left, bounds.Top + 2, bounds.Width - 2, bounds.Height - 2);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Right, bounds.Top + 2), tab_second_color, tab_first_color)) {
            dc.FillRectangle (lgbr, tab_interior);
          }
          
          int l_diff = is_selected ? 2 : 0;
          
          // edges
          tmp_pen = ResPool.GetPen (tab_edge_color);
          dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top, bounds.Right - 1, bounds.Top + 1);
          dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom);
          
          // inner border
          tmp_pen = ResPool.GetPen (Color.White);
          dc.DrawLine (tmp_pen, bounds.Left + l_diff, bounds.Top + 1, bounds.Right - 2, bounds.Top + 1);
          dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2);
          
          // border
          tmp_pen = ResPool.GetPen (border_pressed_dark_color);
          dc.DrawLine (tmp_pen, bounds.Right - 3, bounds.Top, bounds.Right - 1, bounds.Top + 2);
          dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Top + 2, bounds.Right - 1, bounds.Bottom - 2);
          dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom - 2, bounds.Right - 3, bounds.Bottom);
          
          using (LinearGradientBrush lgbr = new LinearGradientBrush (new Point (bounds.Left, bounds.Top + 2), new Point (bounds.Right - 2, bounds.Top + 2), border_pressed_light_color, border_pressed_dark_color)) {
            int diff = is_selected ? 3 : 1;
            
            using (Pen lgbrpen = new Pen (lgbr)) {
              dc.DrawLine (lgbrpen, bounds.Left + l_diff, bounds.Top, bounds.Right - diff, bounds.Top);
              dc.DrawLine (lgbrpen, bounds.Left + l_diff, bounds.Bottom, bounds.Right - diff, bounds.Bottom);
            }
          }
          
          if (page.Focused) {
            tmp_pen = ResPool.GetPen (tab_focus_color);
            dc.DrawLine (tmp_pen, bounds.Right - 3, bounds.Top + 1, bounds.Right - 3, bounds.Bottom - 1);
            dc.DrawLine (tmp_pen, bounds.Right - 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2);
            
            tmp_pen = ResPool.GetPen (tab_top_border_focus_color);
            dc.DrawLine (tmp_pen, bounds.Right - 3, bounds.Top, bounds.Right - 1, bounds.Top + 2);
            dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Top + 2, bounds.Right - 1, bounds.Bottom - 2);
            dc.DrawLine (tmp_pen, bounds.Right - 1, bounds.Bottom - 2, bounds.Right - 3, bounds.Bottom);
          }
          
          interior = new Rectangle (bounds.Left + 4, bounds.Top + 4, bounds.Width - 8, bounds.Height - 8);
          
          string_format.Alignment = StringAlignment.Center;
          string_format.LineAlignment = StringAlignment.Center;
          string_format.FormatFlags = StringFormatFlags.NoWrap;
          string_format.FormatFlags = StringFormatFlags.DirectionVertical;
          
          break;
        }
      }
      
      if (tab.DrawMode == TabDrawMode.Normal && page.Text != null) {
        if (tab.Alignment == TabAlignment.Left) {
          int wo = interior.Width / 2;
          int ho = interior.Height / 2;
          dc.TranslateTransform (interior.X + wo, interior.Y + ho);
          dc.RotateTransform (180);
          dc.DrawString (page.Text, page.Font, ResPool.GetSolidBrush (SystemColors.ControlText), 0, 0, string_format);
          dc.ResetTransform ();
        } else {
          dc.DrawString (page.Text, page.Font,
                   ResPool.GetSolidBrush (SystemColors.ControlText),
                   interior, string_format);
        }
      } else if (page.Text != null) {
        DrawItemState state = DrawItemState.None;
        if (page == tab.SelectedTab)
          state |= DrawItemState.Selected;
        DrawItemEventArgs e = new DrawItemEventArgs (dc,
                       tab.Font, bounds, tab.IndexForTabPage (page),
                       state, page.ForeColor, page.BackColor);
        tab.OnDrawItemInternal (e);
        return res;
      }
      
      return res;
    }    
    
    public override void CPDrawComboButton( Graphics dc, Rectangle rectangle, ButtonState state ) {
      Point[]      arrow = new Point[ 3 ];
      Point        P1;
      Point        P2;
      Point        P3;
      int        centerX;
      int        centerY;
      int        shiftX;
      int        shiftY;
      Rectangle    rect;
      
      bool pushed = false;
      
      Color first_color = Color.White;
      Color second_color = combobox_button_second_gradient_color;
      
      dc.FillRectangle( ResPool.GetSolidBrush( Color.White ), rectangle );
      
      if ( state == ButtonState.Pushed ) {
        first_color = pressed_gradient_first_color;
        second_color = pressed_gradient_second_color;
        pushed = true;
      }
      
      using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( rectangle.X, rectangle.Y + 2 ), new Point( rectangle.X, rectangle.Bottom - 2 ), first_color, second_color ) ) {
        dc.FillRectangle( lgbr, rectangle.X + 2, rectangle.Y + 2, rectangle.Width - 4, rectangle.Height - 4 );
      }
      
      // inner borders
      Pen tmp_pen = ResPool.GetPen( !pushed ? Color.White : pressed_inner_border_dark_color );
      dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 1, rectangle.Right - 2, rectangle.Y + 1 );
      dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 1, rectangle.X + 1, rectangle.Bottom - 2 );
      
      tmp_pen = ResPool.GetPen( !pushed ? inner_border_dark_color : pressed_inner_border_dark_color  );
      dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Y + 2, rectangle.Right - 2, rectangle.Bottom - 2 );
      dc.DrawLine( tmp_pen, rectangle.X + 2, rectangle.Bottom - 2, rectangle.Right - 2, rectangle.Bottom - 2 );
      
      // border
      Point[] points = new Point[] {
        new Point( rectangle.X, rectangle.Y ),
        new Point( rectangle.Right - 3, rectangle.Y ),
        new Point( rectangle.Right - 1, rectangle.Y + 2 ),
        new Point( rectangle.Right - 1, rectangle.Bottom - 3 ),
        new Point( rectangle.Right - 3, rectangle.Bottom - 1 ),
        new Point( rectangle.X, rectangle.Bottom - 1 ),
        new Point( rectangle.X, rectangle.Y )
      };
      
      dc.DrawPolygon( ResPool.GetPen( pushed ? border_pressed_dark_color : border_normal_dark_color ), points );
      
      // edges on right side
      tmp_pen = ResPool.GetPen( control_parent_backcolor );
      dc.DrawLine( tmp_pen, rectangle.Right - 1, rectangle.Y, rectangle.Right - 1, rectangle.Y + 1 );
      dc.DrawLine( tmp_pen, rectangle.Right - 1, rectangle.Bottom - 1, rectangle.Right - 1, rectangle.Bottom - 2 );
      
      tmp_pen = ResPool.GetPen( edge_bottom_inner_color );
      dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Y, rectangle.Right - 1, rectangle.Y + 1 );
      dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Bottom - 1, rectangle.Right - 1, rectangle.Bottom - 2 );
      
      rect = new Rectangle( rectangle.X + 1 + rectangle.Width / 4, rectangle.Y + rectangle.Height / 4, rectangle.Width / 2 - 1, rectangle.Height / 2 );
      centerX = rect.Left + rect.Width / 2;
      centerY = rect.Top + rect.Height / 2;
      shiftX = Math.Max( 1, rect.Width / 8 );
      shiftY = Math.Max( 1, rect.Height / 8 );
      
      if ( ( state & ButtonState.Pushed ) != 0 ) {
        shiftX--;
        shiftY--;
      }
      
      rect.Y -= shiftY;
      centerY -= shiftY;
      
      P1 = new Point( rect.Left, centerY );
      P2 = new Point( centerX, rect.Bottom );
      P3 = new Point( rect.Right - 1, centerY );
      
      arrow[ 0 ] = P1;
      arrow[ 1 ] = P2;
      arrow[ 2 ] = P3;
      
      SmoothingMode old_smoothing_mode = dc.SmoothingMode;
      dc.SmoothingMode = SmoothingMode.AntiAlias;
      
      /* Draw the arrow */
      if ( state == ButtonState.Inactive ) {
        /* Move away from the shadow */
        P1.X += 1;    P1.Y += 1;
        P2.X += 1;    P2.Y += 1;
        P3.X += 1;    P3.Y += 1;
        
        arrow[ 0 ] = P1;
        arrow[ 1 ] = P2;
        arrow[ 2 ] = P3;
        
        using ( Pen pen = new Pen( SystemColors.ControlLightLight, 2 ) ) {
          dc.DrawLines( pen, arrow );
        }
        
        P1 = new Point( rect.Left, centerY );
        P2 = new Point( centerX, rect.Bottom );
        P3 = new Point( rect.Right - 1, centerY );
        
        arrow[ 0 ] = P1;
        arrow[ 1 ] = P2;
        arrow[ 2 ] = P3;
        
        using ( Pen pen = new Pen( SystemColors.ControlDark, 2 ) ) {
          dc.DrawLines( pen, arrow );
        }
      } else {
        using ( Pen pen = new Pen( SystemColors.ControlText, 2 ) ) {
          dc.DrawLines( pen, arrow );
        }
      }
      
      dc.SmoothingMode = old_smoothing_mode;
    }
    
    /* Scroll button: regular button + direction arrow */
    public override void CPDrawScrollButton( Graphics dc, Rectangle area, ScrollButton scroll_button_type, ButtonState state ) {
      bool enabled = ( state == ButtonState.Inactive ) ? false: true;
      
      DrawScrollButtonPrimitive( dc, area, state, scroll_button_type );
      
      Color color_arrow;
      
      if ( enabled )
        color_arrow = arrow_color;
      else
        color_arrow = ColorGrayText;
      
      /* Paint arrows */
      
      int centerX = area.Left + area.Width / 2;
      int centerY = area.Top + area.Height / 2;
      
      int shift = 0;
      
      if ( ( state & ButtonState.Pushed ) != 0 )
        shift = 1;
      
      int min_4 = 4;
      int min_2 = 2;
      if ( area.Width < 12 || area.Height < 12 ) {
        min_4 = 3;
        min_2 = 1;
      }
      
      Point[]  arrow = new Point[ 4 ];
      
      switch (scroll_button_type) {
      case ScrollButton.Down:
        centerY += shift + 1;
        arrow [0] = new Point (centerX - min_4, centerY - min_2);
        arrow [1] = new Point (centerX, centerY + min_2);
        arrow [2] = new Point (centerX + min_4, centerY - min_2);
        arrow [3] = new Point (centerX - min_4, centerY - min_2);
        break;
      case ScrollButton.Up:
        centerY -= shift;
        arrow [0] = new Point (centerX - min_4, centerY + min_2);
        arrow [1] = new Point (centerX, centerY - min_2);
        arrow [2] = new Point (centerX + min_4, centerY + min_2);
        arrow [3] = new Point (centerX - min_4, centerY + min_2);
        break;
      case ScrollButton.Left:
        centerX -= shift;
        arrow [0] = new Point (centerX + min_2, centerY - min_4);
        arrow [1] = new Point (centerX + min_2, centerY + min_4);
        arrow [2] = new Point (centerX - min_2, centerY);
        arrow [3] = new Point (centerX + min_2, centerY - min_4);
        break;
      case ScrollButton.Right:
        centerX += shift + 1;
        arrow [0] = new Point (centerX - min_2, centerY - min_4);
        arrow [1] = new Point (centerX + min_2, centerY);
        arrow [2] = new Point (centerX - min_2, centerY + min_4);
        arrow [3] = new Point (centerX - min_2, centerY - min_4);
        break;
      default:
        break;
      }
      
      SmoothingMode old_smoothing_mode = dc.SmoothingMode;
      dc.SmoothingMode = SmoothingMode.AntiAlias;
      dc.FillPolygon( ResPool.GetSolidBrush( color_arrow ), arrow );
      dc.SmoothingMode = old_smoothing_mode;
    }
    
    public override void CPDrawSizeGrip( Graphics dc, Color backColor, Rectangle bounds ) {
      Point pt1 = new Point( bounds.Right - 3, bounds.Bottom );
      Point pt2 = new Point( bounds.Right, bounds.Bottom - 3 );
      
      // diagonals
      Pen tmp_pen = ResPool.GetPen( Color.White );
      for ( int i = 0; i < 4; i++ ) {
        dc.DrawLine( tmp_pen, pt1.X - i * 4, pt1.Y, pt2.X, pt2.Y - i * 4 );
      }
      
      pt1.X += 1;
      pt2.Y += 1;
      
      tmp_pen = ResPool.GetPen( pressed_inner_border_dark_color );
      for ( int i = 0; i < 4; i++ ) {
        dc.DrawLine( tmp_pen, pt1.X - i * 4, pt1.Y, pt2.X, pt2.Y - i * 4 );
      }
    }
    
    private void DrawScrollBarThumb( Graphics dc, Rectangle area, ScrollBar bar ) {
      LinearGradientBrush lgbr = null;
      
      if ( bar.vert )
        lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.Right - 2, area.Y + 2 ), scrollbar_gradient_first_color, scrollbar_gradient_second_color );
      else
        lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.X + 2, area.Bottom - 2 ), scrollbar_gradient_first_color, scrollbar_gradient_second_color );
      
      dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 4 );
      
      lgbr.Dispose( );
      
      // outer border
      Pen pen = ResPool.GetPen( border_normal_dark_color );
      
      dc.DrawRectangle( pen, area.X, area.Y, area.Width - 1, area.Height - 1 );
      
      // inner border
      pen = ResPool.GetPen( Color.White );
      dc.DrawLine( pen, area.X + 1, area.Bottom - 2, area.X + 1, area.Y + 1 );
      dc.DrawLine( pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 );
      
      pen = ResPool.GetPen( inner_border_dark_color );
      dc.DrawLine( pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 );
      dc.DrawLine( pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 );
      
      if ( bar.vert ) {
        if ( area.Height > 12 ) {
          int mid_y = area.Y + ( area.Height / 2 );
          int mid_x = area.X + ( area.Width / 2 );
          
          pen = ResPool.GetPen( pressed_inner_border_dark_color );
          dc.DrawLine( pen, mid_x - 3, mid_y, mid_x + 3, mid_y );
          dc.DrawLine( pen, mid_x - 3, mid_y - 3, mid_x + 3, mid_y - 3 );
          dc.DrawLine( pen, mid_x - 3, mid_y + 3, mid_x + 3, mid_y + 3 );
          
          Pen spen = ResPool.GetPen( Color.White );
          dc.DrawLine( spen, mid_x - 3, mid_y + 1, mid_x + 3, mid_y + 1 );
          dc.DrawLine( spen, mid_x - 3, mid_y - 2, mid_x + 3, mid_y - 2 );
          dc.DrawLine( spen, mid_x - 3, mid_y + 4, mid_x + 3, mid_y + 4 );
        }
      } else {
        // draw grip lines only if there is enough space
        if ( area.Width > 12 ) {
          int mid_x = area.X +  ( area.Width / 2 );
          int mid_y = area.Y +  ( area.Height / 2 );
          
          pen = ResPool.GetPen( pressed_inner_border_dark_color );
          dc.DrawLine( pen, mid_x, mid_y - 3, mid_x, mid_y + 3 );
          dc.DrawLine( pen, mid_x - 3, mid_y - 3, mid_x - 3, mid_y + 3 );
          dc.DrawLine( pen, mid_x + 3, mid_y - 3, mid_x + 3, mid_y + 3 );
          
          Pen spen = ResPool.GetPen( Color.White );
          dc.DrawLine( spen, mid_x + 1, mid_y - 3, mid_x + 1, mid_y + 3 );
          dc.DrawLine( spen, mid_x - 2, mid_y - 3, mid_x - 2, mid_y + 3 );
          dc.DrawLine( spen, mid_x + 4, mid_y - 3, mid_x + 4, mid_y + 3 );
        }
      }
    }
    
    public void DrawScrollButtonPrimitive( Graphics dc, Rectangle area, ButtonState state, ScrollButton scroll_button_type ) {
      Pen pen = ResPool.GetPen( border_normal_dark_color );
      
      Color first_gradient_color = gradient_first_color; 
      Color second_gradient_color = gradient_second_color_nr2;
      
      bool pushed = false;
      
      if ( ( state & ButtonState.Pushed ) == ButtonState.Pushed ) {
        first_gradient_color = pressed_gradient_first_color;
        second_gradient_color = pressed_gradient_second_color;
        pushed = true;
      }
      
      Point[] points = null;
      
      LinearGradientBrush lgbr = null;
      
      switch ( scroll_button_type ) {
        case ScrollButton.Left:
          // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control
          dc.DrawLine( ResPool.GetPen( ColorControl ), area.X, area.Y, area.X, area.Bottom - 1 );
          
          lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.X + 2, area.Bottom - 2 ), first_gradient_color, second_gradient_color );
          dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 2 );
          
          Pen tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White );
          dc.DrawLine( tmp_pen, area.X + 1, area.Y + 2, area.X + 1, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 );
          
          tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color );
          dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 );
          
          tmp_pen = ResPool.GetPen( edge_top_inner_color );
          dc.DrawLine( tmp_pen, area.X, area.Y + 1, area.X + 1, area.Y );
          dc.DrawLine( tmp_pen, area.X, area.Bottom - 2, area.X + 1, area.Bottom - 1 );
          
          points = new Point[] {
            new Point( area.X + 2, area.Y ),
            new Point( area.Right - 1, area.Y ),
            new Point( area.Right - 1, area.Bottom - 1 ),
            new Point( area.X + 2, area.Bottom - 1 ),
            new Point( area.X, area.Bottom - 3 ),
            new Point( area.X, area.Y + 2 ),
            new Point( area.X + 2, area.Y )
          };
          dc.DrawPolygon( pen, points );
          break;
        case ScrollButton.Right:
          // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control
          dc.DrawLine( ResPool.GetPen( ColorControl ), area.Right - 1, area.Y, area.Right - 1, area.Bottom - 1 );
          
          lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y + 2 ), new Point( area.X + 2, area.Bottom - 2 ), first_gradient_color, second_gradient_color );
          dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 2 );
          
          tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White );
          dc.DrawLine( tmp_pen, area.X + 1, area.Y + 1, area.X + 1, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 );
          
          tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color );
          dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 );
          
          tmp_pen = ResPool.GetPen( edge_top_inner_color );
          dc.DrawLine( tmp_pen, area.Right - 2, area.Y, area.Right - 1, area.Y + 1 );
          dc.DrawLine( tmp_pen, area.Right - 1, area.Bottom - 2, area.Right - 2, area.Bottom - 1 );
          
          points = new Point[] {
            new Point( area.X, area.Y ),
            new Point( area.Right - 3, area.Y ),
            new Point( area.Right - 1, area.Y + 2 ),
            new Point( area.Right - 1, area.Bottom - 3 ),
            new Point( area.Right - 3, area.Bottom - 1 ),
            new Point( area.X, area.Bottom - 1 ),
            new Point( area.X, area.Y ),
          };
          dc.DrawPolygon( pen, points );
          break;
        case ScrollButton.Up:
          // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control
          dc.DrawLine( ResPool.GetPen( ColorControl ), area.X, area.Y, area.Right - 1, area.Y );
          
          lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y ), new Point( area.Right - 2, area.Y ), first_gradient_color, second_gradient_color );
          dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 4 );
          
          tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White );
          dc.DrawLine( tmp_pen, area.X + 1, area.Y + 1, area.X + 1, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 );
          
          tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color );
          dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 );
          
          tmp_pen = ResPool.GetPen( edge_top_inner_color );
          dc.DrawLine( tmp_pen, area.X, area.Y + 1, area.X + 1, area.Y );
          dc.DrawLine( tmp_pen, area.Right - 2, area.Y, area.Right - 1, area.Y + 1 );
          
          points = new Point[] {
            new Point( area.X + 2, area.Y ),
            new Point( area.Right - 3, area.Y ),
            new Point( area.Right - 1, area.Y + 2 ),
            new Point( area.Right - 1, area.Bottom - 1 ),
            new Point( area.X, area.Bottom - 1 ),
            new Point( area.X, area.Y + 2 ),
            new Point( area.X + 2, area.Y )
          };
          dc.DrawPolygon( pen, points );
          break;
        case ScrollButton.Down:
          // FIXME: temporary fix for artefacts, it should use the backcolor of the parent control
          dc.DrawLine( ResPool.GetPen( ColorControl ), area.X, area.Bottom - 1, area.Right - 1, area.Bottom - 1 );
          
          lgbr = new LinearGradientBrush( new Point( area.X + 2, area.Y ), new Point( area.Right - 2, area.Y ), first_gradient_color, second_gradient_color );
          dc.FillRectangle( lgbr, area.X + 2, area.Y + 2, area.Width - 4, area.Height - 4 );
          
          tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : Color.White );
          dc.DrawLine( tmp_pen, area.X + 1, area.Y + 1, area.X + 1, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Y + 1, area.Right - 2, area.Y + 1 );
          
          tmp_pen = ResPool.GetPen( pushed ? pressed_inner_border_dark_color : inner_border_dark_color );
          dc.DrawLine( tmp_pen, area.Right - 2, area.Y + 2, area.Right - 2, area.Bottom - 2 );
          dc.DrawLine( tmp_pen, area.X + 2, area.Bottom - 2, area.Right - 3, area.Bottom - 2 );
          
          tmp_pen = ResPool.GetPen( edge_top_inner_color );
          dc.DrawLine( tmp_pen, area.X, area.Bottom - 2, area.X + 1, area.Bottom - 1 );
          dc.DrawLine( tmp_pen, area.Right - 2, area.Bottom - 1, area.Right - 1, area.Bottom - 2 );
          
          points = new Point[] {
            new Point( area.X, area.Y ),
            new Point( area.Right - 1, area.Y ),
            new Point( area.Right - 1, area.Bottom - 3 ),
            new Point( area.Right - 3, area.Bottom - 1 ),
            new Point( area.X + 2, area.Bottom - 1 ),
            new Point( area.X, area.Bottom - 3 ),
            new Point( area.X, area.Y )
          };
          dc.DrawPolygon( pen, points );
          break;
      }
      
      lgbr.Dispose( );
    }
    
    #region ToolBar

    #endregion // ToolBar

    #region GroupBox
    public override void DrawGroupBox( Graphics dc,  Rectangle area, GroupBox box ) {
      StringFormat  text_format;
      SizeF    size;
      int    width;
      int    y;
      Rectangle  rect;
      
      rect = box.ClientRectangle;
      
      dc.FillRectangle( ResPool.GetSolidBrush( box.BackColor ), rect );
      
      text_format = new StringFormat( );
      text_format.HotkeyPrefix = HotkeyPrefix.Show;
      
      size = dc.MeasureString( box.Text, box.Font );
      width = (int) size.Width;
      
      if ( width > box.Width - 16 )
        width = box.Width - 16;
      
      y = box.Font.Height / 2;
      
      Pen pen = ResPool.GetPen( pressed_inner_border_dark_color );
      
      /* Draw group box*/
      Point[] points = {
        new Point( 8 + width, y ),
        new Point( box.Width - 3, y ),
        new Point( box.Width - 1, y + 2 ),
        new Point( box.Width - 1, box.Height - 3 ),
        new Point( box.Width - 3, box.Height - 1 ),
        new Point( 2, box.Height - 1 ),
        new Point( 0, box.Height - 3 ),
        new Point( 0, y + 2 ),
        new Point( 2, y ),
        new Point( 8, y )
      };
      dc.DrawLines( pen, points );
      
      /* Text */
      if ( box.Enabled ) {
        dc.DrawString( box.Text, box.Font, ResPool.GetSolidBrush( box.ForeColor ), 10, 0, text_format );
      } else {
        CPDrawStringDisabled( dc, box.Text, box.Font, box.ForeColor, 
                 new RectangleF( 10, 0, width,  box.Font.Height ), text_format );
      }
      text_format.Dispose( );  
    }
    #endregion
    
    #region  TrackBar
    private void DrawTrackBar_Vertical( Graphics dc, Rectangle clip_rectangle, TrackBar tb,
               ref Rectangle thumb_pos, ref Rectangle thumb_area,
               float ticks, int value_pos, bool mouse_value ) {      
      
      Point toptick_startpoint = new Point( );
      Point bottomtick_startpoint = new Point( );
      Point channel_startpoint = new Point( );
      float pixel_len;
      float pixels_betweenticks;
      const int space_from_right = 8;
      const int space_from_left = 8;
      Rectangle area = tb.ClientRectangle;
      
      switch ( tb.TickStyle )   {
        case TickStyle.BottomRight:
        case TickStyle.None:
          channel_startpoint.Y = 8;
          channel_startpoint.X = 9;
          bottomtick_startpoint.Y = 13;
          bottomtick_startpoint.X = 24;        
          break;
        case TickStyle.TopLeft:
          channel_startpoint.Y = 8;
          channel_startpoint.X = 19;
          toptick_startpoint.Y = 13;
          toptick_startpoint.X = 8;
          break;
        case TickStyle.Both:
          channel_startpoint.Y = 8;
          channel_startpoint.X = 18;  
          bottomtick_startpoint.Y = 13;
          bottomtick_startpoint.X = 32;        
          toptick_startpoint.Y = 13;
          toptick_startpoint.X = 8;        
          break;
        default:
          break;
      }
      
      thumb_area.X = area.X + channel_startpoint.X;
      thumb_area.Y = area.Y + channel_startpoint.Y;
      thumb_area.Height = area.Height - space_from_right - space_from_left;
      thumb_area.Width = 4;
      
      pixel_len = thumb_area.Height - 11;
      pixels_betweenticks = pixel_len / ( tb.Maximum - tb.Minimum );
      
      /* Convert thumb position from mouse position to value*/
      if ( mouse_value ) {
        
        if ( value_pos >= channel_startpoint.Y )
          value_pos = (int)( ( (float) ( value_pos - channel_startpoint.Y ) ) / pixels_betweenticks );
        else
          value_pos = 0;      
        
        if ( value_pos + tb.Minimum > tb.Maximum )
          value_pos = tb.Maximum - tb.Minimum;
                                
        tb.Value = value_pos + tb.Minimum;
      }    
      
      thumb_pos.Width = 13;
      thumb_pos.Height = 29;
      
      thumb_pos.Y = channel_startpoint.Y + (int) ( pixels_betweenticks * (float) value_pos ) - ( thumb_pos.Height / 3 );
      
      if ( thumb_pos.Y < channel_startpoint.Y )
        thumb_pos.Y = channel_startpoint.Y;
      
      if ( thumb_pos.Y > thumb_area.Bottom - 29 )
        thumb_pos.Y = thumb_area.Bottom - 29;
      
      /* Draw channel */
      // bottom
      Pen pen = ResPool.GetPen( tab_top_border_focus_color );
      dc.DrawLine( pen, channel_startpoint.X, thumb_pos.Y + 29, channel_startpoint.X, thumb_area.Bottom );
      dc.DrawLine( pen, channel_startpoint.X, thumb_area.Bottom, channel_startpoint.X + 4, thumb_area.Bottom );
      dc.DrawLine( pen, channel_startpoint.X + 4, thumb_pos.Y + 29, channel_startpoint.X + 4, thumb_area.Bottom );
      
      pen = ResPool.GetPen( menuitem_gradient_first_color );
      dc.DrawLine( pen, channel_startpoint.X + 1, thumb_pos.Y + 28, channel_startpoint.X + 1, thumb_area.Bottom - 1 );
      pen = ResPool.GetPen( trackbar_second_gradient_color );
      dc.DrawLine( pen, channel_startpoint.X + 2, thumb_pos.Y + 28, channel_startpoint.X + 2, thumb_area.Bottom - 1 );
      pen = ResPool.GetPen( trackbar_third_gradient_color );
      dc.DrawLine( pen, channel_startpoint.X + 3, thumb_pos.Y + 28, channel_startpoint.X + 3, thumb_area.Bottom - 1 );
      
      // top
      pen = ResPool.GetPen( pressed_inner_border_dark_color );
      dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 1, channel_startpoint.X + 1, thumb_pos.Y );
      dc.DrawRectangle( ResPool.GetPen( scrollbar_background_color ), channel_startpoint.X + 2, channel_startpoint.Y + 1, 1, thumb_pos.Y );
      
      pen = ResPool.GetPen( scrollbar_border_color );
      dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, channel_startpoint.X, thumb_pos.Y );
      dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, channel_startpoint.X + 4, channel_startpoint.Y );
      dc.DrawLine( pen, channel_startpoint.X + 4, channel_startpoint.Y, channel_startpoint.X + 4, thumb_pos.Y );
      
      /* Draw thumb */
      thumb_pos.X = channel_startpoint.X - 4;
      
      // inner border
      pen = ResPool.GetPen( Color.White );
      dc.DrawLine( pen, thumb_pos.X + 1, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Bottom - 2 );
      dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Y + 1, thumb_pos.Right - 2, thumb_pos.Y + 1 );
      
      pen = ResPool.GetPen( menu_separator_color );
      dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 );
      dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y + 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 );
      
      // outer border
      Point[] points = {
        new Point( thumb_pos.X + 2, thumb_pos.Y ),
        new Point( thumb_pos.Right - 3 , thumb_pos.Y ),
        new Point( thumb_pos.Right - 1, thumb_pos.Y + 2 ),
        new Point( thumb_pos.Right - 1, thumb_pos.Bottom - 3 ),
        new Point( thumb_pos.Right - 3, thumb_pos.Bottom - 1 ),
        new Point( thumb_pos.X + 2, thumb_pos.Bottom - 1 ),
        new Point( thumb_pos.X, thumb_pos.Bottom - 3 ),
        new Point( thumb_pos.X, thumb_pos.Y + 2 ),
        new Point( thumb_pos.X + 2, thumb_pos.Y )
      };
      
      dc.DrawLines( ResPool.GetPen( border_normal_dark_color ), points );
      
      Color first_gradient_color = mouse_value ? button_edge_bottom_outer_color : trackbar_inner_first_gradient_color;
      Color second_gradient_color = mouse_value ? trackbar_inner_pressed_second_gradient_color : trackbar_inner_second_gradient_color;
      
      using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( thumb_pos.X, thumb_pos.Y + 2 ), new Point( thumb_pos.X, thumb_pos.Bottom - 2 ), first_gradient_color, second_gradient_color ) ) {
        dc.FillRectangle( lgbr, thumb_pos.X + 2, thumb_pos.Y + 2, thumb_pos.Width - 4, thumb_pos.Height - 4 );
      }
      
      // outer egdes
      pen = ResPool.GetPen( edge_top_inner_color );
      dc.DrawLine( pen, thumb_pos.X, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Y );
      dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y, thumb_pos.Right - 1, thumb_pos.Y + 1 );
      
      pen = ResPool.GetPen( edge_bottom_inner_color );
      dc.DrawLine( pen, thumb_pos.X, thumb_pos.Bottom - 2, thumb_pos.X + 1, thumb_pos.Bottom - 1 );
      dc.DrawLine( pen, thumb_pos.Right - 1, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 1 );
      
      // draw grip lines
      pen = ResPool.GetPen( pressed_inner_border_dark_color );
      dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 11, thumb_pos.X + 8, thumb_pos.Y + 11 );
      dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 14, thumb_pos.X + 8, thumb_pos.Y + 14 );
      dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 17, thumb_pos.X + 8, thumb_pos.Y + 17 );
      
      pen = ResPool.GetPen( Color.White );
      dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 12, thumb_pos.X + 8, thumb_pos.Y + 12 );
      dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 15, thumb_pos.X + 8, thumb_pos.Y + 15 );
      dc.DrawLine( pen, thumb_pos.X + 4, thumb_pos.Y + 18, thumb_pos.X + 8, thumb_pos.Y + 18 );
      
      pixel_len = thumb_area.Height - 11;
      pixels_betweenticks = pixel_len / ticks;
      
      /* Draw ticks*/
      thumb_area.X = thumb_pos.X;
      thumb_area.Y = channel_startpoint.Y;
      thumb_area.Width = thumb_pos.Width;
      
      Region outside = new Region( area );
      outside.Exclude( thumb_area );      
      
      if ( outside.IsVisible( clip_rectangle ) ) {        
        if ( pixels_betweenticks > 0 && ( ( tb.TickStyle & TickStyle.BottomRight ) == TickStyle.BottomRight ||
            ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) {  
          
          for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks )   {          
            if ( inc == 0 || ( inc +  pixels_betweenticks ) >= pixel_len + 1 )
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X , area.Y + bottomtick_startpoint.Y  + inc, 
                    area.X + bottomtick_startpoint.X  + 3, area.Y + bottomtick_startpoint.Y + inc );
            else
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X, area.Y + bottomtick_startpoint.Y  + inc, 
                    area.X + bottomtick_startpoint.X  + 2, area.Y + bottomtick_startpoint.Y + inc );
          }
        }
        
        if ( pixels_betweenticks > 0 &&  ( ( tb.TickStyle & TickStyle.TopLeft ) == TickStyle.TopLeft ||
            ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) {
          
          pixel_len = thumb_area.Height - 11;
          pixels_betweenticks = pixel_len / ticks;
          
          for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks ) {          
            if ( inc == 0 || ( inc +  pixels_betweenticks ) >= pixel_len + 1 )
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X  - 3 , area.Y + toptick_startpoint.Y + inc, 
                    area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y + inc );
            else
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X  - 2, area.Y + toptick_startpoint.Y + inc, 
                    area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y  + inc );
          }      
        }
      }
      
      outside.Dispose( );
      
    }
    
    private void DrawTrackBar_Horizontal( Graphics dc, Rectangle clip_rectangle, TrackBar tb,
                 ref Rectangle thumb_pos, ref Rectangle thumb_area,
                 float ticks, int value_pos, bool mouse_value ) {      
      Point toptick_startpoint = new Point( );
      Point bottomtick_startpoint = new Point( );
      Point channel_startpoint = new Point( );
      float pixel_len;
      float pixels_betweenticks;
      const int space_from_right = 8;
      const int space_from_left = 8;
      Rectangle area = tb.ClientRectangle;
      
      switch ( tb.TickStyle ) {
        case TickStyle.BottomRight:
        case TickStyle.None:
          channel_startpoint.X = 8;
          channel_startpoint.Y = 9;
          bottomtick_startpoint.X = 13;
          bottomtick_startpoint.Y = 24;        
          break;
        case TickStyle.TopLeft:
          channel_startpoint.X = 8;
          channel_startpoint.Y = 19;
          toptick_startpoint.X = 13;
          toptick_startpoint.Y = 8;
          break;
        case TickStyle.Both:
          channel_startpoint.X = 8;
          channel_startpoint.Y = 18;  
          bottomtick_startpoint.X = 13;
          bottomtick_startpoint.Y = 32;        
          toptick_startpoint.X = 13;
          toptick_startpoint.Y = 8;        
          break;
        default:
          break;
      }
      
      thumb_area.X = area.X + channel_startpoint.X;
      thumb_area.Y = area.Y + channel_startpoint.Y;
      thumb_area.Width = area.Width - space_from_right - space_from_left;
      thumb_area.Height = 4;
      
      pixel_len = thumb_area.Width - 11;
      pixels_betweenticks = pixel_len / ( tb.Maximum - tb.Minimum );
      
      /* Convert thumb position from mouse position to value*/
      if ( mouse_value ) {      
        if ( value_pos >= channel_startpoint.X )
          value_pos = (int)( ( (float) ( value_pos - channel_startpoint.X ) ) / pixels_betweenticks );
        else
          value_pos = 0;        
        
        if ( value_pos + tb.Minimum > tb.Maximum )
          value_pos = tb.Maximum - tb.Minimum;
                                
        tb.Value = value_pos + tb.Minimum;
      }      
      
      thumb_pos.Width = 29;
      thumb_pos.Height = 13;
      
      thumb_pos.X = channel_startpoint.X + (int) ( pixels_betweenticks * (float) value_pos ) - ( thumb_pos.Width / 3 );
      
      if ( thumb_pos.X < channel_startpoint.X )
        thumb_pos.X = channel_startpoint.X;
      
      if ( thumb_pos.X > thumb_area.Right - 29 )
        thumb_pos.X = thumb_area.Right - 29;
      
      /* Draw channel */
      // left side
      Pen pen = ResPool.GetPen( tab_top_border_focus_color );
      dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, thumb_pos.X, channel_startpoint.Y );
      dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y, channel_startpoint.X, channel_startpoint.Y + 4 );
      dc.DrawLine( pen, channel_startpoint.X, channel_startpoint.Y + 4, thumb_pos.X, channel_startpoint.Y + 4 );
      
      pen = ResPool.GetPen( menuitem_gradient_first_color );
      dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 1, thumb_pos.X, channel_startpoint.Y + 1 );
      pen = ResPool.GetPen( trackbar_second_gradient_color );
      dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 2, thumb_pos.X, channel_startpoint.Y + 2 );
      pen = ResPool.GetPen( trackbar_third_gradient_color );
      dc.DrawLine( pen, channel_startpoint.X + 1, channel_startpoint.Y + 3, thumb_pos.X, channel_startpoint.Y + 3 );
      
      // right side
      pen = ResPool.GetPen( pressed_inner_border_dark_color );
      dc.DrawLine( pen, thumb_pos.X + 29, channel_startpoint.Y + 1, thumb_area.Right - 1, channel_startpoint.Y + 1 );
      dc.DrawRectangle( ResPool.GetPen( scrollbar_background_color ), thumb_pos.X + 29, channel_startpoint.Y + 2, thumb_area.Right - thumb_pos.X - 30, 1 );
      
      pen = ResPool.GetPen( scrollbar_border_color );
      dc.DrawLine( pen, thumb_pos.X + 29, channel_startpoint.Y, thumb_area.Right, channel_startpoint.Y );
      dc.DrawLine( pen, thumb_area.Right, channel_startpoint.Y, thumb_area.Right, channel_startpoint.Y + 4 );
      dc.DrawLine( pen, thumb_pos.X + 29, channel_startpoint.Y + 4, thumb_area.Right, channel_startpoint.Y + 4 );
      
      /* Draw thumb */
      
      thumb_pos.Y = channel_startpoint.Y - 4;
      
      // inner border
      pen = ResPool.GetPen( Color.White );
      dc.DrawLine( pen, thumb_pos.X + 1, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Bottom - 2 );
      dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Y + 1, thumb_pos.Right - 2, thumb_pos.Y + 1 );
      
      pen = ResPool.GetPen( menu_separator_color );
      dc.DrawLine( pen, thumb_pos.X + 2, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 );
      dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y + 2, thumb_pos.Right - 2, thumb_pos.Bottom - 2 );
      
      // outer border
      Point[] points = {
        new Point( thumb_pos.X + 2, thumb_pos.Y ),
        new Point( thumb_pos.Right - 3 , thumb_pos.Y ),
        new Point( thumb_pos.Right - 1, thumb_pos.Y + 2 ),
        new Point( thumb_pos.Right - 1, thumb_pos.Bottom - 3 ),
        new Point( thumb_pos.Right - 3, thumb_pos.Bottom - 1 ),
        new Point( thumb_pos.X + 2, thumb_pos.Bottom - 1 ),
        new Point( thumb_pos.X, thumb_pos.Bottom - 3 ),
        new Point( thumb_pos.X, thumb_pos.Y + 2 ),
        new Point( thumb_pos.X + 2, thumb_pos.Y )
      };
      
      dc.DrawLines( ResPool.GetPen( border_normal_dark_color ), points );
      
      Color first_gradient_color = mouse_value ? button_edge_bottom_outer_color : trackbar_inner_first_gradient_color;
      Color second_gradient_color = mouse_value ? trackbar_inner_pressed_second_gradient_color : trackbar_inner_second_gradient_color;
      
      using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( thumb_pos.X, thumb_pos.Y + 2 ), new Point( thumb_pos.X, thumb_pos.Bottom - 2 ), first_gradient_color, second_gradient_color ) ) {
        dc.FillRectangle( lgbr, thumb_pos.X + 2, thumb_pos.Y + 2, thumb_pos.Width - 4, thumb_pos.Height - 4 );
      }
      
      // outer egdes
      pen = ResPool.GetPen( edge_top_inner_color );
      dc.DrawLine( pen, thumb_pos.X, thumb_pos.Y + 1, thumb_pos.X + 1, thumb_pos.Y );
      dc.DrawLine( pen, thumb_pos.Right - 2, thumb_pos.Y, thumb_pos.Right - 1, thumb_pos.Y + 1 );
      
      pen = ResPool.GetPen( edge_bottom_inner_color );
      dc.DrawLine( pen, thumb_pos.X, thumb_pos.Bottom - 2, thumb_pos.X + 1, thumb_pos.Bottom - 1 );
      dc.DrawLine( pen, thumb_pos.Right - 1, thumb_pos.Bottom - 2, thumb_pos.Right - 2, thumb_pos.Bottom - 1 );
      
      // draw grip lines
      pen = ResPool.GetPen( pressed_inner_border_dark_color );
      dc.DrawLine( pen, thumb_pos.X + 11, thumb_pos.Y + 4, thumb_pos.X + 11, thumb_pos.Y + 8 );
      dc.DrawLine( pen, thumb_pos.X + 14, thumb_pos.Y + 4, thumb_pos.X + 14, thumb_pos.Y + 8 );
      dc.DrawLine( pen, thumb_pos.X + 17, thumb_pos.Y + 4, thumb_pos.X + 17, thumb_pos.Y + 8 );
      
      pen = ResPool.GetPen( Color.White );
      dc.DrawLine( pen, thumb_pos.X + 12, thumb_pos.Y + 4, thumb_pos.X  + 12, thumb_pos.Y + 8 );
      dc.DrawLine( pen, thumb_pos.X + 15, thumb_pos.Y + 4, thumb_pos.X + 15, thumb_pos.Y + 8 );
      dc.DrawLine( pen, thumb_pos.X + 18, thumb_pos.Y + 4, thumb_pos.X + 18, thumb_pos.Y + 8 );
      
      pixel_len = thumb_area.Width - 11;
      pixels_betweenticks = pixel_len / ticks;
      
      /* Draw ticks*/
      thumb_area.Y = thumb_pos.Y;
      thumb_area.X = channel_startpoint.X;
      thumb_area.Height = thumb_pos.Height;
      Region outside = new Region( area );
      outside.Exclude( thumb_area );      
      
      if ( outside.IsVisible( clip_rectangle ) ) {        
        if ( pixels_betweenticks > 0 && ( ( tb.TickStyle & TickStyle.BottomRight ) == TickStyle.BottomRight ||
            ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) {        
          
          for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks ) {          
            if ( inc == 0 || ( inc +  pixels_betweenticks ) >= pixel_len + 1 )
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y, 
                    area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y + 3 );
            else
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y, 
                    area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y + 2 );
          }
        }
        
        if ( pixels_betweenticks > 0 && ( ( tb.TickStyle & TickStyle.TopLeft ) == TickStyle.TopLeft ||
            ( ( tb.TickStyle & TickStyle.Both ) == TickStyle.Both ) ) ) {
          
          for ( float inc = 0; inc < ( pixel_len + 1 ); inc += pixels_betweenticks ) {          
            if ( inc == 0 || ( inc +  pixels_betweenticks ) >= pixel_len + 1 )
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y - 3, 
                    area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y );
            else
              dc.DrawLine( ResPool.GetPen( pen_ticks_color ), area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y - 2, 
                    area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y );
          }      
        }
      }
      
      outside.Dispose( );      
    }
    
    public override void DrawTrackBar( Graphics dc, Rectangle clip_rectangle, TrackBar tb ) {
      int    value_pos;
      bool    mouse_value;
      float    ticks = ( tb.Maximum - tb.Minimum ) / tb.tickFrequency; /* N of ticks draw*/
      Rectangle  area;
      Rectangle  thumb_pos = tb.ThumbPos;
      Rectangle  thumb_area = tb.ThumbArea;
      
      if ( tb.thumb_pressed ) {
        value_pos = tb.thumb_mouseclick;
        mouse_value = true;
      } else {
        value_pos = tb.Value - tb.Minimum;
        mouse_value = false;
      }
      
      area = tb.ClientRectangle;
      
      /* Control Background */
      if ( tb.BackColor == DefaultControlBackColor ) {
        dc.FillRectangle( ResPool.GetSolidBrush( ColorControl ), clip_rectangle );
      } else {
        dc.FillRectangle( ResPool.GetSolidBrush( tb.BackColor ), clip_rectangle );
      }
      
      if ( tb.Orientation == Orientation.Vertical ) {
        DrawTrackBar_Vertical( dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
                  ticks, value_pos, mouse_value );
        
      } else {
        DrawTrackBar_Horizontal( dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
              ticks, value_pos, mouse_value );
      }
      
      // TODO: draw better focus rectangle
      if ( tb.Focused ) {
        dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X, area.Y, area.Width - 1, 1 );
        dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X, area.Y + area.Height - 1, area.Width - 1, 1 );
        dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X, area.Y, 1, area.Height - 1 );
        dc.FillRectangle( ResPool.GetHatchBrush( HatchStyle.Percent50, ColorControl, Color.Black ), area.X + area.Width - 1, area.Y, 1, area.Height - 1 );
      }
      
      tb.ThumbPos = thumb_pos;
      tb.ThumbArea = thumb_area;
    }
    #endregion  // TrackBar
    
    #region ListView
    // draws the ListViewItem of the given index
    protected override void DrawListViewItem( Graphics dc, ListView control, ListViewItem item ) {        
      Rectangle rect_checkrect = item.CheckRectReal;
      Rectangle rect_iconrect = item.GetBounds( ItemBoundsPortion.Icon );
      Rectangle full_rect = item.GetBounds( ItemBoundsPortion.Entire );
      Rectangle text_rect = item.GetBounds( ItemBoundsPortion.Label );      
      
      if ( control.CheckBoxes ) {
        if ( control.StateImageList == null ) {
          // Make sure we've got at least a line width of 1
          int check_wd = Math.Max( 3, rect_checkrect.Width / 6 );
          int scale = Math.Max( 1, rect_checkrect.Width / 12 );
          
          // set the checkbox background
          dc.FillRectangle( this.ResPool.GetSolidBrush( this.ColorWindow ),
               rect_checkrect );
          // define a rectangle inside the border area
          Rectangle rect = new Rectangle( rect_checkrect.X + 2,
                       rect_checkrect.Y + 2,
                       rect_checkrect.Width - 4,
                       rect_checkrect.Height - 4 );
          Pen pen = new Pen( this.ColorWindowText, 2 );
          dc.DrawRectangle( pen, rect );
          
          // Need to draw a check-mark
          if ( item.Checked ) {
            pen.Width = 1;
            // adjustments to get the check-mark at the right place
            rect.X ++; rect.Y ++;
            // following logic is taken from DrawFrameControl method
            for ( int i = 0; i < check_wd; i++ ) {
              dc.DrawLine( pen, rect.Left + check_wd / 2,
                    rect.Top + check_wd + i,
                    rect.Left + check_wd / 2 + 2 * scale,
                    rect.Top + check_wd + 2 * scale + i );
              dc.DrawLine( pen,
                    rect.Left + check_wd / 2 + 2 * scale,
                    rect.Top + check_wd + 2 * scale + i,
                    rect.Left + check_wd / 2 + 6 * scale,
                    rect.Top + check_wd - 2 * scale + i );
            }
          }
        } else {
          if ( item.Checked && control.StateImageList.Images.Count > 1 )
            control.StateImageList.Draw( dc,
                      rect_checkrect.Location, 1 );
          else if ( ! item.Checked && control.StateImageList.Images.Count > 0 )
            control.StateImageList.Draw( dc,
                      rect_checkrect.Location, 0 );
        }
      }
      
      // Item is drawn as a special case, as it is not just text
      if ( control.View == View.LargeIcon ) {
        if ( item.ImageIndex > -1 &&
            control.LargeImageList != null &&
            item.ImageIndex < control.LargeImageList.Images.Count ) {
          // center image
          Point image_location = rect_iconrect.Location;
          Image image = control.LargeImageList.Images[ item.ImageIndex ];
          if ( image.Width < rect_iconrect.Width ) {
            int icon_rect_middle = rect_iconrect.Width / 2;
            int image_middle = image.Width / 2;
            image_location.X = image_location.X + icon_rect_middle - image_middle;
          }
          control.LargeImageList.Draw( dc, image_location,
                    item.ImageIndex );
        }
      } else {
        if ( item.ImageIndex > -1 &&
            control.SmallImageList != null &&
            item.ImageIndex < control.SmallImageList.Images.Count )
          control.SmallImageList.Draw( dc, rect_iconrect.Location,
                    item.ImageIndex );
      }
      
      // draw the item text      
      // format for the item text
      StringFormat format = new StringFormat( );
      format.LineAlignment = StringAlignment.Center;
      if ( control.View == View.LargeIcon )
        format.Alignment = StringAlignment.Center; 
      else
        format.Alignment = StringAlignment.Near;
      
      if ( !control.LabelWrap )
        format.FormatFlags = StringFormatFlags.NoWrap;
      
      if ( item.Selected ) {
        if ( control.View == View.Details ) {
          if ( control.FullRowSelect ) {
            // fill the entire rect excluding the checkbox            
            full_rect.Location = item.GetBounds (ItemBoundsPortion.Label).Location;
            dc.FillRectangle( this.ResPool.GetSolidBrush
                 ( this.ColorHighlight ), full_rect );
          } else {
            Size text_size = Size.Ceiling( dc.MeasureString( item.Text,
                        item.Font ) );
            text_rect.Width = text_size.Width;
            dc.FillRectangle( this.ResPool.GetSolidBrush
                 ( this.ColorHighlight ), text_rect );
          }
        } else {
          /*Size text_size = Size.Ceiling (dc.MeasureString (item.Text,
           item.Font));
           Point loc = text_rect.Location;
           loc.X += (text_rect.Width - text_size.Width) / 2;
           text_rect.Width = text_size.Width;*/
          dc.FillRectangle( this.ResPool.GetSolidBrush( this.ColorHighlight ),
               text_rect );
        }
      } else
        dc.FillRectangle( ResPool.GetSolidBrush( item.BackColor ), text_rect );
      
      if ( item.Text != null && item.Text.Length > 0 ) {
        
        if ( control.View != View.LargeIcon ) {
          if ( item.Selected )
            dc.DrawString( item.Text, item.Font, this.ResPool.GetSolidBrush
                    ( this.ColorHighlightText ), text_rect, format );
          else
            dc.DrawString( item.Text, item.Font, this.ResPool.GetSolidBrush
                    ( item.ForeColor ), text_rect, format );
        } else {
          // ListView CalcTextSize says wrapping is done for two lines only !?!
          // text is centered for the complete text_rect but it should be centered per available row/line
          
          // calculate how much lines we get out of text_rect and current item.Font
          int nr_lines = text_rect.Height / item.Font.Height;
          int rest = text_rect.Height % item.Font.Height;
          int line_height = item.Font.Height + ( rest > 1 ? 2 : 0 );
          
          Rectangle[] text_rects = new Rectangle[ nr_lines ];
          
          for ( int i = 0; i < nr_lines; i++ ) {
            text_rects[ i ].X = text_rect.X;
            text_rects[ i ].Y = text_rect.Y + i * line_height;
            text_rects[ i ].Width = text_rect.Width;
            text_rects[ i ].Height = line_height;
          }
          
          string[] lines = new string[ nr_lines ];
          
          string text = item.Text;
          
          int line_nr = 0;
          int current_pos = 0;
          for ( int k = 1; k <= text.Length; k++ ) {
            lines[ line_nr ] = text.Substring( current_pos, k - current_pos );
            
            // FIXME: Graphics.MeasureString returns wrong results if there is a 
            //        space char in the string
            SizeF sizef = dc.MeasureString( lines[ line_nr ], item.Font, text_rect.Width, format );
            
            if ( (int)sizef.Width > text_rect.Width - 3 ) {
              lines[ line_nr ] = lines[ line_nr ].Remove( lines[ line_nr ].Length - 1, 1 );
              k--;
              current_pos = k;
              line_nr++;
              if ( line_nr == nr_lines )
                break;
            }
          }
          
          int j = 0;
          foreach ( Rectangle t_rect in text_rects ) {
            if ( item.Selected )
              dc.DrawString( lines[ j ], item.Font, this.ResPool.GetSolidBrush
                      ( this.ColorHighlightText ), t_rect, format );
            else
              dc.DrawString( lines[ j ], item.Font, this.ResPool.GetSolidBrush
                      ( item.ForeColor ), t_rect, format );
            j++;
          }
        } 
      }
      
      if ( control.View == View.Details && control.Columns.Count > 0 ) {
        // draw subitems for details view
        ListViewItem.ListViewSubItemCollection subItems = item.SubItems;
        int count = ( control.Columns.Count < subItems.Count ? 
          control.Columns.Count : subItems.Count );
        
        if ( count > 0 ) {
          ColumnHeader col;
          ListViewItem.ListViewSubItem subItem;
          Rectangle sub_item_rect = text_rect; 
          
          // set the format for subitems
          format.FormatFlags = StringFormatFlags.NoWrap;
          format.Alignment = StringAlignment.Near;
          
          // 0th subitem is the item already drawn
          for ( int index = 1; index < count; index++ ) {
            subItem = subItems[ index ];
            col = control.Columns[ index ];
            sub_item_rect.X = col.Rect.Left;
            sub_item_rect.Width = col.Wd;
            sub_item_rect.X -= control.h_marker;
            
            SolidBrush sub_item_back_br = null;
            SolidBrush sub_item_fore_br = null;
            Font sub_item_font = null;
            
            if ( item.UseItemStyleForSubItems ) {
              sub_item_back_br = this.ResPool.GetSolidBrush
              ( item.BackColor );
              sub_item_fore_br = this.ResPool.GetSolidBrush
              ( item.ForeColor );
              sub_item_font = item.Font;
            } else {
              sub_item_back_br = this.ResPool.GetSolidBrush
              ( subItem.BackColor );
              sub_item_fore_br = this.ResPool.GetSolidBrush
              ( subItem.ForeColor );
              sub_item_font = subItem.Font;
            }
            
            // In case of fullrowselect, background is filled
            // for the entire rect above
            if ( item.Selected && control.FullRowSelect ) {
              if ( subItem.Text != null && subItem.Text.Length > 0 )
                dc.DrawString( subItem.Text, sub_item_font,
                        this.ResPool.GetSolidBrush
                        ( this.ColorHighlightText ),
                        sub_item_rect, format );
            } else {
              dc.FillRectangle( sub_item_back_br, sub_item_rect );
              if ( subItem.Text != null && subItem.Text.Length > 0 )
                dc.DrawString( subItem.Text, sub_item_font,
                        sub_item_fore_br,
                        sub_item_rect, format );
            }
            sub_item_rect.X += col.Wd;
          }
        }
      }
      
      if ( item.Focused ) {        
        if ( item.Selected )
          CPDrawFocusRectangle( dc, text_rect, ColorHighlightText, ColorHighlight );
        else
          CPDrawFocusRectangle( dc, text_rect, control.ForeColor, control.BackColor );
      }
      
      format.Dispose( );
    }
    #endregion ListView
    
    #region DateTimePicker
    public override void DrawDateTimePicker (Graphics dc,  Rectangle clip_rectangle, DateTimePicker dtp) {
      // if not showing the numeric updown control then render border
      if (!dtp.ShowUpDown && clip_rectangle.IntersectsWith (dtp.ClientRectangle)) {
        // draw the outer border
        Rectangle button_bounds = dtp.ClientRectangle;
        CPDrawBorder3D (dc, button_bounds, Border3DStyle.Sunken, Border3DSide.Left | Border3DSide.Right | Border3DSide.Top | Border3DSide.Bottom, dtp.BackColor);
        
        // deflate by the border width
        if (clip_rectangle.IntersectsWith (dtp.drop_down_arrow_rect)) {
          button_bounds.Inflate (-2,-2);
          ButtonState state = dtp.is_drop_down_visible ? ButtonState.Pushed : ButtonState.Normal;
          Rectangle button_rect = new Rectangle(dtp.drop_down_arrow_rect.X, dtp.drop_down_arrow_rect.Y + 1,
                        dtp.drop_down_arrow_rect.Width - 1, dtp.drop_down_arrow_rect.Height - 2);
          this.CPDrawComboButton ( 
            dc, 
            button_rect, 
            state);
        }
      }
      
      // render the date part
      if (clip_rectangle.IntersectsWith (dtp.date_area_rect)) {
        // fill the background
        Rectangle date_area_rect = new Rectangle( dtp.date_area_rect.X + 1, dtp.date_area_rect.Y + 1,
                   dtp.date_area_rect.Width - 2,  dtp.date_area_rect.Height - 2);
        dc.FillRectangle (ResPool.GetSolidBrush (ColorWindow), date_area_rect);
        
        // fill the currently highlighted area
        if (dtp.hilight_date_area != Rectangle.Empty) {
          dc.FillRectangle (ResPool.GetSolidBrush (ColorHighlight), dtp.hilight_date_area);
        }
        
        // draw the text part
        // TODO: if date format is CUstom then we need to draw the dates as separate parts
        StringFormat text_format = new StringFormat();
        text_format.LineAlignment = StringAlignment.Center;
        text_format.Alignment = StringAlignment.Near;          
        dc.DrawString (dtp.Text, dtp.Font, ResPool.GetSolidBrush (dtp.ForeColor), Rectangle.Inflate(dtp.date_area_rect, -1, -1), text_format);
        text_format.Dispose ();
      }
    }
    #endregion // DateTimePicker
    
    #region MonthCalendar
    // draw the month calendar
    public override void DrawMonthCalendar(Graphics dc, Rectangle clip_rectangle, MonthCalendar mc) 
    {
      Rectangle client_rectangle = mc.ClientRectangle;
      Size month_size = mc.SingleMonthSize;
      // cache local copies of Marshal-by-ref internal members (gets around error CS0197)
      Size calendar_spacing = (Size)((object)mc.calendar_spacing);
      Size date_cell_size = (Size)((object)mc.date_cell_size);
      
      // draw the singlecalendars
      int x_offset = 1;
      int y_offset = 1;
      // adjust for the position of the specific month
      for (int i=0; i < mc.CalendarDimensions.Height; i++) 
      {
        if (i > 0) 
        {
          y_offset += month_size.Height + calendar_spacing.Height;
        }
        // now adjust for x position  
        for (int j=0; j < mc.CalendarDimensions.Width; j++) 
        {
          if (j > 0) 
          {
            x_offset += month_size.Width + calendar_spacing.Width;
          } 
          else 
          {
            x_offset = 1;
          }
          
          Rectangle month_rect = new Rectangle (x_offset, y_offset, month_size.Width, month_size.Height);
          if (month_rect.IntersectsWith (clip_rectangle)) {
            DrawSingleMonth (
              dc,
              clip_rectangle,
              month_rect,
              mc,
              i,
              j);
          }
        }
      }
      
      Rectangle bottom_rect = new Rectangle (
        client_rectangle.X,
        Math.Max(client_rectangle.Bottom - date_cell_size.Height - 3, 0),
        client_rectangle.Width,
        date_cell_size.Height + 2);
      // draw the today date if it's set
      if (mc.ShowToday && bottom_rect.IntersectsWith (clip_rectangle)) 
      {
        dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), bottom_rect);
        if (mc.ShowToday) {
          int today_offset = 5;
          if (mc.ShowTodayCircle) 
          {
            Rectangle today_circle_rect = new Rectangle (
              client_rectangle.X + 5,
              Math.Max(client_rectangle.Bottom - date_cell_size.Height - 2, 0),
              date_cell_size.Width,
              date_cell_size.Height);
            DrawTodayCircle (dc, today_circle_rect);
            today_offset += date_cell_size.Width + 5;
          }
          // draw today's date
          StringFormat text_format = new StringFormat();
          text_format.LineAlignment = StringAlignment.Center;
          text_format.Alignment = StringAlignment.Near;
          Font bold_font = new Font (mc.Font.FontFamily, mc.Font.Size, mc.Font.Style | FontStyle.Bold);
          Rectangle today_rect = new Rectangle (
            today_offset + client_rectangle.X,
            Math.Max(client_rectangle.Bottom - date_cell_size.Height, 0),
            Math.Max(client_rectangle.Width - today_offset, 0),
            date_cell_size.Height);
          dc.DrawString ("Today: " + DateTime.Now.ToShortDateString(), bold_font, ResPool.GetSolidBrush (mc.ForeColor), today_rect, text_format);
          text_format.Dispose ();
          bold_font.Dispose ();
        }        
      }
      
      // finally paint the borders of the calendars as required
      for (int i = 0; i <= mc.CalendarDimensions.Width; i++) {
        if (i == 0 && clip_rectangle.X == client_rectangle.X) {
          dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.X, client_rectangle.Y, 1, client_rectangle.Height));
        } else if (i == mc.CalendarDimensions.Width && clip_rectangle.Right == client_rectangle.Right) {
          dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.Right-1, client_rectangle.Y, 1, client_rectangle.Height));
        } else { 
          Rectangle rect = new Rectangle (
            client_rectangle.X + (month_size.Width*i) + (calendar_spacing.Width * (i-1)) + 1,
            client_rectangle.Y,
            calendar_spacing.Width,
            client_rectangle.Height);
          if (i < mc.CalendarDimensions.Width && i > 0 && clip_rectangle.IntersectsWith (rect)) {
            dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), rect);
          }
        }
      }
      for (int i = 0; i <= mc.CalendarDimensions.Height; i++) {
        if (i == 0 && clip_rectangle.Y == client_rectangle.Y) {
          dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.X, client_rectangle.Y, client_rectangle.Width, 1));
        } else if (i == mc.CalendarDimensions.Height && clip_rectangle.Bottom == client_rectangle.Bottom) {
          dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), new Rectangle (client_rectangle.X, client_rectangle.Bottom-1, client_rectangle.Width, 1));
        } else { 
          Rectangle rect = new Rectangle (
            client_rectangle.X,
            client_rectangle.Y + (month_size.Height*i) + (calendar_spacing.Height*(i-1)) + 1,
            client_rectangle.Width,
            calendar_spacing.Height);
          if (i < mc.CalendarDimensions.Height && i > 0 && clip_rectangle.IntersectsWith (rect)) {
            dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), rect);
          }
        }
      }
      
      // draw the drop down border if need
      if (mc.owner != null) {
        Rectangle bounds = mc.ClientRectangle;
        if (clip_rectangle.Contains (mc.Location)) {
          // find out if top or left line to draw
          if(clip_rectangle.Contains (new Point (bounds.Left, bounds.Bottom))) {
            
            dc.DrawLine (SystemPens.ControlText, bounds.X, bounds.Y, bounds.X, bounds.Bottom-1);
          }
          if(clip_rectangle.Contains (new Point (bounds.Right, bounds.Y))) {
            dc.DrawLine (SystemPens.ControlText, bounds.X, bounds.Y, bounds.Right-1, bounds.Y);
          }
        }
        if (clip_rectangle.Contains (new Point(bounds.Right, bounds.Bottom))) {
          // find out if bottom or right line to draw
          if(clip_rectangle.Contains (new Point (bounds.Left, bounds.Bottom))) {
            dc.DrawLine (SystemPens.ControlText, bounds.X, bounds.Bottom-1, bounds.Right-1, bounds.Bottom-1);
          }
          if(clip_rectangle.Contains (new Point (bounds.Right, bounds.Y))) {
            dc.DrawLine (SystemPens.ControlText, bounds.Right-1, bounds.Y, bounds.Right-1, bounds.Bottom-1);
          }
        }
      }
    }
    
    // darws a single part of the month calendar (with one month)
    private void DrawSingleMonth(Graphics dc, Rectangle clip_rectangle, Rectangle rectangle, MonthCalendar mc, int row, int col) 
    {
      // cache local copies of Marshal-by-ref internal members (gets around error CS0197)
      Size title_size = (Size)((object)mc.title_size);
      Size date_cell_size = (Size)((object)mc.date_cell_size);
      DateTime current_month = (DateTime)((object)mc.current_month);
      
      // set up some standard string formating variables
      StringFormat text_format = new StringFormat();
      text_format.LineAlignment = StringAlignment.Center;
      text_format.Alignment = StringAlignment.Center;
      
      
      // draw the title back ground
      DateTime this_month = current_month.AddMonths (row*mc.CalendarDimensions.Width+col);
      Rectangle title_rect = new Rectangle(rectangle.X, rectangle.Y, title_size.Width, title_size.Height);
      if (title_rect.IntersectsWith (clip_rectangle)) {
        dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), title_rect);
        // draw the title        
        string title_text = this_month.ToString ("MMMM yyyy");
        dc.DrawString (title_text, mc.Font, ResPool.GetSolidBrush (mc.TitleForeColor), title_rect, text_format);
        
        // draw previous and next buttons if it's time
        if (row == 0 && col == 0) 
        {
          // draw previous button
          DrawMonthCalendarButton (
            dc,
            rectangle,
            mc,
            title_size,
            mc.button_x_offset,
            (System.Drawing.Size)((object)mc.button_size),
            true);
        }
        if (row == 0 && col == mc.CalendarDimensions.Width-1) 
        {
          // draw next button
          DrawMonthCalendarButton (
            dc,
            rectangle,
            mc,
            title_size,
            mc.button_x_offset,
            (System.Drawing.Size)((object)mc.button_size),
            false);
        }
      }
      
      // set the week offset and draw week nums if needed
      int col_offset = (mc.ShowWeekNumbers) ? 1 : 0;
      Rectangle day_name_rect = new Rectangle(
        rectangle.X,
        rectangle.Y + title_size.Height,
        (7 + col_offset) * date_cell_size.Width,
        date_cell_size.Height);
      if (day_name_rect.IntersectsWith (clip_rectangle)) {
        dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), day_name_rect);
        // draw the day names 
        DayOfWeek first_day_of_week = mc.GetDayOfWeek(mc.FirstDayOfWeek);
        for (int i=0; i < 7; i++) 
        {
          int position = i - (int) first_day_of_week;
          if (position < 0) 
          {
            position = 7 + position;
          }
          // draw it
          Rectangle day_rect = new Rectangle(
            day_name_rect.X + ((i + col_offset)* date_cell_size.Width),
            day_name_rect.Y,
            date_cell_size.Width,
            date_cell_size.Height);
          dc.DrawString (((DayOfWeek)i).ToString().Substring(0, 3), mc.Font, ResPool.GetSolidBrush (mc.TitleBackColor), day_rect, text_format);
        }
        
        // draw the vertical divider
        int vert_divider_y = Math.Max(title_size.Height+ date_cell_size.Height-1, 0);
        dc.DrawLine (
          ResPool.GetPen (mc.ForeColor),
          rectangle.X + (col_offset * date_cell_size.Width) + mc.divider_line_offset,
          rectangle.Y + vert_divider_y,
          rectangle.Right - mc.divider_line_offset,
          rectangle.Y + vert_divider_y);
      }
      
      
      // draw the actual date items in the grid (including the week numbers)
      Rectangle date_rect = new Rectangle (
        rectangle.X,
        rectangle.Y + title_size.Height + date_cell_size.Height,
        date_cell_size.Width,
        date_cell_size.Height);
      int month_row_count = 0;
      bool draw_week_num_divider = false;
      DateTime current_date = mc.GetFirstDateInMonthGrid ( new DateTime (this_month.Year, this_month.Month, 1));
      for (int i=0; i < 6; i++) 
      {
        // establish if this row is in our clip_area
        Rectangle row_rect = new Rectangle (
          rectangle.X,
          rectangle.Y + title_size.Height + (date_cell_size.Height * (i+1)),
          date_cell_size.Width * 7,
          date_cell_size.Height);
        if (mc.ShowWeekNumbers) {
          row_rect.Width += date_cell_size.Width;
        }
        
        bool draw_row = row_rect.IntersectsWith (clip_rectangle);
        if (draw_row) {
          dc.FillRectangle (ResPool.GetSolidBrush (mc.BackColor), row_rect);
        }
        // establish if this is a valid week to draw
        if (mc.IsValidWeekToDraw (this_month, current_date, row, col)) {
          month_row_count = i;
        }
        
        // draw the week number if required
        if (mc.ShowWeekNumbers && month_row_count == i) {
          if (!draw_week_num_divider) {
            draw_week_num_divider = draw_row;
          }
          // get the week for this row
          int week = mc.GetWeekOfYear (current_date);  
          
          if (draw_row) {
            dc.DrawString (
              week.ToString(),
              mc.Font,
              ResPool.GetSolidBrush (mc.TitleBackColor),
              date_rect,
              text_format);
          }
          date_rect.Offset(date_cell_size.Width, 0);
        }
        
        // only draw the days if we have to
        if(month_row_count == i) {
          for (int j=0; j < 7; j++) 
          {
            if (draw_row) {
              DrawMonthCalendarDate (
                dc,
                date_rect,
                mc,
                current_date,
                this_month,
                row,
                col);
            }
            
            // move the day on
            current_date = current_date.AddDays(1);
            date_rect.Offset(date_cell_size.Width, 0);
          }
          
          // shift the rectangle down one row
          int offset = (mc.ShowWeekNumbers) ? -8 : -7;
          date_rect.Offset(offset*date_cell_size.Width, date_cell_size.Height);
        }
      }
      
      // month_row_count is zero based, so add one
      month_row_count++;
      
      // draw week numbers if required
      if (draw_week_num_divider) {
        col_offset = 1;
        dc.DrawLine (
          ResPool.GetPen (mc.ForeColor),
          rectangle.X + date_cell_size.Width - 1,
          rectangle.Y + title_size.Height + date_cell_size.Height + mc.divider_line_offset,
          rectangle.X + date_cell_size.Width - 1,
          rectangle.Y + title_size.Height + date_cell_size.Height + (month_row_count * date_cell_size.Height) - mc.divider_line_offset);
      }
      text_format.Dispose ();
    }
    
    // draws the pervious or next button
    private void DrawMonthCalendarButton (Graphics dc, Rectangle rectangle, MonthCalendar mc, Size title_size, int x_offset, Size button_size, bool is_previous) 
    {
      bool is_clicked = false;
      Rectangle button_rect;
      Rectangle arrow_rect = new Rectangle (rectangle.X, rectangle.Y, 4, 7);
      Point[] arrow_path = new Point[3];
      // prepare the button
      if (is_previous) 
      {
        is_clicked = mc.is_previous_clicked;
        button_rect = new Rectangle (
          rectangle.X + 1 + x_offset,
          rectangle.Y + 1 + ((title_size.Height - button_size.Height)/2),
          Math.Max(button_size.Width - 1, 0),
          Math.Max(button_size.Height - 1, 0));
        arrow_rect.X = button_rect.X + ((button_rect.Width - arrow_rect.Width)/2);
        arrow_rect.Y = button_rect.Y + ((button_rect.Height - arrow_rect.Height)/2);
        if (is_clicked) {
          arrow_rect.Offset(1,1);
        }
        arrow_path[0] = new Point (arrow_rect.Right, arrow_rect.Y);
        arrow_path[1] = new Point (arrow_rect.X, arrow_rect.Y + arrow_rect.Height/2);
        arrow_path[2] = new Point (arrow_rect.Right, arrow_rect.Bottom);
      }
      else
      {
        is_clicked = mc.is_next_clicked;
        button_rect = new Rectangle (
          rectangle.Right - 1 - x_offset - button_size.Width,
          rectangle.Y + 1 + ((title_size.Height - button_size.Height)/2),
          Math.Max(button_size.Width - 1, 0),
          Math.Max(button_size.Height - 1, 0));
        arrow_rect.X = button_rect.X + ((button_rect.Width - arrow_rect.Width)/2);
        arrow_rect.Y = button_rect.Y + ((button_rect.Height - arrow_rect.Height)/2);
        if (is_clicked) {
          arrow_rect.Offset(1,1);
        }
        arrow_path[0] = new Point (arrow_rect.X, arrow_rect.Y);
        arrow_path[1] = new Point (arrow_rect.Right, arrow_rect.Y + arrow_rect.Height/2);
        arrow_path[2] = new Point (arrow_rect.X, arrow_rect.Bottom);        
      }
      
      // fill the background
      dc.FillRectangle (ResPool.GetSolidBrush(mc.TitleBackColor), button_rect);
      
      // draw the button
      Color first_gradient_color = is_clicked ? pressed_gradient_first_color : gradient_first_color;
      Color second_gradient_color = is_clicked ? pressed_gradient_second_color : gradient_second_color;
      
      CL_Draw_Button (dc, button_rect, FlatStyle.Standard,
             false, true, is_clicked, 
             first_gradient_color, second_gradient_color,
             false);
        
      // draw the arrow
      SmoothingMode old_smooting_mode = dc.SmoothingMode;
      dc.SmoothingMode = SmoothingMode.AntiAlias;
      dc.FillPolygon (SystemBrushes.ControlText, arrow_path);
      dc.SmoothingMode = old_smooting_mode;
    }
    
    
    // draws one day in the calendar grid
    private void DrawMonthCalendarDate (Graphics dc, Rectangle rectangle, MonthCalendar mc,  DateTime date, DateTime month, int row, int col) {
      Color date_color = mc.ForeColor;
      Rectangle interior = new Rectangle (rectangle.X, rectangle.Y, Math.Max(rectangle.Width - 1, 0), Math.Max(rectangle.Height - 1, 0));
      
      // find out if we are the lead of the first calendar or the trail of the last calendar            
      if (date.Year != month.Year || date.Month != month.Month) {
        DateTime check_date = month.AddMonths (-1);
        // check if it's the month before 
        if (check_date.Year == date.Year && check_date.Month == date.Month && row == 0 && col == 0) {
          date_color = mc.TrailingForeColor;
        } else {
          // check if it's the month after
          check_date = month.AddMonths (1);
          if (check_date.Year == date.Year && check_date.Month == date.Month && row == mc.CalendarDimensions.Height-1 && col == mc.CalendarDimensions.Width-1) {
            date_color = mc.TrailingForeColor;
          } else {
            return;
          }
        }
      } else {
        date_color = mc.ForeColor;
      }
      
      
      if (date == mc.SelectionStart && date == mc.SelectionEnd) {
        // see if the date is in the start of selection
        date_color = mc.BackColor;
        // draw the left hand of the back ground
        Rectangle selection_rect = Rectangle.Inflate(rectangle, -3, -3);        
        dc.FillPie (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect, 0, 359);
      } else if (date == mc.SelectionStart) {
        // see if the date is in the start of selection
        date_color = mc.BackColor;
        // draw the left hand of the back ground
        Rectangle selection_rect = Rectangle.Inflate(rectangle, -3, -3);        
        dc.FillPie (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect, 90, 180);
        // fill the other side as a straight rect
        if (date < mc.SelectionEnd) 
        {
          // use rectangle instead of rectangle to go all the way to edge of rect
          selection_rect.X = (int) Math.Floor((double)(rectangle.X + rectangle.Width / 2));
          selection_rect.Width = Math.Max(rectangle.Right - selection_rect.X, 0);
          dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect);
        }
      } else if (date == mc.SelectionEnd) {
        // see if it is the end of selection
        date_color = mc.BackColor;
        // draw the left hand of the back ground
        Rectangle selection_rect = Rectangle.Inflate(rectangle, -3, -3);
        dc.FillPie (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect, 270, 180);
        // fill the other side as a straight rect
        if (date > mc.SelectionStart) {
          selection_rect.X = rectangle.X;
          selection_rect.Width = rectangle.Width - (rectangle.Width / 2);
          dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect);
        }
      } else if (date > mc.SelectionStart && date < mc.SelectionEnd) {
        // now see if it's in the middle
        date_color = mc.BackColor;
        // draw the left hand of the back ground
        Rectangle selection_rect = Rectangle.Inflate(rectangle, 0, -3);
        dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), selection_rect);
      }
      
      // set up some standard string formating variables
      StringFormat text_format = new StringFormat();
      text_format.LineAlignment = StringAlignment.Center;
      text_format.Alignment = StringAlignment.Center;
      
      
      // establish if it's a bolded font
      Font font;
      if (mc.IsBoldedDate (date)) {
        font = new Font (mc.Font.FontFamily, mc.Font.Size, mc.Font.Style | FontStyle.Bold);
      } else {
        font = mc.Font;
      }
      
      // just draw the date now
      dc.DrawString (date.Day.ToString(), font, ResPool.GetSolidBrush (date_color), rectangle, text_format);
      
      // today circle if needed
      if (mc.ShowTodayCircle && date == DateTime.Now.Date) {
        DrawTodayCircle (dc, interior);
      }
      
      // draw the selection grid
      if (mc.is_date_clicked && mc.clicked_date == date) {        
        using (Pen pen = new Pen (Color.Black, 1) ) {
          pen.DashStyle = DashStyle.Dot;
          dc.DrawRectangle (pen, interior);
        }
      }
      text_format.Dispose ();
    }
    
    private void DrawTodayCircle (Graphics dc, Rectangle rectangle) {
      Color circle_color = Color.FromArgb (248, 0, 0);
      // draw the left hand of the circle 
      Rectangle lhs_circle_rect = new Rectangle (rectangle.X + 1, rectangle.Y + 4, Math.Max(rectangle.Width - 2, 0), Math.Max(rectangle.Height - 5, 0));
      Rectangle rhs_circle_rect = new Rectangle (rectangle.X + 1, rectangle.Y + 1, Math.Max(rectangle.Width - 2, 0), Math.Max(rectangle.Height - 2, 0));
      Point [] curve_points = new Point [3];
      curve_points [0] = new Point (lhs_circle_rect.X, rhs_circle_rect.Y + rhs_circle_rect.Height/12);
      curve_points [1] = new Point (lhs_circle_rect.X + lhs_circle_rect.Width/9, rhs_circle_rect.Y);
      curve_points [2] = new Point (lhs_circle_rect.X + lhs_circle_rect.Width/2 + 1, rhs_circle_rect.Y);
      
      SmoothingMode old_smoothing_mode = dc.SmoothingMode;
      dc.SmoothingMode = SmoothingMode.AntiAlias;
      
      using (Pen pen = new Pen (circle_color, 2)) {
        dc.DrawArc (pen, lhs_circle_rect, 90, 180);
        dc.DrawArc (pen, rhs_circle_rect, 270, 180);          
        dc.DrawCurve (pen, curve_points);
        dc.DrawLine (ResPool.GetPen (circle_color), curve_points [2], new Point (curve_points [2].X, lhs_circle_rect.Y));
      }
      
      dc.SmoothingMode = old_smoothing_mode;
    }
    #endregion   // MonthCalendar
    
    public override void CPDrawBorder3D( Graphics graphics, Rectangle rectangle, Border3DStyle style, Border3DSide sides ) {
      CPDrawBorder3D( graphics, rectangle, style, sides, ColorControl );
    }
    
    public override void CPDrawBorder3D( Graphics dc, Rectangle rectangle, Border3DStyle style, Border3DSide sides, Color control_color ) {
      // currently we don't take care of Border3DStyle or Border3DSide
      
      Pen tmp_pen = ResPool.GetPen( edge_bottom_inner_color );
      dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 2, rectangle.X + 2, rectangle.Y + 1 );
      dc.DrawLine( tmp_pen, rectangle.Right - 3, rectangle.Y + 1, rectangle.Right - 2, rectangle.Y + 2 );
      dc.DrawLine( tmp_pen, rectangle.Right - 3, rectangle.Bottom - 2, rectangle.Right - 2, rectangle.Bottom - 3 );
      dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Bottom - 3, rectangle.X + 2, rectangle.Bottom - 2 );
      
      tmp_pen = ResPool.GetPen( theme_back_color );
      dc.DrawLine( tmp_pen, rectangle.X + 2, rectangle.Y + 2, rectangle.Right - 3, rectangle.Y + 2 );
      dc.DrawLine( tmp_pen, rectangle.X + 2, rectangle.Y + 3, rectangle.X + 2, rectangle.Bottom - 3 );
      
      tmp_pen = ResPool.GetPen( Color.White );
      dc.DrawLine( tmp_pen, rectangle.X + 3, rectangle.Bottom - 3, rectangle.Right - 3, rectangle.Bottom - 3 );
      dc.DrawLine( tmp_pen, rectangle.Right - 3, rectangle.Y + 3, rectangle.Right - 3, rectangle.Bottom - 3 );
      
      Point[] points = {
        new Point( rectangle.X + 3, rectangle.Y + 1 ),
        new Point( rectangle.Right - 4, rectangle.Y + 1 ),
        new Point( rectangle.Right - 2, rectangle.Y + 3 ),
        new Point( rectangle.Right - 2, rectangle.Bottom - 4 ),
        new Point( rectangle.Right - 4, rectangle.Bottom - 2 ),
        new Point( rectangle.X + 3, rectangle.Bottom - 2 ),
        new Point( rectangle.X + 1, rectangle.Bottom - 4 ),
        new Point( rectangle.X + 1, rectangle.Y + 3 ),
        new Point( rectangle.X + 3, rectangle.Y + 1 )
      };
      
      dc.DrawLines( ResPool.GetPen( combobox_border_color ), points );
      
      Point[] points_top_outer = {
        new Point( rectangle.X + 1, rectangle.Y + 1 ),
        new Point( rectangle.X + 2, rectangle.Y ),
        new Point( rectangle.Right - 3, rectangle.Y ),
        new Point( rectangle.Right - 2 , rectangle.Y + 1 )
      };
      
      Point[] points_bottom_outer = {
        new Point( rectangle.X + 1, rectangle.Bottom - 2 ),
        new Point( rectangle.X + 2, rectangle.Bottom - 1 ),
        new Point( rectangle.Right - 3, rectangle.Bottom - 1 ),
        new Point( rectangle.Right - 2, rectangle.Bottom - 2 )
      };
      
      // outer border
      tmp_pen = ResPool.GetPen( button_outer_border_dark_color );
      dc.DrawLines( tmp_pen, points_top_outer );
      tmp_pen = ResPool.GetPen( button_outer_border_light_color );
      dc.DrawLines( tmp_pen, points_bottom_outer );
      
      using ( LinearGradientBrush lgbr = new LinearGradientBrush( new Point( rectangle.X, rectangle.Y + 2 ), new Point( rectangle.X, rectangle.Bottom - 3 ), button_outer_border_dark_color, button_outer_border_light_color ) ) {
        using (Pen lgbrpen = new Pen (lgbr)) {
          dc.DrawLine (lgbrpen, rectangle.X, rectangle.Y + 2, rectangle.X, rectangle.Bottom - 3 );
          dc.DrawLine (lgbrpen, rectangle.Right - 1, rectangle.Y + 2, rectangle.Right - 1, rectangle.Bottom - 3 );
        }
      }
      
      tmp_pen = ResPool.GetPen( button_edge_top_outer_color );
      dc.DrawLine( tmp_pen, rectangle.X, rectangle.Y + 1, rectangle.X + 1, rectangle.Y );
      dc.DrawLine( tmp_pen, rectangle.Right - 2, rectangle.Y, rectangle.Right - 1, rectangle.Y + 1 );
      
      tmp_pen = ResPool.GetPen( button_edge_bottom_outer_color );
      dc.DrawLine( tmp_pen, rectangle.X, rectangle.Bottom - 2, rectangle.X + 1, rectangle.Bottom - 1 );
      dc.DrawLine( tmp_pen, rectangle.Right - 1, rectangle.Bottom - 2, rectangle.Right - 2, rectangle.Bottom - 1 );
    }
    
    public override void CPDrawBorder( Graphics dc, Rectangle bounds, Color leftColor, int leftWidth,
              ButtonBorderStyle leftStyle, Color topColor, int topWidth, ButtonBorderStyle topStyle,
              Color rightColor, int rightWidth, ButtonBorderStyle rightStyle, Color bottomColor,
              int bottomWidth, ButtonBorderStyle bottomStyle ) {
      dc.DrawRectangle( ResPool.GetPen( combobox_border_color ), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1 );
    }
    
    // TODO: inactive...
    public override void CPDrawCheckBox( Graphics dc, Rectangle rectangle, ButtonState state ) {
      
      bool pushed = ( state & ButtonState.Pushed ) != 0;
      
      int lineWidth;
      Rectangle rect;
      int scale;
      
      // background
      dc.FillRectangle( ResPool.GetSolidBrush( pushed ? checkbox_pressed_backcolor : Color.White ), rectangle );
      
      // border
      dc.DrawRectangle( ResPool.GetPen( scrollbar_border_color ), rectangle );
      
      Color inner_border_color = pushed ? checkbox_pressed_inner_boder_color : checkbox_inner_boder_color;
      
      Pen tmp_pen = ResPool.GetPen( inner_border_color );
      dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 1, rectangle.Right - 1, rectangle.Y + 1 );
      dc.DrawLine( tmp_pen, rectangle.X + 1, rectangle.Y + 2, rectangle.X + 1, rectangle.Bottom - 1 );
      
      /* Make sure we've got at least a line width of 1 */
      lineWidth = Math.Max( 3, rectangle.Width / 6 );
      scale = Math.Max( 1, rectangle.Width / 12 );
      
      // define a rectangle inside the border area
      rect = new Rectangle( rectangle.X + 2, rectangle.Y + 2, rectangle.Width - 4, rectangle.Height - 4 );
      if ( ( state & ButtonState.Inactive ) != 0 ) {
        tmp_pen = SystemPens.ControlDark;
      } else {
        tmp_pen = SystemPens.ControlText;
      }
      
      if ( ( state & ButtonState.Checked ) != 0 ) { 
        /* Need to draw a check-mark */
        for ( int i=0; i < lineWidth; i++ ) {
          dc.DrawLine( tmp_pen, rect.Left + lineWidth / 2, rect.Top + lineWidth + i, rect.Left + lineWidth / 2 + 2 * scale, rect.Top + lineWidth + 2 * scale + i );
          dc.DrawLine( tmp_pen, rect.Left + lineWidth / 2 + 2 * scale, rect.Top + lineWidth + 2 * scale + i, rect.Left + lineWidth / 2 + 6 * scale, rect.Top + lineWidth - 2 * scale + i );
        }
      }
    }
    
    public  override void CPDrawStringDisabled( Graphics graphics, string s, Font font, Color color, RectangleF layoutRectangle,
                 StringFormat format ) {      
      
      graphics.DrawString( s, font, ResPool.GetSolidBrush( ColorGrayText), layoutRectangle, format );      
      
    }
    
    public override void CPDrawButton (Graphics dc, Rectangle buttonRectangle, ButtonState state)
    {
      bool is_enabled = true;
      FlatStyle flat_style = FlatStyle.Standard;
      bool is_pressed = false;
      
      if ((state & ButtonState.Pushed) != 0) {
        is_pressed = true;
      }
      
//      if ((state & ButtonState.Checked)!=0) {
//        dfcs |= DrawFrameControlStates.Checked;
//      }
      
      if ((state & ButtonState.Flat) != 0) {
        flat_style = FlatStyle.Flat;
      }
      
      if ((state & ButtonState.Inactive) != 0) {
        is_enabled = false;
      }
      
      Color first_gradient_color = gradient_first_color;
      Color second_gradient_color = gradient_second_color;
      
      if (is_pressed) {
        first_gradient_color = pressed_gradient_first_color;
        second_gradient_color = pressed_gradient_second_color;
      }
      
      CL_Draw_Button (dc, buttonRectangle, flat_style,
          false, is_enabled, is_pressed,
          first_gradient_color, second_gradient_color,
          false);
    }
    
    public override void CPDrawRadioButton (Graphics dc, Rectangle rectangle, ButtonState state)
    {
      bool is_checked = false;
      bool is_inactive = false;
      
      if ((state & ButtonState.Checked) != 0) {
        is_checked = true;
      }
      
      if ((state & ButtonState.Inactive) != 0) {
        is_inactive = true;
      }
      
      SmoothingMode old_smooting_mode = dc.SmoothingMode;
      dc.SmoothingMode = SmoothingMode.AntiAlias;
      
      dc.FillPie (ResPool.GetSolidBrush (this.ColorWindow), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
      
      dc.DrawArc (ResPool.GetPen (radio_button_border_circle_color), rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2, 0, 359);
      
      CL_Draw_RadioButton_Dot (dc, rectangle, is_checked, is_inactive);
      
      dc.SmoothingMode = old_smooting_mode;
    }

    private void CL_Draw_RadioButton_Dot (Graphics dc,  Rectangle rectangle, bool is_checked, bool is_inactive)
    {
      if (is_checked) {
        int lineWidth = Math.Max (1, Math.Min (rectangle.Width, rectangle.Height) / 4);
        
        SolidBrush buttonBrush;
        
        if (is_inactive) {
          buttonBrush = SystemBrushes.ControlDark as SolidBrush;
        } else {
          buttonBrush = ResPool.GetSolidBrush (radio_button_dot_color);
        }
        dc.FillPie (buttonBrush, rectangle.X + lineWidth, rectangle.Y + lineWidth, rectangle.Width - lineWidth * 2, rectangle.Height - lineWidth * 2, 0, 359);
        
        // the white shiny dott
        buttonBrush = ResPool.GetSolidBrush (ColorWindow);
        dc.FillPie (buttonBrush, rectangle.X + lineWidth + lineWidth / 2, rectangle.Y + lineWidth + lineWidth / 2, (rectangle.Width - lineWidth * 2) / 3, (rectangle.Height - lineWidth * 2) / 3, 0, 359);
      }
    }

    #region ToolTip
    public override void DrawToolTip (Graphics dc, Rectangle clip_rectangle, ToolTip.ToolTipWindow control)
    {
      dc.FillRectangle(ResPool.GetSolidBrush (ColorInfo), control.ClientRectangle);
      dc.DrawRectangle(ResPool.GetPen (info_border_color), 0, 0, control.Width-1, control.Height-1);
  
      TextFormatFlags flags = TextFormatFlags.HidePrefix | TextFormatFlags.SingleLine | TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter;
      TextRenderer.DrawTextInternal (dc, control.Text, control.Font, control.ClientRectangle, this.ColorInfoText, flags, false);
    }
    #endregion  // ToolTip

    #region BalloonWindow
#if NET_2_0
    NotifyIcon.BalloonWindow balloon_window;
    
    public override void ShowBalloonWindow (IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
    {
      Control control = Control.FromHandle(handle);
      
      if (control == null)
        return;

      if (balloon_window != null) {
        balloon_window.Close ();
        balloon_window.Dispose ();
      }

      balloon_window = new NotifyIcon.BalloonWindow (handle);
      balloon_window.Title = title;
      balloon_window.Text = text;
      balloon_window.Icon = icon;
      balloon_window.Timeout = timeout;
      balloon_window.Show ();
    }

    private const int balloon_iconsize = 48;
    private const int balloon_bordersize = 8; 
    
    public override void DrawBalloonWindow (Graphics dc, Rectangle clip, NotifyIcon.BalloonWindow control) 
    {
      Brush solidbrush = ResPool.GetSolidBrush(this.ColorInfoText);
      Rectangle rect = control.ClientRectangle;
      int iconsize = (control.Icon == ToolTipIcon.None) ? 0 : balloon_iconsize;
      
      // Rectangle borders and background.
      dc.FillRectangle (ResPool.GetSolidBrush (ColorInfo), rect);
      dc.FillRectangle (ResPool.GetSolidBrush (info_second_color), new Rectangle (rect.X, rect.Y, (balloon_iconsize/2)+balloon_bordersize, rect.Height));
      dc.DrawRectangle (ResPool.GetPen (info_border_color), 0, 0, rect.Width - 1, rect.Height - 1);

      // Icon
      Image image;
      switch (control.Icon) {
        case ToolTipIcon.Info: {
          image = ThemeEngine.Current.Images(UIIcon.MessageBoxInfo, balloon_iconsize);
          break;
        }

        case ToolTipIcon.Warning: {
          image = ThemeEngine.Current.Images(UIIcon.MessageBoxError, balloon_iconsize);
          break;
        }

        case ToolTipIcon.Error: {
          image = ThemeEngine.Current.Images(UIIcon.MessageBoxWarning, balloon_iconsize);
          break;
        }
        
        default: {
          image = null;
          break;
        }
      }

      if (control.Icon != ToolTipIcon.None)
        dc.DrawImage (image, new Rectangle (balloon_bordersize, (2*balloon_bordersize)+7, iconsize, iconsize));
      
      // Title
      Rectangle titlerect = new Rectangle (rect.X + balloon_bordersize + (balloon_iconsize/2) + balloon_bordersize, 
                        rect.Y + balloon_bordersize, 
                        rect.Width - ((3 * balloon_bordersize) + (balloon_iconsize/2)), 
                        rect.Height - (2 * balloon_bordersize));
      
      Font titlefont = new Font (control.Font.FontFamily, control.Font.Size, control.Font.Style | FontStyle.Bold, control.Font.Unit);
      dc.DrawString (control.Title, titlefont, solidbrush, titlerect, control.Format);
      
      // Text
      Rectangle textrect = new Rectangle (rect.X + (2 * balloon_bordersize) + balloon_iconsize, 
                        rect.Y + balloon_bordersize, 
                        rect.Width - ((2 * balloon_bordersize) + balloon_iconsize), 
                        rect.Height - (2 * balloon_bordersize));

      StringFormat textformat = control.Format;
      textformat.LineAlignment = StringAlignment.Far;
      dc.DrawString (control.Text, control.Font, solidbrush, textrect, textformat);
    }

    public override Rectangle BalloonWindowRect (NotifyIcon.BalloonWindow control)
    {
      Rectangle deskrect = Screen.GetWorkingArea (control);
      SizeF maxsize = new SizeF (250, 200);

      SizeF titlesize = TextRenderer.MeasureString (control.Title, control.Font, maxsize, control.Format);
      SizeF textsize = TextRenderer.MeasureString (control.Text, control.Font, maxsize, control.Format);
      
      if (textsize.Height < balloon_iconsize)
        textsize.Height = balloon_iconsize;
      
      Rectangle rect = new Rectangle ();
      rect.Height = (int) (titlesize.Height + textsize.Height + (3 * balloon_bordersize));
      rect.Width = (int) ((titlesize.Width > textsize.Width) ? titlesize.Width : textsize.Width) + (3 * balloon_bordersize) + balloon_iconsize;
      rect.X = deskrect.Width - rect.Width - 2;
      rect.Y = deskrect.Height - rect.Height - 2;
      
      return rect;
    }
#endif
    #endregion  // BalloonWindow
    
  } //class
}


www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.