Qt+QZXing编写识别二维码的程序

本人最近在用Qt编写程序,需要用编写二维码识别功能。在网上搜寻一番,找到了QZXing。配置过程中确实出了一大把汗,这里我写这篇文章记录配置方法,替后人省一把汗吧!
我的开发环境:MSVC2010 + Qt5

这里下载最新版的QZXing_sourceV2.3.zip,解压之后得到的是源代码,里面有一个QZXing.pri文件。理论上用MSVC加载这个pri文件之后这个库的代码就会出现在工程的代码列表中,但是理论归理论,实际上msvc在加载pri的过程中,弹出一大堆错误信息,完全不知所云,网上找遍了,也没找出个所以然来。后来发现在Qt Creator中使用QZXing.pri文件就很容易,只要在pro文件,也就是Qt Creator的工程文件中加入

include(QZXing_Sourcev2.3/QZXing.pri)

即可。

于是我使用的办法是,用Qt Creator创建一个dll,msvc2010调用这个dll就可以了。

用Qt Creator创建dll

随便什么工程,这个工程不需要界面文件。把配置文件里的内容改为:

QT += core
TARGET = Qr
TEMPLATE = lib(之前这里是app)
SOURCES += main.cpp
include (QZXing/QZXing.pri)

TEMPLATE=lib是关键,它表示你创建的是库文件,而不是exe文件。
然后编写识别二维码的函数,将main.cpp里的内容改为:

#include <QtCore>
#include <cstring>
#include <string>
#include "QZXing.h"

extern "C" Q_DECL_EXPORT bool GetQrStr(const char* file, char* buffer, int buffer_size)
{
    QZXing dec;
    dec.setDecoder(QZXing::DecoderFormat_QR_CODE);

    QString strTmp = dec.decodeImageFromFile(file);
    if (strTmp.length())
    {
        strcpy_s(buffer, buffer_size, strTmp.toStdString().c_str());
        return true;
    }
    return false;
}

执行qmake,然后构建。

在MSVC2010中调用编写好的dll

调用方式有很多种,这里我使用的是QLibrary,使用方式如下:

typedef bool (*fpGetQrStr)(const char*, char*, int);

QLibrary lib("qr.dll");
fpGetQrStr GetQrStr = (fpGetQrStr)lib.resolve("GetQrStr");
if (GetQrStr)
{
    char buffer[BUFSIZ] = {0};
    if (GetQrStr(QR_IMAGE_PATH, buffer, BUFSIZ))
    {
        qDebug() << "Content is:" << buffer;
    }
    else
    {
        qDebug() << "resolve failure";
    }
}

注意事项

1、编写类似GetQrStr函数的时候,它的参数以及返回值要是C语言中基本的数据类型,不然可能会引起崩溃。
2、我的Qt Creator调用的编译器也是msvc2010.

相关链接

1、QT实现截图功能并识别其中的二维码
2、QZXing+Opencv+Qt Creater实现二维码,一维码的识别

Qt表格设置某一列禁止被编辑

在Qt中的view-model中,如果希望某一列禁止用户进行编辑,可以给这一列设置一个委托。这个重写这个委托的createEditor函数,让这个函数返回空指针即可。

class DisableEditDelegate : public QItemDelegate
{
Q_OBJECT
public:
    explicit DisableEditDelegate(QWidget* parent = 0)
        : QItemDelegate(parent)
    {

    }

    ~DisableEditDelegate()
    {

    }

    QWidget* createEditor(
        QWidget *parent,
        const QStyleOptionViewItem &option,
        const QModelIndex &index) const
    {
        //以下三行是为了消除“定义了变量未使用”这个警告
        (void)parent;
        (void)option;
        (void)index;

        return NULL;
    }
}

在上面这一段代码中,createEditor返回NULL,然后设置该类的实例为某一列的委托即可

DisableEditDelegate* pDisableEdit = new DisableEditDelegate(this);
m_View->setItemDelegateForColumn(column, pDisableEdit);

另外,多个列可以公用同一个委托实例。

明天回学校了

时间过得很快,我来这里实习的时间又有了小半年。因为毕业的原因,我办理了返校手续,明天回学校。我是2月18号开始过来上班的,掐指一算,哦才两个多月,没半年,也许是因为健忘,让我觉得这半年过得特别久吧。这两个月做的工作跟去年实习做的工作还是有很大的不同的,去年都参与了实际功能的开发,而今年,我翻了一下工作日志才发现,今年我几乎做的都是边角的功能,没有任何技术含量可言。当然去年我们组人少,今年人多了不少,而且多出来的人实力也不错,自然把主要的工作交给他们去做,而剩下的边角,就剩给我了。

