393 lines
8.9 KiB
C
393 lines
8.9 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);
|
||
|
}
|