commctrl.c 48.8 KB
Newer Older
1
/*
Alexandre Julliard's avatar
Alexandre Julliard committed
2 3 4
 * Common controls functions
 *
 * Copyright 1997 Dimitrie O. Paun
5
 * Copyright 1998,2000 Eric Kohl
6
 * Copyright 2014-2015 Michael Müller
Alexandre Julliard's avatar
Alexandre Julliard committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23 24 25 26
 *
 * NOTES
 * 
 * This code was audited for completeness against the documented features
 * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.
 *
Robert Shearman's avatar
Robert Shearman committed
27
 * Unless otherwise noted, we believe this code to be complete, as per
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
 * the specification mentioned above.
 * If you discover missing features, or bugs, please note them below.
 *
 * TODO
 *   -- implement GetMUILanguage + InitMUILanguage
 *   -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
 *   -- FIXMEs + BUGS (search for them)
 *
 * Control Classes
 *   -- ICC_ANIMATE_CLASS
 *   -- ICC_BAR_CLASSES
 *   -- ICC_COOL_CLASSES
 *   -- ICC_DATE_CLASSES
 *   -- ICC_HOTKEY_CLASS
 *   -- ICC_INTERNET_CLASSES
43
 *   -- ICC_LINK_CLASS
44 45 46 47 48 49 50 51 52 53
 *   -- ICC_LISTVIEW_CLASSES
 *   -- ICC_NATIVEFNTCTL_CLASS
 *   -- ICC_PAGESCROLLER_CLASS
 *   -- ICC_PROGRESS_CLASS
 *   -- ICC_STANDARD_CLASSES (not yet implemented)
 *   -- ICC_TAB_CLASSES
 *   -- ICC_TREEVIEW_CLASSES
 *   -- ICC_UPDOWN_CLASS
 *   -- ICC_USEREX_CLASSES
 *   -- ICC_WIN95_CLASSES
Alexandre Julliard's avatar
Alexandre Julliard committed
54 55
 */

56
#include <stdarg.h>
57
#include <string.h>
58
#include <stdlib.h>
59

60
#include "windef.h"
61
#include "winbase.h"
62 63 64
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
65
#include "commctrl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
66
#include "winerror.h"
67
#include "winreg.h"
68
#define NO_SHLWAPI_STREAM
69
#include "shlwapi.h"
Gerard Patel's avatar
Gerard Patel committed
70
#include "comctl32.h"
71
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
72

73
WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
74

75

76
static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
77

78
static LPWSTR COMCTL32_wSubclass = NULL;
79
HMODULE COMCTL32_hModule = 0;
80
static LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
81
HBRUSH  COMCTL32_hPattern55AABrush = NULL;
82
COMCTL32_SysColor  comctl32_color;
83

84
static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
85 86 87 88 89 90

static const WORD wPattern55AA[] =
{
    0x5555, 0xaaaa, 0x5555, 0xaaaa,
    0x5555, 0xaaaa, 0x5555, 0xaaaa
};
91

92 93 94
static const WCHAR strCC32SubclassInfo[] = {
    'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
};
95

96

Alexandre Julliard's avatar
Alexandre Julliard committed
97
/***********************************************************************
98 99 100
 * DllMain [Internal]
 *
 * Initializes the internal 'COMCTL32.DLL'.
Alexandre Julliard's avatar
Alexandre Julliard committed
101 102
 *
 * PARAMS
Alexandre Julliard's avatar
Alexandre Julliard committed
103
 *     hinstDLL    [I] handle to the 'dlls' instance
Alexandre Julliard's avatar
Alexandre Julliard committed
104
 *     fdwReason   [I]
105
 *     lpvReserved [I] reserved, must be NULL
Alexandre Julliard's avatar
Alexandre Julliard committed
106
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
107 108 109
 * RETURNS
 *     Success: TRUE
 *     Failure: FALSE
Alexandre Julliard's avatar
Alexandre Julliard committed
110
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
111

112
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Alexandre Julliard's avatar
Alexandre Julliard committed
113
{
114
    TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
Alexandre Julliard's avatar
Alexandre Julliard committed
115 116 117

    switch (fdwReason) {
	case DLL_PROCESS_ATTACH:
118 119
            DisableThreadLibraryCalls(hinstDLL);

120
            COMCTL32_hModule = hinstDLL;
121 122

            /* add global subclassing atom (used by 'tooltip' and 'updown') */
Frank Richter's avatar
Frank Richter committed
123
            COMCTL32_wSubclass = (LPWSTR)(DWORD_PTR)GlobalAddAtomW (strCC32SubclassInfo);
124
            TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
125 126 127 128 129

            /* create local pattern brush */
            COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
            COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);

130 131 132
	    /* Get all the colors at DLL load */
	    COMCTL32_RefreshSysColors();

133
            /* like comctl32 5.82+ register all the common control classes */
134
            ANIMATE_Register ();
135 136
            COMBOEX_Register ();
            DATETIME_Register ();
137 138 139
            FLATSB_Register ();
            HEADER_Register ();
            HOTKEY_Register ();
140
            IPADDRESS_Register ();
141
            LISTVIEW_Register ();
142 143 144
            MONTHCAL_Register ();
            NATIVEFONT_Register ();
            PAGER_Register ();
145
            PROGRESS_Register ();
146
            REBAR_Register ();
147
            STATUS_Register ();
148
            SYSLINK_Register ();
149 150 151 152 153 154
            TAB_Register ();
            TOOLBAR_Register ();
            TOOLTIPS_Register ();
            TRACKBAR_Register ();
            TREEVIEW_Register ();
            UPDOWN_Register ();
155 156 157

            /* subclass user32 controls */
            THEMING_Initialize ();
158
            break;
159 160

	case DLL_PROCESS_DETACH:
161 162
            if (lpvReserved) break;
            /* clean up subclassing */
163 164
            THEMING_Uninitialize();

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
            /* unregister all common control classes */
            ANIMATE_Unregister ();
            COMBOEX_Unregister ();
            DATETIME_Unregister ();
            FLATSB_Unregister ();
            HEADER_Unregister ();
            HOTKEY_Unregister ();
            IPADDRESS_Unregister ();
            LISTVIEW_Unregister ();
            MONTHCAL_Unregister ();
            NATIVEFONT_Unregister ();
            PAGER_Unregister ();
            PROGRESS_Unregister ();
            REBAR_Unregister ();
            STATUS_Unregister ();
180
            SYSLINK_Unregister ();
181 182 183 184 185 186 187 188 189 190 191 192
            TAB_Unregister ();
            TOOLBAR_Unregister ();
            TOOLTIPS_Unregister ();
            TRACKBAR_Unregister ();
            TREEVIEW_Unregister ();
            UPDOWN_Unregister ();

            /* delete local pattern brush */
            DeleteObject (COMCTL32_hPattern55AABrush);
            DeleteObject (COMCTL32_hPattern55AABitmap);

            /* delete global subclassing atom */
193 194
            GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
            TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
195
            break;
Alexandre Julliard's avatar
Alexandre Julliard committed
196
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
197

Alexandre Julliard's avatar
Alexandre Julliard committed
198
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
199
}
Alexandre Julliard's avatar
Alexandre Julliard committed
200 201


