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"
Alexandre Julliard's avatar
Alexandre Julliard committed
41

42
WINE_DEFAULT_DEBUG_CHANNEL(hotkey);
43

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

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

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

65
static BOOL
66
HOTKEY_IsCombInv(const HOTKEY_INFO *infoPtr)
67 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
{
    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
93

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

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

    hFontOld = SelectObject(hdc, infoPtr->hFont);
107 108 109 110 111 112 113 114 115 116
    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);
    }
117 118 119 120 121 122 123 124 125 126 127 128 129

    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);
130
}
Alexandre Julliard's avatar
Alexandre Julliard committed
131

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

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

    if(!infoPtr->CurrMod && !infoPtr->HotKey) {
143
	HOTKEY_DrawHotKey (infoPtr, hdc, infoPtr->strNone, lstrlenW(infoPtr->strNone));
144 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
	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
182

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

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

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

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

Alexandre Julliard's avatar
Alexandre Julliard committed
227 228

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

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

    return 0;
}


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


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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

329 330 331 332 333 334 335 336 337 338
    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);
    }

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


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

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

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

    bOldMod = infoPtr->CurrMod;

355
    switch (key)
356
    {
357 358 359 360 361 362 363 364 365 366 367 368
	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
369

370 371 372 373 374 375 376 377 378
    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
379 380 381 382 383 384

    return 0;
}


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

    return 0;
}


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

    return 0;
}


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

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

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

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

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

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

    return 0;
}


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

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

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

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

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

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

    return 0;
}

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

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

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

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

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

	case WM_GETDLGCODE:
	    return DLGC_WANTCHARS | DLGC_WANTARROWS;

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

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

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

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

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

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

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

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

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

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


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

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

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


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