From: Bernd Herd codeberg@herdsoft.com
Control display of progress dialog with CAP_INDICATORS.
Use PeekMessage/DispatchMessage loop while scanning. Display some informations on scan job in progress dialog --- dlls/sane.ds/capability.c | 46 +++++++++++++++++++++++++++++++- dlls/sane.ds/ds_ctrl.c | 4 ++- dlls/sane.ds/ds_image.c | 32 ++++++++++++++++++++--- dlls/sane.ds/resource.h | 15 +++++++++-- dlls/sane.ds/sane.rc | 25 ++++++++++++++++-- dlls/sane.ds/sane_i.h | 7 +++++ dlls/sane.ds/sane_main.c | 5 +++- dlls/sane.ds/ui.c | 55 ++++++++++++++++++++++++++++++++++++--- 8 files changed, 175 insertions(+), 14 deletions(-)
diff --git a/dlls/sane.ds/capability.c b/dlls/sane.ds/capability.c index 33b586b0824..7ae48071580 100644 --- a/dlls/sane.ds/capability.c +++ b/dlls/sane.ds/capability.c @@ -181,7 +181,7 @@ static TW_UINT16 msg_get_array(pTW_CAPABILITY pCapability, TW_UINT16 type, const
static TW_UINT16 TWAIN_GetSupportedCaps(pTW_CAPABILITY pCapability) { - static const int supported_caps[] = { CAP_SUPPORTEDCAPS, CAP_XFERCOUNT, CAP_UICONTROLLABLE, + static const int supported_caps[] = { CAP_SUPPORTEDCAPS, CAP_XFERCOUNT, CAP_UICONTROLLABLE, CAP_INDICATORS, CAP_AUTOFEED, CAP_FEEDERENABLED, ICAP_XFERMECH, ICAP_PIXELTYPE, ICAP_UNITS, ICAP_BITDEPTH, ICAP_COMPRESSION, ICAP_PIXELFLAVOR, ICAP_XRESOLUTION, ICAP_YRESOLUTION, ICAP_PHYSICALHEIGHT, ICAP_PHYSICALWIDTH, ICAP_SUPPORTEDSIZES }; @@ -1057,6 +1057,46 @@ static TW_UINT16 SANE_CAPFeederEnabled (pTW_CAPABILITY pCapability, TW_UINT16 ac }
+/* CAP_INDICATORS */ +static TW_UINT16 SANE_CAPIndicators (pTW_CAPABILITY pCapability, TW_UINT16 action) +{ + TW_UINT16 twCC = TWCC_BADCAP; + TW_UINT32 val; + + TRACE("CAP_INDICATORS\n"); + + switch (action) + { + case MSG_QUERYSUPPORT: + twCC = set_onevalue(pCapability, TWTY_INT32, + TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET ); + break; + + case MSG_GET: + twCC = set_onevalue(pCapability, TWTY_BOOL, activeDS.capIndicators); + break; + + case MSG_SET: + twCC = msg_set(pCapability, &val); + if (twCC == TWCC_SUCCESS) + activeDS.capIndicators = (TW_BOOL) val; + break; + + case MSG_GETDEFAULT: + twCC = set_onevalue(pCapability, TWTY_BOOL, TRUE); + break; + + case MSG_RESET: + activeDS.capIndicators = TRUE; + /* .. fall through intentional .. */ + + case MSG_GETCURRENT: + twCC = set_onevalue(pCapability, TWTY_BOOL, activeDS.capIndicators); + break; + } + return twCC; +} +
TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action) { @@ -1089,6 +1129,10 @@ TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action) twCC = SANE_CAPFeederEnabled (pCapability, action); break;
+ case CAP_INDICATORS: + twCC = SANE_CAPIndicators (pCapability, action); + break; + case ICAP_PIXELTYPE: twCC = SANE_ICAPPixelType (pCapability, action); break; diff --git a/dlls/sane.ds/ds_ctrl.c b/dlls/sane.ds/ds_ctrl.c index ac804b8858b..64f505d7712 100644 --- a/dlls/sane.ds/ds_ctrl.c +++ b/dlls/sane.ds/ds_ctrl.c @@ -211,7 +211,8 @@ TW_UINT16 SANE_PendingXfersEndXfer (pTW_IDENTITY pOrigin, pPendingXfers->Count = activeDS.capXferCount==-1 ? -1 : activeDS.capXferCount - activeDS.scannedImages; if (!pPendingXfers->Count || - !activeDS.feederEnabled) + !activeDS.feederEnabled || + activeDS.userCancelled) { /* All requested images transfered. Stop scanning */ pPendingXfers->Count = 0; @@ -403,6 +404,7 @@ TW_UINT16 SANE_EnableDSUserInterface (pTW_IDENTITY pOrigin, else { activeDS.hwndOwner = pUserInterface->hParent; + activeDS.ShowUI = pUserInterface->ShowUI; if (pUserInterface->ShowUI) { BOOL rc; diff --git a/dlls/sane.ds/ds_image.c b/dlls/sane.ds/ds_image.c index 37327bc5db6..27662ffc358 100644 --- a/dlls/sane.ds/ds_image.c +++ b/dlls/sane.ds/ds_image.c @@ -23,6 +23,7 @@ #include "wingdi.h" #include "winuser.h" #include "wine/debug.h" +#include "resource.h"
WINE_DEFAULT_DEBUG_CHANNEL(twain);
@@ -69,6 +70,23 @@ TW_UINT16 SANE_Start(void) return TWRC_FAILURE; }
+ if (activeDS.progressWnd) + { + char szFormat[20]; + int sid_format; + + switch (activeDS.frame_params.format) + { + case FMT_RGB: sid_format=IDS_COLOUR; break; + case FMT_GRAY: sid_format=activeDS.frame_params.depth==1 ? IDS_LINEART : IDS_GRAY; break; + default: sid_format=IDS_UNKNOWN; + } + + LoadStringA( SANE_instance, sid_format, szFormat, ARRAY_SIZE( szFormat ) ); + + SetDlgItemTextA(activeDS.progressWnd, IDC_RESOLUTION, szFormat); + } + TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n" , activeDS.frame_params.pixels_per_line, activeDS.frame_params.lines, activeDS.frame_params.depth, activeDS.frame_params.format, @@ -309,7 +327,7 @@ TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin, pImageMemXfer->BytesWritten = retlen; activeDS.YOffset += rows;
- ScanningDialogBox(activeDS.progressWnd, retlen); + ScanningDialogBox(activeDS.progressWnd, MulDiv(activeDS.YOffset, 100, activeDS.frame_params.lines));
if (retlen < activeDS.frame_params.bytes_per_line * rows) { @@ -329,6 +347,13 @@ TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin,
if (pImageMemXfer->Memory.Flags & TWMF_HANDLE) GlobalUnlock(pImageMemXfer->Memory.TheMem); + + if (activeDS.userCancelled) + { + SANE_Cancel(); + activeDS.twCC = TWCC_OPERATIONERROR; + twRC = TWRC_FAILURE; + }
return twRC; } @@ -514,13 +539,14 @@ TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, } } } - while (!eof); + while (!eof && !activeDS.userCancelled);
- if (twRC != TWCC_SUCCESS || y==0) + if (twRC != TWCC_SUCCESS || y==0 || activeDS.userCancelled) { WARN("sane_read: %u, reading line %d\n", twRC, y); SANE_Cancel(); activeDS.twCC = TWCC_OPERATIONERROR; + GlobalUnlock(hDIB); GlobalFree(hDIB); return TWRC_FAILURE; } diff --git a/dlls/sane.ds/resource.h b/dlls/sane.ds/resource.h index 2454fbd4ce2..f52e7956e4b 100644 --- a/dlls/sane.ds/resource.h +++ b/dlls/sane.ds/resource.h @@ -22,6 +22,17 @@ #include <winbase.h> #include <winuser.h>
-#define IDD_DIALOG1 0x400 +#define IDD_SCANNING 0x400
-#define IDC_STATIC 0x401 +#define IDC_STATIC -1 +#define IDC_PROGRESS 0x401 +#define IDC_MANUFACTURER 0x402 +#define IDC_PRODUCTFAMILY 0x403 +#define IDC_PRODUCTNAME 0x404 +#define IDC_RESOLUTION 0x405 +#define IDC_PAGE 0x406 + +#define IDS_GRAY 0x501 +#define IDS_COLOUR 0x502 +#define IDS_LINEART 0x503 +#define IDS_UNKNOWN 0x504 diff --git a/dlls/sane.ds/sane.rc b/dlls/sane.ds/sane.rc index eaa1640e07d..cc2a44302ab 100644 --- a/dlls/sane.ds/sane.rc +++ b/dlls/sane.ds/sane.rc @@ -35,10 +35,31 @@ STRINGTABLE 6 "#msgctxt#unit: microseconds#us" }
-IDD_DIALOG1 DIALOG 0, 0, 186, 46 +STRINGTABLE +BEGIN + IDS_GRAY,"Gray" + IDS_COLOUR,"Color" + IDS_LINEART,"LineArt" + IDS_UNKNOWN,"Unknown" +END + + +IDD_SCANNING DIALOG 53, 50, 186, 104 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE | DS_CENTER | DS_SETFOREGROUND CAPTION "Scanning" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "SCANNING... Please Wait",IDC_STATIC,5,19,176,8, SS_CENTER + LTEXT "Manufacturer:", IDC_STATIC, 1, 1, 51, 9 + LTEXT "", IDC_MANUFACTURER, 51, 1, 128, 9 + LTEXT "Productfamily:", IDC_STATIC, 1, 11, 51, 9 + LTEXT "", IDC_PRODUCTFAMILY, 51, 11, 128, 9 + LTEXT "Productname:", IDC_STATIC, 1, 20, 51, 9 + LTEXT "", IDC_PRODUCTNAME, 51, 20, 128, 9 + LTEXT "Resolution:", IDC_STATIC, 1, 29, 51, 9 + LTEXT "", IDC_RESOLUTION, 51, 29, 128, 9 + LTEXT "Page", IDC_STATIC, 1, 38, 51, 9 + LTEXT "", IDC_PAGE, 51, 38, 128, 9 + CTEXT "SCANNING... Please Wait", IDC_STATIC, 5, 53, 176, 8 + CONTROL "", IDC_PROGRESS,"msctls_progress32",0 | WS_VISIBLE | WS_CHILD | WS_DISABLED, 6, 68, 174, 9 + PUSHBUTTON "Cancel", IDCANCEL, 68, 85, 50, 14 END diff --git a/dlls/sane.ds/sane_i.h b/dlls/sane.ds/sane_i.h index 0691f02e22d..8c127ffb72e 100644 --- a/dlls/sane.ds/sane_i.h +++ b/dlls/sane.ds/sane_i.h @@ -46,6 +46,7 @@ struct tagActiveDS /* Capabilities */ TW_UINT16 capXferMech; /* ICAP_XFERMECH */ TW_INT16 capXferCount; /* ICAP_XFERCOUNT */ + TW_BOOL capIndicators; /* CAP_INDICATORS */ BOOL PixelTypeSet; TW_UINT16 defaultPixelType; /* ICAP_PIXELTYPE */ BOOL XResolutionSet; @@ -61,6 +62,12 @@ struct tagActiveDS
/* TRUE if we are scanning with an Automatic Document Feeder */ BOOL feederEnabled; + + /* TRUE if user pressed cancel in scanning dialog */ + BOOL userCancelled; + + /* TRUE if user interface dialog is shown in DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS */ + BOOL ShowUI; };
extern struct tagActiveDS activeDS; diff --git a/dlls/sane.ds/sane_main.c b/dlls/sane.ds/sane_main.c index 0ff665c08dd..a1d7ca5ca1d 100644 --- a/dlls/sane.ds/sane_main.c +++ b/dlls/sane.ds/sane_main.c @@ -82,6 +82,8 @@ static TW_UINT16 SANE_OpenDS( pTW_IDENTITY pOrigin, pTW_IDENTITY self) activeDS.appIdentity = *pOrigin; activeDS.capXferMech = TWSX_NATIVE; activeDS.capXferCount = -1; + activeDS.capIndicators = TRUE; + activeDS.ShowUI = FALSE; return TWRC_SUCCESS; } SANE_CALL( close_ds, NULL ); @@ -368,7 +370,7 @@ void SANE_Notify (TW_UINT16 message) /** @brief A new TWAIN data transfer is ready to be processed * * - Notify Application. - * - Set activeDS.remainingImages to start value. + * - Set activeDS.sannedImages to zero. * - Set activeDS.feederEnabled according to current sane parameters * if Automatic Document Feeder (ADF) is enabled. * - Notify the Application of MSG_XFERREADY. @@ -387,6 +389,7 @@ SANE_XferReady(void) activeDS.feederEnabled = sane_option_get_str ("source", current_source, sizeof(current_source)) == TWCC_SUCCESS && (current_source[0]=='A' || current_source[0]=='a'); + activeDS.userCancelled = FALSE;
SANE_Notify(MSG_XFERREADY); } diff --git a/dlls/sane.ds/ui.c b/dlls/sane.ds/ui.c index 3849220b4ef..d8d38e1f980 100644 --- a/dlls/sane.ds/ui.c +++ b/dlls/sane.ds/ui.c @@ -28,6 +28,7 @@ #include "winnls.h" #include "wingdi.h" #include "prsht.h" +#include "commctrl.h" #include "wine/debug.h" #include "resource.h"
@@ -1181,14 +1182,44 @@ static int CALLBACK PropSheetProc(HWND hwnd, UINT msg, LPARAM lParam)
static INT_PTR CALLBACK ScanningProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) + { + case WM_INITDIALOG: + { + SetDlgItemTextA(hwnd, IDC_MANUFACTURER , activeDS.identity.Manufacturer); + SetDlgItemTextA(hwnd, IDC_PRODUCTFAMILY, activeDS.identity.ProductFamily); + SetDlgItemTextA(hwnd, IDC_PRODUCTNAME , activeDS.identity.ProductName); + SetDlgItemInt(hwnd, IDC_PAGE, activeDS.scannedImages+1, TRUE); + } + break; + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDCANCEL: + WARN("User cancelled\n"); + activeDS.userCancelled = TRUE; + } + } + } return FALSE; }
HWND ScanningDialogBox(HWND dialog, LONG progress) { + static DWORD tickLast=0; + DWORD tickNow = GetTickCount(); + + if (!activeDS.capIndicators && + !activeDS.ShowUI) + { + return NULL; + } + if (!dialog) - dialog = CreateDialogW(SANE_instance, - (LPWSTR)MAKEINTRESOURCE(IDD_DIALOG1), NULL, ScanningProc); + { + dialog = CreateDialogW(SANE_instance, MAKEINTRESOURCEW(IDD_SCANNING), NULL, ScanningProc); + }
if (progress == -1) { @@ -1196,8 +1227,24 @@ HWND ScanningDialogBox(HWND dialog, LONG progress) return NULL; }
- RedrawWindow(dialog,NULL,NULL, - RDW_INTERNALPAINT|RDW_UPDATENOW|RDW_ALLCHILDREN); + if (tickNow - tickLast > 100) + { + MSG msg; + tickLast = tickNow; + + /* Update progress bar */ + SendDlgItemMessageA(dialog, IDC_PROGRESS, PBM_SETPOS, progress, 0); + + /* Perform message handling */ + while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (!IsDialogMessageA(dialog, &msg)) + { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + } + }
return dialog; }