4 * Copyright 2006 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
37 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(twain
);
45 #define ID_EDIT_BASE 0x1000
46 #define ID_STATIC_BASE 0x2000
48 static INT_PTR CALLBACK
DialogProc (HWND
, UINT
, WPARAM
, LPARAM
);
49 static INT CALLBACK
PropSheetProc(HWND
, UINT
,LPARAM
);
51 static int create_leading_static(HDC hdc
, LPCSTR text
,
52 LPDLGITEMTEMPLATEW
* template_out
, int y
, int id
)
54 LPDLGITEMTEMPLATEW tpl
= NULL
;
65 base
= GetDialogBaseUnits();
67 len
= MultiByteToWideChar(CP_ACP
,0,text
,-1,NULL
,0);
69 len
+= sizeof(DLGITEMTEMPLATE
);
70 len
+= 3*sizeof(WORD
);
72 tpl
= HeapAlloc(GetProcessHeap(),0,len
);
73 tpl
->style
=WS_VISIBLE
;
74 tpl
->dwExtendedStyle
= 0;
79 GetTextExtentPoint32A(hdc
,text
,lstrlenA(text
),&size
);
81 tpl
->cx
= MulDiv(size
.cx
,4,LOWORD(base
));
82 tpl
->cy
= MulDiv(size
.cy
,8,HIWORD(base
)) * 2;
83 ptr
= (LPBYTE
)tpl
+ sizeof(DLGITEMTEMPLATE
);
84 *(LPWORD
)ptr
= 0xffff;
86 *(LPWORD
)ptr
= 0x0082;
88 ptr
+= MultiByteToWideChar(CP_ACP
,0,text
,-1,(LPWSTR
)ptr
,len
) * sizeof(WCHAR
);
89 *(LPWORD
)ptr
= 0x0000;
95 static int create_trailing_edit(HDC hdc
, LPDLGITEMTEMPLATEW
* template_out
, int id
,
96 int y
, LPCSTR text
,BOOL is_int
)
98 LPDLGITEMTEMPLATEW tpl
= NULL
;
103 static const char int_base
[] = "0000 xxx";
104 static const char float_base
[] = "0000.0000 xxx";
106 base
= GetDialogBaseUnits();
108 len
= MultiByteToWideChar(CP_ACP
,0,text
,-1,NULL
,0);
109 len
*= sizeof(WCHAR
);
110 len
+= sizeof(DLGITEMTEMPLATE
);
111 len
+= 3*sizeof(WORD
);
113 tpl
= HeapAlloc(GetProcessHeap(),0,len
);
114 tpl
->style
=WS_VISIBLE
|ES_READONLY
|WS_BORDER
;
115 tpl
->dwExtendedStyle
= 0;
121 GetTextExtentPoint32A(hdc
,int_base
,lstrlenA(int_base
),&size
);
123 GetTextExtentPoint32A(hdc
,float_base
,lstrlenA(float_base
),&size
);
125 tpl
->cx
= MulDiv(size
.cx
*2,4,LOWORD(base
));
126 tpl
->cy
= MulDiv(size
.cy
,8,HIWORD(base
)) * 2;
128 ptr
= (LPBYTE
)tpl
+ sizeof(DLGITEMTEMPLATE
);
129 *(LPWORD
)ptr
= 0xffff;
131 *(LPWORD
)ptr
= 0x0081;
133 ptr
+= MultiByteToWideChar(CP_ACP
,0,text
,-1,(LPWSTR
)ptr
,len
) * sizeof(WCHAR
);
134 *(LPWORD
)ptr
= 0x0000;
141 static int create_item(HDC hdc
, const SANE_Option_Descriptor
*opt
,
142 INT id
, LPDLGITEMTEMPLATEW
*template_out
, int y
, int *cx
, int* count
)
144 LPDLGITEMTEMPLATEW tpl
= NULL
,rc
= NULL
;
146 DWORD styles
= WS_VISIBLE
;
148 LPDLGITEMTEMPLATEW lead_static
= NULL
;
149 LPDLGITEMTEMPLATEW trail_edit
= NULL
;
150 DWORD leading_len
= 0;
162 GetTextExtentPoint32A(hdc
,"X",1,&size
);
163 base
= GetDialogBaseUnits();
164 base_x
= MulDiv(size
.cx
,4,LOWORD(base
));
166 if (opt
->type
== SANE_TYPE_BOOL
)
168 class = 0x0080; /* Button */
169 styles
|= BS_AUTOCHECKBOX
;
170 local_len
+= MultiByteToWideChar(CP_ACP
,0,opt
->title
,-1,NULL
,0);
171 local_len
*= sizeof(WCHAR
);
174 else if (opt
->type
== SANE_TYPE_INT
)
178 sane_control_option(activeDS
.deviceHandle
, id
-ID_BASE
,
179 SANE_ACTION_GET_VALUE
, &i
,NULL
);
181 sprintf(buffer
,"%i",i
);
183 if (opt
->constraint_type
== SANE_CONSTRAINT_NONE
)
185 class = 0x0081; /* Edit*/
188 local_len
+= MultiByteToWideChar(CP_ACP
,0,title
,-1,NULL
,0);
189 local_len
*= sizeof(WCHAR
);
191 else if (opt
->constraint_type
== SANE_CONSTRAINT_RANGE
)
193 class = 0x0084; /* scroll */
194 ctl_cx
= 10 * base_x
;
195 trail_len
+= create_trailing_edit(hdc
, &trail_edit
, id
+
196 ID_EDIT_BASE
, y
,buffer
,TRUE
);
200 class= 0x0085; /* Combo */
201 ctl_cx
= 10 * base_x
;
202 styles
|= CBS_DROPDOWNLIST
;
204 leading_len
+= create_leading_static(hdc
, opt
->title
, &lead_static
, y
,
207 else if (opt
->type
== SANE_TYPE_FIXED
)
212 i
= HeapAlloc(GetProcessHeap(),0,opt
->size
*sizeof(SANE_Word
));
214 sane_control_option(activeDS
.deviceHandle
, id
-ID_BASE
,
215 SANE_ACTION_GET_VALUE
, i
, NULL
);
218 sprintf(buffer
,"%f",dd
);
219 HeapFree(GetProcessHeap(),0,i
);
221 if (opt
->constraint_type
== SANE_CONSTRAINT_NONE
)
223 class = 0x0081; /* Edit */
225 local_len
+= MultiByteToWideChar(CP_ACP
,0,title
,-1,NULL
,0);
226 local_len
*= sizeof(WCHAR
);
228 else if (opt
->constraint_type
== SANE_CONSTRAINT_RANGE
)
230 class= 0x0084; /* scroll */
231 ctl_cx
= 10 * base_x
;
232 trail_len
+= create_trailing_edit(hdc
, &trail_edit
, id
+
233 ID_EDIT_BASE
, y
,buffer
,FALSE
);
237 class= 0x0085; /* Combo */
238 ctl_cx
= 10 * base_x
;
239 styles
|= CBS_DROPDOWNLIST
;
241 leading_len
+= create_leading_static(hdc
, opt
->title
, &lead_static
, y
,
244 else if (opt
->type
== SANE_TYPE_STRING
)
246 if (opt
->constraint_type
== SANE_CONSTRAINT_NONE
)
248 class = 0x0081; /* Edit*/
252 class= 0x0085; /* Combo */
253 ctl_cx
= opt
->size
* base_x
;
254 styles
|= CBS_DROPDOWNLIST
;
256 leading_len
+= create_leading_static(hdc
, opt
->title
, &lead_static
, y
,
258 sane_control_option(activeDS
.deviceHandle
, id
-ID_BASE
,
259 SANE_ACTION_GET_VALUE
, buffer
,NULL
);
262 local_len
+= MultiByteToWideChar(CP_ACP
,0,title
,-1,NULL
,0);
263 local_len
*= sizeof(WCHAR
);
265 else if (opt
->type
== SANE_TYPE_BUTTON
)
267 class = 0x0080; /* Button */
268 local_len
+= MultiByteToWideChar(CP_ACP
,0,opt
->title
,-1,NULL
,0);
269 local_len
*= sizeof(WCHAR
);
272 else if (opt
->type
== SANE_TYPE_GROUP
)
274 class = 0x0080; /* Button */
275 styles
|= BS_GROUPBOX
;
276 local_len
+= MultiByteToWideChar(CP_ACP
,0,opt
->title
,-1,NULL
,0);
277 local_len
*= sizeof(WCHAR
);
281 local_len
+= sizeof(DLGITEMTEMPLATE
);
283 local_len
+= 3*sizeof(WORD
);
285 local_len
+= 4*sizeof(WORD
);
289 padding
= leading_len
% sizeof(DWORD
);
290 rc
= HeapReAlloc(GetProcessHeap(),0,lead_static
,leading_len
+local_len
+ padding
);
291 tpl
= (LPDLGITEMTEMPLATEW
)((LPBYTE
)rc
+ leading_len
+ padding
);
294 rc
= tpl
= HeapAlloc(GetProcessHeap(),0,local_len
);
297 tpl
->dwExtendedStyle
= 0;
299 tpl
->x
= lead_static
->x
+ lead_static
->cx
+ 1;
300 else if (opt
->type
== SANE_TYPE_GROUP
)
309 GetTextExtentPoint32A(hdc
,title
,lstrlenA(title
),&size
);
316 tpl
->cy
= lead_static
->cy
;
325 ptr
= (LPBYTE
)tpl
+ sizeof(DLGITEMTEMPLATE
);
326 *(LPWORD
)ptr
= 0xffff;
328 *(LPWORD
)ptr
= class;
332 ptr
+= MultiByteToWideChar(CP_ACP
,0,title
,-1,(LPWSTR
)ptr
,local_len
) * sizeof(WCHAR
);
336 *(LPWORD
)ptr
= 0x0000;
340 *((LPWORD
)ptr
) = 0x0000;
345 trail_edit
->x
= tpl
->cx
+ tpl
->x
+ 2;
346 *cx
= trail_edit
->x
+ trail_edit
->cx
;
348 padding2
= (leading_len
+ local_len
+ padding
)% sizeof(DWORD
);
350 rc
= HeapReAlloc(GetProcessHeap(),0,rc
,leading_len
+local_len
+ padding
351 +padding2
+trail_len
);
353 memcpy(((LPBYTE
)rc
) + leading_len
+ local_len
+ padding
+ padding2
,
354 trail_edit
,trail_len
);
357 *cx
= tpl
->cx
+ tpl
->x
;
368 return leading_len
+ local_len
+ padding
+ padding2
+ trail_len
;
372 static LPDLGTEMPLATEW
create_options_page(HDC hdc
, int *from_index
,
379 LPDLGTEMPLATEW tpl
= NULL
;
380 LPBYTE all_controls
= NULL
;
381 DWORD control_len
= 0;
383 int group_max_cx
= 0;
385 int group_offset
= -1;
386 INT control_count
= 0;
388 rc
= sane_control_option(activeDS
.deviceHandle
, 0, SANE_ACTION_GET_VALUE
,
391 if (rc
!= SANE_STATUS_GOOD
)
393 ERR("Unable to read number of options\n");
397 for (i
= *from_index
; i
< optcount
; i
++)
399 LPDLGITEMTEMPLATEW item_tpl
= NULL
;
400 const SANE_Option_Descriptor
*opt
;
405 int hold_for_group
= 0;
407 opt
= sane_get_option_descriptor(activeDS
.deviceHandle
, i
);
408 if (opt
->type
== SANE_TYPE_GROUP
&& split_tabs
)
422 len
= create_item(hdc
, opt
, ID_BASE
+ i
, &item_tpl
, y
, &x
, &count
);
424 control_count
+= count
;
432 y
+= item_tpl
->cy
+ 1;
433 max_cx
= max(max_cx
, x
+ 2);
434 group_max_cx
= max(group_max_cx
, x
);
436 padding
= len
% sizeof(DWORD
);
441 newone
= HeapReAlloc(GetProcessHeap(),0,all_controls
,
442 control_len
+ len
+ padding
);
443 all_controls
= newone
;
444 memcpy(all_controls
+control_len
,item_tpl
,len
);
445 memset(all_controls
+control_len
+len
,0xca,padding
);
446 HeapFree(GetProcessHeap(),0,item_tpl
);
452 all_controls
= (LPBYTE
)item_tpl
;
456 all_controls
= HeapAlloc(GetProcessHeap(),0,len
+ padding
);
457 memcpy(all_controls
,item_tpl
,len
);
458 memset(all_controls
+len
,0xcb,padding
);
459 HeapFree(GetProcessHeap(),0,item_tpl
);
463 if (opt
->type
== SANE_TYPE_GROUP
)
465 if (group_offset
== -1)
467 group_offset
= control_len
;
472 LPDLGITEMTEMPLATEW group
=
473 (LPDLGITEMTEMPLATEW
)(all_controls
+group_offset
);
475 group
->cy
= hold_for_group
- group
->y
;
476 group
->cx
= group_max_cx
;
478 group
= (LPDLGITEMTEMPLATEW
)(all_controls
+control_len
);
482 group_offset
= control_len
;
486 control_len
+= len
+ padding
;
489 if ( group_offset
&& !split_tabs
)
491 LPDLGITEMTEMPLATEW group
=
492 (LPDLGITEMTEMPLATEW
)(all_controls
+group_offset
);
493 group
->cy
= y
- group
->y
;
494 group
->cx
= group_max_cx
;
501 tpl
= HeapAlloc(GetProcessHeap(),0,sizeof(DLGTEMPLATE
) + 3*sizeof(WORD
) +
504 tpl
->style
= WS_VISIBLE
| WS_OVERLAPPEDWINDOW
;
505 tpl
->dwExtendedStyle
= 0;
506 tpl
->cdit
= control_count
;
509 tpl
->cx
= max_cx
+ 10;
511 ptr
= (LPBYTE
)tpl
+ sizeof(DLGTEMPLATE
);
512 *(LPWORD
)ptr
= 0x0000;
514 *(LPWORD
)ptr
= 0x0000;
516 *(LPWORD
)ptr
= 0x0000;
518 memcpy(ptr
,all_controls
,control_len
);
520 HeapFree(GetProcessHeap(),0,all_controls
);
525 BOOL
DoScannerUI(void)
528 PROPSHEETPAGEW psp
[10];
530 PROPSHEETHEADERW psh
;
540 memset(&psp
,0,sizeof(psp
));
541 rc
= sane_control_option(activeDS
.deviceHandle
, 0, SANE_ACTION_GET_VALUE
,
544 while (index
< optcount
)
546 const SANE_Option_Descriptor
*opt
;
547 psp
[page_count
].u
.pResource
= create_options_page(hdc
, &index
,
549 opt
= sane_get_option_descriptor(activeDS
.deviceHandle
, index
);
551 if (opt
->type
== SANE_TYPE_GROUP
)
556 len
= MultiByteToWideChar(CP_ACP
,0,opt
->title
,-1,NULL
,0);
557 title
= HeapAlloc(GetProcessHeap(),0,len
* sizeof(WCHAR
));
558 MultiByteToWideChar(CP_ACP
,0,opt
->title
,-1,title
,len
);
560 psp
[page_count
].pszTitle
= title
;
563 if (psp
[page_count
].u
.pResource
)
565 psp
[page_count
].dwSize
= sizeof(PROPSHEETPAGEW
);
566 psp
[page_count
].dwFlags
= PSP_DLGINDIRECT
| PSP_USETITLE
;
567 psp
[page_count
].hInstance
= SANE_instance
;
568 psp
[page_count
].pfnDlgProc
= DialogProc
;
569 psp
[page_count
].lParam
= (LPARAM
)&activeDS
;
576 len
= lstrlenA(activeDS
.identity
.Manufacturer
)
577 + lstrlenA(activeDS
.identity
.ProductName
) + 2;
578 szCaption
= HeapAlloc(GetProcessHeap(),0,len
*sizeof(WCHAR
));
579 MultiByteToWideChar(CP_ACP
,0,activeDS
.identity
.Manufacturer
,-1,
581 szCaption
[lstrlenA(activeDS
.identity
.Manufacturer
)] = ' ';
582 MultiByteToWideChar(CP_ACP
,0,activeDS
.identity
.ProductName
,-1,
583 &szCaption
[lstrlenA(activeDS
.identity
.Manufacturer
)+1],len
);
584 psh
.dwSize
= sizeof(PROPSHEETHEADERW
);
585 psh
.dwFlags
= PSH_PROPSHEETPAGE
|PSH_PROPTITLE
|PSH_USECALLBACK
;
586 psh
.hwndParent
= activeDS
.hwndOwner
;
587 psh
.hInstance
= SANE_instance
;
589 psh
.pszCaption
= szCaption
;
590 psh
.nPages
= page_count
;
591 psh
.u2
.nStartPage
= 0;
592 psh
.u3
.ppsp
= (LPCPROPSHEETPAGEW
) &psp
;
593 psh
.pfnCallback
= PropSheetProc
;
595 psrc
= PropertySheetW(&psh
);
597 for(index
= 0; index
< page_count
; index
++)
599 HeapFree(GetProcessHeap(),0,(LPBYTE
)psp
[index
].u
.pResource
);
600 HeapFree(GetProcessHeap(),0,(LPBYTE
)psp
[index
].pszTitle
);
609 static void UpdateRelevantEdit(HWND hwnd
, const SANE_Option_Descriptor
*opt
,
610 int index
, int position
)
616 LoadStringA(SANE_instance
, opt
->unit
, unit
,20);
618 if (opt
->type
== SANE_TYPE_INT
)
622 if (opt
->constraint
.range
->quant
)
623 si
= position
* opt
->constraint
.range
->quant
;
627 sprintf(buffer
,"%i %s",si
,unit
);
630 else if (opt
->type
== SANE_TYPE_FIXED
)
634 s_quant
= SANE_UNFIX(opt
->constraint
.range
->quant
);
637 dd
= position
* s_quant
;
639 dd
= position
* 0.01;
641 sprintf(buffer
,"%f %s",dd
,unit
);
646 edit_w
= GetDlgItem(hwnd
,index
+ID_BASE
+ID_EDIT_BASE
);
647 if (edit_w
&& buffer
[0])
648 SetWindowTextA(edit_w
,buffer
);
652 static BOOL
UpdateSaneScrollOption(
653 const SANE_Option_Descriptor
*opt
, int index
, DWORD position
)
655 SANE_Status rc
= SANE_STATUS_GOOD
;
658 if (opt
->type
== SANE_TYPE_INT
)
662 if (opt
->constraint
.range
->quant
)
663 si
= position
* opt
->constraint
.range
->quant
;
667 rc
= sane_control_option (activeDS
.deviceHandle
,index
,
668 SANE_ACTION_SET_VALUE
, &si
, &result
);
671 else if (opt
->type
== SANE_TYPE_FIXED
)
676 s_quant
= SANE_UNFIX(opt
->constraint
.range
->quant
);
679 dd
= position
* s_quant
;
681 dd
= position
* 0.01;
683 sf
= HeapAlloc(GetProcessHeap(),0,opt
->size
*sizeof(SANE_Word
));
687 rc
= sane_control_option (activeDS
.deviceHandle
,index
,
688 SANE_ACTION_SET_VALUE
, sf
, &result
);
690 HeapFree(GetProcessHeap(),0,sf
);
693 if(rc
== SANE_STATUS_GOOD
)
695 if (result
& SANE_INFO_RELOAD_OPTIONS
||
696 result
& SANE_INFO_RELOAD_PARAMS
|| result
& SANE_INFO_INEXACT
)
702 static BOOL
UpdateSaneBoolOption(int index
, BOOL position
)
704 SANE_Status rc
= SANE_STATUS_GOOD
;
710 rc
= sane_control_option (activeDS
.deviceHandle
,index
,
711 SANE_ACTION_SET_VALUE
, &si
, &result
);
713 if(rc
== SANE_STATUS_GOOD
)
715 if (result
& SANE_INFO_RELOAD_OPTIONS
||
716 result
& SANE_INFO_RELOAD_PARAMS
|| result
& SANE_INFO_INEXACT
)
722 static BOOL
UpdateSaneStringOption(int index
, SANE_String value
)
724 SANE_Status rc
= SANE_STATUS_GOOD
;
727 rc
= sane_control_option (activeDS
.deviceHandle
,index
,
728 SANE_ACTION_SET_VALUE
, value
, &result
);
730 if(rc
== SANE_STATUS_GOOD
)
732 if (result
& SANE_INFO_RELOAD_OPTIONS
||
733 result
& SANE_INFO_RELOAD_PARAMS
|| result
& SANE_INFO_INEXACT
)
739 static INT_PTR
InitializeDialog(HWND hwnd
)
746 rc
= sane_control_option(activeDS
.deviceHandle
, 0, SANE_ACTION_GET_VALUE
,
749 for ( i
= 1; i
< optcount
; i
++)
751 const SANE_Option_Descriptor
*opt
;
753 control
= GetDlgItem(hwnd
,i
+ID_BASE
);
758 opt
= sane_get_option_descriptor(activeDS
.deviceHandle
, i
);
760 TRACE("%i %s %i %i\n",i
,opt
->title
,opt
->type
,opt
->constraint_type
);
762 if (!SANE_OPTION_IS_ACTIVE(opt
->cap
))
763 EnableWindow(control
,FALSE
);
765 EnableWindow(control
,TRUE
);
767 SendMessageA(control
,CB_RESETCONTENT
,0,0);
768 /* initialize values */
769 if (opt
->type
== SANE_TYPE_STRING
&& opt
->constraint_type
!=
770 SANE_CONSTRAINT_NONE
)
774 while (opt
->constraint
.string_list
[j
]!=NULL
)
776 SendMessageA(control
,CB_ADDSTRING
,0,
777 (LPARAM
)opt
->constraint
.string_list
[j
]);
780 sane_control_option(activeDS
.deviceHandle
, i
, SANE_ACTION_GET_VALUE
, buffer
,NULL
);
781 SendMessageA(control
,CB_SELECTSTRING
,0,(LPARAM
)buffer
);
783 else if (opt
->type
== SANE_TYPE_BOOL
)
786 sane_control_option(activeDS
.deviceHandle
, i
,
787 SANE_ACTION_GET_VALUE
, &b
, NULL
);
789 SendMessageA(control
,BM_SETCHECK
,BST_CHECKED
,0);
792 else if (opt
->constraint_type
== SANE_CONSTRAINT_RANGE
)
794 if (opt
->type
== SANE_TYPE_INT
)
799 min
= (SANE_Int
)opt
->constraint
.range
->min
/
800 (((SANE_Int
)opt
->constraint
.range
->quant
)?
801 (SANE_Int
)opt
->constraint
.range
->quant
:1);
803 max
= (SANE_Int
)opt
->constraint
.range
->max
/
804 (((SANE_Int
)opt
->constraint
.range
->quant
)
805 ?(SANE_Int
)opt
->constraint
.range
->quant
:1);
807 SendMessageA(control
,SBM_SETRANGE
,min
,max
);
809 sane_control_option(activeDS
.deviceHandle
, i
,
810 SANE_ACTION_GET_VALUE
, &si
,NULL
);
811 if (opt
->constraint
.range
->quant
)
812 si
= si
/ opt
->constraint
.range
->quant
;
814 SendMessageW(control
,SBM_SETPOS
, si
, TRUE
);
815 UpdateRelevantEdit(hwnd
, opt
, i
, si
);
817 else if (opt
->type
== SANE_TYPE_FIXED
)
822 double s_min
,s_max
,s_quant
;
826 s_min
= SANE_UNFIX(opt
->constraint
.range
->min
);
827 s_max
= SANE_UNFIX(opt
->constraint
.range
->max
);
828 s_quant
= SANE_UNFIX(opt
->constraint
.range
->quant
);
832 min
= (s_min
/ s_quant
);
833 max
= (s_max
/ s_quant
);
841 SendMessageA(control
,SBM_SETRANGE
,min
,max
);
844 sf
= HeapAlloc(GetProcessHeap(),0,opt
->size
*sizeof(SANE_Word
));
845 sane_control_option(activeDS
.deviceHandle
, i
,
846 SANE_ACTION_GET_VALUE
, sf
,NULL
);
848 dd
= SANE_UNFIX(*sf
);
849 HeapFree(GetProcessHeap(),0,sf
);
852 pos
= (dd
/ s_quant
);
856 SendMessageW(control
, SBM_SETPOS
, pos
, TRUE
);
858 UpdateRelevantEdit(hwnd
, opt
, i
, pos
);
866 static INT_PTR
ProcessScroll(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
869 const SANE_Option_Descriptor
*opt
;
873 index
= GetDlgCtrlID((HWND
)lParam
)- ID_BASE
;
877 opt
= sane_get_option_descriptor(activeDS
.deviceHandle
, index
);
882 scroll
= LOWORD(wParam
);
887 case SB_THUMBPOSITION
:
890 si
.cbSize
= sizeof(SCROLLINFO
);
891 si
.fMask
= SIF_TRACKPOS
;
892 GetScrollInfo((HWND
)lParam
,SB_CTL
, &si
);
893 position
= si
.nTrackPos
;
899 position
= SendMessageW((HWND
)lParam
,SBM_GETPOS
,0,0);
905 position
= SendMessageW((HWND
)lParam
,SBM_GETPOS
,0,0);
909 position
= SendMessageW((HWND
)lParam
,SBM_GETPOS
,0,0);
912 SendMessageW((HWND
)lParam
,SBM_SETPOS
, position
, TRUE
);
913 position
= SendMessageW((HWND
)lParam
,SBM_GETPOS
,0,0);
915 UpdateRelevantEdit(hwnd
, opt
, index
, position
);
916 if (UpdateSaneScrollOption(opt
, index
, position
))
917 InitializeDialog(hwnd
);
923 static void ButtonClicked(HWND hwnd
, INT id
, HWND control
)
926 const SANE_Option_Descriptor
*opt
;
928 index
= id
- ID_BASE
;
932 opt
= sane_get_option_descriptor(activeDS
.deviceHandle
, index
);
937 if (opt
->type
== SANE_TYPE_BOOL
)
939 BOOL r
= SendMessageW(control
,BM_GETCHECK
,0,0)==BST_CHECKED
;
940 if (UpdateSaneBoolOption(index
, r
))
941 InitializeDialog(hwnd
);
945 static void ComboChanged(HWND hwnd
, INT id
, HWND control
)
950 const SANE_Option_Descriptor
*opt
;
953 index
= id
- ID_BASE
;
957 opt
= sane_get_option_descriptor(activeDS
.deviceHandle
, index
);
962 selection
= SendMessageW(control
,CB_GETCURSEL
,0,0);
963 len
= SendMessageW(control
,CB_GETLBTEXTLEN
,selection
,0);
966 value
= HeapAlloc(GetProcessHeap(),0,len
);
967 SendMessageA(control
,CB_GETLBTEXT
,selection
,(LPARAM
)value
);
969 if (opt
->type
== SANE_TYPE_STRING
)
971 if (UpdateSaneStringOption(index
, value
))
972 InitializeDialog(hwnd
);
977 static INT_PTR CALLBACK
DialogProc(HWND hwndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
982 return InitializeDialog(hwndDlg
);
984 return ProcessScroll(hwndDlg
, wParam
, lParam
);
988 LPPSHNOTIFY psn
= (LPPSHNOTIFY
)lParam
;
989 switch (((NMHDR
*)lParam
)->code
)
992 if (psn
->lParam
== TRUE
)
994 activeDS
.currentState
= 6;
995 activeDS
.pendingEvent
.TWMessage
= MSG_XFERREADY
;
998 case PSN_QUERYCANCEL
:
999 activeDS
.pendingEvent
.TWMessage
= MSG_CLOSEDSREQ
;
1002 InitializeDialog(hwndDlg
);
1008 switch (HIWORD(wParam
))
1011 ButtonClicked(hwndDlg
,LOWORD(wParam
),
1015 ComboChanged(hwndDlg
,LOWORD(wParam
),
1024 static int CALLBACK
PropSheetProc(HWND hwnd
, UINT msg
, LPARAM lParam
)
1026 if (msg
== PSCB_INITIALIZED
)
1028 /* rename OK button to Scan */
1029 HWND scan
= GetDlgItem(hwnd
,IDOK
);
1030 SetWindowTextA(scan
,"Scan");
1036 static INT_PTR CALLBACK
ScanningProc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1041 HWND
ScanningDialogBox(HWND dialog
, LONG progress
)
1044 dialog
= CreateDialogW(SANE_instance
,
1045 (LPWSTR
)MAKEINTRESOURCE(IDD_DIALOG1
), NULL
, ScanningProc
);
1049 EndDialog(dialog
,0);
1053 RedrawWindow(dialog
,NULL
,NULL
,
1054 RDW_INTERNALPAINT
|RDW_UPDATENOW
|RDW_ALLCHILDREN
);
1059 #else /* HAVE_SANE */
1061 BOOL
DoScannerUI(void)
1066 #endif /* HAVE_SANE */