hotkey.c 14.2 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 * Hotkey control
 *
4
 * Copyright 1998, 1999 Eric Kohl
5
 * Copyright 2002 Gyorgy 'Nog' Jeney
6
 * Copyright 2004 Robert Shearman
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
 *
Robert Shearman's avatar
Robert Shearman committed
22 23 24 25 26 27 28
 * This code was audited for completeness against the documented features
 * of Comctl32.dll version 6.0 on Sep. 21, 2004, by Robert Shearman.
 * 
 * Unless otherwise noted, we believe this code to be complete, as per
 * the specification mentioned above.
 * If you discover missing features or bugs please note them below.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
29 30
 */

31
#include <stdarg.h>
32
#include <string.h>
33
#include "windef.h"
34
#include "winbase.h"
35 36 37
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
38
#include "commctrl.h"
39
#include "comctl32.h"
40
#include "wine/debug.h"
41
#include "wine/heap.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
42

43
WINE_DEFAULT_DEBUG_CHANNEL(hotkey);
44

45 46
typedef struct tagHOTKEY_INFO
{
47
    HWND  hwndSelf;
48
    HWND  hwndNotify;
49 50 51
    HFONT hFont;
    BOOL  bFocus;
    INT   nHeight;
52 53 54 55 56 57
    WORD  HotKey;
    WORD  InvComb;
    WORD  InvMod;
    BYTE  CurrMod;
    INT   CaretPos;
    DWORD ScanCode;
58
    WCHAR strNone[15]; /* hope it's long enough ... */
59
} HOTKEY_INFO;
Alexandre Julliard's avatar
Alexandre Julliard committed
60

61
static const WCHAR HOTKEY_plussep[] = { ' ', '+', ' ' };
62
static LRESULT HOTKEY_SetFont (HOTKEY_INFO *infoPtr, HFONT hFont, BOOL redraw);
Alexandre Julliard's avatar
Alexandre Julliard committed
63

64
#define IsOnlySet(flags) (infoPtr->CurrMod == (flags))
Alexandre Julliard's avatar
Alexandre Julliard committed
65

66
static BOOL
67
HOTKEY_IsCombInv(const HOTKEY_INFO *infoPtr)
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
{
    TRACE("(infoPtr=%p)\n", infoPtr);
    if((infoPtr->InvComb & HKCOMB_NONE) && !infoPtr->CurrMod)
	return TRUE;
    if((infoPtr->InvComb & HKCOMB_S) && IsOnlySet(HOTKEYF_SHIFT))
	return TRUE;
    if((infoPtr->InvComb & HKCOMB_C) && IsOnlySet(HOTKEYF_CONTROL))
	return TRUE;
    if((infoPtr->InvComb & HKCOMB_A) && IsOnlySet(HOTKEYF_ALT))
	return TRUE;
    if((infoPtr->InvComb & HKCOMB_SC) && 
       IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_CONTROL))
	return TRUE;
    if((infoPtr->InvComb & HKCOMB_SA) && IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_ALT))
	return TRUE;
    if((infoPtr->InvComb & HKCOMB_CA) && 
       IsOnlySet(HOTKEYF_CONTROL | HOTKEYF_ALT))
	return TRUE;
    if((infoPtr->InvComb & HKCOMB_SCA) && 
       IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_CONTROL | HOTKEYF_ALT))
	return TRUE;

    TRACE("() Modifiers are valid\n");
    return FALSE;
}
#undef IsOnlySet
Alexandre Julliard's avatar
Alexandre Julliard committed
94

95
static void
96
HOTKEY_DrawHotKey(HOTKEY_INFO *infoPtr, HDC hdc, LPCWSTR KeyName, WORD NameLen)
97 98
{
    SIZE TextSize;
99 100 101
    INT nXStart, nYStart;
    COLORREF clrOldText, clrOldBk;
    HFONT hFontOld;
102

103 104 105 106 107
    /* Make a gap from the frame */
    nXStart = GetSystemMetrics(SM_CXBORDER);
    nYStart = GetSystemMetrics(SM_CYBORDER);

    hFontOld = SelectObject(hdc, infoPtr->hFont);
108 109 110 111 112 113 114 115 116 117
    if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
    {
        clrOldText = SetTextColor(hdc, comctl32_color.clrGrayText);
        clrOldBk = SetBkColor(hdc, comctl32_color.clrBtnFace);
    }
    else
    {
        clrOldText = SetTextColor(hdc, comctl32_color.clrWindowText);
        clrOldBk = SetBkColor(hdc, comctl32_color.clrWindow);
    }
118 119 120 121 122 123 124 125 126 127 128 129 130

    TextOutW(hdc, nXStart, nYStart, KeyName, NameLen);

    /* Get the text width for the caret */
    GetTextExtentPoint32W(hdc, KeyName, NameLen, &TextSize);
    infoPtr->CaretPos = nXStart + TextSize.cx;

    SetBkColor(hdc, clrOldBk);
    SetTextColor(hdc, clrOldText);
    SelectObject(hdc, hFontOld);

    /* position the caret */
    SetCaretPos(infoPtr->CaretPos, nYStart);
131
}
Alexandre Julliard's avatar
Alexandre Julliard committed
132

