Reactos
at master 218 lines 7.0 kB view raw
1/* 2 * PROJECT: PAINT for ReactOS 3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) 4 * PURPOSE: Window procedure of the palette window 5 * COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net> 6 * Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 7 */ 8 9#include "precomp.h" 10 11/* The private metrics */ 12#define CXY_SELECTEDBOX 15 /* width / height of a selected color box */ 13#define X_MARGIN 4 /* horizontal margin */ 14#define Y_MARGIN ((rcClient.bottom / 2) - CXY_COLORBOX) /* center position minus one color box */ 15#define X_COLORBOX_OFFSET (X_MARGIN + CXY_BIGBOX + X_MARGIN) 16#define COLOR_COUNT 28 17#define HALF_COLOR_COUNT (COLOR_COUNT / 2) 18 19CPaletteWindow paletteWindow; 20 21/* FUNCTIONS ********************************************************/ 22 23CPaletteWindow::CPaletteWindow() 24 : m_hbmCached(NULL) 25{ 26} 27 28CPaletteWindow::~CPaletteWindow() 29{ 30 if (m_hbmCached) 31 ::DeleteObject(m_hbmCached); 32} 33 34static VOID drawColorBox(HDC hDC, LPCRECT prc, COLORREF rgbColor, UINT nBorder) 35{ 36 RECT rc = *prc; 37 ::FillRect(hDC, &rc, (HBRUSH)(COLOR_3DFACE + 1)); 38 ::DrawEdge(hDC, &rc, nBorder, BF_RECT | BF_ADJUST); 39 40 HBRUSH hbr = ::CreateSolidBrush(rgbColor); 41 ::FillRect(hDC, &rc, hbr); 42 ::DeleteObject(hbr); 43} 44 45static VOID getColorBoxRect(LPRECT prc, const RECT& rcClient, INT iColor) 46{ 47 INT dx = (iColor % HALF_COLOR_COUNT) * CXY_COLORBOX; /* delta x */ 48 INT dy = (iColor / HALF_COLOR_COUNT) * CXY_COLORBOX; /* delta y */ 49 prc->left = X_COLORBOX_OFFSET + dx; 50 prc->right = prc->left + CXY_COLORBOX; 51 prc->top = Y_MARGIN + dy; 52 prc->bottom = prc->top + CXY_COLORBOX; 53} 54 55INT CPaletteWindow::DoHitTest(INT xPos, INT yPos) const 56{ 57 RECT rcClient; 58 GetClientRect(&rcClient); 59 60 /* delta x and y */ 61 INT dx = (xPos - X_COLORBOX_OFFSET), dy = (yPos - Y_MARGIN); 62 63 /* horizontal and vertical indexes */ 64 INT ix = (dx / CXY_COLORBOX), iy = (dy / CXY_COLORBOX); 65 66 /* Is it inside of a color box? */ 67 if (0 <= ix && ix < HALF_COLOR_COUNT && 0 <= iy && iy < 2) 68 return ix + (iy * HALF_COLOR_COUNT); /* return the color index */ 69 70 return -1; /* Not found */ 71} 72 73LRESULT CPaletteWindow::OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 74{ 75 return TRUE; /* Avoid flickering */ 76} 77 78LRESULT CPaletteWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 79{ 80 RECT rc, rcClient; 81 GetClientRect(&rcClient); 82 83 PAINTSTRUCT ps; 84 HDC hDC = BeginPaint(&ps); 85 86 /* To avoid flickering, we use a memory bitmap. 87 The left and top values are zeros in client rectangle */ 88 HDC hMemDC = ::CreateCompatibleDC(hDC); 89 m_hbmCached = CachedBufferDIB(m_hbmCached, rcClient.right, rcClient.bottom); 90 HGDIOBJ hbmOld = ::SelectObject(hMemDC, m_hbmCached); 91 92 /* Fill the background (since WM_ERASEBKGND handling is disabled) */ 93 ::FillRect(hMemDC, &rcClient, (HBRUSH)(COLOR_3DFACE + 1)); 94 95 /* Draw the big box that contains the black box and the white box */ 96 rc = { X_MARGIN, Y_MARGIN, X_MARGIN + CXY_BIGBOX, Y_MARGIN + CXY_BIGBOX }; 97 ::DrawEdge(hMemDC, &rc, EDGE_SUNKEN, BF_RECT | BF_ADJUST); 98 COLORREF rgbLight = ::GetSysColor(COLOR_3DHIGHLIGHT); 99 for (INT y = rc.top; y < rc.bottom; ++y) 100 { 101 BOOL bLight = (y & 1); 102 for (INT x = rc.left; x < rc.right; ++x) 103 { 104 if (bLight) 105 ::SetPixelV(hMemDC, x, y, rgbLight); 106 bLight = !bLight; 107 } 108 } 109 110 /* Draw the white box in the big box, at 5/8 position */ 111 rc.left = X_MARGIN + (CXY_BIGBOX * 5 / 8) - (CXY_SELECTEDBOX / 2); 112 rc.top = Y_MARGIN + (CXY_BIGBOX * 5 / 8) - (CXY_SELECTEDBOX / 2); 113 rc.right = rc.left + CXY_SELECTEDBOX; 114 rc.bottom = rc.top + CXY_SELECTEDBOX; 115 drawColorBox(hMemDC, &rc, paletteModel.GetBgColor(), BDR_RAISEDINNER); 116 117 /* Draw the black box (overlapping the white box), at 3/8 position */ 118 rc.left = X_MARGIN + (CXY_BIGBOX * 3 / 8) - (CXY_SELECTEDBOX / 2); 119 rc.top = Y_MARGIN + (CXY_BIGBOX * 3 / 8) - (CXY_SELECTEDBOX / 2); 120 rc.right = rc.left + CXY_SELECTEDBOX; 121 rc.bottom = rc.top + CXY_SELECTEDBOX; 122 drawColorBox(hMemDC, &rc, paletteModel.GetFgColor(), BDR_RAISEDINNER); 123 124 /* Draw the normal color boxes */ 125 for (INT i = 0; i < COLOR_COUNT; i++) 126 { 127 getColorBoxRect(&rc, rcClient, i); 128 drawColorBox(hMemDC, &rc, paletteModel.GetColor(i), BDR_SUNKENOUTER); 129 } 130 131 /* Transfer bits (hDC <-- hMemDC) */ 132 ::BitBlt(hDC, 0, 0, rcClient.right, rcClient.bottom, hMemDC, 0, 0, SRCCOPY); 133 134 ::SelectObject(hMemDC, hbmOld); 135 ::DeleteDC(hMemDC); 136 EndPaint(&ps); 137 return 0; 138} 139 140LRESULT CPaletteWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 141{ 142 INT iColor = DoHitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 143 if (iColor != -1) 144 paletteModel.SetFgColor(paletteModel.GetColor(iColor)); 145 SetCapture(); 146 return 0; 147} 148 149LRESULT CPaletteWindow::OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 150{ 151 INT iColor = DoHitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 152 if (iColor != -1) 153 paletteModel.SetBgColor(paletteModel.GetColor(iColor)); 154 return 0; 155} 156 157LRESULT CPaletteWindow::OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 158{ 159 INT iColor = DoHitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 160 COLORREF rgbColor = paletteModel.GetFgColor(); 161 if (iColor != -1 && mainWindow.ChooseColor(&rgbColor)) 162 { 163 paletteModel.SetColor(iColor, rgbColor); 164 paletteModel.SetFgColor(rgbColor); 165 } 166 return 0; 167} 168 169LRESULT CPaletteWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 170{ 171 INT iColor = DoHitTest(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 172 COLORREF rgbColor = paletteModel.GetBgColor(); 173 if (iColor != -1 && mainWindow.ChooseColor(&rgbColor)) 174 { 175 paletteModel.SetColor(iColor, rgbColor); 176 paletteModel.SetBgColor(rgbColor); 177 } 178 return 0; 179} 180 181LRESULT CPaletteWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 182{ 183 Invalidate(FALSE); 184 return 0; 185} 186 187LRESULT CPaletteWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 188{ 189 if (::GetCapture() != m_hWnd) 190 return 0; 191 192 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 193 ClientToScreen(&pt); 194 195 RECT rc; 196 mainWindow.GetWindowRect(&rc); 197 198 POINT ptCenter = { (rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2 }; 199 200 DWORD dwExpectedBar1ID = ((pt.y < ptCenter.y) ? BAR1ID_TOP : BAR1ID_BOTTOM); 201 202 if (registrySettings.Bar1ID != dwExpectedBar1ID) 203 { 204 registrySettings.Bar1ID = dwExpectedBar1ID; 205 mainWindow.PostMessage(WM_SIZE, 0, 0); 206 } 207 208 return 0; 209} 210 211LRESULT CPaletteWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 212{ 213 if (::GetCapture() != m_hWnd) 214 return 0; 215 216 ::ReleaseCapture(); 217 return 0; 218}