Alexandre Julliard's avatar
Alexandre Julliard committed
202 203 204
/***********************************************************************
 * MenuHelp [COMCTL32.2]
 *
205 206 207
 * Handles the setting of status bar help messages when the user
 * selects menu items.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
208
 * PARAMS
209 210 211 212 213
 *     uMsg       [I] message (WM_MENUSELECT) (see NOTES)
 *     wParam     [I] wParam of the message uMsg
 *     lParam     [I] lParam of the message uMsg
 *     hMainMenu  [I] handle to the application's main menu
 *     hInst      [I] handle to the module that contains string resources
Alexandre Julliard's avatar
Alexandre Julliard committed
214
 *     hwndStatus [I] handle to the status bar window
215
 *     lpwIDs     [I] pointer to an array of integers (see NOTES)
Alexandre Julliard's avatar
Alexandre Julliard committed
216 217
 *
 * RETURNS
Alexandre Julliard's avatar
Alexandre Julliard committed
218
 *     No return value
Alexandre Julliard's avatar
Alexandre Julliard committed
219 220
 *
 * NOTES
Alexandre Julliard's avatar
Alexandre Julliard committed
221
 *     The official documentation is incomplete!
222 223 224
 *     This is the correct documentation:
 *
 *     uMsg:
Andreas Mohr's avatar
Andreas Mohr committed
225
 *     MenuHelp() does NOT handle WM_COMMAND messages! It only handles
226 227 228 229
 *     WM_MENUSELECT messages.
 *
 *     lpwIDs:
 *     (will be written ...)
Alexandre Julliard's avatar
Alexandre Julliard committed
230 231 232
 */

VOID WINAPI
233
MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
234
	  HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
Alexandre Julliard's avatar
Alexandre Julliard committed
235
{
236
    UINT uMenuID = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
237

238
    if (!IsWindow (hwndStatus))
Alexandre Julliard's avatar
Alexandre Julliard committed
239
	return;
Alexandre Julliard's avatar
Alexandre Julliard committed
240 241 242

    switch (uMsg) {
	case WM_MENUSELECT:
243
	    TRACE("WM_MENUSELECT wParam=0x%lX lParam=0x%lX\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
244
		   wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
245 246 247

            if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
                /* menu was closed */
248
		TRACE("menu was closed!\n");
249
                SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
250
            }
Alexandre Julliard's avatar
Alexandre Julliard committed
251 252 253
	    else {
		/* menu item was selected */
		if (HIWORD(wParam) & MF_POPUP)
254
		    uMenuID = *(lpwIDs+1);
Alexandre Julliard's avatar
Alexandre Julliard committed
255
		else
256
		    uMenuID = (UINT)LOWORD(wParam);
257
		TRACE("uMenuID = %u\n", uMenuID);
Alexandre Julliard's avatar
Alexandre Julliard committed
258 259

		if (uMenuID) {
260
		    WCHAR szText[256];
Alexandre Julliard's avatar
Alexandre Julliard committed
261

262
		    if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
263
			szText[0] = '\0';
Alexandre Julliard's avatar
Alexandre Julliard committed
264

265
		    SendMessageW (hwndStatus, SB_SETTEXTW,
Alexandre Julliard's avatar
Alexandre Julliard committed
266
				    255 | SBT_NOBORDERS, (LPARAM)szText);
267
		    SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
268 269 270
		}
	    }
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
271

272
        case WM_COMMAND :
273
	    TRACE("WM_COMMAND wParam=0x%lX lParam=0x%lX\n",
274 275 276 277 278 279 280 281
		   wParam, lParam);
	    /* WM_COMMAND is not invalid since it is documented
	     * in the windows api reference. So don't output
             * any FIXME for WM_COMMAND
             */
	    WARN("We don't care about the WM_COMMAND\n");
	    break;

Alexandre Julliard's avatar
Alexandre Julliard committed
282
	default:
283
	    FIXME("Invalid Message 0x%x!\n", uMsg);
Alexandre Julliard's avatar
Alexandre Julliard committed
284
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
285 286 287 288 289
    }
}


/***********************************************************************
290
 * ShowHideMenuCtl [COMCTL32.3]
Alexandre Julliard's avatar
Alexandre Julliard committed
291 292 293 294 295 296 297 298 299 300 301 302 303
 *
 * Shows or hides controls and updates the corresponding menu item.
 *
 * PARAMS
 *     hwnd   [I] handle to the client window.
 *     uFlags [I] menu command id.
 *     lpInfo [I] pointer to an array of integers. (See NOTES.)
 *
 * RETURNS
 *     Success: TRUE
 *     Failure: FALSE
 *
 * NOTES
304 305 306 307 308 309 310
 *     The official documentation is incomplete!
 *     This is the correct documentation:
 *
 *     hwnd
 *     Handle to the window that contains the menu and controls.
 *
 *     uFlags
311
 *     Identifier of the menu item to receive or lose a check mark.
Alexandre Julliard's avatar
Alexandre Julliard committed
312 313 314
 *
 *     lpInfo
 *     The array of integers contains pairs of values. BOTH values of
315
 *     the first pair must be the handles to the application's main menu.
Alexandre Julliard's avatar
Alexandre Julliard committed
316 317 318
 *     Each subsequent pair consists of a menu id and control id.
 */

319
BOOL WINAPI
Frank Richter's avatar
Frank Richter committed
320
ShowHideMenuCtl (HWND hwnd, UINT_PTR uFlags, LPINT lpInfo)
Alexandre Julliard's avatar
Alexandre Julliard committed
321
{
322
    LPINT lpMenuId;
Alexandre Julliard's avatar
Alexandre Julliard committed
323

324
    TRACE("%p, %lx, %p\n", hwnd, uFlags, lpInfo);
Alexandre Julliard's avatar
Alexandre Julliard committed
325 326 327 328 329 330 331 332 333 334 335 336

    if (lpInfo == NULL)
	return FALSE;

    if (!(lpInfo[0]) || !(lpInfo[1]))
	return FALSE;

    /* search for control */
    lpMenuId = &lpInfo[2];
    while (*lpMenuId != uFlags)
	lpMenuId += 2;

Frank Richter's avatar
Frank Richter committed
337
    if (GetMenuState ((HMENU)(DWORD_PTR)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
Alexandre Julliard's avatar
Alexandre Julliard committed
338
	/* uncheck menu item */
Frank Richter's avatar
Frank Richter committed
339
	CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
Alexandre Julliard's avatar
Alexandre Julliard committed
340 341 342

	/* hide control */
	lpMenuId++;
343
	SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
Alexandre Julliard's avatar
Alexandre Julliard committed
344 345 346 347
			SWP_HIDEWINDOW);
    }
    else {
	/* check menu item */
Frank Richter's avatar
Frank Richter committed
348
	CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
Alexandre Julliard's avatar
Alexandre Julliard committed
349 350 351

	/* show control */
	lpMenuId++;
352
	SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
Alexandre Julliard's avatar
Alexandre Julliard committed
353 354 355 356 357 358 359 360 361 362
			SWP_SHOWWINDOW);
    }

    return TRUE;
}


/***********************************************************************
 * GetEffectiveClientRect [COMCTL32.4]
 *
363 364
 * Calculates the coordinates of a rectangle in the client area.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
365 366 367
 * PARAMS
 *     hwnd   [I] handle to the client window.
 *     lpRect [O] pointer to the rectangle of the client window
368
 *     lpInfo [I] pointer to an array of integers (see NOTES)
Alexandre Julliard's avatar
Alexandre Julliard committed
369 370
 *
 * RETURNS
Alexandre Julliard's avatar
Alexandre Julliard committed
371
 *     No return value.
Alexandre Julliard's avatar
Alexandre Julliard committed
372 373
 *
 * NOTES
Alexandre Julliard's avatar
Alexandre Julliard committed
374
 *     The official documentation is incomplete!
375 376 377
 *     This is the correct documentation:
 *
 *     lpInfo
378
 *     (will be written ...)
Alexandre Julliard's avatar
Alexandre Julliard committed
379 380 381
 */

