winform下拉框篇.类似Word的颜色下拉框

来源:互联网 发布:推塔网络游戏要网络吗 编辑:程序博客网 时间:2024/06/05 01:56

实现功能:

1)下拉出颜色选取对话框.

2)后台窗口不失去焦点.

3)点击更多调用windows标准颜色选取对话框选取颜色.



开发背景:

在网上看到一些文章可以基本实现这些功能、但是大多使用前台窗口获得焦点后在迅速把焦点

转移到后台窗口的方法、或是将前台窗口 Show 出通过使去焦点来关闭前台窗口,或者干脆用个控件(用普通的控件如果如果范围超出后台窗口的范围就会被窗口遮挡)

而Windows内置的菜单或下拉框都不会出现使、前台窗口触发失去焦点事件的事件、更不会被遮挡、抱着一个程序员执著的信念、在csdn论坛连发数贴(400 分啊)在加上不断的努力终于有所曾就。

在此感谢 csdn 的各位同僚朋友,没有你们就没有这个世界(哈)。

废话不多说了、进入正题。



程序实现代码解析:

1)文章所用到的基础Windows API 类。

using System;

using System.Runtime.InteropServices;

/// <summary>

/// 系统调用,都是Windows API 相关 注视的地方也许大家有用没有删除,具体说明情察看msdn

/// </summary>

public class SystemShell

{



public const int GWL_STYLE = -16;

//public const int GWL_EXSTYLE = -20;

//public const int WS_VISIBLE =0x10000000;

public const int WS_CHILDWINDOW = 0x40000000;

//public const int WS_CLIPSIBLINGS = 0x04000000;

//public const int WS_CLIPCHILDREN = 0x02000000;

//public const int WS_BORDER = 0x00800000;

//public const long WS_THICKFRAME = 0x00040000;

//public const long WS_OVERLAPPED = 0x00000000;

//public const long WS_DLGFRAME = 0x00400000;

//public const long WS_EX_TOOLWINDOW = 0x00000080;



//public const int WM_NCPAINT = 0x0085;

public const int WM_ACTIVATEAPP = 0x001C;

//public const int WM_ERASEBKGND = 0x0014;



[DllImport("user32.dll", CharSet=CharSet.Auto)]

public static extern long SetWindowLong(IntPtr hWnd, int nIndex, long dwNewLong);



[DllImport("user32.dll", CharSet=CharSet.Auto)]

public static extern long GetWindowLong( IntPtr hWnd,int nIndex);





//[DllImport("user32.dll", CharSet=CharSet.Auto)]

//public static extern int SendMessage(IntPtr hWnd , int msg , int wParam ,int lParam );



//[DllImport("user32.dll", CharSet=CharSet.Auto)]

//public static extern int GetWindowRect (IntPtr hWnd , ref System.Drawing.Rectangle lpRect);



private SystemShell()

{

//

// TODO: 在此处添加构造函数逻辑

//

}

}







本文章弹出窗口的基类(代码处理流程情根据标号浏览)







/// <summary>

/// NoActForm 实现弹出窗口的基类。

/// </summary>

public class NoActForm : System.Windows.Forms.Form

{



/// <summary>

/// 必需的设计器变量。

/// </summary>





private System.ComponentModel.Container components = null;

public NoActForm():base()

{

//

// Windows 窗体设计器支持所必需的

//

InitializeComponent();

}

/// <summary>

/// 清理所有正在使用的资源。

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}



#region Windows 窗体设计器生成的代码

/// <summary>

/// 设计器支持所需的方法 - 不要使用代码编辑器修改

/// 此方法的内容。

/// </summary>

private void InitializeComponent()

{

//

// NoActForm

//

this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

this.ClientSize = new System.Drawing.Size(292, 273);

//(1)不要标题图标 和 Text 属性,

this.ControlBox = false;

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;

this.Name = "NoActForm";

this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;

this.Load += new System.EventHandler(this.NoActForm_Load);



}

#endregion



private void NoActForm_Load(object sender, System.EventArgs e)

