Obsługa skanera

0

Czym najlepiej w Windowsach od XP wzwyż obsłużyć skaner(najlepiej jak najbogatszą paletę modeli tegoż piekielnego urządzenia)? Lepiej skorzystać z TWAIN czy WIA? Korzystam z MinGW(biblioteki windowsowe czasem lubią robić mu niespodzianki ;) ). Czy do WIA istnieje jakiś wrapper integrujący to api z Qt(coś takiego dla TWAIN'a chyba widziałem)?

Z góry dziękuję za wszelkie sugestie ;).

0

Dla WIA mam nawet gotowca pod visuala, do kopiowania zdjęć z kodaka.
UWAGA: program pyta o docelowy katalog, ale nie sprawdza czy nadpisuje pliki.

#include <windows.h>
#include <wia.h>
#include <sti.h>
#include <wchar.h>
#include <shlobj.h>

// compile for console
#pragma comment(lib, "c:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Lib\\wiaguid.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "oleaut32.lib")

ITEMIDLIST* ChooseDirectory()
{
	BROWSEINFO bi;
	ZeroMemory(&bi, sizeof(bi));
	bi.lpszTitle = L"Choose a diretory to save images";
	bi.ulFlags   = BIF_DONTGOBELOWDOMAIN | BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
	return SHBrowseForFolder(&bi);
}

void TransferImage(IWiaItem *pWiaItem, WCHAR *wszDirectory, WCHAR *name)
{
	IWiaPropertyStorage *pWiaPropertyStorage;
	if (!pWiaItem->QueryInterface(IID_IWiaPropertyStorage, (void**)&pWiaPropertyStorage))
	{
		IWiaDataTransfer *transfer;
		if (!pWiaItem->QueryInterface(IID_IWiaDataTransfer, (void**)&transfer))
		{
			STGMEDIUM medium;
			medium.tymed = TYMED_FILE;
			medium.lpszFileName = 0;
			medium.pUnkForRelease = 0;

			PROPSPEC PropSpec[2];
			PROPVARIANT PropVariant[2];
			PropSpec[0].ulKind = PRSPEC_PROPID;
			PropSpec[0].propid = WIA_IPA_FORMAT;
			PropVariant[0].vt = VT_CLSID;
			PropVariant[0].puuid = (CLSID*)&WiaImgFmt_JPEG;

			PropSpec[1].ulKind = PRSPEC_PROPID;
			PropSpec[1].propid = WIA_IPA_TYMED;
			PropVariant[1].vt = VT_I4;
			PropVariant[1].lVal = TYMED_FILE;

			pWiaPropertyStorage->WriteMultiple(2, PropSpec, PropVariant, WIA_IPA_FIRST);

			if (!transfer->idtGetData(&medium, NULL))
			{
				int cch = wcslen(wszDirectory);
				wcscpy(&wszDirectory[cch], name);
				CopyFileW(medium.lpszFileName, wszDirectory, false);
				wszDirectory[cch] = 0;
				ReleaseStgMedium(&medium);
			}
			else MessageBoxW(0, L"idtGetData failed", 0, 0);

			transfer->Release();
		}
		pWiaPropertyStorage->Release();
	}
}

