先看图在说 .
实现功能 :
下拉出颜色选取对话框 .
后台窗口不失去焦点 .
点击更多调用 windows 标准颜色选取对话框选取颜色 .
开发背景:
在网上看到一些文章可以基本实现这些功能、但是大多使用前台窗口获得焦点后在迅速把焦点
转移到后台窗口的方法、或是将前台窗口 Show 出通过使去焦点来关闭前台窗口,或者干脆用个控件(用普通的控件如果如果范围超出后台窗口的范围就会被窗口遮挡)
而 Windows 内置的菜单或下拉框都不会出现使、前台窗口触发失去焦点事件的事件、更不会被遮挡、抱着一个程序员执著的信念、在 csdn 论坛连发数贴( 400 分啊)在加上不断的努力终于有所曾就。
在此感谢 csdn 的各位同僚朋友,没有你们就没有这个世界(哈)。
废话不多说了、进入正题。
程序实现代码解析:
** 1 ** ** )文章所用到的基础 Windows API 类。 **
using System;
using System.Runtime.InteropServices;
///
1<summary>
2
3/// 系统调用,都是 Windows API 相关 注视的地方也许大家有用没有删除,具体说明情察看 msdn
4
5/// </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 = 0x 001C ;
//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: 在此处添加构造函数逻辑
//
}
}
** 本文章弹出窗口的基类 ** ** (代码处理流程情根据标号浏览) **
///
1<summary>
2
3/// NoActForm 实现弹出窗口的基类。
4
5/// </summary>
public class NoActForm : System.Windows.Forms.Form
{
///
1<summary>
2
3/// 必需的设计器变量。
4
5/// </summary>
private System.ComponentModel.Container components = null ;
public NoActForm(): base ()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
}
///
1<summary>
2
3/// 清理所有正在使用的资源。
4
5/// </summary>
protected override void Dispose( bool disposing )
{
if ( disposing )
{
if (components != null )
{
components.Dispose();
}
}
base .Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
///
1<summary>
2
3/// 设计器支持所需的方法 \- 不要使用代码编辑器修改
4
5/// 此方法的内容。
6
7/// </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);
}
}
///
1<summary>
2
3/// 自己定义的 show
4
5/// </summary>
///
1<param name="Ctl"/>
要在那个控件附近 show 出本窗口
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;
<SPAN style="mso-tab-count