133 134 135 136
/* Draw the names of the keys in the control */
static void 
HOTKEY_Refresh(HOTKEY_INFO *infoPtr, HDC hdc)
{
137
    WCHAR KeyName[64];
138 139 140
    WORD NameLen = 0;
    BYTE Modifier;

141
    TRACE("(infoPtr=%p hdc=%p)\n", infoPtr, hdc);
142 143

    if(!infoPtr->CurrMod && !infoPtr->HotKey) {
144
	HOTKEY_DrawHotKey (infoPtr, hdc, infoPtr->strNone, lstrlenW(infoPtr->strNone));
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
	return;
    }
	
    if(infoPtr->HotKey)
	Modifier = HIBYTE(infoPtr->HotKey);
    else if(HOTKEY_IsCombInv(infoPtr)) 
	Modifier = infoPtr->InvMod;
    else
	Modifier = infoPtr->CurrMod;

    if(Modifier & HOTKEYF_CONTROL) {
	GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_CONTROL, 0)),
	                          KeyName, 64);
        NameLen = lstrlenW(KeyName);
	memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep));
	NameLen += 3;
    }
    if(Modifier & HOTKEYF_SHIFT) {
	GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_SHIFT, 0)),
	                           &KeyName[NameLen], 64 - NameLen);
	NameLen = lstrlenW(KeyName);
	memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep));
	NameLen += 3;
    }
    if(Modifier & HOTKEYF_ALT) {
	GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_MENU, 0)),
	                           &KeyName[NameLen], 64 - NameLen);
	NameLen = lstrlenW(KeyName);
	memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep));
	NameLen += 3;
    }

    if(infoPtr->HotKey) {
	GetKeyNameTextW(infoPtr->ScanCode, &KeyName[NameLen], 64 - NameLen);
	NameLen = lstrlenW(KeyName);
    }
    else
	KeyName[NameLen] = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
183

184
    HOTKEY_DrawHotKey (infoPtr, hdc, KeyName, NameLen);
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
}

static void
HOTKEY_Paint(HOTKEY_INFO *infoPtr, HDC hdc)
{
    if (hdc)
	HOTKEY_Refresh(infoPtr, hdc);
    else {
	PAINTSTRUCT ps;
	hdc = BeginPaint (infoPtr->hwndSelf, &ps);
	HOTKEY_Refresh (infoPtr, hdc);
	EndPaint (infoPtr->hwndSelf, &ps);
    }
}

static LRESULT
201
HOTKEY_GetHotKey(const HOTKEY_INFO *infoPtr)
202 203 204 205 206 207 208
{
    TRACE("(infoPtr=%p) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr, 
          HIBYTE(infoPtr->HotKey), LOBYTE(infoPtr->HotKey));
    return (LRESULT)infoPtr->HotKey;
}

static void
209
HOTKEY_SetHotKey(HOTKEY_INFO *infoPtr, WORD hotKey)
210
{
211
    infoPtr->HotKey = hotKey;
212 213
    infoPtr->ScanCode = 
        MAKELPARAM(0, MapVirtualKeyW(LOBYTE(infoPtr->HotKey), 0));
214 215
    TRACE("(infoPtr=%p hotKey=%x) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr,
          hotKey, HIBYTE(infoPtr->HotKey), LOBYTE(infoPtr->HotKey));
216 217 218 219
    InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
}

static void 
220
HOTKEY_SetRules(HOTKEY_INFO *infoPtr, WORD invComb, WORD invMod)
221
{
222 223
    infoPtr->InvComb = invComb;
    infoPtr->InvMod = invMod;
224 225 226 227
    TRACE("(infoPtr=%p) Invalid Modifers: 0x%x, If Invalid: 0x%x\n", infoPtr,
          infoPtr->InvComb, infoPtr->InvMod);
}