VOID WINAPI
382
GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, const INT *lpInfo)
Alexandre Julliard's avatar
Alexandre Julliard committed
383
{
384
    RECT rcCtrl;
385
    const INT *lpRun;
386
    HWND hwndCtrl;
Alexandre Julliard's avatar
Alexandre Julliard committed
387

Frank Richter's avatar
Frank Richter committed
388 389
    TRACE("(%p %p %p)\n",
	   hwnd, lpRect, lpInfo);
Alexandre Julliard's avatar
Alexandre Julliard committed
390

391
    GetClientRect (hwnd, lpRect);
Alexandre Julliard's avatar
Alexandre Julliard committed
392 393 394 395 396 397 398
    lpRun = lpInfo;

    do {
	lpRun += 2;
	if (*lpRun == 0)
	    return;
	lpRun++;
399
	hwndCtrl = GetDlgItem (hwnd, *lpRun);
400
	if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
401
	    TRACE("control id 0x%x\n", *lpRun);
402
	    GetWindowRect (hwndCtrl, &rcCtrl);
403
	    MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
404
	    SubtractRect (lpRect, lpRect, &rcCtrl);
Alexandre Julliard's avatar
Alexandre Julliard committed
405 406 407 408 409 410
	}
	lpRun++;
    } while (*lpRun);
}


