这样的一个问题:界面上一组(一堆)静态控件,比如模拟控制器上许多按钮,当某个信号来时,一些设置为红色(故障),当另一个信号来时,一些设置为绿色(正常),使用了CLabel类,在http://www.codeproject.com/KB/static/clabel.aspx上下载,因为它可以直观设置【背景色】。
因为是“一组按钮”(不是一个),程序应该用循环的方式来遍历“每一个按钮”,而不是直接去直观的“按钮2设置颜色、按钮2设置颜色,。。。。按钮N设置颜色”。第一次我选用了循环遍历控件ID下标方式,以下程序是选择了两个静态控件做例子:
使用VC创建一个基于对话框的程序,上面添加两个静态文本框(IDC_STATIC01、IDC_STATIC02)和一个按钮,两个静态文本框分别关联CLabel类:
在头文件中:
CLabel m1;
CLabel m2;
在实现cpp文件初始化函数OnInitDialog中:
m1.SubclassDlgItem(IDC_STATIC01,this); m2.SubclassDlgItem(IDC_STATIC02,this);
// // 奇数时为红色,偶数时为绿色 // void CTest2Dlg::SetColors(int x) { int i; for (i=IDC_STATIC01; i<=IDC_STATIC02;i++) { if(x%2) { CLabel *p = ((CLabel *)GetDlgItem(i)); p->SetBkColor(RGB(0, 255, 0)); } else { CLabel *p = ((CLabel *)GetDlgItem(i)); p->SetBkColor(RGB(255, 0, 0)); } } }
void CTest2Dlg::OnOK() { static y=0; SetColors(y++); }也可以使用SetTimer调用,也是正常闪烁的:
void CTest2Dlg::OnOK() { SetTimer(1, 100, 0); } void CTest2Dlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default static int x=0; SetColors(x++); CDialog::OnTimer(nIDEvent); }
void CTest2Dlg::OnOK() { AfxBeginThread(MyControllingFunction, this); } UINT MyControllingFunction( LPVOID pParam ) { CTest2Dlg *p = (CTest2Dlg *)pParam; int x = 0; while(1) { Sleep(100); p->SetColors(x++); } return 1L; }
好像是
CLabel *p = ((CLabel *)GetDlgItem(i));
转换类型时失败,但是为何在按钮事件(或者时钟触发事件)中直接调用,又不失败呢?
最后的解决办法:不使用控件ID下标循环:
定义时:
CLabel m[2];关联时:
for (int i=0; i<2; i++) { m[i].SubclassDlgItem(IDC_STATIC01+i,this); }
void CTest2Dlg::SetColors(int x) { int i; for (i=0; i<=2;i++) { if(x%2) { m[i].SetBkColor(RGB(0, 255, 0)); } else { m[i].SetBkColor(RGB(255, 0, 0)); } } }
因为起到了同样的遍历静态控件的效果,只好暂时到此为止。
观察CLabel的源码,没看出什么问题,并且自己也尝试写过一个CColorStatic类(只是实现设置背景颜色),在http://blog.csdn.net/dijkstar/article/details/7184752,用第一方式调用(线程函数循环ID下标),是正常的!更加百思不得其解,先到此。