自定义控件在软件中的应用

在软件开发过程中,经常需要创建一些特定的控件来满足用户界面的需求。本文将介绍如何在自己的代码中使用通用选择器控件,并提供一个创建自定义选择器控件的示例。

颜色选择器的起源

本文的灵感来源于Chris Maunder的Office 97风格的Color Picker控件。几年前,对它进行了大量修改,以便在软件中从调色板中选择颜色。没有创建自己的调色板,而是使用了Autocad在DXF文件中定义的颜色。0代表黑色,1代表白色,2代表红色,以此类推。最近,需要添加一些绘图功能。一旦添加了一些图案,就想添加其余的。这将形成一个包含60多个选项的下拉列表。同样,想要有下拉列表来选择线宽和线型。

通用选择器控件的使用

希望这非常简单!将以线型选择器为例。首先,在对话框中添加一个按钮,并给它一个ID号。文本无关紧要,但方便以后编辑对话框。

#include "DrawingPickers.h" class CGenericPickerDemoDlg : public CDialog { ... CPickerLineStyle m_LineStyle; ... };

接下来,在OnInitDialog对话框成员函数中子类化控件。还喜欢初始化当前项。如果愿意,可以在DoDataExchange中使用DDX_Control,但很少这样做。

BOOL CGenericPickerDemoDlg::OnInitDialog() { CDialog::OnInitDialog(); ... m_LineStyle.SubclassDlgItem(IDC_LINESTYLE, this); m_LineStyle.SetStyle(Gdiplus::DashStyleSolid); ... return TRUE; // return TRUE unless you set the focus to a control }

要处理选择的变化,应该处理CBN_SELCHANGE通知。Chris的控件使用了自定义消息,但想偷懒,能够使用ON_CBN_SELCHANGE宏来编写代码。

BEGIN_MESSAGE_MAP(CGenericPickerDemoDlg, CDialog) ... ON_CBN_SELCHANGE(IDC_LINESTYLE, OnPickerChanged) ... END_MESSAGE_MAP()

最后,需要对选择做一些事情。在演示程序中,用各种样式画一个圆。由于这不是一个GDI+教程,将跳过这部分!

创建自己的选择器

在CGenericPicker中有一些纯函数需要覆盖。它们是:

virtual int GetColumns() const = 0; virtual int GetRows() const = 0; virtual void MeasureSubItem(CSize &mis) = 0; virtual void DrawSubItem(const DrawItemSubStruct &dis) = 0; virtual BOOL ShowDefaultItem() const = 0; virtual BOOL IsCellValid(int nCol, int nRow) const { return TRUE; }

将展示CPickerLineWidth的实现作为示例。

int CPickerLineWidth::GetColumns() const { return 2; } int CPickerLineWidth::GetRows() const { return 10; }

希望这两个可覆盖函数相当直观!2D下拉菜单有多少个框宽和高...

void CPickerLineWidth::MeasureSubItem(CSize &mis) { mis.cx /= 2; mis.cy = 12; }

MeasureSubItem被调用一次。CSize结构被初始化为与添加到对话框的按钮相同的大小。这使得将下拉菜单的宽度与父控件的宽度匹配变得容易。由于有两列,而且它们都不需要特定的宽度,只是将宽度在它们之间分割。对于其他控件(如颜色或填充样式,这是固定大小的)。

void CPickerLineWidth::DrawSubItem(const DrawItemSubStruct &dis) { CRect rc(dis.rcItem); Graphics graphics(*dis.pDC); Color colour; colour.SetFromCOLORREF(dis.bSelected ? GetSysColor(COLOR_BTNTEXT) : GetSysColor(COLOR_BTNSHADOW)); float fWidth = dis.nRow + float(10 * dis.nColumn); fWidth /= 2.0f; Pen pen(colour, fWidth); graphics.DrawLine(&pen, rc.left, rc.top + 6, rc.right, rc.top + 6); }

DrawSubItem负责控件的繁重工作。它用于绘制按钮和每个单元格。DrawItemSubStruct结构有CDC、绘图矩形、当前列和行,以及是否应该绘制为选中状态。

BOOL CPickerLineWidth::ShowDefaultItem() const { return FALSE; }

这并不是真的由实现的 - Chris的控件使用它。这让继承控件告诉CGenericPicker类是否要为默认项留出空间。这将用-1的列和行绘制。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485