b61d4926483bb9858ff4f6938fc1520ac1a2d06f
[reactos.git] / reactos / lib / user32 / windows / dialog.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/dialog.c
23 * PURPOSE: Input
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
26 * Steven Edwards (Steven_Ed4153@yahoo.com)
27 * UPDATE HISTORY:
28 * 07-26-2003 Code ported from wine
29 * 09-05-2001 CSH Created
30 */
31
32 /* INCLUDES ******************************************************************/
33
34 #include <user32.h>
35
36 /* MACROS/DEFINITIONS ********************************************************/
37
38 #define DF_END 0x0001
39 #define DF_OWNERENABLED 0x0002
40 #define CW_USEDEFAULT16 ((short)0x8000)
41 #define DWL_INIT (12)
42 #define GETDLGINFO(hwnd) (DIALOGINFO*)GetWindowLongW((hwnd), DWL_INIT)
43 #define SETDLGINFO(hwnd, info) SetWindowLongW((hwnd), DWL_INIT, (LONG)(info))
44 #define GET_WORD(ptr) (*(WORD *)(ptr))
45 #define GET_DWORD(ptr) (*(DWORD *)(ptr))
46 #define MAKEINTATOMA(atom) ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
47 #define MAKEINTATOMW(atom) ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
48 #define DIALOG_CLASS_ATOMA MAKEINTATOMA(32770) /* Dialog */
49 #define DIALOG_CLASS_ATOMW MAKEINTATOMW(32770) /* Dialog */
50
51 /* INTERNAL STRUCTS **********************************************************/
52
53 /* Dialog info structure */
54 typedef struct
55 {
56 HWND hwndFocus; /* Current control with focus */
57 HFONT hUserFont; /* Dialog font */
58 HMENU hMenu; /* Dialog menu */
59 UINT xBaseUnit; /* Dialog units (depends on the font) */
60 UINT yBaseUnit;
61 INT idResult; /* EndDialog() result / default pushbutton ID */
62 UINT flags; /* EndDialog() called for this dialog */
63 } DIALOGINFO;
64
65 /* Dialog control information */
66 typedef struct
67 {
68 DWORD style;
69 DWORD exStyle;
70 DWORD helpId;
71 short x;
72 short y;
73 short cx;
74 short cy;
75 UINT id;
76 LPCWSTR className;
77 LPCWSTR windowName;
78 BOOL windowNameFree;
79 LPCVOID data;
80 } DLG_CONTROL_INFO;
81
82 /* Dialog template */
83 typedef struct
84 {
85 DWORD style;
86 DWORD exStyle;
87 DWORD helpId;
88 WORD nbItems;
89 short x;
90 short y;
91 short cx;
92 short cy;
93 LPCWSTR menuName;
94 LPCWSTR className;
95 LPCWSTR caption;
96 WORD pointSize;
97 WORD weight;
98 BOOL italic;
99 LPCWSTR faceName;
100 BOOL dialogEx;
101 } DLG_TEMPLATE;
102
103 /* GetDlgItem structure */
104 typedef struct
105 {
106 INT nIDDlgItem;
107 HWND control;
108 } GETDLGITEMINFO;
109
110 /* CheckRadioButton structure */
111 typedef struct
112 {
113 UINT firstID;
114 UINT lastID;
115 UINT checkID;
116 } RADIOGROUP;
117
118
119 /*********************************************************************
120 * dialog class descriptor
121 */
122 const struct builtin_class_descr DIALOG_builtin_class =
123 {
124 DIALOG_CLASS_ATOMW, /* name */
125 CS_SAVEBITS | CS_DBLCLKS, /* style */
126 (WNDPROC) DefDlgProcW, /* procW */
127 (WNDPROC) DefDlgProcA, /* procA */
128 DWL_INIT + sizeof(LONG), /* extra */
129 (LPCWSTR) IDC_ARROW, /* cursor */
130 0 /* brush */
131 };
132
133
134 /* INTERNAL FUNCTIONS ********************************************************/
135
136 /***********************************************************************
137 * DIALOG_GetCharSize
138 *
139 * Despite most of MSDN insisting that the horizontal base unit is
140 * tmAveCharWidth it isn't. Knowledge base article Q145994
141 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
142 * says that we should take the average of the 52 English upper and lower
143 * case characters.
144 */
145 BOOL DIALOG_GetCharSize( HDC hDC, HFONT hFont, SIZE * pSize )
146 {
147 HFONT hFontPrev = 0;
148 char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
149 SIZE sz;
150 TEXTMETRICA tm;
151
152 if(!hDC) return FALSE;
153
154 if(hFont) hFontPrev = SelectObject(hDC, hFont);
155 if(!GetTextMetricsA(hDC, &tm)) return FALSE;
156 if(!GetTextExtentPointA(hDC, alphabet, 52, &sz)) return FALSE;
157
158 pSize->cy = tm.tmHeight;
159 pSize->cx = (sz.cx / 26 + 1) / 2;
160
161 if (hFontPrev) SelectObject(hDC, hFontPrev);
162
163 return TRUE;
164 }
165
166 /***********************************************************************
167 * DIALOG_EnableOwner
168 *
169 * Helper function for modal dialogs to enable again the
170 * owner of the dialog box.
171 */
172 void DIALOG_EnableOwner( HWND hOwner )
173 {
174 /* Owner must be a top-level window */
175 if (hOwner)
176 hOwner = GetAncestor( hOwner, GA_ROOT );
177 if (!hOwner) return;
178 EnableWindow( hOwner, TRUE );
179 }
180
181 /***********************************************************************
182 * DIALOG_DisableOwner
183 *
184 * Helper function for modal dialogs to disable the
185 * owner of the dialog box. Returns TRUE if owner was enabled.
186 */
187 BOOL DIALOG_DisableOwner( HWND hOwner )
188 {
189 /* Owner must be a top-level window */
190 if (hOwner)
191 hOwner = GetAncestor( hOwner, GA_ROOT );
192 if (!hOwner) return FALSE;
193 if (IsWindowEnabled( hOwner ))
194 {
195 EnableWindow( hOwner, FALSE );
196 return TRUE;
197 }
198 else
199 return FALSE;
200 }
201
202 /***********************************************************************
203 * DIALOG_GetControl32
204 *
205 * Return the class and text of the control pointed to by ptr,
206 * fill the header structure and return a pointer to the next control.
207 */
208 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
209 BOOL dialogEx )
210 {
211 if (dialogEx)
212 {
213 info->helpId = GET_DWORD(p); p += 2;
214 info->exStyle = GET_DWORD(p); p += 2;
215 info->style = GET_DWORD(p); p += 2;
216 }
217 else
218 {
219 info->helpId = 0;
220 info->style = GET_DWORD(p); p += 2;
221 info->exStyle = GET_DWORD(p); p += 2;
222 }
223 info->x = GET_WORD(p); p++;
224 info->y = GET_WORD(p); p++;
225 info->cx = GET_WORD(p); p++;
226 info->cy = GET_WORD(p); p++;
227
228 if (dialogEx)
229 {
230 /* id is a DWORD for DIALOGEX */
231 info->id = GET_DWORD(p);
232 p += 2;
233 }
234 else
235 {
236 info->id = GET_WORD(p);
237 p++;
238 }
239
240 if (GET_WORD(p) == 0xffff)
241 {
242 static const WCHAR class_names[6][10] =
243 {
244 { 'B','u','t','t','o','n', }, /* 0x80 */
245 { 'E','d','i','t', }, /* 0x81 */
246 { 'S','t','a','t','i','c', }, /* 0x82 */
247 { 'L','i','s','t','B','o','x', }, /* 0x83 */
248 { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
249 { 'C','o','m','b','o','B','o','x', } /* 0x85 */
250 };
251 WORD id = GET_WORD(p+1);
252 /* Windows treats dialog control class ids 0-5 same way as 0x80-0x85 */
253 if ((id >= 0x80) && (id <= 0x85)) id -= 0x80;
254 if (id <= 5)
255 info->className = class_names[id];
256 else
257 {
258 info->className = NULL;
259 /* FIXME: load other classes here? */
260 }
261 p += 2;
262 }
263 else
264 {
265 info->className = (LPCWSTR)p;
266 p += wcslen( info->className ) + 1;
267 }
268
269 if (GET_WORD(p) == 0xffff) /* Is it an integer id? */
270 {
271 info->windowName = HeapAlloc( GetProcessHeap(), 0, 10 );
272 swprintf((LPWSTR)info->windowName, L"#%d", GET_WORD(p + 1));
273 info->windowNameFree = TRUE;
274 p += 2;
275 }
276 else
277 {
278 info->windowName = (LPCWSTR)p;
279 info->windowNameFree = FALSE;
280 p += wcslen( info->windowName ) + 1;
281 }
282
283 if (GET_WORD(p))
284 {
285 info->data = p + 1;
286 p += GET_WORD(p) / sizeof(WORD);
287 }
288 else info->data = NULL;
289 p++;
290
291 /* Next control is on dword boundary */
292 return (const WORD *)((((int)p) + 3) & ~3);
293 }
294
295 /***********************************************************************
296 * DIALOG_CreateControls32
297 *
298 * Create the control windows for a dialog.
299 */
300 static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPLATE *dlgTemplate,
301 HINSTANCE hInst, BOOL unicode )
302 {
303 DIALOGINFO * dlgInfo;
304 DLG_CONTROL_INFO info;
305 HWND hwndCtrl, hwndDefButton = 0;
306 INT items = dlgTemplate->nbItems;
307
308 if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
309
310 while (items--)
311 {
312 template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info,
313 dlgTemplate->dialogEx );
314 /* Is this it? */
315 if (info.style & WS_BORDER)
316 {
317 info.style &= ~WS_BORDER;
318 info.exStyle |= WS_EX_CLIENTEDGE;
319 }
320 if (unicode)
321 {
322 hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
323 info.className, info.windowName,
324 info.style | WS_CHILD,
325 MulDiv(info.x, dlgInfo->xBaseUnit, 4),
326 MulDiv(info.y, dlgInfo->yBaseUnit, 8),
327 MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
328 MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
329 hwnd, (HMENU)info.id,
330 hInst, (LPVOID)info.data );
331 }
332 else
333 {
334 LPSTR class = (LPSTR)info.className;
335 LPSTR caption = (LPSTR)info.windowName;
336
337 if (HIWORD(class))
338 {
339 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.className, -1, NULL, 0, NULL, NULL );
340 class = HeapAlloc( GetProcessHeap(), 0, len );
341 WideCharToMultiByte( CP_ACP, 0, info.className, -1, class, len, NULL, NULL );
342 }
343 if (HIWORD(caption))
344 {
345 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, NULL, 0, NULL, NULL );
346 caption = HeapAlloc( GetProcessHeap(), 0, len );
347 WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, caption, len, NULL, NULL );
348 }
349 hwndCtrl = CreateWindowExA( info.exStyle | WS_EX_NOPARENTNOTIFY,
350 class, caption, info.style | WS_CHILD,
351 MulDiv(info.x, dlgInfo->xBaseUnit, 4),
352 MulDiv(info.y, dlgInfo->yBaseUnit, 8),
353 MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
354 MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
355 hwnd, (HMENU)info.id,
356 hInst, (LPVOID)info.data );
357 if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
358 if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
359 }
360
361 if (info.windowNameFree)
362 {
363 HeapFree( GetProcessHeap(), 0, (LPVOID)info.windowName );
364 }
365
366 if (!hwndCtrl)
367 {
368 if (dlgTemplate->style & DS_NOFAILCREATE) continue;
369 return FALSE;
370 }
371
372 /* Send initialisation messages to the control */
373 if (dlgInfo->hUserFont) SendMessageA( hwndCtrl, WM_SETFONT,
374 (WPARAM)dlgInfo->hUserFont, 0 );
375 if (SendMessageA(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
376 {
377 /* If there's already a default push-button, set it back */
378 /* to normal and use this one instead. */
379 if (hwndDefButton)
380 SendMessageA( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE );
381 hwndDefButton = hwndCtrl;
382 dlgInfo->idResult = GetWindowLongA( hwndCtrl, GWL_ID );
383 }
384 }
385 return TRUE;
386 }
387
388 /***********************************************************************
389 * DIALOG_FindMsgDestination
390 *
391 * The messages that IsDialogMessage sends may not go to the dialog
392 * calling IsDialogMessage if that dialog is a child, and it has the
393 * DS_CONTROL style set.
394 * We propagate up until we hit one that does not have DS_CONTROL, or
395 * whose parent is not a dialog.
396 *
397 * This is undocumented behaviour.
398 */
399 static HWND DIALOG_FindMsgDestination( HWND hwndDlg )
400 {
401 while (GetWindowLongA(hwndDlg, GWL_STYLE) & DS_CONTROL)
402 {
403 HWND hParent = GetParent(hwndDlg);
404 if (!hParent) break;
405
406 if (!IsWindow(hParent)) break;
407
408 if (!GETDLGINFO(hParent)) /* TODO: Correct? */
409 {
410 break;
411 }
412
413 hwndDlg = hParent;
414 }
415
416 return hwndDlg;
417 }
418
419 /***********************************************************************
420 * DIALOG_IsAccelerator
421 */
422 static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM wParam )
423 {
424 HWND hwndControl = hwnd;
425 HWND hwndNext;
426 INT dlgCode;
427 WCHAR buffer[128];
428
429 do
430 {
431 DWORD style = GetWindowLongW( hwndControl, GWL_STYLE );
432 if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
433 {
434 dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
435 if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
436 GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) ))
437 {
438 /* find the accelerator key */
439 LPWSTR p = buffer - 2;
440
441 do
442 {
443 p = wcschr( p + 2, '&' );
444 }
445 while (p != NULL && p[1] == '&');
446
447 /* and check if it's the one we're looking for */
448 /* FIXME: usage of towupper correct? */
449 if (p != NULL && towupper( p[1] ) == towupper( wParam ) )
450 {
451 if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX )
452 {
453 /* set focus to the control */
454 SendMessageA( hwndDlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, 1);
455 /* and bump it on to next */
456 SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
457 }
458 else if (dlgCode & DLGC_BUTTON)
459 {
460 /* send BM_CLICK message to the control */
461 SendMessageA( hwndControl, BM_CLICK, 0, 0 );
462 }
463 return TRUE;
464 }
465 }
466 hwndNext = GetWindow( hwndControl, GW_CHILD );
467 }
468 else hwndNext = 0;
469
470 if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
471
472 while (!hwndNext && hwndControl)
473 {
474 hwndControl = GetParent( hwndControl );
475 if (hwndControl == hwndDlg)
476 {
477 if(hwnd==hwndDlg) /* prevent endless loop */
478 {
479 hwndNext=hwnd;
480 break;
481 }
482 hwndNext = GetWindow( hwndDlg, GW_CHILD );
483 }
484 else
485 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
486 }
487 hwndControl = hwndNext;
488 }
489 while (hwndControl && (hwndControl != hwnd));
490
491 return FALSE;
492 }
493
494 /***********************************************************************
495 * DIALOG_DoDialogBox
496 */
497 INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
498 {
499 DIALOGINFO * dlgInfo;
500 MSG msg;
501 INT retval;
502 HWND ownerMsg = GetAncestor( owner, GA_ROOT );
503 if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
504
505 if (!(dlgInfo->flags & DF_END)) /* was EndDialog called in WM_INITDIALOG ? */
506 {
507 ShowWindow( hwnd, SW_SHOW );
508 for (;;)
509 {
510 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
511 {
512 if (!PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
513 {
514 /* No message present -> send ENTERIDLE and wait */
515 SendMessageW( ownerMsg, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd );
516 if (!GetMessageW( &msg, 0, 0, 0 )) break;
517 }
518 }
519 else if (!GetMessageW( &msg, 0, 0, 0 )) break;
520
521 if (!IsWindow( hwnd )) return -1;
522 if (!(dlgInfo->flags & DF_END) && !IsDialogMessageW( hwnd, &msg))
523 {
524 TranslateMessage( &msg );
525 DispatchMessageW( &msg );
526 }
527 if (dlgInfo->flags & DF_END) break;
528 }
529 }
530 if (dlgInfo->flags & DF_OWNERENABLED) DIALOG_EnableOwner( owner );
531 retval = dlgInfo->idResult;
532 DestroyWindow( hwnd );
533 return retval;
534 }
535
536 /***********************************************************************
537 * DIALOG_ParseTemplate32
538 *
539 * Fill a DLG_TEMPLATE structure from the dialog template, and return
540 * a pointer to the first control.
541 */
542 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
543 {
544 const WORD *p = (const WORD *)template;
545
546 result->style = GET_DWORD(p); p += 2;
547 if (result->style == 0xffff0001) /* DIALOGEX resource */
548 {
549 result->dialogEx = TRUE;
550 result->helpId = GET_DWORD(p); p += 2;
551 result->exStyle = GET_DWORD(p); p += 2;
552 result->style = GET_DWORD(p); p += 2;
553 }
554 else
555 {
556 result->dialogEx = FALSE;
557 result->helpId = 0;
558 result->exStyle = GET_DWORD(p); p += 2;
559 }
560 result->nbItems = GET_WORD(p); p++;
561 result->x = GET_WORD(p); p++;
562 result->y = GET_WORD(p); p++;
563 result->cx = GET_WORD(p); p++;
564 result->cy = GET_WORD(p); p++;
565
566 /* Get the menu name */
567
568 switch(GET_WORD(p))
569 {
570 case 0x0000:
571 result->menuName = NULL;
572 p++;
573 break;
574 case 0xffff:
575 result->menuName = (LPCWSTR)(UINT)GET_WORD( p + 1 );
576 p += 2;
577 break;
578 default:
579 result->menuName = (LPCWSTR)p;
580 p += wcslen( result->menuName ) + 1;
581 break;
582 }
583
584 /* Get the class name */
585
586 switch(GET_WORD(p))
587 {
588 case 0x0000:
589 result->className = DIALOG_CLASS_ATOMW;
590 p++;
591 break;
592 case 0xffff:
593 result->className = (LPCWSTR)(UINT)GET_WORD( p + 1 );
594 p += 2;
595 break;
596 default:
597 result->className = (LPCWSTR)p;
598 p += wcslen( result->className ) + 1;
599 break;
600 }
601
602 /* Get the window caption */
603
604 result->caption = (LPCWSTR)p;
605 p += wcslen( result->caption ) + 1;
606
607 /* Get the font name */
608
609 if (result->style & DS_SETFONT)
610 {
611 result->pointSize = GET_WORD(p);
612 p++;
613 if (result->dialogEx)
614 {
615 result->weight = GET_WORD(p); p++;
616 result->italic = LOBYTE(GET_WORD(p)); p++;
617 }
618 else
619 {
620 result->weight = FW_DONTCARE;
621 result->italic = FALSE;
622 }
623 result->faceName = (LPCWSTR)p;
624 p += wcslen( result->faceName ) + 1;
625 }
626 else
627 {
628 result->pointSize = 0;
629 result->weight = FW_DONTCARE;
630 result->italic = FALSE;
631 result->faceName = NULL;
632 }
633
634 /* First control is on dword boundary */
635 return (LPCSTR)((((int)p) + 3) & ~3);
636 }
637
638 /***********************************************************************
639 * DIALOG_CreateIndirect
640 * Creates a dialog box window
641 *
642 * modal = TRUE if we are called from a modal dialog box.
643 * (it's more compatible to do it here, as under Windows the owner
644 * is never disabled if the dialog fails because of an invalid template)
645 */
646 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
647 HWND owner, DLGPROC dlgProc, LPARAM param,
648 BOOL unicode, BOOL modal )
649 {
650 HWND hwnd;
651 RECT rect;
652 DLG_TEMPLATE template;
653 DIALOGINFO * dlgInfo;
654 DWORD units = GetDialogBaseUnits();
655 BOOL ownerEnabled = TRUE;
656
657 /* Parse dialog template */
658
659 if (!dlgTemplate) return 0;
660 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
661
662 /* Initialise dialog extra data */
663
664 if (!(dlgInfo = HeapAlloc( GetProcessHeap(), 0, sizeof(*dlgInfo) ))) return 0;
665 dlgInfo->hwndFocus = 0;
666 dlgInfo->hUserFont = 0;
667 dlgInfo->hMenu = 0;
668 dlgInfo->xBaseUnit = LOWORD(units);
669 dlgInfo->yBaseUnit = HIWORD(units);
670 dlgInfo->idResult = 0;
671 dlgInfo->flags = 0;
672 //dlgInfo->hDialogHeap = 0;
673
674 /* Load menu */
675
676 if (template.menuName) dlgInfo->hMenu = LoadMenuW( hInst, template.menuName );
677
678 /* Create custom font if needed */
679
680 if (template.style & DS_SETFONT)
681 {
682 /* We convert the size to pixels and then make it -ve. This works
683 * for both +ve and -ve template.pointSize */
684 HDC dc;
685 int pixels;
686 dc = GetDC(0);
687 pixels = MulDiv(template.pointSize, GetDeviceCaps(dc , LOGPIXELSY), 72);
688 dlgInfo->hUserFont = CreateFontW( -pixels, 0, 0, 0, template.weight,
689 template.italic, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
690 PROOF_QUALITY, FF_DONTCARE,
691 template.faceName );
692 if (dlgInfo->hUserFont)
693 {
694 SIZE charSize;
695 HFONT hOldFont = SelectObject( dc, dlgInfo->hUserFont );
696 charSize.cx = GdiGetCharDimensions( dc, NULL, &charSize.cy );
697 if (charSize.cx)
698 {
699 dlgInfo->xBaseUnit = charSize.cx;
700 dlgInfo->yBaseUnit = charSize.cy;
701 }
702 SelectObject( dc, hOldFont );
703 }
704 ReleaseDC(0, dc);
705 }
706
707 /* Create dialog main window */
708
709 rect.left = rect.top = 0;
710 rect.right = MulDiv(template.cx, dlgInfo->xBaseUnit, 4);
711 rect.bottom = MulDiv(template.cy, dlgInfo->yBaseUnit, 8);
712 if (template.style & WS_CHILD)
713 template.style &= ~(WS_CAPTION|WS_SYSMENU);
714 if (template.style & DS_MODALFRAME)
715 template.exStyle |= WS_EX_DLGMODALFRAME;
716 if (template.style & DS_CONTROL)
717 template.exStyle |= WS_EX_CONTROLPARENT;
718 AdjustWindowRectEx( &rect, template.style, (dlgInfo->hMenu != 0), template.exStyle );
719 rect.right -= rect.left;
720 rect.bottom -= rect.top;
721
722 if (template.x == CW_USEDEFAULT16)
723 {
724 rect.left = rect.top = CW_USEDEFAULT;
725 }
726 else
727 {
728 if (template.style & DS_CENTER)
729 {
730 rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
731 rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
732 }
733 else
734 {
735 rect.left += MulDiv(template.x, dlgInfo->xBaseUnit, 4);
736 rect.top += MulDiv(template.y, dlgInfo->yBaseUnit, 8);
737 }
738 if ( !(template.style & WS_CHILD) )
739 {
740 INT dX, dY;
741
742 if( !(template.style & DS_ABSALIGN) )
743 ClientToScreen( owner, (POINT *)&rect );
744
745 /* try to fit it into the desktop */
746
747 if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
748 - GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
749 if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
750 - GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
751 if( rect.left < 0 ) rect.left = 0;
752 if( rect.top < 0 ) rect.top = 0;
753 }
754 }
755
756 if (modal)
757 {
758 ownerEnabled = DIALOG_DisableOwner( owner );
759 if (ownerEnabled) dlgInfo->flags |= DF_OWNERENABLED;
760 }
761
762 if (unicode)
763 {
764 hwnd = CreateWindowExW(template.exStyle, template.className, template.caption,
765 template.style & ~WS_VISIBLE,
766 rect.left, rect.top, rect.right, rect.bottom,
767 owner, dlgInfo->hMenu, hInst, NULL );
768 }
769 else
770 {
771 LPSTR class = (LPSTR)template.className;
772 LPSTR caption = (LPSTR)template.caption;
773
774 if (HIWORD(class))
775 {
776 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL );
777 class = HeapAlloc( GetProcessHeap(), 0, len );
778 WideCharToMultiByte( CP_ACP, 0, template.className, -1, class, len, NULL, NULL );
779 }
780 if (HIWORD(caption))
781 {
782 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL );
783 caption = HeapAlloc( GetProcessHeap(), 0, len );
784 WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption, len, NULL, NULL );
785 }
786 hwnd = CreateWindowExA(template.exStyle, class, caption,
787 template.style & ~WS_VISIBLE,
788 rect.left, rect.top, rect.right, rect.bottom,
789 owner, dlgInfo->hMenu, hInst, NULL );
790 if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
791 if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
792 }
793
794 if (!hwnd)
795 {
796 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
797 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
798 if (modal && (dlgInfo->flags & DF_OWNERENABLED)) DIALOG_EnableOwner(owner);
799 HeapFree( GetProcessHeap(), 0, dlgInfo );
800 return 0;
801 }
802
803 if (template.helpId)
804 SetWindowContextHelpId( hwnd, template.helpId );
805
806 if (unicode)
807 {
808 SETDLGINFO(hwnd, dlgInfo); /* maybe SetPropW? */
809 SetWindowLongW( hwnd, DWL_DLGPROC, (LONG)dlgProc );
810 }
811 else
812 {
813 SETDLGINFO(hwnd, dlgInfo);
814 SetWindowLongA( hwnd, DWL_DLGPROC, (LONG)dlgProc );
815 }
816
817 if (dlgInfo->hUserFont)
818 SendMessageA( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
819
820 /* Create controls */
821
822 if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode ))
823 {
824 /* Send initialisation messages and set focus */
825
826 if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ))
827 {
828 /* By returning TRUE, app has requested a default focus assignment */
829 dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE);
830 if( dlgInfo->hwndFocus )
831 SetFocus( dlgInfo->hwndFocus );
832 }
833
834 if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
835 {
836 ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
837 }
838 return hwnd;
839 }
840
841 if( IsWindow(hwnd) ) DestroyWindow( hwnd );
842 if (modal && ownerEnabled) DIALOG_EnableOwner(owner);
843 return 0;
844 }
845
846 /***********************************************************************
847 * DEFDLG_SetFocus
848 *
849 * Set the focus to a control of the dialog, selecting the text if
850 * the control is an edit dialog.
851 */
852 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
853 {
854 HWND hwndPrev = GetFocus();
855
856 if (IsChild( hwndDlg, hwndPrev ))
857 {
858 if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
859 SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
860 }
861 if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
862 SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
863 SetFocus( hwndCtrl );
864 }
865
866 /***********************************************************************
867 * DEFDLG_SaveFocus
868 */
869 static void DEFDLG_SaveFocus( HWND hwnd )
870 {
871 DIALOGINFO *infoPtr;
872 HWND hwndFocus = GetFocus();
873
874 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
875 if (!(infoPtr = GETDLGINFO(hwnd))) return;
876 infoPtr->hwndFocus = hwndFocus;
877 /* Remove default button */
878 }
879
880 /***********************************************************************
881 * DEFDLG_RestoreFocus
882 */
883 static void DEFDLG_RestoreFocus( HWND hwnd )
884 {
885 DIALOGINFO *infoPtr;
886
887 if (IsIconic( hwnd )) return;
888 if (!(infoPtr = GETDLGINFO(hwnd))) return;
889 if (!IsWindow( infoPtr->hwndFocus )) return;
890 /* Don't set the focus back to controls if EndDialog is already called.*/
891 if (!(infoPtr->flags & DF_END))
892 {
893 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
894 return;
895 }
896 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
897 sometimes losing focus when receiving WM_SETFOCUS messages. */
898 }
899
900 /***********************************************************************
901 * DEFDLG_FindDefButton
902 *
903 * Find the current default push-button.
904 */
905 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
906 {
907 HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
908 while (hwndChild)
909 {
910 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
911 break;
912 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
913 }
914 return hwndChild;
915 }
916
917 /***********************************************************************
918 * DEFDLG_SetDefButton
919 *
920 * Set the new default button to be hwndNew.
921 */
922 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
923 HWND hwndNew )
924 {
925 DWORD dlgcode=0; /* initialize just to avoid a warning */
926 if (hwndNew &&
927 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
928 & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
929 return FALSE; /* Destination is not a push button */
930
931 if (dlgInfo->idResult) /* There's already a default pushbutton */
932 {
933 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
934 if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
935 SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
936 }
937 if (hwndNew)
938 {
939 if(dlgcode==DLGC_UNDEFPUSHBUTTON)
940 SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
941 dlgInfo->idResult = GetDlgCtrlID( hwndNew );
942 }
943 else dlgInfo->idResult = 0;
944 return TRUE;
945 }
946
947 /***********************************************************************
948 * DEFDLG_Proc
949 *
950 * Implementation of DefDlgProc(). Only handle messages that need special
951 * handling for dialogs.
952 */
953 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
954 LPARAM lParam, DIALOGINFO *dlgInfo )
955 {
956 switch(msg)
957 {
958 case WM_ERASEBKGND:
959 {
960 HBRUSH brush = (HBRUSH)SendMessageW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
961 if (!brush) brush = (HBRUSH)DefWindowProcW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
962 if (brush)
963 {
964 RECT rect;
965 HDC hdc = (HDC)wParam;
966 GetClientRect( hwnd, &rect );
967 DPtoLP( hdc, (LPPOINT)&rect, 2 );
968 FillRect( hdc, &rect, brush );
969 }
970 return 1;
971 }
972 case WM_NCDESTROY:
973 if ((dlgInfo = GETDLGINFO(hwnd)))
974 {
975 /* Free dialog heap (if created) */
976 /*if (dlgInfo->hDialogHeap)
977 {
978 GlobalUnlock16(dlgInfo->hDialogHeap);
979 GlobalFree16(dlgInfo->hDialogHeap);
980 }*/
981 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
982 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
983 HeapFree( GetProcessHeap(), 0, dlgInfo );
984 }
985 /* Window clean-up */
986 return DefWindowProcA( hwnd, msg, wParam, lParam );
987
988 case WM_SHOWWINDOW:
989 if (!wParam) DEFDLG_SaveFocus( hwnd );
990 return DefWindowProcA( hwnd, msg, wParam, lParam );
991
992 case WM_ACTIVATE:
993 if (wParam) DEFDLG_RestoreFocus( hwnd );
994 else DEFDLG_SaveFocus( hwnd );
995 return 0;
996
997 case WM_SETFOCUS:
998 DEFDLG_RestoreFocus( hwnd );
999 return 0;
1000
1001 case DM_SETDEFID:
1002 if (dlgInfo && !(dlgInfo->flags & DF_END))
1003 DEFDLG_SetDefButton( hwnd, dlgInfo, wParam ? GetDlgItem( hwnd, wParam ) : 0 );
1004 return 1;
1005
1006 case DM_GETDEFID:
1007 if (dlgInfo && !(dlgInfo->flags & DF_END))
1008 {
1009 HWND hwndDefId;
1010 if (dlgInfo->idResult)
1011 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
1012 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
1013 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
1014 }
1015 return 0;
1016
1017 case WM_NEXTDLGCTL:
1018 if (dlgInfo)
1019 {
1020 HWND hwndDest = (HWND)wParam;
1021 if (!lParam)
1022 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
1023 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
1024 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
1025 }
1026 return 0;
1027
1028 case WM_ENTERMENULOOP:
1029 case WM_LBUTTONDOWN:
1030 case WM_NCLBUTTONDOWN:
1031 {
1032 HWND hwndFocus = GetFocus();
1033 if (hwndFocus)
1034 {
1035 /* always make combo box hide its listbox control */
1036 if (!SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
1037 SendMessageA( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
1038 }
1039 }
1040 return DefWindowProcA( hwnd, msg, wParam, lParam );
1041
1042 case WM_GETFONT:
1043 return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0;
1044
1045 case WM_CLOSE:
1046 PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED),
1047 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
1048 return 0;
1049
1050 case WM_NOTIFYFORMAT:
1051 return DefWindowProcA( hwnd, msg, wParam, lParam );
1052 }
1053 return 0;
1054 }
1055
1056 /***********************************************************************
1057 * DEFDLG_Epilog
1058 */
1059 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, BOOL fResult)
1060 {
1061 // TODO: where's wine's WM_CTLCOLOR from?
1062 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
1063 /*msg == WM_CTLCOLOR || */ msg == WM_COMPAREITEM ||
1064 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
1065 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
1066 return fResult;
1067
1068 return GetWindowLongA( hwnd, DWL_MSGRESULT );
1069 }
1070
1071 /***********************************************************************
1072 * DIALOG_GetNextTabItem
1073 *
1074 * Helper for GetNextDlgTabItem
1075 */
1076 static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1077 {
1078 LONG dsStyle;
1079 LONG exStyle;
1080 UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT;
1081 HWND retWnd = 0;
1082 HWND hChildFirst = 0;
1083
1084 if(!hwndCtrl)
1085 {
1086 hChildFirst = GetWindow(hwndDlg,GW_CHILD);
1087 if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST);
1088 }
1089 else if (IsChild( hwndMain, hwndCtrl ))
1090 {
1091 hChildFirst = GetWindow(hwndCtrl,wndSearch);
1092 if(!hChildFirst)
1093 {
1094 if(GetParent(hwndCtrl) != hwndMain)
1095 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch);
1096 else
1097 {
1098 if(fPrevious)
1099 hChildFirst = GetWindow(hwndCtrl,GW_HWNDLAST);
1100 else
1101 hChildFirst = GetWindow(hwndCtrl,GW_HWNDFIRST);
1102 }
1103 }
1104 }
1105
1106 while(hChildFirst)
1107 {
1108 BOOL bCtrl = FALSE;
1109 while(hChildFirst)
1110 {
1111 dsStyle = GetWindowLongA(hChildFirst,GWL_STYLE);
1112 exStyle = GetWindowLongA(hChildFirst,GWL_EXSTYLE);
1113 if( (dsStyle & DS_CONTROL || exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1114 {
1115 bCtrl=TRUE;
1116 break;
1117 }
1118 else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1119 break;
1120 hChildFirst = GetWindow(hChildFirst,wndSearch);
1121 }
1122 if(hChildFirst)
1123 {
1124 if(bCtrl)
1125 retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
1126 else
1127 retWnd = hChildFirst;
1128 }
1129 if(retWnd) break;
1130 hChildFirst = GetWindow(hChildFirst,wndSearch);
1131 }
1132 if(!retWnd && hwndCtrl)
1133 {
1134 HWND hParent = GetParent(hwndCtrl);
1135 while(hParent)
1136 {
1137 if(hParent == hwndMain) break;
1138 retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious );
1139 if(retWnd) break;
1140 hParent = GetParent(hParent);
1141 }
1142 if(!retWnd)
1143 retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious );
1144 }
1145 return retWnd;
1146 }
1147
1148 /**********************************************************************
1149 * DIALOG_DlgDirList
1150 *
1151 * Helper function for DlgDirList*
1152 */
1153 static INT DIALOG_DlgDirList( HWND hDlg, LPSTR spec, INT idLBox,
1154 INT idStatic, UINT attrib, BOOL combo )
1155 {
1156 HWND hwnd;
1157 LPSTR orig_spec = spec;
1158 char any[] = "*.*";
1159
1160 #define SENDMSG(msg,wparam,lparam) \
1161 ((attrib & DDL_POSTMSGS) ? PostMessageA( hwnd, msg, wparam, lparam ) \
1162 : SendMessageA( hwnd, msg, wparam, lparam ))
1163
1164 DPRINT("%p '%s' %d %d %04x\n",
1165 hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib );
1166
1167 /* If the path exists and is a directory, chdir to it */
1168 if (!spec || !spec[0] || SetCurrentDirectoryA( spec )) spec = any;
1169 else
1170 {
1171 char *p, *p2;
1172 p = spec;
1173 if ((p2 = strrchr( p, '\\' ))) p = p2;
1174 if ((p2 = strrchr( p, '/' ))) p = p2;
1175 if (p != spec)
1176 {
1177 char sep = *p;
1178 *p = 0;
1179 if (!SetCurrentDirectoryA( spec ))
1180 {
1181 *p = sep; /* Restore the original spec */
1182 return FALSE;
1183 }
1184 spec = p + 1;
1185 }
1186 }
1187
1188 DPRINT( "mask=%s\n", spec );
1189
1190 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
1191 {
1192 SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 );
1193 if (attrib & DDL_DIRECTORY)
1194 {
1195 if (!(attrib & DDL_EXCLUSIVE))
1196 {
1197 if (SENDMSG( combo ? CB_DIR : LB_DIR,
1198 attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1199 (LPARAM)spec ) == LB_ERR)
1200 return FALSE;
1201 }
1202 if (SENDMSG( combo ? CB_DIR : LB_DIR,
1203 (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1204 (LPARAM)"*.*" ) == LB_ERR)
1205 return FALSE;
1206 }
1207 else
1208 {
1209 if (SENDMSG( combo ? CB_DIR : LB_DIR, attrib,
1210 (LPARAM)spec ) == LB_ERR)
1211 return FALSE;
1212 }
1213 }
1214
1215 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
1216 {
1217 char temp[MAX_PATH];
1218 GetCurrentDirectoryA( sizeof(temp), temp );
1219 CharLowerA( temp );
1220 /* Can't use PostMessage() here, because the string is on the stack */
1221 SetDlgItemTextA( hDlg, idStatic, temp );
1222 }
1223
1224 if (orig_spec && (spec != orig_spec))
1225 {
1226 /* Update the original file spec */
1227 char *p = spec;
1228 while ((*orig_spec++ = *p++));
1229 }
1230
1231 return TRUE;
1232 #undef SENDMSG
1233 }
1234
1235 /**********************************************************************
1236 * DIALOG_DlgDirListW
1237 *
1238 * Helper function for DlgDirList*W
1239 */
1240 static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
1241 INT idStatic, UINT attrib, BOOL combo )
1242 {
1243 if (spec)
1244 {
1245 LPSTR specA;
1246 INT ret;
1247
1248 HEAP_strdupWtoA ( &specA, spec, lstrlenW(spec) );
1249 ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic,
1250 attrib, combo );
1251 MultiByteToWideChar( CP_ACP, 0, specA, -1, spec, 0x7fffffff );
1252 HEAP_free( specA );
1253 return ret;
1254 }
1255 return DIALOG_DlgDirList( hDlg, NULL, idLBox, idStatic, attrib, combo );
1256 }
1257
1258 /**********************************************************************
1259 * DIALOG_DlgDirSelect
1260 *
1261 * Helper function for DlgDirSelect*
1262 */
1263 static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPSTR str, INT len,
1264 INT id, BOOL unicode, BOOL combo )
1265 {
1266 char *buffer, *ptr;
1267 INT item, size;
1268 BOOL ret;
1269 HWND listbox = GetDlgItem( hwnd, id );
1270
1271 DPRINT("%p '%s' %d\n", hwnd, str, id );
1272 if (!listbox) return FALSE;
1273
1274 item = SendMessageA(listbox, combo ? CB_GETCURSEL : LB_GETCURSEL, 0, 0 );
1275 if (item == LB_ERR) return FALSE;
1276 size = SendMessageA(listbox, combo ? CB_GETLBTEXTLEN : LB_GETTEXTLEN, 0, 0 );
1277 if (size == LB_ERR) return FALSE;
1278
1279 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size+1 ))) return FALSE;
1280
1281 SendMessageA( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT, item, (LPARAM)buffer );
1282
1283 if ((ret = (buffer[0] == '['))) /* drive or directory */
1284 {
1285 if (buffer[1] == '-') /* drive */
1286 {
1287 buffer[3] = ':';
1288 buffer[4] = 0;
1289 ptr = buffer + 2;
1290 }
1291 else
1292 {
1293 buffer[strlen(buffer)-1] = '\\';
1294 ptr = buffer + 1;
1295 }
1296 }
1297 else ptr = buffer;
1298
1299 if (unicode)
1300 {
1301 if (len > 0 && !MultiByteToWideChar( CP_ACP, 0, ptr, -1, (LPWSTR)str, len ))
1302 ((LPWSTR)str)[len-1] = 0;
1303 }
1304 else lstrcpynA( str, ptr, len );
1305 HeapFree( GetProcessHeap(), 0, buffer );
1306 DPRINT("Returning %d '%s'\n", ret, str );
1307 return ret;
1308 }
1309
1310 /***********************************************************************
1311 * GetDlgItemEnumProc
1312 *
1313 * Callback for GetDlgItem
1314 */
1315 BOOL CALLBACK GetDlgItemEnumProc (HWND hwnd, LPARAM lParam )
1316 {
1317 GETDLGITEMINFO * info = (GETDLGITEMINFO *)lParam;
1318 if(info->nIDDlgItem == GetWindowLongW( hwnd, GWL_ID ))
1319 {
1320 info->control = hwnd;
1321 return FALSE;
1322 }
1323 return TRUE;
1324 }
1325
1326
1327 /* FUNCTIONS *****************************************************************/
1328
1329 /*
1330 * @implemented
1331 */
1332 HWND
1333 STDCALL
1334 CreateDialogIndirectParamA(
1335 HINSTANCE hInstance,
1336 LPCDLGTEMPLATE lpTemplate,
1337 HWND hWndParent,
1338 DLGPROC lpDialogFunc,
1339 LPARAM lParamInit)
1340 {
1341 return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, FALSE, FALSE );
1342 }
1343
1344
1345 /*
1346 * @unimplemented
1347 */
1348 HWND
1349 STDCALL
1350 CreateDialogIndirectParamAorW(
1351 HINSTANCE hInstance,
1352 LPCDLGTEMPLATE lpTemplate,
1353 HWND hWndParent,
1354 DLGPROC lpDialogFunc,
1355 LPARAM lParamInit)
1356 {
1357 /* FIXME:
1358 This function might be obsolete since I don't think it is exported by NT
1359 Also wine has one more parameter identifying weather it should call
1360 the function with unicode or not */
1361 UNIMPLEMENTED;
1362 return (HWND)0;
1363 }
1364
1365
1366 /*
1367 * @implemented
1368 */
1369 HWND
1370 STDCALL
1371 CreateDialogIndirectParamW(
1372 HINSTANCE hInstance,
1373 LPCDLGTEMPLATE lpTemplate,
1374 HWND hWndParent,
1375 DLGPROC lpDialogFunc,
1376 LPARAM lParamInit)
1377 {
1378 return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, TRUE, FALSE );
1379 }
1380
1381
1382 /*
1383 * @implemented
1384 */
1385 HWND
1386 STDCALL
1387 CreateDialogParamA(
1388 HINSTANCE hInstance,
1389 LPCSTR lpTemplateName,
1390 HWND hWndParent,
1391 DLGPROC lpDialogFunc,
1392 LPARAM dwInitParam)
1393 {
1394 HRSRC hrsrc;
1395 LPCDLGTEMPLATE ptr;
1396
1397 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1398 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1399 return CreateDialogIndirectParamA( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1400 }
1401
1402
1403 /*
1404 * @implemented
1405 */
1406 HWND
1407 STDCALL
1408 CreateDialogParamW(
1409 HINSTANCE hInstance,
1410 LPCWSTR lpTemplateName,
1411 HWND hWndParent,
1412 DLGPROC lpDialogFunc,
1413 LPARAM dwInitParam)
1414 {
1415 HRSRC hrsrc;
1416 LPCDLGTEMPLATE ptr;
1417
1418 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1419 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1420 return CreateDialogIndirectParamW( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1421 }
1422
1423
1424 /*
1425 * @implemented
1426 */
1427 LRESULT
1428 STDCALL
1429 DefDlgProcA(
1430 HWND hDlg,
1431 UINT Msg,
1432 WPARAM wParam,
1433 LPARAM lParam)
1434 {
1435 WNDPROC dlgproc;
1436 BOOL result = FALSE;
1437 DIALOGINFO * dlgInfo;
1438
1439 /* if there's no dialog info property then call default windows proc?? */
1440 if (!(dlgInfo = GETDLGINFO(hDlg)))
1441 return DefWindowProcA( hDlg, Msg, wParam, lParam );
1442
1443 SetWindowLongW( hDlg, DWL_MSGRESULT, 0 );
1444
1445 if ((dlgproc = (WNDPROC)GetWindowLongA( hDlg, DWL_DLGPROC )))
1446 {
1447 /* Call dialog procedure */
1448 result = CallWindowProcA( dlgproc, hDlg, Msg, wParam, lParam );
1449 }
1450
1451 if (!result && IsWindow(hDlg))
1452 {
1453 /* callback didn't process this message */
1454
1455 switch(Msg)
1456 {
1457 case WM_ERASEBKGND:
1458 case WM_SHOWWINDOW:
1459 case WM_ACTIVATE:
1460 case WM_SETFOCUS:
1461 case DM_SETDEFID:
1462 case DM_GETDEFID:
1463 case WM_NEXTDLGCTL:
1464 case WM_GETFONT:
1465 case WM_CLOSE:
1466 case WM_NCDESTROY:
1467 case WM_ENTERMENULOOP:
1468 case WM_LBUTTONDOWN:
1469 case WM_NCLBUTTONDOWN:
1470 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1471 case WM_INITDIALOG:
1472 case WM_VKEYTOITEM:
1473 case WM_COMPAREITEM:
1474 case WM_CHARTOITEM:
1475 break;
1476
1477 default:
1478 return DefWindowProcA( hDlg, Msg, wParam, lParam );
1479 }
1480 }
1481 return DEFDLG_Epilog(hDlg, Msg, result);
1482 }
1483
1484
1485 /*
1486 * @implemented
1487 */
1488 LRESULT
1489 STDCALL
1490 DefDlgProcW(
1491 HWND hDlg,
1492 UINT Msg,
1493 WPARAM wParam,
1494 LPARAM lParam)
1495 {
1496 WNDPROC dlgproc;
1497 BOOL result = FALSE;
1498 DIALOGINFO * dlgInfo;
1499
1500 /* if there's no dialog info property then call default windows proc?? */
1501 if (!(dlgInfo = GETDLGINFO(hDlg)))
1502 return DefWindowProcW( hDlg, Msg, wParam, lParam );
1503
1504 SetWindowLongW( hDlg, DWL_MSGRESULT, 0 );
1505
1506 if ((dlgproc = (WNDPROC)GetWindowLongW( hDlg, DWL_DLGPROC )))
1507 {
1508 /* Call dialog procedure */
1509 result = CallWindowProcW( dlgproc, hDlg, Msg, wParam, lParam );
1510 }
1511
1512 if (!result && IsWindow(hDlg))
1513 {
1514 /* callback didn't process this message */
1515
1516 switch(Msg)
1517 {
1518 case WM_ERASEBKGND:
1519 case WM_SHOWWINDOW:
1520 case WM_ACTIVATE:
1521 case WM_SETFOCUS:
1522 case DM_SETDEFID:
1523 case DM_GETDEFID:
1524 case WM_NEXTDLGCTL:
1525 case WM_GETFONT:
1526 case WM_CLOSE:
1527 case WM_NCDESTROY:
1528 case WM_ENTERMENULOOP:
1529 case WM_LBUTTONDOWN:
1530 case WM_NCLBUTTONDOWN:
1531 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1532 case WM_INITDIALOG:
1533 case WM_VKEYTOITEM:
1534 case WM_COMPAREITEM:
1535 case WM_CHARTOITEM:
1536 break;
1537
1538 default:
1539 return DefWindowProcW( hDlg, Msg, wParam, lParam );
1540 }
1541 }
1542 return DEFDLG_Epilog(hDlg, Msg, result);
1543 }
1544
1545
1546 /*
1547 * @implemented
1548 */
1549 INT_PTR
1550 STDCALL
1551 DialogBoxIndirectParamA(
1552 HINSTANCE hInstance,
1553 LPCDLGTEMPLATE hDialogTemplate,
1554 HWND hWndParent,
1555 DLGPROC lpDialogFunc,
1556 LPARAM dwInitParam)
1557 {
1558 HWND hwnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, FALSE, TRUE );
1559 if (hwnd) return DIALOG_DoDialogBox( hwnd, hWndParent );
1560 return -1;
1561 }
1562
1563
1564 /*
1565 * @unimplemented
1566 */
1567 INT_PTR
1568 STDCALL
1569 DialogBoxIndirectParamAorW(
1570 HINSTANCE hInstance,
1571 LPCDLGTEMPLATE hDialogTemplate,
1572 HWND hWndParent,
1573 DLGPROC lpDialogFunc,
1574 LPARAM dwInitParam)
1575 {
1576 /* FIXME:
1577 This function might be obsolete since I don't think it is exported by NT
1578 Also wine has one more parameter identifying weather it should call
1579 the function with unicode or not */
1580 UNIMPLEMENTED;
1581 return (INT_PTR)NULL;
1582 }
1583
1584
1585 /*
1586 * @implemented
1587 */
1588 INT_PTR
1589 STDCALL
1590 DialogBoxIndirectParamW(
1591 HINSTANCE hInstance,
1592 LPCDLGTEMPLATE hDialogTemplate,
1593 HWND hWndParent,
1594 DLGPROC lpDialogFunc,
1595 LPARAM dwInitParam)
1596 {
1597 HWND hwnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, TRUE, TRUE );
1598 if (hwnd) return DIALOG_DoDialogBox( hwnd, hWndParent );
1599 return -1;
1600 }
1601
1602
1603 /*
1604 * @implemented
1605 */
1606 INT_PTR
1607 STDCALL
1608 DialogBoxParamA(
1609 HINSTANCE hInstance,
1610 LPCSTR lpTemplateName,
1611 HWND hWndParent,
1612 DLGPROC lpDialogFunc,
1613 LPARAM dwInitParam)
1614 {
1615 HWND hwnd;
1616 HRSRC hrsrc;
1617 LPCDLGTEMPLATE ptr;
1618
1619 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1620 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1621 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, FALSE, TRUE);
1622 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1623 return -1;
1624 }
1625
1626
1627 /*
1628 * @implemented
1629 */
1630 INT_PTR
1631 STDCALL
1632 DialogBoxParamW(
1633 HINSTANCE hInstance,
1634 LPCWSTR lpTemplateName,
1635 HWND hWndParent,
1636 DLGPROC lpDialogFunc,
1637 LPARAM dwInitParam)
1638 {
1639 HWND hwnd;
1640 HRSRC hrsrc;
1641 LPCDLGTEMPLATE ptr;
1642
1643 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1644 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1645 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, TRUE, TRUE);
1646 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1647 return -1;
1648 }
1649
1650
1651 /*
1652 * @implemented
1653 */
1654 int
1655 STDCALL
1656 DlgDirListA(
1657 HWND hDlg,
1658 LPSTR lpPathSpec,
1659 int nIDListBox,
1660 int nIDStaticPath,
1661 UINT uFileType)
1662 {
1663 return DIALOG_DlgDirList( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
1664 }
1665
1666
1667 /*
1668 * @unimplemented
1669 */
1670 int
1671 STDCALL
1672 DlgDirListComboBoxA(
1673 HWND hDlg,
1674 LPSTR lpPathSpec,
1675 int nIDComboBox,
1676 int nIDStaticPath,
1677 UINT uFiletype)
1678 {
1679 UNIMPLEMENTED;
1680 return 0;
1681 }
1682
1683
1684 /*
1685 * @unimplemented
1686 */
1687 int
1688 STDCALL
1689 DlgDirListComboBoxW(
1690 HWND hDlg,
1691 LPWSTR lpPathSpec,
1692 int nIDComboBox,
1693 int nIDStaticPath,
1694 UINT uFiletype)
1695 {
1696 UNIMPLEMENTED;
1697 return 0;
1698 }
1699
1700
1701 /*
1702 * @implemented
1703 */
1704 int
1705 STDCALL
1706 DlgDirListW(
1707 HWND hDlg,
1708 LPWSTR lpPathSpec,
1709 int nIDListBox,
1710 int nIDStaticPath,
1711 UINT uFileType)
1712 {
1713 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
1714 }
1715
1716
1717 /*
1718 * @unimplemented
1719 */
1720 BOOL
1721 STDCALL
1722 DlgDirSelectComboBoxExA(
1723 HWND hDlg,
1724 LPSTR lpString,
1725 int nCount,
1726 int nIDComboBox)
1727 {
1728 UNIMPLEMENTED;
1729 return FALSE;
1730 }
1731
1732
1733 /*
1734 * @unimplemented
1735 */
1736 BOOL
1737 STDCALL
1738 DlgDirSelectComboBoxExW(
1739 HWND hDlg,
1740 LPWSTR lpString,
1741 int nCount,
1742 int nIDComboBox)
1743 {
1744 UNIMPLEMENTED;
1745 return FALSE;
1746 }
1747
1748
1749 /*
1750 * @implemented
1751 */
1752 BOOL
1753 STDCALL
1754 DlgDirSelectExA(
1755 HWND hDlg,
1756 LPSTR lpString,
1757 int nCount,
1758 int nIDListBox)
1759 {
1760 return DIALOG_DlgDirSelect( hDlg, lpString, nCount, nIDListBox, FALSE, FALSE );
1761 }
1762
1763
1764 /*
1765 * @implemented
1766 */
1767 BOOL
1768 STDCALL
1769 DlgDirSelectExW(
1770 HWND hDlg,
1771 LPWSTR lpString,
1772 int nCount,
1773 int nIDListBox)
1774 {
1775 return DIALOG_DlgDirSelect( hDlg, (LPSTR)lpString, nCount, nIDListBox, TRUE, FALSE );
1776 }
1777
1778
1779 /*
1780 * @implemented
1781 */
1782 BOOL
1783 STDCALL
1784 EndDialog(
1785 HWND hDlg,
1786 INT_PTR nResult)
1787 {
1788 BOOL wasEnabled = TRUE;
1789 DIALOGINFO * dlgInfo;
1790 HWND owner;
1791
1792 if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
1793
1794 dlgInfo->idResult = nResult;
1795 dlgInfo->flags |= DF_END;
1796 wasEnabled = (dlgInfo->flags & DF_OWNERENABLED);
1797
1798 if (wasEnabled && (owner = GetWindow( hDlg, GW_OWNER )))
1799 DIALOG_EnableOwner( owner );
1800
1801 /* Windows sets the focus to the dialog itself in EndDialog */
1802
1803 if (IsChild(hDlg, GetFocus()))
1804 SetFocus( hDlg );
1805
1806 /* Don't have to send a ShowWindow(SW_HIDE), just do
1807 SetWindowPos with SWP_HIDEWINDOW as done in Windows */
1808
1809 SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
1810 | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
1811
1812 /* unblock dialog loop */
1813 PostMessageA(hDlg, WM_NULL, 0, 0);
1814 return TRUE;
1815 }
1816
1817
1818 /*
1819 * @implemented
1820 */
1821 LONG
1822 STDCALL
1823 GetDialogBaseUnits(VOID)
1824 {
1825 static DWORD units;
1826
1827 if (!units)
1828 {
1829 HDC hdc;
1830 SIZE size;
1831
1832 if ((hdc = GetDC(0)))
1833 {
1834 size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
1835 if (size.cx) units = MAKELONG( size.cx, size.cy );
1836 ReleaseDC( 0, hdc );
1837 }
1838 }
1839 return units;
1840 }
1841
1842
1843 /*
1844 * @implemented
1845 */
1846 int
1847 STDCALL
1848 GetDlgCtrlID(
1849 HWND hwndCtl)
1850 {
1851 return GetWindowLongW( hwndCtl, GWL_ID );
1852 }
1853
1854
1855 /*
1856 * @implemented
1857 */
1858 HWND
1859 STDCALL
1860 GetDlgItem(
1861 HWND hDlg,
1862 int nIDDlgItem)
1863 {
1864 GETDLGITEMINFO info;
1865 info.nIDDlgItem = nIDDlgItem;
1866 info.control = 0;
1867 if(hDlg && !EnumChildWindows(hDlg, (ENUMWINDOWSPROC)&GetDlgItemEnumProc, (LPARAM)&info))
1868 return info.control;
1869 else
1870 return 0;
1871 }
1872
1873
1874 /*
1875 * @implemented
1876 */
1877 UINT
1878 STDCALL
1879 GetDlgItemInt(
1880 HWND hDlg,
1881 int nIDDlgItem,
1882 BOOL *lpTranslated,
1883 BOOL bSigned)
1884 {
1885 char str[30];
1886 char * endptr;
1887 long result = 0;
1888
1889 if (lpTranslated) *lpTranslated = FALSE;
1890 if (!SendDlgItemMessageA(hDlg, nIDDlgItem, WM_GETTEXT, sizeof(str), (LPARAM)str))
1891 return 0;
1892 if (bSigned)
1893 {
1894 result = strtol( str, &endptr, 10 );
1895 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
1896 return 0;
1897 /* FIXME: errno? */
1898 if (((result == 0) || (result == 0xFFFFFFFF))/* && (errno == ERANGE) */)
1899 return 0;
1900 }
1901 else
1902 {
1903 result = strtoul( str, &endptr, 10 );
1904 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
1905 return 0;
1906 /* FIXME: errno? */
1907 if ((result == 0xFFFFFFFF)/* && (errno == ERANGE) */) return 0;
1908 }
1909 if (lpTranslated) *lpTranslated = TRUE;
1910 return (UINT)result;
1911 }
1912
1913
1914 /*
1915 * @implemented
1916 */
1917 UINT
1918 STDCALL
1919 GetDlgItemTextA(
1920 HWND hDlg,
1921 int nIDDlgItem,
1922 LPSTR lpString,
1923 int nMaxCount)
1924 {
1925 return (UINT)SendDlgItemMessageA( hDlg, nIDDlgItem, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
1926 }
1927
1928
1929 /*
1930 * @implemented
1931 */
1932 UINT
1933 STDCALL
1934 GetDlgItemTextW(
1935 HWND hDlg,
1936 int nIDDlgItem,
1937 LPWSTR lpString,
1938 int nMaxCount)
1939 {
1940 return (UINT)SendDlgItemMessageW( hDlg, nIDDlgItem, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
1941 }
1942
1943
1944 /*
1945 * @implemented
1946 */
1947 HWND
1948 STDCALL
1949 GetNextDlgGroupItem(
1950 HWND hDlg,
1951 HWND hCtl,
1952 BOOL bPrevious)
1953 {
1954 HWND hwnd, retvalue;
1955
1956 if(hCtl)
1957 {
1958 /* if the hwndCtrl is the child of the control in the hwndDlg,
1959 * then the hwndDlg has to be the parent of the hwndCtrl */
1960 if(GetParent(hCtl) != hDlg && GetParent(GetParent(hCtl)) == hDlg)
1961 hDlg = GetParent(hCtl);
1962 }
1963
1964 if (hCtl)
1965 {
1966 /* Make sure hwndCtrl is a top-level child */
1967 HWND parent = GetParent( hCtl );
1968 while (parent && parent != hDlg) parent = GetParent(parent);
1969 if (parent != hDlg) return 0;
1970 }
1971 else
1972 {
1973 /* No ctrl specified -> start from the beginning */
1974 if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
1975 if (bPrevious) hCtl = GetWindow( hCtl, GW_HWNDLAST );
1976 }
1977
1978 retvalue = hCtl;
1979 hwnd = GetWindow( hCtl, GW_HWNDNEXT );
1980 while (1)
1981 {
1982 if (!hwnd || (GetWindowLongW( hwnd, GWL_STYLE ) & WS_GROUP))
1983 {
1984 /* Wrap-around to the beginning of the group */
1985 HWND tmp;
1986
1987 hwnd = GetWindow( hDlg, GW_CHILD );
1988 for (tmp = hwnd; tmp; tmp = GetWindow( tmp, GW_HWNDNEXT ) )
1989 {
1990 if (GetWindowLongW( tmp, GWL_STYLE ) & WS_GROUP) hwnd = tmp;
1991 if (tmp == hCtl) break;
1992 }
1993 }
1994 if (hwnd == hCtl) break;
1995 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
1996 {
1997 retvalue = hwnd;
1998 if (!bPrevious) break;
1999 }
2000 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
2001 }
2002 return retvalue;
2003 }
2004
2005
2006 /*
2007 * @implemented
2008 */
2009 HWND
2010 STDCALL
2011 GetNextDlgTabItem(
2012 HWND hDlg,
2013 HWND hCtl,
2014 BOOL bPrevious)
2015 {
2016 return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious);
2017 }
2018
2019 #if 0
2020 BOOL
2021 STDCALL
2022 IsDialogMessage(
2023 HWND hDlg,
2024 LPMSG lpMsg)
2025 {
2026 return IsDialogMessageW(hDlg, lpMsg);
2027 }
2028 #endif
2029
2030
2031 /*
2032 * @implemented
2033 */
2034 BOOL
2035 STDCALL
2036 IsDialogMessageA(
2037 HWND hDlg,
2038 LPMSG lpMsg)
2039 {
2040 INT dlgCode = 0;
2041
2042 // FIXME: hooks
2043 if (CallMsgFilterA( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2044
2045 if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
2046
2047 hDlg = DIALOG_FindMsgDestination(hDlg);
2048
2049 switch(lpMsg->message)
2050 {
2051 case WM_KEYDOWN:
2052 dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2053 if (dlgCode & DLGC_WANTMESSAGE) break;
2054
2055 switch(lpMsg->wParam)
2056 {
2057 case VK_TAB:
2058 if (!(dlgCode & DLGC_WANTTAB))
2059 {
2060 SendMessageA( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
2061 return TRUE;
2062 }
2063 break;
2064
2065 case VK_RIGHT:
2066 case VK_DOWN:
2067 case VK_LEFT:
2068 case VK_UP:
2069 if (!(dlgCode & DLGC_WANTARROWS))
2070 {
2071 BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
2072 HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious );
2073 SendMessageA( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
2074 return TRUE;
2075 }
2076 break;
2077
2078 case VK_CANCEL:
2079 case VK_ESCAPE:
2080 SendMessageA( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
2081 return TRUE;
2082
2083 case VK_EXECUTE:
2084 case VK_RETURN:
2085 {
2086 DWORD dw = SendMessageA( hDlg, DM_GETDEFID, 0, 0 );
2087 if (HIWORD(dw) == DC_HASDEFID)
2088 {
2089 SendMessageA( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
2090 (LPARAM)GetDlgItem(hDlg, LOWORD(dw)));
2091 }
2092 else
2093 {
2094 SendMessageA( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
2095
2096 }
2097 }
2098 return TRUE;
2099 }
2100 break;
2101
2102 case WM_CHAR:
2103 dlgCode = SendMessageA( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2104 if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
2105 if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
2106 /* drop through */
2107
2108 case WM_SYSCHAR:
2109 if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
2110 {
2111 /* don't translate or dispatch */
2112 return TRUE;
2113 }
2114 break;
2115 }
2116
2117 TranslateMessage( lpMsg );
2118 DispatchMessageA( lpMsg );
2119 return TRUE;
2120 }
2121
2122
2123 /*
2124 * @implemented
2125 */
2126 BOOL
2127 STDCALL
2128 IsDialogMessageW(
2129 HWND hDlg,
2130 LPMSG lpMsg)
2131 {
2132 INT dlgCode = 0;
2133
2134 // FIXME: hooks
2135 if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2136
2137 if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
2138
2139 hDlg = DIALOG_FindMsgDestination(hDlg);
2140
2141 switch(lpMsg->message)
2142 {
2143 case WM_KEYDOWN:
2144 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2145 if (dlgCode & DLGC_WANTMESSAGE) break;
2146
2147 switch(lpMsg->wParam)
2148 {
2149 case VK_TAB:
2150 if (!(dlgCode & DLGC_WANTTAB))
2151 {
2152 SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
2153 return TRUE;
2154 }
2155 break;
2156
2157 case VK_RIGHT:
2158 case VK_DOWN:
2159 case VK_LEFT:
2160 case VK_UP:
2161 if (!(dlgCode & DLGC_WANTARROWS))
2162 {
2163 BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
2164 HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious );
2165 SendMessageW( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
2166 return TRUE;
2167 }
2168 break;
2169
2170 case VK_CANCEL:
2171 case VK_ESCAPE:
2172 SendMessageW( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
2173 return TRUE;
2174
2175 case VK_EXECUTE:
2176 case VK_RETURN:
2177 {
2178 DWORD dw = SendMessageW( hDlg, DM_GETDEFID, 0, 0 );
2179 if (HIWORD(dw) == DC_HASDEFID)
2180 {
2181 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
2182 (LPARAM)GetDlgItem(hDlg, LOWORD(dw)));
2183 }
2184 else
2185 {
2186 SendMessageW( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
2187
2188 }
2189 }
2190 return TRUE;
2191 }
2192 break;
2193
2194 case WM_CHAR:
2195 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2196 if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
2197 if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
2198 /* drop through */
2199
2200 case WM_SYSCHAR:
2201 if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
2202 {
2203 /* don't translate or dispatch */
2204 return TRUE;
2205 }
2206 break;
2207 }
2208
2209 TranslateMessage( lpMsg );
2210 DispatchMessageW( lpMsg );
2211 return TRUE;
2212 }
2213
2214
2215 /*
2216 * @implemented
2217 */
2218 UINT
2219 STDCALL
2220 IsDlgButtonChecked(
2221 HWND hDlg,
2222 int nIDButton)
2223 {
2224 return (UINT)SendDlgItemMessageA( hDlg, nIDButton, BM_GETCHECK, 0, 0 );
2225 }
2226
2227
2228 /*
2229 * @implemented
2230 */
2231 BOOL
2232 STDCALL
2233 MapDialogRect(
2234 HWND hDlg,
2235 LPRECT lpRect)
2236 {
2237 DIALOGINFO * dlgInfo;
2238 if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
2239 lpRect->left = MulDiv(lpRect->left, dlgInfo->xBaseUnit, 4);
2240 lpRect->right = MulDiv(lpRect->right, dlgInfo->xBaseUnit, 4);
2241 lpRect->top = MulDiv(lpRect->top, dlgInfo->yBaseUnit, 8);
2242 lpRect->bottom = MulDiv(lpRect->bottom, dlgInfo->yBaseUnit, 8);
2243 return TRUE;
2244 }
2245
2246
2247 /*
2248 * @implemented
2249 */
2250 LRESULT
2251 STDCALL
2252 SendDlgItemMessageA(
2253 HWND hDlg,
2254 int nIDDlgItem,
2255 UINT Msg,
2256 WPARAM wParam,
2257 LPARAM lParam)
2258 {
2259 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2260 if (hwndCtrl) return SendMessageA( hwndCtrl, Msg, wParam, lParam );
2261 else return 0;
2262 }
2263
2264
2265 /*
2266 * @implemented
2267 */
2268 LRESULT
2269 STDCALL
2270 SendDlgItemMessageW(
2271 HWND hDlg,
2272 int nIDDlgItem,
2273 UINT Msg,
2274 WPARAM wParam,
2275 LPARAM lParam)
2276 {
2277 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2278 if (hwndCtrl) return SendMessageW( hwndCtrl, Msg, wParam, lParam );
2279 else return 0;
2280 }
2281
2282
2283 /*
2284 * @implemented
2285 */
2286 BOOL
2287 STDCALL
2288 SetDlgItemInt(
2289 HWND hDlg,
2290 int nIDDlgItem,
2291 UINT uValue,
2292 BOOL bSigned)
2293 {
2294 char str[20];
2295
2296 if (bSigned) sprintf( str, "%d", (INT)uValue );
2297 else sprintf( str, "%u", uValue );
2298 SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)str );
2299 return TRUE;
2300 }
2301
2302
2303 /*
2304 * @implemented
2305 */
2306 BOOL
2307 STDCALL
2308 SetDlgItemTextA(
2309 HWND hDlg,
2310 int nIDDlgItem,
2311 LPCSTR lpString)
2312 {
2313 return SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)lpString );
2314 }
2315
2316
2317 /*
2318 * @implemented
2319 */
2320 BOOL
2321 STDCALL
2322 SetDlgItemTextW(
2323 HWND hDlg,
2324 int nIDDlgItem,
2325 LPCWSTR lpString)
2326 {
2327 return SendDlgItemMessageW( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)lpString );
2328 }
2329
2330
2331 /*
2332 * @implemented
2333 */
2334 BOOL
2335 STDCALL
2336 CheckDlgButton(
2337 HWND hDlg,
2338 int nIDButton,
2339 UINT uCheck)
2340 {
2341 SendDlgItemMessageA( hDlg, nIDButton, BM_SETCHECK, uCheck, 0 );
2342 return TRUE;
2343 }
2344
2345 static BOOL CALLBACK CheckRB(HWND hwnd, LPARAM lParam)
2346 {
2347 LONG lChildID = GetWindowLongW(hwnd, GWL_ID);
2348 RADIOGROUP *lpRadioGroup = (RADIOGROUP *)lParam;
2349
2350 if((lChildID >= lpRadioGroup->firstID) &&
2351 (lChildID <= lpRadioGroup->lastID))
2352 {
2353 if (lChildID == lpRadioGroup->checkID)
2354 {
2355 SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0);
2356 }
2357 else
2358 {
2359 SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0);
2360 }
2361 }
2362
2363 return TRUE;
2364 }
2365
2366 /*
2367 * @implemented
2368 */
2369 BOOL
2370 STDCALL
2371 CheckRadioButton(
2372 HWND hDlg,
2373 int nIDFirstButton,
2374 int nIDLastButton,
2375 int nIDCheckButton)
2376 {
2377 RADIOGROUP radioGroup;
2378
2379 radioGroup.firstID = nIDFirstButton;
2380 radioGroup.lastID = nIDLastButton;
2381 radioGroup.checkID = nIDCheckButton;
2382
2383 return EnumChildWindows(hDlg, CheckRB, (LPARAM)&radioGroup);
2384 }
2385