Alexandre Julliard's avatar
Alexandre Julliard committed
411
/***********************************************************************
412
 * DrawStatusTextW [COMCTL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
413 414 415 416 417 418 419
 *
 * Draws text with borders, like in a status bar.
 *
 * PARAMS
 *     hdc   [I] handle to the window's display context
 *     lprc  [I] pointer to a rectangle
 *     text  [I] pointer to the text
420
 *     style [I] drawing style
Alexandre Julliard's avatar
Alexandre Julliard committed
421 422 423
 *
 * RETURNS
 *     No return value.
424 425 426 427
 *
 * NOTES
 *     The style variable can have one of the following values:
 *     (will be written ...)
Alexandre Julliard's avatar
Alexandre Julliard committed
428
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
429

430
void WINAPI DrawStatusTextW (HDC hdc, LPCRECT lprc, LPCWSTR text, UINT style)
Alexandre Julliard's avatar
Alexandre Julliard committed
431
{
432 433
    RECT r = *lprc;
    UINT border = BDR_SUNKENOUTER;
Alexandre Julliard's avatar
Alexandre Julliard committed
434

435
    if (style & SBT_POPOUT)
436
        border = BDR_RAISEDOUTER;
437
    else if (style & SBT_NOBORDERS)
438
        border = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
439

440
    DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
Alexandre Julliard's avatar
Alexandre Julliard committed
441 442 443

    /* now draw text */
    if (text) {
444 445
        int oldbkmode = SetBkMode (hdc, TRANSPARENT);
        UINT align = DT_LEFT;
446 447
        int strCnt = 0;

448
        if (style & SBT_RTLREADING)
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
            FIXME("Unsupported RTL style!\n");
        r.left += 3;
        do {
            if (*text == '\t') {
                if (strCnt) {
                    DrawTextW (hdc, text - strCnt, strCnt, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
                    strCnt = 0;
                }
                if (align==DT_RIGHT) {
                    break;
                }
                align = (align==DT_LEFT ? DT_CENTER : DT_RIGHT);
            } else {
                strCnt++;
            }
        } while(*text++);

        if (strCnt) DrawTextW (hdc, text - strCnt, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
467
	SetBkMode(hdc, oldbkmode);
Alexandre Julliard's avatar
Alexandre Julliard committed
468 469 470
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
471

Alexandre Julliard's avatar
Alexandre Julliard committed
472
/***********************************************************************
473
 * DrawStatusText  [COMCTL32.@]
474
 * DrawStatusTextA [COMCTL32.5]
Alexandre Julliard's avatar
Alexandre Julliard committed
475 476 477 478 479 480 481
 *
 * Draws text with borders, like in a status bar.
 *
 * PARAMS
 *     hdc   [I] handle to the window's display context
 *     lprc  [I] pointer to a rectangle
 *     text  [I] pointer to the text
482
 *     style [I] drawing style
Alexandre Julliard's avatar
Alexandre Julliard committed
483 484 485
 *
 * RETURNS
 *     No return value.
Alexandre Julliard's avatar
Alexandre Julliard committed
486
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
487

488
void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
Alexandre Julliard's avatar
Alexandre Julliard committed
489
{
490 491 492 493 494
    INT len;
    LPWSTR textW = NULL;

    if ( text ) {
	if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
495
	    if ( (textW = Alloc( len * sizeof(WCHAR) )) )
496 497 498 499
		MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
	}
    }
    DrawStatusTextW( hdc, lprc, textW, style );
500
    Free( textW );
Alexandre Julliard's avatar
Alexandre Julliard committed
501 502
}

Alexandre Julliard's avatar
Alexandre Julliard committed
503

Alexandre Julliard's avatar
Alexandre Julliard committed
504
/***********************************************************************
505
 * CreateStatusWindow  [COMCTL32.@]
506
 * CreateStatusWindowA [COMCTL32.6]
507 508
 *
 * Creates a status bar
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510
 *
 * PARAMS
511 512
 *     style  [I] window style
 *     text   [I] pointer to the window text
Alexandre Julliard's avatar
Alexandre Julliard committed
513
 *     parent [I] handle to the parent window
514
 *     wid    [I] control id of the status bar
Alexandre Julliard's avatar
Alexandre Julliard committed
515 516
 *
 * RETURNS
517
 *     Success: handle to the status window
Alexandre Julliard's avatar
Alexandre Julliard committed
518
 *     Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
519
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
520

521
HWND WINAPI
522
CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
Alexandre Julliard's avatar
Alexandre Julliard committed
523
{
524 525
    return CreateWindowA(STATUSCLASSNAMEA, text, style,
			   CW_USEDEFAULT, CW_USEDEFAULT,
526
			   CW_USEDEFAULT, CW_USEDEFAULT,
Frank Richter's avatar
Frank Richter committed
527
			   parent, (HMENU)(DWORD_PTR)wid, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
528 529
}

Alexandre Julliard's avatar
Alexandre Julliard committed
530

Alexandre Julliard's avatar
Alexandre Julliard committed
531
/***********************************************************************
532 533 534
 * CreateStatusWindowW [COMCTL32.@]
 *
 * Creates a status bar control
Alexandre Julliard's avatar
Alexandre Julliard committed
535 536
 *
 * PARAMS
537 538
 *     style  [I] window style
 *     text   [I] pointer to the window text
539 540
 *     parent [I] handle to the parent window
 *     wid    [I] control id of the status bar
Alexandre Julliard's avatar
Alexandre Julliard committed
541 542
 *
 * RETURNS
543
 *     Success: handle to the status window
Alexandre Julliard's avatar
Alexandre Julliard committed
544
 *     Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
545
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
546

547
HWND WINAPI
548
CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
Alexandre Julliard's avatar
Alexandre Julliard committed
549
{
550 551 552
    return CreateWindowW(STATUSCLASSNAMEW, text, style,
			   CW_USEDEFAULT, CW_USEDEFAULT,
			   CW_USEDEFAULT, CW_USEDEFAULT,
Frank Richter's avatar
Frank Richter committed
553
			   parent, (HMENU)(DWORD_PTR)wid, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
554 555
}

Alexandre Julliard's avatar
Alexandre Julliard committed
556

557
/***********************************************************************
558 559 560
 * CreateUpDownControl [COMCTL32.16]
 *
 * Creates an up-down control
561 562
 *
 * PARAMS
563 564 565 566 567
 *     style  [I] window styles
 *     x      [I] horizontal position of the control
 *     y      [I] vertical position of the control
 *     cx     [I] with of the control
 *     cy     [I] height of the control
568
 *     parent [I] handle to the parent window
569 570 571 572 573 574
 *     id     [I] the control's identifier
 *     inst   [I] handle to the application's module instance
 *     buddy  [I] handle to the buddy window, can be NULL
 *     maxVal [I] upper limit of the control
 *     minVal [I] lower limit of the control
 *     curVal [I] current value of the control
Alexandre Julliard's avatar
Alexandre Julliard committed
575 576
 *
 * RETURNS
577
 *     Success: handle to the updown control
Alexandre Julliard's avatar
Alexandre Julliard committed
578
 *     Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
579
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
580

581 582 583 584
HWND WINAPI
CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
		     HWND parent, INT id, HINSTANCE inst,
		     HWND buddy, INT maxVal, INT minVal, INT curVal)
Alexandre Julliard's avatar
Alexandre Julliard committed
585
{
586
    HWND hUD =
587
	CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
Frank Richter's avatar
Frank Richter committed
588
			 parent, (HMENU)(DWORD_PTR)id, inst, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
589
    if (hUD) {
590 591 592
	SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
	SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
	SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
Alexandre Julliard's avatar
Alexandre Julliard committed
593 594 595
    }

    return hUD;
Alexandre Julliard's avatar
Alexandre Julliard committed
596 597 598 599
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
600 601
 * InitCommonControls [COMCTL32.17]
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
602
 * Registers the common controls.
Alexandre Julliard's avatar
Alexandre Julliard committed
603
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
604
 * PARAMS
Alexandre Julliard's avatar
Alexandre Julliard committed
605 606 607 608
 *     No parameters.
 *
 * RETURNS
 *     No return values.
Alexandre Julliard's avatar
Alexandre Julliard committed
609
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
610
 * NOTES
611
 *     This function is just a dummy - all the controls are registered at
612
 *     the DLL initialization time. See InitCommonContolsEx for details.
Alexandre Julliard's avatar
Alexandre Julliard committed
613 614 615
 */

VOID WINAPI
616
InitCommonControls (void)
Alexandre Julliard's avatar
Alexandre Julliard committed
617 618 619 620 621
{
}


/***********************************************************************
622
 * InitCommonControlsEx [COMCTL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
623
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
624
 * Registers the common controls.
Alexandre Julliard's avatar
Alexandre Julliard committed
625
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
626
 * PARAMS
Alexandre Julliard's avatar
Alexandre Julliard committed
627 628 629 630 631
 *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
 *
 * RETURNS
 *     Success: TRUE
 *     Failure: FALSE
Alexandre Julliard's avatar
Alexandre Julliard committed
632 633
 *
 * NOTES
634
 *     Probably all versions of comctl32 initializes the Win95 controls in DllMain
635
 *     during DLL initialization. Starting from comctl32 v5.82 all the controls
636 637 638 639 640 641 642
 *     are initialized there. We follow this behaviour and this function is just
 *     a dummy.
 *
 *     Note: when writing programs under Windows, if you don't call any function
 *     from comctl32 the linker may not link this DLL. If InitCommonControlsEx
 *     was the only comctl32 function you were calling and you remove it you may
 *     have a false impression that InitCommonControlsEx actually did something.
Alexandre Julliard's avatar
Alexandre Julliard committed
643
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
644

645
BOOL WINAPI
646
InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
Alexandre Julliard's avatar
Alexandre Julliard committed
647
{
648 649
    if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
        return FALSE;
650

651
    TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
Alexandre Julliard's avatar
Alexandre Julliard committed
652
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
653
}
Alexandre Julliard's avatar
Alexandre Julliard committed
654 655 656


/***********************************************************************
657 658 659
 * CreateToolbarEx [COMCTL32.@]
 *
 * Creates a toolbar window.
Alexandre Julliard's avatar
Alexandre Julliard committed
660
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
661 662 663 664 665 666 667 668 669 670 671 672 673 674
 * PARAMS
 *     hwnd
 *     style
 *     wID
 *     nBitmaps
 *     hBMInst
 *     wBMID
 *     lpButtons
 *     iNumButtons
 *     dxButton
 *     dyButton
 *     dxBitmap
 *     dyBitmap
 *     uStructSize
Alexandre Julliard's avatar
Alexandre Julliard committed
675
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
676 677 678
 * RETURNS
 *     Success: handle to the tool bar control
 *     Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
679 680
 */

681 682
HWND WINAPI
CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
683
                 HINSTANCE hBMInst, UINT_PTR wBMID, LPCTBBUTTON lpButtons,
684 685
                 INT iNumButtons, INT dxButton, INT dyButton,
                 INT dxBitmap, INT dyBitmap, UINT uStructSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
686
{
687 688 689
    HWND hwndTB;

    hwndTB =
690
        CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
Frank Richter's avatar
Frank Richter committed
691
                        hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
692 693 694
    if(hwndTB) {
	TBADDBITMAP tbab;

695
        SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, uStructSize, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
696

697 698
       /* set bitmap and button size */
       /*If CreateToolbarEx receives 0, windows sets default values*/
699
       if (dxBitmap < 0)
700
           dxBitmap = 16;
701 702 703 704 705
       if (dyBitmap < 0)
           dyBitmap = 16;
       if (dxBitmap == 0 || dyBitmap == 0)
           dxBitmap = dyBitmap = 16;
       SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxBitmap, dyBitmap));
706

707 708 709 710 711 712 713
       if (dxButton < 0)
           dxButton = dxBitmap;
       if (dyButton < 0)
           dyButton = dyBitmap;
       /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
       if (dxButton != 0 && dyButton != 0)
            SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
714

Alexandre Julliard's avatar
Alexandre Julliard committed
715 716

	/* add bitmaps */
717
	if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL)
718
	{
719 720
	    tbab.hInst = hBMInst;
	    tbab.nID   = wBMID;
721

722
            SendMessageW (hwndTB, TB_ADDBITMAP, nBitmaps, (LPARAM)&tbab);
723
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
724
	/* add buttons */
725
	if(iNumButtons > 0)
726
        SendMessageW (hwndTB, TB_ADDBUTTONSW, iNumButtons, (LPARAM)lpButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
727 728
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
729
    return hwndTB;
Alexandre Julliard's avatar
Alexandre Julliard committed
730 731 732 733 734 735
}


/***********************************************************************
 * CreateMappedBitmap [COMCTL32.8]
 *
736 737
 * Loads a bitmap resource using a colour map.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
738
 * PARAMS
739 740 741 742 743
 *     hInstance  [I] Handle to the module containing the bitmap.
 *     idBitmap   [I] The bitmap resource ID.
 *     wFlags     [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
 *     lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
 *     iNumMaps   [I] Number of COLORMAP's pointed to by lpColorMap.
Alexandre Julliard's avatar
Alexandre Julliard committed
744 745
 *
 * RETURNS
746
 *     Success: handle to the new bitmap
Alexandre Julliard's avatar
Alexandre Julliard committed
747
 *     Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
748 749
 */

750
HBITMAP WINAPI
Frank Richter's avatar
Frank Richter committed
751
CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
752
		    LPCOLORMAP lpColorMap, INT iNumMaps)
Alexandre Julliard's avatar
Alexandre Julliard committed
753
{
754 755
    HGLOBAL hglb;
    HRSRC hRsrc;
756 757
    const BITMAPINFOHEADER *lpBitmap;
    LPBITMAPINFOHEADER lpBitmapInfo;
758
    UINT nSize, nColorTableSize, iColor;
759
    RGBQUAD *pColorTable;
760
    INT i, iMaps, nWidth, nHeight;
761 762
    HDC hdcScreen;
    HBITMAP hbm;
Alexandre Julliard's avatar
Alexandre Julliard committed
763
    LPCOLORMAP sysColorMap;
764
    COLORREF cRef;
Alexandre Julliard's avatar
Alexandre Julliard committed
765 766 767 768 769 770 771 772 773
    COLORMAP internalColorMap[4] =
	{{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};

    /* initialize pointer to colortable and default color table */
    if (lpColorMap) {
	iMaps = iNumMaps;
	sysColorMap = lpColorMap;
    }
    else {
774 775 776 777
	internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
	internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
	internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
	internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
Alexandre Julliard's avatar
Alexandre Julliard committed
778
	iMaps = 4;
779
	sysColorMap = internalColorMap;
Alexandre Julliard's avatar
Alexandre Julliard committed
780
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
781

782
    hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
Alexandre Julliard's avatar
Alexandre Julliard committed
783 784
    if (hRsrc == 0)
	return 0;
785
    hglb = LoadResource (hInstance, hRsrc);
Alexandre Julliard's avatar
Alexandre Julliard committed
786 787
    if (hglb == 0)
	return 0;
788
    lpBitmap = LockResource (hglb);
Alexandre Julliard's avatar
Alexandre Julliard committed
789
    if (lpBitmap == NULL)
Alexandre Julliard's avatar
Alexandre Julliard committed
790
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
791

792 793 794 795 796 797
    if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
        nColorTableSize = lpBitmap->biClrUsed;
    else if (lpBitmap->biBitCount <= 8)	
        nColorTableSize = (1 << lpBitmap->biBitCount);
    else
        nColorTableSize = 0;
798 799 800 801
    nSize = lpBitmap->biSize;
    if (nSize == sizeof(BITMAPINFOHEADER) && lpBitmap->biCompression == BI_BITFIELDS)
        nSize += 3 * sizeof(DWORD);
    nSize += nColorTableSize * sizeof(RGBQUAD);
802
    lpBitmapInfo = GlobalAlloc (GMEM_FIXED, nSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
803
    if (lpBitmapInfo == NULL)
Alexandre Julliard's avatar
Alexandre Julliard committed
804
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
805 806
    RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);

807
    pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo) + lpBitmapInfo->biSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
808 809 810

    for (iColor = 0; iColor < nColorTableSize; iColor++) {
	for (i = 0; i < iMaps; i++) {
811 812 813 814
            cRef = RGB(pColorTable[iColor].rgbRed,
                       pColorTable[iColor].rgbGreen,
                       pColorTable[iColor].rgbBlue);
	    if ( cRef  == sysColorMap[i].from) {
Alexandre Julliard's avatar
Alexandre Julliard committed
815 816 817 818 819 820 821
#if 0
		if (wFlags & CBS_MASKED) {
		    if (sysColorMap[i].to != COLOR_BTNTEXT)
			pColorTable[iColor] = RGB(255, 255, 255);
		}
		else
#endif
822 823 824
                    pColorTable[iColor].rgbBlue  = GetBValue(sysColorMap[i].to);
                    pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
                    pColorTable[iColor].rgbRed   = GetRValue(sysColorMap[i].to);
Alexandre Julliard's avatar
Alexandre Julliard committed
825 826 827 828
		break;
	    }
	}
    }
829 830
    nWidth  = lpBitmapInfo->biWidth;
    nHeight = lpBitmapInfo->biHeight;
831
    hdcScreen = GetDC (NULL);
832
    hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
Alexandre Julliard's avatar
Alexandre Julliard committed
833
    if (hbm) {
834 835
	HDC hdcDst = CreateCompatibleDC (hdcScreen);
	HBITMAP hbmOld = SelectObject (hdcDst, hbm);
836
	const BYTE *lpBits = (const BYTE *)lpBitmap + nSize;
837
	StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
Alexandre Julliard's avatar
Alexandre Julliard committed
838 839
		         lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
		         SRCCOPY);
840 841
	SelectObject (hdcDst, hbmOld);
	DeleteDC (hdcDst);
Alexandre Julliard's avatar
Alexandre Julliard committed
842
    }
843
    ReleaseDC (NULL, hdcScreen);
844
    GlobalFree (lpBitmapInfo);
845
    FreeResource (hglb);
Alexandre Julliard's avatar
Alexandre Julliard committed
846 847

    return hbm;
Alexandre Julliard's avatar
Alexandre Julliard committed
848
}
Alexandre Julliard's avatar
Alexandre Julliard committed
849 850 851


/***********************************************************************
852 853 854
 * CreateToolbar [COMCTL32.7]
 *
 * Creates a toolbar control.
Alexandre Julliard's avatar
Alexandre Julliard committed
855
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
856 857 858 859 860 861 862 863 864
 * PARAMS
 *     hwnd
 *     style
 *     wID
 *     nBitmaps
 *     hBMInst
 *     wBMID
 *     lpButtons
 *     iNumButtons
Alexandre Julliard's avatar
Alexandre Julliard committed
865
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
866 867 868
 * RETURNS
 *     Success: handle to the tool bar control
 *     Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
869
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
870
 * NOTES
871
 *     Do not use this function anymore. Use CreateToolbarEx instead.
Alexandre Julliard's avatar
Alexandre Julliard committed
872 873
 */

874 875 876
HWND WINAPI
CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
	       HINSTANCE hBMInst, UINT wBMID,
877
	       LPCTBBUTTON lpButtons,INT iNumButtons)
Alexandre Julliard's avatar
Alexandre Julliard committed
878 879
{
    return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
880 881
			    hBMInst, wBMID, lpButtons,
			    iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
Alexandre Julliard's avatar
Alexandre Julliard committed
882 883
}

Alexandre Julliard's avatar
Alexandre Julliard committed
884 885

/***********************************************************************
886
 * DllGetVersion [COMCTL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
887
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
888
 * Retrieves version information of the 'COMCTL32.DLL'
Alexandre Julliard's avatar
Alexandre Julliard committed
889 890
 *
 * PARAMS
Alexandre Julliard's avatar
Alexandre Julliard committed
891
 *     pdvi [O] pointer to version information structure.
Alexandre Julliard's avatar
Alexandre Julliard committed
892
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
893
 * RETURNS
Alexandre Julliard's avatar
Alexandre Julliard committed
894 895
 *     Success: S_OK
 *     Failure: E_INVALIDARG
Alexandre Julliard's avatar
Alexandre Julliard committed
896 897 898
 *
 * NOTES
 *     Returns version of a comctl32.dll from IE4.01 SP1.
Alexandre Julliard's avatar
Alexandre Julliard committed
899 900
 */

901
HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
Alexandre Julliard's avatar
Alexandre Julliard committed
902
{
Alexandre Julliard's avatar
Alexandre Julliard committed
903
    if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
904
        WARN("wrong DLLVERSIONINFO size from app\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
905
	return E_INVALIDARG;
Alexandre Julliard's avatar
Alexandre Julliard committed
906 907
    }

Gerard Patel's avatar
Gerard Patel committed
908 909
    pdvi->dwMajorVersion = COMCTL32_VERSION;
    pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
910 911
    pdvi->dwBuildNumber = 2919;
    pdvi->dwPlatformID = 6304;
Alexandre Julliard's avatar
Alexandre Julliard committed
912

913
    TRACE("%u.%u.%u.%u\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
914 915 916 917
	   pdvi->dwMajorVersion, pdvi->dwMinorVersion,
	   pdvi->dwBuildNumber, pdvi->dwPlatformID);

    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
918
}
919

920
/***********************************************************************
921
 *		DllInstall (COMCTL32.@)
922 923 924 925 926 927
 *
 * Installs the ComCtl32 DLL.
 *
 * RETURNS
 *     Success: S_OK
 *     Failure: A HRESULT error
928
 */
929
HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
930
{
931 932
    TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
    return S_OK;
933
}
934 935

/***********************************************************************
936
 * _TrackMouseEvent [COMCTL32.@]
937 938 939
 *
 * Requests notification of mouse events
 *
940 941 942 943 944 945 946 947
 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
 * to the hwnd specified in the ptme structure.  After the event message
 * is posted to the hwnd, the entry in the queue is removed.
 *
 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
 * immediately and the TME_LEAVE flag being ignored.
 *
948 949 950 951 952 953 954
 * PARAMS
 *     ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
 *
 * RETURNS
 *     Success: non-zero
 *     Failure: zero
 *
955 956
 * IMPLEMENTATION moved to USER32.TrackMouseEvent
 *
957 958 959 960 961
 */

BOOL WINAPI
_TrackMouseEvent (TRACKMOUSEEVENT *ptme)
{
962
    return TrackMouseEvent (ptme);
963
}
964 965

/*************************************************************************
966
 * GetMUILanguage [COMCTL32.@]
967
 *
968
 * Returns the user interface language in use by the current process.
969
 *
970 971
 * RETURNS
 *      Language ID in use by the current process.
972 973 974 975 976 977 978 979
 */
LANGID WINAPI GetMUILanguage (VOID)
{
    return COMCTL32_uiLang;
}


/*************************************************************************
980
 * InitMUILanguage [COMCTL32.@]
981
 *
982
 * Sets the user interface language to be used by the current process.
983
 *
984 985
 * RETURNS
 *      Nothing.
986 987 988 989 990
 */
VOID WINAPI InitMUILanguage (LANGID uiLang)
{
   COMCTL32_uiLang = uiLang;
}
991 992


993
/***********************************************************************
994
 * SetWindowSubclass [COMCTL32.410]
995 996 997 998 999 1000
 *
 * Starts a window subclass
 *
 * PARAMS
 *     hWnd [in] handle to window subclass.
 *     pfnSubclass [in] Pointer to new window procedure.
1001
 *     uIDSubclass [in] Unique identifier of subclass together with pfnSubclass.
1002 1003 1004 1005 1006 1007 1008 1009
 *     dwRef [in] Reference data to pass to window procedure.
 *
 * RETURNS
 *     Success: non-zero
 *     Failure: zero
 *
 * BUGS
 *     If an application manually subclasses a window after subclassing it with
1010
 *     this API and then with this API again, then none of the previous 
1011
 *     subclasses get called or the original window procedure.
1012
 */
1013

1014 1015 1016 1017
BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
                        UINT_PTR uIDSubclass, DWORD_PTR dwRef)
{
   LPSUBCLASS_INFO stack;
1018
   LPSUBCLASSPROCS proc;
1019

1020
   TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1021 1022 1023 1024 1025 1026 1027

   /* Since the window procedure that we set here has two additional arguments,
    * we can't simply set it as the new window procedure of the window. So we
    * set our own window procedure and then calculate the other two arguments
    * from there. */

   /* See if we have been called for this window */
1028
   stack = GetPropW (hWnd, COMCTL32_wSubclass);
1029 1030
   if (!stack) {
      /* allocate stack */
1031
      stack = Alloc (sizeof(SUBCLASS_INFO));
1032
      if (!stack) {
1033
         ERR ("Failed to allocate our Subclassing stack\n");
1034 1035
         return FALSE;
      }
1036
      SetPropW (hWnd, COMCTL32_wSubclass, stack);
1037 1038 1039

      /* set window procedure to our own and save the current one */
      if (IsWindowUnicode (hWnd))
1040 1041
         stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
                                                   (DWORD_PTR)COMCTL32_SubclassProc);
1042
      else
1043 1044
         stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
                                                   (DWORD_PTR)COMCTL32_SubclassProc);
