terminal/src/propsheet/ColorsPage.cpp
pi1024e 9f95b54f2c
Change NULL to nullptr since they are pointers (#4960)
Some functions and variables are having NULL assigned to them when they are in fact pointers, so nullptr might be more accurate here.
2020-03-20 20:35:12 +00:00

434 lines
14 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "ColorsPage.h"
#include "ColorControl.h"
static BYTE ColorArray[4];
static int iColor;
// Routine Description:
// - Window proc for the color buttons
[[nodiscard]] LRESULT CALLBACK ColorTableControlProc(HWND hColor, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
int ColorId;
RECT rColor;
RECT rTemp;
HDC hdc;
HWND hWnd;
HWND hDlg;
ColorId = GetWindowLong(hColor, GWL_ID);
hDlg = GetParent(hColor);
switch (wMsg)
{
case WM_SETFOCUS:
if (ColorArray[iColor] != (BYTE)(ColorId - IDD_COLOR_1))
{
hWnd = GetDlgItem(hDlg, ColorArray[iColor] + IDD_COLOR_1);
SetFocus(hWnd);
}
__fallthrough;
case WM_KILLFOCUS:
hdc = GetDC(hDlg);
hWnd = GetDlgItem(hDlg, IDD_COLOR_1);
GetWindowRect(hWnd, &rColor);
hWnd = GetDlgItem(hDlg, IDD_COLOR_16);
GetWindowRect(hWnd, &rTemp);
rColor.right = rTemp.right;
ScreenToClient(hDlg, (LPPOINT)&rColor.left);
ScreenToClient(hDlg, (LPPOINT)&rColor.right);
InflateRect(&rColor, 2, 2);
DrawFocusRect(hdc, &rColor);
ReleaseDC(hDlg, hdc);
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_UP:
case VK_LEFT:
if (ColorId > IDD_COLOR_1)
{
SendMessage(hDlg, CM_SETCOLOR, ColorId - 1 - IDD_COLOR_1, (LPARAM)hColor);
}
break;
case VK_DOWN:
case VK_RIGHT:
if (ColorId < IDD_COLOR_16)
{
SendMessage(hDlg, CM_SETCOLOR, ColorId + 1 - IDD_COLOR_1, (LPARAM)hColor);
}
break;
case VK_TAB:
hWnd = GetDlgItem(hDlg, IDD_COLOR_1);
hWnd = GetNextDlgTabItem(hDlg, hWnd, GetKeyState(VK_SHIFT) < 0);
SetFocus(hWnd);
break;
default:
return DefWindowProc(hColor, wMsg, wParam, lParam);
}
break;
case WM_RBUTTONDOWN:
case WM_LBUTTONDOWN:
SendMessage(hDlg, CM_SETCOLOR, ColorId - IDD_COLOR_1, (LPARAM)hColor);
break;
case WM_PAINT:
BeginPaint(hColor, &ps);
GetClientRect(hColor, &rColor);
// are we the selected color for the current object?
if (ColorArray[iColor] == (BYTE)(ColorId - IDD_COLOR_1))
{
// highlight the selected color
FrameRect(ps.hdc, &rColor, (HBRUSH)GetStockObject(BLACK_BRUSH));
InflateRect(&rColor, -1, -1);
FrameRect(ps.hdc, &rColor, (HBRUSH)GetStockObject(BLACK_BRUSH));
}
SimpleColorDoPaint(hColor, ps, ColorId);
EndPaint(hColor, &ps);
break;
default:
return SimpleColorControlProc(hColor, wMsg, wParam, lParam);
break;
}
return TRUE;
}
bool InitColorsDialog(HWND hDlg)
{
ColorArray[IDD_COLOR_SCREEN_TEXT - IDD_COLOR_SCREEN_TEXT] =
LOBYTE(gpStateInfo->ScreenAttributes) & 0x0F;
ColorArray[IDD_COLOR_SCREEN_BKGND - IDD_COLOR_SCREEN_TEXT] =
LOBYTE(gpStateInfo->ScreenAttributes >> 4);
ColorArray[IDD_COLOR_POPUP_TEXT - IDD_COLOR_SCREEN_TEXT] =
LOBYTE(gpStateInfo->PopupAttributes) & 0x0F;
ColorArray[IDD_COLOR_POPUP_BKGND - IDD_COLOR_SCREEN_TEXT] =
LOBYTE(gpStateInfo->PopupAttributes >> 4);
CheckRadioButton(hDlg, IDD_COLOR_SCREEN_TEXT, IDD_COLOR_POPUP_BKGND, IDD_COLOR_SCREEN_BKGND);
iColor = IDD_COLOR_SCREEN_BKGND - IDD_COLOR_SCREEN_TEXT;
// initialize size of edit controls
SendDlgItemMessage(hDlg, IDD_COLOR_RED, EM_LIMITTEXT, 3, 0);
SendDlgItemMessage(hDlg, IDD_COLOR_GREEN, EM_LIMITTEXT, 3, 0);
SendDlgItemMessage(hDlg, IDD_COLOR_BLUE, EM_LIMITTEXT, 3, 0);
// initialize arrow controls
SendDlgItemMessage(hDlg, IDD_COLOR_REDSCROLL, UDM_SETRANGE, 0, MAKELONG(255, 0));
SendDlgItemMessage(hDlg, IDD_COLOR_REDSCROLL, UDM_SETPOS, 0, MAKELONG(GetRValue(AttrToRGB(ColorArray[iColor])), 0));
SendDlgItemMessage(hDlg, IDD_COLOR_GREENSCROLL, UDM_SETRANGE, 0, MAKELONG(255, 0));
SendDlgItemMessage(hDlg, IDD_COLOR_GREENSCROLL, UDM_SETPOS, 0, MAKELONG(GetGValue(AttrToRGB(ColorArray[iColor])), 0));
SendDlgItemMessage(hDlg, IDD_COLOR_BLUESCROLL, UDM_SETRANGE, 0, MAKELONG(255, 0));
SendDlgItemMessage(hDlg, IDD_COLOR_BLUESCROLL, UDM_SETPOS, 0, MAKELONG(GetBValue(AttrToRGB(ColorArray[iColor])), 0));
CreateAndAssociateToolTipToControl(IDD_TRANSPARENCY, hDlg, IDS_TOOLTIP_OPACITY);
SendMessage(GetDlgItem(hDlg, IDD_TRANSPARENCY), TBM_SETRANGE, FALSE, (LPARAM)MAKELONG(TRANSPARENCY_RANGE_MIN, BYTE_MAX));
ToggleV2ColorControls(hDlg);
return TRUE;
}
// Routine Description:
// - Dialog proc for the color selection dialog box.
//
INT_PTR WINAPI ColorDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
UINT Value;
UINT Red;
UINT Green;
UINT Blue;
UINT Item;
HWND hWnd;
HWND hWndOld;
BOOL bOK;
static bool fHaveInitialized = false;
switch (wMsg)
{
case WM_INITDIALOG:
{
fHaveInitialized = true;
return InitColorsDialog(hDlg);
}
case WM_COMMAND:
{
if (!fHaveInitialized)
{
return FALSE;
}
Item = LOWORD(wParam);
switch (Item)
{
case IDD_COLOR_SCREEN_TEXT:
case IDD_COLOR_SCREEN_BKGND:
case IDD_COLOR_POPUP_TEXT:
case IDD_COLOR_POPUP_BKGND:
hWndOld = GetDlgItem(hDlg, ColorArray[iColor] + IDD_COLOR_1);
iColor = Item - IDD_COLOR_SCREEN_TEXT;
// repaint new color
hWnd = GetDlgItem(hDlg, ColorArray[iColor] + IDD_COLOR_1);
InvalidateRect(hWnd, nullptr, TRUE);
// repaint old color
if (hWndOld != hWnd)
{
InvalidateRect(hWndOld, nullptr, TRUE);
}
return TRUE;
case IDD_COLOR_RED:
case IDD_COLOR_GREEN:
case IDD_COLOR_BLUE:
{
switch (HIWORD(wParam))
{
case EN_UPDATE:
if (!CheckNum(hDlg, Item))
{
Undo((HWND)lParam);
}
break;
case EN_CHANGE:
/*
* Update the state info structure
*/
Value = GetDlgItemInt(hDlg, Item, &bOK, TRUE);
if (bOK)
{
if (Value > 255)
{
UpdateItem(hDlg, Item, 255);
Value = 255;
}
if (Item == IDD_COLOR_RED)
{
Red = Value;
}
else
{
Red = GetRValue(AttrToRGB(ColorArray[iColor]));
}
if (Item == IDD_COLOR_GREEN)
{
Green = Value;
}
else
{
Green = GetGValue(AttrToRGB(ColorArray[iColor]));
}
if (Item == IDD_COLOR_BLUE)
{
Blue = Value;
}
else
{
Blue = GetBValue(AttrToRGB(ColorArray[iColor]));
}
UpdateStateInfo(hDlg, ColorArray[iColor] + IDD_COLOR_1, RGB(Red, Green, Blue));
UpdateApplyButton(hDlg);
}
__fallthrough;
case EN_KILLFOCUS:
/*
* Update the preview windows with the new value
*/
hWnd = GetDlgItem(hDlg, IDD_COLOR_SCREEN_COLORS);
InvalidateRect(hWnd, nullptr, FALSE);
hWnd = GetDlgItem(hDlg, IDD_COLOR_POPUP_COLORS);
InvalidateRect(hWnd, nullptr, FALSE);
hWnd = GetDlgItem(hDlg, ColorArray[iColor] + IDD_COLOR_1);
InvalidateRect(hWnd, nullptr, FALSE);
break;
}
return TRUE;
}
}
break;
}
case WM_NOTIFY:
{
const PSHNOTIFY* const pshn = (LPPSHNOTIFY)lParam;
switch (pshn->hdr.code)
{
case PSN_APPLY:
/*
* Write out the state values and exit.
*/
// Ignore opacity in v1 console
if (g_fForceV2)
{
gpStateInfo->bWindowTransparency = (BYTE)SendDlgItemMessage(hDlg, IDD_TRANSPARENCY, TBM_GETPOS, 0, 0);
}
EndDlgPage(hDlg, !pshn->lParam);
return TRUE;
case PSN_RESET:
// Ignore opacity in v1 console
if (g_fForceV2 && g_bPreviewOpacity != gpStateInfo->bWindowTransparency)
{
SetLayeredWindowAttributes(gpStateInfo->hWnd, 0, gpStateInfo->bWindowTransparency, LWA_ALPHA);
}
return 0;
case PSN_SETACTIVE:
ToggleV2ColorControls(hDlg);
return 0;
case PSN_KILLACTIVE:
/*
* Fake the dialog proc into thinking the edit control just
* lost focus so it'll update properly
*/
Item = GetDlgCtrlID(GetFocus());
if (Item)
{
SendMessage(hDlg, WM_COMMAND, MAKELONG(Item, EN_KILLFOCUS), 0);
}
return TRUE;
}
break;
}
case WM_VSCROLL:
/*
* Fake the dialog proc into thinking the edit control just
* lost focus so it'll update properly
*/
Item = GetDlgCtrlID((HWND)lParam) - 1;
SendMessage(hDlg, WM_COMMAND, MAKELONG(Item, EN_KILLFOCUS), 0);
return TRUE;
case WM_HSCROLL:
if (IDD_TRANSPARENCY == GetDlgCtrlID((HWND)lParam))
{
switch (LOWORD(wParam))
{
//When moving slider with the mouse
case TB_THUMBPOSITION:
case TB_THUMBTRACK:
g_bPreviewOpacity = (BYTE)HIWORD(wParam);
break;
//moving via keyboard
default:
g_bPreviewOpacity = (BYTE)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
}
PreviewOpacity(hDlg, g_bPreviewOpacity);
UpdateApplyButton(hDlg);
return TRUE;
}
break;
case CM_SETCOLOR:
UpdateStateInfo(hDlg, iColor + IDD_COLOR_SCREEN_TEXT, (UINT)wParam);
UpdateApplyButton(hDlg);
hWndOld = GetDlgItem(hDlg, ColorArray[iColor] + IDD_COLOR_1);
ColorArray[iColor] = (BYTE)wParam;
/* Force the preview window to repaint */
if (iColor < (IDD_COLOR_POPUP_TEXT - IDD_COLOR_SCREEN_TEXT))
{
hWnd = GetDlgItem(hDlg, IDD_COLOR_SCREEN_COLORS);
}
else
{
hWnd = GetDlgItem(hDlg, IDD_COLOR_POPUP_COLORS);
}
InvalidateRect(hWnd, nullptr, TRUE);
// repaint new color
hWnd = GetDlgItem(hDlg, ColorArray[iColor] + IDD_COLOR_1);
InvalidateRect(hWnd, nullptr, TRUE);
SetFocus(hWnd);
UpdateItem(hDlg, IDD_COLOR_RED, GetRValue(AttrToRGB(ColorArray[iColor])));
UpdateItem(hDlg, IDD_COLOR_GREEN, GetGValue(AttrToRGB(ColorArray[iColor])));
UpdateItem(hDlg, IDD_COLOR_BLUE, GetBValue(AttrToRGB(ColorArray[iColor])));
// repaint old color
if (hWndOld != hWnd)
{
InvalidateRect(hWndOld, nullptr, TRUE);
}
return TRUE;
default:
break;
}
return FALSE;
}
// enables or disables color page dialog controls depending on whether V2 is enabled or not
void ToggleV2ColorControls(__in const HWND hDlg)
{
EnableWindow(GetDlgItem(hDlg, IDD_TRANSPARENCY), g_fForceV2);
SetOpacitySlider(hDlg);
EnableWindow(GetDlgItem(hDlg, IDD_OPACITY_GROUPBOX), g_fForceV2);
EnableWindow(GetDlgItem(hDlg, IDD_OPACITY_LOW_LABEL), g_fForceV2);
EnableWindow(GetDlgItem(hDlg, IDD_OPACITY_HIGH_LABEL), g_fForceV2);
EnableWindow(GetDlgItem(hDlg, IDD_OPACITY_VALUE), g_fForceV2);
}
void PreviewOpacity(HWND hDlg, BYTE bOpacity)
{
// Ignore opacity in v1 console
if (g_fForceV2)
{
WCHAR wszOpacityValue[4];
HWND hWndConsole = gpStateInfo->hWnd;
StringCchPrintf(wszOpacityValue, ARRAYSIZE(wszOpacityValue), L"%d", (int)((float)bOpacity / BYTE_MAX * 100));
SetDlgItemText(hDlg, IDD_OPACITY_VALUE, wszOpacityValue);
if (hWndConsole)
{
// TODO: CONSIDER:What happens when this code is eventually ported directly into the shell. Which "hWnd" does this apply to then? Desktop?
// Hopefully it is simply null. -RSE http://osgvsowi/2136073
SetLayeredWindowAttributes(hWndConsole, 0, bOpacity, LWA_ALPHA);
}
}
}
void SetOpacitySlider(__in HWND hDlg)
{
if (g_fForceV2)
{
if (0 == g_bPreviewOpacity) //if no preview opacity has been set yet...
{
g_bPreviewOpacity = (gpStateInfo->bWindowTransparency >= TRANSPARENCY_RANGE_MIN) ? gpStateInfo->bWindowTransparency : BYTE_MAX;
}
}
else
{
g_bPreviewOpacity = BYTE_MAX; //always fully opaque in V1
}
SendMessage(GetDlgItem(hDlg, IDD_TRANSPARENCY), TBM_SETPOS, TRUE, (LPARAM)(g_bPreviewOpacity));
PreviewOpacity(hDlg, g_bPreviewOpacity);
}