00001 // $Id: scrlbutn.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 // 00099 // Custom Windows scroll bar button. This object is used by the (private) 00100 // implementation of CScroller. 00101 // 00102 00103 00104 #include "camtypes.h" 00105 00106 #include "scroller.h" 00107 #include "scrlbutn.h" 00108 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 #include "mainfrm.h" 00110 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 #include "brushmsg.h" 00112 00113 #ifdef _DEBUG 00114 #undef THIS_FILE 00115 static char BASED_CODE THIS_FILE[] = __FILE__; 00116 #endif 00117 00118 00119 DECLARE_SOURCE("$Revision: 1282 $"); 00120 00121 00122 00123 00124 BEGIN_MESSAGE_MAP(CScrollerButton, CBitmapButton) 00125 //{{AFX_MSG_MAP(CScrollerButton) 00126 ON_WM_LBUTTONDOWN() 00127 ON_WM_LBUTTONUP() 00128 ON_WM_RBUTTONDOWN() 00129 ON_WM_RBUTTONUP() 00130 ON_WM_TIMER() 00131 ON_WM_CANCELMODE() 00132 ON_WM_LBUTTONDBLCLK() 00133 ON_WM_RBUTTONDBLCLK() 00134 //}}AFX_MSG_MAP 00135 END_MESSAGE_MAP() 00136 00137 00138 00139 00140 UINT32 CScrollerButton::BitmapNames[4][3] = 00141 { 00142 { OBM_UPARROW, OBM_UPARROWD, OBM_UPARROWI }, 00143 { OBM_DNARROW, OBM_DNARROWD, OBM_DNARROWI }, 00144 { OBM_LFARROW, OBM_LFARROWD, OBM_LFARROWI }, 00145 { OBM_RGARROW, OBM_RGARROWD, OBM_RGARROWI } 00146 }; 00147 00148 00149 00150 00151 /********************************************************************************************* 00152 > CScrollerButton::CScrollerButton(CScroller::Orientation ort, UINT32 msg) 00153 00154 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00155 Created: ages ago 00156 Inputs: The orientation of the bitmap on the button's face, the message the button 00157 button should send the CScroller parent when it is clicked. 00158 Outputs: - 00159 Returns: - 00160 Purpose: Constructs a CScrollerButton with the appropriate face. 00161 Errors: ENSURE failure if, for any stupid reason, the orientation is invalid. 00162 Scope: Public 00163 SeeAlso: CScrollerButton::Create(); CScroller::OnCreate() 00164 00165 **********************************************************************************************/ 00166 CScrollerButton::CScrollerButton(CScrollerButton::Orientation ort, UINT32 msg) 00167 : CBitmapButton(), Orient(ort), Message(msg) 00168 { 00169 // So far, very little to do here. 00170 ENSURE(ort >= CScrollerButton::UP && ort <= CScrollerButton::RIGHT, 00171 "Unknown orientation code passed to scroller button constructor!\n"); 00172 } 00173 00174 00175 00176 /********************************************************************************************* 00177 > virtual BOOL CScrollerButton::Create(LPCTSTR, DWORD style, const RECT& rect, 00178 CWnd* parent, UINT32 id) 00179 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00180 Created: ages ago 00181 Inputs: A dummy long pointer, not used; the window-instance style flags, a rectangle 00182 describing the button's size and position; a pointer to the parent window (a 00183 CScroller derivative); a numeric child window identifier. 00184 Outputs: - 00185 Returns: TRUE if the button is successfully created, and all bitmaps it requires 00186 are successfully extracted from the dislay driver. 00187 Purpose: Try to connect the C++ button object to the appropriate Windows 00188 interface object. As an aid to the programmer we load the bitmaps 00189 used for the button here, instead of requiring the owner to do it. 00190 Errors: - 00191 Scope: Public 00192 SeeAlso: CScrollerButton::CScrollerButton(); CScroller::OnCreate() 00193 00194 **********************************************************************************************/ 00195 BOOL CScrollerButton::Create(LPCTSTR, DWORD style, const RECT& rect, 00196 CWnd* parent, UINT32 id) 00197 { 00198 return CBitmapButton::Create("", 00199 style | WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD 00200 | BS_OWNERDRAW | BS_PUSHBUTTON, 00201 rect, 00202 parent, 00203 id) 00204 && LoadOEMBitmaps(BitmapNames[Orient][0], // button up 00205 BitmapNames[Orient][1], // button down 00206 BitmapNames[Orient][2]); // disabled 00207 } 00208 00209 00210 00211 /********************************************************************************************* 00212 > virtual BOOL CScrollerButton::LoadOEMBitmaps(UINT32 upID, UINT32 downID, UINT32 disableID) 00213 00214 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00215 Created: ages ago 00216 Inputs: The resource identifier of the bitmap displayed on the button when it is 00217 "up", ie. not clicked; the ID of the "down" bitmap; the ID of the "disabled" 00218 bitmap. 00219 Outputs: - 00220 Returns: TRUE if the bitmaps are successfully extracted from the display driver, FALSE 00221 if some essential bitmaps cannot be extracted. 00222 Purpose: Some display drivers, such as the ET4000, do not contain a "disabled" bitmap 00223 for scroll bars buttons. In this case the function substitutes the "up" 00224 bitmap for the "disabled" bitmap. 00225 Errors: - 00226 Scope: Private 00227 SeeAlso: CScrollerButton::Create() 00228 00229 **********************************************************************************************/ 00230 BOOL CScrollerButton::LoadOEMBitmaps(UINT32 upID, UINT32 downID, UINT32 disableID) 00231 { 00232 m_bitmap.DeleteObject(); 00233 m_bitmapSel.DeleteObject(); 00234 m_bitmapDisabled.DeleteObject(); 00235 00236 #ifndef _MAC 00237 // The up/down bitmaps are essential and must be present. 00238 if (!m_bitmap.LoadOEMBitmap(upID) || !m_bitmapSel.LoadOEMBitmap(downID)) 00239 return FALSE; 00240 00241 // The disabled bitmap is not essential, and if not present, the up 00242 // bitmap can be substituted for it. 00243 if (!m_bitmapDisabled.LoadOEMBitmap(disableID)) 00244 m_bitmapDisabled.LoadOEMBitmap(upID); 00245 #endif 00246 return TRUE; 00247 } 00248 00249 00250 00252 // Implementation. 00253 00254 00255 /********************************************************************************************* 00256 > void CScrollerButton::HandleButtonDown(BOOL reverse) 00257 00258 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00259 Created: ages ago 00260 Inputs: A boolean which if TRUE indicates that the button is responding to a click 00261 with the right mouse button, so the scroll is in the opposite direction. 00262 Outputs: - 00263 Returns: - 00264 Purpose: Captures the mouse, to guarantee receiving a button-up message some time in 00265 the future. Sets a timer in case that the button is held down and further 00266 messages must be processed (Windows buttons only send one notification 00267 message, no matter how long they are held down for). Sends a private 00268 "button clicked" message to the parent CScroller object. 00269 Errors: - 00270 Scope: Private 00271 SeeAlso: CScrollerButton::HandleButtonUp(); CScrollerButton::OnLButtonDown(); 00272 CScrollerButton::OnRButtonDown(); CScrollerButton::OnTimer() 00273 CScroller::OnDecBtnClicked(); CScroller::OnIncBtnClicked() 00274 00275 **********************************************************************************************/ 00276 void CScrollerButton::HandleButtonDown(BOOL reverse) 00277 { 00278 // On the initial click, we set up an auto-repeat timer to start after the configured 00279 // keyboard auto-repeat delay 00280 UINT32 CallbackTime = 1000; 00281 UINT32 RepsPerSec; 00282 00283 ::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &RepsPerSec, 0); 00284 RepsPerSec = 4 - RepsPerSec; 00285 if (RepsPerSec > 1) 00286 CallbackTime = (UINT32) 1000 / RepsPerSec; 00287 00288 TimerOn = ::FixSetTimer(m_hWnd, 3, CallbackTime, 0); 00289 00290 #ifdef _DEBUG 00291 if (!TimerOn) 00292 TRACE( _T("Unable to allocate a timer in CScrollerButton::HandleButtonDown()!\n")); 00293 #endif // _DEBUG 00294 00295 SetCapture(); 00296 GetParent()->SendMessage(Message, WPARAM(Reversed = reverse)); 00297 SetState(TRUE); 00298 } 00299 00300 00301 00302 /********************************************************************************************* 00303 > void CScrollerButton::HandleButtonUp() 00304 00305 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00306 Created: ages ago 00307 Inputs: - 00308 Outputs: - 00309 Returns: - 00310 Purpose: Releases the captured mouse and kills the timer set by HandleButtonDown(). 00311 Errors: - 00312 Scope: Private 00313 SeeAlso: CScrollerButton::HandleButtonDown(); CScrollerButton::OnLButtonUp(); 00314 CScrollerButton::OnRButtonUp(); CScrollerButton::OnTimer() 00315 00316 **********************************************************************************************/ 00317 void CScrollerButton::HandleButtonUp() 00318 { 00319 ReleaseCapture(); 00320 if (TimerOn) 00321 { 00322 ::FixKillTimer(m_hWnd, 3); 00323 TimerOn = FALSE; 00324 } 00325 SetState(FALSE); 00326 00327 // tell people things have changed on screen 00328 BROADCAST_TO_ALL(ScreenChangeMsg(TRUE)); 00329 } 00330 00331 00332 00334 // CScrollerButton message response functions. 00335 00336 /********************************************************************************************* 00337 > afx_msg void CScrollerButton::OnLButtonDown(UINT32 nFlags, CPoint point) 00338 00339 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00340 Created: ages ago 00341 Inputs: Some flags detailing which buttons and keys were down when the mouse message 00342 was generated; the coordinates of the mouse cursor. 00343 Outputs: - 00344 Returns: - 00345 Purpose: We must override the default handling for push-buttons because scroll-bar 00346 buttons generate a sequence of messages until they are released, whilst 00347 normal buttons generate only one message when pressed. This member function 00348 passes the message on to HandleButtonDown() with a FALSE parameter. 00349 Errors: - 00350 Scope: Protected 00351 SeeAlso: CScrollerButton::HandleButtonDown(); CScrollerButton::OnLButtonUp() 00352 00353 **********************************************************************************************/ 00354 void CScrollerButton::OnLButtonDown(UINT32 nFlags, CPoint point) 00355 { 00356 CBitmapButton::OnLButtonDown(nFlags, point); 00357 HandleButtonDown(FALSE); 00358 } 00359 00360 00361 00362 /********************************************************************************************* 00363 > afx_msg void CScrollerButton::OnLButtonUp(UINT32 nFlags, CPoint point) 00364 00365 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00366 Created: ages ago 00367 Inputs: Some flags detailing which buttons and keys were down when the mouse message 00368 was generated; the coordinates of the mouse cursor. 00369 Outputs: - 00370 Returns: - 00371 Purpose: Passes message on to HandleButtonUp() 00372 Errors: - 00373 Scope: Protected 00374 SeeAlso: CScrollerButton::HandleButtonUp(); CScrollerButton::OnLButtonDown() 00375 00376 **********************************************************************************************/ 00377 void CScrollerButton::OnLButtonUp(UINT32 nFlags, CPoint point) 00378 { 00379 CBitmapButton::OnLButtonUp(nFlags, point); 00380 SetState(FALSE); 00381 HandleButtonUp(); 00382 } 00383 00384 00385 00386 /********************************************************************************************* 00387 > afx_msg void CScrollerButton::OnRButtonDown(UINT32 nFlags, CPoint point) 00388 00389 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00390 Created: ages ago 00391 Inputs: Some flags detailing which buttons and keys were down when the mouse message 00392 was generated; the coordinates of the mouse cursor. 00393 Outputs: - 00394 Returns: - 00395 Purpose: We must override the default handling for push-buttons because Windows 00396 buttons do not respond to clicks with the right mouse-button. This member 00397 function passes the message on to HandleButtonDown() with a TRUE parameter, 00398 after calling CButton::SetState(TRUE) to "simulate" the button being clicked. 00399 Errors: - 00400 Scope: Protected 00401 SeeAlso: CScrollerButton::HandleButtonDown(); CScrollerButton::OnRButtonUp() 00402 00403 **********************************************************************************************/ 00404 void CScrollerButton::OnRButtonDown(UINT32 nFlags, CPoint point) 00405 { 00406 SetState(TRUE); 00407 HandleButtonDown(TRUE); 00408 } 00409 00410 00411 00412 /********************************************************************************************* 00413 > afx_msg void CScrollerButton::OnRButtonUp(UINT32 nFlags, CPoint point) 00414 00415 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00416 Created: ages ago 00417 Inputs: Some flags detailing which buttons and keys were down when the mouse message 00418 was generated; the coordinates of the mouse cursor. 00419 Outputs: - 00420 Returns: - 00421 Purpose: Passes message on to HandleButtonUp(), after calling CButton::SetState(FALSE) 00422 to draw the button "undepressed". 00423 Errors: - 00424 Scope: Protected 00425 SeeAlso: CScrollerButton::HandleButtonUp(); CScrollerButton::OnRButtonDown() 00426 00427 **********************************************************************************************/ 00428 void CScrollerButton::OnRButtonUp(UINT32 nFlags, CPoint point) 00429 { 00430 SetState(FALSE); 00431 HandleButtonUp(); 00432 } 00433 00434 00435 00436 /********************************************************************************************* 00437 > afx_msg void CScrollerButton::OnLButtonDblClk(UINT32 nFlags, CPoint point) 00438 00439 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00440 Created: ages ago 00441 Inputs: Some flags detailing which buttons and keys were down when the mouse message 00442 was generated; the coordinates of the mouse cursor. 00443 Outputs: - 00444 Returns: - 00445 Purpose: Calls CScrollerButton::OnLButtonDown(), to convert a double-click into 00446 a single click (MFC buttons don't normally respond to double-clicks). 00447 Errors: - 00448 Scope: Protected 00449 SeeAlso: CScrollerButton::OnLButtonDown(); CScrollerButton::OnRButtonDblClk() 00450 00451 **********************************************************************************************/ 00452 void CScrollerButton::OnLButtonDblClk(UINT32 nFlags, CPoint point) 00453 { 00454 OnLButtonDown(nFlags, point); 00455 } 00456 00457 00458 00459 /********************************************************************************************* 00460 > afx_msg void CScrollerButton::OnRButtonDblClk(UINT32 nFlags, CPoint point) 00461 00462 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00463 Created: ages ago 00464 Inputs: Some flags detailing which buttons and keys were down when the mouse message 00465 was generated; the coordinates of the mouse cursor. 00466 Outputs: - 00467 Returns: - 00468 Purpose: Calls CScrollerButton::OnRButtonDown(), to convert a double-click into 00469 a single click (MFC buttons don't normally respond to double-clicks). 00470 Errors: - 00471 Scope: Protected 00472 SeeAlso: CScrollerButton::OnRButtonDown(); CScrollerButton::OnLButtonDblClk() 00473 00474 **********************************************************************************************/ 00475 void CScrollerButton::OnRButtonDblClk(UINT32 nFlags, CPoint point) 00476 { 00477 OnRButtonDown(nFlags, point); 00478 } 00479 00480 00481 00482 /********************************************************************************************* 00483 > afx_msg void CScrollerButton::OnTimer(UINT32 nIDEvent) 00484 00485 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00486 Created: ages ago 00487 Inputs: The timer's numeric identifier (not used). 00488 Outputs: - 00489 Returns: - 00490 Purpose: Responds to the elapsed timer, set in HandleButtonDown(), by repeating the 00491 last "button-clicked" message sent to the parent CScroller. This allows the 00492 button to send a stream of messages until it is released - normally, Windows 00493 buttons send only one message per click. 00494 Errors: - 00495 Scope: Protected 00496 SeeAlso: CScrollerButton::HandleButtonDown(); CScrollerButton::HandleButtonUp() 00497 00498 **********************************************************************************************/ 00499 void CScrollerButton::OnTimer(UINT32) 00500 { 00501 // This checks for auto-repeat on the scroll button at the keyboard auto-repeat rate 00502 UINT32 CallbackTime = 1000; 00503 UINT32 RepsPerSec; 00504 00505 ::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &RepsPerSec, 0); 00506 CallbackTime = (UINT32) 1000 / (RepsPerSec + 1); 00507 TimerOn = ::FixSetTimer(m_hWnd, 3, CallbackTime, 0); 00508 00509 #ifdef _DEBUG 00510 if (!TimerOn) TRACE( _T("Unable to allocate a timer in CScrollerButton::OnTimer()!\n")); 00511 #endif // _DEBUG 00512 00513 GetParent()->SendMessage(Message, WPARAM(Reversed)); 00514 } 00515 00516 00517 00518 /********************************************************************************************* 00519 > afx_msg void CScrollerButton::OnCancelMode() 00520 00521 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00522 Created: ages ago 00523 Inputs: - 00524 Outputs: - 00525 Returns: - 00526 Purpose: Sent by windows if the user hits ESCAPE or the dialog of another app. pops 00527 up in the middle of some mouse capturing. Gives this window a chance to 00528 release the captured mouse and kill any running timer. 00529 Errors: - 00530 Scope: Protected 00531 SeeAlso: CScrollerButton::HandleButtonDown(); CScrollerButton::OnTimer(); 00532 CScrollerButton::HandleButtonUp() 00533 00534 **********************************************************************************************/ 00535 void CScrollerButton::OnCancelMode() 00536 { 00537 CBitmapButton::OnCancelMode(); 00538 if (TimerOn) HandleButtonUp(); 00539 } 00540 00541 00542 00543 /******************************************************************************************** 00544 > void PatB(CDC* hDC, INT32 x, INT32 y, INT32 dx, INT32 dy, COLORREF rgb) 00545 00546 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (Some MFC dude, actually) 00547 Created: 14/3/94 00548 Inputs: hDC - destination DC 00549 x,y,dx,dy - rectangle to fill 00550 rgb - colour to fill with 00551 Purpose: Paints a rectangle in the given (dithered) colour 00552 It looks pretty hideous, but this is how the MFC buttonbar does it... 00553 The conclusions that this leads to are left as an exercise for the reader. 00554 (OK, so they're not. It suggest that either MFC sux, or plotting text is 00555 easier/faster than creating a brush, in which case Windoze sux) 00556 ********************************************************************************************/ 00557 00558 static void NEAR PASCAL PatB(CDC* cDC, INT32 x, INT32 y, INT32 dx, INT32 dy, COLORREF rgb) 00559 { 00560 RECT rect; 00561 rect.left = x; 00562 rect.top = y; 00563 rect.right = x + dx; 00564 rect.bottom = y + dy; 00565 00566 cDC->SetBkColor(rgb); 00567 cDC->ExtTextOut(0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); 00568 } 00569 00570 00571 /******************************************************************************************** 00572 > void PlotMaskedBitmap(CDC* destDC, CBitmap* srcBitmap, INT32 x, INT32 y, INT32 width, INT32 height) 00573 00574 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> and Chris 00575 Created: 14/3/94 00576 Inputs: destDC - DC into which the BMP will be plotted 00577 srcBitmap - NULL, or the source bitmap 00578 x, y, width, height - rectangle to plot into 00579 Purpose: Plots the given bitmap (srcDC) into the given rectangle of the destination 00580 (destDC). 00581 if srcDC == NULL, then just fills the button with grey, else... 00582 ********************************************************************************************/ 00583 00584 // Raster Ops, used to... 00585 00586 // Plot colour in the glyph bitmaps transparent (grey) regions 00587 #define ROP_DSPDxax 0x00E20746L 00588 00589 // Plot colour in the glyph bitmaps non-transparent (coloured) regions 00590 #define ROP_PSDPxax 0x00B8074AL 00591 00592 00593 00594 BOOL CScrollerButton::PlotMaskedBitmap(CDC* destDC, CBitmap* srcBitmap, INT32 SrcOffset, 00595 INT32 xPlotOffset,INT32 yPlotOffset, INT32 width, INT32 height) 00596 { 00597 00598 ERROR2IF(srcBitmap == NULL,FALSE,"NULL Bitmap in PlotMaskedBitmap()"); 00599 ERROR2IF(destDC == NULL,FALSE,"NULL DC in PlotMaskedBitmap()"); 00600 00601 // always fill the entire background with BTNFACE to make sure we don't 00602 // miss any pixels 00603 00604 PatB(destDC, 0, 0, width, height, GetSysColor(COLOR_BTNFACE)); 00605 00606 // create a screen dc 00607 CDC scrDC ; 00608 scrDC.CreateCompatibleDC(destDC); 00609 00610 // and select the bitmap into it 00611 CBitmap* OldSrcBitmap = (CBitmap *) scrDC.SelectObject(srcBitmap); 00612 00613 // create a mask for the button glyph... First a DC 00614 CDC hDCMono ; 00615 hDCMono.CreateCompatibleDC(NULL); 00616 00617 // create a mono bitmap for the mask 00618 CBitmap hbmMono ; 00619 hbmMono.CreateBitmap(width, height, 1, 1, NULL); 00620 00621 CBitmap * oldmonobitmap = (CBitmap *)hDCMono.SelectObject(&hbmMono); 00622 00623 // initalize the bitmapto white (all 1's) 00624 hDCMono.PatBlt(0, 0, width, height, WHITENESS); 00625 00626 // plot all non-lightgrey pixels in the glyph as black in our mask 00627 scrDC.SetBkColor( RGB(192,192,192)); 00628 hDCMono.BitBlt(xPlotOffset,yPlotOffset, width, height, &scrDC, 00629 SrcOffset, 0, SRCCOPY); 00630 00631 destDC->SetTextColor(0L); // 0's in mono -> 0 (for ROP) 00632 destDC->SetBkColor((COLORREF)0x00FFFFFFL); // 1's in mono -> 1 00633 00634 // plot the glyph 00635 destDC->BitBlt( xPlotOffset, yPlotOffset, width, height, 00636 &scrDC, SrcOffset, 0, SRCCOPY); 00637 00638 // fill with the normal BTNFACE colour 00639 CBrush HighlightBrush ; 00640 HighlightBrush.CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); 00641 00642 CBrush* hbrOld = (CBrush *) destDC->SelectObject(&HighlightBrush); 00643 if (hbrOld != NULL) 00644 { 00645 // draw highlight color where we have 0's in the mask 00646 destDC->BitBlt( xPlotOffset,yPlotOffset, width, height, &hDCMono, 0, 0, ROP_DSPDxax); 00647 destDC->SelectObject(hbrOld); 00648 } 00649 00650 // clean up DC's 00651 hDCMono.SelectObject(oldmonobitmap); 00652 scrDC.SelectObject(OldSrcBitmap); 00653 return TRUE; 00654 } 00655 00656 00657 void CScrollerButton::DrawItem (LPDRAWITEMSTRUCT lpDIS) 00658 { 00659 00660 00661 ASSERT(lpDIS != NULL); 00662 // must have at least the first bitmap loaded before calling DrawItem 00663 ASSERT(m_bitmap.m_hObject != NULL); // required 00664 00665 // use the main bitmap for up, the selected bitmap for down 00666 CBitmap* pBitmap = &m_bitmap; 00667 UINT32 state = lpDIS->itemState; 00668 if ((state & ODS_SELECTED) && m_bitmapSel.m_hObject != NULL) 00669 pBitmap = &m_bitmapSel; 00670 00671 #ifndef _MAC 00672 else if ((state & ODS_FOCUS) && m_bitmapFocus.m_hObject != NULL) 00673 #else 00674 else if ((state & ODS_FOCUS) && m_bitmapFocus.m_hObject != NULL && 00675 (GetParent()->GetStyle() & DS_WINDOWSUI)) 00676 #endif 00677 pBitmap = &m_bitmapFocus; // third image for focused 00678 else if ((state & ODS_DISABLED) && m_bitmapDisabled.m_hObject != NULL) 00679 pBitmap = &m_bitmapDisabled; // last image for disabled 00680 00681 00682 00683 CDC* pDC = CDC::FromHandle(lpDIS->hDC); 00684 00685 // New masked version 00686 //------------------------------------------------------------------------------ 00687 CRect rect; 00688 rect.CopyRect(&lpDIS->rcItem); 00689 if(!IS_CHICAGO) // UIC 00690 { 00691 // draw the whole button 00692 PlotMaskedBitmap(pDC,pBitmap,0,rect.left, rect.top, rect.Width(), rect.Height()); 00693 } 00694 else 00695 { 00696 UINT32 Flags =0; 00697 switch(Orient) 00698 { 00699 case UP: 00700 Flags = DFCS_SCROLLUP; 00701 break; 00702 case DOWN: 00703 Flags = DFCS_SCROLLDOWN; 00704 break; 00705 case LEFT: 00706 Flags = DFCS_SCROLLLEFT; 00707 break; 00708 case RIGHT: 00709 Flags = DFCS_SCROLLRIGHT; 00710 break; 00711 } 00712 if (state & ODS_SELECTED) 00713 Flags |= DFCS_PUSHED; 00714 00715 pDC->DrawFrameControl(&rect,DFC_SCROLL, Flags); 00716 } 00717 00718 00719 //------------------------------------------------------------------------------- 00720 00721 // Old "scrcopy" version 00722 //------------------------------------------------------------------------------- 00723 /* 00724 CDC memDC; 00725 memDC.CreateCompatibleDC(pDC); 00726 CBitmap* pOld = memDC.SelectObject(pBitmap); 00727 if (pOld == NULL) 00728 return; // destructors will clean up 00729 00730 CRect rect; 00731 rect.CopyRect(&lpDIS->rcItem); 00732 pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), 00733 &memDC, 0, 0, SRCCOPY); 00734 00735 memDC.SelectObject(pOld); 00736 */ 00737 //------------------------------------------------------------------------------- 00738 }