// 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; }