我没抱怨什么,我只是觉得这两个月技术方面的东西学的东西不多,但因为犯了几次低级错误,被老大批评了,养成了用严谨的态度去工作。在被批评之后到现在的这么长的时间里,我的代码就再也没有犯过低级错误了。我觉得这一点,对我来说是一次大的成长,它影响的不光是我的编码工作,它还影响着我今后的其他工作和生活。我会不断地提醒自己,要严谨。

我觉得,无论做什么工作,要想把它做好,就得在别人不注意的细节上死磕吧!

用Win32 Api编写Win7/XP风格的界面

首先在RES目录下建一个文件,命名 windows.manifest 后缀为:.manifest
然后再用记事本打开放入如下代码:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity name="Microsoft.Windows.XXXX" processorArchitecture="x86" version="5.1.0.0" type="win32" />
    <description>Windows Shell</description>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*" />
        </dependentAssembly>
    </dependency>
</assembly>

然后导入资源,把文件windows.manifest添加到工程的资源中:
插入->资源->导入->文件类型改为“所有文件”->找到windows.manifest->弹出对话框
资源类型 填”24″->确定后。再把资源的ID改为”IDR_MANIFEST”
然后在String Table中添加IDR_MANIFEST,值为1

重新生成编译运行。

文章是转载过来的,没高清来源!

写在博客空间到期之前

前两天在删除垃圾邮件的时候看到了这个博客的空间提供商发给我的邮件,邮件上说,我的博客到3月30日日就到期了。工作之后一直都没什么时间来打理博客,我只好等到周末晚上抽空把博客搬迁到新的空间去。目前还没有租好空间,如果你认识好的空间提供商,不妨介绍一下吧。

工作上的笔记一般都发到印象笔记中,平时拍的照片也只是发到lofter上去,所以,博客就没怎么更新。我已经来这边工作了一阵子了,感觉能力上进步不是很大。我做需求总是做得很慢,之前是因为写代码的速度太慢了,后来写代码的速度加快了,但是做需求的速度还是那样,原因是我调试代码和自测的时间比以前久了。之所以如此,是因为很容易犯错的我怕犯错,所以我在编写程序的时候不得不反复调试,可是即便如此,我的提测的代码还是偶尔会爆出一些BUG。

我觉得,无论做什么行业“快速提升”自己都是一种能力,注意,这里所说的是“快速”提升,不是“提升”,“快速”才是重点,“提升”只是用来修饰这个“快速”。很显然,我目前很缺乏“快速提升”自己的能力。我最近也在反思我为什么缺乏这种能力,并希望自己今后能在工作和生活的方方面面都有一个提升!加油!

Win32 api使用双缓冲绘图

写下这段代码,用作备忘,其中的CLIENT_WIDTH、RGH_WITHE、RGB_SEAGREEN是我自己定义的宏。

case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            HDC hCompDc = ::CreateCompatibleDC(hdc);
            HBITMAP hBitmap = ::CreateCompatibleBitmap(hdc, CLIENT_WIDTH, CLIENT_HEIGHT);
            SelectObject(hCompDc, hBitmap);

            RECT rect = {0};
            GetClientRect(hWnd, &rect);

            HBRUSH hBkBrush = (HBRUSH)::CreateSolidBrush(RGB_WHITE);
            FillRect(hCompDc, &rect, hBkBrush);

            HPEN hPen = ::CreatePen(PS_SOLID, GRID_LINE_WIDTH, RGB_SEAGREEN);
            SelectObject(hCompDc, hPen);

            PaintMap(hCompDc);

            BitBlt(hdc, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT, hCompDc, 0, 0, SRCCOPY);

            if (hCompDc)
            {
                DeleteDC(hCompDc);
            }

            if (hBitmap)
            {
                DeleteObject(hBitmap);
            }
            if (hBkBrush)
            {
                DeleteObject(hBkBrush);
            }
            if (hPen)
            {
                DeleteObject(hPen);
            }

            EndPaint(hWnd, &ps);
        }
        break;

SetUnhandledExceptionFilter设置处理异常函数.

SetUnhandleExceptionFilter函数

