winamp/Src/Plugins/General/gen_hotkeys/Configdlg.cpp
2024-09-24 14:54:57 +02:00

471 lines
13 KiB
C++

#include "ConfigDlg.h"
#include "gen_hotkeys.h"
#include "accelBlock.h"
#define ListView_InsertColumnW(hwnd, iCol, pcol) \
(int)SNDMSG((hwnd), LVM_INSERTCOLUMNW, (WPARAM)(int)(iCol), (LPARAM)(const LV_COLUMNW *)(pcol))
#define ListView_InsertItemW(hwnd, pitem) \
(int)SNDMSG((hwnd), LVM_INSERTITEMW, 0, (LPARAM)(const LV_ITEMW *)(pitem))
#define ListView_SetItemTextW(hwndLV, i, iSubItem_, pszText_) \
{ LV_ITEMW _macro_lvi;\
_macro_lvi.iSubItem = (iSubItem_);\
_macro_lvi.pszText = (pszText_);\
SNDMSG((hwndLV), LVM_SETITEMTEXTW, (WPARAM)(i), (LPARAM)(LV_ITEMW *)&_macro_lvi);\
}
#define ListView_SetItemW(hwnd, pitem) \
(BOOL)SNDMSG((hwnd), LVM_SETITEMW, 0, (LPARAM)(LV_ITEMW *)(pitem))
void SetListItem(HWND hwHKList, HWND hwHK, HOTKEY_DATA *hk_data, int idx = -1, int failed = 0);
static AcceleratorBlocker *pAccelBlock = NULL;
static bool changed = false;
static int setCheckedStuff(HWND hwndDlg)
{
int checked = SendMessage(GetDlgItem(hwndDlg, IDC_ENABLED), BM_GETCHECK, 0, 0) == BST_CHECKED;
EnableWindow(GetDlgItem(hwndDlg,IDC_HKLIST),checked);
EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO),checked);
EnableWindow(GetDlgItem(hwndDlg,IDC_HOTKEY),checked);
EnableWindow(GetDlgItem(hwndDlg,IDC_ADD),checked);
if (!checked)
{
EnableWindow(GetDlgItem(hwndDlg,IDC_SAVE),0);
EnableWindow(GetDlgItem(hwndDlg,IDC_REMOVE),0);
}
EnableWindow(GetDlgItem(hwndDlg,IDC_DEFAULT),checked);
return checked;
}
int ResizeComboBoxDropDown(HWND hwndDlg, UINT id, const char* str, int width){
SIZE size = {0};
HWND control = GetDlgItem(hwndDlg, id);
HDC hdc = GetDC(control);
// get and select parent dialog's font so that it'll calculate things correctly
HFONT font = (HFONT)SendMessage(hwndDlg,WM_GETFONT,0,0), oldfont = (HFONT)SelectObject(hdc,font);
GetTextExtentPoint32(hdc, str, lstrlen(str)+1, &size);
int ret = width;
if(size.cx > width)
{
SendDlgItemMessageW(hwndDlg, id, CB_SETDROPPEDWIDTH, size.cx, 0);
ret = size.cx;
}
SelectObject(hdc, oldfont);
ReleaseDC(control, hdc);
return ret;
}
int ResizeComboBoxDropDownW(HWND hwndDlg, UINT id, const wchar_t *str, int width){
SIZE size = {0};
HWND control = GetDlgItem(hwndDlg, id);
HDC hdc = GetDC(control);
// get and select parent dialog's font so that it'll calculate things correctly
HFONT font = (HFONT)SendMessage(hwndDlg,WM_GETFONT,0,0), oldfont = (HFONT)SelectObject(hdc,font);
GetTextExtentPoint32W(hdc, str, (int)wcslen(str)+1, &size);
int ret = width;
if(size.cx > width)
{
SendDlgItemMessageW(hwndDlg, id, CB_SETDROPPEDWIDTH, size.cx, 0);
ret = size.cx;
}
SelectObject(hdc, oldfont);
ReleaseDC(control, hdc);
return ret;
}
BOOL CALLBACK ConfigProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND hwHKList = GetDlgItem(hwndDlg, IDC_HKLIST);
HWND hwCombo = GetDlgItem(hwndDlg, IDC_COMBO);
HWND hwHK = GetDlgItem(hwndDlg, IDC_HOTKEY);
switch (uMsg)
{
case WM_INITDIALOG:
{
int colwidth1 = -1, colwidth2 = -1;
if (hwHKList && hwHK)
{
RECT r;
SendMessage(hwHKList, WM_SETREDRAW, FALSE, 0);
ListView_SetExtendedListViewStyle(hwHKList, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
GetClientRect(hwHKList, &r);
colwidth2 = GetPrivateProfileIntW(L"gen_hotkeys", L"col2", -1, g_iniFile);
LVCOLUMNW lc = {LVCF_TEXT | LVCF_WIDTH, 0,
(colwidth2==-1?((r.right / 2) - GetSystemMetrics(SM_CYHSCROLL)):colwidth2),
WASABI_API_LNGSTRINGW(IDS_GHK_HOTKEY_COLUMN), 0, 0
};
ListView_InsertColumnW(hwHKList, 0, &lc);
lc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
colwidth1 = GetPrivateProfileIntW(L"gen_hotkeys", L"col1", -1, g_iniFile);
lc.cx = (colwidth1==-1?(r.right - lc.cx - GetSystemMetrics(SM_CYHSCROLL)):colwidth1);
lc.pszText = WASABI_API_LNGSTRINGW(IDS_GHK_ACTION_COLUMN);
lc.iSubItem = 1;
ListView_InsertColumnW(hwHKList, 0, &lc);
}
changed = false;
SubclassEditBox(hwHK);
if (NULL != hwHK && NULL == pAccelBlock)
pAccelBlock = new AcceleratorBlocker(hwHK);
HBITMAP hBitmap = LoadBitmap(psPlugin.hDllInstance, MAKEINTRESOURCE(IDB_LVSTATE));
HIMAGELIST hImageList = ImageList_Create(14, 14, ILC_COLOR8|ILC_MASK, 1, 0);
ImageList_AddMasked(hImageList, hBitmap, RGB(252, 254, 252));
ListView_SetImageList(hwHKList, hImageList, LVSIL_STATE);
DeleteObject(hBitmap);
ListView_SetItemCount(hwHKList, g_dwHotkeys);
// We don't want our hot keys while in the config
for (size_t i = 0; i < g_dwHotkeys; i++)
{
SetLastError(0);
UnregisterHotkey(g_hotkeys + i);
SetListItem(hwHKList, hwHK, &g_hotkeys[i].hkd, -1, g_hotkeys[i].failed);
}
hotkeysClear();
if(colwidth1==-1)
ListView_SetColumnWidth(hwHKList, 0, LVSCW_AUTOSIZE);
if(colwidth2==-1)
ListView_SetColumnWidth(hwHKList, 1, LVSCW_AUTOSIZE);
// clear
SendMessage(hwHK, wmHKCtlSet, 0, 0);
ListView_SetItemState(hwHKList, -1, 0, LVIS_SELECTED);
SendMessage(hwHKList, WM_SETREDRAW, TRUE, 0);
int width = 0;
for (size_t i = 0; i < GetCommandsNum(); i++)
{
bool unicode = 0;
char *cmdname = GetCommandName((unsigned int)i, &unicode);
if (*cmdname)
{
LRESULT pos;
if (unicode)
{
pos = SendMessageW(hwCombo, CB_ADDSTRING, 0, (LPARAM) cmdname);
width = ResizeComboBoxDropDownW(hwndDlg, IDC_COMBO, (wchar_t*)cmdname, width);
}
else
{
pos = SendMessageA(hwCombo, CB_ADDSTRING, 0, (LPARAM) cmdname);
width = ResizeComboBoxDropDown(hwndDlg, IDC_COMBO, cmdname, width);
}
SendMessage(hwCombo, CB_SETITEMDATA, pos, i);
}
}
// Set the enabled checkbox
CheckDlgButton(hwndDlg,IDC_ENABLED,GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile));
CheckDlgButton(hwndDlg,IDC_ENABLED_WM_APPCOMMAND,GetPrivateProfileIntW(L"gen_hotkeys", L"appcommand", 0, g_iniFile));
setCheckedStuff(hwndDlg);
if (NULL != WASABI_API_APP)
WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(hwHKList, TRUE);
break;
}
case WM_COMMAND:
{
// we don't want accelerator keys working when the hotkey window is focused
// that could be a problem if someone wants to bind Alt+D for example...
if (GetFocus() == hwHK)
break;
switch (LOWORD(wParam))
{
case IDC_ADD:
{
HOTKEY_DATA hkd;
DWORD dwHotKey = (unsigned long)SendMessage(hwHK, wmHKCtlGet, 0, 0);
UINT iCommand = (unsigned int)SendMessage(hwCombo, CB_GETITEMDATA, SendMessage(hwCombo, CB_GETCURSEL, 0, 0), 0);
if (!dwHotKey || iCommand == CB_ERR)
break;
hkd.dwHotKey = dwHotKey;
hkd.iCommand = iCommand;
changed = true;
SetListItem(hwHKList, hwHK, &hkd);
break;
}
case IDC_REMOVE:
{
int i = ListView_GetNextItem(hwHKList, -1, LVNI_SELECTED);
while (i != -1)
{
LVITEM lvi = {LVIF_PARAM, i};
ListView_GetItem(hwHKList, &lvi);
HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
delete hkd;
changed = true;
ListView_DeleteItem(hwHKList, i);
i = ListView_GetNextItem(hwHKList, -1, LVNI_SELECTED);
}
EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), 0);
break;
}
case IDC_SAVE:
{
if (ListView_GetSelectedCount(hwHKList) != 1)
break;
int iSel = ListView_GetNextItem(hwHKList, -1, LVNI_SELECTED);
LVITEMW lvi = {LVIF_PARAM, iSel};
ListView_GetItem(hwHKList, &lvi);
HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
if (hkd)
{
DWORD dwHotKey = (unsigned long)SendMessage(hwHK, wmHKCtlGet, 0, 0);
UINT iCommand = (unsigned int)SendMessage(hwCombo, CB_GETITEMDATA, SendMessage(hwCombo, CB_GETCURSEL, 0, 0), 0);
if (!dwHotKey || iCommand == CB_ERR)
break;
hkd->dwHotKey = dwHotKey;
hkd->iCommand = iCommand;
changed = true;
SetListItem(hwHKList, hwHK, hkd, iSel);
}
break;
}
case IDC_ENABLED:
if (setCheckedStuff(hwndDlg))
{
DWORD dwSelected = ListView_GetSelectedCount(hwHKList);
EnableWindow(GetDlgItem(hwndDlg, IDC_SAVE), dwSelected == 1);
EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), dwSelected);
changed = true;
}
break;
case IDC_DEFAULT:
{
DWORD i;
SendMessage(hwndDlg, WM_SETREDRAW, FALSE, 0);
DWORD dwCount = (DWORD)ListView_GetItemCount(hwHKList);
if (dwCount)
{
for (i = 0; i < dwCount; i++)
{
LVITEM lvi = {LVIF_PARAM,(int)i};
ListView_GetItem(hwHKList, &lvi);
HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
delete hkd;
}
}
changed = true;
ListView_DeleteAllItems(hwHKList);
for (i = 0; i < DEFHKDS_NUM; i++)
{
SetListItem(hwHKList, hwHK, g_defhkds + i);
}
// restore the size of the columns on a reset as well
ListView_SetColumnWidth(hwHKList, 0, LVSCW_AUTOSIZE);
ListView_SetColumnWidth(hwHKList, 1, LVSCW_AUTOSIZE);
ListView_SetItemState(hwHKList, -1, 0, LVIS_SELECTED);
SendMessage(hwndDlg, WM_SETREDRAW, TRUE, 0);
InvalidateRect(hwndDlg, 0, 0);
break;
}
}
break;
}
case WM_NOTIFY:
{
LPNMHDR nmhdr = (LPNMHDR) lParam;
if (nmhdr && nmhdr->idFrom == IDC_HKLIST)
{
if (nmhdr->code == LVN_ITEMCHANGED)
{
LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
DWORD dwSelected = ListView_GetSelectedCount(hwHKList);
EnableWindow(GetDlgItem(hwndDlg, IDC_SAVE), dwSelected == 1);
EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), dwSelected);
SendMessage(hwHK, wmHKCtlSet, 0, 0);
SendMessage(hwCombo, CB_SETCURSEL, -1, 0);
if (dwSelected == 1 && (pnmv->uNewState & LVIS_SELECTED))
{
HOTKEY_DATA *hkd = (HOTKEY_DATA *) pnmv->lParam;
if (hkd)
{
SendMessage(hwHK, wmHKCtlSet, hkd->dwHotKey, 0);
bool unicode = 0;
char *cmd = GetCommandName(hkd->iCommand, &unicode);
if (*cmd)
{
if(unicode) SendMessageW(hwCombo, CB_SELECTSTRING, -1, (LPARAM) cmd);
else SendMessageA(hwCombo, CB_SELECTSTRING, -1, (LPARAM) cmd);
}
}
}
}
else if(nmhdr->code == LVN_KEYDOWN)
{
LPNMLVKEYDOWN pnmv = (LPNMLVKEYDOWN) lParam;
if(pnmv->wVKey == VK_DELETE)
{
changed = true;
SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_REMOVE,0),0);
}
else if(pnmv->wVKey == 'A' && GetAsyncKeyState(VK_CONTROL))
{
for(int i = 0; i < ListView_GetItemCount(hwHKList); i++)
{
ListView_SetItemState(hwHKList,i,LVIS_SELECTED,LVIS_SELECTED);
}
}
}
}
}
break;
case WM_DESTROY:
{
int checked = (SendMessage(GetDlgItem(hwndDlg, IDC_ENABLED), BM_GETCHECK, 0, 0) == BST_CHECKED);
writePrivateProfileInt(L"enabled", checked);
writePrivateProfileInt(L"appcommand",
(SendMessage(GetDlgItem(hwndDlg, IDC_ENABLED_WM_APPCOMMAND), BM_GETCHECK, 0, 0) == BST_CHECKED));
hotkeysClear();
int iCount = ListView_GetItemCount(hwHKList);
HOTKEY_DATA *hkds = NULL;
if (iCount)
{
hkds = new HOTKEY_DATA[iCount]; // TODO: could alloca this
memset(hkds, 0, iCount * sizeof(HOTKEY_DATA));
}
if (hkds || !iCount)
{
for (size_t i = 0; i < (unsigned int)iCount; i++)
{
LVITEM lvi = {LVIF_PARAM, (int)i};
ListView_GetItem(hwHKList, &lvi);
HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
if (hkd)
{
hkds[i] = *hkd;
delete hkd;
}
}
hotkeysLoad(hkds, iCount, checked);
if (changed) hotkeysSave(hkds, iCount);
delete [] hkds;
}
writePrivateProfileInt(L"col1", ListView_GetColumnWidth(hwHKList,0));
writePrivateProfileInt(L"col2", ListView_GetColumnWidth(hwHKList,1));
RegisterShellHookWindow(psPlugin.hwndParent);
if (NULL != pAccelBlock && hwHK == pAccelBlock->GetHwnd())
{
delete(pAccelBlock);
pAccelBlock = NULL;
}
if (NULL != WASABI_API_APP)
WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(hwHKList, FALSE);
}
break;
}
return FALSE;
}
// idx = -1 for insertion
void SetListItem(HWND hwHKList, HWND hwHK, HOTKEY_DATA *hk_data, int idx, int failed)
{
wchar_t szHK[1024] = {L""};
SendMessage(hwHK, wmHKCtlSet, hk_data->dwHotKey, 0);
GetWindowTextW(hwHK, szHK, sizeof(szHK));
HOTKEY_DATA *hk_data_allocated = 0;
if (idx < 0)
hk_data_allocated = new HOTKEY_DATA;
if (idx >= 0 || hk_data_allocated)
{
if (idx < 0)
*hk_data_allocated = *hk_data;
int pos = ListView_GetItemCount(hwHKList);
if (idx >= 0)
pos = idx;
// Add item to the list
bool unicode = 0;
LVITEM lvi = {
LVIF_PARAM | LVIF_TEXT | LVIF_STATE,
pos,
0,
LVIS_SELECTED | INDEXTOSTATEIMAGEMASK(failed ? (UINT)1 : 0) | LVIS_FOCUSED,
LVIS_SELECTED | LVIS_STATEIMAGEMASK | LVIS_FOCUSED,
GetCommandName(hk_data->iCommand, &unicode),
0,
0,
(LPARAM) hk_data_allocated
};
char tmp[1024] = {0};
if (!lvi.pszText || !*lvi.pszText)
{
if (hk_data->szCommand)
{
StringCchPrintf(tmp, 1024, "[%s]", hk_data->szCommand);
lvi.pszText = tmp;
}
}
if (!lvi.pszText || !*lvi.pszText)
lvi.pszText = WASABI_API_LNGSTRING(IDS_GHK_ACTION_NOT_FOUND);
if (idx >= 0)
{
lvi.mask ^= LVIF_PARAM;
if(unicode) ListView_SetItemW(hwHKList, &lvi);
else ListView_SetItem(hwHKList, &lvi);
}
else
{
ListView_SetItemState(hwHKList, -1, 0, LVIS_SELECTED | LVIS_FOCUSED);
if(unicode) ListView_InsertItemW(hwHKList, &lvi);
else ListView_InsertItem(hwHKList, &lvi);
}
ListView_SetItemTextW(hwHKList, pos, 1, szHK);
}
}