{

//如果不是在设计模式

if (!this.DesignMode)

{

//没有 Owner 是不行的

if (this.Owner == null)

{

throw new ApplicationException("not Owner Form");

}



this.ShowInTaskbar =false;

//(2)关键在这里任何窗口子要加上 WS_CHILDWINDOW 样式即可

long Style = SystemShell.GetWindowLong(this.Handle,SystemShell.GWL_STYLE);

Style |= SystemShell.WS_CHILDWINDOW;

SystemShell.SetWindowLong(this.Handle,SystemShell.GWL_STYLE,Style);

}

}

/// <summary>

/// 自己定义的show

/// </summary>

/// <param name="Ctl">要在那个控件附近show 出本窗口</param>

public virtual void Show(Control Ctl)

{

//取得控件在屏幕的位置

Rectangle rect = Ctl.RectangleToScreen(new Rectangle(0,0,Ctl.Width,Ctl.Height));





this.Left=rect.Left;

this.Top=rect.Top+Ctl.Height;



Rectangle ScreenRect = Screen.PrimaryScreen.WorkingArea;

if( this.Right > ScreenRect.Width || this.Bottom > ScreenRect.Height)

{

this.Left=rect.Left - this.Width + Ctl.Width;

this.Top=rect.Top - this.Height;

}

this.Show();

}



/// <summary>

/// 重写 WndProc

/// </summary>

/// <param name="m"></param>

protected override void WndProc(ref Message m)

{

//(3)如果整个程序失去就隐藏

if (m.Msg==SystemShell.WM_ACTIVATEAPP && m.WParam==IntPtr.Zero)

{

this.Hide();

}

base.WndProc (ref m);

}

}



具体实现(代码处理流程情根据标号浏览)





/// <summary>

/// ColorSelectForm 的摘要说明。

/// (1)继承 NoActForm

/// </summary>

public class ColorSelectForm : NoActForm

{

/// <summary>

///

/// </summary>

public delegate void MouseSelectColor(Color SelectColor);

/// <summary>

/// (2)颜色选取事件当本窗口 获得颜色时触发

/// </summary>

public event MouseSelectColor SelectColor;

private Control _ShowCtl;

private System.Windows.Forms.PictureBox pictureBox1;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.ColorDialog colorDialog1;

/// <summary>

/// 必需的设计器变量。

/// </summary>

private System.ComponentModel.Container components = null;



public ColorSelectForm():base()

{

//

// Windows 窗体设计器支持所必需的

//

InitializeComponent();

this.MouseDown+=new MouseEventHandler(ColorSelectForm_MouseDown);

this.MouseMove+=new MouseEventHandler(ColorSelectForm_MouseMove);

//

// TODO: 在 InitializeComponent 调用后添加任何构造函数代码

//

}



/// <summary>

/// 清理所有正在使用的资源。

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}



#region Windows 窗体设计器生成的代码

/// <summary>

/// 设计器支持所需的方法 - 不要使用代码编辑器修改

/// 此方法的内容。

/// </summary>

private void InitializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(ColorSelectForm));

this.pictureBox1 = new System.Windows.Forms.PictureBox();

this.label1 = new System.Windows.Forms.Label();

this.colorDialog1 = new System.Windows.Forms.ColorDialog();

this.SuspendLayout();

//

// pictureBox1

//

this.pictureBox1.Cursor = System.Windows.Forms.Cursors.Cross;

this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Top;

//(3)将 pictureBox1.Image 放一个色盘 图

this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));

this.pictureBox1.Location = new System.Drawing.Point(0, 0);

this.pictureBox1.Name = "pictureBox1";

this.pictureBox1.Size = new System.Drawing.Size(194, 289);

this.pictureBox1.TabIndex = 0;

this.pictureBox1.TabStop = false;

//

// label1

//

this.label1.BackColor = System.Drawing.SystemColors.Control;

this.label1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;

this.label1.Dock = System.Windows.Forms.DockStyle.Fill;

