Windows2000/private/windows/shell/progman/hotkey.c
2020-09-30 17:12:32 +02:00

393 lines
8.8 KiB
C

/*
* hotkey.c
* Copyright (c) 1991, Microsoft Corporation
* DESCRIPTION
* This file is for support of program manager under NT Windows.
* This file is/was ported from hotkey.c (program manager).
* MODIFICATION HISTORY
* Initial Version: x/x/90 Author Unknown, since he didn't feel
* like commenting the code...
* NT 32b Version: 1/18/91 Jeff Pack
* Intitial port to begin.
*/
#include "progman.h"
#define HK_SHIFT 0x0100
#define HK_CONTROL 0x0200
#define HK_ALT 0x0400
#define HK_EXT 0x0800
#define F_EXT 0x01000000L
TCHAR szHotKey[] = TEXT("pmhotkey");
typedef struct HOTKEYWINDOWBYTES {
UINT hotkey;
int cyFont;
HFONT hfont;
} HOTKEYWINDOWBYTES;
#define HWL_HOTKEY FIELD_OFFSET(HOTKEYWINDOWBYTES, hotkey)
#define HWL_CYFONT FIELD_OFFSET(HOTKEYWINDOWBYTES, cyFont)
#define HWLP_FONT FIELD_OFFSET(HOTKEYWINDOWBYTES, hfont)
/*** SetHotKey --
* void APIENTRY SetHotKey(HWND hwnd, WORD hk)
* ENTRY - HWND hWnd
* WORD hk
* EXIT - void
* SYNOPSIS - ???
* WARNINGS -
* EFFECTS -
*/
void APIENTRY SetHotKey(HWND hwnd, WPARAM hk)
{
/* don't invalidate if it's the same
*/
if((LONG)hk == GetWindowLong(hwnd, HWL_HOTKEY)){
return;
}
SetWindowLong(hwnd, HWL_HOTKEY, (LONG)hk);
InvalidateRect(hwnd,NULL,TRUE);
}
/*** GetKeyName --
* void APIENTRY GetKeyName(WORD vk, PSTR psz, BOOL fExt)
* ENTRY - WORD hk
* PSTR psz
* BOOL fExt
* EXIT - void
* SYNOPSIS - ???
* WARNINGS -
* EFFECTS -
*/
void APIENTRY GetKeyName(UINT vk, LPTSTR psz, BOOL fExt)
{
LONG scan;
scan = (LONG)MapVirtualKey(vk,0) << 16;
if (fExt){
scan |= F_EXT;
}
GetKeyNameText(scan,psz,50);
}
/*** PaintHotKey --
* void APIENTRY PaintHotKey(register HWND hwnd)
* ENTRY - HWND hWnd
* EXIT - void
* SYNOPSIS - ???
* WARNINGS -
* EFFECTS -
*/
void APIENTRY PaintHotKey(register HWND hwnd)
{
TCHAR sz[128];
TCHAR szPlus[10];
WORD cch;
WORD hk;
register HDC hdc;
#ifndef ORGCODE
SIZE size;
#endif
PAINTSTRUCT ps;
int x, y;
HANDLE hFont;
DWORD dwColor;
LoadString(hAppInstance, IDS_PLUS, szPlus, CharSizeOf(szPlus));
if(hk = (WORD)GetWindowLong(hwnd, HWL_HOTKEY)){
sz[0] = 0;
cch = 0;
if (hk & HK_CONTROL){
GetKeyName(VK_CONTROL,sz,FALSE);
lstrcat(sz,szPlus);
}
if (hk & HK_SHIFT){
GetKeyName(VK_SHIFT, sz + lstrlen(sz), FALSE);
lstrcat(sz,szPlus);
}
if (hk & HK_ALT){
GetKeyName(VK_MENU, sz + lstrlen(sz), FALSE);
lstrcat(sz,szPlus);
}
GetKeyName((UINT)LOBYTE(hk), sz + lstrlen(sz), hk & HK_EXT);
}
else{
LoadString(hAppInstance,IDS_NONE,sz,100);
}
cch = (WORD)lstrlen(sz);
HideCaret(hwnd);
hdc = BeginPaint(hwnd,&ps);
SetBkMode(hdc, TRANSPARENT);
hFont = SelectObject(hdc,(HANDLE)GetWindowLongPtr(hwnd,HWLP_FONT));
x = GetSystemMetrics(SM_CXBORDER);
y = GetSystemMetrics(SM_CYBORDER);
if (IsWindowEnabled(hwnd)){
dwColor = GetSysColor(COLOR_WINDOWTEXT);
dwColor = SetTextColor(hdc,dwColor);
TextOut(hdc,x,y,sz,cch);
}
else if (dwColor = GetSysColor(COLOR_GRAYTEXT)){
dwColor = SetTextColor(hdc,dwColor);
TextOut(hdc,x,y,sz,cch);
SetTextColor(hdc,dwColor);
}
else{
GrayString(hdc,NULL,NULL,(LPARAM)(LPTSTR)sz,cch,x,y,0,0);
}
#ifdef ORGCODE
x = (WORD)GetTextExtentPoint(hdc,sz,cch);
#else
/*Used to return x/y in DWORD, now returns cx,cy in size*/
GetTextExtentPoint(hdc, sz, cch, &size);
x = size.cx;
#endif
if (GetFocus() == hwnd)
SetCaretPos(x+GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
ShowCaret(hwnd);
if (hFont){
SelectObject(hdc,hFont);
}
SetBkMode(hdc, OPAQUE);
EndPaint(hwnd,&ps);
}
/*** HotKeyWndProc --
* LRESULT APIENTRY HotKeyWndProc(register HWND hwnd, UINT wMsg,
* register WPARAM wParam, LPARAM lParam)
* ENTRY - HWND hWnd
* WORD wMsg
* WPARAM wParam
* LPARAM lParam
* EXIT - LRESULT xxx - returns info, or zero, for nothing to return
* SYNOPSIS - ???
* WARNINGS -
* EFFECTS -
*/
LRESULT APIENTRY HotKeyWndProc(register HWND hwnd, UINT wMsg,
register WPARAM wParam, LPARAM lParam)
{
HDC hdc;
WORD wT;
#ifndef ORGCODE
SIZE size;
#endif
switch (wMsg){
case WM_CREATE:
SetHotKey(hwnd,0);
SendMessage(hwnd,WM_SETFONT,(WPARAM)GetStockObject(SYSTEM_FONT),0L);
break;
case WM_SETFOCUS:
InvalidateRect(hwnd,NULL,TRUE);
CreateCaret(hwnd,NULL,0,GetWindowLong(hwnd,HWL_CYFONT));
ShowCaret(hwnd);
break;
case WM_KILLFOCUS:
if (!LOBYTE(GetWindowLong(hwnd,HWL_HOTKEY))){
SetHotKey(hwnd,0);
}
DestroyCaret();
break;
case WM_GETDLGCODE:
return DLGC_WANTCHARS | DLGC_WANTARROWS;
case WM_SETTEXT:
SetHotKey(hwnd,LOWORD(lParam));
break;
case WM_GETTEXT:
*(LPINT)lParam = GetWindowLong(hwnd,HWL_HOTKEY);
break;
case WM_SETHOTKEY:
SetHotKey(hwnd,(WPARAM) wParam);
break;
case WM_GETHOTKEY:
return GetWindowLong(hwnd,HWL_HOTKEY);
case WM_LBUTTONDOWN:
SetFocus(hwnd);
break;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
switch (wParam) {
case VK_RETURN:
case VK_TAB:
case VK_SPACE:
case VK_DELETE:
case VK_ESCAPE:
case VK_BACK:
SetHotKey(hwnd,0);
return DefWindowProc(hwnd,wMsg,wParam,lParam);
case VK_MENU:
case VK_SHIFT:
case VK_CONTROL:
wParam = 0;
/*** fall thru ***/
default:
if (GetKeyState(VK_CONTROL) < 0)
wParam |= HK_CONTROL;
if (GetKeyState(VK_SHIFT) < 0)
wParam |= HK_SHIFT;
if (GetKeyState(VK_MENU) < 0)
wParam |= HK_ALT;
if (lParam & F_EXT)
wParam |= HK_EXT;
// more than one shift key must be specified. That is,
// CONTROL+ALT, CONTROL+SHIFT, SHIFT+ALT
// get the bitmask of shift keys and then determine whether
// it has at least two bits set via the bitcount trick
// if not enough control things are present we add them
// in. so the user gets the idea.
if ((wParam & HK_ALT) && !(wParam & HK_CONTROL)
&& !(wParam & HK_SHIFT)) {
break;
}
else {
wT = (WORD)(wParam & (HK_CONTROL|HK_SHIFT|HK_ALT));
if (!wT || !(wT & (wT - 1)))
wParam |= HK_CONTROL | HK_ALT;
SetHotKey(hwnd,wParam);
break;
}
}
break;
case WM_SYSKEYUP:
case WM_CHAR:
case WM_SYSCHAR:
case WM_KEYUP:
if (!LOBYTE((WORD)GetWindowLong(hwnd,HWL_HOTKEY)))
SetHotKey(hwnd,0);
break;
case WM_GETFONT:
return GetWindowLongPtr(hwnd,HWLP_FONT);
case WM_SETFONT:
lParam = GetWindowLongPtr(hwnd,HWLP_FONT);
SetWindowLongPtr(hwnd,HWLP_FONT,wParam);
hdc = GetDC(hwnd);
wParam = (WPARAM) SelectObject(hdc,(HANDLE)wParam);
GetTextExtentPoint(hdc, TEXT("C"), 1, &size);
SetWindowLong(hwnd, HWL_CYFONT, size.cy);
if (wParam){
SelectObject(hdc,(HANDLE)wParam);
}
ReleaseDC(hwnd,hdc);
InvalidateRect(hwnd,NULL,TRUE);
return lParam;
case WM_PAINT:
PaintHotKey(hwnd);
break;
case WM_ERASEBKGND:
HideCaret(hwnd);
lParam = DefWindowProc(hwnd,wMsg,wParam,lParam);
ShowCaret(hwnd);
return lParam;
default:
return DefWindowProc(hwnd,wMsg,wParam,lParam);
}
return 0L;
}
/*** RegisterHotKeyClass --
* BOOL APIENTRY RegisterHotKeyClass(HANDLE hInstance)
* ENTRY - HWND HANDLE hInstance
* EXIT - BOOL xxx - returns return code from RegisterClass
* SYNOPSIS - ???
* WARNINGS - This (under 16) took hInstance. Under win32, hInstance is
* NULL, cause there is only one instance.
* EFFECTS -
*/
BOOL APIENTRY RegisterHotKeyClass(HANDLE hInstance)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = HotKeyWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(HOTKEYWINDOWBYTES);
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szHotKey;
return RegisterClass(&wc);
}