Alexandre Julliard's avatar
Alexandre Julliard committed
228 229

static LRESULT
230
HOTKEY_Create (HOTKEY_INFO *infoPtr, const CREATESTRUCTW *lpcs)
Alexandre Julliard's avatar
Alexandre Julliard committed
231
{
232
    infoPtr->hwndNotify = lpcs->hwndParent;
233

234
    HOTKEY_SetFont(infoPtr, GetStockObject(SYSTEM_FONT), 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
235 236 237 238 239 240

    return 0;
}


static LRESULT
241
HOTKEY_Destroy (HOTKEY_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
242 243
{
    /* free hotkey info data */
244
    SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0);
245
    heap_free (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
246 247 248 249 250
    return 0;
}


static LRESULT
251
HOTKEY_EraseBackground (const HOTKEY_INFO *infoPtr, HDC hdc)
Alexandre Julliard's avatar
Alexandre Julliard committed
252
{
253
    HBRUSH hBrush, hSolidBrush = NULL;
254
    RECT   rc;
Alexandre Julliard's avatar
Alexandre Julliard committed
255

256 257 258 259 260
    if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
        hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrBtnFace);
    else
    {
        hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLOREDIT,
261
                                      (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
262 263 264 265
        if (!hBrush)
            hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrWindow);
    }

266
    GetClientRect (infoPtr->hwndSelf, &rc);
Alexandre Julliard's avatar
Alexandre Julliard committed
267

268
    FillRect (hdc, &rc, hBrush);
Alexandre Julliard's avatar
Alexandre Julliard committed
269

270 271 272
    if (hSolidBrush)
        DeleteObject(hSolidBrush);

Alexandre Julliard's avatar
Alexandre Julliard committed
273 274 275 276
    return -1;
}


277
static inline LRESULT
278
HOTKEY_GetFont (const HOTKEY_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
279
{
280
    return (LRESULT)infoPtr->hFont;
Alexandre Julliard's avatar
Alexandre Julliard committed
281 282 283
}

static LRESULT
284
HOTKEY_KeyDown (HOTKEY_INFO *infoPtr, DWORD key, DWORD flags)
Alexandre Julliard's avatar
Alexandre Julliard committed
285
{
286 287 288 289 290 291
    WORD wOldHotKey;
    BYTE bOldMod;

    if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
        return 0;

292
    TRACE("() Key: %d\n", key);
293 294 295 296

    wOldHotKey = infoPtr->HotKey;
    bOldMod = infoPtr->CurrMod;

297 298
    /* If any key is Pressed, we have to reset the hotkey in the control */
    infoPtr->HotKey = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
299

300
    switch (key)
301
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
302 303 304 305 306 307
	case VK_RETURN:
	case VK_TAB:
	case VK_SPACE:
	case VK_DELETE:
	case VK_ESCAPE:
	case VK_BACK:
308
	    InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
309
	    return DefWindowProcW (infoPtr->hwndSelf, WM_KEYDOWN, key, flags);
Alexandre Julliard's avatar
Alexandre Julliard committed
310 311

	case VK_SHIFT:
312 313
	    infoPtr->CurrMod |= HOTKEYF_SHIFT;
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
314
	case VK_CONTROL:
315 316
	    infoPtr->CurrMod |= HOTKEYF_CONTROL;
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
317
	case VK_MENU:
318
	    infoPtr->CurrMod |= HOTKEYF_ALT;
Alexandre Julliard's avatar
Alexandre Julliard committed
319 320 321
	    break;

	default:
322
	    if(HOTKEY_IsCombInv(infoPtr))
323
	        infoPtr->HotKey = MAKEWORD(key, infoPtr->InvMod);
324
	    else
325 326
	        infoPtr->HotKey = MAKEWORD(key, infoPtr->CurrMod);
	    infoPtr->ScanCode = flags;
Alexandre Julliard's avatar
Alexandre Julliard committed
327 328 329
	    break;
    }

330 331 332 333 334 335 336 337 338 339
    if ((wOldHotKey != infoPtr->HotKey) || (bOldMod != infoPtr->CurrMod))
    {
        InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);

        /* send EN_CHANGE notification */
        SendMessageW(infoPtr->hwndNotify, WM_COMMAND,
            MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), EN_CHANGE),
            (LPARAM)infoPtr->hwndSelf);
    }

340
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
341 342 343 344
}


