mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
999 lines
36 KiB
999 lines
36 KiB
/***************************************************************************
|
|
DC_SCAN.C
|
|
|
|
Purpose: TWAIN Scanner Support Code for O/i Client, provides the open
|
|
and close for TWAIN devices to provide the look and feel of
|
|
a handler interface.
|
|
|
|
$Log: S:\products\wangview\oiwh\scanlib\dc_scan.c_v $
|
|
*
|
|
* Rev 1.11 08 Apr 1996 14:58:42 BG
|
|
* Modified buffer size of app title to go from 81 chars to 281 chars
|
|
* to close bug #5609. If long filename, app name being lost.
|
|
*
|
|
* Rev 1.10 08 Apr 1996 11:38:14 BG
|
|
* If the app flags request no data source UI, call ImgGetScanOpts() to send
|
|
* the saved scanner options to the data source. If the UI is requested,
|
|
* as in the Wang Viewer, do not call the API to set these options. This
|
|
* exhibits bad behavior in the HP data sources when their UI is displayed.
|
|
*
|
|
* Rev 1.9 21 Mar 1996 13:21:44 BG
|
|
* In IMGCloseScanner(), do not Disable the data source. If the EnableDS call
|
|
* fails, this Disable call can cause problems. Besides, the DS is always
|
|
* Disabled in IMGTwainScanPages().
|
|
*
|
|
* Rev 1.8 12 Mar 1996 11:25:50 BG
|
|
* If a data source fails to be Enabled, set a flag so on close
|
|
* it is not attempted to be Closed, where an exception may occur.
|
|
*
|
|
* Rev 1.7 22 Feb 1996 13:15:00 BG
|
|
* Set TWAIN flag ShowUI based on input from Flags. This will show
|
|
* the data source UI or not. Also, when ImgTWAINProcessDCMesImgTWAINScanPages()
|
|
* lets try that again:
|
|
* When IMGTWAINProcessDCMessage() is called in IMGTWAINScanPages(), added
|
|
* LPTWPAGE and LPSCANDATA parms so OITWAIN.DLL can do the filing.
|
|
*
|
|
* Rev 1.5 14 Sep 1995 18:59:20 KFS
|
|
* Product Name for Image Vue application not being updated due to the app
|
|
* window not being found, and second the new format of the caption for windows
|
|
* 95. File before Application Title. This will not work for old win31 title
|
|
* format correctly.
|
|
*
|
|
* Rev 1.4 13 Sep 1995 18:10:24 KFS
|
|
* Found the close and reopen had a problem, close deleted the product name,
|
|
* which on the open we get the default product, not the one working on, a next
|
|
* scan would use the default scanner, very strange. Need to save productname
|
|
* and restore it for the open in struct ID.
|
|
*
|
|
* Rev 1.3 08 Sep 1995 14:24:08 BG
|
|
* Modified CreateTWAINScannerWindow() to use the correct
|
|
* scanner icon instead of the default Window's icon. Also
|
|
* removed the min and max buttons from this window. They
|
|
* were grayed out anyway.
|
|
*
|
|
*
|
|
* Rev 1.2 05 Sep 1995 18:42:08 KFS
|
|
* Showing the UI could happen when scanning also, so need to make sure spec
|
|
* satisfied in closing the data source when the UI is used. Two conditions
|
|
* this could happen at present. When we know a ds doesn't work with the UI not
|
|
* present as the patch for logitech camera, and if status on Enable comes back
|
|
* with CHECKSTATUS. This tells the code the UI will be up even if not
|
|
* requested.
|
|
*
|
|
* Rev 1.1 22 Aug 1995 18:10:46 KFS
|
|
* Make call to findwin() to see if TWUNK_16.exe is running, if so use window
|
|
* returned which matches the classname TWAIN TWUNK_16 to set it to the top of
|
|
* the z order so scanner UI boxes will be on top.
|
|
*
|
|
* Rev 1.0 20 Jul 1995 14:37:02 KFS
|
|
* Initial entry
|
|
*
|
|
* Rev 1.2 20 Jan 1995 13:51:06 KFS
|
|
* 1. added function so scanseq can call it so no direct calls to oitwain.dll,
|
|
* so link of scanseq.dll not necessary.
|
|
* 2. eliminate 2nd call to disable the source module if done during the scan or
|
|
* scan setup.
|
|
*
|
|
* Rev 1.1 22 Aug 1994 15:45:08 KFS
|
|
* No code changes, added vlog comments to file
|
|
*
|
|
|
|
****************************************************************************/
|
|
/*
|
|
Copyright (C) '92-'93 Wang Laboratories, Inc.:
|
|
All rights reserved.
|
|
|
|
Author: Ken Spina
|
|
Project: TWAIN Scanner Support in O/i Client
|
|
Module: DC_SCAN.H - Include file for dc_scan.c
|
|
|
|
History of Revisions:
|
|
|
|
REV# INITIALS DATE CHANGES
|
|
|
|
1 kfs 09/02/92 Created TwainOpenScanner()
|
|
2 kfs 12/15/92 Added Icon Window to TwainOpenScanner()
|
|
3 kfs 6/04/93 Made it part of scanlib so it would build
|
|
4 kfs 6/07/93 Minor revision to work with WMAKE
|
|
5 kfs 8/04/93 added AppID constants to resoucre file and
|
|
ProductName for AppID comes from Caption
|
|
so can put it up during transfer as
|
|
Deskscan
|
|
6 kfs 8/13/93 can terminate TwainOpenScanner with cancel
|
|
from select box, before continued with the
|
|
default value, eliminated commented out
|
|
code and made sure the window came back to
|
|
the prev. active window on cancel
|
|
7 kfs 9/14/93 took out deleteobject for brushes, may be
|
|
cause of fatal exit message
|
|
|
|
*/
|
|
#include "pvundef.h"
|
|
#ifdef NO_SCANUI_SCANSEQ
|
|
#define IMG_SJF_DISPLAY 0x0010
|
|
#define IMG_SJF_DISP_2ND_SIDE 0x2000
|
|
#define IMG_SJF_CAPTION 0x0040
|
|
#define IMG_SJF_SCROLL 0x0080
|
|
#define IMG_SJF_FILE 0x4000
|
|
#endif
|
|
|
|
#define DEBUG // Show errors that result from application
|
|
// calls to Source Manager
|
|
|
|
#define MAX_RESOURCE_CHAR 281
|
|
#define IMG_SJF_DISP_BOTH (IMG_SJF_DISPLAY | IMG_SJF_DISP_2ND_SIDE)
|
|
#define DI_DONT_KNOW -1 /* displayed image -- don't know status */
|
|
#define DI_NO_IMAGE 0 /* displayed image -- no image exists */
|
|
#define DI_IMAGE_EXISTS 1 /* displayed image -- image exists */
|
|
#define DI_IMAGE_NO_FILE 2 /* displayed image -- exists but no file */
|
|
|
|
// Redefined here for moving to SCANLIB
|
|
#define IDS_TWAIN_SCAN_WNDW 2
|
|
|
|
// TAKEN OUT OF OIDISP.H
|
|
#define OI_DISP_WINDOW 0L
|
|
|
|
// Internal Module Prototypes
|
|
int TranslateErrors(TW_UINT16 dcCC);
|
|
|
|
/* HERE FOR REFERENCE ONLY - It's commented out
|
|
// Structure contains Twain Property Handle and Pointer for TWAIN structure
|
|
typedef struct
|
|
{
|
|
HANDLE TSdh; // handle to property
|
|
LP_TWAIN_SCANDATA lpTSdp; // long pointer to data for property
|
|
} TWAIN_PROP, far * LP_TWAIN_PROP;
|
|
*/
|
|
|
|
|
|
char TwainPropName[] = "TWAINScanner";
|
|
char szTwainMsgProp[] = "TWAIN Scanner Msg";
|
|
HICON hIcon;
|
|
HBRUSH hBrush = 0;
|
|
static char class_name[] = {"TWAIN SCANNER"};
|
|
// static char aboutbox[] = {"AboutBox"};
|
|
|
|
extern TW_IDENTITY PrivdsID; // access to open ds id structure
|
|
extern TW_UINT16 DCDSOpen; // glue code flag for an Open Source
|
|
extern TW_UINT16 DCDSMOpen; // glue code flag for an Open Source Mgr
|
|
// Added for Window Creation
|
|
extern HANDLE hLibInst; // current instance
|
|
extern TWAIN_PROP TwainProperty;
|
|
|
|
// add for use of UI when scanning, satisfy spec - kfs
|
|
int GetCurrentOpts(HWND hMainWnd); // For getting current Twain options from device
|
|
int SetTwainOpts(HWND hMainWnd, int wMsgType);
|
|
|
|
long FAR PASCAL TwainWndProc(HWND hWnd, unsigned message, WPARAM wParam, LONG lParam);
|
|
// BOOL FAR PASCAL AboutProc(HWND hWnd, unsigned, WORD wParam, LONG lParam);
|
|
|
|
HWND CreateTwainScannerWndw(HWND hWnd, HANDLE hInstance);
|
|
static WORD Init(HANDLE hInstance);
|
|
|
|
int IMGTwainOpenScanner(HWND hWnd, LPSTR lpProductName, LP_TWAIN_PROP lpToTwain)
|
|
{
|
|
int ret_val = IMGSE_ALREADY_OPEN;
|
|
BOOL bOpennedByAnotherApp = FALSE;
|
|
TW_UINT16 dcRC;
|
|
HANDLE hInstance;
|
|
HANDLE hTwainMsg;
|
|
STR_DCSTATUS dcStatus;
|
|
HWND hActWnd;
|
|
|
|
// pTWAIN_MSG_STRUCT pTwainMsg;
|
|
|
|
// check window handle
|
|
if (!IsWindow(hWnd))
|
|
return IMGSE_BAD_WND;
|
|
|
|
hActWnd = GetActiveWindow();
|
|
|
|
// LockData(0);
|
|
|
|
if (!IMGGetProp(hWnd, TwainPropName))
|
|
{ // if Property doesn't exist, create property
|
|
// lets get the handle for the TWAIN Property
|
|
lpToTwain->TSdh = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (WORD)sizeof(TWAIN_SCANDATA));
|
|
// check validity of handle
|
|
if (lpToTwain->TSdh)
|
|
{
|
|
// set ret value to unsucessful attempt to get property
|
|
ret_val = IMGSE_PROPERTY;
|
|
// if non zero, property created
|
|
if (IMGSetProp(hWnd, TwainPropName, lpToTwain->TSdh))
|
|
{
|
|
lpToTwain->lpTSdp = (LP_TWAIN_SCANDATA)GlobalLock(lpToTwain->TSdh);
|
|
|
|
if (lpToTwain->lpTSdp)
|
|
{
|
|
LPSTR lpDash;
|
|
char szBuffer[MAX_RESOURCE_CHAR];
|
|
HWND hAppWnd; // Need to search for window with Title, usually app wndw
|
|
|
|
// Need to Create a Control Window to get messages from OITWAIN.DLL
|
|
hInstance = hLibInst; // Create local copy of Instance
|
|
lpToTwain->lpTSdp->hCtlWnd = CreateTwainScannerWndw(hWnd, hInstance);
|
|
|
|
// Create Twain Message Property associated with wndw
|
|
if (lpToTwain->lpTSdp->hCtlWnd)
|
|
{
|
|
if (hTwainMsg = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (WORD)sizeof(TWAIN_MSG_STRUCT)))
|
|
{ // let's set property
|
|
if (!IMGSetProp(lpToTwain->lpTSdp->hCtlWnd, szTwainMsgProp, hTwainMsg))
|
|
{ // if fails clear out of open, report failure
|
|
GlobalUnlock(lpToTwain->TSdh);
|
|
GlobalFree(lpToTwain->TSdh);
|
|
GlobalFree(hTwainMsg);
|
|
lpToTwain->TSdh = 0;
|
|
return IMGSE_PROPERTY;
|
|
}
|
|
}
|
|
else
|
|
{ // abort if mem alloc fails
|
|
GlobalUnlock(lpToTwain->TSdh);
|
|
GlobalFree(lpToTwain->TSdh);
|
|
return IMGSE_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{ // abort if cannot create window for control (icon wndw)
|
|
return IMGSE_BAD_WND;
|
|
}
|
|
|
|
// init to 0, but Source Manager will assign real value
|
|
(lpToTwain->lpTSdp->AppID).Id = 0;
|
|
|
|
// Use LoadString and translate values to AppID
|
|
|
|
LoadString(hLibInst, IDS_MAJORNUM, szBuffer, MAX_RESOURCE_CHAR);
|
|
(lpToTwain->lpTSdp->AppID).Version.MajorNum = atoun(szBuffer);
|
|
LoadString(hLibInst, IDS_MINORNUM, szBuffer, MAX_RESOURCE_CHAR);
|
|
(lpToTwain->lpTSdp->AppID).Version.MinorNum = atoun(szBuffer);
|
|
(lpToTwain->lpTSdp->AppID).Version.Language = TWLG_USA;
|
|
(lpToTwain->lpTSdp->AppID).Version.Country = TWCY_USA;
|
|
LoadString(hLibInst, IDS_VERINFO, szBuffer, MAX_RESOURCE_CHAR);
|
|
lstrcpy ((lpToTwain->lpTSdp->AppID).Version.Info, szBuffer);
|
|
|
|
LoadString(hLibInst, IDS_MANUFACTURER, szBuffer, MAX_RESOURCE_CHAR);
|
|
lstrcpy ((lpToTwain->lpTSdp->AppID).Manufacturer, szBuffer);
|
|
LoadString(hLibInst, IDS_PRODUCTFAMILY, szBuffer, MAX_RESOURCE_CHAR);
|
|
lstrcpy ((lpToTwain->lpTSdp->AppID).ProductFamily, szBuffer);
|
|
|
|
// Always get it from application window
|
|
if (!(hAppWnd = GetParent(hWnd))) hAppWnd = hWnd;
|
|
while (hAppWnd && !GetWindowText(hAppWnd, szBuffer, MAX_RESOURCE_CHAR))
|
|
{// No title, search other windows
|
|
hAppWnd = GetParent(hAppWnd);
|
|
}
|
|
|
|
lpDash = lstrchr(szBuffer, '-');
|
|
if (lpDash)
|
|
{
|
|
if (*(lpDash - 1) == 0x20) {
|
|
// *(lpDash - 1) = 0; // Changed for Win95
|
|
lstrcpy((lpToTwain->lpTSdp->AppID).ProductName, (lpDash + 1));
|
|
}
|
|
}
|
|
else { // no dash use all of it, no longer than TW_STR32
|
|
if ((UINT)lstrlen(szBuffer) > 33 /*sizeof(TW_STR32)*/)
|
|
szBuffer[33] = 0;
|
|
lstrcpy((lpToTwain->lpTSdp->AppID).ProductName, szBuffer);
|
|
}
|
|
|
|
(lpToTwain->lpTSdp->AppID).ProtocolMajor = TWON_PROTOCOLMAJOR;
|
|
(lpToTwain->lpTSdp->AppID).ProtocolMinor = TWON_PROTOCOLMINOR;
|
|
(lpToTwain->lpTSdp->AppID).SupportedGroups = DG_IMAGE | DG_CONTROL;
|
|
|
|
// copy hWnd to prop struct
|
|
lpToTwain->lpTSdp->hMainWnd = hWnd;
|
|
// lpToTwain->lpTSdp->hCtlWnd = hWnd;
|
|
|
|
//if (DCDSMOpen = IMGTwainOpenDSM (hWnd, lpToTwain->lpTSdp->hCtlWnd,
|
|
// &lpToTwain->lpTSdp->AppID, &dcStatus))
|
|
DCDSMOpen = IMGTwainOpenDSM (hWnd, lpToTwain->lpTSdp->hCtlWnd,
|
|
&lpToTwain->lpTSdp->AppID, &dcStatus);
|
|
if (DCDSMOpen && !dcStatus.DCError.dcRC) // make sure we register it
|
|
{
|
|
// TW_UINT32 dcError;
|
|
|
|
ret_val = IMGSE_SUCCESS;
|
|
if (!lpProductName || !(*lpProductName) || !lstrcmp(lpProductName, "twain"))
|
|
{ // product name not specified, put up select box
|
|
dcRC = IMGTwainSelectDS (hWnd, &lpToTwain->lpTSdp->DsID, &dcStatus.DCError);
|
|
if (!dcRC ) // successful
|
|
{
|
|
// set the Users lpProductName to the selected Product
|
|
(lpToTwain->lpTSdp->DsID).Id = 0;
|
|
DCDSOpen = IMGTwainOpenDS(hWnd, &lpToTwain->lpTSdp->DsID, &dcStatus);
|
|
dcRC = dcStatus.DCError.dcRC;
|
|
if (!DCDSOpen || dcRC)
|
|
{
|
|
// for now assume any failure, due to it being openned previously
|
|
// ... will need to change at latter date when condition
|
|
// ... code returned along with open call - kfs 9/28/92
|
|
ret_val = TranslateErrors(dcStatus.DCError.dcCC);
|
|
if (ret_val == IMGSE_ALREADY_OPEN)
|
|
{
|
|
bOpennedByAnotherApp = TRUE;
|
|
}
|
|
// some don't report the source being used
|
|
if ((ret_val == IMGSE_HANDLER)
|
|
&& ((lpToTwain->lpTSdp->AppID).Id > 2))
|
|
{
|
|
// most likely openned by another app
|
|
bOpennedByAnotherApp = TRUE;
|
|
ret_val = IMGSE_ALREADY_OPEN;
|
|
}
|
|
DCDSMOpen = IMGTwainCloseDSM(hWnd, &dcStatus);
|
|
}
|
|
else
|
|
{
|
|
// no_error:
|
|
if (lpProductName) // if valid pointer return productname
|
|
lstrcpy(lpProductName,
|
|
(lpToTwain->lpTSdp->DsID).ProductName);
|
|
PrivdsID = lpToTwain->lpTSdp->DsID; // pass it to PrivdsID
|
|
// ... for now
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dcRC == TWRC_CANCEL)
|
|
ret_val = IMGSE_CANCEL;
|
|
else
|
|
if (dcStatus.DCError.dcCC == TWCC_NODS)
|
|
ret_val = IMGSE_HWNOTFOUND;
|
|
else
|
|
ret_val = IMGSE_HANDLER;
|
|
// Close down DSM (TWAIN.DLL)
|
|
DCDSMOpen = IMGTwainCloseDSM(hWnd, &dcStatus);
|
|
}
|
|
}
|
|
else
|
|
{ // Product name specified, no select box entered
|
|
// copy product name into DsId.ProductName and call OpenDS
|
|
lstrcpy((lpToTwain->lpTSdp->DsID).ProductName, lpProductName);
|
|
(lpToTwain->lpTSdp->DsID).Id = 0L;
|
|
DCDSOpen = IMGTwainOpenDS(hWnd, &lpToTwain->lpTSdp->DsID, &dcStatus);
|
|
dcRC = dcStatus.DCError.dcRC;
|
|
|
|
if (!DCDSOpen || dcStatus.DCError.dcRC)
|
|
{
|
|
// for now assume any failure, due to it being openned previously
|
|
// ... will need to change at latter date when condition
|
|
// ... code returned along with open call - kfs 9/28/92
|
|
|
|
// ret_val = IMGSE_ALREADY_OPEN;
|
|
ret_val = TranslateErrors(dcStatus.DCError.dcCC); // replaced above
|
|
if (ret_val == IMGSE_ALREADY_OPEN)
|
|
{
|
|
bOpennedByAnotherApp = TRUE;
|
|
}
|
|
// some don't report the source being used
|
|
if ((ret_val == IMGSE_HANDLER)
|
|
&& ((lpToTwain->lpTSdp->AppID).Id > 2))
|
|
{
|
|
// most likely openned by another app
|
|
bOpennedByAnotherApp = TRUE;
|
|
ret_val = IMGSE_ALREADY_OPEN;
|
|
}
|
|
DCDSMOpen = IMGTwainCloseDSM(hWnd, &dcStatus);
|
|
}
|
|
else
|
|
PrivdsID = lpToTwain->lpTSdp->DsID; // pass it to PrivdsID
|
|
// ... for now
|
|
}
|
|
// Display Product Name
|
|
SetWindowText(lpToTwain->lpTSdp->hCtlWnd,
|
|
(lpToTwain->lpTSdp->DsID).ProductName);
|
|
}
|
|
else
|
|
ret_val = IMGSE_NOT_OPEN;
|
|
}
|
|
else
|
|
{
|
|
IMGRemoveProp(hWnd, TwainPropName);
|
|
GlobalUnlock(lpToTwain->TSdh);
|
|
GlobalFree(lpToTwain->TSdh);
|
|
return (ret_val = IMGSE_MEMORY);
|
|
}
|
|
}
|
|
else
|
|
ret_val = IMGSE_PROPERTY;
|
|
}
|
|
else
|
|
{
|
|
ret_val = IMGSE_MEMORY;
|
|
}
|
|
}
|
|
|
|
// Unlock the handle to the property
|
|
if (lpToTwain->lpTSdp)
|
|
{
|
|
if (ret_val && (ret_val != IMGSE_ALREADY_OPEN))
|
|
{
|
|
if (hTwainMsg)
|
|
{
|
|
IMGRemoveProp(lpToTwain->lpTSdp->hCtlWnd, szTwainMsgProp);
|
|
GlobalFree(hTwainMsg);
|
|
}
|
|
|
|
// DESTROY ICON WINDOW
|
|
SetFocus(hActWnd);
|
|
SendMessage(lpToTwain->lpTSdp->hCtlWnd, WM_CLOSE, (WPARAM) 0, 0L);
|
|
|
|
GlobalUnlock(lpToTwain->TSdh);
|
|
IMGRemoveProp(hWnd, TwainPropName);
|
|
GlobalFree(lpToTwain->TSdh);
|
|
|
|
// Set HANDLE to property to zero
|
|
lpToTwain->TSdh = 0;
|
|
}
|
|
else
|
|
{
|
|
if (ret_val == IMGSE_ALREADY_OPEN)
|
|
{ // Already openned by either this app or another app
|
|
if (bOpennedByAnotherApp)
|
|
{ // only if openned by another app do we want to close it out
|
|
if (hTwainMsg)
|
|
{
|
|
IMGRemoveProp(lpToTwain->lpTSdp->hCtlWnd, szTwainMsgProp);
|
|
GlobalFree(hTwainMsg);
|
|
}
|
|
|
|
// DESTROY ICON WINDOW
|
|
SetFocus(hActWnd);
|
|
SendMessage(lpToTwain->lpTSdp->hCtlWnd, WM_CLOSE, (WPARAM) 0, 0L);
|
|
|
|
GlobalUnlock(lpToTwain->TSdh);
|
|
IMGRemoveProp(hWnd, TwainPropName);
|
|
GlobalFree(lpToTwain->TSdh);
|
|
|
|
// Set HANDLE to property to zero
|
|
lpToTwain->TSdh = 0;
|
|
}
|
|
}
|
|
else // Openned properly
|
|
GlobalUnlock(lpToTwain->TSdh);
|
|
}
|
|
}
|
|
|
|
// UnlockData(0);
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
int IMGTwainGetProp(HWND hWnd, LP_TWAIN_PROP lpToTwain)
|
|
{
|
|
int ret_val = IMGSE_SUCCESS;
|
|
|
|
if (!IsWindow(hWnd))
|
|
return IMGSE_BAD_WND;
|
|
|
|
// LockData(0);
|
|
|
|
if (lpToTwain) // make sure its a valid pointer
|
|
{
|
|
if (lpToTwain->TSdh = IMGGetProp(hWnd, TwainPropName))
|
|
{
|
|
if (!(lpToTwain->lpTSdp =
|
|
(LP_TWAIN_SCANDATA)GlobalLock(lpToTwain->TSdh)))
|
|
ret_val = IMGSE_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
ret_val = IMGSE_NULL_PTR;
|
|
|
|
// UnlockData(0);
|
|
return ret_val;
|
|
}
|
|
|
|
int IMGTwainCloseScanner(HWND hWnd, LP_TWAIN_PROP lpToTwain)
|
|
{
|
|
int ret_val;
|
|
TW_UINT16 SourceClosed;
|
|
HANDLE hTwainMsg;
|
|
STR_DCSTATUS dcStatus;
|
|
|
|
ret_val = IMGTwainGetProp(hWnd, lpToTwain);
|
|
|
|
// BG 3/21/96 Dont do this. It can blow up a DS if the EnableDS fails!
|
|
// Besides, it is not Disabled anywhere else but in IMGTwainScanPages().
|
|
//if (!(lpToTwain->lpTSdp->dwOverRunBytes & 1L)) // it may have been disabled in Sequencer code
|
|
// IMGTwainDisableDS(hWnd, &dcStatus.DCError);
|
|
|
|
// close the source
|
|
DCDSOpen = IMGTwainCloseDS (hWnd, &lpToTwain->lpTSdp->DsID, &dcStatus);
|
|
SourceClosed = !(DCDSOpen | dcStatus.DCError.dcRC);
|
|
DCDSMOpen = IMGTwainCloseDSM (hWnd, &dcStatus);
|
|
|
|
if (SourceClosed) // Close down ICON
|
|
{ // unlock handle to msg prop and remove it, then destroy icon wndw
|
|
HANDLE hPropStr;
|
|
|
|
hTwainMsg = IMGGetProp(lpToTwain->lpTSdp->hCtlWnd, szTwainMsgProp);
|
|
GlobalUnlock(hTwainMsg);
|
|
hPropStr = IMGRemoveProp(lpToTwain->lpTSdp->hCtlWnd, szTwainMsgProp);
|
|
GlobalFree(hTwainMsg);
|
|
|
|
// DESTROY ICON WINDOW
|
|
SendMessage(lpToTwain->lpTSdp->hCtlWnd, WM_CLOSE, (WPARAM) 0, 0L);
|
|
}
|
|
|
|
// Unlock the handle & free the property
|
|
if (lpToTwain->lpTSdp)
|
|
{
|
|
HANDLE hPropStr;
|
|
|
|
GlobalUnlock(lpToTwain->TSdh);
|
|
hPropStr = IMGRemoveProp(hWnd, TwainPropName);
|
|
GlobalFree(lpToTwain->TSdh);
|
|
lpToTwain->TSdh = NULL;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
HWND CreateTwainScannerWndw(HWND hWnd, HANDLE hInstance)
|
|
{
|
|
HWND hTwainWnd; // Window Handle for ICON
|
|
HMENU hMenu;
|
|
char handler_name[MAX_RESOURCE_CHAR];
|
|
// char about_name[MAX_RESOURCE_CHAR]; // Support at later date
|
|
|
|
|
|
hBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
|
|
|
|
Init(hInstance);
|
|
|
|
LoadString(hInstance, IDS_TWAIN_SCAN_WNDW, handler_name, MAX_RESOURCE_CHAR);
|
|
|
|
hTwainWnd = CreateWindow(class_name,
|
|
handler_name,
|
|
// BG 9/8/95 Get rid of minimize and maximize buttons. They are grayed out anyway.
|
|
// WS_OVERLAPPEDWINDOW,
|
|
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
|
|
10, 10, 150, 150,
|
|
hWnd,
|
|
NULL,
|
|
hInstance,
|
|
NULL );
|
|
|
|
if (!hTwainWnd)
|
|
return hTwainWnd; // Could not create window
|
|
|
|
hMenu = GetSystemMenu(hTwainWnd, FALSE);
|
|
DeleteMenu(hMenu, SC_RESTORE, MF_BYCOMMAND);
|
|
DeleteMenu(hMenu, SC_SIZE, MF_BYCOMMAND);
|
|
DeleteMenu(hMenu, SC_MINIMIZE, MF_BYCOMMAND);
|
|
DeleteMenu(hMenu, SC_MAXIMIZE, MF_BYCOMMAND);
|
|
DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
|
|
DeleteMenu(hMenu, 1, MF_BYPOSITION);
|
|
// Win32 obsolete function
|
|
//ChangeMenu(hMenu, SC_RESTORE, NULL, NULL, MF_DELETE);
|
|
//ChangeMenu(hMenu, SC_SIZE, NULL, NULL, MF_DELETE);
|
|
//ChangeMenu(hMenu, SC_MINIMIZE, NULL, NULL, MF_DELETE);
|
|
//ChangeMenu(hMenu, SC_MAXIMIZE, NULL, NULL, MF_DELETE);
|
|
//ChangeMenu(hMenu, SC_CLOSE, NULL, NULL, MF_DELETE);
|
|
//ChangeMenu(hMenu, 1, NULL, NULL, MF_BYPOSITION | MF_DELETE);
|
|
|
|
/* Incorporate AboutBox at later date
|
|
LoadString(hInstance, stAboutMenu, about_name, MAX_RESOURCE_CHAR);
|
|
ChangeMenu(hMenu, NULL, about_name, IDM_ABOUT, MF_APPEND);
|
|
*/
|
|
|
|
hIcon = LoadIcon(hInstance, "DC_SCAN_ICO");
|
|
ShowWindow(hTwainWnd, SW_SHOWMINNOACTIVE);
|
|
InvalidateRect(hTwainWnd, NULL, FALSE);
|
|
UpdateWindow (hTwainWnd);
|
|
|
|
return hTwainWnd;
|
|
}
|
|
|
|
/***************/
|
|
/* Init */
|
|
/***************/
|
|
|
|
static WORD Init(HANDLE hInstance)
|
|
{
|
|
NPWNDCLASS npWndClass;
|
|
BOOL bSuccess;
|
|
|
|
npWndClass = (NPWNDCLASS)LocalAlloc(LPTR, sizeof(WNDCLASS));
|
|
|
|
npWndClass->style = 0;
|
|
npWndClass->lpfnWndProc = (WNDPROC)TwainWndProc;
|
|
npWndClass->hInstance = hInstance;
|
|
// BG 9/8/95 Use the scan icon!
|
|
//npWndClass->hIcon = NULL;
|
|
npWndClass->hIcon = LoadIcon(hInstance, "DC_SCAN_ICO");
|
|
npWndClass->hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
npWndClass->hbrBackground = hBrush;
|
|
npWndClass->lpszMenuName = (LPSTR)NULL;
|
|
npWndClass->lpszClassName = (LPSTR)class_name;
|
|
|
|
bSuccess = RegisterClass(npWndClass);
|
|
|
|
LocalFree ((LOCALHANDLE)npWndClass);
|
|
|
|
return(bSuccess);
|
|
}
|
|
|
|
/****************************/
|
|
/* Twain Window Proc */
|
|
/****************************/
|
|
|
|
long FAR PASCAL TwainWndProc(HWND hWnd, unsigned message,
|
|
WPARAM wParam, long lParam)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hDC;
|
|
RECT rect;
|
|
HWND hOrgWnd = 0;
|
|
|
|
switch (message)
|
|
|
|
{
|
|
case WM_QUERYOPEN: /* keep as icon */
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
hDC = BeginPaint(hWnd, &ps);
|
|
GetClientRect(hWnd, &rect);
|
|
FillRect(hDC, &rect, hBrush);
|
|
DrawIcon(hDC, 0, 0, hIcon);
|
|
EndPaint(hWnd, &ps);
|
|
break;
|
|
|
|
/* Incorporate About Bos at later date
|
|
case WM_SYSCOMMAND:
|
|
if (wParam == IDM_ABOUT)
|
|
{
|
|
lpProcAbout = MakeProcInstance (About, hLibInst);
|
|
IMGDialogBox (hLibInst, aboutbox, hWnd, lpProcAbout);
|
|
FreeProcInstance (lpProcAbout);
|
|
}
|
|
else
|
|
return(DefWindowProc(hWnd, message, wParam, lParam));
|
|
break;
|
|
*/
|
|
|
|
case WM_CLOSE:
|
|
//DeleteObject(hBrush);
|
|
hBrush = 0;
|
|
DestroyWindow(hWnd);
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE: /* BackGround Color has Changed */
|
|
//DeleteObject(hBrush);
|
|
hBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
UpdateWindow(hWnd);
|
|
break;
|
|
|
|
case PM_CLOSESRC:
|
|
// This is for test application, should not hurt for scanlib.dll
|
|
// hOrgWnd = (TwainProperty.lpTSdp)->hMainWnd;
|
|
// PostMessage(hOrgWnd, PM_CLOSESRC, NULL, 0);
|
|
break;
|
|
|
|
case PM_XFERDONE:
|
|
// This is for test application, wParam is handle to image
|
|
TwainProperty.lpTSdp = (LP_TWAIN_SCANDATA)GlobalLock(TwainProperty.TSdh);
|
|
//hOrgWnd = (TwainProperty.lpTSdp)->hMainWnd;
|
|
(TwainProperty.lpTSdp)->hOverRun = (HANDLE)wParam;
|
|
SendMessage ((TwainProperty.lpTSdp)->hMainWnd, message, wParam, 0);
|
|
GlobalUnlock(TwainProperty.TSdh);
|
|
break;
|
|
|
|
case PM_STARTXFER:
|
|
{
|
|
STR_TRIPLET Triplet;
|
|
|
|
TwainProperty.lpTSdp = (LP_TWAIN_SCANDATA)GlobalLock(TwainProperty.TSdh);
|
|
//hOrgWnd = (TwainProperty.lpTSdp)->hMainWnd;
|
|
|
|
// get image info in state 6
|
|
Triplet.wDATType = DAT_IMAGEINFO;
|
|
Triplet.wMsgState = MSG_GET;
|
|
Triplet.pVoidStr =
|
|
(pTW_IMAGEINFO)(&((TwainProperty.lpTSdp)->dcImageInfo));
|
|
IMGTwainExecTriplet((TwainProperty.lpTSdp)->hMainWnd, &Triplet);
|
|
GlobalUnlock(TwainProperty.TSdh);
|
|
}
|
|
break;
|
|
|
|
case PM_FEEDPAGE:
|
|
break;
|
|
|
|
case PM_PREEJECT:
|
|
break;
|
|
|
|
default:
|
|
return(DefWindowProc(hWnd, message, wParam, lParam));
|
|
}
|
|
|
|
return(0L);
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
* FUNCTION: TransLateErrors()
|
|
*
|
|
* PURPOSE: To translate dcCC error of TWAIN to O/i Errors
|
|
*
|
|
* COMMENTS: For now is an internal structure to this module
|
|
*
|
|
* ARGS: dcCC error code from TWAIN
|
|
*
|
|
* RETURNS: O/i Error code
|
|
*
|
|
*************************************************************************/
|
|
|
|
int TranslateErrors(TW_UINT16 dcCC)
|
|
{
|
|
WORD ret_val;
|
|
|
|
switch (dcCC)
|
|
{
|
|
case TWCC_MAXCONNECTIONS:
|
|
ret_val = IMGSE_ALREADY_OPEN;
|
|
break;
|
|
|
|
case TWCC_LOWMEMORY:
|
|
ret_val = IMGSE_MEMORY;
|
|
break;
|
|
|
|
default:
|
|
case TWCC_SUCCESS:
|
|
case TWCC_BUMMER:
|
|
ret_val = IMGSE_HANDLER;
|
|
break;
|
|
|
|
case TWCC_OPERATIONERROR:
|
|
// Error in the DS or DSM which was already reported to the user. The
|
|
// App should not be redundant. The operation failed. ???????????? kfs
|
|
ret_val = IMGSE_HANDLER; // I'm going to report it in this routine - kfs
|
|
break;
|
|
|
|
case TWCC_BADCAP:
|
|
ret_val = IMGSE_INVALIDPARM;
|
|
break;
|
|
|
|
case TWCC_BADPROTOCOL:
|
|
ret_val = IMGSE_BADUSAGE;
|
|
break;
|
|
|
|
case TWCC_BADVALUE:
|
|
ret_val = IMGSE_INVALIDPARM;
|
|
break;
|
|
|
|
case TWCC_NODS:
|
|
ret_val = IMGSE_NO_SCANNERS;
|
|
break;
|
|
|
|
case TWCC_SEQERROR:
|
|
ret_val = IMGSE_BADUSAGE;
|
|
break;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
/****************** Internal API for SCANSEQ.DLL *******************/
|
|
/* */
|
|
/* IMGTwainScanPages() - Scans images from TWAIN sources, isolates */
|
|
/* the OITWAIN.DLL and TWAIN.DLL from the */
|
|
/* SCANSEQ.DLL, only link required to */
|
|
/* oitwain is now to SCANLIB.DLL */
|
|
/* */
|
|
/* Comments: For 3.6 - 3.7.2 - this code was in the */
|
|
/* IMGScanPage(), taken out so don't have to */
|
|
/* hard link SCANSEQD.DLL with OITWAIN.DLL */
|
|
/* and add functionality so call can be used */
|
|
/* in new IMGScanPages() which will scan */
|
|
/* multiple images to a file. */
|
|
/* */
|
|
/* History: 1. KFS - 12/13/94 - Initial write of function from */
|
|
/* IMGScanPage(), not functional */
|
|
/* */
|
|
/* 2. */
|
|
/* */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
int PASCAL IMGTwainScanPages(LP_TWAIN_SCANDATA lpTwainInfo,
|
|
lpTWSCANPAGE lpTWPage,
|
|
LPSCANDATA sdp)
|
|
{
|
|
TW_USERINTERFACE dcUI;
|
|
TW_UINT16 AppdcRC;
|
|
MSG msg;
|
|
BOOL bCancel_Xfer;
|
|
STR_DCERROR dcError;
|
|
//bgSTR_CAP TwainCap;
|
|
//bgDWORD dwOiTwainMultiImg;
|
|
DWORD dwUseChild = 0;
|
|
int ret_stat = IMGSE_SUCCESS;
|
|
HWND hAppWnd;
|
|
FINDWNDSPEC fws;
|
|
BOOL bUseUI = FALSE;
|
|
//bg STR_DCSTATUS dcStatus;
|
|
|
|
// Set it so use MSG_ENDXFER in TWAIN
|
|
//bgdwOiTwainMultiImg = OI_TWAIN_MULTIIMGXFER;
|
|
|
|
//bgTwainCap.ItemIndex = 0;
|
|
//bgTwainCap.wMsgState = MSG_GET;
|
|
//bgTwainCap.ItemType = TWTY_BOOL;
|
|
//bgTwainCap.lpData = (pTW_BOOL)&(lpTWPage->bAutoMode);
|
|
//bgTwainCap.wCapType = CAP_AUTOFEED;
|
|
//bgif (AppdcRC = IMGTwainGetCaps(lpTwainInfo->hMainWnd, &TwainCap, NULL))
|
|
//bg {
|
|
//bg // if true don't have to use MSG_RESET in TWAIN
|
|
//bg dwOiTwainMultiImg = OI_TWAIN_MULTIIMGXFER;
|
|
//bg }
|
|
//bgelse
|
|
//bg {
|
|
//bg // will only do one image per call, issue reset in TWAIN
|
|
//bg if (lpTWPage->bAutoMode)
|
|
//bg dwOiTwainMultiImg = 0;
|
|
//bg }
|
|
|
|
if (lpTWPage->flags & IMG_SJF_DISP_BOTH)
|
|
{
|
|
if (lpTWPage->flags & IMG_SJF_SCROLL)
|
|
lpTWPage->open_disp_flags = OI_DISP_SCROLL;
|
|
else
|
|
{
|
|
lpTWPage->open_disp_flags = OI_DISP_NO; // No scroll, display after scan complete
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpTWPage->open_disp_flags = OI_DONT_REPAINT;
|
|
}
|
|
|
|
|
|
// Always show the UI now! BG 1/15/96
|
|
if (lpTWPage->flags & IMG_SJF_SHOWSCANUI)
|
|
{
|
|
dcUI.ShowUI = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// BG 4/8/96 Set the scanner options from win.ini to the data source
|
|
// Only Set them if no UI. HP DS's dont behave well if we do it and use
|
|
// their UI.
|
|
IMGGetScanOpts(lpTWPage->hScancb); // This will do the SHF_WGETOPTS B.G. 12/14/92
|
|
dcUI.ShowUI = FALSE;
|
|
}
|
|
|
|
dcUI.hParent = lpTwainInfo->hCtlWnd;
|
|
IMGTwaintoOiControl(lpTwainInfo->hMainWnd,
|
|
lpTWPage->hImageWnd,
|
|
//bg OI_TWAIN_NOUNTITLED | dwOiTwainMultiImg
|
|
OI_TWAIN_NOUNTITLED
|
|
| dwUseChild | lpTWPage->open_disp_flags,
|
|
OI_TWAIN_NOUNTITLED | OI_TWAIN_EXTERNXFER
|
|
| OI_TWAIN_MULTIIMGXFER | OI_TWAIN_ALTIMGWND
|
|
| OI_TWAIN_DISPMASK);
|
|
|
|
if (lpTWPage->flags & IMG_SJF_CAPTION) // only update caption if flag set so init won't
|
|
// be destroyed
|
|
{
|
|
if (lpTWPage->bIsPrivApp)
|
|
{ // use UIUpdateTitle
|
|
WORD wPageNoForTitle, wPagePerForTitle;
|
|
BOOL bIsItaDoc;
|
|
|
|
if (bIsItaDoc = (*sdp->autodoc) || (*sdp->document))
|
|
{
|
|
wPageNoForTitle = sdp->docpage;
|
|
wPagePerForTitle = 0;
|
|
}
|
|
else
|
|
{ // set to page_num instead of 1 and pagesperfile;
|
|
wPageNoForTitle = lpTWPage->page_num;
|
|
wPagePerForTitle = sdp->pagesperfile;
|
|
}
|
|
//IMGUIUpdateTitle(lpTWPage->hOiAppWnd, lpTWPage->lpCaption, bIsItaDoc, wPageNoForTitle, wPagePerForTitle);
|
|
sdp->fnUIUpdateTitle(lpTWPage->hOiAppWnd, lpTWPage->lpCaption, bIsItaDoc, wPageNoForTitle, wPagePerForTitle);
|
|
}
|
|
else
|
|
{
|
|
SetWindowText(lpTWPage->hOiAppWnd, lpTWPage->lpCaption); // put up the caption on window
|
|
}
|
|
}
|
|
|
|
// Set the app window on top or twunk_16 as top level window
|
|
hAppWnd = GetAppWndw(lpTwainInfo->hMainWnd); // get app window
|
|
if (!findwin(GetWindow(GetDesktopWindow(), GW_CHILD), 0, &fws))
|
|
hAppWnd = fws.hwnd;
|
|
SetWindowPos(
|
|
hAppWnd, // handle of application window
|
|
HWND_TOP, // placement-order handle
|
|
0, // horizontal position not used
|
|
0, // vertical position not used
|
|
0, // width not used
|
|
0, // height not used
|
|
SWP_NOSIZE | SWP_NOMOVE // window-positioning flags
|
|
);
|
|
|
|
AppdcRC = IMGTwainEnableDS (lpTwainInfo->hMainWnd, &dcUI, &dcError);
|
|
// if Enable failed, assume a cancel for now.
|
|
if (AppdcRC)
|
|
{
|
|
lpTwainInfo->dwOverRunBytes = 1L; // so ds wont be disabled on close
|
|
ret_stat = IMGSE_ABORT; // for now
|
|
}
|
|
|
|
if (lpTWPage->bEnableSuccess = (!(AppdcRC) || (bUseUI = (AppdcRC == TWRC_CHECKSTATUS))))
|
|
{
|
|
// Will need some timer for fail safe operation, if not found
|
|
// Wait for PM_XFERDONE msg
|
|
while (GetMessage((LPMSG)&msg, NULL, 0, 0))
|
|
{
|
|
if ((!IMGTwainProcessDCMessage ((LPMSG)&msg, lpTwainInfo,
|
|
lpTWPage, sdp))
|
|
&& !IsDialogMessage(lpTwainInfo->hMainWnd, (LPMSG)&msg))
|
|
{
|
|
TranslateMessage ((LPMSG)&msg);
|
|
DispatchMessage ((LPMSG)&msg);
|
|
}
|
|
if (msg.hwnd == lpTwainInfo->hCtlWnd)
|
|
{
|
|
BOOL msg_found = FALSE;
|
|
|
|
switch (msg.message)
|
|
{
|
|
case PM_STARTXFER: // OK or DONE or SCAN, code aborts here
|
|
msg_found = TRUE;
|
|
bCancel_Xfer = FALSE; // if started
|
|
break; // get out of switch
|
|
|
|
case PM_CLOSESRC: // Close down the source
|
|
msg_found = TRUE;
|
|
bCancel_Xfer = TRUE;
|
|
break; // get out of switch
|
|
|
|
default: // no message and non defined msgs
|
|
;
|
|
|
|
} // END OF SWITCH
|
|
if (msg_found) // if TRUE, we have found msg
|
|
break; // get out of while
|
|
} // END OF IF HANDLE == TO WHAT WE WANT
|
|
} // END OF WHILE
|
|
|
|
if (!IMGTwainDisableDS(lpTwainInfo->hMainWnd, &dcError))
|
|
lpTwainInfo->dwOverRunBytes = 1L;
|
|
|
|
// use hOverRun just to see if it works
|
|
ret_stat = (lpTwainInfo->hOverRun == 0) ? IMGSE_ABORT : IMGSE_SUCCESS;
|
|
if (!lpTwainInfo->hOverRun)
|
|
{
|
|
ret_stat = IMGSE_ABORT;
|
|
lpTwainInfo->hOverRun = 0;
|
|
lpTWPage->iImageState = DI_IMAGE_NO_FILE;
|
|
}
|
|
else // success, get current options
|
|
{
|
|
GetCurrentOpts(lpTwainInfo->hMainWnd);
|
|
}
|
|
//bg if (bUseUI) // UI is up even when we don't want it
|
|
//bg { // need to close down and reopen due to spec
|
|
//bg TW_STR32 ProductName;
|
|
|
|
//bg lstrcpy(ProductName, lpTwainInfo->DsID.ProductName);
|
|
//bg DCDSOpen = IMGTwainCloseDS(lpTwainInfo->hMainWnd, &lpTwainInfo->DsID, &dcStatus);
|
|
//bg lstrcpy(lpTwainInfo->DsID.ProductName, ProductName);
|
|
//bg DCDSOpen = IMGTwainOpenDS(lpTwainInfo->hMainWnd, &lpTwainInfo->DsID, &dcStatus);
|
|
//bg SetTwainOpts(lpTwainInfo->hMainWnd, MSG_SET);
|
|
//bg }
|
|
} // END OF IMGTwainEnableDS
|
|
|
|
return ret_stat;
|
|
|
|
} // END OF IMGTwainScanPages()
|