|
In an effort to have the latest and greatest wizz-bang features in
my programs I unashamedly ripped of the colour picker from Office 97.
Initially I tried to modify an owner drawn combo box and combine
that with a multicolumn combobox, but current multicolumn combo
boxes are really just a single column with dividing lines drawn in.
I then decided to write the whole thing from scratch based on a button,
since it would at least give me a BN_CLICKED notification to get
things started.
The colour picker is in two parts: an owner drawn button that
reflects the currently selected colour, and a popup colour chooser
window to select this colour. When the user clicks on the button
the popup window appears and all mouse messages are captured until
the left mouse button is clicked, or until the Enter or Escape keys
are pressed. The popup window can be navigated using the mouse or
the keyboard and includes tooltips explaining what each colour is.
The control can be incorporated into a project like any other
CButton derived control. Either Create the control manually, subclass
an existing CButton or DDX_control it. The control also comes with
a DDX_ColourPicker routine to get/set the colour of
the control using a variable of type COLORREF.
The Colour Picker is contained in the class CColourPicker.
It uses the class CColourPopup for the popup window.
These classes are contained in the file
colour_picker_src.zip, and a sample project is contained in
colour_picker_demo.zip.
CColourPicker only has the following public member functions:
void SetColour(COLORREF crColour);
COLORREF GetColour();
void SetDefaultText(LPCTSTR szDefaultText);
void SetCustomText(LPCTSTR szCustomText);
void SetSelectionMode(UINT nMode);
UINT GetSelectionMode();
void SetBkColour(COLORREF crColourBk);
COLORREF GetBkColour();
void SetTextColour(COLORREF crColourText);
COLORREF GetTextColour();
SetDefaultText allows you to set the text that will appear in the "Default"
area of the colour chooser. If you pass NULL, then the Default area will not be available
to the user. If this area is availble and the user selects it, the value CLR_DEFAULT
will be returned.
SetCustomText allows you to set the text that will appear in the "Custom"
area of the colour chooser. If you pass NULL, then the Custom area will not be available
to the user. The Custom area allows the user to select a custom colour using the
standard windows colour selection dialog.
You can choose whether the colour chosen using the dropdown colour chooser will
affect the text or the background colour using the function
SetSelectionMode(int nMode). Possible values for nMode are CP_MODE_TEXT
to make colour changes affect the text colour, and CP_MODE_BK to make changes
affect the background (default).
SetColour, GetColour and the the DDX-function
will set and get the colour according to the current selection mode. To access
the text colour and the background colour directly use the Set/GetTextColour
and Set/GetBkColour functions.
There are also a number of user messages that may be handled to
get more information from the control. These are:
| Message |
Description |
| CPN_SELCHANGE |
Colour Picker Selection change |
| CPN_DROPDOWN |
Colour Picker drop down |
| CPN_CLOSEUP |
Colour Picker close up |
| CPN_SELENDOK |
Colour Picker end OK |
| CPN_SELENDCANCEL |
Colour Picker end (cancelled) |
These messages can be handled using ON_MESSAGE(< MESSAGE>, MessageFn)
in you message map entries, where MessageFn is of
the form
afx_msg LONG MessageFn(UINT lParam, LONG wParam);
The demo program gives an example of how to do this.
Acknowledgments
Alexander Bischofberger kindly
supplied the Selection mode modifications, as well as the background and text color methods.
Paul Wilkerson fixed a focus related bug, and Geir Arne Trillhus also helped fix a few bugs.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 39 (Total in Forum: 39) (Refresh) | FirstPrevNext |
|
 |
