渐变颜色选择器
目录
介绍
我不确定需要多少次才能生成一种颜色数组,该颜色数组是两种或多种颜色的线性渐变。当为我的网站的COVID-19部分构建动画图形时,我需要生成许多比例。例如:
随着任务的繁重,我决定开发一种辅助工具。结果是渐变颜色选择器。
用户界面
轴向颜色渐变(有时也称为线性颜色渐变)由两个点指定,每个点都有一种颜色。使用线性插值计算通过这些点的直线上的颜色。
我想要一个可以为我提供从线性颜色渐变派生的颜色列表的工具。颜色列表将放置在剪贴板中。该工具需要提供以下功能。
- 接受两种颜色,然后用线性颜色渐变填充面板(gradient_PAN);接受要从线性颜色渐变中提取的颜色数量。最小颜色数是3(无需使用少于三种颜色的工具);颜色的最大数量为20(受工具客户区大小的限制)。
- 当用户单击Generate时,该工具将绘制彩色按钮,这些按钮的颜色与关联的线性渐变的颜色相同(即,线性渐变在按钮正上方的颜色)。
-
现在向用户显示将颜色值捕获到剪贴板的选项。这些包括:
- 用户可以选择将用于剪贴板条目的颜色格式。默认格式为RGB十六进制。
-
通过单击任何单独的颜色按钮,该按钮的颜色将复制到剪贴板。两个末端按钮具有原始指定颜色的颜色。如果在示例中单击第六个彩色按钮,则复制到剪贴板的值是:
'#FF6666' -
通过单击从左复制到右,剪贴板从左到右填充了所有彩色按钮颜色的逗号分隔列表。例如,复制到剪贴板的值是:
'#FFBBBB','#FFA7A7','#FF9797','#FF8787','#FF7777',
'#FF6666','#FF5656','#FF4545 ','#FF3535','#FF2525','#FF1414','#FF0000' -
通过单击从右到左复制,剪贴板从右到左填充了所有彩色按钮的颜色的逗号分隔列表。例如,复制到剪贴板的值是:
'#FF0000','#FF1414','#FF2525','#FF3535','#FF4545','#FF5656',
'#FF6666','#FF7777 ','#FF8787','#FF9797','#FFA7A7','#FFBBBB'
- 如果用户单击“重置”,则用户返回到步骤1;否则,如果用户单击Exit,用户返回步骤1。则应用程序退出。
实现
与任何事件驱动的应用程序一样,初始化主要花费在建立图形用户界面上。对于渐变颜色选择器(Gradient Color Picker),实际上只有两个感兴趣的组件:gradient_PAN和button_PAN面板。
gradient_PAN
选择开始或结束颜色时,将调用fill_gradient_PAN方法。此方法可确保已访问“开始和结束颜色”按钮,并且已选择“开始和结束颜色”。如果是这样,则该方法执行以下操作:
gradient_PAN.Visible = true;
gradient_PAN.Invalidate ( );
gradient_PAN有PAN_OnPaint事件处理程序。
// *********************************************** PAN_OnPaint
void PAN_OnPaint ( object sender,
PaintEventArgs e )
{
base.OnPaint ( e );
e.Graphics.FillRectangle (
new LinearGradientBrush (
gradient_PAN.ClientRectangle,
start_color,
end_color,
0.0F ),
gradient_PAN.ClientRectangle );
} // PAN_OnPaint
PAN_OnPaint事件处理程序非常简单。它所做的只是创建一个LinearGradientBrush [ ^ ],并用它来填充gradient_PAN客户矩形。
button_PAN
单击“生成”按钮后,将呈现工具GUI的剩余部分。在大多数情况下,这需要使各种对象可见。但是,生成button_PAN面板要稍微复杂一些。
// ******************************************* fill_button_PAN
bool fill_button_PAN ( )
{
int right_most = 0;
int spacing = 0;
int top = 2;
Point UL = new Point ( 0, 0 ) ;
// remove existing event
// handlers from buttons in
// the button_PAN
foreach ( Control control in button_PAN.Controls )
{
if ( control is Button )
{
control.Click -= new EventHandler (
gradient_BUT_Click );
}
}
// remove any existing buttons
// from the button_PAN
button_PAN.Controls.Clear ( );
// clear the buttons list
buttons.Clear ( );
// compute initial spacing
// between buttons
spacing = ( gradient_PAN.Size.Width -
( BUTTON_WIDTH * number_of_colors ) ) /
( number_of_colors - 1 );
// create gradient buttons and
// add them to buttons list
for ( int i = 0; ( i < number_of_colors ); i++ )
{
Button button = new Button ( );
int left = ( i * ( spacing + BUTTON_WIDTH ) );
// want no borders
button.FlatStyle = FlatStyle.Popup;
button.Location = new Point ( left, top );
button.Size = BUTTON_SIZE;
button.Click += new EventHandler (
gradient_BUT_Click );
right_most = button.Location.X + button.Size.Width;
buttons.Add ( button );
}
// the spacing may not be
// large enough to cause the
// buttons to completely fill
// the button panel to the
// right; here we correct the
// inter-button spacing;
// EPSILON is currently 3
if ( right_most < ( gradient_PAN.Size.Width - EPSILON ) )
{
int pixels = 1;
int start = 0;
// start is expected to be
// greater than zero
start = buttons.Count -
( gradient_PAN.Size.Width - right_most );
for ( int i = start; ( i < buttons.Count ); i++ )
{
Point location = buttons [ i ].Location;
location.X += pixels++;
buttons [ i ].Location = location;
}
}
// set the button BackColor;
// copy the button from the
// buttons List to the
// button_PAN
for ( int i = 0; ( i < buttons.Count ); i++ )
{
Button button = buttons [ i ];
// color the button based upon
// its current location in the
// buttons panel
if ( i == 0 )
{
button.BackColor = start_color;
}
else if ( i == ( number_of_colors - 1 ) )
{
button.BackColor = end_color;
}
else
{
generate_back_color ( ref button );
}
button.UseVisualStyleBackColor = false;
// place button in button_PAN
button_PAN.Controls.Add ( button );
}
button_PAN.Visible = true;
reset_BUT.Visible = true;
initialize_miscellaneous_controls ( );
return ( true );
} // fill_button_PAN
fill_button_PAN执行以下任务:
- 由于应用程序可能会执行多次,因此有必要删除每个按钮上附加的所有事件处理程序。此外,所有按钮均已从button_PAN中删除,所有按钮均已从按钮列表中删除。
- 计算初始间隔。请注意,由于舍入误差,计算出的值可能不是按钮之间的最终间距。
- 这些按钮是沿着button_PAN面板创建并隔开的,从而跟踪最右边的按钮右侧的位置。
- 校正了按钮之间的间距,以使按钮沿button_PAN等距分布。需要执行此步骤,以确保按钮颜色准确地描绘了gradient_PAN中的颜色。
- 至此,按钮数据已存储在按钮列表中。现在将按钮放入button_PAN。因为最终位置是已知的,所以调用generate_back_color方法最终为每个按钮分配一个BackColor。
- 最后,使控件的平衡可见。
generate_back_color方法首先计算在gradient_PAN的垂直中心的点,在所述按钮水平居中button_PAN。该点在工具的客户矩形坐标中定义。
在调用Win32 get_pixel_color_at_location方法之前,必须将点转换为屏幕坐标。
// *************************************** generate_back_color
bool generate_back_color ( ref Button button )
{
Point point;
Point screen_point;
point = new Point (
( ( button_PAN.Location.X +
button.Location.X ) +
( button.Size.Width / 2 ) ),
( gradient_PAN.Location.Y +
( gradient_PAN.Size.Height / 2 ) ) );
screen_point = PointToScreen ( point );
button.BackColor =
Win32API.get_pixel_color_at_location ( screen_point );
return ( true );
} // generate_back_color
Win32的get_pixel_color_at_location方法对一个一像素的位图使用GetPixel。将位于指定位置的像素(BitBlt [ ^ ])复制到screen_pixel位图。这带来了四个好处:该方法在多监视器环境中使用时不会引发异常;它比GetPixel更快;使用的位图只有一个像素高和一个宽;并且位图在此方法中是本地的。get_pixel_color_at_location方法采用以下形式:
// **************************************************** BitBlt
[ DllImport ( "gdi32.dll",
EntryPoint = "BitBlt" ) ]
public static extern bool BitBlt ( IntPtr hdcDest,
int nXDest,
int nYDest,
int nWidth,
int nHeight,
IntPtr hdcSrc,
int nXSrc,
int nYSrc,
int dwRop );
:
:
// ******************************* get_pixel_color_at_location
public static Color get_pixel_color_at_location (
Point screen_location )
{
Color color;
Bitmap screen_pixel = new Bitmap (
1,
1,
PixelFormat.Format32bppArgb );
using ( Graphics destination = Graphics.FromImage (
screen_pixel ) )
{
using ( Graphics source = Graphics.FromHwnd (
IntPtr.Zero ) )
{
IntPtr source_DC = source.GetHdc ( );
IntPtr destination_DC = destination.GetHdc ( );
BitBlt ( destination_DC,
0,
0,
1,
1,
source_DC,
screen_location.X,
screen_location.Y,
( int ) CopyPixelOperation.SourceCopy );
}
}
color = screen_pixel.GetPixel ( 0, 0 );
screen_pixel.Dispose ( );
return ( color );
}
} // class Win32API
参考文献
结论
本文介绍了一种工具,该工具为开发人员提供了从线性颜色渐变中选择颜色的功能。
开发环境
渐变颜色选择器是在以下环境中开发的:
Microsoft Windows 7专业版SP 1 |
Microsoft Visual Studio专业版2008 Professional SP1 |
Microsoft Visual C#2008 |
Microsoft .Net Framework版本3.5 SP1 |
下一篇: php文件系统函数问题!