デバイスの選択をできるようにする

概要

スキャンするアプリケーションのメニューには、”デバイスの選択”のようなメニューがあります。

ここから以下のようなダイアログが表示されて、スキャンするドライバを選択することができます。

まず、このダイアログが表示されるようにします。

 

ソース

とりあえず、VCのウィザードでEXEのプロジェクトを作ります。

今回はMFCのEXEで、SDIで作ってみました。(特に深くは考えずに・・・。)

また、Twain.hをダウンロードしてきて、プロジェクトに追加します。

 

まず、TWAIN_32.DLLをロードします。

TWAIN_32.DLLは、スキャナのドライバをインストールすればWindowsディレクトリに入っているはずです。

(ないとスキャンできないので。)

TWAIN_32.DLLがない場合には、自分でダウンロードしてきてコピーしてください。

 

State 1 to  2 

BOOL CScanApp::LoadDSM()
{
    CString strSMDir;
    CFileFind filefind;

    ::GetWindowsDirectory(strSMDir.GetBuffer(MAX_PATH),MAX_PATH);//sizeof(szSMDir));
    strSMDir.ReleaseBuffer();
    if(strSMDir.Right(1) != _T("\\")){
        strSMDir += _T("\\");
    }
    strSMDir += _T("TWAIN_32.DLL");
    if(filefind.FindFile(strSMDir)){ //TWAIN_32.DLLあり
        m_hDSMDLL = ::LoadLibrary("TWAIN_32.DLL");
        if(m_hDSMDLL != NULL){ //DLLのロードに成功    
            m_pDSM_ENTRY = (DSMENTRYPROC)::GetProcAddress(m_hDSMDLL,MAKEINTRESOURCE(1));
            if(m_pDSM_ENTRY == NULL){
                return FALSE;
            }
        }
        else{ //DLLのロードに失敗
            ::MessageBox(NULL,_T("TWAIN_32.DLLのロードに失敗しました。"),_T("エラー"),MB_OK|MB_ICONSTOP);
            return FALSE;
        }
    }
    else{ //TWAIN_32.DLLがない
        ::MessageBox(NULL,_T("TWAIN_32.DLLがインストールされていません。\nTWAIN_32.DLLをインストールしてください。"),_T("エラー"),MB_OK|MB_ICONSTOP);
        return FALSE;
    }

    return TRUE;
}

この関数の戻り値がFALSEだった場合には、メニューの”デバイスの選択”をグレーアウトして無効にするようにしましょう。

 

State 2 to  3

次に、ソースマネージャーをOPENします。

BOOL CScanApp::OpenDSM()
{
    m_AppID.Id = 0;
    m_AppID.Version.MajorNum = 1;
    m_AppID.Version.MinorNum = 0;
    m_AppID.Version.Language = TWLG_JAPANESE;
    m_AppID.Version.Country = TWCY_JAPAN;
    lstrcpy(m_AppID.Version.Info,_T("Scanning Program"));
    m_AppID.ProtocolMajor = TWON_PROTOCOLMAJOR;
    m_AppID.ProtocolMinor = TWON_PROTOCOLMINOR;
    m_AppID.SupportedGroups = DG_IMAGE | DG_CONTROL;
    lstrcpy(m_AppID.Manufacturer,_T("M&M"));
    lstrcpy(m_AppID.ProductFamily,_T("Twain 1.9"));
    lstrcpy(m_AppID.ProductName,_T("Test Scanning Program"));

    TW_UINT16 rc;
    rc = (*m_pDSM_ENTRY)(&m_AppID,NULL,DG_CONTROL,DAT_PARENT,MSG_OPENDSM,(TW_MEMREF)&m_pMainWnd->m_hWnd);

    return TRUE;
}

TW_IDENTITY構造体を適当にいぢくって、DG_CONTROL/DAT_PARENT/MSG_OPENDSMを呼びます。

関数のリターンコードを見た方が良いのでしょうが、面倒なのでとりあえず成功するものとしちゃいます。

ホントは失敗したら、メニューの”デバイスの選択”をグレーアウトして無効にするようにしましょう。

 

以上の2つの関数は、InitInstanceから呼べば良い感じでしょう。

ExitInstanceでTWAIN_32.DLLを解放するようにします。

int CScanApp::ExitInstance() 
{
    // TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
    //TWAIN_32.DLLの解放
    if(m_hDSMDLL != NULL){
        ::FreeLibrary(m_hDSMDLL);
    }

    return CWinApp::ExitInstance();
}

 

State 3

メニューの”デバイスの選択”を選択したときの、メッセージハンドらを実装します。

void CMainFrame::OnSelectSource() 
{
    // TODO: この位置にコマンド ハンドラ用のコードを追加してください
    TW_UINT16 twRC;
    TW_IDENTITY NewDSIdentity;

    memset(&NewDSIdentity, 0, sizeof(TW_IDENTITY));

    //Defaultを取得
    twRC = (*theApp.m_pDSM_ENTRY)(&theApp.m_AppID,
    NULL,
    DG_CONTROL,
    DAT_IDENTITY,
    MSG_GETDEFAULT,
    (TW_MEMREF)&NewDSIdentity);

    //DSの選択ダイアログを表示
    twRC = (*theApp.m_pDSM_ENTRY)(&theApp.m_AppID,
    NULL,
    DG_CONTROL,
    DAT_IDENTITY,
    MSG_USERSELECT,
    (TW_MEMREF)&NewDSIdentity);

    switch (twRC)
    {
    case TWRC_SUCCESS:
        theApp.m_DSID = NewDSIdentity;
        break;
    case TWRC_CANCEL:
        break;
    case TWRC_FAILURE: 
    default:
        break;
    }
}

DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULTでデフォルトの設定を取得します。

以前に選択されたドライバを、デフォルトとして選択状態にして表示するためです。

DG_CONTROL/ DAT_IDENTITY/MSG_USERSELECTでドライバを選択するダイアログを表示します。

ドライバの選択ダイアログでOKボタンが押されたら、TW_IDENTITYをコピーして保存しておきます。

ホントは関数のリターンコードがTWRC_SUCCESS以外の場合も、ちゃんと処理したほうが良いでしょうがはしょります。

 

ここまでで、とりあえずドライバの選択ができるようになります。

Last Update:2000/08/20