Signed-off-by: Vincent Povirk vincent@codeweavers.com --- dlls/twain_32/Makefile.in | 2 + dlls/twain_32/dsm_ctrl.c | 114 ++++++++++++++++++++++++++++++++++++++----- dlls/twain_32/resource.h | 25 ++++++++++ dlls/twain_32/twain.rc | 34 +++++++++++++ dlls/twain_32/twain32_main.c | 18 +++++++ dlls/twain_32/twain_i.h | 2 + 6 files changed, 182 insertions(+), 13 deletions(-) create mode 100644 dlls/twain_32/resource.h create mode 100644 dlls/twain_32/twain.rc
diff --git a/dlls/twain_32/Makefile.in b/dlls/twain_32/Makefile.in index cadaf8081d8..c82b5a74453 100644 --- a/dlls/twain_32/Makefile.in +++ b/dlls/twain_32/Makefile.in @@ -4,3 +4,5 @@ IMPORTS = user32 C_SRCS = \ dsm_ctrl.c \ twain32_main.c + +RC_SRCS = twain.rc diff --git a/dlls/twain_32/dsm_ctrl.c b/dlls/twain_32/dsm_ctrl.c index 9b878676656..bfd0651cb46 100644 --- a/dlls/twain_32/dsm_ctrl.c +++ b/dlls/twain_32/dsm_ctrl.c @@ -30,6 +30,7 @@ #include "winuser.h" #include "twain.h" #include "twain_i.h" +#include "resource.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(twain); @@ -345,24 +346,111 @@ TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) return TWRC_SUCCESS; }
+typedef struct { + pTW_IDENTITY origin; + pTW_IDENTITY result; +} userselect_data; + +INT_PTR CALLBACK userselect_dlgproc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + userselect_data *data = (userselect_data*)lparam; + int i; + HWND sourcelist; + BOOL any_devices = FALSE; + + SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)data); + + sourcelist = GetDlgItem(hwnd, IDC_LISTSOURCE); + + for (i=0; i<nrdevices; i++) + { + TW_IDENTITY *id = &devices[i].identity; + LRESULT index; + + if ((id->SupportedGroups & data->origin->SupportedGroups) == 0) + continue; + + index = SendMessageA(sourcelist, LB_ADDSTRING, 0, (LPARAM)id->ProductName); + SendMessageW(sourcelist, LB_SETITEMDATA, (WPARAM)index, (LPARAM)i); + any_devices = TRUE; + } + + if (any_devices) + { + EnableWindow(GetDlgItem(hwnd, IDOK), TRUE); + + /* FIXME: Select the supplied product name or default source. */ + SendMessageW(sourcelist, LB_SETCURSEL, 0, 0); + } + + return TRUE; + } + case WM_CLOSE: + EndDialog(hwnd, 0); + return TRUE; + case WM_COMMAND: + if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED)) + { + EndDialog(hwnd, 0); + return TRUE; + } + else if (wparam == MAKEWPARAM(IDOK, BN_CLICKED) || + wparam == MAKEWPARAM(IDC_LISTSOURCE, LBN_DBLCLK)) + { + userselect_data *data = (userselect_data*)GetWindowLongPtrW(hwnd, DWLP_USER); + HWND sourcelist; + LRESULT index; + + sourcelist = GetDlgItem(hwnd, IDC_LISTSOURCE); + + index = SendMessageW(sourcelist, LB_GETCURSEL, 0, 0); + + if (index == LB_ERR) + return TRUE; + + index = SendMessageW(sourcelist, LB_GETITEMDATA, (WPARAM)index, 0); + + *data->result = devices[index].identity; + + /* FIXME: Save this as the default source */ + + EndDialog(hwnd, 1); + return TRUE; + } + break; + } + return FALSE; +} + /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */ TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData) { - pTW_IDENTITY selected = (pTW_IDENTITY)pData; + userselect_data param = {pOrigin, pData}; + HWND parent = DSM_parent;
- TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT SupportedGroups=0x%x ProductName=%s\n", - selected->SupportedGroups, wine_dbgstr_a(selected->ProductName)); + TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT SupportedGroups=0x%x ProductName=%s\n", + pOrigin->SupportedGroups, wine_dbgstr_a(param.result->ProductName));
- twain_autodetect(); - if (!nrdevices) { - TRACE("<-- TWRC_FAILURE\n"); - DSM_twCC = TWCC_OPERATIONERROR; - return TWRC_FAILURE; - } - *selected = devices[0].identity; - TRACE("<-- %s\n", wine_dbgstr_a(selected->ProductName)); - DSM_twCC = TWCC_SUCCESS; - return TWRC_SUCCESS; + twain_autodetect(); + + if (!IsWindow(parent)) + parent = NULL; + + if (DialogBoxParamW(DSM_hinstance, MAKEINTRESOURCEW(DLG_USERSELECT), + parent, userselect_dlgproc, (LPARAM)¶m) == 0) + { + TRACE("canceled\n"); + DSM_twCC = TWCC_SUCCESS; + return TWRC_CANCEL; + } + + TRACE("<-- %s\n", wine_dbgstr_a(param.result->ProductName)); + DSM_twCC = TWCC_SUCCESS; + return TWRC_SUCCESS; }
/* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */ diff --git a/dlls/twain_32/resource.h b/dlls/twain_32/resource.h new file mode 100644 index 00000000000..366f52f181c --- /dev/null +++ b/dlls/twain_32/resource.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Vincent Povirk for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windef.h> +#include <winuser.h> + +#define DLG_USERSELECT 1 + +#define IDC_LISTSOURCE 1001 + diff --git a/dlls/twain_32/twain.rc b/dlls/twain_32/twain.rc new file mode 100644 index 00000000000..2c5939308d5 --- /dev/null +++ b/dlls/twain_32/twain.rc @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Vincent Povirk for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "resource.h" + +#pragma makedep po + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +DLG_USERSELECT DIALOG 0, 0, 140, 140 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_NOIDLEMSG +FONT 8, "MS Shell Dlg" +CAPTION "Select Source" +{ + LISTBOX IDC_LISTSOURCE, 7, 7, 126, 104 + DEFPUSHBUTTON "OK", IDOK, 29, 118, 50, 15, BS_DEFPUSHBUTTON|WS_TABSTOP|WS_DISABLED + PUSHBUTTON "Cancel", IDCANCEL, 83, 118, 50, 15 +} + diff --git a/dlls/twain_32/twain32_main.c b/dlls/twain_32/twain32_main.c index d1977b4d75f..016680b96eb 100644 --- a/dlls/twain_32/twain32_main.c +++ b/dlls/twain_32/twain32_main.c @@ -31,6 +31,24 @@
WINE_DEFAULT_DEBUG_CHANNEL(twain);
+extern HINSTANCE DSM_hinstance; + +BOOL WINAPI DllMain (HINSTANCE hinstance, DWORD reason, LPVOID reserved) +{ + TRACE("%p,%x,%p\n", hinstance, reason, reserved); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstance); + DSM_hinstance = hinstance; + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + /* A helper function that looks up a destination identity in the active source list */ static activeDS *TWAIN_LookupSource (const TW_IDENTITY *pDest) diff --git a/dlls/twain_32/twain_i.h b/dlls/twain_32/twain_i.h index f46999c6fa1..4d33135344e 100644 --- a/dlls/twain_32/twain_i.h +++ b/dlls/twain_32/twain_i.h @@ -53,6 +53,8 @@ TW_UINT16 DSM_twCC DECLSPEC_HIDDEN; /* current condition code of Sou
activeDS *activeSources DECLSPEC_HIDDEN; /* list of active data sources */
+HINSTANCE DSM_hinstance DECLSPEC_HIDDEN; + /* Implementation of operation triplets (From Application to Source Manager) */ extern TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) DECLSPEC_HIDDEN;