GME
13
|
00001 // ColourPopup.cpp : implementation file 00002 // 00003 // Written by Chris Maunder (chrismaunder@codeguru.com) 00004 // Extended by Alexander Bischofberger (bischofb@informatik.tu-muenchen.de) 00005 // Copyright (c) 1998. 00006 // 00007 // Updated 30 May 1998 to allow any number of colours, and to 00008 // make the appearance closer to Office 97. 00009 // Also added "Default" text area. (CJM) 00010 // 00011 // 13 June 1998 Fixed change of focus bug (CJM) 00012 // 30 June 1998 Fixed bug caused by focus bug fix (D'oh!!) 00013 // Solution suggested by Paul Wilkerson. 00014 // 00015 // ColourPopup is a helper class for the colour picker control 00016 // CColourPicker. Check out the header file or the accompanying 00017 // HTML doc file for details. 00018 // 00019 // This code may be used in compiled form in any way you desire. This 00020 // file may be redistributed unmodified by any means PROVIDING it is 00021 // not sold for profit without the authors written consent, and 00022 // providing that this notice and the authors name is included. 00023 // 00024 // This file is provided "as is" with no expressed or implied warranty. 00025 // The author accepts no liability if it causes any damage to you or your 00026 // computer whatsoever. It's free, so don't hassle me about it. 00027 // 00028 // Expect bugs. 00029 // 00030 // Please use and enjoy. Please let me know of any bugs/mods/improvements 00031 // that you have found/implemented and I will fix/incorporate them into this 00032 // file. 00033 00034 #include "stdafx.h" 00035 #include <math.h> 00036 #include "ColourPopup.h" 00037 #include "InPlaceCommon.h" 00038 00039 #ifdef _DEBUG 00040 #define new DEBUG_NEW 00041 #undef THIS_FILE 00042 static char THIS_FILE[] = __FILE__; 00043 #endif 00044 00045 #define CUSTOM_BOX_VALUE -2 00046 #define INVALID_COLOUR -1 00047 00048 #define MAX_COLOURS 100 00049 00050 IMPLEMENT_DYNAMIC(CColourPopup, CDialog) 00051 00052 00053 ColourTableEntry CColourPopup::m_crColours[] = 00054 { 00055 { RGB(0x00, 0x00, 0x00), _T("Black") }, 00056 { RGB(0xA5, 0x2A, 0x00), _T("Brown") }, 00057 { RGB(0x00, 0x40, 0x40), _T("Dark Olive Green") }, 00058 { RGB(0x00, 0x55, 0x00), _T("Dark Green") }, 00059 { RGB(0x00, 0x00, 0x5E), _T("Dark Teal") }, 00060 { RGB(0x00, 0x00, 0x8B), _T("Dark blue") }, 00061 { RGB(0x4B, 0x00, 0x82), _T("Indigo") }, 00062 { RGB(0x28, 0x28, 0x28), _T("Dark grey") }, 00063 00064 { RGB(0x8B, 0x00, 0x00), _T("Dark red") }, 00065 { RGB(0xFF, 0x68, 0x20), _T("Orange") }, 00066 { RGB(0x8B, 0x8B, 0x00), _T("Dark yellow") }, 00067 { RGB(0x00, 0x93, 0x00), _T("Green") }, 00068 { RGB(0x38, 0x8E, 0x8E), _T("Teal") }, 00069 { RGB(0x00, 0x00, 0xFF), _T("Blue") }, 00070 { RGB(0x7B, 0x7B, 0xC0), _T("Blue-grey") }, 00071 { RGB(0x66, 0x66, 0x66), _T("Grey - 40") }, 00072 00073 { RGB(0xFF, 0x00, 0x00), _T("Red") }, 00074 { RGB(0xFF, 0xAD, 0x5B), _T("Light orange") }, 00075 { RGB(0x32, 0xCD, 0x32), _T("Lime") }, 00076 { RGB(0x3C, 0xB3, 0x71), _T("Sea green") }, 00077 { RGB(0x7F, 0xFF, 0xD4), _T("Aqua") }, 00078 { RGB(0x7D, 0x9E, 0xC0), _T("Light blue") }, 00079 { RGB(0x80, 0x00, 0x80), _T("Violet") }, 00080 { RGB(0x7F, 0x7F, 0x7F), _T("Grey - 50") }, 00081 00082 { RGB(0xFF, 0xC0, 0xCB), _T("Pink") }, 00083 { RGB(0xFF, 0xD7, 0x00), _T("Gold") }, 00084 { RGB(0xFF, 0xFF, 0x00), _T("Yellow") }, 00085 { RGB(0x00, 0xFF, 0x00), _T("Bright green") }, 00086 { RGB(0x40, 0xE0, 0xD0), _T("Turquoise") }, 00087 { RGB(0xC0, 0xFF, 0xFF), _T("Skyblue") }, 00088 { RGB(0x48, 0x00, 0x48), _T("Plum") }, 00089 { RGB(0xC0, 0xC0, 0xC0), _T("Light grey") }, 00090 00091 { RGB(0xFF, 0xE4, 0xE1), _T("Rose") }, 00092 { RGB(0xD2, 0xB4, 0x8C), _T("Tan") }, 00093 { RGB(0xFF, 0xFF, 0xE0), _T("Light yellow") }, 00094 { RGB(0x98, 0xFB, 0x98), _T("Pale green ") }, 00095 { RGB(0xAF, 0xEE, 0xEE), _T("Pale turquoise") }, 00096 { RGB(0x68, 0x83, 0x8B), _T("Pale blue") }, 00097 { RGB(0xE6, 0xE6, 0xFA), _T("Lavender") }, 00098 { RGB(0xFF, 0xFF, 0xFF), _T("White") } 00099 }; 00100 00102 // CColourPopup 00103 00104 CColourPopup::CColourPopup(CWnd* pParent /*=NULL*/) 00105 : CDialog(CColourPopup::IDD, pParent) 00106 { 00107 m_bFirstMouseMsgReceived = false; 00108 } 00109 00110 CColourPopup::~CColourPopup() 00111 { 00112 m_Font.DeleteObject(); 00113 m_Palette.DeleteObject(); 00114 } 00115 00117 // CColourPopup implementation 00118 00119 // Works out an appropriate size and position of this window 00120 void CColourPopup::SetWindowSize(void) 00121 { 00122 CSize TextSize; 00123 00124 // If we are showing a custom or default text area, get the font and text size. 00125 if (m_strCustomText.GetLength() || m_strDefaultText.GetLength()) 00126 { 00127 CClientDC dc(this); 00128 CFont* pOldFont = (CFont*) dc.SelectObject(&m_Font); 00129 00130 // Get the size of the custom text (if there IS custom text) 00131 TextSize = CSize(0,0); 00132 if (m_strCustomText.GetLength()) 00133 TextSize = dc.GetTextExtent(m_strCustomText); 00134 00135 // Get the size of the default text (if there IS default text) 00136 if (m_strDefaultText.GetLength()) 00137 { 00138 CSize DefaultSize = dc.GetTextExtent(m_strDefaultText); 00139 if (DefaultSize.cx > TextSize.cx) TextSize.cx = DefaultSize.cx; 00140 if (DefaultSize.cy > TextSize.cy) TextSize.cy = DefaultSize.cy; 00141 } 00142 00143 dc.SelectObject(pOldFont); 00144 TextSize += CSize(2*m_nMargin,2*m_nMargin); 00145 00146 // Add even more space to draw the horizontal line 00147 TextSize.cy += 2*m_nMargin + 2; 00148 } 00149 00150 // Get the number of columns and rows 00151 //m_nNumColumns = (int) sqrt((double)m_nNumColours); // for a square window (yuk) 00152 m_nNumColumns = 8; 00153 m_nNumRows = m_nNumColours / m_nNumColumns; 00154 if (m_nNumColours % m_nNumColumns) m_nNumRows++; 00155 00156 // Get the current window position, and set the new size 00157 CRect rect; 00158 GetWindowRect(rect); 00159 00160 m_WindowRect.SetRect(rect.left, rect.top, 00161 rect.left + m_nNumColumns*m_nBoxSize + 2*m_nMargin, 00162 rect.top + m_nNumRows*m_nBoxSize + 2*m_nMargin); 00163 00164 // if custom text, then expand window if necessary, and set text width as 00165 // window width 00166 if (m_strDefaultText.GetLength()) 00167 { 00168 if (TextSize.cx > m_WindowRect.Width()) 00169 m_WindowRect.right = m_WindowRect.left + TextSize.cx; 00170 TextSize.cx = m_WindowRect.Width()-2*m_nMargin; 00171 00172 // Work out the text area 00173 m_DefaultTextRect.SetRect(m_nMargin, m_nMargin, 00174 m_nMargin+TextSize.cx, 2*m_nMargin+TextSize.cy); 00175 m_WindowRect.bottom += m_DefaultTextRect.Height() + 2*m_nMargin; 00176 } 00177 00178 // if custom text, then expand window if necessary, and set text width as 00179 // window width 00180 if (m_strCustomText.GetLength()) 00181 { 00182 if (TextSize.cx > m_WindowRect.Width()) 00183 m_WindowRect.right = m_WindowRect.left + TextSize.cx; 00184 TextSize.cx = m_WindowRect.Width()-2*m_nMargin; 00185 00186 // Work out the text area 00187 m_CustomTextRect.SetRect(m_nMargin, m_WindowRect.Height(), 00188 m_nMargin+TextSize.cx, 00189 m_WindowRect.Height()+m_nMargin+TextSize.cy); 00190 m_WindowRect.bottom += m_CustomTextRect.Height() + 2*m_nMargin; 00191 } 00192 00193 // Need to check it'll fit on screen: Too far right? 00194 // 00195 // Beware of multi monitor systems! GetSystemMetrics(SM_CYSCREEN) and GetSystemMetrics(SM_CXSCREEN) is just for the primary screen! 00196 // We will use the dimensions of the virtual screen area (composed by the multiple monitor), 00197 // but we assume rectangular area, so if the area is composed by different resolution monitors this safety code 00198 // can be also misleading, but 99% it will be good. For more info see MSDN chapters about multiple monitor displays: 00199 // http://msdn.microsoft.com/en-us/library/ms534611(VS.85).aspx 00200 00201 int virtualScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN); 00202 int virtualScreenTop = GetSystemMetrics(SM_YVIRTUALSCREEN); 00203 int virtualScreenRight = virtualScreenLeft + GetSystemMetrics(SM_CXVIRTUALSCREEN); 00204 int virtualScreenBottom = virtualScreenTop + GetSystemMetrics(SM_CYVIRTUALSCREEN); 00205 00206 // Too far right? 00207 if (m_WindowRect.right > virtualScreenRight) 00208 m_WindowRect.OffsetRect(virtualScreenRight - m_WindowRect.right, 0); 00209 00210 // Too far left? 00211 if (m_WindowRect.left < virtualScreenLeft) 00212 m_WindowRect.OffsetRect(virtualScreenLeft - m_WindowRect.left, 0); 00213 00214 // Too far top? 00215 if (m_WindowRect.top < virtualScreenTop) 00216 m_WindowRect.OffsetRect(virtualScreenTop - m_WindowRect.top, 0); 00217 00218 // Bottom falling out of screen? 00219 if (m_WindowRect.bottom > virtualScreenBottom) 00220 m_WindowRect.OffsetRect(virtualScreenBottom - m_WindowRect.bottom, 0); 00221 00222 // Set the window size and position 00223 MoveWindow(m_WindowRect, TRUE); 00224 } 00225 00226 void CColourPopup::SetParameters(CRect rectBound, COLORREF crColour, bool rightSideClick, 00227 LPCTSTR szDefaultText, LPCTSTR szCustomText) 00228 { 00229 m_RectBound = rectBound; 00230 m_crColour = m_crInitialColour = crColour; 00231 m_bRightSideClick= rightSideClick; 00232 m_strDefaultText = (szDefaultText)? szDefaultText : _T(""); 00233 m_strCustomText = (szCustomText)? szCustomText : _T(""); 00234 } 00235 00236 void CColourPopup::Initialize() 00237 { 00238 m_nNumColours = sizeof(m_crColours)/sizeof(ColourTableEntry); 00239 ASSERT(m_nNumColours <= MAX_COLOURS); 00240 if (m_nNumColours > MAX_COLOURS) 00241 m_nNumColours = MAX_COLOURS; 00242 00243 m_nNumColumns = 0; 00244 m_nNumRows = 0; 00245 m_nBoxSize = 18; 00246 m_nMargin = ::GetSystemMetrics(SM_CXEDGE); 00247 m_nCurrentSel = INVALID_COLOUR; 00248 m_nChosenColourSel = INVALID_COLOUR; 00249 m_crColour = m_crInitialColour = RGB(0,0,0); 00250 00251 m_bChildWindowVisible = FALSE; 00252 00253 // Idiot check: Make sure the colour square is at least 5 x 5; 00254 if (m_nBoxSize - 2*m_nMargin - 2 < 5) m_nBoxSize = 5 + 2*m_nMargin + 2; 00255 00256 // Create the font 00257 NONCLIENTMETRICS ncm; 00258 ncm.cbSize = sizeof(NONCLIENTMETRICS); 00259 VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)); 00260 m_Font.CreateFontIndirect(&(ncm.lfMessageFont)); 00261 00262 // Create the palette 00263 struct { 00264 LOGPALETTE LogPalette; 00265 PALETTEENTRY PalEntry[MAX_COLOURS]; 00266 } pal; 00267 00268 LOGPALETTE* pLogPalette = (LOGPALETTE*) &pal; 00269 pLogPalette->palVersion = 0x300; 00270 pLogPalette->palNumEntries = (WORD) m_nNumColours; 00271 00272 for (int i = 0; i < m_nNumColours; i++) 00273 { 00274 pLogPalette->palPalEntry[i].peRed = GetRValue(m_crColours[i].crColour); 00275 pLogPalette->palPalEntry[i].peGreen = GetGValue(m_crColours[i].crColour); 00276 pLogPalette->palPalEntry[i].peBlue = GetBValue(m_crColours[i].crColour); 00277 pLogPalette->palPalEntry[i].peFlags = 0; 00278 } 00279 00280 m_Palette.CreatePalette(pLogPalette); 00281 } 00282 00283 int CColourPopup::GetIndex(int row, int col) const 00284 { 00285 if ((row == CUSTOM_BOX_VALUE || col == CUSTOM_BOX_VALUE) && m_strCustomText.GetLength()) 00286 return CUSTOM_BOX_VALUE; 00287 else if ((row == DEFAULT_BOX_VALUE || col == DEFAULT_BOX_VALUE) && m_strDefaultText.GetLength()) 00288 return DEFAULT_BOX_VALUE; 00289 else if (row < 0 || col < 0 || row >= m_nNumRows || col >= m_nNumColumns) 00290 return INVALID_COLOUR; 00291 else 00292 { 00293 if (row*m_nNumColumns + col >= m_nNumColours) 00294 return INVALID_COLOUR; 00295 else 00296 return row*m_nNumColumns + col; 00297 } 00298 } 00299 00300 int CColourPopup::GetRow(int nIndex) const 00301 { 00302 if (nIndex == CUSTOM_BOX_VALUE && m_strCustomText.GetLength()) 00303 return CUSTOM_BOX_VALUE; 00304 else if (nIndex == DEFAULT_BOX_VALUE && m_strDefaultText.GetLength()) 00305 return DEFAULT_BOX_VALUE; 00306 else if (nIndex < 0 || nIndex >= m_nNumColours) 00307 return INVALID_COLOUR; 00308 else 00309 return nIndex / m_nNumColumns; 00310 } 00311 00312 int CColourPopup::GetColumn(int nIndex) const 00313 { 00314 if (nIndex == CUSTOM_BOX_VALUE && m_strCustomText.GetLength()) 00315 return CUSTOM_BOX_VALUE; 00316 else if (nIndex == DEFAULT_BOX_VALUE && m_strDefaultText.GetLength()) 00317 return DEFAULT_BOX_VALUE; 00318 else if (nIndex < 0 || nIndex >= m_nNumColours) 00319 return INVALID_COLOUR; 00320 else 00321 return nIndex % m_nNumColumns; 00322 } 00323 00324 void CColourPopup::FindCellFromColour(COLORREF crColour) 00325 { 00326 if (crColour == CLR_DEFAULT && m_strDefaultText.GetLength()) 00327 { 00328 m_nChosenColourSel = DEFAULT_BOX_VALUE; 00329 return; 00330 } 00331 00332 for (int i = 0; i < m_nNumColours; i++) 00333 { 00334 if (GetColour(i) == crColour) 00335 { 00336 m_nChosenColourSel = i; 00337 return; 00338 } 00339 } 00340 00341 if (m_strCustomText.GetLength()) 00342 m_nChosenColourSel = CUSTOM_BOX_VALUE; 00343 else 00344 m_nChosenColourSel = INVALID_COLOUR; 00345 } 00346 00347 // Gets the dimensions of the colour cell given by (row,col) 00348 BOOL CColourPopup::GetCellRect(int nIndex, const LPRECT& rect) 00349 { 00350 if (nIndex == CUSTOM_BOX_VALUE) 00351 { 00352 ::SetRect(rect, 00353 m_CustomTextRect.left, m_CustomTextRect.top, 00354 m_CustomTextRect.right, m_CustomTextRect.bottom); 00355 return TRUE; 00356 } 00357 else if (nIndex == DEFAULT_BOX_VALUE) 00358 { 00359 ::SetRect(rect, 00360 m_DefaultTextRect.left, m_DefaultTextRect.top, 00361 m_DefaultTextRect.right, m_DefaultTextRect.bottom); 00362 return TRUE; 00363 } 00364 00365 if (nIndex < 0 || nIndex >= m_nNumColours) 00366 return FALSE; 00367 00368 rect->left = GetColumn(nIndex) * m_nBoxSize + m_nMargin; 00369 rect->top = GetRow(nIndex) * m_nBoxSize + m_nMargin; 00370 00371 // Move everything down if we are displaying a default text area 00372 if (m_strDefaultText.GetLength()) 00373 rect->top += (m_nMargin + m_DefaultTextRect.Height()); 00374 00375 rect->right = rect->left + m_nBoxSize; 00376 rect->bottom = rect->top + m_nBoxSize; 00377 00378 return TRUE; 00379 } 00380 00381 void CColourPopup::CreateToolTips() 00382 { 00383 // Create the tool tip 00384 if (!m_ToolTip.Create(this)) return; 00385 00386 // Add a tool for each cell 00387 for (int i = 0; i < m_nNumColours; i++) 00388 { 00389 CRect rect; 00390 if (!GetCellRect(i, rect)) continue; 00391 m_ToolTip.AddTool(this, GetColourName(i), rect, 1); 00392 } 00393 } 00394 00395 void CColourPopup::ChangeSelection(int nIndex) 00396 { 00397 CClientDC dc(this); // device context for drawing 00398 00399 if (nIndex > m_nNumColours) 00400 nIndex = CUSTOM_BOX_VALUE; 00401 00402 if ((m_nCurrentSel >= 0 && m_nCurrentSel < m_nNumColours) || 00403 m_nCurrentSel == CUSTOM_BOX_VALUE || m_nCurrentSel == DEFAULT_BOX_VALUE) 00404 { 00405 // Set Current selection as invalid and redraw old selection (this way 00406 // the old selection will be drawn unselected) 00407 int OldSel = m_nCurrentSel; 00408 m_nCurrentSel = INVALID_COLOUR; 00409 DrawCell(&dc, OldSel); 00410 } 00411 00412 // Set the current selection as row/col and draw (it will be drawn selected) 00413 m_nCurrentSel = nIndex; 00414 DrawCell(&dc, m_nCurrentSel); 00415 00416 // Store the current colour 00417 if (m_nCurrentSel == DEFAULT_BOX_VALUE) 00418 { 00419 m_crColour = CLR_DEFAULT; 00420 } 00421 else 00422 { 00423 m_crColour = GetColour(m_nCurrentSel); 00424 } 00425 } 00426 00427 void CColourPopup::EndSelection(int nMessage) 00428 { 00429 ReleaseCapture(); 00430 00431 // If custom text selected, perform a custom colour selection 00432 if (nMessage != IDCANCEL && m_nCurrentSel == CUSTOM_BOX_VALUE) 00433 { 00434 m_bChildWindowVisible = TRUE; 00435 00436 CColorDialog dlg(m_crInitialColour, CC_FULLOPEN | CC_ANYCOLOR, this); 00437 00438 if (dlg.DoModal() == IDOK) 00439 m_crColour = dlg.GetColor(); 00440 else 00441 nMessage = IDCANCEL; 00442 00443 m_bChildWindowVisible = FALSE; 00444 } 00445 00446 if (nMessage == IDCANCEL) 00447 m_crColour = m_crInitialColour; 00448 00449 if (nMessage == IDCANCEL) 00450 OnCancel(); 00451 else 00452 OnOK(); 00453 } 00454 00455 void CColourPopup::DrawCell(CDC* pDC, int nIndex) 00456 { 00457 // For the Custom Text area 00458 if (m_strCustomText.GetLength() && nIndex == CUSTOM_BOX_VALUE) 00459 { 00460 // The extent of the actual text button 00461 CRect TextButtonRect = m_CustomTextRect; 00462 TextButtonRect.top += 2*m_nMargin; 00463 00464 // Fill background 00465 pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DFACE)); 00466 00467 // Draw horizontal line 00468 pDC->FillSolidRect(m_CustomTextRect.left+2*m_nMargin, m_CustomTextRect.top, 00469 m_CustomTextRect.Width()-4*m_nMargin, 1, ::GetSysColor(COLOR_3DSHADOW)); 00470 pDC->FillSolidRect(m_CustomTextRect.left+2*m_nMargin, m_CustomTextRect.top+1, 00471 m_CustomTextRect.Width()-4*m_nMargin, 1, ::GetSysColor(COLOR_3DHILIGHT)); 00472 00473 TextButtonRect.DeflateRect(1,1); 00474 00475 // fill background 00476 if (m_nChosenColourSel == nIndex && m_nCurrentSel != nIndex) 00477 pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DLIGHT)); 00478 else 00479 pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DFACE)); 00480 00481 // Draw button 00482 if (m_nCurrentSel == nIndex) 00483 pDC->DrawEdge(TextButtonRect, BDR_RAISEDINNER, BF_RECT); 00484 else if (m_nChosenColourSel == nIndex) 00485 pDC->DrawEdge(TextButtonRect, BDR_SUNKENOUTER, BF_RECT); 00486 00487 // Draw custom text 00488 CFont *pOldFont = (CFont*) pDC->SelectObject(&m_Font); 00489 pDC->SetBkMode(TRANSPARENT); 00490 pDC->DrawText(m_strCustomText, TextButtonRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 00491 pDC->SelectObject(pOldFont); 00492 00493 return; 00494 } 00495 00496 // For the Default Text area 00497 if (m_strDefaultText.GetLength() && nIndex == DEFAULT_BOX_VALUE) 00498 { 00499 // Fill background 00500 pDC->FillSolidRect(m_DefaultTextRect, ::GetSysColor(COLOR_3DFACE)); 00501 00502 // The extent of the actual text button 00503 CRect TextButtonRect = m_DefaultTextRect; 00504 TextButtonRect.DeflateRect(1,1); 00505 00506 // fill background 00507 if (m_nChosenColourSel == nIndex && m_nCurrentSel != nIndex) 00508 pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DLIGHT)); 00509 else 00510 pDC->FillSolidRect(TextButtonRect, ::GetSysColor(COLOR_3DFACE)); 00511 00512 // Draw thin line around text 00513 CRect LineRect = TextButtonRect; 00514 LineRect.DeflateRect(2*m_nMargin,2*m_nMargin); 00515 CPen pen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); 00516 CPen* pOldPen = pDC->SelectObject(&pen); 00517 pDC->SelectStockObject(NULL_BRUSH); 00518 pDC->Rectangle(LineRect); 00519 pDC->SelectObject(pOldPen); 00520 00521 // Draw button 00522 if (m_nCurrentSel == nIndex) 00523 pDC->DrawEdge(TextButtonRect, BDR_RAISEDINNER, BF_RECT); 00524 else if (m_nChosenColourSel == nIndex) 00525 pDC->DrawEdge(TextButtonRect, BDR_SUNKENOUTER, BF_RECT); 00526 00527 // Draw custom text 00528 CFont *pOldFont = (CFont*) pDC->SelectObject(&m_Font); 00529 pDC->SetBkMode(TRANSPARENT); 00530 pDC->DrawText(m_strDefaultText, TextButtonRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 00531 pDC->SelectObject(pOldFont); 00532 00533 return; 00534 } 00535 00536 CRect rect; 00537 if (!GetCellRect(nIndex, rect)) return; 00538 00539 // Select and realize the palette 00540 CPalette* pOldPalette = NULL; 00541 if (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) 00542 { 00543 pOldPalette = pDC->SelectPalette(&m_Palette, FALSE); 00544 pDC->RealizePalette(); 00545 } 00546 00547 // fill background 00548 if (m_nChosenColourSel == nIndex && m_nCurrentSel != nIndex) 00549 pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DHILIGHT)); 00550 else 00551 pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE)); 00552 00553 // Draw button 00554 if (m_nCurrentSel == nIndex) 00555 pDC->DrawEdge(rect, BDR_RAISEDINNER, BF_RECT); 00556 else if (m_nChosenColourSel == nIndex) 00557 pDC->DrawEdge(rect, BDR_SUNKENOUTER, BF_RECT); 00558 00559 CBrush brush(PALETTERGB(GetRValue(GetColour(nIndex)), 00560 GetGValue(GetColour(nIndex)), 00561 GetBValue(GetColour(nIndex)) )); 00562 CPen pen; 00563 pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); 00564 00565 CBrush* pOldBrush = (CBrush*) pDC->SelectObject(&brush); 00566 CPen* pOldPen = (CPen*) pDC->SelectObject(&pen); 00567 00568 // Draw the cell colour 00569 rect.DeflateRect(m_nMargin+1, m_nMargin+1); 00570 pDC->Rectangle(rect); 00571 00572 // restore DC and cleanup 00573 pDC->SelectObject(pOldBrush); 00574 pDC->SelectObject(pOldPen); 00575 brush.DeleteObject(); 00576 pen.DeleteObject(); 00577 00578 if (pOldPalette && pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) 00579 pDC->SelectPalette(pOldPalette, FALSE); 00580 } 00581 00582 00583 BEGIN_MESSAGE_MAP(CColourPopup, CWnd) 00584 //{{AFX_MSG_MAP(CColourPopup) 00585 ON_WM_DESTROY() 00586 ON_WM_LBUTTONUP() 00587 ON_WM_LBUTTONDBLCLK() 00588 ON_WM_PAINT() 00589 ON_WM_MOUSEMOVE() 00590 ON_WM_KEYDOWN() 00591 ON_WM_QUERYNEWPALETTE() 00592 ON_WM_PALETTECHANGED() 00593 //}}AFX_MSG_MAP 00594 END_MESSAGE_MAP() 00595 00597 // CColourPopup message handlers 00598 00599 // CColourPopup message handlers 00600 00601 BOOL CColourPopup::OnInitDialog() 00602 { 00603 CDialog::OnInitDialog(); 00604 00605 Initialize(); 00606 00607 ASSERT(GetParent() && ::IsWindow(GetParent()->GetSafeHwnd())); 00608 00609 // Set the window size 00610 SetWindowSize(); 00611 00612 // Create the tooltips 00613 CreateToolTips(); 00614 00615 // Find which cell (if any) corresponds to the initial colour 00616 FindCellFromColour(m_crColour); 00617 00618 // Capture the mouse, this allows the dialog to close when the user clicks outside. 00619 // The dialog has no "close" button. 00620 SetCapture(); 00621 00622 // Align right 00623 CRect rectWnd; 00624 GetWindowRect(rectWnd); 00625 int nXOffset = m_RectBound.right - rectWnd.right; 00626 SetWindowPos(NULL, rectWnd.left + nXOffset, m_RectBound.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); 00627 SetWindowSize(); 00628 00629 if (!m_bRightSideClick) 00630 m_bFirstMouseMsgReceived = true; 00631 00632 return TRUE; // return TRUE unless you set the focus to a control 00633 // EXCEPTION: OCX Property Pages should return FALSE 00634 } 00635 00636 void CColourPopup::OnDestroy() 00637 { 00638 ReleaseCapture(); 00639 00640 CDialog::OnDestroy(); 00641 } 00642 00643 // If an arrow key is pressed, then move the selection 00644 void CColourPopup::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 00645 { 00646 int row = GetRow(m_nCurrentSel), 00647 col = GetColumn(m_nCurrentSel); 00648 00649 if (nChar == VK_DOWN) 00650 { 00651 if (row == DEFAULT_BOX_VALUE) 00652 row = col = 0; 00653 else if (row == CUSTOM_BOX_VALUE) 00654 { 00655 if (m_strDefaultText.GetLength()) 00656 row = col = DEFAULT_BOX_VALUE; 00657 else 00658 row = col = 0; 00659 } 00660 else 00661 { 00662 row++; 00663 if (GetIndex(row,col) < 0) 00664 { 00665 if (m_strCustomText.GetLength()) 00666 row = col = CUSTOM_BOX_VALUE; 00667 else if (m_strDefaultText.GetLength()) 00668 row = col = DEFAULT_BOX_VALUE; 00669 else 00670 row = col = 0; 00671 } 00672 } 00673 ChangeSelection(GetIndex(row, col)); 00674 } 00675 00676 if (nChar == VK_UP) 00677 { 00678 if (row == DEFAULT_BOX_VALUE) 00679 { 00680 if (m_strCustomText.GetLength()) 00681 row = col = CUSTOM_BOX_VALUE; 00682 else 00683 { 00684 row = GetRow(m_nNumColours-1); 00685 col = GetColumn(m_nNumColours-1); 00686 } 00687 } 00688 else if (row == CUSTOM_BOX_VALUE) 00689 { 00690 row = GetRow(m_nNumColours-1); 00691 col = GetColumn(m_nNumColours-1); 00692 } 00693 else if (row > 0) row--; 00694 else /* row == 0 */ 00695 { 00696 if (m_strDefaultText.GetLength()) 00697 row = col = DEFAULT_BOX_VALUE; 00698 else if (m_strCustomText.GetLength()) 00699 row = col = CUSTOM_BOX_VALUE; 00700 else 00701 { 00702 row = GetRow(m_nNumColours-1); 00703 col = GetColumn(m_nNumColours-1); 00704 } 00705 } 00706 ChangeSelection(GetIndex(row, col)); 00707 } 00708 00709 if (nChar == VK_RIGHT) 00710 { 00711 if (row == DEFAULT_BOX_VALUE) 00712 row = col = 0; 00713 else if (row == CUSTOM_BOX_VALUE) 00714 { 00715 if (m_strDefaultText.GetLength()) 00716 row = col = DEFAULT_BOX_VALUE; 00717 else 00718 row = col = 0; 00719 } 00720 else if (col < m_nNumColumns-1) 00721 col++; 00722 else 00723 { 00724 col = 0; row++; 00725 } 00726 00727 if (GetIndex(row,col) == INVALID_COLOUR) 00728 { 00729 if (m_strCustomText.GetLength()) 00730 row = col = CUSTOM_BOX_VALUE; 00731 else if (m_strDefaultText.GetLength()) 00732 row = col = DEFAULT_BOX_VALUE; 00733 else 00734 row = col = 0; 00735 } 00736 00737 ChangeSelection(GetIndex(row, col)); 00738 } 00739 00740 if (nChar == VK_LEFT) 00741 { 00742 if (row == DEFAULT_BOX_VALUE) 00743 { 00744 if (m_strCustomText.GetLength()) 00745 row = col = CUSTOM_BOX_VALUE; 00746 else 00747 { 00748 row = GetRow(m_nNumColours-1); 00749 col = GetColumn(m_nNumColours-1); 00750 } 00751 } 00752 else if (row == CUSTOM_BOX_VALUE) 00753 { 00754 row = GetRow(m_nNumColours-1); 00755 col = GetColumn(m_nNumColours-1); 00756 } 00757 else if (col > 0) col--; 00758 else /* col == 0 */ 00759 { 00760 if (row > 0) { row--; col = m_nNumColumns-1; } 00761 else 00762 { 00763 if (m_strDefaultText.GetLength()) 00764 row = col = DEFAULT_BOX_VALUE; 00765 else if (m_strCustomText.GetLength()) 00766 row = col = CUSTOM_BOX_VALUE; 00767 else 00768 { 00769 row = GetRow(m_nNumColours-1); 00770 col = GetColumn(m_nNumColours-1); 00771 } 00772 } 00773 } 00774 ChangeSelection(GetIndex(row, col)); 00775 } 00776 00777 if (nChar == VK_ESCAPE) 00778 { 00779 m_crColour = m_crInitialColour; 00780 EndSelection(IDCANCEL); 00781 return; 00782 } 00783 00784 if (nChar == VK_RETURN || nChar == VK_SPACE) 00785 { 00786 EndSelection(IDOK); 00787 return; 00788 } 00789 00790 CDialog::OnKeyDown(nChar, nRepCnt, nFlags); 00791 } 00792 00793 void CColourPopup::OnPaint() 00794 { 00795 CPaintDC dc(this); // device context for painting 00796 00797 // Draw the Default Area text 00798 if (m_strDefaultText.GetLength()) 00799 DrawCell(&dc, DEFAULT_BOX_VALUE); 00800 00801 // Draw colour cells 00802 for (int i = 0; i < m_nNumColours; i++) 00803 DrawCell(&dc, i); 00804 00805 // Draw custom text 00806 if (m_strCustomText.GetLength()) 00807 DrawCell(&dc, CUSTOM_BOX_VALUE); 00808 00809 // Draw raised window edge (ex-window style WS_EX_WINDOWEDGE is sposed to do this, 00810 // but for some reason isn't 00811 CRect rect; 00812 GetClientRect(rect); 00813 dc.DrawEdge(rect, EDGE_RAISED, BF_RECT); 00814 } 00815 00816 void CColourPopup::OnMouseMove(UINT nFlags, CPoint point) 00817 { 00818 int nNewSelection = INVALID_COLOUR; 00819 00820 // Translate points to be relative raised window edge 00821 point.x -= m_nMargin; 00822 point.y -= m_nMargin; 00823 00824 // First check we aren't in text box 00825 if (m_strCustomText.GetLength() && m_CustomTextRect.PtInRect(point)) 00826 nNewSelection = CUSTOM_BOX_VALUE; 00827 else if (m_strDefaultText.GetLength() && m_DefaultTextRect.PtInRect(point)) 00828 nNewSelection = DEFAULT_BOX_VALUE; 00829 else 00830 { 00831 // Take into account text box 00832 if (m_strDefaultText.GetLength()) 00833 point.y -= m_DefaultTextRect.Height(); 00834 00835 // Get the row and column 00836 nNewSelection = GetIndex(point.y / m_nBoxSize, point.x / m_nBoxSize); 00837 00838 // In range? If not, default and exit 00839 if (nNewSelection < 0 || nNewSelection >= m_nNumColours) 00840 { 00841 CDialog::OnMouseMove(nFlags, point); 00842 return; 00843 } 00844 } 00845 00846 // OK - we have the row and column of the current selection (may be CUSTOM_BOX_VALUE) 00847 // Has the row/col selection changed? If yes, then redraw old and new cells. 00848 if (nNewSelection != m_nCurrentSel) 00849 ChangeSelection(nNewSelection); 00850 00851 CDialog::OnMouseMove(nFlags, point); 00852 } 00853 00854 // End selection on LButtonUp 00855 void CColourPopup::OnLButtonUp(UINT nFlags, CPoint point) 00856 { 00857 CDialog::OnLButtonUp(nFlags, point); 00858 00859 if (!m_bFirstMouseMsgReceived) { 00860 m_bFirstMouseMsgReceived = true; 00861 return; 00862 } 00863 00864 CPoint sPoint = point; 00865 ClientToScreen(&sPoint); 00866 CRect cRect; 00867 GetClientRect(&cRect); 00868 if (cRect.PtInRect(point)) { 00869 EndSelection(IDOK); 00870 } else { 00871 EndSelection(IDCANCEL); 00872 RelayMouseClickToInspectorList(m_pParentWnd, sPoint); 00873 } 00874 } 00875 00876 BOOL CColourPopup::OnQueryNewPalette() 00877 { 00878 Invalidate(); 00879 return CDialog::OnQueryNewPalette(); 00880 } 00881 00882 void CColourPopup::OnPaletteChanged(CWnd* pFocusWnd) 00883 { 00884 CDialog::OnPaletteChanged(pFocusWnd); 00885 00886 if (pFocusWnd->GetSafeHwnd() != GetSafeHwnd()) 00887 Invalidate(); 00888 } 00889 00890 void CColourPopup::EndDialog(int nResult) 00891 { 00892 ReleaseCapture(); 00893 00894 CDialog::EndDialog(nResult); 00895 } 00896 00897 // For tooltips 00898 BOOL CColourPopup::PreTranslateMessage(MSG* pMsg) 00899 { 00900 m_ToolTip.RelayEvent(pMsg); 00901 00902 // Fix (Adrian Roman): Sometimes if the picker loses focus it is never destroyed 00903 if (GetCapture()->GetSafeHwnd() != m_hWnd) 00904 SetCapture(); 00905 00906 return CWnd::PreTranslateMessage(pMsg); 00907 }