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

概要
スキャンするアプリケーションのメニューには、”デバイスの選択”のようなメニューがあります。
ここから以下のようなダイアログが表示されて、スキャンするドライバを選択することができます。
まず、このダイアログが表示されるようにします。

ソース
とりあえず、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