获取扫描仪图片-TWAIN协议

源代码(连接另存为方式下载,重命名为zip文件再解压就可以到到源文件了)

下载链接http://hi.csdn.net/attachment/201107/19/0_1311044325WNjx.gif


请先到twain官方网站下载twain32头文件定义。


BOOL SaveBitmap(HGLOBAL _hDIB, const int serial_number){ 
    BITMAPFILEHEADER bfh = {0};
    BITMAPINFOHEADER *pBIH = NULL;
    HANDLE hf = NULL;
    
    // 获取临时文件
    char _szTempFile [MAX_PATH] = {0};
    char _szTempDir [MAX_PATH] = {0};
    srand(GetTickCount());
    GetTempPathA(sizeof(_szTempDir), _szTempDir);
    
    sprintf_s(_szTempFile
            , sizeof(_szTempFile)
            , "%s//%d-%d.bmp"
            , _szTempDir
            , serial_number
            , rand());
            
    hf = CreateFileA(_szTempFile
            , GENERIC_WRITE
            , 0
            , NULL
            , CREATE_ALWAYS
            , FILE_ATTRIBUTE_NORMAL
            , NULL);

    if(hf == INVALID_HANDLE_VALUE) 
        GlobalFree(_hDIB);
        return FALSE;

    // 解析成位图文件头
    pBIH = (BITMAPINFOHEADER*)GlobalLock(_hDIB);

    DWORD dwBytesWritten = 0l;
    bfh.bfType = ( (WORD) ('M' << 8) | 'B');

    bfh.bfSize = sizeof(BITMAPFILEHEADER) 
        + sizeof(BITMAPINFOHEADER) 
        +((((pBIH->biWidth*pBIH->biBitCount+31)/32)*4)*pBIH->biHeight)
        + pBIH->biClrUsed * sizeof(RGBQUAD);
    bfh.bfReserved1 = 0;

    bfh.bfReserved2 = 0;

    bfh.bfOffBits = sizeof(BITMAPFILEHEADER) 
                + sizeof(BITMAPINFOHEADER) 
                + pBIH->biClrUsed * sizeof(RGBQUAD);
    
    // 写入位图到文件
    WriteFile(hf
            , &bfh
            , sizeof(BITMAPFILEHEADER)
            , &dwBytesWritten
            , NULL);
    WriteFile(hf
            , pBIH
            , bfh.bfSize-sizeof(BITMAPFILEHEADER)
            , &dwBytesWritten
            , NULL);
    CloseHandle(hf);hf=INVALID_HANDLE_VALUE;
    TRACE("save bitmap to:");TRACE(_szTempFile);
    
    GlobalUnlock(_hDIB);
    GlobalFree(_hDIB);
    return TRUE;
}

