From d815052c34136cd084905d7a83cd482a66c34e73 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 20 Jun 2012 21:15:15 +0000 Subject: hotkey options dialog extracted to the separate file git-svn-id: http://svn.miranda-ng.org/main/trunk@505 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/modules/skin/hotkey_opts.cpp | 1009 ++++++++++++++++++++++++++++++++ src/modules/skin/hotkeys.cpp | 1168 ++------------------------------------ src/modules/skin/skin.h | 75 +++ 3 files changed, 1138 insertions(+), 1114 deletions(-) create mode 100644 src/modules/skin/hotkey_opts.cpp create mode 100644 src/modules/skin/skin.h (limited to 'src') diff --git a/src/modules/skin/hotkey_opts.cpp b/src/modules/skin/hotkey_opts.cpp new file mode 100644 index 0000000000..aa1526e955 --- /dev/null +++ b/src/modules/skin/hotkey_opts.cpp @@ -0,0 +1,1009 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "..\..\core\commonheaders.h" + +#include +#include "skin.h" + +static TCHAR *sttHokeyVkToName(WORD vkKey) +{ + static TCHAR buf[256] = {0}; + DWORD code = MapVirtualKey(vkKey, 0) << 16; + + switch (vkKey) + { + case 0: + case VK_CONTROL: + case VK_SHIFT: + case VK_MENU: + case VK_LWIN: + case VK_RWIN: + case VK_PAUSE: + case VK_CANCEL: + case VK_NUMLOCK: + case VK_CAPITAL: + case VK_SCROLL: + return _T(""); + + case VK_DIVIDE: + case VK_INSERT: + case VK_HOME: + case VK_PRIOR: + case VK_DELETE: + case VK_END: + case VK_NEXT: + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + code |= (1UL << 24); + } + + GetKeyNameText(code, buf, 256); + return buf; +} + +void HotkeyToName(TCHAR *buf, int size, BYTE shift, BYTE key) +{ + mir_sntprintf(buf, size, _T("%s%s%s%s%s"), + (shift & HOTKEYF_CONTROL) ? _T("Ctrl + ") : _T(""), + (shift & HOTKEYF_ALT) ? _T("Alt + ") : _T(""), + (shift & HOTKEYF_SHIFT) ? _T("Shift + ") : _T(""), + (shift & HOTKEYF_EXT) ? _T("Win + ") : _T(""), + sttHokeyVkToName(key)); +} + +/////////////////////////////////////////////////////////////////////////////// +// Hotkey control + +static LRESULT CALLBACK sttHotkeyEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + THotkeyBoxData *data = (THotkeyBoxData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + BOOL bKeyDown = FALSE; + if (!data) return 0; + + switch (msg) { + case HKM_GETHOTKEY: + return data->key ? MAKEWORD(data->key, data->shift) : 0; + + case HKM_SETHOTKEY: + { + TCHAR buf[256] = {0}; + data->key = (BYTE)LOWORD(wParam); + data->shift = (BYTE)HIWORD(wParam); + HotkeyToName(buf, SIZEOF(buf), data->shift, data->key); + SetWindowText(hwnd, buf); + } + return 0; + + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_KILLFOCUS: + break; + + case WM_CHAR: + case WM_SYSCHAR: + case WM_PASTE: + case WM_CONTEXTMENU: + return TRUE; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + bKeyDown = TRUE; + + case WM_KEYUP: + case WM_SYSKEYUP: + { + TCHAR buf[256] = {0}; + + BYTE shift = 0; + BYTE key = wParam; + TCHAR *name = sttHokeyVkToName(key); + if (!*name || !bKeyDown) + key = 0; + + if (GetAsyncKeyState(VK_CONTROL)) shift |= HOTKEYF_CONTROL; + if (GetAsyncKeyState(VK_MENU)) shift |= HOTKEYF_ALT; + if (GetAsyncKeyState(VK_SHIFT)) shift |= HOTKEYF_SHIFT; + if (GetAsyncKeyState(VK_LWIN) || GetAsyncKeyState(VK_RWIN)) shift |= HOTKEYF_EXT; + + if (bKeyDown || !data->key) { + data->shift = shift; + data->key = key; + } + + HotkeyToName(buf, SIZEOF(buf), data->shift, data->key); + SetWindowText(hwnd, buf); + + if (bKeyDown && data->key) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKELONG(GetWindowLongPtr(hwnd, GWL_ID), 0), (LPARAM)hwnd); + } + return TRUE; + + case WM_DESTROY: + { + WNDPROC saveOldWndProc = data->oldWndProc; + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)data->oldWndProc); + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + mir_free(data); + return CallWindowProc(saveOldWndProc, hwnd, msg, wParam, lParam); + } + } + + return CallWindowProc(data->oldWndProc, hwnd, msg, wParam, lParam); +} + +void HotkeyEditCreate(HWND hwnd) +{ + THotkeyBoxData *data = (THotkeyBoxData *)mir_alloc(sizeof(THotkeyBoxData)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (ULONG_PTR)data); + data->oldWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (ULONG_PTR)sttHotkeyEditProc); +} + +/////////////////////////////////////////////////////////////////////////////// +// Options + +enum { COL_NAME, COL_TYPE, COL_KEY, COL_RESET, COL_ADDREMOVE }; + +static void sttOptionsSetupItem(HWND hwndList, int idx, THotkeyItem *item) +{ + TCHAR buf[256]; + LVITEM lvi = {0}; + lvi.iItem = idx; + + if ( !item->rootHotkey) { + lvi.mask = LVIF_TEXT|LVIF_IMAGE; + lvi.iSubItem = COL_NAME; + lvi.pszText = item->getDescr(); + lvi.iImage = item->OptType; + ListView_SetItem(hwndList, &lvi); + + ListView_SetCheckState(hwndList, lvi.iItem, item->Enabled); + } + + lvi.mask = LVIF_TEXT; + lvi.iSubItem = COL_KEY; + HotkeyToName(buf, SIZEOF(buf), HIBYTE(item->OptHotkey), LOBYTE(item->OptHotkey)); + lvi.pszText = buf; + ListView_SetItem(hwndList, &lvi); + + if (item->rootHotkey) { + lvi.mask = LVIF_IMAGE; + lvi.iSubItem = COL_TYPE; + lvi.iImage = item->OptType; + ListView_SetItem(hwndList, &lvi); + } + + lvi.mask = LVIF_IMAGE; + lvi.iSubItem = COL_RESET; + lvi.iImage = (item->Hotkey != item->OptHotkey) ? 5 : -1; + ListView_SetItem(hwndList, &lvi); + + lvi.mask = LVIF_IMAGE|LVIF_TEXT; + lvi.iSubItem = COL_ADDREMOVE; + if (item->rootHotkey) { + lvi.iImage = 4; + lvi.pszText = TranslateT("Remove shortcut"); + } + else { + lvi.iImage = 3; + lvi.pszText = TranslateT("Add another shortcut"); + } + ListView_SetItem(hwndList, &lvi); +} + +static void sttOptionsDeleteHotkey(HWND hwndList, int idx, THotkeyItem *item) +{ + item->OptDeleted = TRUE; + ListView_DeleteItem(hwndList, idx); + if (item->rootHotkey) + item->rootHotkey->OptChanged = TRUE; +} + +static int CALLBACK sttOptionsSortList(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + TCHAR title1[256] = {0}, title2[256] = {0}; + THotkeyItem *item1 = NULL, *item2 = NULL; + LVITEM lvi = {0}; + int res; + + lvi.mask = LVIF_TEXT|LVIF_PARAM; + lvi.iItem = lParam1; + lvi.pszText = title1; + lvi.cchTextMax = SIZEOF(title1); + if (ListView_GetItem((HWND)lParamSort, &lvi)) + item1 = (THotkeyItem *)lvi.lParam; + + lvi.mask = LVIF_TEXT|LVIF_PARAM; + lvi.iItem = lParam2; + lvi.pszText = title2; + lvi.cchTextMax = SIZEOF(title2); + if (ListView_GetItem((HWND)lParamSort, &lvi)) + item2 = (THotkeyItem *)lvi.lParam; + + if ( !item1 && !item2) + return lstrcmp(title1, title2); + + if ( !item1) { + if (res = lstrcmp(title1, item2->getSection())) + return res; + return -1; + } + + if ( !item2) { + if (res = lstrcmp(item1->getSection(), title2)) + return res; + return 1; + } + + if (res = lstrcmp(item1->getSection(), item2->getSection())) return res; + if (res = lstrcmp(item1->getDescr(), item2->getDescr())) return res; + if (!item1->rootHotkey && item2->rootHotkey) return -1; + if (item1->rootHotkey && !item2->rootHotkey) return 1; + return 0; +} + +static void sttOptionsAddHotkey(HWND hwndList, THotkeyItem *item) +{ + char buf[256]; + + THotkeyItem *newItem = (THotkeyItem *)mir_alloc(sizeof(THotkeyItem)); + newItem->pszName = NULL; + newItem->pszService = item->pszService ? mir_strdup(item->pszService) : NULL; + newItem->ptszSection = mir_tstrdup(item->ptszSection); + newItem->ptszDescription = mir_tstrdup(item->ptszDescription); + newItem->lParam = item->lParam; + mir_snprintf(buf, SIZEOF(buf), "mir_hotkey_%d_%d", g_pid, hotkeys.getCount()+1); + newItem->idHotkey = GlobalAddAtomA(buf); + newItem->rootHotkey = item; + newItem->Hotkey = newItem->DefHotkey = newItem->OptHotkey = 0; + newItem->type = newItem->OptType = item->OptType; + newItem->Enabled = newItem->OptEnabled = TRUE; + newItem->OptChanged = newItem->OptDeleted = FALSE; + newItem->OptNew = TRUE; + hotkeys.insert(newItem); + + SendMessage(hwndList, WM_SETREDRAW, FALSE, 0); + + LVITEM lvi = {0}; + lvi.mask |= LVIF_PARAM; + lvi.lParam = (LPARAM)newItem; + sttOptionsSetupItem(hwndList, ListView_InsertItem(hwndList, &lvi), newItem); + ListView_SortItemsEx(hwndList, sttOptionsSortList, (LPARAM)hwndList); + + SendMessage(hwndList, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwndList, NULL, NULL, RDW_INVALIDATE); + + item->OptChanged = TRUE; +} + +static void sttOptionsSetChanged(THotkeyItem *item) +{ + item->OptChanged = TRUE; + if (item->rootHotkey) + item->rootHotkey->OptChanged = TRUE; +} + +static void sttOptionsSaveItem(THotkeyItem *item) +{ + int i; + char buf[MAXMODULELABELLENGTH]; + + if (item->rootHotkey) return; + if ( !item->OptChanged) return; + + item->Hotkey = item->OptHotkey; + item->type = item->OptType; + item->Enabled = item->OptEnabled; + + DBWriteContactSettingWord(NULL, DBMODULENAME, item->pszName, item->Hotkey); + DBWriteContactSettingByte(NULL, DBMODULENAME "Off", item->pszName, (BYTE)!item->Enabled); + if (item->type != HKT_MANUAL) + DBWriteContactSettingByte(NULL, DBMODULENAME "Types", item->pszName, (BYTE)item->type); + + item->nSubHotkeys = 0; + for (i = 0; i < hotkeys.getCount(); i++) { + THotkeyItem *subItem = hotkeys[i]; + if (subItem->rootHotkey == item) { + subItem->Hotkey = subItem->OptHotkey; + subItem->type = subItem->OptType; + + mir_snprintf(buf, SIZEOF(buf), "%s$%d", item->pszName, item->nSubHotkeys); + DBWriteContactSettingWord(NULL, DBMODULENAME, buf, subItem->Hotkey); + if (subItem->type != HKT_MANUAL) + DBWriteContactSettingByte(NULL, DBMODULENAME "Types", buf, (BYTE)subItem->type); + + ++item->nSubHotkeys; + } } + + mir_snprintf(buf, SIZEOF(buf), "%s$count", item->pszName); + DBWriteContactSettingDword(NULL, DBMODULENAME, buf, item->nSubHotkeys); +} + +static void sttBuildHotkeyList(HWND hwndList) +{ + int i, nItems=0; + ListView_DeleteAllItems(hwndList); + + for (i = 0; i < hotkeys.getCount(); i++) { + LVITEM lvi = {0}; + THotkeyItem *item = hotkeys[i]; + + if (item->OptDeleted) + continue; + + if ( !i || lstrcmp(item->ptszSection, hotkeys[i-1]->ptszSection)) { + lvi.mask = LVIF_TEXT|LVIF_PARAM; + lvi.iItem = nItems++; + lvi.iSubItem = 0; + lvi.lParam = 0; + lvi.pszText = item->getSection(); + ListView_InsertItem(hwndList, &lvi); + ListView_SetCheckState(hwndList, lvi.iItem, TRUE); + + lvi.mask = LVIF_TEXT; + lvi.iSubItem = 1; + lvi.pszText = item->ptszSection; + ListView_SetItem(hwndList, &lvi); + + lvi.iSubItem = 0; + } + + lvi.mask = LVIF_PARAM | LVIF_INDENT; + lvi.iIndent = 1; + lvi.iItem = nItems++; + lvi.lParam = (LPARAM)item; + ListView_InsertItem(hwndList, &lvi); + sttOptionsSetupItem(hwndList, nItems-1, item); + } + + ListView_SortItemsEx(hwndList, sttOptionsSortList, (LPARAM)hwndList); +} + +static void sttOptionsStartEdit(HWND hwndDlg, HWND hwndHotkey) +{ + LVITEM lvi; + THotkeyItem *item; + int iItem = ListView_GetNextItem(hwndHotkey, -1, LVNI_SELECTED); + if (iItem < 0) return; + + lvi.mask = LVIF_PARAM; + lvi.iItem = iItem; + ListView_GetItem(hwndHotkey, &lvi); + + if (item = (THotkeyItem *)lvi.lParam) { + RECT rc; + ListView_GetSubItemRect(hwndHotkey, iItem, COL_KEY, LVIR_BOUNDS, &rc); + MapWindowPoints(hwndHotkey, hwndDlg, (LPPOINT)&rc, 2); + SendDlgItemMessage(hwndDlg, IDC_HOTKEY, HKM_SETHOTKEY, MAKELONG(LOBYTE(item->OptHotkey), HIBYTE(item->OptHotkey)), 0); + + SetWindowPos(hwndHotkey, HWND_BOTTOM, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); + SetWindowPos(GetDlgItem(hwndDlg, IDC_HOTKEY), HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); + RedrawWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), NULL, NULL, RDW_INVALIDATE); + + SetFocus(GetDlgItem(hwndDlg, IDC_HOTKEY)); + RedrawWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), NULL, NULL, RDW_INVALIDATE); + } +} + +static void sttOptionsDrawTextChunk(HDC hdc, TCHAR *text, RECT *rc) +{ + SIZE sz; + DrawText(hdc, text, lstrlen(text), rc, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER|DT_WORD_ELLIPSIS); + GetTextExtentPoint32(hdc, text, lstrlen(text), &sz); + rc->left += sz.cx; +} + +static INT_PTR CALLBACK sttOptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static BOOL initialized = FALSE; + static int colWidth = 0; + static WORD currentLanguage = 0; + + HWND hwndHotkey = GetDlgItem(hwndDlg, IDC_LV_HOTKEYS); + + switch (msg) { + case WM_INITDIALOG: + initialized = FALSE; + + TranslateDialogDefault(hwndDlg); + + HotkeyEditCreate(GetDlgItem(hwndDlg, IDC_HOTKEY)); + { + HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK + (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 3, 1); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_WINDOWS); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_MIRANDA); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_WINDOW); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_ADDCONTACT); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_DELETE); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_UNDO); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_GROUPOPEN); + ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_GROUPSHUT); + ListView_SetImageList(hwndHotkey, hIml, LVSIL_SMALL); + } + ListView_SetExtendedListViewStyle(hwndHotkey, LVS_EX_CHECKBOXES|LVS_EX_SUBITEMIMAGES|LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER|LVS_EX_INFOTIP); + { + RECT rc; + GetClientRect(hwndHotkey, &rc); + colWidth = rc.right - GetSystemMetrics(SM_CXHTHUMB) - 3*GetSystemMetrics(SM_CXSMICON) - 5; + + LVCOLUMN lvc; + lvc.mask = LVCF_WIDTH; + lvc.cx = colWidth * 2 / 3; + ListView_InsertColumn(hwndHotkey, COL_NAME, &lvc); + lvc.cx = GetSystemMetrics(SM_CXSMICON); + ListView_InsertColumn(hwndHotkey, COL_TYPE, &lvc); + lvc.cx = colWidth / 3; + ListView_InsertColumn(hwndHotkey, COL_KEY, &lvc); + lvc.cx = GetSystemMetrics(SM_CXSMICON); + ListView_InsertColumn(hwndHotkey, COL_RESET, &lvc); + lvc.cx = GetSystemMetrics(SM_CXSMICON); + ListView_InsertColumn(hwndHotkey, COL_ADDREMOVE, &lvc); + + for (int i = 0; i < hotkeys.getCount(); i++) { + THotkeyItem *item = hotkeys[i]; + + item->OptChanged = FALSE; + item->OptDeleted = item->OptNew = FALSE; + item->OptEnabled = item->Enabled; + item->OptHotkey = item->Hotkey; + item->OptType = item->type; + } + + currentLanguage = LOWORD(GetKeyboardLayout(0)); + sttBuildHotkeyList(hwndHotkey); + } + SetTimer(hwndDlg, 1024, 1000, NULL); + initialized = TRUE; + { + /* load group states */ + int count = ListView_GetItemCount(hwndHotkey); + TCHAR buf[128]; + LVITEM lvi = {0}; + lvi.pszText = buf; + lvi.cchTextMax = SIZEOF(buf); + for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { + char *szSetting; + + lvi.mask = LVIF_PARAM; + lvi.iSubItem = 0; + ListView_GetItem(hwndHotkey, &lvi); + if (lvi.lParam) continue; + + lvi.mask = LVIF_TEXT; + lvi.iSubItem = 1; + ListView_GetItem(hwndHotkey, &lvi); + + szSetting = mir_t2a(lvi.pszText); + + ListView_SetCheckState(hwndHotkey, lvi.iItem, + DBGetContactSettingByte(NULL, DBMODULENAME "UI", szSetting, TRUE)); + + mir_free(szSetting); + } + } + + g_hwndHkOptions = hwndDlg; + break; + + case WM_TIMER: + if (initialized) { + WORD newLanguage = LOWORD(GetKeyboardLayout(0)); + if (newLanguage == currentLanguage) + break; + + int count = ListView_GetItemCount(hwndHotkey); + + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { + ListView_GetItem(hwndHotkey, &lvi); + if (lvi.lParam) + sttOptionsSetupItem(hwndHotkey, lvi.iItem, (THotkeyItem *)lvi.lParam); + } + currentLanguage = newLanguage; + } + break; + + case WM_HOTKEYUNREGISTERED: + { + int count = ListView_GetItemCount(hwndHotkey); + + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { + ListView_GetItem(hwndHotkey, &lvi); + if ( !lvi.lParam) continue; + + if (((THotkeyItem *)lvi.lParam)->UnregisterHotkey) { + ListView_DeleteItem(hwndHotkey, lvi.iItem); + --lvi.iItem; + --count; + } + } + } + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; + RECT rc = lpdis->rcItem; + int prefix = 65; + int width = (lpdis->rcItem.right - lpdis->rcItem.left - prefix) / 3; + rc.left += 5; + + HIMAGELIST hIml = ListView_GetImageList(hwndHotkey, LVSIL_SMALL); + + if (lpdis->CtlID == IDC_CANVAS2) { + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Scope:"), &rc); + + rc.left = prefix + width * 0; + ImageList_Draw(hIml, 0, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); + rc.left += 20; + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("System"), &rc); + + rc.left = prefix + width * 1; + ImageList_Draw(hIml, 1, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); + rc.left += 20; + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Miranda"), &rc); + + rc.left = prefix + width * 2; + ImageList_Draw(hIml, 2, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); + rc.left += 20; + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Window"), &rc); + return TRUE; + } + + if (lpdis->CtlID == IDC_CANVAS) { + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Actions:"), &rc); + rc.left += 10; + + rc.left = prefix + width * 0; + ImageList_Draw(hIml, 5, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); + rc.left += 20; + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Undo"), &rc); + + rc.left = prefix + width * 1; + ImageList_Draw(hIml, 3, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); + rc.left += 20; + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Add binding"), &rc); + + rc.left = prefix + width * 2; + ImageList_Draw(hIml, 4, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); + rc.left += 20; + sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Remove"), &rc); + return TRUE; + } + } + break; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_HOTKEY) && ((HIWORD(wParam) == EN_KILLFOCUS) || (HIWORD(wParam) == 0))) { + LVITEM lvi; + THotkeyItem *item; + WORD wHotkey = (WORD)SendDlgItemMessage(hwndDlg, IDC_HOTKEY, HKM_GETHOTKEY, 0, 0); + + ShowWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), SW_HIDE); + SetFocus(hwndHotkey); + if ( !wHotkey || (wHotkey == VK_ESCAPE) || (HIWORD(wParam) != 0)) + break; + + lvi.mask = LVIF_PARAM; + lvi.iItem = ListView_GetNextItem(hwndHotkey, -1, LVNI_SELECTED); + if (lvi.iItem >= 0) { + ListView_GetItem(hwndHotkey, &lvi); + if (item = (THotkeyItem *)lvi.lParam) { + item->OptHotkey = wHotkey; + + sttOptionsSetupItem(hwndHotkey, lvi.iItem, item); + sttOptionsSetChanged(item); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } } } + break; + + case WM_CONTEXTMENU: + if (GetWindowLongPtr((HWND)wParam, GWL_ID) == IDC_LV_HOTKEYS) { + HWND hwndList = (HWND)wParam; + POINT pt = { (signed short)LOWORD(lParam), (signed short)HIWORD(lParam) }; + LVITEM lvi = {0}; + THotkeyItem *item = NULL; + + lvi.iItem = ListView_GetNextItem(hwndHotkey, -1, LVNI_SELECTED); + if (lvi.iItem < 0) return FALSE; + + lvi.mask = LVIF_PARAM; + ListView_GetItem(hwndList, &lvi); + if ( !(item = (THotkeyItem *)lvi.lParam)) return FALSE; + + if ((pt.x == -1) && (pt.y == -1)) { + RECT rc; + ListView_GetItemRect(hwndList, lvi.iItem, &rc, LVIR_LABEL); + pt.x = rc.left; + pt.y = rc.bottom; + ClientToScreen(hwndList, &pt); + } + + enum { MI_CANCEL, MI_CHANGE, MI_SYSTEM, MI_LOCAL, MI_ADD, MI_REMOVE, MI_REVERT }; + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = MFS_DEFAULT; + + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_CHANGE, TranslateT("Modify")); + SetMenuItemInfo(hMenu, (UINT_PTR)MI_CHANGE, FALSE, &mii); + if (item->type != HKT_MANUAL) { + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + AppendMenu(hMenu, MF_STRING| + ((item->OptType == HKT_GLOBAL) ? MF_CHECKED : 0), + (UINT_PTR)MI_SYSTEM, TranslateT("System scope")); + AppendMenu(hMenu, MF_STRING| + ((item->OptType == HKT_LOCAL) ? MF_CHECKED : 0), + (UINT_PTR)MI_LOCAL, TranslateT("Miranda scope")); + } + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + if ( !item->rootHotkey) + AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_ADD, TranslateT("Add binding")); + else + AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_REMOVE, TranslateT("Remove")); + if (item->Hotkey != item->OptHotkey) { + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_REVERT, TranslateT("Undo")); + } + + switch (TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) { + case MI_CHANGE: + sttOptionsStartEdit(hwndDlg, hwndHotkey); + break; + case MI_SYSTEM: + item->OptType = HKT_GLOBAL; + sttOptionsSetupItem(hwndList, lvi.iItem, item); + sttOptionsSetChanged(item); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case MI_LOCAL: + item->OptType = HKT_LOCAL; + sttOptionsSetupItem(hwndList, lvi.iItem, item); + sttOptionsSetChanged(item); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case MI_ADD: + initialized = FALSE; + sttOptionsAddHotkey(hwndList, item); + initialized = FALSE; + break; + case MI_REMOVE: + sttOptionsDeleteHotkey(hwndList, lvi.iItem, item); + break; + case MI_REVERT: + item->OptHotkey = item->Hotkey; + sttOptionsSetupItem(hwndList, lvi.iItem, item); + break; + } + DestroyMenu(hMenu); + break; + } + break; + + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR)lParam; + switch (lpnmhdr->idFrom) { + case 0: + { + int i; + + if ((lpnmhdr->code != PSN_APPLY) && (lpnmhdr->code != PSN_RESET)) + break; + + UnregisterHotkeys(); + + for (i = 0; i < hotkeys.getCount(); i++) { + THotkeyItem *item = hotkeys[i]; + if (item->OptNew && item->OptDeleted || + item->rootHotkey && !item->OptHotkey || + (lpnmhdr->code == PSN_APPLY) && item->OptDeleted || + (lpnmhdr->code == PSN_RESET) && item->OptNew) + { + FreeHotkey(item); + hotkeys.remove(i--); + } + } + + if (lpnmhdr->code == PSN_APPLY) { + LVITEM lvi = {0}; + int count = ListView_GetItemCount(hwndHotkey); + + for (i = 0; i < hotkeys.getCount(); i++) + sttOptionsSaveItem(hotkeys[i]); + + lvi.mask = LVIF_IMAGE; + lvi.iSubItem = COL_RESET; + lvi.iImage = -1; + for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) + ListView_SetItem(hwndHotkey, &lvi); + } + + RegisterHotkeys(); + + NotifyEventHooks(hEvChanged, 0, 0); + } + break; + + case IDC_LV_HOTKEYS: + switch (lpnmhdr->code) { + case NM_CLICK: + { + THotkeyItem *item = NULL; + LPNMITEMACTIVATE lpnmia = (LPNMITEMACTIVATE)lParam; + LVHITTESTINFO lvhti = {0}; + LVITEM lvi = {0}; + + lvi.mask = LVIF_PARAM|LVIF_IMAGE; + lvi.iItem = lpnmia->iItem; + ListView_GetItem(lpnmia->hdr.hwndFrom, &lvi); + item = (THotkeyItem *)lvi.lParam; + + lvhti.pt = lpnmia->ptAction; + lvhti.iItem = lpnmia->iItem; + lvhti.iSubItem = lpnmia->iSubItem; + ListView_HitTest(lpnmia->hdr.hwndFrom, &lvhti); + + if (item && + ( !item->rootHotkey && (lpnmia->iSubItem == COL_NAME) && ((lvhti.flags & LVHT_ONITEM) == LVHT_ONITEMICON) || + item->rootHotkey && (lpnmia->iSubItem == COL_TYPE)) && + ((item->OptType == HKT_GLOBAL) || (item->OptType == HKT_LOCAL))) + { + item->OptType = (item->OptType == HKT_GLOBAL) ? HKT_LOCAL : HKT_GLOBAL; + sttOptionsSetupItem(lpnmia->hdr.hwndFrom, lpnmia->iItem, item); + sttOptionsSetChanged(item); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + else if (item && (lpnmia->iSubItem == COL_RESET)) { + item->OptHotkey = item->Hotkey; + sttOptionsSetupItem(lpnmia->hdr.hwndFrom, lpnmia->iItem, item); + } + else if (item && (lpnmia->iSubItem == COL_ADDREMOVE)) { + if (item->rootHotkey) + sttOptionsDeleteHotkey(lpnmia->hdr.hwndFrom, lpnmia->iItem, item); + else { + initialized = FALSE; + sttOptionsAddHotkey(lpnmia->hdr.hwndFrom, item); + initialized = TRUE; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + + case LVN_KEYDOWN: + { + LPNMLVKEYDOWN param = (LPNMLVKEYDOWN)lParam; + if (param->wVKey == VK_SUBTRACT || param->wVKey == VK_LEFT || param->wVKey == VK_ADD || param->wVKey == VK_RIGHT) { + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + lvi.iItem = ListView_GetNextItem(lpnmhdr->hwndFrom, -1, LVNI_SELECTED); + if (lvi.iItem < 0) + break; + + ListView_GetItem(lpnmhdr->hwndFrom, &lvi); + if (lvi.lParam) + break; + + if (param->wVKey == VK_ADD || param->wVKey == VK_RIGHT) { + ListView_SetCheckState(lpnmhdr->hwndFrom, lvi.iItem, TRUE); + } + else { + ListView_SetCheckState(lpnmhdr->hwndFrom, lvi.iItem, FALSE); + } + } + else if (param->wVKey == VK_F2) + sttOptionsStartEdit(hwndDlg, hwndHotkey); + } + break; + + case LVN_ITEMACTIVATE: + { + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + lvi.iItem = ListView_GetNextItem(lpnmhdr->hwndFrom, -1, LVNI_SELECTED); + if (lvi.iItem < 0) break; + ListView_GetItem(lpnmhdr->hwndFrom, &lvi); + + if (lvi.lParam) + sttOptionsStartEdit(hwndDlg, hwndHotkey); + else + ListView_SetCheckState(lpnmhdr->hwndFrom, lvi.iItem, !ListView_GetCheckState(lpnmhdr->hwndFrom, lvi.iItem)); + } + break; + + case LVN_ITEMCHANGED: + { + LPNMLISTVIEW param = (LPNMLISTVIEW)lParam; + THotkeyItem *item = (THotkeyItem *)param->lParam; + if ( !initialized || (param->uNewState>>12 == param->uOldState>>12)) + break; + + if (item && !item->rootHotkey) { + item->OptEnabled = ListView_GetCheckState(lpnmhdr->hwndFrom, param->iItem) ? 1 : 0; + sttOptionsSetChanged(item); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + else if ( !item) { + TCHAR buf[256]; + LVITEM lvi = {0}; + lvi.mask = LVIF_TEXT; + lvi.iItem = param->iItem; + lvi.pszText = buf; + lvi.cchTextMax = SIZEOF(buf); + ListView_GetItem(lpnmhdr->hwndFrom, &lvi); + + if (param->uNewState>>12 == 1) { + int count = ListView_GetItemCount(lpnmhdr->hwndFrom); + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { + THotkeyItem *item; + ListView_GetItem(lpnmhdr->hwndFrom, &lvi); + item = (THotkeyItem *)lvi.lParam; + if ( !item) continue; + if ( !lstrcmp( item->getSection(), buf)) { + ListView_DeleteItem(lpnmhdr->hwndFrom, lvi.iItem); + --lvi.iItem; + --count; + } } + } + else if (param->uNewState>>12 == 2) { + int i, nItems = ListView_GetItemCount(lpnmhdr->hwndFrom); + initialized = FALSE; + for (i = 0; i < hotkeys.getCount(); ++i) { + LVITEM lvi = {0}; + THotkeyItem *item = hotkeys[i]; + + if (item->OptDeleted) + continue; + if ( lstrcmp(buf, item->getSection())) + continue; + + lvi.mask = LVIF_PARAM|LVIF_INDENT; + lvi.iIndent = 1; + lvi.iItem = nItems++; + lvi.lParam = (LPARAM)item; + ListView_InsertItem(lpnmhdr->hwndFrom, &lvi); + sttOptionsSetupItem(lpnmhdr->hwndFrom, nItems-1, item); + } + ListView_SortItemsEx(lpnmhdr->hwndFrom, sttOptionsSortList, (LPARAM)lpnmhdr->hwndFrom); + initialized = TRUE; + } + } + break; + } + case NM_CUSTOMDRAW: + { + NMLVCUSTOMDRAW *param = (NMLVCUSTOMDRAW *) lParam; + switch (param->nmcd.dwDrawStage) { + case CDDS_PREPAINT: + case CDDS_ITEMPREPAINT: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_NOTIFYSUBITEMDRAW); + return TRUE; + + case CDDS_SUBITEM|CDDS_ITEMPREPAINT: + { + THotkeyItem *item; + TCHAR buf[256]; + LVITEM lvi = {0}; + lvi.mask = LVIF_TEXT|LVIF_PARAM; + lvi.iItem = param->nmcd.dwItemSpec; + lvi.pszText = buf; + lvi.cchTextMax = SIZEOF(buf); + ListView_GetItem(lpnmhdr->hwndFrom, &lvi); + + item = (THotkeyItem *)lvi.lParam; + if (!item) { + RECT rc; + HFONT hfnt; + + ListView_GetSubItemRect(lpnmhdr->hwndFrom, param->nmcd.dwItemSpec, param->iSubItem, LVIR_BOUNDS, &rc); + FillRect(param->nmcd.hdc, &rc, GetSysColorBrush(param->nmcd.uItemState&CDIS_SELECTED ? COLOR_HIGHLIGHT : COLOR_WINDOW)); + SetTextColor(param->nmcd.hdc, GetSysColor(param->nmcd.uItemState&CDIS_SELECTED ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT)); + + if (param->iSubItem == 0) { + rc.left += 3; + HIMAGELIST hIml = ListView_GetImageList(hwndHotkey, LVSIL_SMALL); + ImageList_Draw(hIml, + ListView_GetCheckState(hwndHotkey, lvi.iItem) ? 6 : 7, + param->nmcd.hdc, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); + rc.left += 18; + hfnt = (HFONT)SelectObject(param->nmcd.hdc, (HFONT)SendMessage(GetParent(hwndDlg), PSM_GETBOLDFONT, 0, 0)); + DrawText(param->nmcd.hdc, buf, -1, &rc, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER); + SelectObject(param->nmcd.hdc, hfnt); + } + + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT); + return TRUE; + } + + if (item->rootHotkey && (param->iSubItem == 0)) { + RECT rc; + ListView_GetSubItemRect(lpnmhdr->hwndFrom, param->nmcd.dwItemSpec, param->iSubItem, LVIR_BOUNDS, &rc); + FillRect(param->nmcd.hdc, &rc, GetSysColorBrush(COLOR_WINDOW)); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT); + return TRUE; + } + break; + } + } + break; + } + break; + } + } + } + break; + + case WM_DESTROY: + { + int count = ListView_GetItemCount(hwndHotkey); + + g_hwndHkOptions = NULL; + + KillTimer(hwndDlg, 1024); + + TCHAR buf[128]; + LVITEM lvi = {0}; + lvi.pszText = buf; + lvi.cchTextMax = SIZEOF(buf); + for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { + lvi.mask = LVIF_PARAM; + lvi.iSubItem = 0; + ListView_GetItem(hwndHotkey, &lvi); + if (lvi.lParam) continue; + + lvi.mask = LVIF_TEXT; + lvi.iSubItem = 1; + ListView_GetItem(hwndHotkey, &lvi); + + DBWriteContactSettingByte(NULL, DBMODULENAME "UI", _T2A(lvi.pszText), ListView_GetCheckState(hwndHotkey, lvi.iItem)); + } + } + } + + return FALSE; +} + +int HotkeyOptionsInit(WPARAM wParam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.hInstance = hMirandaInst; + odp.flags = ODPF_BOLDGROUPS; + odp.position = -180000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_HOTKEYS); + odp.pszTitle = LPGEN("Hotkeys"); + odp.pszGroup = LPGEN("Customize"); + odp.pfnDlgProc = sttOptionsDlgProc; + Options_AddPage(wParam, &odp); + return 0; +} diff --git a/src/modules/skin/hotkeys.cpp b/src/modules/skin/hotkeys.cpp index 2d2fd77be0..7d62892e25 100644 --- a/src/modules/skin/hotkeys.cpp +++ b/src/modules/skin/hotkeys.cpp @@ -21,38 +21,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "..\..\core\commonheaders.h" -#include - -#define DBMODULENAME "SkinHotKeys" -#define WM_HOTKEYUNREGISTERED (WM_USER+721) -typedef enum { HKT_GLOBAL, HKT_LOCAL, HKT_MANUAL, HKT_COUNT } THotkeyType; - -struct THotkeyItem -{ - THotkeyType type; - char *pszService, *pszName; // pszName is valid _only_ for "root" hotkeys - TCHAR *ptszSection, *ptszDescription; - LPARAM lParam; - WORD DefHotkey, Hotkey; - bool Enabled; - int hLangpack; - ATOM idHotkey; - - THotkeyItem *rootHotkey; - int nSubHotkeys; - bool allowSubHotkeys; - - bool OptChanged, OptDeleted, OptNew; - WORD OptHotkey; - THotkeyType OptType; - bool OptEnabled; - - bool UnregisterHotkey; // valid only during WM_APP message in options UI, used to remove unregistered hotkeys from options - - __inline TCHAR* getSection() const { return LangPackTranslateStringT(hLangpack, ptszSection); } - __inline TCHAR* getDescr() const { return LangPackTranslateStringT(hLangpack, ptszDescription); } -}; +#include +#include "skin.h" static int sttCompareHotkeys(const THotkeyItem *p1, const THotkeyItem *p2) { @@ -68,35 +39,25 @@ static int sttCompareHotkeys(const THotkeyItem *p1, const THotkeyItem *p2) return 0; } -static LIST hotkeys(10, sttCompareHotkeys); - -static void sttFreeHotkey(THotkeyItem *item); +LIST hotkeys(10, sttCompareHotkeys); +DWORD g_pid = 0; +HWND g_hwndHotkeyHost = NULL, g_hwndHkOptions = NULL; +HANDLE hEvChanged = 0; static BOOL bModuleInitialized = FALSE; -static HWND g_hwndHotkeyHost = NULL; -static HWND g_hwndOptions = NULL; -static DWORD g_pid = 0; -static int g_hotkeyCount = 0; -static HANDLE hEvChanged = 0; - -static LRESULT CALLBACK sttHotkeyHostWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - -static TCHAR *sttHokeyVkToName(WORD vkKey); -static void sttHotkeyEditCreate(HWND hwnd); -static void sttHotkeyEditDestroy(HWND hwnd); -static LRESULT CALLBACK sttHotkeyEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); -static void sttRegisterHotkeys(); -static void sttUnregisterHotkeys(); - -static INT_PTR svcHotkeySubclass(WPARAM wParam, LPARAM lParam); -static INT_PTR svcHotkeyUnsubclass(WPARAM wParam, LPARAM lParam); -static INT_PTR svcHotkeyRegister(WPARAM wParam, LPARAM lParam); -static INT_PTR svcHotkeyUnregister(WPARAM wParam, LPARAM lParam); -static INT_PTR svcHotkeyCheck(WPARAM wParam, LPARAM lParam); HHOOK hhkKeyboard = NULL; static LRESULT CALLBACK sttKeyboardProc(int code, WPARAM wParam, LPARAM lParam); +WORD GetHotkeyValue(INT_PTR idHotkey) +{ + for (int i = 0; i < hotkeys.getCount(); i++) + if (hotkeys[i]->idHotkey == idHotkey) + return hotkeys[i]->Enabled ? hotkeys[i]->Hotkey : 0; + + return 0; +} + static void sttWordToModAndVk(WORD w, BYTE *mod, BYTE *vk) { *mod = 0; @@ -118,7 +79,8 @@ static LRESULT CALLBACK sttHotkeyHostWndProc(HWND hwnd, UINT msg, WPARAM wParam, if (item->pszService && (wParam == item->idHotkey)) { CallService(item->pszService, 0, item->lParam); break; - } } + } + } return FALSE; } @@ -129,7 +91,6 @@ static LRESULT CALLBACK sttHotkeyHostWndProc(HWND hwnd, UINT msg, WPARAM wParam, static LRESULT CALLBACK sttKeyboardProc(int code, WPARAM wParam, LPARAM lParam) { if (code == HC_ACTION && !(HIWORD(lParam) & KF_UP)) { - int i; BYTE mod=0, vk=wParam; if (vk) { @@ -138,7 +99,7 @@ static LRESULT CALLBACK sttKeyboardProc(int code, WPARAM wParam, LPARAM lParam) if (GetAsyncKeyState(VK_SHIFT)) mod |= MOD_SHIFT; if (GetAsyncKeyState(VK_LWIN) || GetAsyncKeyState(VK_RWIN)) mod |= MOD_WIN; - for (i = 0; i < hotkeys.getCount(); i++) { + for (int i = 0; i < hotkeys.getCount(); i++) { THotkeyItem *item = hotkeys[i]; BYTE hkMod, hkVk; if (item->type != HKT_LOCAL) continue; @@ -155,13 +116,17 @@ static LRESULT CALLBACK sttKeyboardProc(int code, WPARAM wParam, LPARAM lParam) static INT_PTR svcHotkeySubclass(WPARAM wParam, LPARAM) { - sttHotkeyEditCreate((HWND)wParam); + HotkeyEditCreate((HWND)wParam); return 0; } static INT_PTR svcHotkeyUnsubclass(WPARAM wParam, LPARAM) { - sttHotkeyEditDestroy((HWND)wParam); + HWND hwnd = (HWND)wParam; + THotkeyBoxData *data = (THotkeyBoxData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (ULONG_PTR)data->oldWndProc); + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + mir_free(data); return 0; } @@ -217,7 +182,7 @@ static INT_PTR svcHotkeyRegister(WPARAM wParam, LPARAM lParam) item->lParam = desc->lParam; char buf[256]; - mir_snprintf(buf, SIZEOF(buf), "mir_hotkey_%d_%d", g_pid, g_hotkeyCount++); + mir_snprintf(buf, SIZEOF(buf), "mir_hotkey_%d_%d", g_pid, hotkeys.getCount()+1); item->idHotkey = GlobalAddAtomA(buf); if (item->type == HKT_GLOBAL) { if (item->Enabled) { @@ -271,12 +236,12 @@ static INT_PTR svcHotkeyUnregister(WPARAM, LPARAM lParam) !strncmp(pszCurrentName, pszNamePrefix, cbNamePrefix); } - if (g_hwndOptions) - SendMessage(g_hwndOptions, WM_HOTKEYUNREGISTERED, 0, 0); + if (g_hwndHkOptions) + SendMessage(g_hwndHkOptions, WM_HOTKEYUNREGISTERED, 0, 0); for (i = 0; i < hotkeys.getCount(); ++i) if (hotkeys[i]->UnregisterHotkey) { - sttFreeHotkey(hotkeys[i]); + FreeHotkey(hotkeys[i]); List_Remove((SortedList *)&hotkeys, i); --i; } @@ -315,7 +280,7 @@ static INT_PTR svcHotkeyCheck(WPARAM wParam, LPARAM lParam) return 0; } -static void sttFreeHotkey(THotkeyItem *item) +void FreeHotkey(THotkeyItem *item) { if (item->type == HKT_GLOBAL && item->Enabled) UnregisterHotKey(g_hwndHotkeyHost, item->idHotkey); @@ -327,10 +292,9 @@ static void sttFreeHotkey(THotkeyItem *item) mir_free(item); } -static void sttRegisterHotkeys() +void RegisterHotkeys() { - int i; - for (i = 0; i < hotkeys.getCount(); i++) { + for (int i = 0; i < hotkeys.getCount(); i++) { THotkeyItem *item = hotkeys[i]; UnregisterHotKey(g_hwndHotkeyHost, item->idHotkey); if (item->type != HKT_GLOBAL) continue; @@ -340,1042 +304,18 @@ static void sttRegisterHotkeys() if (vk) RegisterHotKey(g_hwndHotkeyHost, item->idHotkey, mod, vk); } } } -static void sttUnregisterHotkeys() +void UnregisterHotkeys() { - int i; - for (i = 0; i < hotkeys.getCount(); i++) { + for (int i = 0; i < hotkeys.getCount(); i++) { THotkeyItem *item = hotkeys[i]; if (item->type == HKT_GLOBAL && item->Enabled) UnregisterHotKey(g_hwndHotkeyHost, item->idHotkey); } } -/////////////////////////////////////////////////////////////////////////////// -// Hotkey control -typedef struct -{ - WNDPROC oldWndProc; - BYTE shift; - BYTE key; -} - THotkeyBoxData; - -static TCHAR *sttHokeyVkToName(WORD vkKey) -{ - static TCHAR buf[256] = {0}; - DWORD code = MapVirtualKey(vkKey, 0) << 16; - - switch (vkKey) - { - case 0: - case VK_CONTROL: - case VK_SHIFT: - case VK_MENU: - case VK_LWIN: - case VK_RWIN: - case VK_PAUSE: - case VK_CANCEL: - case VK_NUMLOCK: - case VK_CAPITAL: - case VK_SCROLL: - return _T(""); - - case VK_DIVIDE: - case VK_INSERT: - case VK_HOME: - case VK_PRIOR: - case VK_DELETE: - case VK_END: - case VK_NEXT: - case VK_LEFT: - case VK_RIGHT: - case VK_UP: - case VK_DOWN: - code |= (1UL << 24); - } - - GetKeyNameText(code, buf, 256); - return buf; -} - -void HotkeyToName(TCHAR *buf, int size, BYTE shift, BYTE key) -{ - mir_sntprintf(buf, size, _T("%s%s%s%s%s"), - (shift & HOTKEYF_CONTROL) ? _T("Ctrl + ") : _T(""), - (shift & HOTKEYF_ALT) ? _T("Alt + ") : _T(""), - (shift & HOTKEYF_SHIFT) ? _T("Shift + ") : _T(""), - (shift & HOTKEYF_EXT) ? _T("Win + ") : _T(""), - sttHokeyVkToName(key)); -} - -WORD GetHotkeyValue(INT_PTR idHotkey) -{ - for (int i = 0; i < hotkeys.getCount(); i++) - if (hotkeys[i]->idHotkey == idHotkey) - return hotkeys[i]->Enabled ? hotkeys[i]->Hotkey : 0; - - return 0; -} - -static LRESULT CALLBACK sttHotkeyEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - THotkeyBoxData *data = (THotkeyBoxData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - BOOL bKeyDown = FALSE; - if ( !data) return 0; - - switch (msg) { - case HKM_GETHOTKEY: - return data->key ? MAKEWORD(data->key, data->shift) : 0; - - case HKM_SETHOTKEY: - { - TCHAR buf[256] = {0}; - data->key = (BYTE)LOWORD(wParam); - data->shift = (BYTE)HIWORD(wParam); - HotkeyToName(buf, SIZEOF(buf), data->shift, data->key); - SetWindowText(hwnd, buf); - return 0; - } - - case WM_GETDLGCODE: - return DLGC_WANTALLKEYS; - - case WM_KILLFOCUS: - break; - - case WM_CHAR: - case WM_SYSCHAR: - case WM_PASTE: - case WM_CONTEXTMENU: - return TRUE; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - bKeyDown = TRUE; - - case WM_KEYUP: - case WM_SYSKEYUP: - { - TCHAR buf[256] = {0}; - - BYTE shift = 0; - BYTE key = wParam; - TCHAR *name = sttHokeyVkToName(key); - if ( !*name || !bKeyDown) key = 0; - - if (GetAsyncKeyState(VK_CONTROL)) shift |= HOTKEYF_CONTROL; - if (GetAsyncKeyState(VK_MENU)) shift |= HOTKEYF_ALT; - if (GetAsyncKeyState(VK_SHIFT)) shift |= HOTKEYF_SHIFT; - if (GetAsyncKeyState(VK_LWIN) || GetAsyncKeyState(VK_RWIN)) shift |= HOTKEYF_EXT; - - if (bKeyDown || !data->key) { - data->shift = shift; - data->key = key; - } - - HotkeyToName(buf, SIZEOF(buf), data->shift, data->key); - SetWindowText(hwnd, buf); - - if (bKeyDown && data->key) - SendMessage(GetParent(hwnd), WM_COMMAND, MAKELONG(GetWindowLongPtr(hwnd, GWL_ID), 0), (LPARAM)hwnd); - return TRUE; - } - - case WM_DESTROY: - { - WNDPROC saveOldWndProc = data->oldWndProc; - SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)data->oldWndProc); - SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); - mir_free(data); - return CallWindowProc(saveOldWndProc, hwnd, msg, wParam, lParam); - } } - - return CallWindowProc(data->oldWndProc, hwnd, msg, wParam, lParam); -} - -static void sttHotkeyEditCreate(HWND hwnd) -{ - THotkeyBoxData *data = (THotkeyBoxData *)mir_alloc(sizeof(THotkeyBoxData)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (ULONG_PTR)data); - data->oldWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (ULONG_PTR)sttHotkeyEditProc); -} - -static void sttHotkeyEditDestroy(HWND hwnd) -{ - THotkeyBoxData *data = (THotkeyBoxData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - SetWindowLongPtr(hwnd, GWLP_WNDPROC, (ULONG_PTR)data->oldWndProc); - SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); - mir_free(data); -} - -/////////////////////////////////////////////////////////////////////////////// -// Options - -enum { COL_NAME, COL_TYPE, COL_KEY, COL_RESET, COL_ADDREMOVE }; - -static void sttOptionsSetupItem(HWND hwndList, int idx, THotkeyItem *item) -{ - TCHAR buf[256]; - LVITEM lvi = {0}; - lvi.iItem = idx; - - if ( !item->rootHotkey) { - lvi.mask = LVIF_TEXT|LVIF_IMAGE; - lvi.iSubItem = COL_NAME; - lvi.pszText = item->getDescr(); - lvi.iImage = item->OptType; - ListView_SetItem(hwndList, &lvi); - - ListView_SetCheckState(hwndList, lvi.iItem, item->Enabled); - } - - lvi.mask = LVIF_TEXT; - lvi.iSubItem = COL_KEY; - HotkeyToName(buf, SIZEOF(buf), HIBYTE(item->OptHotkey), LOBYTE(item->OptHotkey)); - lvi.pszText = buf; - ListView_SetItem(hwndList, &lvi); - - if (item->rootHotkey) { - lvi.mask = LVIF_IMAGE; - lvi.iSubItem = COL_TYPE; - lvi.iImage = item->OptType; - ListView_SetItem(hwndList, &lvi); - } - - lvi.mask = LVIF_IMAGE; - lvi.iSubItem = COL_RESET; - lvi.iImage = (item->Hotkey != item->OptHotkey) ? 5 : -1; - ListView_SetItem(hwndList, &lvi); - - lvi.mask = LVIF_IMAGE|LVIF_TEXT; - lvi.iSubItem = COL_ADDREMOVE; - if (item->rootHotkey) { - lvi.iImage = 4; - lvi.pszText = TranslateT("Remove shortcut"); - } - else { - lvi.iImage = 3; - lvi.pszText = TranslateT("Add another shortcut"); - } - ListView_SetItem(hwndList, &lvi); -} - -static void sttOptionsDeleteHotkey(HWND hwndList, int idx, THotkeyItem *item) -{ - item->OptDeleted = TRUE; - ListView_DeleteItem(hwndList, idx); - if (item->rootHotkey) - item->rootHotkey->OptChanged = TRUE; -} - -static int CALLBACK sttOptionsSortList(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) -{ - TCHAR title1[256] = {0}, title2[256] = {0}; - THotkeyItem *item1 = NULL, *item2 = NULL; - LVITEM lvi = {0}; - int res; - - lvi.mask = LVIF_TEXT|LVIF_PARAM; - lvi.iItem = lParam1; - lvi.pszText = title1; - lvi.cchTextMax = SIZEOF(title1); - if (ListView_GetItem((HWND)lParamSort, &lvi)) - item1 = (THotkeyItem *)lvi.lParam; - - lvi.mask = LVIF_TEXT|LVIF_PARAM; - lvi.iItem = lParam2; - lvi.pszText = title2; - lvi.cchTextMax = SIZEOF(title2); - if (ListView_GetItem((HWND)lParamSort, &lvi)) - item2 = (THotkeyItem *)lvi.lParam; - - if ( !item1 && !item2) - return lstrcmp(title1, title2); - - if ( !item1) { - if (res = lstrcmp(title1, item2->getSection())) - return res; - return -1; - } - - if ( !item2) { - if (res = lstrcmp(item1->getSection(), title2)) - return res; - return 1; - } - - if (res = lstrcmp(item1->getSection(), item2->getSection())) return res; - if (res = lstrcmp(item1->getDescr(), item2->getDescr())) return res; - if (!item1->rootHotkey && item2->rootHotkey) return -1; - if (item1->rootHotkey && !item2->rootHotkey) return 1; - return 0; -} - -static void sttOptionsAddHotkey(HWND hwndList, THotkeyItem *item) -{ - char buf[256]; - LVITEM lvi = {0}; - - THotkeyItem *newItem = (THotkeyItem *)mir_alloc(sizeof(THotkeyItem)); - newItem->pszName = NULL; - newItem->pszService = item->pszService ? mir_strdup(item->pszService) : NULL; - newItem->ptszSection = mir_tstrdup(item->ptszSection); - newItem->ptszDescription = mir_tstrdup(item->ptszDescription); - newItem->lParam = item->lParam; - mir_snprintf(buf, SIZEOF(buf), "mir_hotkey_%d_%d", g_pid, g_hotkeyCount++); - newItem->idHotkey = GlobalAddAtomA(buf); - newItem->rootHotkey = item; - newItem->Hotkey = newItem->DefHotkey = newItem->OptHotkey = 0; - newItem->type = newItem->OptType = item->OptType; - newItem->Enabled = newItem->OptEnabled = TRUE; - newItem->OptChanged = newItem->OptDeleted = FALSE; - newItem->OptNew = TRUE; - - hotkeys.insert(newItem); - - SendMessage(hwndList, WM_SETREDRAW, FALSE, 0); - - lvi.mask |= LVIF_PARAM; - lvi.lParam = (LPARAM)newItem; - sttOptionsSetupItem(hwndList, ListView_InsertItem(hwndList, &lvi), newItem); - ListView_SortItemsEx(hwndList, sttOptionsSortList, (LPARAM)hwndList); - - SendMessage(hwndList, WM_SETREDRAW, TRUE, 0); - RedrawWindow(hwndList, NULL, NULL, RDW_INVALIDATE); - - item->OptChanged = TRUE; -} - -static void sttOptionsSetChanged(THotkeyItem *item) -{ - item->OptChanged = TRUE; - if (item->rootHotkey) - item->rootHotkey->OptChanged = TRUE; -} - -static void sttOptionsSaveItem(THotkeyItem *item) -{ - int i; - char buf[MAXMODULELABELLENGTH]; - - if (item->rootHotkey) return; - if ( !item->OptChanged) return; - - item->Hotkey = item->OptHotkey; - item->type = item->OptType; - item->Enabled = item->OptEnabled; - - DBWriteContactSettingWord(NULL, DBMODULENAME, item->pszName, item->Hotkey); - DBWriteContactSettingByte(NULL, DBMODULENAME "Off", item->pszName, (BYTE)!item->Enabled); - if (item->type != HKT_MANUAL) - DBWriteContactSettingByte(NULL, DBMODULENAME "Types", item->pszName, (BYTE)item->type); - - item->nSubHotkeys = 0; - for (i = 0; i < hotkeys.getCount(); i++) { - THotkeyItem *subItem = hotkeys[i]; - if (subItem->rootHotkey == item) { - subItem->Hotkey = subItem->OptHotkey; - subItem->type = subItem->OptType; - - mir_snprintf(buf, SIZEOF(buf), "%s$%d", item->pszName, item->nSubHotkeys); - DBWriteContactSettingWord(NULL, DBMODULENAME, buf, subItem->Hotkey); - if (subItem->type != HKT_MANUAL) - DBWriteContactSettingByte(NULL, DBMODULENAME "Types", buf, (BYTE)subItem->type); - - ++item->nSubHotkeys; - } } - - mir_snprintf(buf, SIZEOF(buf), "%s$count", item->pszName); - DBWriteContactSettingDword(NULL, DBMODULENAME, buf, item->nSubHotkeys); -} - -static void sttBuildHotkeyList(HWND hwndList) -{ - int i, nItems=0; - ListView_DeleteAllItems(hwndList); - - for (i = 0; i < hotkeys.getCount(); i++) { - LVITEM lvi = {0}; - THotkeyItem *item = hotkeys[i]; - - if (item->OptDeleted) - continue; - - if ( !i || lstrcmp(item->ptszSection, hotkeys[i-1]->ptszSection)) { - lvi.mask = LVIF_TEXT|LVIF_PARAM; - lvi.iItem = nItems++; - lvi.iSubItem = 0; - lvi.lParam = 0; - lvi.pszText = item->getSection(); - ListView_InsertItem(hwndList, &lvi); - ListView_SetCheckState(hwndList, lvi.iItem, TRUE); - - lvi.mask = LVIF_TEXT; - lvi.iSubItem = 1; - lvi.pszText = item->ptszSection; - ListView_SetItem(hwndList, &lvi); - - lvi.iSubItem = 0; - } - - lvi.mask = LVIF_PARAM | LVIF_INDENT; - lvi.iIndent = 1; - lvi.iItem = nItems++; - lvi.lParam = (LPARAM)item; - ListView_InsertItem(hwndList, &lvi); - sttOptionsSetupItem(hwndList, nItems-1, item); - } - - ListView_SortItemsEx(hwndList, sttOptionsSortList, (LPARAM)hwndList); -} - -static void sttOptionsStartEdit(HWND hwndDlg, HWND hwndHotkey) -{ - LVITEM lvi; - THotkeyItem *item; - int iItem = ListView_GetNextItem(hwndHotkey, -1, LVNI_SELECTED); - if (iItem < 0) return; - - lvi.mask = LVIF_PARAM; - lvi.iItem = iItem; - ListView_GetItem(hwndHotkey, &lvi); - - if (item = (THotkeyItem *)lvi.lParam) { - RECT rc; - ListView_GetSubItemRect(hwndHotkey, iItem, COL_KEY, LVIR_BOUNDS, &rc); - MapWindowPoints(hwndHotkey, hwndDlg, (LPPOINT)&rc, 2); - SendDlgItemMessage(hwndDlg, IDC_HOTKEY, HKM_SETHOTKEY, MAKELONG(LOBYTE(item->OptHotkey), HIBYTE(item->OptHotkey)), 0); - - SetWindowPos(hwndHotkey, HWND_BOTTOM, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); - SetWindowPos(GetDlgItem(hwndDlg, IDC_HOTKEY), HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); - RedrawWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), NULL, NULL, RDW_INVALIDATE); - - SetFocus(GetDlgItem(hwndDlg, IDC_HOTKEY)); - RedrawWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), NULL, NULL, RDW_INVALIDATE); - } -} - -static void sttOptionsDrawTextChunk(HDC hdc, TCHAR *text, RECT *rc) -{ - SIZE sz; - DrawText(hdc, text, lstrlen(text), rc, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER|DT_WORD_ELLIPSIS); - GetTextExtentPoint32(hdc, text, lstrlen(text), &sz); - rc->left += sz.cx; -} - -static INT_PTR CALLBACK sttOptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static BOOL initialized = FALSE; - static int colWidth = 0; - static WORD currentLanguage = 0; - - HWND hwndHotkey = GetDlgItem(hwndDlg, IDC_LV_HOTKEYS); - - switch (msg) { - case WM_INITDIALOG: - initialized = FALSE; - - TranslateDialogDefault(hwndDlg); - - sttHotkeyEditCreate(GetDlgItem(hwndDlg, IDC_HOTKEY)); - { - HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK + (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 3, 1); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_WINDOWS); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_MIRANDA); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_WINDOW); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_ADDCONTACT); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_DELETE); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_UNDO); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_GROUPOPEN); - ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_GROUPSHUT); - ListView_SetImageList(hwndHotkey, hIml, LVSIL_SMALL); - } - ListView_SetExtendedListViewStyle(hwndHotkey, LVS_EX_CHECKBOXES|LVS_EX_SUBITEMIMAGES|LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER|LVS_EX_INFOTIP); - { - RECT rc; - GetClientRect(hwndHotkey, &rc); - colWidth = rc.right - GetSystemMetrics(SM_CXHTHUMB) - 3*GetSystemMetrics(SM_CXSMICON) - 5; - - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = colWidth * 2 / 3; - ListView_InsertColumn(hwndHotkey, COL_NAME, &lvc); - lvc.cx = GetSystemMetrics(SM_CXSMICON); - ListView_InsertColumn(hwndHotkey, COL_TYPE, &lvc); - lvc.cx = colWidth / 3; - ListView_InsertColumn(hwndHotkey, COL_KEY, &lvc); - lvc.cx = GetSystemMetrics(SM_CXSMICON); - ListView_InsertColumn(hwndHotkey, COL_RESET, &lvc); - lvc.cx = GetSystemMetrics(SM_CXSMICON); - ListView_InsertColumn(hwndHotkey, COL_ADDREMOVE, &lvc); - - for (int i = 0; i < hotkeys.getCount(); i++) { - THotkeyItem *item = hotkeys[i]; - - item->OptChanged = FALSE; - item->OptDeleted = item->OptNew = FALSE; - item->OptEnabled = item->Enabled; - item->OptHotkey = item->Hotkey; - item->OptType = item->type; - } - - currentLanguage = LOWORD(GetKeyboardLayout(0)); - sttBuildHotkeyList(hwndHotkey); - } - SetTimer(hwndDlg, 1024, 1000, NULL); - initialized = TRUE; - { - /* load group states */ - int count = ListView_GetItemCount(hwndHotkey); - TCHAR buf[128]; - LVITEM lvi = {0}; - lvi.pszText = buf; - lvi.cchTextMax = SIZEOF(buf); - for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { - char *szSetting; - - lvi.mask = LVIF_PARAM; - lvi.iSubItem = 0; - ListView_GetItem(hwndHotkey, &lvi); - if (lvi.lParam) continue; - - lvi.mask = LVIF_TEXT; - lvi.iSubItem = 1; - ListView_GetItem(hwndHotkey, &lvi); - - szSetting = mir_t2a(lvi.pszText); - - ListView_SetCheckState(hwndHotkey, lvi.iItem, - DBGetContactSettingByte(NULL, DBMODULENAME "UI", szSetting, TRUE)); - - mir_free(szSetting); - } - } - - g_hwndOptions = hwndDlg; - break; - - case WM_DESTROY: - { - int count = ListView_GetItemCount(hwndHotkey); - TCHAR buf[128]; - LVITEM lvi = {0}; - - g_hwndOptions = NULL; - - KillTimer(hwndDlg, 1024); - - lvi.pszText = buf; - lvi.cchTextMax = SIZEOF(buf); - for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { - char *szSetting; - - lvi.mask = LVIF_PARAM; - lvi.iSubItem = 0; - ListView_GetItem(hwndHotkey, &lvi); - if (lvi.lParam) continue; - - lvi.mask = LVIF_TEXT; - lvi.iSubItem = 1; - ListView_GetItem(hwndHotkey, &lvi); - - szSetting = mir_t2a(lvi.pszText); - - DBWriteContactSettingByte(NULL, DBMODULENAME "UI", szSetting, - (BYTE) ListView_GetCheckState(hwndHotkey, lvi.iItem)); - - mir_free(szSetting); - } - break; - } - - case WM_TIMER: - { - WORD newLanguage; - int count; - LVITEM lvi = {0}; - - if ( !initialized) break; - - newLanguage = LOWORD(GetKeyboardLayout(0)); - if (newLanguage == currentLanguage) break; - - count = ListView_GetItemCount(hwndHotkey); - lvi.mask = LVIF_PARAM; - for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { - ListView_GetItem(hwndHotkey, &lvi); - if ( !lvi.lParam) continue; - - sttOptionsSetupItem(hwndHotkey, lvi.iItem, (THotkeyItem *)lvi.lParam); - } - - currentLanguage = newLanguage; - break; - } - - case WM_HOTKEYUNREGISTERED: - { - int count; - LVITEM lvi = {0}; - - count = ListView_GetItemCount(hwndHotkey); - lvi.mask = LVIF_PARAM; - for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { - ListView_GetItem(hwndHotkey, &lvi); - if ( !lvi.lParam) continue; - - if (((THotkeyItem *)lvi.lParam)->UnregisterHotkey) { - ListView_DeleteItem(hwndHotkey, lvi.iItem); - --lvi.iItem; - --count; - } - } - break; - } - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; - RECT rc = lpdis->rcItem; - int prefix = 65; - int width = (lpdis->rcItem.right - lpdis->rcItem.left - prefix) / 3; - rc.left += 5; - - HIMAGELIST hIml = ListView_GetImageList(hwndHotkey, LVSIL_SMALL); - - if (lpdis->CtlID == IDC_CANVAS2) { - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Scope:"), &rc); - - rc.left = prefix + width * 0; - ImageList_Draw(hIml, 0, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); - rc.left += 20; - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("System"), &rc); - - rc.left = prefix + width * 1; - ImageList_Draw(hIml, 1, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); - rc.left += 20; - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Miranda"), &rc); - - rc.left = prefix + width * 2; - ImageList_Draw(hIml, 2, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); - rc.left += 20; - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Window"), &rc); - - return TRUE; - } - - if (lpdis->CtlID == IDC_CANVAS) { - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Actions:"), &rc); - rc.left += 10; - - rc.left = prefix + width * 0; - ImageList_Draw(hIml, 5, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); - rc.left += 20; - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Undo"), &rc); - - rc.left = prefix + width * 1; - ImageList_Draw(hIml, 3, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); - rc.left += 20; - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Add binding"), &rc); - - rc.left = prefix + width * 2; - ImageList_Draw(hIml, 4, lpdis->hDC, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); - rc.left += 20; - sttOptionsDrawTextChunk(lpdis->hDC, TranslateT("Remove"), &rc); - - return TRUE; - } - - break; - } - - case WM_COMMAND: - if ((LOWORD(wParam) == IDC_HOTKEY) && ((HIWORD(wParam) == EN_KILLFOCUS) || (HIWORD(wParam) == 0))) { - LVITEM lvi; - THotkeyItem *item; - WORD wHotkey = (WORD)SendDlgItemMessage(hwndDlg, IDC_HOTKEY, HKM_GETHOTKEY, 0, 0); - - ShowWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), SW_HIDE); - SetFocus(hwndHotkey); - if ( !wHotkey || (wHotkey == VK_ESCAPE) || (HIWORD(wParam) != 0)) - break; - - lvi.mask = LVIF_PARAM; - lvi.iItem = ListView_GetNextItem(hwndHotkey, -1, LVNI_SELECTED); - if (lvi.iItem >= 0) { - ListView_GetItem(hwndHotkey, &lvi); - if (item = (THotkeyItem *)lvi.lParam) { - item->OptHotkey = wHotkey; - - sttOptionsSetupItem(hwndHotkey, lvi.iItem, item); - sttOptionsSetChanged(item); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } } } - break; - - case WM_CONTEXTMENU: - if (GetWindowLongPtr((HWND)wParam, GWL_ID) == IDC_LV_HOTKEYS) - { - HWND hwndList = (HWND)wParam; - POINT pt = { (signed short)LOWORD(lParam), (signed short)HIWORD(lParam) }; - LVITEM lvi = {0}; - THotkeyItem *item = NULL; - - lvi.iItem = ListView_GetNextItem(hwndHotkey, -1, LVNI_SELECTED); - if (lvi.iItem < 0) return FALSE; - - lvi.mask = LVIF_PARAM; - ListView_GetItem(hwndList, &lvi); - if ( !(item = (THotkeyItem *)lvi.lParam)) return FALSE; - - if ((pt.x == -1) && (pt.y == -1)) { - RECT rc; - ListView_GetItemRect(hwndList, lvi.iItem, &rc, LVIR_LABEL); - pt.x = rc.left; - pt.y = rc.bottom; - ClientToScreen(hwndList, &pt); - } - - { - enum { MI_CANCEL, MI_CHANGE, MI_SYSTEM, MI_LOCAL, MI_ADD, MI_REMOVE, MI_REVERT }; - - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_DEFAULT; - - HMENU hMenu = CreatePopupMenu(); - AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_CHANGE, TranslateT("Modify")); - SetMenuItemInfo(hMenu, (UINT_PTR)MI_CHANGE, FALSE, &mii); - if (item->type != HKT_MANUAL) { - AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); - AppendMenu(hMenu, MF_STRING| - ((item->OptType == HKT_GLOBAL) ? MF_CHECKED : 0), - (UINT_PTR)MI_SYSTEM, TranslateT("System scope")); - AppendMenu(hMenu, MF_STRING| - ((item->OptType == HKT_LOCAL) ? MF_CHECKED : 0), - (UINT_PTR)MI_LOCAL, TranslateT("Miranda scope")); - } - AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); - if ( !item->rootHotkey) - AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_ADD, TranslateT("Add binding")); - else - AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_REMOVE, TranslateT("Remove")); - if (item->Hotkey != item->OptHotkey) { - AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); - AppendMenu(hMenu, MF_STRING, (UINT_PTR)MI_REVERT, TranslateT("Undo")); - } - - switch (TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) { - case MI_CHANGE: - sttOptionsStartEdit(hwndDlg, hwndHotkey); - break; - case MI_SYSTEM: - item->OptType = HKT_GLOBAL; - sttOptionsSetupItem(hwndList, lvi.iItem, item); - sttOptionsSetChanged(item); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - case MI_LOCAL: - item->OptType = HKT_LOCAL; - sttOptionsSetupItem(hwndList, lvi.iItem, item); - sttOptionsSetChanged(item); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - case MI_ADD: - initialized = FALSE; - sttOptionsAddHotkey(hwndList, item); - initialized = FALSE; - break; - case MI_REMOVE: - sttOptionsDeleteHotkey(hwndList, lvi.iItem, item); - break; - case MI_REVERT: - item->OptHotkey = item->Hotkey; - sttOptionsSetupItem(hwndList, lvi.iItem, item); - break; - } - DestroyMenu(hMenu); - } - - break; - } - break; - - case WM_NOTIFY: - { - LPNMHDR lpnmhdr = (LPNMHDR)lParam; - switch (lpnmhdr->idFrom) { - case 0: - { - int i; - - if ((lpnmhdr->code != PSN_APPLY) && (lpnmhdr->code != PSN_RESET)) - break; - - sttUnregisterHotkeys(); - - for (i = 0; i < hotkeys.getCount(); i++) { - THotkeyItem *item = hotkeys[i]; - if (item->OptNew && item->OptDeleted || - item->rootHotkey && !item->OptHotkey || - (lpnmhdr->code == PSN_APPLY) && item->OptDeleted || - (lpnmhdr->code == PSN_RESET) && item->OptNew) - { - sttFreeHotkey(item); - hotkeys.remove(i--); - } - } - - if (lpnmhdr->code == PSN_APPLY) { - LVITEM lvi = {0}; - int count = ListView_GetItemCount(hwndHotkey); - - for (i = 0; i < hotkeys.getCount(); i++) - sttOptionsSaveItem(hotkeys[i]); - - lvi.mask = LVIF_IMAGE; - lvi.iSubItem = COL_RESET; - lvi.iImage = -1; - for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) - ListView_SetItem(hwndHotkey, &lvi); - } - - sttRegisterHotkeys(); - - NotifyEventHooks(hEvChanged, 0, 0); - break; - } - case IDC_LV_HOTKEYS: - switch (lpnmhdr->code) { - case NM_CLICK: - { - THotkeyItem *item = NULL; - LPNMITEMACTIVATE lpnmia = (LPNMITEMACTIVATE)lParam; - LVHITTESTINFO lvhti = {0}; - LVITEM lvi = {0}; - - lvi.mask = LVIF_PARAM|LVIF_IMAGE; - lvi.iItem = lpnmia->iItem; - ListView_GetItem(lpnmia->hdr.hwndFrom, &lvi); - item = (THotkeyItem *)lvi.lParam; - - lvhti.pt = lpnmia->ptAction; - lvhti.iItem = lpnmia->iItem; - lvhti.iSubItem = lpnmia->iSubItem; - ListView_HitTest(lpnmia->hdr.hwndFrom, &lvhti); - - if (item && - ( !item->rootHotkey && (lpnmia->iSubItem == COL_NAME) && ((lvhti.flags & LVHT_ONITEM) == LVHT_ONITEMICON) || - item->rootHotkey && (lpnmia->iSubItem == COL_TYPE)) && - ((item->OptType == HKT_GLOBAL) || (item->OptType == HKT_LOCAL))) - { - item->OptType = (item->OptType == HKT_GLOBAL) ? HKT_LOCAL : HKT_GLOBAL; - sttOptionsSetupItem(lpnmia->hdr.hwndFrom, lpnmia->iItem, item); - sttOptionsSetChanged(item); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - else if (item && (lpnmia->iSubItem == COL_RESET)) { - item->OptHotkey = item->Hotkey; - sttOptionsSetupItem(lpnmia->hdr.hwndFrom, lpnmia->iItem, item); - } - else if (item && (lpnmia->iSubItem == COL_ADDREMOVE)) { - if (item->rootHotkey) - sttOptionsDeleteHotkey(lpnmia->hdr.hwndFrom, lpnmia->iItem, item); - else { - initialized = FALSE; - sttOptionsAddHotkey(lpnmia->hdr.hwndFrom, item); - initialized = TRUE; - } - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - break; - } - case LVN_KEYDOWN: - { - LPNMLVKEYDOWN param = (LPNMLVKEYDOWN)lParam; - if ((param->wVKey == VK_SUBTRACT) || (param->wVKey == VK_LEFT) || - (param->wVKey == VK_ADD) || (param->wVKey == VK_RIGHT)) - { - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM; - lvi.iItem = ListView_GetNextItem(lpnmhdr->hwndFrom, -1, LVNI_SELECTED); - if (lvi.iItem < 0) break; - ListView_GetItem(lpnmhdr->hwndFrom, &lvi); - if (lvi.lParam) break; - - if ((param->wVKey == VK_ADD) || (param->wVKey == VK_RIGHT)) - { - ListView_SetCheckState(lpnmhdr->hwndFrom, lvi.iItem, TRUE); - } else - // if ((param->wVKey == VK_SUBTRACT) || (param->wVKey == VK_LEFT)) - { - ListView_SetCheckState(lpnmhdr->hwndFrom, lvi.iItem, FALSE); - } - } - else if (param->wVKey == VK_F2) - sttOptionsStartEdit(hwndDlg, hwndHotkey); - - break; - } - case LVN_ITEMACTIVATE: - { - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM; - lvi.iItem = ListView_GetNextItem(lpnmhdr->hwndFrom, -1, LVNI_SELECTED); - if (lvi.iItem < 0) break; - ListView_GetItem(lpnmhdr->hwndFrom, &lvi); - - if (lvi.lParam) - sttOptionsStartEdit(hwndDlg, hwndHotkey); - else - ListView_SetCheckState(lpnmhdr->hwndFrom, lvi.iItem, !ListView_GetCheckState(lpnmhdr->hwndFrom, lvi.iItem)); - break; - } - case LVN_ITEMCHANGED: - { - LPNMLISTVIEW param = (LPNMLISTVIEW)lParam; - THotkeyItem *item = (THotkeyItem *)param->lParam; - if ( !initialized || (param->uNewState>>12 == param->uOldState>>12)) - break; - - if (item && !item->rootHotkey) { - item->OptEnabled = ListView_GetCheckState(lpnmhdr->hwndFrom, param->iItem) ? 1 : 0; - sttOptionsSetChanged(item); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - else if ( !item) { - TCHAR buf[256]; - LVITEM lvi = {0}; - lvi.mask = LVIF_TEXT; - lvi.iItem = param->iItem; - lvi.pszText = buf; - lvi.cchTextMax = SIZEOF(buf); - ListView_GetItem(lpnmhdr->hwndFrom, &lvi); - - if (param->uNewState>>12 == 1) { - int count = ListView_GetItemCount(lpnmhdr->hwndFrom); - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM; - for (lvi.iItem = 0; lvi.iItem < count; ++lvi.iItem) { - THotkeyItem *item; - ListView_GetItem(lpnmhdr->hwndFrom, &lvi); - item = (THotkeyItem *)lvi.lParam; - if ( !item) continue; - if ( !lstrcmp( item->getSection(), buf)) { - ListView_DeleteItem(lpnmhdr->hwndFrom, lvi.iItem); - --lvi.iItem; - --count; - } } - } - else if (param->uNewState>>12 == 2) { - int i, nItems = ListView_GetItemCount(lpnmhdr->hwndFrom); - initialized = FALSE; - for (i = 0; i < hotkeys.getCount(); ++i) { - LVITEM lvi = {0}; - THotkeyItem *item = hotkeys[i]; - - if (item->OptDeleted) - continue; - if ( lstrcmp(buf, item->getSection())) - continue; - - lvi.mask = LVIF_PARAM|LVIF_INDENT; - lvi.iIndent = 1; - lvi.iItem = nItems++; - lvi.lParam = (LPARAM)item; - ListView_InsertItem(lpnmhdr->hwndFrom, &lvi); - sttOptionsSetupItem(lpnmhdr->hwndFrom, nItems-1, item); - } - ListView_SortItemsEx(lpnmhdr->hwndFrom, sttOptionsSortList, (LPARAM)lpnmhdr->hwndFrom); - initialized = TRUE; - } - } - break; - } - case NM_CUSTOMDRAW: - { - NMLVCUSTOMDRAW *param = (NMLVCUSTOMDRAW *) lParam; - switch (param->nmcd.dwDrawStage) { - case CDDS_PREPAINT: - case CDDS_ITEMPREPAINT: - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_NOTIFYSUBITEMDRAW); - return TRUE; - - case CDDS_SUBITEM|CDDS_ITEMPREPAINT: - { - THotkeyItem *item; - TCHAR buf[256]; - LVITEM lvi = {0}; - lvi.mask = LVIF_TEXT|LVIF_PARAM; - lvi.iItem = param->nmcd.dwItemSpec; - lvi.pszText = buf; - lvi.cchTextMax = SIZEOF(buf); - ListView_GetItem(lpnmhdr->hwndFrom, &lvi); - item = (THotkeyItem *)lvi.lParam; - - if ( !item) { - RECT rc; - HFONT hfnt; - - ListView_GetSubItemRect(lpnmhdr->hwndFrom, param->nmcd.dwItemSpec, param->iSubItem, LVIR_BOUNDS, &rc); - FillRect(param->nmcd.hdc, &rc, GetSysColorBrush(param->nmcd.uItemState&CDIS_SELECTED ? COLOR_HIGHLIGHT : COLOR_WINDOW)); - SetTextColor(param->nmcd.hdc, GetSysColor(param->nmcd.uItemState&CDIS_SELECTED ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT)); - - if (param->iSubItem == 0) { - rc.left += 3; - HIMAGELIST hIml = ListView_GetImageList(hwndHotkey, LVSIL_SMALL); - ImageList_Draw(hIml, - ListView_GetCheckState(hwndHotkey, lvi.iItem) ? 6 : 7, - param->nmcd.hdc, rc.left, (rc.top+rc.bottom-16)/2, ILD_TRANSPARENT); - rc.left += 18; - hfnt = (HFONT)SelectObject(param->nmcd.hdc, (HFONT)SendMessage(GetParent(hwndDlg), PSM_GETBOLDFONT, 0, 0)); - DrawText(param->nmcd.hdc, buf, -1, &rc, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER); - SelectObject(param->nmcd.hdc, hfnt); - } - - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT); - return TRUE; - } - - if (item->rootHotkey && (param->iSubItem == 0)) { - RECT rc; - ListView_GetSubItemRect(lpnmhdr->hwndFrom, param->nmcd.dwItemSpec, param->iSubItem, LVIR_BOUNDS, &rc); - FillRect(param->nmcd.hdc, &rc, GetSysColorBrush(COLOR_WINDOW)); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT); - return TRUE; - } - break; - } } - break; - } - break; - } } - break; - } /* case WM_NOTIFY */ - } /* switch */ - - return FALSE; -} - -static int sttOptionsInit(WPARAM wParam, LPARAM) -{ - OPTIONSDIALOGPAGE odp = {0}; - odp.cbSize = sizeof(odp); - odp.hInstance = hMirandaInst; - odp.flags = ODPF_BOLDGROUPS; - odp.position = -180000000; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_HOTKEYS); - odp.pszTitle = LPGEN("Hotkeys"); - odp.pszGroup = LPGEN("Customize"); - odp.pfnDlgProc = sttOptionsDlgProc; - Options_AddPage(wParam, &odp); - return 0; -} - static int sttModulesLoaded(WPARAM, LPARAM) { - HookEvent(ME_OPT_INITIALISE, sttOptionsInit); + HookEvent(ME_OPT_INITIALISE, HotkeyOptionsInit); return 0; } @@ -1421,37 +361,37 @@ int LoadSkinHotkeys(void) CreateServiceFunction(MS_HOTKEY_CHECK, svcHotkeyCheck); HookEvent(ME_SYSTEM_MODULESLOADED, sttModulesLoaded); - { + + for (int i = 0; i < SIZEOF(oldSettings); i++) { + char szSetting[ 100 ]; + mir_snprintf(szSetting, SIZEOF(szSetting), "HK%s", oldSettings[i]); + WORD key; - int i; - for (i = 0; i < SIZEOF(oldSettings); i++) { - char szSetting[ 100 ]; - mir_snprintf(szSetting, SIZEOF(szSetting), "HK%s", oldSettings[i]); - if ((key = DBGetContactSettingWord(NULL, "Clist", szSetting, 0))) { - DBDeleteContactSetting(NULL, "Clist", szSetting); - DBWriteContactSettingWord(NULL, DBMODULENAME, newSettings[i], key); - } + if ((key = DBGetContactSettingWord(NULL, "Clist", szSetting, 0))) { + DBDeleteContactSetting(NULL, "Clist", szSetting); + DBWriteContactSettingWord(NULL, DBMODULENAME, newSettings[i], key); + } - mir_snprintf(szSetting, SIZEOF(szSetting), "HKEn%s", oldSettings[i]); - if ((key = DBGetContactSettingByte(NULL, "Clist", szSetting, 0))) { - DBDeleteContactSetting(NULL, "Clist", szSetting); - DBWriteContactSettingByte(NULL, DBMODULENAME "Off", newSettings[i], (BYTE)(key == 0)); - } } } + mir_snprintf(szSetting, SIZEOF(szSetting), "HKEn%s", oldSettings[i]); + if ((key = DBGetContactSettingByte(NULL, "Clist", szSetting, 0))) { + DBDeleteContactSetting(NULL, "Clist", szSetting); + DBWriteContactSettingByte(NULL, DBMODULENAME "Off", newSettings[i], (BYTE)(key == 0)); + } + } return 0; } void UnloadSkinHotkeys(void) { - int i; - - if ( !bModuleInitialized) return; + if ( !bModuleInitialized) + return; DestroyHookableEvent(hEvChanged); UnhookWindowsHookEx(hhkKeyboard); - sttUnregisterHotkeys(); + UnregisterHotkeys(); DestroyWindow(g_hwndHotkeyHost); - for (i = 0; i < hotkeys.getCount(); i++) - sttFreeHotkey(hotkeys[i]); + for (int i = 0; i < hotkeys.getCount(); i++) + FreeHotkey(hotkeys[i]); hotkeys.destroy(); } diff --git a/src/modules/skin/skin.h b/src/modules/skin/skin.h new file mode 100644 index 0000000000..d66ee16515 --- /dev/null +++ b/src/modules/skin/skin.h @@ -0,0 +1,75 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#define DBMODULENAME "SkinHotKeys" + +#define WM_HOTKEYUNREGISTERED (WM_USER+721) + +typedef enum { HKT_GLOBAL, HKT_LOCAL, HKT_MANUAL, HKT_COUNT } THotkeyType; + +struct THotkeyBoxData +{ + WNDPROC oldWndProc; + BYTE shift; + BYTE key; +}; + +struct THotkeyItem +{ + THotkeyType type; + char *pszService, *pszName; // pszName is valid _only_ for "root" hotkeys + TCHAR *ptszSection, *ptszDescription; + LPARAM lParam; + WORD DefHotkey, Hotkey; + bool Enabled; + int hLangpack; + ATOM idHotkey; + + THotkeyItem *rootHotkey; + int nSubHotkeys; + bool allowSubHotkeys; + + bool OptChanged, OptDeleted, OptNew; + WORD OptHotkey; + THotkeyType OptType; + bool OptEnabled; + + bool UnregisterHotkey; // valid only during WM_APP message in options UI, used to remove unregistered hotkeys from options + + __inline TCHAR* getSection() const { return LangPackTranslateStringT(hLangpack, ptszSection); } + __inline TCHAR* getDescr() const { return LangPackTranslateStringT(hLangpack, ptszDescription); } +}; + +extern LIST hotkeys; +extern HWND g_hwndHkOptions, g_hwndHotkeyHost; +extern DWORD g_pid; +extern HANDLE hEvChanged; + +int HotkeyOptionsInit(WPARAM, LPARAM); + +void FreeHotkey(THotkeyItem *item); +void RegisterHotkeys(); +void UnregisterHotkeys(); + +void HotkeyEditCreate(HWND hwnd); +void tHotkeyEditDestroy(HWND hwnd); -- cgit v1.2.3