midimap: Handle MIDI running status.
[wine.git] / dlls / sane.ds / ui.c
blobe66526a088ea6c6895b296a21d3fcf56e42f86cf
1 /*
2 * TWAIN32 Options UI
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
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
25 #define NONAMELESSUNION
27 #include "sane_i.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "wingdi.h"
31 #include "prsht.h"
32 #include "wine/debug.h"
33 #include "resource.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(twain);
37 #define ID_BASE 0x100
38 #define ID_EDIT_BASE 0x1000
39 #define ID_STATIC_BASE 0x2000
41 static INT_PTR CALLBACK DialogProc (HWND , UINT , WPARAM , LPARAM );
42 static INT CALLBACK PropSheetProc(HWND, UINT,LPARAM);
44 static int create_leading_static(HDC hdc, const WCHAR *text,
45 LPDLGITEMTEMPLATEW* template_out, int y, int id)
47 LPDLGITEMTEMPLATEW tpl = NULL;
48 INT len;
49 SIZE size;
50 WORD *ptr;
51 LONG base;
53 *template_out = NULL;
55 if (!text)
56 return 0;
58 base = GetDialogBaseUnits();
60 len = lstrlenW(text) * sizeof(WCHAR);
61 len += sizeof(DLGITEMTEMPLATE);
62 len += 4*sizeof(WORD);
64 tpl = malloc(len);
65 tpl->style=WS_VISIBLE;
66 tpl->dwExtendedStyle = 0;
67 tpl->x = 4;
68 tpl->y = y;
69 tpl->id = ID_BASE;
71 GetTextExtentPoint32W(hdc,text,lstrlenW(text),&size);
73 tpl->cx = MulDiv(size.cx,4,LOWORD(base));
74 tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2;
75 ptr = (WORD *)(tpl + 1);
76 *ptr++ = 0xffff;
77 *ptr++ = 0x0082;
78 lstrcpyW( ptr, text );
79 ptr += lstrlenW(ptr) + 1;
80 *ptr = 0;
82 *template_out = tpl;
83 return len;
86 static int create_trailing_edit(HDC hdc, LPDLGITEMTEMPLATEW* template_out, int id,
87 int y, const WCHAR *text,BOOL is_int)
89 LPDLGITEMTEMPLATEW tpl = NULL;
90 INT len;
91 WORD *ptr;
92 SIZE size;
93 LONG base;
94 static const char int_base[] = "0000 xxx";
95 static const char float_base[] = "0000.0000 xxx";
97 base = GetDialogBaseUnits();
99 len = lstrlenW(text) * sizeof(WCHAR);
100 len += sizeof(DLGITEMTEMPLATE);
101 len += 4*sizeof(WORD);
103 tpl = malloc(len);
104 tpl->style=WS_VISIBLE|ES_READONLY|WS_BORDER;
105 tpl->dwExtendedStyle = 0;
106 tpl->x = 1;
107 tpl->y = y;
108 tpl->id = id;
110 if (is_int)
111 GetTextExtentPoint32A(hdc,int_base,lstrlenA(int_base),&size);
112 else
113 GetTextExtentPoint32A(hdc,float_base,lstrlenA(float_base),&size);
115 tpl->cx = MulDiv(size.cx*2,4,LOWORD(base));
116 tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2;
118 ptr = (WORD *)(tpl + 1);
119 *ptr++ = 0xffff;
120 *ptr++ = 0x0081;
121 lstrcpyW( ptr, text );
122 ptr += lstrlenW(ptr) + 1;
123 *ptr = 0;
125 *template_out = tpl;
126 return len;
130 static int create_item(HDC hdc, const struct option_descriptor *opt,
131 INT id, LPDLGITEMTEMPLATEW *template_out, int y, int *cx, int* count)
133 LPDLGITEMTEMPLATEW tpl = NULL,rc = NULL;
134 WORD class = 0xffff;
135 DWORD styles = WS_VISIBLE;
136 WORD *ptr = NULL;
137 LPDLGITEMTEMPLATEW lead_static = NULL;
138 LPDLGITEMTEMPLATEW trail_edit = NULL;
139 DWORD leading_len = 0;
140 DWORD trail_len = 0;
141 DWORD local_len = 0;
142 const WCHAR *title = NULL;
143 WCHAR buffer[255];
144 int padding = 0;
145 int padding2 = 0;
146 int base_x = 0;
147 LONG base;
148 int ctl_cx = 0;
149 SIZE size;
151 GetTextExtentPoint32A(hdc,"X",1,&size);
152 base = GetDialogBaseUnits();
153 base_x = MulDiv(size.cx,4,LOWORD(base));
155 switch (opt->type)
157 case TYPE_BOOL:
158 class = 0x0080; /* Button */
159 styles |= BS_AUTOCHECKBOX;
160 title = opt->title;
161 break;
162 case TYPE_INT:
164 int i;
165 sane_option_get_value( id - ID_BASE, &i );
166 swprintf(buffer, ARRAY_SIZE(buffer), L"%i", i);
168 switch (opt->constraint_type)
170 case CONSTRAINT_NONE:
171 class = 0x0081; /* Edit*/
172 styles |= ES_NUMBER;
173 title = buffer;
174 break;
175 case CONSTRAINT_RANGE:
176 class = 0x0084; /* scroll */
177 ctl_cx = 10 * base_x;
178 trail_len += create_trailing_edit(hdc, &trail_edit, id +
179 ID_EDIT_BASE, y,buffer,TRUE);
180 break;
181 default:
182 class= 0x0085; /* Combo */
183 ctl_cx = 10 * base_x;
184 styles |= CBS_DROPDOWNLIST;
185 break;
187 leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
188 break;
190 case TYPE_FIXED:
192 int *i = calloc( opt->size, sizeof(int) );
194 sane_option_get_value( id - ID_BASE, i );
196 swprintf(buffer, ARRAY_SIZE(buffer), L"%f", *i / 65536.0);
197 free( i );
199 switch (opt->constraint_type)
201 case CONSTRAINT_NONE:
202 class = 0x0081; /* Edit */
203 title = buffer;
204 break;
205 case CONSTRAINT_RANGE:
206 class= 0x0084; /* scroll */
207 ctl_cx = 10 * base_x;
208 trail_len += create_trailing_edit(hdc, &trail_edit, id + ID_EDIT_BASE, y,buffer,FALSE);
209 break;
210 default:
211 class= 0x0085; /* Combo */
212 ctl_cx = 10 * base_x;
213 styles |= CBS_DROPDOWNLIST;
214 break;
216 leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
217 break;
219 case TYPE_STRING:
221 char str[256];
222 switch (opt->constraint_type)
224 case CONSTRAINT_NONE:
225 class = 0x0081; /* Edit*/
226 break;
227 default:
228 class= 0x0085; /* Combo */
229 ctl_cx = opt->size * base_x;
230 styles |= CBS_DROPDOWNLIST;
231 break;
233 leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
234 sane_option_get_value( id - ID_BASE, str );
235 MultiByteToWideChar( CP_UNIXCP, 0, str, -1, buffer, ARRAY_SIZE(buffer) );
236 title = buffer;
237 break;
239 case TYPE_BUTTON:
240 class = 0x0080; /* Button */
241 title = opt->title;
242 break;
243 case TYPE_GROUP:
244 class = 0x0080; /* Button */
245 styles |= BS_GROUPBOX;
246 title = opt->title;
247 break;
250 local_len += sizeof(DLGITEMTEMPLATE);
251 if (title) local_len += lstrlenW(title) * sizeof(WCHAR);
252 local_len += 4*sizeof(WORD);
254 padding = leading_len % sizeof(DWORD);
255 rc = realloc(lead_static, leading_len + local_len + padding);
256 tpl = (LPDLGITEMTEMPLATEW)((LPBYTE)rc + leading_len + padding);
257 tpl->style=styles;
258 tpl->dwExtendedStyle = 0;
259 if (lead_static)
260 tpl->x = lead_static->x + lead_static->cx + 1;
261 else if (opt->type == TYPE_GROUP)
262 tpl->x = 2;
263 else
264 tpl->x = 4;
265 tpl->y = y;
266 tpl->id = id;
268 if (title)
270 GetTextExtentPoint32W(hdc,title,lstrlenW(title),&size);
271 tpl->cx = size.cx;
272 tpl->cy = size.cy;
274 else
276 if (lead_static)
277 tpl->cy = lead_static->cy;
278 else
279 tpl->cy = 15;
281 if (!ctl_cx)
282 ctl_cx = 15;
284 tpl->cx = ctl_cx;
286 ptr = (WORD *)(tpl + 1);
287 *ptr++ = 0xffff;
288 *ptr++ = class;
289 if (title)
291 lstrcpyW( ptr, title );
292 ptr += lstrlenW(ptr);
294 *ptr++ = 0;
295 *ptr = 0;
297 if (trail_edit)
299 trail_edit->x = tpl->cx + tpl->x + 2;
300 *cx = trail_edit->x + trail_edit->cx;
302 padding2 = (leading_len + local_len + padding)% sizeof(DWORD);
304 rc = realloc( rc, leading_len + local_len + padding +padding2 + trail_len);
306 memcpy(((LPBYTE)rc) + leading_len + local_len + padding + padding2,
307 trail_edit,trail_len);
309 else
310 *cx = tpl->cx + tpl->x;
312 *template_out = rc;
313 if (leading_len)
314 *count = 2;
315 else
316 *count = 1;
318 if (trail_edit)
319 *count+=1;
321 free(trail_edit);
322 return leading_len + local_len + padding + padding2 + trail_len;
326 static LPDLGTEMPLATEW create_options_page(HDC hdc, int *from_index,
327 int optcount, BOOL split_tabs)
329 int i;
330 INT y = 2;
331 LPDLGTEMPLATEW tpl = NULL;
332 LPBYTE all_controls = NULL;
333 DWORD control_len = 0;
334 int max_cx = 0;
335 int group_max_cx = 0;
336 LPBYTE ptr;
337 int group_offset = -1;
338 INT control_count = 0;
340 for (i = *from_index; i < optcount; i++)
342 LPDLGITEMTEMPLATEW item_tpl = NULL;
343 struct option_descriptor opt;
344 int len;
345 int padding = 0;
346 int x;
347 int count;
348 int hold_for_group = 0;
350 opt.optno = i;
351 if (SANE_CALL( option_get_descriptor, &opt )) continue;
352 if (opt.type == TYPE_GROUP && split_tabs)
354 if (control_len > 0)
356 *from_index = i - 1;
357 goto exit;
359 else
361 *from_index = i;
362 return NULL;
365 if (!opt.is_active)
366 continue;
368 len = create_item(hdc, &opt, ID_BASE + i, &item_tpl, y, &x, &count);
370 control_count += count;
372 if (!len)
374 continue;
377 hold_for_group = y;
378 y+= item_tpl->cy + 1;
379 max_cx = max(max_cx, x + 2);
380 group_max_cx = max(group_max_cx, x );
382 padding = len % sizeof(DWORD);
384 if (all_controls)
386 all_controls = realloc(all_controls, control_len + len + padding);
387 memcpy(all_controls+control_len,item_tpl,len);
388 memset(all_controls+control_len+len,0xca,padding);
389 free(item_tpl);
391 else
393 if (!padding)
395 all_controls = (LPBYTE)item_tpl;
397 else
399 all_controls = malloc(len + padding);
400 memcpy(all_controls,item_tpl,len);
401 memset(all_controls+len,0xcb,padding);
402 free(item_tpl);
406 if (opt.type == TYPE_GROUP)
408 if (group_offset == -1)
410 group_offset = control_len;
411 group_max_cx = 0;
413 else
415 LPDLGITEMTEMPLATEW group =
416 (LPDLGITEMTEMPLATEW)(all_controls+group_offset);
418 group->cy = hold_for_group - group->y;
419 group->cx = group_max_cx;
421 group = (LPDLGITEMTEMPLATEW)(all_controls+control_len);
422 group->y += 2;
423 y+=2;
424 group_max_cx = 0;
425 group_offset = control_len;
429 control_len += len + padding;
432 if ( group_offset && !split_tabs )
434 LPDLGITEMTEMPLATEW group =
435 (LPDLGITEMTEMPLATEW)(all_controls+group_offset);
436 group->cy = y - group->y;
437 group->cx = group_max_cx;
438 y+=2;
441 *from_index = i-1;
442 exit:
444 tpl = malloc(sizeof(DLGTEMPLATE) + 3*sizeof(WORD) + control_len);
446 tpl->style = WS_VISIBLE | WS_OVERLAPPEDWINDOW;
447 tpl->dwExtendedStyle = 0;
448 tpl->cdit = control_count;
449 tpl->x = 0;
450 tpl->y = 0;
451 tpl->cx = max_cx + 10;
452 tpl->cy = y + 10;
453 ptr = (LPBYTE)tpl + sizeof(DLGTEMPLATE);
454 *(LPWORD)ptr = 0x0000;
455 ptr+=sizeof(WORD);
456 *(LPWORD)ptr = 0x0000;
457 ptr+=sizeof(WORD);
458 *(LPWORD)ptr = 0x0000;
459 ptr+=sizeof(WORD);
460 memcpy(ptr,all_controls,control_len);
462 free(all_controls);
464 return tpl;
467 BOOL DoScannerUI(void)
469 HDC hdc;
470 PROPSHEETPAGEW psp[10];
471 int page_count= 0;
472 PROPSHEETHEADERW psh;
473 int index = 1;
474 TW_UINT16 rc;
475 int optcount;
476 UINT psrc;
477 LPWSTR szCaption;
478 DWORD len;
480 hdc = GetDC(0);
482 memset(psp,0,sizeof(psp));
483 rc = sane_option_get_value( 0, &optcount );
484 if (rc != TWCC_SUCCESS)
486 ERR("Unable to read number of options\n");
487 return FALSE;
490 while (index < optcount)
492 struct option_descriptor opt;
494 psp[page_count].u.pResource = create_options_page(hdc, &index,
495 optcount, TRUE);
496 opt.optno = index;
497 SANE_CALL( option_get_descriptor, &opt );
499 if (opt.type == TYPE_GROUP)
501 psp[page_count].pszTitle = wcsdup( opt.title );
504 if (psp[page_count].u.pResource)
506 psp[page_count].dwSize = sizeof(PROPSHEETPAGEW);
507 psp[page_count].dwFlags = PSP_DLGINDIRECT | PSP_USETITLE;
508 psp[page_count].hInstance = SANE_instance;
509 psp[page_count].pfnDlgProc = DialogProc;
510 psp[page_count].lParam = (LPARAM)&activeDS;
511 page_count ++;
514 index ++;
517 len = lstrlenA(activeDS.identity.Manufacturer)
518 + lstrlenA(activeDS.identity.ProductName) + 2;
519 szCaption = malloc(len *sizeof(WCHAR));
520 MultiByteToWideChar(CP_ACP,0,activeDS.identity.Manufacturer,-1,
521 szCaption,len);
522 szCaption[lstrlenA(activeDS.identity.Manufacturer)] = ' ';
523 MultiByteToWideChar(CP_ACP,0,activeDS.identity.ProductName,-1,
524 &szCaption[lstrlenA(activeDS.identity.Manufacturer)+1],len);
525 psh.dwSize = sizeof(PROPSHEETHEADERW);
526 psh.dwFlags = PSH_PROPSHEETPAGE|PSH_PROPTITLE|PSH_USECALLBACK;
527 psh.hwndParent = activeDS.hwndOwner;
528 psh.hInstance = SANE_instance;
529 psh.u.pszIcon = 0;
530 psh.pszCaption = szCaption;
531 psh.nPages = page_count;
532 psh.u2.nStartPage = 0;
533 psh.u3.ppsp = (LPCPROPSHEETPAGEW)psp;
534 psh.pfnCallback = PropSheetProc;
536 psrc = PropertySheetW(&psh);
538 for(index = 0; index < page_count; index ++)
540 free((LPBYTE)psp[index].u.pResource);
541 free((LPBYTE)psp[index].pszTitle);
543 free(szCaption);
545 if (psrc == IDOK)
546 return TRUE;
547 else
548 return FALSE;
551 static void UpdateRelevantEdit(HWND hwnd, const struct option_descriptor *opt, int position)
553 WCHAR buffer[244];
554 HWND edit_w;
555 int len;
557 switch (opt->type)
559 case TYPE_INT:
561 INT si;
563 if (opt->constraint.range.quant)
564 si = position * opt->constraint.range.quant;
565 else
566 si = position;
568 len = swprintf( buffer, ARRAY_SIZE(buffer), L"%i", si );
569 break;
571 case TYPE_FIXED:
573 double dd;
575 if (opt->constraint.range.quant)
576 dd = position * (opt->constraint.range.quant / 65536.0);
577 else
578 dd = position * 0.01;
580 len = swprintf( buffer, ARRAY_SIZE(buffer), L"%f", dd );
581 break;
583 default:
584 return;
587 buffer[len++] = ' ';
588 LoadStringW( SANE_instance, opt->unit, buffer + len, ARRAY_SIZE( buffer ) - len );
590 edit_w = GetDlgItem(hwnd,opt->optno + ID_BASE + ID_EDIT_BASE);
591 if (edit_w) SetWindowTextW(edit_w,buffer);
595 static BOOL UpdateSaneScrollOption(const struct option_descriptor *opt, DWORD position)
597 BOOL result = FALSE;
598 int si;
600 switch (opt->type)
602 case TYPE_INT:
604 if (opt->constraint.range.quant)
605 si = position * opt->constraint.range.quant;
606 else
607 si = position;
609 sane_option_set_value( opt->optno, &si, &result );
610 break;
612 case TYPE_FIXED:
613 if (opt->constraint.range.quant)
614 si = position * opt->constraint.range.quant;
615 else
616 si = MulDiv( position, 65536, 100 );
618 sane_option_set_value( opt->optno, &si, &result );
619 break;
620 default:
621 break;
624 return result;
627 static INT_PTR InitializeDialog(HWND hwnd)
629 TW_UINT16 rc;
630 int optcount;
631 HWND control;
632 int i;
634 rc = sane_option_get_value( 0, &optcount );
635 if (rc != TWCC_SUCCESS)
637 ERR("Unable to read number of options\n");
638 return FALSE;
641 for ( i = 1; i < optcount; i++)
643 struct option_descriptor opt;
645 control = GetDlgItem(hwnd,i+ID_BASE);
647 if (!control)
648 continue;
650 opt.optno = i;
651 SANE_CALL( option_get_descriptor, &opt );
653 TRACE("%i %s %i %i\n",i,debugstr_w(opt.title),opt.type,opt.constraint_type);
654 EnableWindow(control,opt.is_active);
656 SendMessageA(control,CB_RESETCONTENT,0,0);
657 /* initialize values */
658 if (opt.type == TYPE_STRING && opt.constraint_type != CONSTRAINT_NONE)
660 CHAR buffer[255];
661 WCHAR *p;
663 for (p = opt.constraint.strings; *p; p += lstrlenW(p) + 1)
664 SendMessageW( control,CB_ADDSTRING,0, (LPARAM)p );
665 sane_option_get_value( i, buffer );
666 SendMessageA(control,CB_SELECTSTRING,0,(LPARAM)buffer);
668 else if (opt.type == TYPE_BOOL)
670 BOOL b;
671 sane_option_get_value( i, &b );
672 if (b)
673 SendMessageA(control,BM_SETCHECK,BST_CHECKED,0);
676 else if (opt.type == TYPE_INT && opt.constraint_type == CONSTRAINT_WORD_LIST)
678 int j, count = opt.constraint.word_list[0];
679 CHAR buffer[16];
680 int val;
681 for (j=1; j<=count; j++)
683 sprintf(buffer, "%d", opt.constraint.word_list[j]);
684 SendMessageA(control, CB_ADDSTRING, 0, (LPARAM)buffer);
686 sane_option_get_value( i, &val );
687 sprintf(buffer, "%d", val);
688 SendMessageA(control,CB_SELECTSTRING,0,(LPARAM)buffer);
690 else if (opt.constraint_type == CONSTRAINT_RANGE)
692 if (opt.type == TYPE_INT)
694 int si;
695 int min,max;
697 min = opt.constraint.range.min /
698 (opt.constraint.range.quant ? opt.constraint.range.quant : 1);
700 max = opt.constraint.range.max /
701 (opt.constraint.range.quant ? opt.constraint.range.quant : 1);
703 SendMessageA(control,SBM_SETRANGE,min,max);
705 sane_option_get_value( i, &si );
706 if (opt.constraint.range.quant)
707 si = si / opt.constraint.range.quant;
709 SendMessageW(control,SBM_SETPOS, si, TRUE);
710 UpdateRelevantEdit(hwnd, &opt, si);
712 else if (opt.type == TYPE_FIXED)
714 int pos, min, max, *sf;
716 if (opt.constraint.range.quant)
718 min = opt.constraint.range.min / opt.constraint.range.quant;
719 max = opt.constraint.range.max / opt.constraint.range.quant;
721 else
723 min = MulDiv( opt.constraint.range.min, 100, 65536 );
724 max = MulDiv( opt.constraint.range.max, 100, 65536 );
727 SendMessageA(control,SBM_SETRANGE,min,max);
730 sf = calloc( opt.size, sizeof(int) );
731 sane_option_get_value( i, sf );
733 /* Note that conversion of float -> SANE_Fixed is lossy;
734 * and when you truncate it into an integer, you can get
735 * unfortunate results. This calculation attempts
736 * to mitigate that harm */
737 if (opt.constraint.range.quant)
738 pos = *sf / opt.constraint.range.quant;
739 else
740 pos = MulDiv( *sf, 100, 65536 );
742 free(sf);
743 SendMessageW(control, SBM_SETPOS, pos, TRUE);
744 UpdateRelevantEdit(hwnd, &opt, pos);
749 return TRUE;
752 static INT_PTR ProcessScroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
754 struct option_descriptor opt;
755 WORD scroll;
756 DWORD position;
758 opt.optno = GetDlgCtrlID((HWND)lParam)- ID_BASE;
759 if (opt.optno < 0)
760 return FALSE;
762 if (SANE_CALL( option_get_descriptor, &opt )) return FALSE;
764 scroll = LOWORD(wParam);
766 switch (scroll)
768 case SB_THUMBTRACK:
769 case SB_THUMBPOSITION:
771 SCROLLINFO si;
772 si.cbSize = sizeof(SCROLLINFO);
773 si.fMask = SIF_TRACKPOS;
774 GetScrollInfo((HWND)lParam,SB_CTL, &si);
775 position = si.nTrackPos;
777 break;
778 case SB_LEFT:
779 case SB_LINELEFT:
780 case SB_PAGELEFT:
781 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
782 position--;
783 break;
784 case SB_RIGHT:
785 case SB_LINERIGHT:
786 case SB_PAGERIGHT:
787 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
788 position++;
789 break;
790 default:
791 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
794 SendMessageW((HWND)lParam,SBM_SETPOS, position, TRUE);
795 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
797 UpdateRelevantEdit(hwnd, &opt, position);
798 if (UpdateSaneScrollOption(&opt, position))
799 InitializeDialog(hwnd);
801 return TRUE;
805 static void ButtonClicked(HWND hwnd, INT id, HWND control)
807 struct option_descriptor opt;
808 BOOL changed = FALSE;
810 opt.optno = id - ID_BASE;
811 if (opt.optno < 0)
812 return;
814 if (SANE_CALL( option_get_descriptor, &opt )) return;
816 if (opt.type == TYPE_BOOL)
818 BOOL r = SendMessageW(control,BM_GETCHECK,0,0)==BST_CHECKED;
819 sane_option_set_value( opt.optno, &r, &changed );
820 if (changed) InitializeDialog(hwnd);
824 static void ComboChanged(HWND hwnd, INT id, HWND control)
826 int selection;
827 int len;
828 struct option_descriptor opt;
829 char *value;
830 BOOL changed = FALSE;
832 opt.optno = id - ID_BASE;
833 if (opt.optno < 0)
834 return;
836 if (SANE_CALL( option_get_descriptor, &opt )) return;
838 selection = SendMessageW(control,CB_GETCURSEL,0,0);
839 len = SendMessageW(control,CB_GETLBTEXTLEN,selection,0);
841 len++;
842 value = malloc(len);
843 SendMessageA(control,CB_GETLBTEXT,selection,(LPARAM)value);
845 if (opt.type == TYPE_STRING)
847 sane_option_set_value( opt.optno, value, &changed );
849 else if (opt.type == TYPE_INT)
851 int val = atoi( value );
852 sane_option_set_value( opt.optno, &val, &changed );
854 if (changed) InitializeDialog(hwnd);
855 free( value );
859 static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
861 switch (msg)
863 case WM_INITDIALOG:
864 return InitializeDialog(hwndDlg);
865 case WM_HSCROLL:
866 return ProcessScroll(hwndDlg, wParam, lParam);
867 case WM_NOTIFY:
869 LPPSHNOTIFY psn = (LPPSHNOTIFY)lParam;
870 switch (((NMHDR*)lParam)->code)
872 case PSN_APPLY:
873 if (psn->lParam)
875 activeDS.currentState = 6;
876 SANE_Notify(MSG_XFERREADY);
878 break;
879 case PSN_QUERYCANCEL:
880 SANE_Notify(MSG_CLOSEDSREQ);
881 break;
882 case PSN_SETACTIVE:
883 InitializeDialog(hwndDlg);
884 break;
886 break;
888 case WM_COMMAND:
889 switch (HIWORD(wParam))
891 case BN_CLICKED:
892 ButtonClicked(hwndDlg,LOWORD(wParam), (HWND)lParam);
893 break;
894 case CBN_SELCHANGE:
895 ComboChanged(hwndDlg,LOWORD(wParam), (HWND)lParam);
899 return FALSE;
902 static int CALLBACK PropSheetProc(HWND hwnd, UINT msg, LPARAM lParam)
904 if (msg == PSCB_INITIALIZED)
906 /* rename OK button to Scan */
907 HWND scan = GetDlgItem(hwnd,IDOK);
908 SetWindowTextA(scan,"Scan");
910 return TRUE;
914 static INT_PTR CALLBACK ScanningProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
916 return FALSE;
919 HWND ScanningDialogBox(HWND dialog, LONG progress)
921 if (!dialog)
922 dialog = CreateDialogW(SANE_instance,
923 (LPWSTR)MAKEINTRESOURCE(IDD_DIALOG1), NULL, ScanningProc);
925 if (progress == -1)
927 EndDialog(dialog,0);
928 return NULL;
931 RedrawWindow(dialog,NULL,NULL,
932 RDW_INTERNALPAINT|RDW_UPDATENOW|RDW_ALLCHILDREN);
934 return dialog;