this.label1.Location = new System.Drawing.Point(0, 289);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(194, 25);

this.label1.TabIndex = 1;

this.label1.Text = " 更多....";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// ColorSelectForm

//

this.AutoScale = false;

this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

this.ClientSize = new System.Drawing.Size(194, 314);

this.ControlBox = false;

this.Controls.Add(this.label1);

this.Controls.Add(this.pictureBox1);

this.Cursor = System.Windows.Forms.Cursors.Cross;

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;

this.Name = "ColorSelectForm";

this.Text = "";

this.ResumeLayout(false);



}

#endregion

/// <summary>

/// (4) 封装 Show

/// </summary>

/// <param name="Ctl"></param>

public override void Show(Control Ctl)

{

_ShowCtl =Ctl;



Owner.Cursor = Cursors.Cross;

base.Show(Ctl);

//show 后立刻捕捉鼠标

this.Capture=true;

}

/// <summary>

/// (6)如果鼠标按下进行一系列处理

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void ColorSelectForm_MouseDown(object sender, MouseEventArgs e)

{

//释放鼠标

this.Capture=false;

Point pt = Control.MousePosition;

Color cl =Color.Empty;

while(true)

{

//是否在窗口范围内

if(!(pt.X> this.Right || pt.X < this.Left|| pt.Y>this.Bottom || pt.Y< this.Top))

{

//取label1 在屏幕上的位置

Rectangle rect =label1.RectangleToScreen(new Rectangle(0,0,label1.Width,label1.Height));



//如果鼠标点击在 label1 上弹出 colorDialog1

if (!(pt.X> rect.Right || pt.X < rect.X|| pt.Y> rect.Bottom || pt.Y < rect.Y))

{

if (colorDialog1.ShowDialog() == DialogResult.OK )

{

cl = colorDialog1.Color;

}

break;

}



//取上方 pictureBox 在屏幕上的位置

rect =pictureBox1.RectangleToScreen(new Rectangle(0,0,pictureBox1.Width ,pictureBox1.Height));

//判断鼠标是否点击到了 pictureBox1

if (!(pt.X> rect.Right || pt.X < rect.X|| pt.Y> rect.Bottom || pt.Y < rect.Y))

{

//根据鼠标位置得到选择颜色

Bitmap bmp = (Bitmap)this.pictureBox1.Image;

cl = bmp.GetPixel(e.X,e.Y);





}







}

break;

}

Owner.Cursor = Cursors.Default ;

//如果 SelectColor 事件被映射,而且颜色已经被选择

if (SelectColor!=null && cl!= Color.Empty)

{

//触发颜色选取事件

SelectColor(cl);

}

this.Dispose();



}

/// <summary>

/// (5)如果鼠标进入 label1 的范围将 label1 BackColor 属性改变

/// 类是鼠标悬停的感觉.

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void ColorSelectForm_MouseMove(object sender, MouseEventArgs e)

{

Point pt = Control.MousePosition;

Color cl = SystemColors.Control;

if(!(pt.X> this.Right || pt.X < this.Left|| pt.Y>this.Bottom || pt.Y< this.Top))

{

Rectangle rect =label1.RectangleToScreen(new Rectangle(0,0,label1.Width,label1.Height));



if (!(pt.X> rect.Right || pt.X < rect.X|| pt.Y> rect.Bottom || pt.Y < rect.Y))

{

cl = Color.FromArgb(224, 224, 224);

}



}

label1.BackColor=cl;



}

}









调用颜色选取窗口(很简单不注视了)



private void button1_Click(object sender, System.EventArgs e)

{

ColorSelectForm ColorForm = new ColorSelectForm();

ColorForm.Owner=this;

ColorForm.SelectColor+=new ColorSelectForm.MouseSelectColor(ColorForm_SelectColor);

ColorForm.Show(sender as Button);



}



private void ColorForm_SelectColor(Color SelectColor)

{

button1.BackColor=SelectColor;

}
(ps  没必要记住,随用随查就ok了)