擷取掃描器圖片-TWAIN協議

來源:互聯網
上載者:User

原始碼(串連另存新檔方式下載,重新命名為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;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.