unsigned long __stdcall ScanThread(void * args)
{ 
    HWND _hWnd = NULL;
    MSG _msg = {0};
    HMODULE _hDSM = NULL;
    HBITMAP _hBitmap = NULL;
    int _nCount = 0;
    TW_CAPABILITY _cap = {0};
    TW_UINT16 _twRC = TWRC_FAILURE;
    pTW_ENUMERATION _pEnumeration = NULL;
    pTW_ONEVALUE _pOneValue = NULL;
    TW_EVENT _twEvent = {0};
    TW_IDENTITY _dsid = {0};
    TW_USERINTERFACE _twUI = {0};
    TW_PENDINGXFERS _twPendingXfer = {0};
    TW_UINT16 _ModeType = -1;
    TW_UINT32 _index = 0;    
    TW_IDENTITY _dsmid = { 
        0,     
        { 1, 703, TWLG_USA, TWCY_USA, "twain-1.7.0.3" },
        1,
        7, 
        (DG_IMAGE | DG_CONTROL), 
        "xxxx IT Corp. Ltd.", 
        "xxxx webctrl", "wuzh1230" 
    }; 

    // 初始化 
    _hDSM = LoadLibraryA("TWAIN_32.DLL");

    // 获取接口指针
    DSMENTRYPROC _pDSMEntryProc = (DSMENTRYPROC)
                    GetProcAddress(_hDSM, "DSM_Entry");

    // 创建窗口,利用窗口的消息循环收取位图
    _hWnd = CreateWindowExA(0
                , "#32770"
                , "Scan Client"
                , WS_OVERLAPPEDWINDOW
                , 0, 0, 1, 1
                , NULL
                , NULL
                , GetModuleHandleA(0)
                , NULL);

    // 打开数据源管理器 
    _twRC = CallDSMEntry(&_dsmid
                    , NULL
                    , DG_CONTROL
                    , DAT_PARENT
                    , MSG_OPENDSM
                    , (TW_MEMREF)&_hWnd);

    // 选择数据源 
    _twRC = CallDSMEntry(&_dsmid
                    , NULL
                    , DG_CONTROL
                    , DAT_IDENTITY
                    , MSG_GETDEFAULT
                    , (TW_MEMREF)&_dsid);

    _twRC = CallDSMEntry(&_dsmid
                    , NULL
                    , DG_CONTROL
                    , DAT_IDENTITY
                    , MSG_USERSELECT
                    , (TW_MEMREF)&_dsid);

    // 打开数据源 
    _twRC = CallDSMEntry(&_dsmid
                    , NULL
                    , DG_CONTROL
                    , DAT_IDENTITY
                    , MSG_OPENDS
                    , &_dsid);

    // 读取并设置传输模式ICAP_XFERMECH 
    memset(&_cap, 0, sizeof(TW_CAPABILITY));
    _cap.Cap = ICAP_XFERMECH;
    _cap.ConType = TWON_ENUMERATION;
    _twRC = CallDSMEntry(&_dsmid
                    , &_dsid
                    , DG_CONTROL
                    , DAT_CAPABILITY
                    , MSG_GET
                    , (TW_MEMREF)&_cap);
                    
    _pEnumeration = (pTW_ENUMERATION)GlobalLock(_cap.hContainer);

    // 搜索native模式的索引
    for (_index = 0; _index < _pEnumeration->NumItems; _index++) 
    { 
        if (((TW_UINT16*)_pEnumeration->ItemList)[_index] == TWSX_NATIVE) 
        { break;}
    }
    // 没有搜索到native模式的索引
    if (_index == _pEnumeration->NumItems)
    {    
        goto end_of_function;
    }
    // 如果当前索引位置的模式已经是NATIVE
    if (_index == _pEnumeration->CurrentIndex) 
    { 
        TRACE("Current xfer mode is 'native(TWSX_NATIVE)'");
        _ModeType = TWSX_NATIVE;
        GlobalUnlock(_cap.hContainer);
        GlobalFree(_cap.hContainer);
    } 
    else 
    { 
        TRACE("Current Mode is not 'native(TWSX_NATIVE)'");
        
        // 设置native模式, _index是搜索到的native模式的索引
        _pEnumeration->CurrentIndex = _index; 
        _pEnumeration->DefaultIndex = _index;
        GlobalUnlock(_cap.hContainer);
        _twRC = CallDSMEntry(&_dsmid
                        , &_dsid
                        , DG_CONTROL
                        , DAT_CAPABILITY
                        , MSG_SET
                        , (TW_MEMREF)&_cap);
        
        if (_twRC != TWRC_SUCCESS) 
        { 
            TRACE("Failed to set xfer mode to 'native(TWSX_NATIVE)'");
            goto end_of_function;
        }
        GlobalFree(_cap.hContainer);
        
        // 再次读取模式
        _twRC = CallDSMEntry(&_dsmid
                            , &_dsid
                            , DG_CONTROL
                            , DAT_CAPABILITY
                            , MSG_GET
                            , (TW_MEMREF)&_cap);
        if (_twRC != TWRC_SUCCESS) 
        { 
            TRACE("Failed to read back xfer mode.");
            goto end_of_function;
        }
        _pEnumeration = (pTW_ENUMERATION)GlobalLock(_cap.hContainer);
        // 读取
        _ModeType = ((TW_UINT16*)
                    _pEnumeration->ItemList)[_pEnumeration->CurrentIndex];
        GlobalUnlock(_cap.hContainer);
        GlobalFree(_cap.hContainer);

        // 检查模式是否是native
        if (_ModeType != TWSX_NATIVE) 
        { 
            TRACE("xfer mode NOT 'native(TWSX_NATIVE)',quit.");
            goto end_of_function;
        } 
    }
 
    TRACE("Current xfer mode is 'native(TWSX_NATIVE)'");
 
    // 读取送纸参数CAP_FEEDERENABLED 
    TRACE("Read capability 'feed enabled(CAP_FEEDERENABLED)'.");

    memset(&_cap, 0, sizeof(TW_CAPABILITY));
    _cap.Cap = CAP_FEEDERENABLED;
    _cap.ConType = TWON_ONEVALUE;
    _twRC = CallDSMEntry(&_dsmid
                    , &_dsid
                    , DG_CONTROL
                    , DAT_CAPABILITY
                    , MSG_GET
                    , (TW_MEMREF)&_cap);
    GlobalFree(_cap.hContainer);
    // 读取自动喂纸设备失败,可能是没有硬件支持
    if (_twRC != TWRC_SUCCESS) 
    { 
        TRACE("Failed to read 'feed enabled(CAP_FEEDERENABLED)'");
        TRACE("[possiblly NO this hardware.].");
        if (FEED_ENABLED) 
        { 
            TRACE("NO Hardware to support feed, so Unable to set, quit.");
            goto end_of_function;
        }
    }
    else 
    {
        // 有送纸硬件 
        TRACE("OK to read 'feed enabled(CAP_FEEDERENABLED)'");
        TRACE("[Hardware present].");
        
        // 先检查是否启用了 
        memset(&_cap, 0, sizeof(TW_CAPABILITY));
        _cap.Cap = CAP_FEEDERENABLED;
        _cap.ConType = TWON_ONEVALUE;
        _twRC = CallDSMEntry(&_dsmid
                        , &_dsid
                        , DG_CONTROL
                        , DAT_CAPABILITY
                        , MSG_GET
                        , (TW_MEMREF)&_cap);
                        
        if (_twRC != TWRC_SUCCESS) 
        { 
            TRACE("Failed to set 'feed enabled(CAP_FEEDERENABLED)'");
            GlobalFree(_cap.hContainer);
            goto end_of_function;
        }
        
        _pOneValue = (pTW_ONEVALUE)GlobalLock(_cap.hContainer);
        // 如果已经启用了
        if (_pOneValue->Item == FEED_ENABLED) 
        { 
            TRACE("[feeder enabled(CAP_FEEDERENABLED)] is same as parameter")
            GlobalUnlock(_cap.hContainer);
            GlobalFree(_cap.hContainer);
        }
        // 没有启用,启用喂纸设备    
        else 
        { 
             _pOneValue->Item = FEED_ENABLED;
            GlobalUnlock(_cap.hContainer);
            _twRC = CallDSMEntry(&_dsmid
                            , &_dsid
                            , DG_CONTROL
                            , DAT_CAPABILITY
                            , MSG_SET
                            , (TW_MEMREF)&_cap);
            GlobalFree(_cap.hContainer);
            if (_twRC != TWRC_SUCCESS) 
            {
                TRACE("Faile to set [feeder enabled(CAP_FEEDERENABLED)]");
                goto end_of_function;
            }
        }
        
        // 再次读取,检查是否设置成功
        memset(&_cap, 0, sizeof(TW_CAPABILITY));
        _cap.Cap = CAP_FEEDERENABLED;
        _cap.ConType = TWON_ONEVALUE;
        _twRC = CallDSMEntry(&_dsmid
                            , &_dsid
                            , DG_CONTROL
                            , DAT_CAPABILITY
                            , MSG_GET
                            , (TW_MEMREF)&_cap);
        if (_twRC != TWRC_SUCCESS) 
        { 
            GlobalFree(_cap.hContainer);
            TRACE("Failed to read [feeder enabled(CAP_FEEDERENABLED)]");
            goto end_of_function;
        }
        _pOneValue = (pTW_ONEVALUE)GlobalLock(_cap.hContainer);
        GlobalUnlock(_cap.hContainer);
        GlobalFree(_cap.hContainer);
        
        // 设置成功
        TRACE("OK to read [feed enabled(CAP_FEEDERENABLED)]");    
        
    #if 0 
        // 启用送纸:read 
        memset(&_cap, 0, sizeof(TW_CAPABILITY));
         _cap.Cap = CAP_AUTOFEED;
         _cap.ConType = TWON_ONEVALUE;
         _twRC = CallDSMEntry(&_dsmid
                            , &_dsid
                            , DG_CONTROL
                            , DAT_CAPABILITY
                            , MSG_GET
                            , (TW_MEMREF)&_cap);
         if (_twRC != TWRC_SUCCESS) 
         { 
             GlobalFree(_cap.hContainer);
             TRACE("设置'自动送纸(CAP_AUTOFEED)'失败");
             goto end_of_function;
         }
     
        // 如果已经启用送纸 
        _pOneValue = (pTW_ONEVALUE)GlobalLock(_cap.hContainer);
         if (_pOneValue->Item == AUTOFEED_ENABLED) 
         { 
             GlobalUnlock(_cap.hContainer);
             GlobalFree(_cap.hContainer);
         }
         // 没有启用,设置
         else 
         {
             _pOneValue->Item = AUTOFEED_ENABLED;
             GlobalUnlock(_cap.hContainer);
             _twRC = CallDSMEntry(&_dsmid
                            , &_dsid
                            , DG_CONTROL
                            , DAT_CAPABILITY
                            , MSG_SET
                            , (TW_MEMREF)&_cap);
             GlobalFree(_cap.hContainer);
             if (_twRC != TWRC_SUCCESS) 
             { 
                 TRACE("设置'自动送纸(CAP_AUTOFEED)'失败");
                 goto end_of_function;
             }
         }
         
        // 再次读取,检查是否成功启用送纸
        memset(&_cap, 0, sizeof(TW_CAPABILITY));
        _cap.Cap = CAP_AUTOFEED;
        _cap.ConType = TWON_ONEVALUE;
        _twRC = CallDSMEntry(&_dsmid
                        , &_dsid
                        , DG_CONTROL
                        , DAT_CAPABILITY
                        , MSG_GET
                        , (TW_MEMREF)&_cap);
        if (_twRC != TWRC_SUCCESS) 
        {
            GlobalFree(_cap.hContainer);
            TRACE("设置'自动送纸(CAP_AUTOFEED)'失败");
            goto end_of_function;
        }
        _pOneValue = (pTW_ONEVALUE)GlobalLock(_cap.hContainer);
        GlobalUnlock(_cap.hContainer);
        GlobalFree(_cap.hContainer);
        
        // 设置成功
        TRACE("设置'自动送纸(CAP_AUTOFEED)'成功");
    #endif 
    }

    // 显示界面,扫描 
    _twUI.hParent = GetActiveWindow();
    _twUI.ShowUI = TRUE;
    _twRC = CallDSMEntry(&_dsmid
                    , &_dsid
                    , DG_CONTROL
                    , DAT_USERINTERFACE
                    , MSG_ENABLEDS
                    , (TW_MEMREF)&_twUI);
    if (_twRC != TWRC_SUCCESS) 
    { 
        TRACE("Faile to enable UI.");
        goto end_of_function;
    }

    // 消息循环 
    _twEvent.pEvent = (TW_MEMREF)&_msg;
     while (GetMessage(&_msg, NULL, 0, 0)) 
     {
        _twRC = TWRC_FAILURE;
        _twEvent.TWMessage = -1;
        _twRC = CallDSMEntry(&_dsmid
                        , &_dsid
                        , DG_CONTROL
                        , DAT_EVENT
                        , MSG_PROCESSEVENT
                        , (TW_MEMREF)&_twEvent);
        if (_twRC == TWRC_FAILURE || _twEvent.TWMessage == -1) 
        { 
            TRACE("Failed to get message.");
            goto end_of_function;
        }

        // 不是数据源发送过来的消息,交给窗口默认处理
        if (_twRC == TWRC_NOTDSEVENT) 
        { 
            TranslateMessage(&_msg);
            DispatchMessage(&_msg);
            continue;
        }
        
        // 处理数据源发送来的消息
        switch (_twEvent.TWMessage) 
        { 
            // 位图在扫描仪内就绪了
            case MSG_XFERREADY: 
            { 
                // 循环接受每一张位图
                memset(&_twPendingXfer, 0, sizeof(TW_PENDINGXFERS));
                do {
                    _hBitmap = NULL;
                    // 接受一张位图
                    _twRC = CallDSMEntry(&_dsmid
                                    , &_dsid
                                    , DG_IMAGE
                                    , DAT_IMAGENATIVEXFER
                                    , MSG_GET
                                    , (TW_MEMREF)&_hBitmap);
                    switch (_twRC) 
                    { 
                        case TWRC_XFERDONE: // 传输完成,保存位图                 
                        { 
                            TRACE("xfer is done.(TWRC_XFERDONE)");
                            if (SaveBitmap((HGLOBAL)_hBitmap, _nCount++)) 
                            { 
                                TRACE("OK to save bitmap to file.");
                            }
                            else 
                            { 
                                TRACE("Failed to save bitmap to file.");
                            }
                            TRACE("send endxfer[MSG_ENDXFER] message.");
                            _twRC = CallDSMEntry(&_dsmid
                                            , &_dsid
                                            , DG_CONTROL
                                            , DAT_PENDINGXFERS
                                            , MSG_ENDXFER
                                            , (TW_MEMREF)&_twPendingXfer);
                        }break;
                        case TWRC_CANCEL:    // 取消
                        case TWRC_FAILURE:     // 失败
                        default:                         
                        { 
                            //    结束位图传输
                            TRACE("User canceld(TWRC_CANCEL),");
                            TRACE("or xfer failed(TWRC_FAILURE).");
                            _twRC = CallDSMEntry(&_dsmid
                                            , &_dsid
                                            , DG_CONTROL
                                            , DAT_PENDINGXFERS
                                            , MSG_ENDXFER
                                            , (TW_MEMREF)&_twPendingXfer);
                            TRACE("send endxfer message.");
                        }break;
                    }
                }while (_twPendingXfer.Count != 0); // 如果有多张位图
            }break;

            
            case MSG_CLOSEDSREQ:     // 关闭数据源请求
            case MSG_CLOSEDSOK:      // 数据源成功关闭
            case MSG_NULL:          // 空消息            
                TRACE("MSG_CLOSEDSREQ or MSG_CLOSEDSOK or MSG_NULL)");
            default: break;            // 忽略
        }        
        
        // 如果是关闭请求,就退出外层循环
        if (_twEvent.TWMessage != MSG_NULL) 
        { 
            TRACE("Break up from Message loop.");
            break;
        }
     }
     
end_of_function: 

    TRACE("Start to cleanup resources of thread.");
     
    // 关闭用户界面 
     memset(&_twUI, 0, sizeof(TW_USERINTERFACE));
     _twUI.hParent = _hWnd;
     _twUI.ShowUI = TWON_DONTCARE8;
     _twRC = CallDSMEntry(&_dsmid
                 , &_dsid
                 , DG_CONTROL
                 , DAT_USERINTERFACE
                 , MSG_DISABLEDS
                 , (TW_MEMREF)&_twUI);
     
    // 关闭数据源 
     _twRC = CallDSMEntry(&_dsmid
                        , NULL
                        , DG_CONTROL
                        , DAT_IDENTITY
                        , MSG_CLOSEDS
                        , &_dsid);

    // 关闭数据源管理器 
     _twRC = CallDSMEntry(&_dsmid
                        , NULL
                        , DG_CONTROL
                        , DAT_PARENT
                        , MSG_CLOSEDSM
                        , &_hWnd);

    // 关闭窗口 
    DestroyWindow(_hWnd);

    // 释放管理库 
     FreeLibrary(_hDSM);
     
     return 0;
}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值