Windows平台下的C++程序异常通常可分为两种:结构化异常(Structured Exception,可以理解为与操作系统相关的异常)和C++异常。对于结构化异常处理(SEH),可以找到很多资料,在此不细说。对于crash错 误,一般由未被正常捕获的异常引起,Windows操作系统提供了一个API函数可以在程序crash之前有机会处理这些异常,就是 SetUnhandleExceptionFilter函数。(C++也有一个类似函数set_terminate可以处理未被捕获的C++异常。)

SetUnhandleExceptionFilter函数声明如下:

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
    LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
    );
    //其中 LPTOP_LEVEL_EXCEPTION_FILTER 定义如下:

typedef LONG (WINAPI *PTOP_LEVEL_EXCEPTION_FILTER)(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    );

typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER;

简单来说,SetUnhandleExceptionFilter允许我们设置一个自己的函数作为全局SEH过滤函数,当程序crash前会调用我们的函 数进行处理。我们可以利用的是 _EXCEPTION_POINTERS 结构类型的变量ExceptionInfo,它包含了对异常的描述以及发生异常的线程状态,过滤函数可以通过返回不同的值来让系统继续运行或退出应用程 序。
关于 SetUnhandleExceptionFilter 函数的具体用法和示例请参考MSDN。

转载自http://blog.sina.com.cn/s/blog_648d306d0100qmca.html

利用模板实现多态性

今天早上我在看《MFC程序员的WTL指南》,其中开篇就有讲到一个例子,里面有一段这样的代码:

template <class T>
class B1
{
public:
    void SayHi()
    {
        T* pT = static_cast<t*>(this);
        pT->PrintClassName();
    }
protected:
    void PrintClassName() { cout << "This is B1"; }
};

class D1 : public B1<d1>
{
    // No overridden functions at all
};

class D2 : public B1<d2>
{
protected:
    void PrintClassName() { cout << "This is D2"; }
};

在D1中,由于没有重写任何函数,因此当B1中的this指针被转成D1指针的时候,pT->PrintClassName();将调用基类中的PrintClassName();函数,
在D2中,PrintClassName();被重写,因此 pT->PrintClassName();将会调用被重写后的PrintClassName();函数

在类和继承比较多的情况下,这样可以节省不少内存。

【Windows编程基础】设置SeDebugPrivilege提升进程权限

在openprocess的时候,如果需要全部权限,是需要SeDebugPrivilege privilege的。以下我写的代码,以后可能常常用到,这里贴出来,以后直接从这里复制吧!

BOOL EnableDebugPrivilege()
{
    HANDLE              hToken = NULL;
    LUID                Luid = {0};
    TOKEN_PRIVILEGES    tp = {0};

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
    {
        return FALSE;
    }
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Luid))
    {
        CloseHandle(hToken);
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = Luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL))
    {
        CloseHandle(hToken);
        return FALSE;
    }
    return TRUE;
}

设置进程特权大概就三个步骤:
第一步:查询特权的名字
LUID Luid = {0};
LookupPrivilegeValue(NULL, szPrivName, Luid);

第二部:打开进程令牌
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES|TOKE_QUERY, &hToken);

第三部:调整特权
AdjustTokenPrivileges(hToken…);

VS2005设置程序必须以管理员权限运行

公司目前使用的VS2005作为开发环境。而前不久,我需要编写一个demo,该demo在Vista以上的系统上必须以管理员权限运行。而VS2005是一款比较老的编译器,刚发布那时,Windows还不支持UAC。所以要通过一些设置才能让VS2005编译出来的程序出现“小盾牌”

exe_with_uac

方法如下:
①:在工程的目录下创建一个mani.xml文件,文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
      <ms_asmv2:security>
        <ms_asmv3:requestedPrivileges xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
          <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
        </ms_asmv3:requestedPrivileges>
      </ms_asmv2:security>
    </ms_asmv2:trustInfo>
</assembly>

②打开工程的属性(Properties)“Manifest Tools” ==> “Input and Output” ==> “Additional Manifest File” 设置成刚刚创建的xml文件:“./mani.xml”

编译之后就可以看到生成的exe图标下的小盾牌了。

编译的过程中可能会产生一条这样的警告:

.mani.xml : manifest authoring warning 81010002: Unrecognized Element "requestedPrivileges" in namespace "urn:schemas-microsoft-com:asm.v3".