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.
1511 lines
46 KiB
1511 lines
46 KiB
// MSQSCANDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "MSQSCAN.h"
|
|
#include "MSQSCANDlg.h"
|
|
#include "ProgressDlg.h"
|
|
#include "uitables.h"
|
|
#include "ADFDlg.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define PIXELS_PER_INCH_FACTOR 32
|
|
#define PREVIEW_WINDOW_OFFSET 11
|
|
|
|
DWORD g_dwCookie = 0;
|
|
IGlobalInterfaceTable *g_pGIT = NULL;
|
|
|
|
//
|
|
// global UI lookup tables
|
|
//
|
|
|
|
extern WIA_FORMAT_TABLE_ENTRY g_WIA_FORMAT_TABLE[];
|
|
extern WIA_DATATYPE_TABLE_ENTRY g_WIA_DATATYPE_TABLE[];
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMSQSCANDlg dialog
|
|
|
|
CMSQSCANDlg::CMSQSCANDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CMSQSCANDlg::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CMSQSCANDlg)
|
|
m_MAX_Brightness = _T("");
|
|
m_MAX_Contrast = _T("");
|
|
m_MIN_Brightness = _T("");
|
|
m_MIN_Contrast = _T("");
|
|
m_XResolution = 0;
|
|
m_YResolution = 0;
|
|
//}}AFX_DATA_INIT
|
|
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
|
m_DataAcquireInfo.bTransferToClipboard = FALSE;
|
|
m_DataAcquireInfo.bPreview = TRUE;
|
|
m_DataAcquireInfo.bTransferToFile = FALSE;
|
|
m_DataAcquireInfo.dwCookie = 0;
|
|
m_DataAcquireInfo.hBitmap = NULL;
|
|
m_DataAcquireInfo.hClipboardData = NULL;
|
|
m_DataAcquireInfo.pProgressFunc = NULL;
|
|
m_DataAcquireInfo.hBitmapData = NULL;
|
|
m_pConnectEventCB = NULL;
|
|
}
|
|
|
|
void CMSQSCANDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CMSQSCANDlg)
|
|
DDX_Control(pDX, IDC_CHANGE_BOTH_CHECKBOX, m_ChangeBothResolutionsCheckBox);
|
|
DDX_Control(pDX, IDC_EDIT_YRES_SPIN_BUDDY, m_YResolutionBuddy);
|
|
DDX_Control(pDX, IDC_EDIT_XRES_SPIN_BUDDY, m_XResolutionBuddy);
|
|
DDX_Control(pDX, IDC_SCAN_BUTTON, m_ScanButton);
|
|
DDX_Control(pDX, IDC_PREVIEW_BUTTON, m_PreviewButton);
|
|
DDX_Control(pDX, IDC_IMAGE_FILETYPE_COMBO, m_FileTypeComboBox);
|
|
DDX_Control(pDX, IDC_DATATYPE_COMBO, m_DataTypeComboBox);
|
|
DDX_Control(pDX, IDC_CONTRAST_SLIDER, m_ContrastSlider);
|
|
DDX_Control(pDX, IDC_BRIGHTNESS_SLIDER, m_BrightnessSlider);
|
|
DDX_Control(pDX, IDC_PREVIEW_WINDOW, m_PreviewRect);
|
|
DDX_Text(pDX, IDC_MAX_BRIGHTNESS, m_MAX_Brightness);
|
|
DDX_Text(pDX, IDC_MAX_CONTRAST, m_MAX_Contrast);
|
|
DDX_Text(pDX, IDC_MIN_BRIGHTNESS, m_MIN_Brightness);
|
|
DDX_Text(pDX, IDC_MIN_CONTRAST, m_MIN_Contrast);
|
|
DDX_Text(pDX, IDC_EDIT_XRES, m_XResolution);
|
|
DDX_Text(pDX, IDC_EDIT_YRES, m_YResolution);
|
|
DDX_Control(pDX, IDC_DATA_TO_FILE, m_DataToFile);
|
|
DDX_Control(pDX, IDC_DATA_TO_CLIPBOARD, m_DataToClipboard);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CMSQSCANDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CMSQSCANDlg)
|
|
ON_WM_PAINT()
|
|
ON_WM_QUERYDRAGICON()
|
|
ON_NOTIFY(UDN_DELTAPOS, IDC_EDIT_XRES_SPIN_BUDDY, OnDeltaposEditXresSpinBuddy)
|
|
ON_NOTIFY(UDN_DELTAPOS, IDC_EDIT_YRES_SPIN_BUDDY, OnDeltaposEditYresSpinBuddy)
|
|
ON_EN_SETFOCUS(IDC_EDIT_XRES, OnSetfocusEditXres)
|
|
ON_EN_KILLFOCUS(IDC_EDIT_XRES, OnKillfocusEditXres)
|
|
ON_EN_KILLFOCUS(IDC_EDIT_YRES, OnKillfocusEditYres)
|
|
ON_EN_SETFOCUS(IDC_EDIT_YRES, OnSetfocusEditYres)
|
|
ON_BN_CLICKED(IDC_SCAN_BUTTON, OnScanButton)
|
|
ON_BN_CLICKED(IDC_PREVIEW_BUTTON, OnPreviewButton)
|
|
ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
|
|
ON_COMMAND(ID_FILE_SELECT_DEVICE, OnFileSelectDevice)
|
|
ON_BN_CLICKED(IDC_ADF_SETTINGS, OnAdfSettings)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMSQSCANDlg message handlers
|
|
|
|
BOOL CMSQSCANDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
// Set the icon for this dialog. The framework does this automatically
|
|
// when the application's main window is not a dialog
|
|
SetIcon(m_hIcon, TRUE); // Set big icon
|
|
SetIcon(m_hIcon, FALSE); // Set small icon
|
|
|
|
//
|
|
// Set radio button setting (Data to File as DEFAULT setting)
|
|
//
|
|
|
|
m_DataToFile.SetCheck(1);
|
|
m_DataAcquireInfo.hBitmap = NULL;
|
|
|
|
OnFileSelectDevice();
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
}
|
|
|
|
// If you add a minimize button to your dialog, you will need the code below
|
|
// to draw the icon. For MFC applications using the document/view model,
|
|
// this is automatically done for you by the framework.
|
|
|
|
void CMSQSCANDlg::OnPaint()
|
|
{
|
|
if (IsIconic()) {
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
|
|
|
|
// Center icon in client rectangle
|
|
int cxIcon = GetSystemMetrics(SM_CXICON);
|
|
int cyIcon = GetSystemMetrics(SM_CYICON);
|
|
CRect rect;
|
|
GetClientRect(&rect);
|
|
int x = (rect.Width() - cxIcon + 1) / 2;
|
|
int y = (rect.Height() - cyIcon + 1) / 2;
|
|
|
|
// Draw the icon
|
|
dc.DrawIcon(x, y, m_hIcon);
|
|
}
|
|
else {
|
|
CDialog::OnPaint();
|
|
}
|
|
}
|
|
|
|
// The system calls this to obtain the cursor to display while the user drags
|
|
// the minimized window.
|
|
HCURSOR CMSQSCANDlg::OnQueryDragIcon()
|
|
{
|
|
return (HCURSOR) m_hIcon;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMSQSCANDlg message handlers
|
|
|
|
BOOL CMSQSCANDlg::InitDialogSettings()
|
|
{
|
|
|
|
//
|
|
// fill common resolution combo box
|
|
//
|
|
|
|
if (InitResolutionEditBoxes()) {
|
|
|
|
//
|
|
// fill data type combo box
|
|
//
|
|
|
|
if (InitDataTypeComboBox()) {
|
|
|
|
//
|
|
// set min/max contrast slider control
|
|
//
|
|
|
|
if (InitContrastSlider()) {
|
|
|
|
//
|
|
// set min/max brightness slider control
|
|
//
|
|
|
|
if (InitBrightnessSlider()) {
|
|
|
|
//
|
|
// fill supported file type combo box
|
|
//
|
|
|
|
if (!InitFileTypeComboBox()) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Brightness Slider control failed to initialize");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Contrast Slider control failed to initialize");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Data Type combobox failed to initialize");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Resolution edit boxes failed to initialize");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::InitResolutionEditBoxes()
|
|
{
|
|
|
|
//
|
|
// Set buddy controls to their "buddy"
|
|
//
|
|
|
|
LONG lMin = 0;
|
|
LONG lMax = 0;
|
|
LONG lCurrent = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_XRES,WIA_RANGE_MIN,&lMin);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_XRES,WIA_RANGE_MAX,&lMax);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadLong(NULL,WIA_IPS_XRES,&lCurrent);
|
|
if (FAILED(hr)) {
|
|
MessageBox("Application Failed to read x resolution (Min Setting)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to read x resolution (Max Setting)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to read x resolution (Current Setting)");
|
|
return FALSE;
|
|
}
|
|
|
|
m_XResolutionBuddy.SetBuddy(GetDlgItem(IDC_EDIT_XRES));
|
|
m_XResolutionBuddy.SetRange(lMin,lMax);
|
|
m_XResolutionBuddy.SetPos(lCurrent);
|
|
m_XResolution = m_XResolutionBuddy.GetPos();
|
|
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_XRES,WIA_RANGE_MIN,&lMin);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_XRES,WIA_RANGE_MAX,&lMax);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = m_WIA.ReadLong(NULL,WIA_IPS_XRES,&lCurrent);
|
|
if (FAILED(hr)) {
|
|
MessageBox("Application Failed to read y resolution (Min Setting)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to read y resolution (Max Setting)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to read y resolution (Current Setting)");
|
|
return FALSE;
|
|
}
|
|
|
|
m_YResolutionBuddy.SetBuddy(GetDlgItem(IDC_EDIT_YRES));
|
|
m_YResolutionBuddy.SetRange(lMin,lMax);
|
|
m_YResolutionBuddy.SetPos(lCurrent);
|
|
m_YResolution = m_YResolutionBuddy.GetPos();
|
|
|
|
//
|
|
// set current selection, to be scanner's current setting
|
|
//
|
|
|
|
UpdateData(FALSE);
|
|
|
|
//
|
|
// check 'change both resolutions' check box
|
|
//
|
|
|
|
m_ChangeBothResolutionsCheckBox.SetCheck(1);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::InitDataTypeComboBox()
|
|
{
|
|
//
|
|
// reset data type combo box
|
|
//
|
|
|
|
m_DataTypeComboBox.ResetContent();
|
|
|
|
//
|
|
// set current selection, to be scanner's current setting
|
|
//
|
|
|
|
//
|
|
// Below is a hard coded supported data type list. This should be obtained from the
|
|
// device itself. (ie. some scanners may not support color..)
|
|
// This was done for testing purposes.
|
|
//
|
|
|
|
ULONG ulCount = 3;
|
|
TCHAR szDataType[MAX_PATH];
|
|
LONG plDataType[3] = {
|
|
WIA_DATA_THRESHOLD,
|
|
WIA_DATA_COLOR,
|
|
WIA_DATA_GRAYSCALE
|
|
};
|
|
|
|
for(ULONG index = 0;index < ulCount;index++) {
|
|
|
|
//
|
|
// add data type to combo box
|
|
//
|
|
|
|
INT TableIndex = GetIDAndStringFromDataType(plDataType[index],szDataType);
|
|
INT InsertIndex = m_DataTypeComboBox.AddString(szDataType);
|
|
m_DataTypeComboBox.SetItemData(InsertIndex, TableIndex);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::InitContrastSlider()
|
|
{
|
|
LONG lMin = 0;
|
|
LONG lMax = 0;
|
|
LONG lCurrent = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_CONTRAST,WIA_RANGE_MIN,&lMin);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_CONTRAST,WIA_RANGE_MAX,&lMax);
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadLong(NULL,WIA_IPS_CONTRAST,&lCurrent);
|
|
if(FAILED(hr)){
|
|
MessageBox("Application Failed to read contrast (Current Setting)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to read contrast (Max Setting)");
|
|
return FALSE;
|
|
}
|
|
}else {
|
|
MessageBox("Application Failed to read contrast (Min Setting)");
|
|
return FALSE;
|
|
}
|
|
|
|
m_ContrastSlider.SetRange(lMin,lMax,TRUE);
|
|
m_ContrastSlider.SetPos(lCurrent);
|
|
m_ContrastSlider.SetTicFreq(lMax/11);
|
|
|
|
m_MIN_Contrast.Format("%d",lMin);
|
|
m_MAX_Contrast.Format("%d",lMax);
|
|
|
|
UpdateData(FALSE);
|
|
|
|
//
|
|
// set current selection, to be scanner's current setting
|
|
//
|
|
|
|
m_DataTypeComboBox.SetCurSel(0);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::InitBrightnessSlider()
|
|
{
|
|
LONG lMin = 0;
|
|
LONG lMax = 0;
|
|
LONG lCurrent = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_BRIGHTNESS,WIA_RANGE_MIN,&lMin);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_BRIGHTNESS,WIA_RANGE_MAX,&lMax);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadLong(NULL,WIA_IPS_BRIGHTNESS,&lCurrent);
|
|
if (FAILED(hr)) {
|
|
MessageBox("Application Failed to read brightness (Current Setting)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to read brightness (Max Setting)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to read brightness (Min Setting)");
|
|
return FALSE;
|
|
}
|
|
|
|
m_BrightnessSlider.SetRange(lMin,lMax,TRUE);
|
|
m_BrightnessSlider.SetPos(lCurrent);
|
|
m_BrightnessSlider.SetTicFreq(lMax/11);
|
|
|
|
m_MIN_Brightness.Format("%d",lMin);
|
|
m_MAX_Brightness.Format("%d",lMax);
|
|
|
|
UpdateData(FALSE);
|
|
|
|
//
|
|
// set current selection, to be scanner's current setting
|
|
//
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::InitFileTypeComboBox()
|
|
{
|
|
//
|
|
// reset file type combo box
|
|
//
|
|
|
|
m_FileTypeComboBox.ResetContent();
|
|
|
|
HRESULT hr = S_OK;
|
|
TCHAR szguidFormat[MAX_PATH];
|
|
|
|
//
|
|
// set current selection, to be scanner's current setting
|
|
//
|
|
|
|
//
|
|
// enumerate supported file types
|
|
//
|
|
|
|
WIA_FORMAT_INFO *pSupportedFormats = NULL;
|
|
ULONG ulCount = 0;
|
|
|
|
hr = m_WIA.EnumerateSupportedFormats(NULL, &pSupportedFormats, &ulCount);
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// filter out TYMED_FILE formats only
|
|
//
|
|
|
|
for(ULONG index = 0;index < ulCount;index++) {
|
|
if(pSupportedFormats[index].lTymed == TYMED_FILE) {
|
|
|
|
//
|
|
// add supported file format to combo box
|
|
//
|
|
|
|
INT TableIndex = GetIDAndStringFromGUID(pSupportedFormats[index].guidFormatID,szguidFormat);
|
|
INT InsertIndex = m_FileTypeComboBox.AddString(szguidFormat);
|
|
m_FileTypeComboBox.SetItemData(InsertIndex, TableIndex);
|
|
}
|
|
}
|
|
|
|
//
|
|
// free the memory allocated by the CWIA call
|
|
//
|
|
|
|
GlobalFree(pSupportedFormats);
|
|
m_FileTypeComboBox.SetCurSel(0);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::SetDeviceNameToWindowTitle(BSTR bstrDeviceName)
|
|
{
|
|
//
|
|
// convert BSTR to a CString
|
|
//
|
|
|
|
CString DeviceName = bstrDeviceName;
|
|
|
|
//
|
|
// write the new title to the window
|
|
//
|
|
|
|
SetWindowText("Microsoft Quick Scan: [ " + DeviceName + " ]");
|
|
return TRUE;
|
|
}
|
|
|
|
void CMSQSCANDlg::OnDeltaposEditXresSpinBuddy(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
|
if(m_ChangeBothResolutionsCheckBox.GetCheck() == 1) {
|
|
m_YResolution = (pNMUpDown->iPos + pNMUpDown->iDelta);
|
|
UpdateData(FALSE);
|
|
}
|
|
*pResult = 0;
|
|
}
|
|
|
|
void CMSQSCANDlg::OnDeltaposEditYresSpinBuddy(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
|
if(m_ChangeBothResolutionsCheckBox.GetCheck() == 1) {
|
|
m_XResolution = (pNMUpDown->iPos + pNMUpDown->iDelta);
|
|
UpdateData(FALSE);
|
|
}
|
|
*pResult = 0;
|
|
}
|
|
|
|
void CMSQSCANDlg::OnSetfocusEditXres()
|
|
{
|
|
UpdateData(TRUE);
|
|
if(m_ChangeBothResolutionsCheckBox.GetCheck() == 1) {
|
|
m_XResolution = m_YResolution;
|
|
UpdateData(FALSE);
|
|
}
|
|
}
|
|
|
|
void CMSQSCANDlg::OnKillfocusEditXres()
|
|
{
|
|
UpdateData(TRUE);
|
|
if(m_ChangeBothResolutionsCheckBox.GetCheck() == 1) {
|
|
m_YResolution = m_XResolution;
|
|
UpdateData(FALSE);
|
|
}
|
|
}
|
|
|
|
void CMSQSCANDlg::OnKillfocusEditYres()
|
|
{
|
|
UpdateData(TRUE);
|
|
if(m_ChangeBothResolutionsCheckBox.GetCheck() == 1) {
|
|
m_XResolution = m_YResolution;
|
|
UpdateData(FALSE);
|
|
}
|
|
}
|
|
|
|
void CMSQSCANDlg::OnSetfocusEditYres()
|
|
{
|
|
UpdateData(TRUE);
|
|
if(m_ChangeBothResolutionsCheckBox.GetCheck() == 1) {
|
|
m_XResolution = m_YResolution;
|
|
UpdateData(FALSE);
|
|
}
|
|
}
|
|
|
|
void CMSQSCANDlg::OnScanButton()
|
|
{
|
|
memset(m_DataAcquireInfo.szFileName,0,sizeof(m_DataAcquireInfo.szFileName));
|
|
|
|
if(m_DataToFile.GetCheck() == 1) {
|
|
|
|
//
|
|
// scan to file
|
|
//
|
|
|
|
m_DataAcquireInfo.bTransferToFile = TRUE;
|
|
|
|
//
|
|
// allow user to set the file name
|
|
//
|
|
|
|
CHAR szFilter[256];
|
|
memset(szFilter,0,sizeof(szFilter));
|
|
CFileDialog FileDialog(FALSE);
|
|
|
|
//
|
|
// Get filter from selected combobox (file type)
|
|
//
|
|
|
|
INT CurrentSelection = m_FileTypeComboBox.GetCurSel();
|
|
m_FileTypeComboBox.GetLBText(CurrentSelection, szFilter);
|
|
FileDialog.m_ofn.lpstrFilter = szFilter;
|
|
|
|
//
|
|
// Show the SaveAs dialog to user
|
|
//
|
|
|
|
if(FileDialog.DoModal() == IDOK) {
|
|
|
|
//
|
|
// save user selected filename
|
|
//
|
|
|
|
strcpy(m_DataAcquireInfo.szFileName,FileDialog.m_ofn.lpstrFile);
|
|
DeleteFile(m_DataAcquireInfo.szFileName);
|
|
} else {
|
|
|
|
//
|
|
// do nothing... the user decided not to enter a file name
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// scan to clipboard
|
|
//
|
|
|
|
m_DataAcquireInfo.bTransferToFile = FALSE;
|
|
m_DataAcquireInfo.bTransferToClipboard = TRUE;
|
|
}
|
|
|
|
//
|
|
// Write settings from dialog to device
|
|
//
|
|
|
|
if(WriteScannerSettingsToDevice()) {
|
|
|
|
ADF_SETTINGS ADFSettings;
|
|
if(SUCCEEDED(ReadADFSettings(&ADFSettings))){
|
|
|
|
//
|
|
// check file type, and warn user about BMP files.
|
|
//
|
|
|
|
CHAR szFormat[256];
|
|
memset(szFormat,0,sizeof(szFormat));
|
|
|
|
INT FILEFORMAT = m_FileTypeComboBox.GetCurSel();
|
|
m_FileTypeComboBox.GetLBText(FILEFORMAT, szFormat);
|
|
if (NULL != strstr(szFormat,"BMP")) {
|
|
if(ADFSettings.lPages > 1) {
|
|
MessageBox(TEXT("BMP Files will only save the last page scanned, because there\nis no Multi-page BMP file format."),TEXT("BMP File Format Warning"),MB_ICONWARNING);
|
|
} else if(ADFSettings.lPages == 0) {
|
|
MessageBox(TEXT("BMP Files will only save the last page scanned, because there\nis no Multi-page BMP file format."),TEXT("BMP File Format Warning"),MB_ICONWARNING);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// create progress dialog object
|
|
//
|
|
|
|
CProgressDlg ProgDlg(this);
|
|
|
|
//
|
|
// set preview flag, and data acquire information
|
|
//
|
|
|
|
m_DataAcquireInfo.bPreview = FALSE; // this is a 'final' scan
|
|
ProgDlg.SetAcquireData(&m_DataAcquireInfo);
|
|
|
|
//
|
|
// activate scan progress dialog
|
|
//
|
|
|
|
ProgDlg.DoModal();
|
|
|
|
if(m_DataAcquireInfo.bTransferToClipboard ) {
|
|
|
|
//
|
|
// Put memory on clipboard
|
|
//
|
|
|
|
PutDataOnClipboard();
|
|
m_DataAcquireInfo.bTransferToClipboard = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMSQSCANDlg::OnPreviewButton()
|
|
{
|
|
|
|
memset(m_DataAcquireInfo.szFileName,0,sizeof(m_DataAcquireInfo.szFileName));
|
|
m_DataAcquireInfo.bTransferToFile = FALSE;
|
|
|
|
//
|
|
// Write settings from dialog to device
|
|
//
|
|
|
|
if(WriteScannerSettingsToDevice(TRUE)) {
|
|
|
|
//
|
|
// create progress dialog object
|
|
//
|
|
|
|
CProgressDlg ProgDlg(this);
|
|
|
|
//
|
|
// set preview flag, and data acquire information
|
|
//
|
|
|
|
m_DataAcquireInfo.bPreview = TRUE; // this is a 'preview' scan
|
|
if(m_DataAcquireInfo.hBitmapData != NULL) {
|
|
GlobalUnlock(m_DataAcquireInfo.hBitmapData);
|
|
|
|
//
|
|
// free previous preview scan
|
|
//
|
|
|
|
GlobalFree(m_DataAcquireInfo.hBitmapData);
|
|
m_DataAcquireInfo.hBitmapData = NULL;
|
|
}
|
|
|
|
ProgDlg.SetAcquireData(&m_DataAcquireInfo);
|
|
|
|
//
|
|
// activate scan progress dialog
|
|
//
|
|
|
|
ProgDlg.DoModal();
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
INT CMSQSCANDlg::GetIDAndStringFromGUID(GUID guidFormat, TCHAR *pszguidString)
|
|
{
|
|
INT index = 0;
|
|
while(*(g_WIA_FORMAT_TABLE[index].pguidFormat) != guidFormat && index < NUM_WIA_FORMAT_INFO_ENTRIES) {
|
|
index++;
|
|
}
|
|
|
|
if(index > NUM_WIA_FORMAT_INFO_ENTRIES)
|
|
index = NUM_WIA_FORMAT_INFO_ENTRIES;
|
|
|
|
lstrcpy(pszguidString, g_WIA_FORMAT_TABLE[index].szFormatName);
|
|
|
|
return index;
|
|
}
|
|
|
|
GUID CMSQSCANDlg::GetGuidFromID(INT iID)
|
|
{
|
|
return *(g_WIA_FORMAT_TABLE[iID].pguidFormat);
|
|
}
|
|
|
|
LRESULT CMSQSCANDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if(message == WM_UPDATE_PREVIEW) {
|
|
m_PreviewWindow.SetHBITMAP(m_DataAcquireInfo.hBitmap);
|
|
}
|
|
return CDialog::WindowProc(message, wParam, lParam);
|
|
}
|
|
|
|
INT CMSQSCANDlg::GetIDAndStringFromDataType(LONG lDataType, TCHAR *pszString)
|
|
{
|
|
INT index = 0;
|
|
while(g_WIA_DATATYPE_TABLE[index].lDataType != lDataType && index < NUM_WIA_DATATYPE_ENTRIES) {
|
|
index++;
|
|
}
|
|
|
|
if(index > NUM_WIA_DATATYPE_ENTRIES)
|
|
index = NUM_WIA_DATATYPE_ENTRIES;
|
|
|
|
lstrcpy(pszString, g_WIA_DATATYPE_TABLE[index].szDataTypeName);
|
|
|
|
return index;
|
|
}
|
|
|
|
LONG CMSQSCANDlg::GetDataTypeFromID(INT iID)
|
|
{
|
|
return (g_WIA_DATATYPE_TABLE[iID].lDataType);
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::WriteScannerSettingsToDevice(BOOL bPreview)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int SelectionIndex = 0;
|
|
int TableIndex = 0;
|
|
SelectionIndex = m_DataTypeComboBox.GetCurSel();
|
|
TableIndex = (int)m_DataTypeComboBox.GetItemData(SelectionIndex);
|
|
|
|
//
|
|
// Set data type
|
|
//
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPA_DATATYPE,GetDataTypeFromID(TableIndex));
|
|
|
|
if(SUCCEEDED(hr)){
|
|
LONG lBrightness = m_BrightnessSlider.GetPos();
|
|
|
|
//
|
|
// Set Brightness
|
|
//
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_BRIGHTNESS,lBrightness);
|
|
if(SUCCEEDED(hr)){
|
|
LONG lContrast = m_ContrastSlider.GetPos();
|
|
|
|
//
|
|
// Set Contrast
|
|
//
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_CONTRAST,lContrast);
|
|
if(FAILED(hr)) {
|
|
MessageBox("Application Failed to set Data Type");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to set Brightness");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to set Data Type");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Reset selection rect, to be full bed.
|
|
// This is good to do if you want a solid starting
|
|
// place, for extent setting
|
|
//
|
|
|
|
if(!ResetWindowExtents()) {
|
|
return FALSE;
|
|
}
|
|
|
|
if(bPreview) {
|
|
|
|
//
|
|
// set to preview X resolution
|
|
//
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_XRES,PREVIEW_RES);
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// set to preview Y resolution
|
|
//
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_YRES,PREVIEW_RES);
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// set to memory bitmap for preview display
|
|
//
|
|
|
|
hr = m_WIA.WriteGuid(NULL,WIA_IPA_FORMAT,WiaImgFmt_MEMORYBMP);
|
|
if(FAILED(hr)) {
|
|
MessageBox("Application Failed to set format to Memory BMP");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to set Y Resolution (Preview)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to set X Resolution (Preview)");
|
|
return FALSE;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Are we scanning to the clipboard??
|
|
//
|
|
|
|
if(m_DataAcquireInfo.bTransferToClipboard ) {
|
|
|
|
//
|
|
// Do only Banded transfer, and WiaImgFmt_MEMORYBMP for clipboard
|
|
// transfers. (This application can only do this function using
|
|
// those specific settings).
|
|
// Note: Other applications are not restricted by this. This is
|
|
// is a design issue with this sample only!!!
|
|
//
|
|
|
|
//
|
|
// set to memory bitmap for clipboard scanning
|
|
//
|
|
|
|
hr = m_WIA.WriteGuid(NULL,WIA_IPA_FORMAT,WiaImgFmt_MEMORYBMP);
|
|
if(FAILED(hr)) {
|
|
MessageBox("Memory BMP could not be set to Device");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// write dialog setting for resolution
|
|
//
|
|
|
|
UpdateData(TRUE);
|
|
|
|
//
|
|
// set X resolution
|
|
//
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_XRES,m_XResolution);
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// set Y resolution
|
|
//
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_YRES,m_YResolution);
|
|
if(FAILED(hr)) {
|
|
MessageBox("Application Failed to set Y Resolution (Preview)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application Failed to set X Resolution (Preview)");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// write extent values
|
|
//
|
|
|
|
CRect SelectionRect;
|
|
m_PreviewWindow.GetSelectionRect(SelectionRect);
|
|
|
|
CRect PreviewRect;
|
|
m_PreviewWindow.GetWindowRect(PreviewRect);
|
|
|
|
LONG lXPos = 0;
|
|
LONG lYPos = 0;
|
|
LONG lMaxXExtent = 0;
|
|
LONG lMaxYExtent = 0;
|
|
LONG lXExtent = 0;
|
|
LONG lYExtent = 0;
|
|
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_XEXTENT,WIA_RANGE_MAX,&lMaxXExtent);
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_YEXTENT,WIA_RANGE_MAX,&lMaxYExtent);
|
|
if(FAILED(hr)) {
|
|
MessageBox("Application failed to read y extent (Max value)");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read x extent (Max value)");
|
|
return FALSE;
|
|
}
|
|
|
|
FLOAT fxRatio = ((FLOAT)lMaxXExtent/(FLOAT)PreviewRect.Width());
|
|
FLOAT fyRatio = ((FLOAT)lMaxYExtent/(FLOAT)PreviewRect.Height());
|
|
|
|
lXPos = (LONG)(SelectionRect.left * fxRatio);
|
|
lYPos = (LONG)(SelectionRect.top * fyRatio);
|
|
|
|
lXExtent = (LONG)(SelectionRect.Width() * fxRatio);
|
|
lYExtent = (LONG)(SelectionRect.Height() * fyRatio);
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_XPOS,lXPos);
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_YPOS,lYPos);
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_XEXTENT,lXExtent);
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_YEXTENT,lYExtent);
|
|
if(FAILED(hr)){
|
|
MessageBox("Application failed to set Y Extent");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to set X Extent");
|
|
return FALSE;
|
|
}
|
|
}else {
|
|
MessageBox("Application failed to set Y Position");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to set X Position");
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CMSQSCANDlg::OnFileClose()
|
|
{
|
|
CDialog::OnOK();
|
|
}
|
|
|
|
void CMSQSCANDlg::OnFileSelectDevice()
|
|
{
|
|
CRect DialogClientRect;
|
|
|
|
GetClientRect(DialogClientRect);
|
|
|
|
//
|
|
// use scan window place holder, as template for placing the scan
|
|
// preview window
|
|
//
|
|
|
|
CRect WindowRect;
|
|
m_PreviewRect.GetWindowRect(WindowRect);
|
|
ScreenToClient(WindowRect);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IGlobalInterfaceTable,(void**)&g_pGIT);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
hr = CoCreateInstance(CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_IWiaDevMgr,(void**)&m_pIWiaDevMgr);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// An example on how to register for Device Connection Events
|
|
//
|
|
|
|
m_pConnectEventCB = new CEventCallback;
|
|
if (m_pConnectEventCB) {
|
|
|
|
IWiaEventCallback* pIWiaEventCallback = NULL;
|
|
IUnknown* pIUnkRelease;
|
|
|
|
// register connected event
|
|
m_pConnectEventCB->Initialize(ID_WIAEVENT_CONNECT);
|
|
m_pConnectEventCB->QueryInterface(IID_IWiaEventCallback,(void **)&pIWiaEventCallback);
|
|
|
|
GUID guidConnect = WIA_EVENT_DEVICE_CONNECTED;
|
|
hr = m_pIWiaDevMgr->RegisterEventCallbackInterface(WIA_REGISTER_EVENT_CALLBACK,
|
|
NULL,
|
|
&guidConnect,
|
|
pIWiaEventCallback,
|
|
&pIUnkRelease);
|
|
|
|
m_pConnectEventCB->m_pIUnkRelease = pIUnkRelease;
|
|
|
|
//
|
|
// An Example on how to register for events with this application
|
|
//
|
|
|
|
WCHAR szMyApplicationLaunchPath[MAX_PATH];
|
|
memset(szMyApplicationLaunchPath,0,sizeof(szMyApplicationLaunchPath));
|
|
GetModuleFileNameW(NULL,szMyApplicationLaunchPath,sizeof(szMyApplicationLaunchPath));
|
|
BSTR bstrMyApplicationLaunchPath = SysAllocString(szMyApplicationLaunchPath);
|
|
|
|
WCHAR szMyApplicationName[MAX_PATH];
|
|
memset(szMyApplicationName,0,sizeof(szMyApplicationName));
|
|
HINSTANCE hInst = AfxGetInstanceHandle();
|
|
if(hInst){
|
|
LoadStringW(hInst, IDS_MYAPPLICATION_NAME, szMyApplicationName, (sizeof(szMyApplicationName)/sizeof(WCHAR)));
|
|
|
|
BSTR bstrMyApplicationName = SysAllocString(szMyApplicationName);
|
|
|
|
GUID guidScanButtonEvent = WIA_EVENT_SCAN_IMAGE;
|
|
hr = m_pIWiaDevMgr->RegisterEventCallbackProgram(
|
|
WIA_REGISTER_EVENT_CALLBACK,
|
|
NULL,
|
|
&guidScanButtonEvent,
|
|
bstrMyApplicationLaunchPath,
|
|
bstrMyApplicationName,
|
|
bstrMyApplicationName,
|
|
bstrMyApplicationLaunchPath);
|
|
if(FAILED(hr)){
|
|
MessageBox("Could not Register Application for Events");
|
|
hr = S_OK; // continue and try to use device
|
|
}
|
|
|
|
SysFreeString(bstrMyApplicationName);
|
|
bstrMyApplicationName = NULL;
|
|
|
|
}
|
|
SysFreeString(bstrMyApplicationLaunchPath);
|
|
bstrMyApplicationLaunchPath = NULL;
|
|
|
|
}
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// select your scanning device here
|
|
//
|
|
|
|
IWiaItem *pIWiaRootItem = NULL;
|
|
|
|
hr = m_pIWiaDevMgr->SelectDeviceDlg(m_hWnd,StiDeviceTypeScanner,0,NULL,&pIWiaRootItem);
|
|
if (hr == S_OK) {
|
|
|
|
//
|
|
// Write interface to Global Interface Table
|
|
//
|
|
|
|
hr = WriteInterfaceToGlobalInterfaceTable(&m_DataAcquireInfo.dwCookie,
|
|
pIWiaRootItem);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// save root item (device) created
|
|
//
|
|
|
|
m_WIA.SetRootItem(pIWiaRootItem);
|
|
|
|
//
|
|
// query selected device for it's name
|
|
//
|
|
|
|
BSTR bstrDeviceName;
|
|
hr = m_WIA.ReadStr(pIWiaRootItem,WIA_DIP_DEV_NAME,&bstrDeviceName);
|
|
if (SUCCEEDED(hr)) {
|
|
SetDeviceNameToWindowTitle(bstrDeviceName);
|
|
SysFreeString(bstrDeviceName);
|
|
}
|
|
|
|
//
|
|
// query selected device for scanner bed size, so we can create
|
|
// a scanner preview window
|
|
//
|
|
|
|
LONG MaxScanBedWidth = 0;
|
|
LONG MaxScanBedHeight = 0;
|
|
FLOAT fRatio = 0;
|
|
FLOAT fXFactor = 0.0f;
|
|
FLOAT fYFactor = 0.0f;
|
|
FLOAT fTheFactor = 0.0f;
|
|
|
|
m_WIA.ReadLong(pIWiaRootItem,WIA_DPS_HORIZONTAL_BED_SIZE,&MaxScanBedWidth);
|
|
m_WIA.ReadLong(pIWiaRootItem,WIA_DPS_VERTICAL_BED_SIZE,&MaxScanBedHeight);
|
|
|
|
fRatio = (FLOAT)((FLOAT)MaxScanBedHeight / (FLOAT)MaxScanBedWidth);
|
|
|
|
fXFactor = (FLOAT)WindowRect.Width()/(FLOAT)MaxScanBedWidth;
|
|
fYFactor = (FLOAT)WindowRect.Height()/(FLOAT)MaxScanBedHeight;
|
|
|
|
if (fXFactor > fYFactor)
|
|
fTheFactor = fYFactor;
|
|
else
|
|
fTheFactor = fXFactor;
|
|
|
|
//
|
|
// adjust the pixel returned size so it will fit on the dialog correctly
|
|
//
|
|
|
|
WindowRect.right = (LONG)(fTheFactor * MaxScanBedWidth) + WindowRect.left;
|
|
WindowRect.bottom = (LONG)(fTheFactor * MaxScanBedHeight) + WindowRect.top;
|
|
//WindowRect.right = (MaxScanBedWidth/PIXELS_PER_INCH_FACTOR);
|
|
//WindowRect.bottom = (LONG)(WindowRect.right * fRatio);
|
|
|
|
//
|
|
// check scanner bed size, against actual window size, and adjust
|
|
//
|
|
|
|
if (DialogClientRect.bottom < WindowRect.bottom) {
|
|
CRect DialogRect;
|
|
GetWindowRect(DialogRect);
|
|
DialogRect.InflateRect(0,0,0,(WindowRect.bottom - DialogClientRect.bottom) + 10);
|
|
MoveWindow(DialogRect);
|
|
}
|
|
} else {
|
|
MessageBox("Failed to Set IWiaRootItem Interface in to Global Interface Table");
|
|
}
|
|
|
|
} else {
|
|
MessageBox("No Scanner was selected.");
|
|
return;
|
|
}
|
|
} else {
|
|
MessageBox("Could not Register for Device Disconnect Events");
|
|
}
|
|
|
|
m_PreviewWindow.DestroyWindow();
|
|
|
|
//
|
|
// create the preview window
|
|
//
|
|
|
|
if(!m_PreviewWindow.Create(NULL,
|
|
TEXT("Preview Window"),
|
|
WS_CHILD|WS_VISIBLE,
|
|
WindowRect,
|
|
this,
|
|
PREVIEW_WND_ID)){
|
|
MessageBox("Failed to create preview window");
|
|
return;
|
|
}
|
|
|
|
m_DataAcquireInfo.hWnd = m_PreviewWindow.m_hWnd;
|
|
|
|
//
|
|
// intialize selection rect to entire bed for preview
|
|
//
|
|
|
|
m_PreviewWindow.SetPreviewRect(WindowRect);
|
|
|
|
//
|
|
// InitDialogSettings
|
|
//
|
|
|
|
InitDialogSettings();
|
|
|
|
} else {
|
|
MessageBox("CoCreateInstance for WIA Device Manager failed");
|
|
return;
|
|
}
|
|
} else {
|
|
MessageBox("CoCreateInstance for Global Interface Table failed");
|
|
return;
|
|
}
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::PutDataOnClipboard()
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
if(OpenClipboard()){
|
|
if(EmptyClipboard()){
|
|
BYTE* pbBuf = (BYTE*)GlobalLock(m_DataAcquireInfo.hClipboardData);
|
|
VerticalFlip(pbBuf);
|
|
GlobalUnlock(m_DataAcquireInfo.hClipboardData);
|
|
if(SetClipboardData(CF_DIB, m_DataAcquireInfo.hClipboardData) == NULL) {
|
|
MessageBox("SetClipboardData failed");
|
|
} else {
|
|
|
|
//
|
|
// We succeeded to give memory handle to clipboard
|
|
//
|
|
|
|
bSuccess = TRUE;
|
|
}
|
|
} else {
|
|
MessageBox("EmptyClipboard failed");
|
|
}
|
|
if (!CloseClipboard()) {
|
|
MessageBox("CloseClipboard failed");
|
|
}
|
|
} else {
|
|
MessageBox("OpenClipboard failed");
|
|
}
|
|
|
|
if(!bSuccess) {
|
|
|
|
//
|
|
// Free the memory ourselves, because the Clipboard failed to accept it.
|
|
//
|
|
|
|
GlobalFree(m_DataAcquireInfo.hClipboardData);
|
|
}
|
|
|
|
//
|
|
// Set handle to NULL, to mark it fresh when scanning more data.
|
|
// This handle is now owned by the Clipbpard...so freeing it would be a bad idea.
|
|
//
|
|
|
|
m_DataAcquireInfo.hClipboardData = NULL;
|
|
return bSuccess;
|
|
}
|
|
|
|
VOID CMSQSCANDlg::VerticalFlip(BYTE *pBuf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lHeight;
|
|
LONG lWidth;
|
|
BITMAPINFOHEADER *pbmih;
|
|
PBYTE pTop = NULL;
|
|
PBYTE pBottom = NULL;
|
|
|
|
pbmih = (BITMAPINFOHEADER*) pBuf;
|
|
|
|
if (pbmih->biHeight > 0) {
|
|
return;
|
|
}
|
|
|
|
pTop = pBuf + pbmih->biSize + ((pbmih->biClrUsed) * sizeof(RGBQUAD));
|
|
lWidth = ((pbmih->biWidth * pbmih->biBitCount + 31) / 32) * 4;
|
|
pbmih->biHeight = abs(pbmih->biHeight);
|
|
lHeight = pbmih->biHeight;
|
|
|
|
PBYTE pTempBuffer = (PBYTE)LocalAlloc(LPTR, lWidth);
|
|
|
|
if (pTempBuffer) {
|
|
LONG index = 0;
|
|
pBottom = pTop + (lHeight-1) * lWidth;
|
|
for (index = 0;index < (lHeight/2);index++) {
|
|
|
|
memcpy(pTempBuffer, pTop, lWidth);
|
|
memcpy(pTop, pBottom, lWidth);
|
|
memcpy(pBottom,pTempBuffer, lWidth);
|
|
|
|
pTop += lWidth;
|
|
pBottom -= lWidth;
|
|
}
|
|
LocalFree(pTempBuffer);
|
|
}
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::ResetWindowExtents()
|
|
{
|
|
|
|
LONG lMaxXExtent = 0;
|
|
LONG lMaxYExtent = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_XPOS,0);
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_YPOS,0);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_XEXTENT,WIA_RANGE_MAX,&lMaxXExtent);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.ReadRangeLong(NULL,WIA_IPS_YEXTENT,WIA_RANGE_MAX,&lMaxYExtent);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_XEXTENT,lMaxXExtent);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.WriteLong(NULL,WIA_IPS_YEXTENT,lMaxYExtent);
|
|
if(FAILED(hr)) {
|
|
MessageBox("Application failed to write y extent");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to write x extent");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read y extent");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read x extent");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to write y pos");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to write x pos");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::ReadADFSettings(ADF_SETTINGS *pADFSettings)
|
|
{
|
|
|
|
//#define USE_FAKE_ADFCAPS
|
|
#ifdef USE_FAKE_ADFCAPS
|
|
pADFSettings->lDocumentHandlingCapabilites = FEED| // Feeder
|
|
FLAT| // Flatbed
|
|
DUP; // Duplex
|
|
pADFSettings->lDocumentHandlingCapacity = 20; // 20 pages max
|
|
pADFSettings->lDocumentHandlingSelect = FLATBED| // Feeder Mode is ON
|
|
FRONT_FIRST|// scan front page first
|
|
FRONT_ONLY; // scan front only
|
|
|
|
pADFSettings->lDocumentHandlingStatus = FLAT_READY; // Feeder is ready
|
|
pADFSettings->lPages = 1; // Initialize pages to 1
|
|
return TRUE;
|
|
|
|
#endif
|
|
|
|
HRESULT hr = S_OK;
|
|
if(pADFSettings!= NULL) {
|
|
|
|
//
|
|
// Read Settings From Root Item
|
|
//
|
|
|
|
IWiaItem *pRootItem = NULL;
|
|
pRootItem = m_WIA.GetRootItem();
|
|
|
|
if(pRootItem != NULL) {
|
|
hr = m_WIA.ReadLong(pRootItem,WIA_DPS_DOCUMENT_HANDLING_SELECT,&pADFSettings->lDocumentHandlingSelect);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.ReadLong(pRootItem,WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES,&pADFSettings->lDocumentHandlingCapabilites);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.ReadLong(pRootItem,WIA_DPS_DOCUMENT_HANDLING_STATUS,&pADFSettings->lDocumentHandlingStatus);
|
|
if(SUCCEEDED(hr)){
|
|
hr = m_WIA.ReadLong(pRootItem,WIA_DPS_PAGES,&pADFSettings->lPages);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_WIA.ReadLong(pRootItem,WIA_DPS_DOCUMENT_HANDLING_CAPACITY,&pADFSettings->lDocumentHandlingCapacity);
|
|
if (FAILED(hr)) {
|
|
MessageBox("Application failed to read the Document Handling Capacity");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read the Pages Property");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read the Document Handling Status");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read the Document Handling Capabilites");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read the Document Handling Select Property");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to find the Root Item.");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to read ADF settings, because the pointer to the Settings structure is NULL");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMSQSCANDlg::WriteADFSettings(ADF_SETTINGS *pADFSettings)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if(pADFSettings!= NULL) {
|
|
|
|
//
|
|
// Write Settings to the Root Item
|
|
//
|
|
|
|
IWiaItem *pRootItem = NULL;
|
|
pRootItem = m_WIA.GetRootItem();
|
|
|
|
if(pRootItem != NULL) {
|
|
hr = m_WIA.WriteLong(pRootItem,WIA_DPS_DOCUMENT_HANDLING_SELECT,pADFSettings->lDocumentHandlingSelect);
|
|
if(FAILED(hr)){
|
|
MessageBox("Application failed to write ADF settings, because the Document Handling Select value failed to set");
|
|
return FALSE;
|
|
}
|
|
hr = m_WIA.WriteLong(pRootItem,WIA_DPS_PAGES,pADFSettings->lPages);
|
|
if(FAILED(hr)){
|
|
MessageBox("Application failed to write ADF settings, because the Pages property failed to set");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to find the Root Item.");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
MessageBox("Application failed to write ADF settings, because the pointer to the Settings structure is NULL");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CMSQSCANDlg::OnAdfSettings()
|
|
{
|
|
if(ReadADFSettings(&m_ADFSettings)) {
|
|
|
|
//
|
|
// create ADF dialog object
|
|
//
|
|
|
|
CADFDlg ADFDlg(&m_ADFSettings);
|
|
|
|
//
|
|
// display setting dialog
|
|
//
|
|
|
|
if(ADFDlg.DoModal() == IDOK) {
|
|
|
|
//
|
|
// write ADF settings back to the scanner if the user pushes the "OK" button
|
|
//
|
|
|
|
WriteADFSettings(&m_ADFSettings);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEventCallback message handlers
|
|
|
|
HRESULT _stdcall CEventCallback::QueryInterface(const IID& iid, void** ppv)
|
|
{
|
|
*ppv = NULL;
|
|
if (iid == IID_IUnknown || iid == IID_IWiaEventCallback)
|
|
*ppv = (IWiaEventCallback*) this;
|
|
else
|
|
return E_NOINTERFACE;
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG _stdcall CEventCallback::AddRef()
|
|
{
|
|
InterlockedIncrement((long*)&m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
ULONG _stdcall CEventCallback::Release()
|
|
{
|
|
ULONG ulRefCount = m_cRef - 1;
|
|
if (InterlockedDecrement((long*) &m_cRef) == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return ulRefCount;
|
|
}
|
|
|
|
CEventCallback::CEventCallback()
|
|
{
|
|
m_cRef = 0;
|
|
m_pIUnkRelease = NULL;
|
|
}
|
|
|
|
CEventCallback::~CEventCallback()
|
|
{
|
|
Release();
|
|
}
|
|
|
|
HRESULT _stdcall CEventCallback::Initialize(int EventID)
|
|
{
|
|
if((EventID > 1)||(EventID < 0))
|
|
return S_FALSE;
|
|
|
|
m_EventID = EventID;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT _stdcall CEventCallback::ImageEventCallback(
|
|
const GUID *pEventGUID,
|
|
BSTR bstrEventDescription,
|
|
BSTR bstrDeviceID,
|
|
BSTR bstrDeviceDescription,
|
|
DWORD dwDeviceType,
|
|
BSTR bstrFullItemName,
|
|
ULONG *plEventType,
|
|
ULONG ulReserved)
|
|
{
|
|
switch(m_EventID)
|
|
{
|
|
case ID_WIAEVENT_CONNECT:
|
|
MessageBox(NULL,"a connect event has been trapped...","Event Notice",MB_OK);
|
|
break;
|
|
case ID_WIAEVENT_DISCONNECT:
|
|
MessageBox(NULL,"a disconnect event has been trapped...","Event Notice",MB_OK);
|
|
break;
|
|
default:
|
|
AfxMessageBox("Ah HA!..an event just happened!!!!\n and...I have no clue what is was..");
|
|
break;
|
|
}
|
|
return S_OK;
|
|
}
|