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();