dotNet 桌面程序改造计划.下拉框篇.类似Word的颜色下拉框 - 中国WEB开发者网络 (http://www.webasp.net) -- 技术教程 (http://www.webasp.net/article/) --- dotNet 桌面程序改造计划.下拉框篇.类似Word的颜色下拉框 (http://www.webasp.net/article/17/16484.htm) |
| -- 作者:未知 -- 发布日期: 2005-02-02 |
| 实现功能:
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; } 备注: 组合下拉框 Grid 下拉框 以上代码均以实现正在整理中,近期发表 |
| webasp.net |