|
|
Thank you for your exellent code. It solved my problem for picking a color easily. BTW, in my solution i combined the "ColourPopup" with the class derived from CComboBox,not using "ColourPicker", for a better appearance.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
The project is converted by VC9 without problems. The fix given by toxcct bellow is still needed to compile succesfully. One should also note that VC9 compiles for Vista by default, and the executable won't run on previous versions. The source of the error is in line 94 of "ColourPopup.cpp": VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)); The API call fails in XP yet a subsequent call to GetLastError() will provide no further information - it simply return 0, i.e. "No error". I traced this down to an extra int member added in Vista to the NONCLIENTMETRICS struct. Hence its size is 344 instead of 340 in my XP, and the system presumably refuse to honor the call because of this difference.
To cut shortly you have to define WINVER to atmost 0x0501 in your project for the control to work in pre Vista versions of Windows.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
|
hi Chris,
i tried to port a VC6 project that used your colorPicker for Visual C++ 2003, and an error occured :
ColourPopup.cpp(230) error C2440: 'static_cast' : cannot cast from 'void (__thiscall CColourPopup::* )(BOOL,HTASK)' to 'void (__thiscall CWnd::* )(BOOL,DWORD)' ColourPopup.cpp(908) error C2664: 'CWnd::OnActivateApp' : cannot cast parameter 2 from 'HTASK' to 'DWORD' i wanted to give myself a try to fix this, but i don't know the framework enough... do you know a simple way to compile the control under VC7 or later ?
thanks,
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
hello Chris,
it's me again. I've fixed it, and here is the code i added, i you wished to add it to your source. I actually made 2 changes :
ColourPopup.cpp : line 906 replaced by : #if _MFC_VER < 0x0700 void CColourPopup::OnActivateApp(BOOL bActive, HTASK hTask) #else void CColourPopup::OnActivateApp(BOOL bActive, DWORD hTask) #endif
ColourPopup.h : line 118 replaced by : #if _MFC_VER < 0x0700 afx_msg void OnActivateApp(BOOL bActive, HTASK hTask); #else afx_msg void OnActivateApp(BOOL bActive, DWORD hTask); #endif
Now, the ColourPicker compiles without error nor warnings under VC6 and VC7.1...
cheers,
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
|
is it possible to get the value of the COLORREF, and how can I display it as a messagebox
something like
MessageBox(COLORREF); or even to display it in editbox using SetWindowText()
thanks in advance
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
How do I customize the drop down palette to display user defined colors. For example I want to display only 16 colors of my choice in the drop down palette.
laiju
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
I have put my colors in the variable CColourPopup::m_crColours[] and it works fine. However I need to change this dynamically.Like as per my requirement I shall change the colors .Hope I can do this. Thanx anyway
laiju
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I would like to use this colour picker control in Chris Maunder Grid conrol.
If you you got anyidea on doing this please let me know.
Thanks Tom
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
First, thank you for the article and source code. I've used and extended it with some success for my requirements.
I believe that some of the casting is not correct. Just an example, in CColourPicker::OnSelEndOK:
pParent->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
I believe that 3rd argument is a LPARAM. The naming convention is also a bit misleading: "lParam" when the value is actually type WPARAM, conventionally "wParam".
So far, despite the incorrect casting I haven't been able to attribute any problem to it.
Again, Thanks.
Art Gorr
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I attached ColourPicker in Toolbar. But, I cannot handle message. Please, let me know...
Thank you
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
Great control, but there is a problem on multi-monitor systems, due to your use of GetMessagePos().
In CColourPopup::OnLButtonUp you have the following:
DWORD pos = GetMessagePos(); point = CPoint(LOWORD(pos), HIWORD(pos)); But this doesn't work correctly on multi-monitor systems if the colour picker is used in an app positioned to the left of or above the primary monitor. The co-ordinates in this case can be negative, but using LOWORD/HIWORD forces them to be unsigned, giving the wrong values.
The documentation for GetMessagePos() describes this, and suggests the use of GET_X_LPARAM and GET_Y_LPARAM. In fact, using CPoint you can just pass the DWORD returned from GetMessagePos() which gives the correct results thus: point = CPoint(GetMessagePos());
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Great control! I suggest it should also mimic Windows Listbox in responding to keyboard input. (F4 and Alt+Up and Alt+Down should activate popup when picker control has focus). This code does it for Alt+Up and Alt+Down. (F4 is more of a problem to handle.) //================================================================ // Alt+Down and Alt+Up should activate drop down List //================================================================ void CColourPicker::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { #if defined(_DEBUG) && 0 DB_SHOWENTRY(CColourPicker::OnSysKeyDown); #define DIAGOnSysKeyDown #endif // _DEBUG
// Alt+Down and Alt+Up: Standard Windows List Box activation keys const bool bActivatePopup = (VK_DOWN == nChar || VK_UP == nChar); if (bActivatePopup) { // Activate _ASSERT(1 == nRepCnt); _ASSERT(!((1 << 0) & nFlags)); // 8th bit: Extended key, such as a function key or a key on the numeric keypad (1 if it is an extended key; otherwise 0). _ASSERT((1 << 13) & nFlags); // 13th bit: Context code (1 if the ALT key is held down while the key is pressed, 0 otherwise)
#if defined(DIAGOnSysKeyDown) TRACE(_T("\tActivate Popup: nChar=%d, nRepCnt=%d, nFlags="), nChar, nRepCnt, nFlags); ::DB_ShowDWORDasBinary(nFlags, false); // Show decimal DWORD value as 00011111-00011111-00011111-00011111b TRACE0(_T("\n")); #endif // DIAGOnSysKeyDown
OnClicked(); // Equivalent to clicking drop down button return; } // Activate CButton::OnSysKeyDown(nChar, nRepCnt, nFlags); } // OnSysKeyDown ============================================================
gjr
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
How to make in the newest office 2000 or 2003 to appear More Colors... like that in office 97 ? Or an addin programaticaly?
Adrian Bacaianu
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
I am writing a completely freeware application (open source) for which I would like to use the ColorPicker code. I will have to make a couple of small modifications in order for it to work with my application. Can you please permit me to redistribute the ColorPicker source (with my modification) along with my application.
thanks -- narm
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am wondering how to install or implement this within office '97. Can anybody give me a hint how to do this.
Greetings,
Ronald
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I need to set control to so called "undefined state". I Do this with little change of control.
1.Add variable, that named like this "m_bUndefinedState" and add methods to manipulate this variable.
2.change DrawItem method: //****************************************************** //** Draw Color //****************************************************** if ((state & ODS_DISABLED) == 0) { //END of changes///////////////////////////////////////////////////////////////////////////////// if ( m_bUndefinedState && !m_bPopupActive ) { CBrush* htBrush = pDC->GetHalftoneBrush(); pDC->FillRect(&rDraw, htBrush); } //END of changes///////////////////////////////////////////////////////////////////////////////// else { pDC->FillSolidRect(&rDraw, (m_Color == CLR_DEFAULT) ? m_DefaultColor : m_Color);
::FrameRect(pDC->m_hDC, &rDraw, (HBRUSH)::GetStockObject(BLACK_BRUSH)); } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
very nice control! I would like to put the value of the selected COLORREF in a database but rather than putting 3 entries (R,G and B), I would like to use only 1 entry, such as an equivalent integer. is there is another type than COLORREF that handle one basic type (such as integer) as a color reference?
thanks.
Mat
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Mat, A COLORREF is a DWORD so it easily can be casted to an int if needed.
I found this in the MSDN library:
typedef DWORD COLORREF;
John
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|