static LRESULT
345
HOTKEY_KeyUp (HOTKEY_INFO *infoPtr, DWORD key)
Alexandre Julliard's avatar
Alexandre Julliard committed
346
{
347 348 349 350 351
    BYTE bOldMod;

    if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
        return 0;

352
    TRACE("() Key: %d\n", key);
353 354 355

    bOldMod = infoPtr->CurrMod;

356
    switch (key)
357
    {
358 359 360 361 362 363 364 365 366 367 368 369
	case VK_SHIFT:
	    infoPtr->CurrMod &= ~HOTKEYF_SHIFT;
	    break;
	case VK_CONTROL:
	    infoPtr->CurrMod &= ~HOTKEYF_CONTROL;
	    break;
	case VK_MENU:
	    infoPtr->CurrMod &= ~HOTKEYF_ALT;
	    break;
	default:
	    return 1;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
370

371 372 373 374 375 376 377 378 379
    if (bOldMod != infoPtr->CurrMod)
    {
        InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);

        /* send EN_CHANGE notification */
        SendMessageW(infoPtr->hwndNotify, WM_COMMAND,
            MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), EN_CHANGE),
            (LPARAM)infoPtr->hwndSelf);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
380 381 382 383 384 385

    return 0;
}


static LRESULT
386
HOTKEY_KillFocus (HOTKEY_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
387 388
{
    infoPtr->bFocus = FALSE;
389
    DestroyCaret ();
Alexandre Julliard's avatar
Alexandre Julliard committed
390 391 392 393 394 395

    return 0;
}


static LRESULT
396
HOTKEY_LButtonDown (const HOTKEY_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
397
{
398 399
    if (!(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED))
        SetFocus (infoPtr->hwndSelf);
Alexandre Julliard's avatar
Alexandre Julliard committed
400 401 402 403 404

    return 0;
}


405
static inline LRESULT
406
HOTKEY_NCCreate (HWND hwnd, const CREATESTRUCTW *lpcs)
Alexandre Julliard's avatar
Alexandre Julliard committed
407
{
Robert Shearman's avatar
Robert Shearman committed
408 409 410
    HOTKEY_INFO *infoPtr;
    DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE);
    SetWindowLongW (hwnd, GWL_EXSTYLE, 
411
                    dwExStyle | WS_EX_CLIENTEDGE);
Robert Shearman's avatar
Robert Shearman committed
412 413

    /* allocate memory for info structure */
414
    infoPtr = heap_alloc_zero (sizeof(*infoPtr));
Robert Shearman's avatar
Robert Shearman committed
415 416 417 418
    SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr);

    /* initialize info structure */
    infoPtr->HotKey = infoPtr->InvComb = infoPtr->InvMod = infoPtr->CurrMod = 0;
419
    infoPtr->CaretPos = GetSystemMetrics(SM_CXBORDER);
Robert Shearman's avatar
Robert Shearman committed
420 421 422
    infoPtr->hwndSelf = hwnd;
    LoadStringW(COMCTL32_hModule, HKY_NONE, infoPtr->strNone, 15);

423
    return DefWindowProcW (infoPtr->hwndSelf, WM_NCCREATE, 0, (LPARAM)lpcs);
Alexandre Julliard's avatar
Alexandre Julliard committed
424 425 426
}

