下载demo project (v1.1) - 301 Kb
下载source + icons (v1.1) - 12.5 Kb
下载source Help file - 71 Kb
表的内容
动机环境使用将LED按钮文件和资源添加到项目中一个简单的LED按钮一个多状态LED按钮活动LED按钮A条件LED按钮文本属性工具提示代码文档提供文件免责声明使用条款更新日志
动机
写这个CLedButton控件的动机是有一个LED控件,即:
只读了控制。能够处理传统的两国关系之外的问题。能够发出“活动”信号(在可控超时后自动关闭)。能够控制从一种状态到另一种状态的转换。(从一种状态到另一种状态的转换由外部控制。)使用从资源文件加载的LED图标。无闪烁的控制。
两年前,我在CodeProject和SourceForge中寻找一个可以满足我的五个需求的静态控件或按钮控件,但是我没有找到,所以我决定自己构建一个。
我从这个伟大的网站上展示的以下控件中获得了灵感:
第一个候选是Benjamin Mayrargue[]发布的CLedButton[],它给了我使用复选框(CBbutton作为基类)作为控件的想法。然后我看到了VGirish的动态LED控制,但也缺少一些我想要的功能。保罗·梅西纳(Paolo Messina)的COddButton给了我使用自画按钮的想法。然后Davide Calabro[]在他的神奇的CButtonST[]中为我提供了实现LED按钮控制所需的其余背景。
有了这个背景,两年前我开始定制我自己的CLedButton控件。从一个项目到另一个项目,代码得到了增强和简化,直到它变得成熟和健壮,可以在这里发布。
环境使用
LED按钮最初是用VC 6.0 (Visual Studio c++ 6.0)开发的,现在我用的是VC 7.1 (Visual Studio c++ . net 2003)。我将“尝试”提供适用于这两个版本的说明。
将LED按钮文件和资源添加到项目中
确保你有以下文件:
此控件的来源:LedButton.h和LedButton。cpp,将它们复制到项目目录中。您想要使用的LED图标文件。(你可以使用我提供的演示中的那些。)将它们复制到项目资源目录(res子目录)。
在您的开发环境中打开您的项目,并遵循以下步骤:
将LedButton.h和LedButton.cpp文件添加到项目中。使用资源编辑器,在对话框中添加一个复选框,将其ID更改为IDC_LED_CHECK。你也可以改变这个复选框的属性,相关的属性是:左文本,多行,水平对齐,垂直对齐,右对齐文本。使用资源编辑器导入图标文件,将id分别命名为IDI_GRAY_ICON、IDI_GREEN_ICON、IDI_YELLOW_ICON、IDI_RED_ICON和IDI_BLUE_ICON。使用ClassWizard添加名为m_ledCtrl的成员变量作为控制变量。(生成的类型为CButton,稍后会更改)。在对话框头文件中将LED按钮控件的类型从CButton更改为CLedButton。添加预处理器#include“LedButton”。h"的头文件,以及。
对话头文件应该包含:…
#include “LedButton.h”
…
class DemoDlg : public CDialog
{
…
private:
…
CLedButton m_ledCtrl;
};
对话框实现文件应该包含:void CDemoDlg::DoDataExchange(CDataExchange* pDX)
{
…
DDX_Control(pDX, IDC_LED_CHECK, m_ledCtrl);
…
}
现在是初始化和配置LED按钮的时候了。
一个简单的LED按钮
默认情况下,创建的CLedButton控件有两个LedStates,你只需要设置图标,每个状态一个,然后根据你的需要设置LedState。
为了方便起见,可以定义用于描述每种状态的枚举类型。关闭状态的整数值为0,打开状态的值为1,或使用Afx FALSE和TRUE #定义,或使用LED按钮自己预定义的值LED_BUTTON_STATE_OFF或LED_BUTTON_STATE_ON。
在InitDialog()方法中添加以下代码:…
m_ledCtrl.SetIcons(IDI_GRAY_ICON, IDI_YELLOW_ICON);
…
LED按钮的默认状态是LED_BUTTON_STATE_OFF。
如果你想改变图标的默认大小,你不能使用SetIcons(),相反,调用SetIcon()方法为每个LED状态:…
m_ledCtrl.SetIcon(LED_BUTTON_STATE_OFF, IDI_GRAY_ICON, 14,14);
m_ledCtrl.SetIcon(LED_BUTTON_STATE_ON, IDI_YELLOW_ICON, 14,14);
…
每次您想要改变LED的颜色时,只需调用SetLedState()方法来显示新的LED状态。…
// Turn the Led ON
m_ledCtrl.SetLedState(LED_BUTTON_STATE_ON);
…
如果你不想要一个更复杂的LED按钮,这就是全部。
如果在与LED当前显示的LED状态相同的情况下调用该方法,则SetLedState()不会执行任何操作。(这样做是为了减少闪烁)
一个多状态LED按钮
多状态LED按钮就像一个简单的LED,但有两个以上的LED状态。
定义一个枚举类型来表示每个LED状态可能是符合逻辑的,尽管这不是强制性的。
在本文档中,让我们定义一个名为EMyLedState的枚举类型,用于多状态LED按钮,如下所示:…
enum EMyLedState {
GRAY_LED_STATE = LED_BUTTON_STATE_ON, // Initial LedState
GREEN_LED_STATE,
YELLOW_LED_STATE,
RED_LED_STATE,
BLUE_LED_STATE,
MY_LED_STATES_SENTINEL // Not to be used as a EMyLedState.
};
…
MY_LED_STATES_SENTINEL是我们将使用的LED状态的数量。
多状态LED按钮的初始化要求在为每个状态设置图标之前,调用SetLedStatesNumber()方法来设置LED状态的最大数量。
InitDialog()中的代码变成:…
m_ledCtrl.SetLedStatesNumber(MY_LED_STATES_SENTINEL);
m_ledCtrl.SetIcon(GRAY_LED_STATE, IDI_GRAY_ICON);
m_ledCtrl.SetIcon(GREEN_LED_STATE, IDI_GREEN_ICON);
m_ledCtrl.SetIcon(YELLOW_LED_STATE, IDI_YELLOW_ICON);
m_ledCtrl.SetIcon(RED_LED_STATE, IDI_RED_ICON);
m_ledCtrl.SetIcon(BLUE_LED_STATE, IDI_BLUE_ICON);
…
状态设置与以前相同,但是现在可能的值是从GRAY_LED_STATE到BLUE_LED_STATE。
活动LED按钮
Activity LED按钮是在可控一段时间后自动关闭的LED按钮,这样用户就不用负责管理关闭时间了。
活动时间由一个内部计时器控制,当LED按钮被设置为除LED_BUTTON_STATE_OFF之外的任何状态时,它就会被触发。当定时器计时结束时,LED按钮关闭。(当定时器计时结束时,LED将停止活动。)
因为计时器是一个有限的全局资源,要激活一个LED按钮,用户应该提供一个timerId来识别计时器。这样,两个或多个Activity LED按钮可以在同一个应用程序中共存,每个按钮都有不同的计时器标识。
要停用一个活动计时器,只需提供一个空的timerId。计时器也被释放时,LED按钮窗口被销毁。
首先,你可能想要管理所有的计时器你使用的代码在一个单独的地方,因此,在一些可见的头文件,定时器标识符:…
#define MY_ACTIVITY_LED_TIMER_ID (WM_USER + 0x123)
…
然后InitDialog()中的代码变成:…
// Simple Led with Activity detection
m_ledCtrl.SetIcons(IDI_GRAY_ICON, IDI_YELLOW_ICON);
m_ledCtrl.SetLedActivityTimer(MY_ACTIVITY_LED_TIMER_ID, 123);
…
上面的代码将LED设置为持续时间123毫秒的活动LED。
一个简单的,多状态或条件LED按钮也可以是一个活动LED按钮。
A条件LED按钮
为了更好地理解条件LED的状态,让我们来看看下面的情况:
LED按钮控件能够显示两种以上的状态。LED按钮用作故障检测器。一个线程将高速从硬件读取一些数据,等待一些信号的改变。当需要时,它将向GUI发送带有更改通知的通知。当变化为“缓慢”变化时,LED应在“开”和“关”之间正常改变颜色。但是,如果在不到50秒的时间内连续发生两次变化,则LED应该以不同的颜色显示“开”或“关”状态。
下面的状态机可能提供更好的画面:
当LED按钮状态依赖于两个(或更多)输入时,则LED按钮成为条件LED。
对于“故障检测器”,输入如下:
当前领导国家。被请求的新LED状态。自上次更换LED以来的经过时间。
为了设置条件LED,您应该从派生自CLedStateCondition(在LedButton.h头文件中定义的一个类)的类中创建一个派生对象。
子类应该覆盖ChangeState()虚方法。
ChangeState()方法接收三个参数:
newLedState,被请求的新LedState。oldLedState,转换前的当前LedState。isForcedChange,指示强制转换到newLedState的布尔标志。派生类应该修复它的私有FSM,以反映这种强制更改,并返回newLedState。
ChangeState()应该包含决定LED按钮将进入的新LED状态的所有逻辑。(我不会在这里提供故障检测器的代码,因为我想关注条件LED。)
您可以在某些头文件中定义以下枚举类型来处理故障检测器:…
enum EGlitchDetectorState
{
OFF_STATE = LED_BUTTON_STATE_ON, // Green LED,
ON_STATE, // Yellow LED,
GLITCH_OFF_STATE, // Blue LED,
GLITCH_ON_STATE, // Red LED,
IDLE_STATE, // No LED Icon,
GLITCH_DETECTOR_STATES_SENTINEL // Not to be used as a EGlitchDetectorState.
};
…
硬件通知将分别为TRUE和FALSE。
对于本例,CLedStateCondition派生类的名称将是CGlitchDetector。将这个CGlitchDetector的一个实例放在CDemoDlg中,并调用它m_glitchDetector。
对话框InitDialog()的代码可以是:…
//
// 1) Initialize the m_glitchDetector as required (code not shown here)
// 2) Set the led as a multi-state led.
// 3) Add the Glitch Detector to the Led Button.
// 4) Set the initial state as IDLE_STATE. (Force this state)
//
m_ledCtrl.SetLedStatesNumber(GLITCH_DETECTOR_STATES_SENTINEL);
m_ledCtrl.SetIcon(OFF_STATE, IDI_GREEN_ICON);
m_ledCtrl.SetIcon(ON_STATE, IDI_YELLOW_ICON);
m_ledCtrl.SetIcon(GLITCH_ON_STATE, IDI_RED_ICON);
m_ledCtrl.SetIcon(GLITCH_OFF_STATE, IDI_BLUE_ICON);
m_ledCtrl.SetIcon(IDLE_STATE, 0,0,0); // No Icon on purpose.
m_ledCtrl.SetLedStateCondition(&m_glitchDetector);
m_ledCtrl.SetLedState(IDLE_STATE, true); // Force IDLE_STATE.
…
在接收硬件通知的代码中,我们将分别使用OFF_STATE或ON_STATE值调用SetLedState()方法。afx_msg LONG CDemoDlg::OnHWUpdate(WPARAM wparam, LPARAM /lparam/)
{
…
LedState ledState = (TRUE == wparam) ? ON_STATE : OFF_STATE;
m_ledCtrl(ledState);
…
}
一个简单的,多状态或活动的LED按钮也可以是一个条件LED按钮。
文本属性
可以为每个LED状态更改文本前景色或/和按钮背景色。默认情况下,文本前景色为::GetSysColor(COLOR_BTNTEXT),按钮背景色为::GetSysColor(COLOR_BTNFACE)。
控制LED状态颜色的方法如下:
SetTextForeground ():
为特定的LED状态设置文本前景色。GetTextForeground ():
获取特定LED状态的文本前景色。SetTextBackground ():
为特定的LED状态设置文本背景颜色。GetTextBackground ():
获取特定LED状态的文本背景颜色。SetTextColors ():
为特定的LED状态设置文本前景色和按钮背景色。RestoreDefaultColors ():
恢复所有LED状态的默认颜色,请小心使用。
工具提示
这个LED按钮控件可以显示一个“工具提示”,一个小的弹出窗口,显示一些描述LED用途的文本。工具提示在大多数情况下是隐藏的,只有当用户将光标放在LED按钮上并让它停留半秒时才会出现。工具提示出现在光标附近,当用户单击鼠标按钮或将光标移离工具时消失。
以下方法控制工具提示:
SetTooltipText ():
从资源字符串或提供的文本设置工具提示文本。ActivateTooltip ():
激活/禁用工具提示。
在当前版本中,只支持“矩形”工具提示。
代码文档
代码中包含Doxygen注释,用于生成HTML文档的代码。我强烈建议你直接或间接地使用这些工具。
Doxygen是一个针对c++, C, Java, Objective-C, IDL (CORBA和微软风格)的文档系统,在某种程度上,也适用于PHP, c#和d。
辅助帮助文件是使用KingsTools [^] Visual Studio . net插件通过SteveKing[^]生成的。此外接程序包含您可能希望在开发环境中集成的几个有用工具。(Doxygen、代码统计、语法着色等)
感谢SteveKing提供了这个工具,以及我在代码中使用的他的免责声明。
提供文件
在源代码和演示项目中提供了以下文件,您可以在自己的项目上使用:
源文件:LedButton.h和LedButton.cppLED图标文件:13个不同颜色的LED图标。(LedButton_src.zip)灯泡文件:LightBulbOff。ico, LightBulbOn。ico, LightBulbBroken.ico(在演示项目中)
免责声明
本代码和随附文件是“按原样”提供的,没有明示或默示保证。不负责可能的损害,或其功能的副作用。用户必须承担使用此代码的全部风险。如果它对你的电脑造成任何损害,使你的宠物生病,使你的秃顶增加,或使你的汽车在你启动它时发出奇怪的噪音,作者不承担责任。这段代码没有bug,只是没有文档化的特性!
使用条款
此代码对于个人使用或免费软件应用程序是免费的。如果您计划在商业或共享软件应用程序中使用此代码,请与作者联系以获得他的许可。
更新日志
DateRev.Description2004/Jan/161.1无闪烁更新(感谢Iain Clarke[^])2004 / 12月/ 251.0在CodeProject上亮相2002 / 8月16——创建
后记
希望这个LED控制对你有用。
为了帮助其他使用CodeProject的用户,请对本文进行评价:)
本文转载于:http://www.diyabc.com/frontweb/news14508.html