自定义颜色对话框





1.00/5 (2投票s)
2007年6月8日
5分钟阅读

30602

307
通过重写窗口过程方法来自定义颜色对话框
引言
颜色对话框是 C#.NET 中的一个预定义对话框,我们可以用它来在运行时选择和更改控件的颜色。它允许我们通过有限的属性和可用的事件进行一些修改。
与其他窗口窗体一样,它没有 Paint 事件或 BackColor 属性来根据我们的需求进行更改。在我们的许多应用程序中,我们需要更改对话框的外观,但这并非直接可能。在这段代码中,我重写了 WinProc() 方法,从而跟踪窗口消息并将我自己的方法整合进来以绘制对话框。通过使用这段代码,任何人都可以根据自己的需求更改外观。
背景
有了基本的编程知识,应该对窗口过程、窗口消息和消息处理有很好的了解。我们可以通过捕获 WM_Paint 消息来整合我们自己的方法来绘制颜色对话框,我在这里使用了渐变画笔来绘制对话框的背景。
使用代码
您可以使用 zip 文件中提供的代码来更改颜色对话框的外观。通过遵循相同的步骤,可以更改任何其他对话框的外观。
可以使用 Visual Studio 附带的 WinSpy++ 来获取对话框上不同控件的窗口句柄和控件 ID。
以下是可以用于更改对话框外观的消息列表:
private const int WM_DESTROY = 0x0002;
private const int WM_PAINT = 0x000F;
private const int WM_INITDIALOG = 0x0110;
private const int WM_COMMAND = 0x0111;
private const int BN_CLICKED = 0;
private const int BN_PAINT = 0;
private const int WM_CTLCOLORBTN = 0x0135;
private const int WM_CTLCOLORSTATIC = 0x0138;
private const int WS_CHILD = 0x40000000;
private const int WM_CTLCOLORDLG = 0x0136;
private const int MSG_MOVETOTOPMOST = 0x00F2;
private const int WM_CTLCOLOREDIT = 0x0133;
private const int WM_DRAWITEM = 0x002B;
private const UInt32 WM_NCPAINT = 0x0085;
private const int WM_ERASEBKGND = 0x0014;
private const int WM_WINDOWPOSCHANGED = 0x0047;
对话框上不同控件的控件 ID 列表
private const int ID_OK = 1;
private const int ID_CANCEL = 2;
private const int DLG_COLOR = 10;
private const int NUM_BASIC_COLORS = 48;
private const int COLOR_SOLID_LEFT = 730;
private const int COLOR_SOLID_RIGHT = 731;
private const int COLOR_HUE = 703; // 编辑
private const int COLOR_SAT = 704; // 编辑
private const int COLOR_LUM = 705; // 编辑
private const int COLOR_RED = 706; // 编辑
private const int COLOR_GREEN = 707; // 编辑
private const int COLOR_BLUE = 708; // 编辑
private const int COLOR_CURRENT = 709;
private const int COLOR_RAINBOW = 710; //颜色渐变轮
private const int COLOR_ELEMENT = 716;
private const int COLOR_ADD = 712; // 按钮: "&添加自定义颜色"
private const int COLOR_MIX = 719; // 按钮: "&定义颜色 >>"
private const int COLOR_BOX1 = 720; // 静态: 基本颜色
private const int COLOR_CUSTOM1 = 721; // 静态: 自定义颜色
private const int COLOR_HUEACCEL = 723; // 标签编辑
private const int COLOR_SATACCEL = 724; // 标签编辑
private const int COLOR_LUMACCEL = 725; // 标签编辑
private const int COLOR_REDACCEL = 726; // 标签编辑
private const int COLOR_GREENACCEL = 727; // 标签编辑
private const int COLOR_BLUEACCEL = 728; // 标签编辑
控件被归类为“静态”、“编辑”、“按钮”等。有一个控件 ID 为 Color_RAINBOW 的颜色渐变轮,这是我们可以输入 RGB 值或色相、饱和度和亮度值来更改颜色的轮盘。
通过窗口过程,我们还可以更改颜色对话框的大小,并可以添加我们需要的控件显示在对话框上。所有这些都可以通过跟踪所需的修改的窗口消息来轻松完成。
除了窗口消息和控件 ID 之外,还应该从 User32.dll 导入必要的函数来实际提供窗口句柄并在对话框上进行操作。示例如下:
private static extern bool GetWindowRect(int hWnd, ref Rectangle lpRect);
[DllImport("user32.dll")]
private static extern int GetParent(int hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
[DllImport("user32.dll")]
static extern uint GetDlgItemInt(IntPtr hDlg, int nIDDlgItem, IntPtr lpTranslated, bool bSigned);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern int GetDlgCtrlID(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int Width, int Height, bool repaint);
[DllImport("user32.dll")]
private static extern bool UpdateWindow(IntPtr hWnd);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool redraw);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int InvalidateRect(IntPtr hWnd, IntPtr rc, int bErase);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SetWindowPos(IntPtr hWnd,IntPtr hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern bool LockWindowUpdate(IntPtr hWndLock);
[DllImport("gdi32.dll")]
static extern uint SetBkColor(IntPtr hdc, int crColor);
[DllImport("gdi32.dll")]
static extern int SetBkMode(IntPtr hdc, int iBkMode);
//[DllImport("user32.dll", CharSet = CharSet.Auto)]
//static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
[DllImport("gdi32.dll")]
static extern IntPtr GetStockObject(int fnObject);
//rotected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { switch (msg) { case WM_ERASEBKGND: Graphics gfr = Graphics.FromHwnd(hWnd); LinearGradientBrush lnrfr = new LinearGradientBrush(new Point(0, 0), new Point(400, 400), Color.CornflowerBlue, Color.White); gfr.FillRegion(lnrfr, gfr.Clip); break; } return base.HookProc(hWnd, msg, wparam, lparam); } } } //
关注点
MSDN 上提供了很多关于修改对话框的信息,但这次没有一个真正帮到我,尽管 MSDN 在其他情况下很有帮助。