static LRESULT
427
HOTKEY_SetFocus (HOTKEY_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
428 429 430
{
    infoPtr->bFocus = TRUE;

431 432
    CreateCaret (infoPtr->hwndSelf, NULL, 1, infoPtr->nHeight);
    SetCaretPos (infoPtr->CaretPos, GetSystemMetrics(SM_CYBORDER));
433
    ShowCaret (infoPtr->hwndSelf);
Alexandre Julliard's avatar
Alexandre Julliard committed
434 435 436 437 438

    return 0;
}


439
static LRESULT
440
HOTKEY_SetFont (HOTKEY_INFO *infoPtr, HFONT hFont, BOOL redraw)
Alexandre Julliard's avatar
Alexandre Julliard committed
441
{
442
    TEXTMETRICW tm;
443 444
    HDC hdc;
    HFONT hOldFont = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
445

446
    infoPtr->hFont = hFont;
Alexandre Julliard's avatar
Alexandre Julliard committed
447

448
    hdc = GetDC (infoPtr->hwndSelf);
Alexandre Julliard's avatar
Alexandre Julliard committed
449
    if (infoPtr->hFont)
450
	hOldFont = SelectObject (hdc, infoPtr->hFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
451

452
    GetTextMetricsW (hdc, &tm);
Alexandre Julliard's avatar
Alexandre Julliard committed
453 454 455
    infoPtr->nHeight = tm.tmHeight;

    if (infoPtr->hFont)
456
	SelectObject (hdc, hOldFont);
457
    ReleaseDC (infoPtr->hwndSelf, hdc);
Alexandre Julliard's avatar
Alexandre Julliard committed
458

459
    if (redraw)
460
	InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
461 462 463 464

    return 0;
}

465
static LRESULT WINAPI
466
HOTKEY_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
467
{
468
    HOTKEY_INFO *infoPtr = (HOTKEY_INFO *)GetWindowLongPtrW (hwnd, 0);
469
    TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hwnd, uMsg, wParam, lParam);
Robert Shearman's avatar
Robert Shearman committed
470
    if (!infoPtr && (uMsg != WM_NCCREATE))
471
        return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
472 473
    switch (uMsg)
    {
474 475 476
	case HKM_GETHOTKEY:
	    return HOTKEY_GetHotKey (infoPtr);
	case HKM_SETHOTKEY:
477
	    HOTKEY_SetHotKey (infoPtr, (WORD)wParam);
478 479
	    break;
	case HKM_SETRULES:
480
            HOTKEY_SetRules (infoPtr, (WORD)wParam, (WORD)lParam);
481
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
482

483 484 485
	case WM_CHAR:
	case WM_SYSCHAR:
	    return HOTKEY_KeyDown (infoPtr, MapVirtualKeyW(LOBYTE(HIWORD(lParam)), 1), lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
486 487

	case WM_CREATE:
488
	    return HOTKEY_Create (infoPtr, (LPCREATESTRUCTW)lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
489 490

	case WM_DESTROY:
491
	    return HOTKEY_Destroy (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
492 493

	case WM_ERASEBKGND:
494
	    return HOTKEY_EraseBackground (infoPtr, (HDC)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
495 496 497 498 499

	case WM_GETDLGCODE:
	    return DLGC_WANTCHARS | DLGC_WANTARROWS;

	case WM_GETFONT:
500
	    return HOTKEY_GetFont (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
501 502 503

	case WM_KEYDOWN:
	case WM_SYSKEYDOWN:
504
	    return HOTKEY_KeyDown (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
505 506 507

	case WM_KEYUP:
	case WM_SYSKEYUP:
508
	    return HOTKEY_KeyUp (infoPtr, wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510

	case WM_KILLFOCUS:
511
	    return HOTKEY_KillFocus (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
512 513

	case WM_LBUTTONDOWN:
514
	    return HOTKEY_LButtonDown (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
515 516

	case WM_NCCREATE:
517
	    return HOTKEY_NCCreate (hwnd, (LPCREATESTRUCTW)lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
518

519
	case WM_PRINTCLIENT:
520 521 522
	case WM_PAINT:
	    HOTKEY_Paint(infoPtr, (HDC)wParam);
	    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
523 524

	case WM_SETFOCUS:
525
	    return HOTKEY_SetFocus (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
526 527

	case WM_SETFONT:
528
	    return HOTKEY_SetFont (infoPtr, (HFONT)wParam, LOWORD(lParam));
Alexandre Julliard's avatar
Alexandre Julliard committed
529 530

	default:
531
	    if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
532
		ERR("unknown msg %04x wp=%08lx lp=%08lx\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
533
		     uMsg, wParam, lParam);
534
	    return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
535 536 537 538 539
    }
    return 0;
}


540
void
541
HOTKEY_Register (void)
Alexandre Julliard's avatar
Alexandre Julliard committed
542
{
543
    WNDCLASSW wndClass;
Alexandre Julliard's avatar
Alexandre Julliard committed
544

545
    ZeroMemory (&wndClass, sizeof(WNDCLASSW));
Alexandre Julliard's avatar
Alexandre Julliard committed
546
    wndClass.style         = CS_GLOBALCLASS;
547
    wndClass.lpfnWndProc   = HOTKEY_WindowProc;
Alexandre Julliard's avatar
Alexandre Julliard committed
548 549 550 551
    wndClass.cbClsExtra    = 0;
    wndClass.cbWndExtra    = sizeof(HOTKEY_INFO *);
    wndClass.hCursor       = 0;
    wndClass.hbrBackground = 0;
552
    wndClass.lpszClassName = HOTKEY_CLASSW;
553

554
    RegisterClassW (&wndClass);
Alexandre Julliard's avatar
Alexandre Julliard committed
555
}
556 557


558
void
559
HOTKEY_Unregister (void)
560
{
561
    UnregisterClassW (HOTKEY_CLASSW, NULL);
562
}