1045
   }
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
   else {
      /* Check to see if we have called this function with the same uIDSubClass
       * and pfnSubclass */
      proc = stack->SubclassProcs;
      while (proc) {
         if ((proc->id == uIDSubclass) &&
            (proc->subproc == pfnSubclass)) {
            proc->ref = dwRef;
            return TRUE;
         }
         proc = proc->next;
1057
      }
1058 1059
   }
   
1060
   proc = Alloc(sizeof(SUBCLASSPROCS));
1061 1062 1063
   if (!proc) {
      ERR ("Failed to allocate subclass entry in stack\n");
      if (IsWindowUnicode (hWnd))
1064
         SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1065
      else
1066
         SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1067
      Free (stack);
1068
      RemovePropW( hWnd, COMCTL32_wSubclass );
1069 1070 1071
      return FALSE;
   }
   
1072 1073 1074 1075 1076 1077
   proc->subproc = pfnSubclass;
   proc->ref = dwRef;
   proc->id = uIDSubclass;
   proc->next = stack->SubclassProcs;
   stack->SubclassProcs = proc;

1078 1079 1080 1081 1082
   return TRUE;
}


/***********************************************************************
1083
 * GetWindowSubclass [COMCTL32.411]
1084 1085 1086 1087
 *
 * Gets the Reference data from a subclass.
 *
 * PARAMS
1088
 *     hWnd [in] Handle to the window which we are subclassing
1089
 *     pfnSubclass [in] Pointer to the subclass procedure
1090
 *     uID [in] Unique identifier of the subclassing procedure
1091 1092 1093
 *     pdwRef [out] Pointer to the reference data
 *
 * RETURNS
Jon Griffiths's avatar
Jon Griffiths committed
1094 1095
 *     Success: Non-zero
 *     Failure: 0
1096
 */