int main()
{
	CoInitialize(0);
	IWiaDevMgr *mgr;
	SC_HANDLE manager = 0;
	SC_HANDLE service = 0;
	SERVICE_STATUS ss;
	BOOL ServiceWasDisabled = FALSE;
	BOOL ServiceHasBeenStarted = FALSE;
	QUERY_SERVICE_CONFIG *qsc = NULL;
	WCHAR wszDirectory[MAX_PATH];

	ITEMIDLIST *pidl = ChooseDirectory();
	if (!pidl) return 0;
	SHGetPathFromIDList(pidl, wszDirectory);
	CoTaskMemFree(pidl);
	wcscat(wszDirectory, L"\\");

	// jeżeli CoCreateInstance nawali, uruchom stisvc.
	// można to wywalić.
	if (!CoCreateInstance(CLSID_WiaDevMgr,0, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&mgr))
	{
		mgr->Release();
	}
	else // jednak nawaliło
	{
		manager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
		if (manager)
		{
			service = OpenService(manager, TEXT("stisvc"), MAXIMUM_ALLOWED);
			if (service)
			{
				if (QueryServiceStatus(service, &ss))
				{
					if (ss.dwCurrentState == SERVICE_STOPPED)
					{
						if (!StartService(service, 0, 0))
						{
							if (GetLastError() == ERROR_SERVICE_DISABLED)
							{
								DWORD cb = 0;
								QueryServiceConfig(service, 0,0, &cb);
								if (cb)
								{
									qsc = (QUERY_SERVICE_CONFIG*)new char[cb];
									if (QueryServiceConfig(service, qsc, cb, &cb))
									{
										if (ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE,0,0,0,0,0,0,0))
										{
											ServiceWasDisabled = TRUE;
											if (StartService(service, 0, 0))
											{
												ServiceHasBeenStarted = TRUE;
												for (int a=0; a<50; a++)
												{
													Sleep(100);
													QueryServiceStatus(service, &ss);
													if (ss.dwCurrentState == SERVICE_RUNNING) break;
												}
											}
										}
									}
									delete qsc;
								}
							}
						}
						else
						{
							ServiceHasBeenStarted = TRUE;
							for (int a=0; a<50; a++)
							{
								Sleep(100);
								QueryServiceStatus(service, &ss);
								if (ss.dwCurrentState == SERVICE_RUNNING) break;
							}
						}
					}
				}
				
			}
		}
	}
	if (!CoCreateInstance(CLSID_WiaDevMgr,0, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&mgr))
	{
		IEnumWIA_DEV_INFO *info;
		if (!mgr->EnumDeviceInfo(WIA_DEVINFO_ENUM_LOCAL, &info))
		{
			ULONG items = 0;
			info->GetCount(&items);
			IWiaPropertyStorage *properties;
			while (!info->Next(1, &properties, &items))
			{
				PROPSPEC propid[1];
				propid[0].ulKind = PRSPEC_PROPID;
				propid[0].propid = WIA_DIP_DEV_ID;//L"Unique Device ID";

				PROPVARIANT names[1];

				if (!properties->ReadMultiple(1, propid, names))
				{
					if (names[0].vt == VT_BSTR) // my kodak: L"{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\0000"
					{
						IWiaItem *device;
						if (!mgr->CreateDevice(names[0].bstrVal, &device))
						{
//ShowDeviceProps(device);
							// Determine if the selected device is a scanner
						//	if (IsScanner(device)) // disable this IF to grab images from foto camera or other devices
						//	{
								LONG nImages = 0;
								IWiaItem **pImages = 0; // receives pointer to IWiaItem* array

								// display scanner configuration dialog
								if (!device->DeviceDlg(0, WIA_DEVICE_DIALOG_USE_COMMON_UI, WIA_INTENT_NONE, &nImages, &pImages))
								{
									WCHAR szName[64];
									int index = 1;
									while (nImages) // scanner: 0 <= selected count <= 1
									{
										nImages--;
										IWiaItem *pImage = pImages[nImages];
										swprintf(szName, L"image %.3d.jpg", nImages);
										TransferImage(pImage, wszDirectory, szName);

										pImage->Release();
									}
									CoTaskMemFree(pImages);
								}
						//	}
							device->Release();
						}
						PropVariantClear(&names[0]);
					}
				}
				properties->Release();
			}
		}
		else
		{
			MessageBox(0, TEXT("IWiaDevMgr::EnumDeviceInfo error"),0,0);
		}
		mgr->Release();
	}
	else
	{
		MessageBox(0, TEXT("CoCreateInstance CLSID_WiaDevMgr error"),0,0);
	}

	if (manager)
	{
		if (service)
		{
			if (ServiceHasBeenStarted)
			{
				ControlService(service, SERVICE_CONTROL_STOP, &ss);
			}
			if (ServiceWasDisabled)
			{
				ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE,0,0,0,0,0,0,0);
			}
			CloseServiceHandle(service);
		}
		CloseServiceHandle(manager);
	}
	CoUninitialize();
}


//-------------------------------------------------------------
BOOL IsScanner(IWiaItem *device)
{
	BOOL is = FALSE;
	IWiaPropertyStorage *properties;
	if (!device->QueryInterface(IID_IWiaPropertyStorage, (void**)&properties))
	{
		PROPSPEC spec;
		spec.ulKind = PRSPEC_PROPID;
		spec.propid = WIA_DIP_DEV_TYPE;

		PROPVARIANT pv;
		if (!properties->ReadMultiple(1, &spec, &pv))
		{
			is = (GET_STIDEVICE_TYPE(pv.lVal) == StiDeviceTypeScanner);
			PropVariantClear(&pv);
		}
		properties->Release();
	}
	return is;
}

//-------------------------------------------------------------
void ShowDeviceProps(IWiaItem *device) // displays the properties of selected device group, device, or image format
{
	IWiaPropertyStorage *properties;
	if (!device->QueryInterface(IID_IWiaPropertyStorage, (void**)&properties))
	{
		IEnumSTATPROPSTG *enumerator;
		if (!properties->Enum(&enumerator))
		{
			STATPROPSTG item;
			ULONG       items;
			while (!enumerator->Next(1, &item, &items))
			{
				if (item.lpwstrName)
				{
					wprintf(L"%s: ", item.lpwstrName);
					CoTaskMemFree(item.lpwstrName);
				}
				else
				{
					wprintf(L"%.8X: ", item.propid);
				}
				PROPSPEC PropSpec;
				PROPVARIANT PropVar;

				PropSpec.ulKind = PRSPEC_PROPID;
				PropSpec.propid = item.propid;

				if (!properties->ReadMultiple(1, &PropSpec, &PropVar))
				{
					if (!VariantChangeType((VARIANTARG*)&PropVar, (VARIANTARG*)&PropVar, VARIANT_ALPHABOOL, VT_BSTR))
					{
						wprintf(L"%s\n", PropVar.bstrVal);
					}
					else wprintf(L"failed\n");
				}//else wprintf(L"ReadMultiple failed\n");
			}
			enumerator->Release();
		}//else wprintf(L"properties->Enum failed\n");

		properties->Release();
	}//else wprintf(L"IWiaPropertyStorage failed\n");
}
0

Dzięki!
Jutro pobawię się z przerobieniem .lib na .a ;). I spróbuję wykorzystać kod w praktyce :).

1 użytkowników online, w tym zalogowanych: 0, gości: 1