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 20 21
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
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 57
    WORD  HotKey;
    WORD  InvComb;
    WORD  InvMod;
    BYTE  CurrMod;
    INT   CaretPos;
    DWORD ScanCode;
    WCHAR strNone[15]; /* hope its 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 66 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
static BOOL
HOTKEY_IsCombInv(HOTKEY_INFO *infoPtr)
{
    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, 4);
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 200 201 202 203 204 205 206 207
}

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
HOTKEY_GetHotKey(HOTKEY_INFO *infoPtr)
{
    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, LPCREATESTRUCTW 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
    HWND hwnd = infoPtr->hwndSelf;
Alexandre Julliard's avatar
Alexandre Julliard committed
243
    /* free hotkey info data */
244
    Free (infoPtr);
245
    SetWindowLongPtrW (hwnd, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
246 247 248 249 250
    return 0;
}


static LRESULT
251
HOTKEY_EraseBackground (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;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
277
inline static LRESULT
278
HOTKEY_GetFont (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: %ld\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, DWORD flags)
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: %ld\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, HWND receiveFocus)
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 (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;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
405
inline static LRESULT
406
HOTKEY_NCCreate (HWND hwnd, LPCREATESTRUCTW 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 414 415 416 417 418

    /* allocate memory for info structure */
    infoPtr = (HOTKEY_INFO *)Alloc (sizeof(HOTKEY_INFO));
    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, HWND lostFocus)
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=%x 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, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510

	case WM_KILLFOCUS:
511
	    return HOTKEY_KillFocus (infoPtr, (HWND)wParam);
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 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, (HWND)wParam);
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))
531
		ERR("unknown msg %04x wp=%08x 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
}