error C2440: “static_cast”: 无法从“UINT (__thiscall CSizingControlBar::* )(CPoint)”转换为“LRESULT (__thiscall CWnd::* )(CPoint)”
error C2440: “static_cast”: 无法从“UINT (__thiscall CSizingControlBar::* )(CPoint)”转换为“LRESULT (__thiscall CWnd::* )(CPoint)” f:\tools\4bands ifx_xmm2130_ft\common\sizecbar.cpp 109
CWnd类,afx_msg LRESULT OnNcHitTest(CPoint point);
而在CSizingControlBar中是afx_msg UINT OnNcHitTest(CPoint point);
只要将这些UINT替换为LRESULT就可以了。
查找OnNcHitTest,将下面两行:
afx_msg UINT OnNcHitTest(CPoint point);//.h
UINT CTestDlg::OnNcHitTest(CPoint point);//.cpp
改为:
afx_msg LRESULT OnNcHitTest(CPoint point);//.h
LRESULT CTestDlg::OnNcHitTest(CPoint point);//.cpp
另外一个小问题:
CString atMyCmd;
atMyCmd+=0x0d;
编译时出现“operator+=不明确”。改正方法:atMyCmd+=(char)0x0d;因为从unsigned int转换到CString和char的等级都是标准转换,所以编译器无法判断到底应该转换到哪一个,所以就导致了这个问题,所以应该强制转换。
关于Qt显示中文乱码问题
一直都在代码中使用GBK编码来解决Qt显示中文的问题,即在main()函数中添加下面几句:
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK")); QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
然后在发布的应用程序文件夹下建立plugins\codecs,然后将qcncodecs4.dll放到该目录下,也没再出现乱码。但是后来客户反馈说存在乱码。为什么会出现乱码呢?
原来如此。比如写了“汉字”两个字,然后以GBK形式保存在计算机的存储设备中(“汉字”的GBK编码是BA、BA、D7、D6)。然后在读取时,计算机中的二进制码“BA、BA、D7、D6”却不是以同样的GBK形式被解释成“汉字”两个字符。比如说以ISO-88591形式被读取,那么“BA、BA、D7、D6”就会被解释为四个西欧文字了。如果将程序发布到一些非简体中文的国家或地区,可能出现对方的机器上根本没有安装任何中文的编码格式,所以就会出现乱码。
那么,如何彻底解决乱码问题呢?Qt提供了强大的多国语言工具Qt Linguist。
一、编写源码:
实现多语言,1)、首先必须保证每一个用户可见的字符串都使用了tr()函数;2)、在应用程序启动时使用QTranslator载入一个翻译文件(.qm)。如:
#include <QtGui/QApplication> #include <QTranslator> #include <QMessageBox> int main(int argc, char *argv[]) { QApplication app(argc, argv); //载入翻译文件 QTranslator translator; bool bLoaded = translator.load("readnv_chs");//语言包文件,由linguist工具生成 if (!bLoaded) { QMessageBox::warning(NULL,QApplication::tr("Load File Failed"), QApplication::tr("Load readnv_chs.qm Failed!")); } app.installTranslator(&translator); mainwindow w; w.show(); return app.exec(); }
注意:翻译文件加载的位置必须在界面实例化之前完成。编写好代码后:
二、生成翻译文件:
1)、在.pro文件中添加TRANSLATIONS+=readnv_chs.ts。指明在项目中生成翻译源文件readnv_chs.ts。<.ts是可读的翻译文件,使用简单的XML格式;而.qm是经过.ts转换而成的二进制机器语言>。
2)、执行命令:lupdate -verbose xx.pro。从应用程序的源代码中提取所有用户可见的字符串,生成相应的.ts文件(readnv_chs.ts)。
3)、使用Qt Linguist翻译该应用程序。使用linguist打开readnv_chs.ts文件,对tr()函数的字符串参数进行翻译,然后点击release,生成相应的.qm文件,即readnv_chs.qm。然后将.qm文件放在应用程序目录下即可。
0x7c92e4ff 处最可能的异常: 0xC0000008: An invalid handle was specified
遇到一个纠结的问题,先贴代码。
void mainwindow::browseNvFile() { QString fileName; fileName =QFileDialog::getSaveFileName(NULL,tr("Save File"), "E:/", tr("Exp Files (*.bin)")); fileName.trimmed(); if (!fileName.isEmpty()) { ui.ReadBtn->setEnabled(true); strBinFile = fileName; ui.NvLineEdit->setText(strBinFile); } }
每次运行到fileName =QFileDialog::getSaveFileName(NULL,tr("Save File"), "E:/", tr("Exp Files (*.bin)"));时就出现:0x7c92e4ff处最可能的异常:0xC0000008:An invalid handle。之后无论是点击“继续”或者“忽略”都能运行,直接找到工程目录下的exe文件也能正常运行,也就是说只在调试的时候才会出现这个错误。代码看来看去都没觉得有问题,然后找了两个人帮忙,都没找到原因,而且奇怪的是之前没问题的代码现在调试都有这个问题了。晕啊!!后来在别的机器上运行发现没有这个问题,于是“找到”了原因:我的Qt库有问题。于是换个Qt的库试试。
换了Qt的库之后又出现了一个问题:单独执行qmake时没有问题,但是编译程序执行qmake时就出现:系统无法找到指定的程序,可能调用的某个命令出问题了。继续换Qt的库。。。
换好之后,第二个问题解决了,第一个仍然存在,重装IDE。。。装完了,问题依旧存在。跟系统有关??换到我的笔记本上现在也存在这个问题了,而之前的都是没问题,很奇怪,问题依旧没有得到解决。先记录下来,找到了原因再更新。或者哪位可以帮忙解决。。。
有时候还真的老遇到一些奇怪的问题,qt用着用着就来句“qmake不是内部或外部命令”,环境变量并没有改变。但是重新设置一下环境变量就又好了。
续:
今天问题终于解决了,好吧,就满足下某人,“感谢高手--李亚科的帮助”,^_^。
后来用其他程序测试了下,排除了Qt的问题,也曾怀疑过360私自改了系统文件,不过这个后来也被排除了。调试代码,发现调用了Overlaycon.dll,而正是在该处抛出异常。话说,Overlaycon.dll是个神马东东呢?原来是装了wuala之后出现的,仔细想想,这个问题也确实是在装wuala之后才有的。于是卸载了wuala,意料之中,问题得到了解决。其实也用不着卸载wuala,只要卸载掉Wuala OverlayIcons就可以了。应该是wuala为了把自己的软件整合到 explorer中,而 GetSaveFileName 需要调用explorer,所以加载了 overlayicon.dll。 而这个dll竟然存在bug,所以就出现问题了。呃,回家整笔记本去。。。
串口通讯中遇到的几个函数
串口工具中碰到的几个问题:
1、ClearCommError()
用途:清除串口错误或者读取串口现在状态
原型:BOOL ClearCommError(HANDLE hFile,LPDWORD lpErrors,LPCOMATAT lpStat)
参数:hFile:串口句柄
lpErrors:返回错误数值,错误代码:
1-CE_BREAK:检测到中断信号。也就是检测到某个字节数据缺少合法的停止位。
2-CE_FRAME:硬件检测到帧错误。
3-CE_IOE:通信设备发生输入/输出错误。
4-CE_MODE:设置模式错误,或者hFile值错误。
5-CE_OVERRUN:溢出错误,缓冲区容量不足,数据将丢失。
6-CE_RXOVER:溢出错误。
7-CE_RXPARITY:硬件检测到校验位错误。
8-CE_TXFULL:发送缓冲区已满。
lpStat:指向通信端口状态的结构变量,原型:
type struct _COMSTAT{
...
...
DWORD cbInQue;//输入缓冲区中的字节数
DWORD cbOutQue;//输出缓冲区的字节数
}
while (1) { bool bClearOk; bClearOk = ClearCommError( m_hComDev, &dwErrorFlags, &ComStat ); //如果函数调用成功,则返回值为非0;若函数调用失败,则返回值为0 }
if(!bClearOk) { return FALSE; } if (dwErrorFlags!=0)//错误数值 { end_time = clock(); if ((DWORD)((end_time-start_time)*1000/CLOCKS_PER_SEC) >= SERIALREAD_TIMEOUT) { return FALSE; } } else if ( ComStat.cbInQue >=data_size)//ComStat.cbInQue即为串口中当前含有的数据字节个数 { break; } else { end_time = clock(); if ((DWORD)((end_time-start_time)*1000/CLOCKS_PER_SEC) >= SERIALREAD_TIMEOUT) { return FALSE; }
2、clock()
c/c++中的计时函数是clock(),与其相关的数据类型是clock_t。MSDN中对该函数的定义:
clock_t clock(void);
该函数返回自程序开始运行的处理器时间,如果无可用信息,返回-1。转换返回值若以秒计需除以CLOCKS_PER_SEC。(在linux下是1000000,windows下是1000).也可以用clock()函数来计算机器运行一个循环或者处理其他事件到底花了多长时间。在要计时程序前后段分别调用clock函数,用最后一次的返回值减去前一次的返回值就得到运行的处理器时间,然后再转换为秒。如上例。
3、GetLastError()
作用就是取得上一个函数操作时所产生的错误代码。
DWORD GetLastError(void);通过调用,返回一个32位的数值。如:
DWORD dwError = GetLastError();
返回值的意义:
http://hi.baidu.com/_%E2d_%B7%B3_%DE%B2%C2%D2/blog/item/c12e8f3fff6f54c17c1e71c1.html
其实用第三方类也挺方便的,不过貌似第三方类有个问题,具体的问题记不清了,后续继续研究串口通讯。先写到这,待续。。。^_^
.ini文件的读写
一直用Qt开发,无奈最近却要用MFC搞个东西,估计以后也不会用它开发,先记录下来,免得到时用时忘了。
ini文件由若干个节(Section)组成,每个Section由若干键(Key)组成,每个Key可以赋相应的值。读写ini文件实际上就是读写某个的Section中相应的Key的值。
MFC中读写ini文件:
1、把信息写入自己定义的.ini文件
BOOL WritePrivateProfileString(LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpString,
LPCTSTR lpFileName //要写入的文件的文件名,若该ini文件与程序在同一个目录下,也可使用相对路径,否则要给出绝对路径。)
如:
::WritePrivateProfileString("CONFIGINFO","SOFT VERSION",m_SoftVer,".\\SET_NO2.ini");//将m_SoftVer的内容写进SET_NO2.ini
注,当使用相对路径时,\\前的.号不能丢掉了。
2、从.ini文件中读取信息
(1)、读取字符串
DWORD GetPrivateProfileString(LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpDefault,
LPCTSTR lpReturnedString,
DWORD nSize,
LPCTSTR lpFileName)。
如:
::GetPrivateProfileString("CONFIGINFO","BAND","Error",strBandProof.GetBuffer(5),5,".\\SET_NO2.ini");
(2)、读取整数
UINT GetPrivateProfileInt(LPCTSTR lpAppName,
LPCTSTR lpKeyName,
INT nDefault,
LPCTSTR lpFileName)
如果用以下语句写入年龄信息:
::WritePrivateProfileString("Test","age","34",".\\exp.ini");
则可以用以下语句读取age的值:
int age;
age=::GetPrivateProfileInt("Test","age",0,".exp.ini");
Qt下:
写进.ini文件:
strIniDir = QCoreApplication::applicationDirPath() + "/config.ini"; QSettings *ConfigIni = new QSettings(strIniDir,QSettings::IniFormat,0); ConfigIni->setValue("Port",Params.PortName);
读取.ini文件:
strIniDir = QCoreApplication::applicationDirPath() +"/config.ini"; QSettings *ConfigIni = new QSettings(strIniDir,QSettings::IniFormat,0); PortName=ConfigIni->value("Port",PortName).toString();