1097

1098 1099 1100
BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
                              UINT_PTR uID, DWORD_PTR *pdwRef)
{
1101 1102
   const SUBCLASS_INFO *stack;
   const SUBCLASSPROCS *proc;
1103

1104
   TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1105 1106

   /* See if we have been called for this window */
1107
   stack = GetPropW (hWnd, COMCTL32_wSubclass);
1108 1109 1110
   if (!stack)
      return FALSE;

1111 1112 1113 1114 1115
   proc = stack->SubclassProcs;
   while (proc) {
      if ((proc->id == uID) &&
         (proc->subproc == pfnSubclass)) {
         *pdwRef = proc->ref;
1116 1117
         return TRUE;
      }
1118 1119
      proc = proc->next;
   }
1120 1121 1122 1123 1124 1125

   return FALSE;
}


/***********************************************************************
1126
 * RemoveWindowSubclass [COMCTL32.412]
1127 1128 1129 1130
 *
 * Removes a window subclass.
 *
 * PARAMS
1131
 *     hWnd [in] Handle to the window which we are subclassing
1132 1133 1134 1135 1136 1137 1138
 *     pfnSubclass [in] Pointer to the subclass procedure
 *     uID [in] Unique identifier of this subclass
 *
 * RETURNS
 *     Success: non-zero
 *     Failure: zero
 */
1139

1140 1141 1142
BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
{
   LPSUBCLASS_INFO stack;
1143 1144 1145
   LPSUBCLASSPROCS prevproc = NULL;
   LPSUBCLASSPROCS proc;
   BOOL ret = FALSE;
1146

1147
   TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1148 1149

   /* Find the Subclass to remove */
1150
   stack = GetPropW (hWnd, COMCTL32_wSubclass);
1151 1152 1153
   if (!stack)
      return FALSE;

1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
   proc = stack->SubclassProcs;
   while (proc) {
      if ((proc->id == uID) &&
         (proc->subproc == pfnSubclass)) {
         
         if (!prevproc)
            stack->SubclassProcs = proc->next;
         else
            prevproc->next = proc->next;
          
         if (stack->stackpos == proc)
            stack->stackpos = stack->stackpos->next;
            
1167
         Free (proc);
1168 1169 1170 1171 1172 1173 1174 1175
         ret = TRUE;
         break;
      }
      prevproc = proc;
      proc = proc->next;
   }
   
   if (!stack->SubclassProcs && !stack->running) {
1176
      TRACE("Last Subclass removed, cleaning up\n");
1177
      /* clean up our heap and reset the original window procedure */
1178
      if (IsWindowUnicode (hWnd))
1179
         SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1180
      else
1181
         SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1182
      Free (stack);
1183
      RemovePropW( hWnd, COMCTL32_wSubclass );
1184
   }
1185 1186 1187
   
   return ret;
}
1188

