// 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); }