1189 1190 1191 1192 1193 1194
/***********************************************************************
 * COMCTL32_SubclassProc (internal)
 *
 * Window procedure for all subclassed windows. 
 * Saves the current subclassing stack position to support nested messages
 */
1195
static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1196 1197 1198 1199 1200
{
   LPSUBCLASS_INFO stack;
   LPSUBCLASSPROCS proc;
   LRESULT ret;
    
1201
   TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1202

1203
   stack = GetPropW (hWnd, COMCTL32_wSubclass);
1204 1205 1206 1207 1208 1209 1210 1211
   if (!stack) {
      ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
      return 0;
   }
    
   /* Save our old stackpos to properly handle nested messages */
   proc = stack->stackpos;
   stack->stackpos = stack->SubclassProcs;
1212
   stack->running++;
1213
   ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1214
   stack->running--;
1215 1216
   stack->stackpos = proc;
    
1217
   if (!stack->SubclassProcs && !stack->running) {
1218
      TRACE("Last Subclass removed, cleaning up\n");
1219
      /* clean up our heap and reset the original window procedure */
1220
      if (IsWindowUnicode (hWnd))
1221
         SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1222
      else
1223
         SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1224
      Free (stack);
1225
      RemovePropW( hWnd, COMCTL32_wSubclass );
1226 1227
   }
   return ret;
1228 1229 1230
}

/***********************************************************************
1231
 * DefSubclassProc [COMCTL32.413]
1232
 *
1233
 * Calls the next window procedure (i.e. the one before this subclass)
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
 *
 * PARAMS
 *     hWnd [in] The window that we're subclassing
 *     uMsg [in] Message
 *     wParam [in] WPARAM
 *     lParam [in] LPARAM
 *
 * RETURNS
 *     Success: non-zero
 *     Failure: zero
 */
1245

1246 1247 1248 1249
LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   LPSUBCLASS_INFO stack;
   LRESULT ret;
1250
   
1251
   TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1252 1253

   /* retrieve our little stack from the Properties */
1254
   stack = GetPropW (hWnd, COMCTL32_wSubclass);
1255
   if (!stack) {
1256
      ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1257 1258 1259
      return 0;
   }

1260 1261
   /* If we are at the end of stack then we have to call the original
    * window procedure */
1262
   if (!stack->stackpos) {
1263
      if (IsWindowUnicode (hWnd))
1264
         ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1265
      else
1266 1267
         ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
   } else {
1268
      const SUBCLASSPROCS *proc = stack->stackpos;
1269
      stack->stackpos = stack->stackpos->next; 
1270
      /* call the Subclass procedure from the stack */
1271 1272
      ret = proc->subproc (hWnd, uMsg, wParam, lParam,
            proc->id, proc->ref);
1273 1274 1275 1276 1277 1278
   }

   return ret;
}


1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
/***********************************************************************
 * COMCTL32_CreateToolTip [NOT AN API]
 *
 * Creates a tooltip for the control specified in hwnd and does all
 * necessary setup and notifications.
 *
 * PARAMS
 *     hwndOwner [I] Handle to the window that will own the tool tip.
 *
 * RETURNS
 *     Success: Handle of tool tip window.
 *     Failure: NULL
 */
1292

1293 1294 1295 1296 1297
HWND
COMCTL32_CreateToolTip(HWND hwndOwner)
{
    HWND hwndToolTip;

1298
    hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1299 1300 1301 1302 1303 1304 1305 1306
				  CW_USEDEFAULT, CW_USEDEFAULT,
				  CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
				  0, 0, 0);

    /* Send NM_TOOLTIPSCREATED notification */
    if (hwndToolTip)
    {
	NMTOOLTIPSCREATED nmttc;
1307 1308 1309
        /* true owner can be different if hwndOwner is a child window */
        HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
        nmttc.hdr.hwndFrom = hwndTrueOwner;
1310
        nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1311 1312 1313
	nmttc.hdr.code = NM_TOOLTIPSCREATED;
	nmttc.hwndToolTips = hwndToolTip;

1314 1315
        SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
                     GetWindowLongPtrW(hwndTrueOwner, GWLP_ID), (LPARAM)&nmttc);
1316 1317 1318 1319
    }

    return hwndToolTip;
}
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333


/***********************************************************************
 * COMCTL32_RefreshSysColors [NOT AN API]
 *
 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
 * refresh the color values in the color structure
 *
 * PARAMS
 *     none
 *
 * RETURNS
 *     none
 */
1334

1335 1336 1337 1338 1339 1340 1341 1342 1343
VOID
COMCTL32_RefreshSysColors(void)
{
    comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
    comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
    comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
    comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
    comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
    comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1344
    comctl32_color.clrHotTrackingColor = GetSysColor (COLOR_HOTLIGHT);
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
    comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
    comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
    comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
    comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
    comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
    comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
    comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
    comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
    comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
    comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
}
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408

/***********************************************************************
 * COMCTL32_DrawInsertMark [NOT AN API]
 *
 * Draws an insertion mark (which looks similar to an 'I').
 *
 * PARAMS
 *     hDC           [I] Device context to draw onto.
 *     lpRect        [I] Co-ordinates of insertion mark.
 *     clrInsertMark [I] Colour of the insertion mark.
 *     bHorizontal   [I] True if insert mark should be drawn horizontally,
 *                       vertical otherwise.
 *
 * RETURNS
 *     none
 *
 * NOTES
 *     Draws up to but not including the bottom co-ordinate when drawing
 *     vertically or the right co-ordinate when horizontal.
 */
void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
{
    HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
    HPEN hOldPen;
    static const DWORD adwPolyPoints[] = {4,4,4};
    LONG lCentre = (bHorizontal ? 
        lpRect->top + (lpRect->bottom - lpRect->top)/2 : 
        lpRect->left + (lpRect->right - lpRect->left)/2);
    LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
    LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
    const POINT aptInsertMark[] =
    {
        /* top (V) or left (H) arrow */
        {lCentre    , l1 + 2},
        {lCentre - 2, l1    },
        {lCentre + 3, l1    },
        {lCentre + 1, l1 + 2},
        /* middle line */
        {lCentre    , l2 - 2},
        {lCentre    , l1 - 1},
        {lCentre + 1, l1 - 1},
        {lCentre + 1, l2 - 2},
        /* bottom (V) or right (H) arrow */
        {lCentre    , l2 - 3},
        {lCentre - 2, l2 - 1},
        {lCentre + 3, l2 - 1},
        {lCentre + 1, l2 - 3},
    };
    hOldPen = SelectObject(hDC, hPen);
    PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
    SelectObject(hDC, hOldPen);
    DeleteObject(hPen);
}
1409

1410 1411 1412
/***********************************************************************
 * COMCTL32_EnsureBitmapSize [internal]
 *
1413 1414
 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
 * the height is at least cyMinHeight. If the bitmap already has these
1415 1416 1417 1418
 * dimensions nothing changes.
 *
 * PARAMS
 *     hBitmap       [I/O] Bitmap to modify. The handle may change
1419
 *     cxMinWidth    [I]   If the width of the bitmap is smaller, then it will
1420
 *                         be enlarged to this value
1421
 *     cyMinHeight   [I]   If the height of the bitmap is smaller, then it will
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
 *                         be enlarged to this value
 *     cyBackground  [I]   The color with which the new area will be filled
 *
 * RETURNS
 *     none
 */
void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
{
    int cxNew, cyNew;
    BITMAP bmp;
    HBITMAP hNewBitmap;
    HBITMAP hNewDCBitmap, hOldDCBitmap;
    HBRUSH hNewDCBrush;
    HDC hdcNew, hdcOld;

    if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
        return;
    cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
    cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
    if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
        return;

    hdcNew = CreateCompatibleDC(NULL);
    hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
    hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
    hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));

    hdcOld = CreateCompatibleDC(NULL);
    hOldDCBitmap = SelectObject(hdcOld, *pBitmap);

    BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
    if (bmp.bmWidth < cxMinWidth)
        PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
    if (bmp.bmHeight < cyMinHeight)
        PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
    if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
        PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);

    SelectObject(hdcNew, hNewDCBitmap);
    DeleteObject(SelectObject(hdcNew, hNewDCBrush));
    DeleteDC(hdcNew);
    SelectObject(hdcOld, hOldDCBitmap);
    DeleteDC(hdcOld);

    DeleteObject(*pBitmap);    
    *pBitmap = hNewBitmap;
    return;
}

1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
void COMCTL32_GetFontMetrics(HFONT hFont, TEXTMETRICW *ptm)
{
    HDC hdc = GetDC(NULL);
    HFONT hOldFont;

    hOldFont = SelectObject(hdc, hFont);
    GetTextMetricsW(hdc, ptm);
    SelectObject(hdc, hOldFont);
    ReleaseDC(NULL, hdc);
}

1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
#ifndef OCM__BASE      /* avoid including olectl.h */
#define OCM__BASE (WM_USER+0x1c00)
#endif

/***********************************************************************
 * COMCTL32_IsReflectedMessage [internal]
 *
 * Some parents reflect notify messages - for some messages sent by the child,
 * they send it back with the message code increased by OCM__BASE (0x2000).
 * This allows better subclassing of controls. We don't need to handle such
 * messages but we don't want to print ERRs for them, so this helper function
 * identifies them.
 *
 * Some of the codes are in the CCM_FIRST..CCM_LAST range, but there is no
1496
 * collision with defined CCM_ codes.
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525
 */
BOOL COMCTL32_IsReflectedMessage(UINT uMsg)
{
    switch (uMsg)
    {
        case OCM__BASE + WM_COMMAND:
        case OCM__BASE + WM_CTLCOLORBTN:
        case OCM__BASE + WM_CTLCOLOREDIT:
        case OCM__BASE + WM_CTLCOLORDLG:
        case OCM__BASE + WM_CTLCOLORLISTBOX:
        case OCM__BASE + WM_CTLCOLORMSGBOX:
        case OCM__BASE + WM_CTLCOLORSCROLLBAR:
        case OCM__BASE + WM_CTLCOLORSTATIC:
        case OCM__BASE + WM_DRAWITEM:
        case OCM__BASE + WM_MEASUREITEM:
        case OCM__BASE + WM_DELETEITEM:
        case OCM__BASE + WM_VKEYTOITEM:
        case OCM__BASE + WM_CHARTOITEM:
        case OCM__BASE + WM_COMPAREITEM:
        case OCM__BASE + WM_HSCROLL:
        case OCM__BASE + WM_VSCROLL:
        case OCM__BASE + WM_PARENTNOTIFY:
        case OCM__BASE + WM_NOTIFY:
            return TRUE;
        default:
            return FALSE;
    }
}

1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
/***********************************************************************
 * MirrorIcon [COMCTL32.414]
 *
 * Mirrors an icon so that it will appear correctly on a mirrored DC.
 *
 * PARAMS
 *     phicon1 [I/O] Icon.
 *     phicon2 [I/O] Icon.
 *
 * RETURNS
 *     Success: TRUE.
 *     Failure: FALSE.
 */
BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
{
    FIXME("(%p, %p): stub\n", phicon1, phicon2);
    return FALSE;
}

1545
static inline BOOL IsDelimiter(WCHAR c)
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
{
    switch(c)
    {
	case '/':
	case '\\':
	case '.':
	case ' ':
	    return TRUE;
    }
    return FALSE;
}

1558
static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588
{
    if (code == WB_ISDELIMITER)
        return IsDelimiter(lpch[ichCurrent]);
    else
    {
        int dir = (code == WB_LEFT) ? -1 : 1;
        for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
            if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
    }
    return ichCurrent;
}

/***********************************************************************
 * SetPathWordBreakProc [COMCTL32.384]
 *
 * Sets the word break procedure for an edit control to one that understands
 * paths so that the user can jump over directories.
 *
 * PARAMS
 *     hwnd [I] Handle to edit control.
 *     bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
 *
 * RETURNS
 *     Result from EM_SETWORDBREAKPROC message.
 */
LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
{
    return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
        (LPARAM)(bSet ? PathWordBreakProc : NULL));
}
1589 1590 1591 1592 1593 1594

/***********************************************************************
 * DrawShadowText [COMCTL32.@]
 *
 * Draw text with shadow.
 */
1595
int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1596 1597
                          COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
{
1598
    FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1599
                                                                  crText, crShadow, ixOffset, iyOffset);
1600
    return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);
1601
}
1602 1603 1604 1605 1606 1607 1608

/***********************************************************************
 * TaskDialogIndirect [COMCTL32.@]
 */
HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton,
                                  int *pnRadioButton, BOOL *pfVerificationFlagChecked)
{
1609 1610
    UINT uType = 0;
    INT  ret;
1611 1612
    FIXME("%p, %p, %p, %p\n", pTaskConfig, pnButton, pnRadioButton, pfVerificationFlagChecked);

1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
    if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
        pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON &&
        pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
        uType |= MB_YESNOCANCEL;
    else
    if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
        pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON)
        uType |= MB_YESNO;
    else
    if (pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON &&
        pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
        uType |= MB_RETRYCANCEL;
    else
    if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON &&
        pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
        uType |= MB_OKCANCEL;
    else
    if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
        uType |= MB_OK;
    ret = MessageBoxW(pTaskConfig->hwndParent, pTaskConfig->pszMainInstruction,
                      pTaskConfig->pszWindowTitle, uType);
    FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig->dwCommonButtons, uType, ret);

    if (pnButton) *pnButton = ret;
1637 1638 1639 1640
    if (pnRadioButton) *pnRadioButton = pTaskConfig->nDefaultButton;
    if (pfVerificationFlagChecked) *pfVerificationFlagChecked = TRUE;
    return S_OK;
}
1641 1642 1643 1644

/***********************************************************************
 * LoadIconWithScaleDown [COMCTL32.@]
 */
1645
HRESULT WINAPI LoadIconWithScaleDown(HINSTANCE hinst, const WCHAR *name, int cx, int cy, HICON *icon)
1646
{
1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659
    TRACE("(%p, %s, %d, %d, %p)\n", hinst, debugstr_w(name), cx, cy, icon);

    *icon = NULL;

    if (!name)
        return E_INVALIDARG;

    *icon = LoadImageW(hinst, name, IMAGE_ICON, cx, cy,
                       (hinst || IS_INTRESOURCE(name)) ? 0 : LR_LOADFROMFILE);
    if (!*icon)
        return HRESULT_FROM_WIN32(GetLastError());

    return S_OK;
1660
}
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688

/***********************************************************************
 * LoadIconMetric [COMCTL32.@]
 */
HRESULT WINAPI LoadIconMetric(HINSTANCE hinst, const WCHAR *name, int size, HICON *icon)
{
    int cx, cy;

    TRACE("(%p, %s, %d, %p)\n", hinst, debugstr_w(name), size, icon);

    if (size == LIM_SMALL)
    {
        cx = GetSystemMetrics(SM_CXSMICON);
        cy = GetSystemMetrics(SM_CYSMICON);
    }
    else if (size == LIM_LARGE)
    {
        cx = GetSystemMetrics(SM_CXICON);
        cy = GetSystemMetrics(SM_CYICON);
    }
    else
    {
        *icon = NULL;
        return E_INVALIDARG;
    }

    return LoadIconWithScaleDown(hinst, name, cx, cy, icon);
}