Color, Link and Image Editor Controls for MFC

An operating system has crucial building blocks, without which it cannot function. One of these is its controls. They work together to complete complex tasks and to make your work easier. This article will focus on some new controls for an old favorite.

Contributed by
Rating: 4 stars4 stars4 stars4 stars4 stars / 4
October 21, 2009
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Controls also provide some harmony and common style to an operating system. This way you generally do not need to spend a lot of time learning how to use a new program if it works with an operating system with which you are already familiar. Because all applications are put together from the same building blocks (controls), once you are familiar with the OS you can use any application in it with minimal headaches.

The last time I started to present how to use these controls if you are creating a new program within Microsoft Visual Studio with the Microsoft Foundation Class Library. I used (and will continue to use) the New Controls application you can find on the MSDN site. I completely covered the button-related controls. Today I will focus on the color, shell, font combo box, link button, image editor, browse and CVS List Box controls.

There is a lot to learn, so let's get on with it. The link button is a sort of extension to the buttons. You could consider it more like a label on what you can click to open up a browser and visit a custom link/site. We will create pages in the same way we did in my previous article. Use the resource editor to create a common button, add a new class and replace the button with a CMFCLinkCtrl.

Afterward you can make all the settings inside the initialization of the property page:

CMFCLinkCtrl m_btnLink;

...

m_btnLink.SetURL (_T ("http://www.microsoft.com"));

m_btnLink.SetTooltip (_T ("Visit Microsoft site"));

m_btnLink.SizeToContent ();

Additionally, you may use the SetURLPrefix function. With this you can set the implicit protocol of the URL. For instance, this can be http or ftp or whatever seems appropriate. Other than these few functions, this will behave just like any other button, and you can use the same methods to change the text and complete other general actions:

CString text (L"Alfa and Omega");

m_btnLink.SetWindowText (text);

 

m_btnLink.SetURLPrefix (_T ("http:"));

m_btnLink.SetURL (_T ("www.microsoft.com"));

m_btnLink.SetTooltip (_T ("Visit Microsoft site"));

m_btnLink.SizeToContent ();

Colors

Life is beautiful in colors. Besides this, colors also enhance our computer experiences. There are countless times when you may want to customize something and paint/show it in a different color. In these situations you need to ask the user to choose a control. There are a couple of controls that will do just this. While each and every one of them generally returns the same result (a color), the presentation is different.

When you want to change the intensity of a color or use a whole new color, there are different controls that will assure that this takes as little time as possible. I will present the advanced color dialog method, the color picker, the color palette, the color bar and the color bar with custom palette.

The advanced color dialog is something you could also find in previous versions (Windows 98 and older) under the name of CColorDialog. However, this received a face lift and now runs under the name of CMFCColorDialog. Nevertheless, its usage remains basically the same. Take the following example that will write out to the screen the selected color in RGB value:

->Final result<-

// Constructor arguments -> first -> initial color value

// -> second -> Reserved

// -> third -> Pointer to parent/owner

// -> fourth -> handle to color palette

 

CMFCColorDialog dlg (m_Color, 0, this);

 

if (dlg.DoModal () == IDOK)

{

m_Color = dlg.GetColor (); // get the color

 

// set the new text to the screen

m_strRGBColorDialog.Format (_T ("%d,%d,%d"),

GetRValue(m_Color), GetGValue(m_Color),GetBValue(m_Color));

 

UpdateData (FALSE);

}

 

 

 

The color picker is a little more visual. You can see the currently selected color. It uses a combo box style to display the name and the color or only the color. The text under the combo box that you can see on the picture below is added beside it by me. Again, use a button and replace it with the CMFCColorButton class name.

Inside the color picker you can choose from a set, predefined automatic color or you can take the other path, which will bring up a color dialog that I just presented.

CMFCColorButton m_ColorPicker;

...

// acquire the new color

COLORREF color = m_ColorPicker.GetColor ();

 

// set the new text to the screen

m_strRGB.Format (_T ("%d,%d,%d"),

GetRValue (m_Color), GetGValue(m_Color),GetBValue(m_Color));

 

UpdateData(FALSE);

 

Method

Effect

EnableAutomaticButton

Enables and disables an "automatic" button that is positioned above the regular color buttons. (set color, text and enable/disable)

EnableOtherButton

Enables and disables an "other" button that is positioned below the regular color buttons. (Set text, specify to use a CMFCColorDialog or a system dialog and to enable/disable).

GetAutomaticColor

Retrieves the current automatic color. (COLORREF item)

GetColor

Retrieves a button's color. (COLORREF item)

SetColor

Sets a button's color. (COLORREF item)

SetColorName

Sets a color name. (COLORREF item, text pairs)

SetColumnsNumber

Sets the number of columns on the color picker dialog box. (int)

SetDocumentColors

Specifies a list of document-specific colors that are displayed on the color picker dialog box. (label to display and CList<COLORREF,COLORREF>& item(list of RGB items)).

SetPalette

Specifies a palette of standard display colors. (CPalette pointer)

SizeToContent

Changes the size of the button control, depending on its text and image size.

 

For the upper image, the following initialization was made:

// Create color picker:

m_ColorPicker.EnableAutomaticButton(_T("Automatic"), RGB(255, 0, 255));

m_ColorPicker.EnableOtherButton(_T("Other"));

m_ColorPicker.SetColor((COLORREF)-1);

m_ColorPicker.SetColumnsNumber(10);

 

More Colors

The color bar is a large frame that hosts multiple colors and maybe two buttons (automatic and other) that will choose a default color or bring up the color dialog.

Method

What it does

ContextToSize

Calculates the size needed for the buttons and the colors, and then adjusts to this. A sort of size to content.

CreateControl

Handles the create process and resize of the control to contain the colors.

Create

The same as CreateControl, but does not resize.

EnableAutomaticButton

Show/hide this.

EnableOtherButton

Show/hide this.

GetColor

Currently selected color.

GetCommandID

Returns the command ID of the current color bar control.

GetHighlightedColor

Tells what color is used to signal the selected state of a color.

GetHorzMargin

Space between the client area boundary and left/right color cell.

GetVertMargin

Space between the client area boundary and top/bottom color cell.

IsTearOff

Is the color bar dockable?

SetColor

Sets the currently selected color.

SetColorName

Sets the name for a specified color.

SetCommandID

Sets a new command ID for a color bar.

SetDocumentColors

Sets a list of controls to display inside the color bar.

SetHorzMargin

Set the horizontal margin.

SetVertMargin

Sets the vertical margin.

CStatic m_wndColorBarFrame;

CMFCColorBar m_wndColorBar;

...

// Create regular color bar:

CRect rectColorBar;

m_wndColorBarFrame.GetClientRect(&rectColorBar);

 

//transform this point to the context of the window

m_wndColorBarFrame.MapWindowPoints(this, &rectColorBar);

 

m_wndColorBar.SetHorzMargin(0);

m_wndColorBar.SetVertMargin(0);

m_wndColorBar.EnableOtherButton(_T("Other..."));

 

m_wndColorBar.CreateControl(this, rectColorBar, IDC_COLORBAR, 5 /* columns */);

m_wndColorBar.SetColor(RGB(0, 0, 0));

 

 

Finally, call the same GetColor method to find out the chosen color:

COLORREF color = m_wndColorBar.GetColor();

 

Using a custom palette is a little more complicated. You need to create a logical palette and fill it one by one with the elements that you want to put inside it. To do this we will use a cycle and some shift operations.

// define a structure where to define the colors

#define NUM_COLOURS 64

struct

{

LOGPALETTE LogPalette;

PALETTEENTRY PalEntry[NUM_COLOURS];

}pal;

 

//create a logical palette -> and set version +color numbers

LOGPALETTE* pLogPalette = (LOGPALETTE*) &pal;

pLogPalette->palVersion = 0x300;

pLogPalette->palNumEntries = (WORD) NUM_COLOURS;

 

// Go from color to color

COLORREF colorStart = RGB(0, 0, 255);

COLORREF colorFinish = RGB(255, 255, 255);

int nShift = 6;

 

// Generate the colors

for (int i = 0; i < NUM_COLOURS; i++)

{ BYTE bR = (BYTE)((GetRValue(colorStart) *(NUM_COLOURS - i) + GetRValue(colorFinish) * i) >> nShift);

BYTE bG = (BYTE)((GetGValue(colorStart) *(NUM_COLOURS - i) + GetGValue(colorFinish) * i) >> nShift);

BYTE bB = (BYTE)((GetBValue(colorStart) *(NUM_COLOURS - i)

+ GetBValue(colorFinish) * i) >> nShift);

 

//set the new color combination

pLogPalette->palPalEntry[i].peRed = bR;

pLogPalette->palPalEntry[i].peGreen = bG;

pLogPalette->palPalEntry[i].peBlue = bB;

pLogPalette->palPalEntry[i].peFlags = 0; }

 

//Create the palette

m_palColorPicker.CreatePalette(pLogPalette);

 

//Set the margins and create the control with our palette

m_wndColorBar2.SetHorzMargin(0);

m_wndColorBar2.SetVertMargin(0);

m_wndColorBar2.CreateControl(this, rectColorBar, IDC_COLORBAR2, -1 /* columns */, &m_palColorPicker);

 

//set the selected control

m_wndColorBar2.SetColor(colorStart);

 

The color picker control

Finally, between the color controls, let us see the color picker control. This is also derived from CButton. In fact, the CMFCButtonControl is made up of this control. Anything that you can see there, you can also configure to exist here. There exists four types.

We will implement in our property sheet the custom part. We will need two items, one for the palette and the scope on the left side, and one is for the shade changer on the right side.

 

Method

Effect it has

GetColor

Acquire the color selected.

GetHLS

Acquire the hue/luminance and saturation selected by the user. (There exists also a set).

GetHue

Get the hue component. (there exists also a set).

GetLuminance

Get the luminance component. (There exists also a set).

GetSaturation

Get the saturation component. (There exists also a set).

SelectCellHexagon

Sets the current color to the color defined by the specified RGB color components or the specified cell hexagon.

SetLuminanceBarWidth

The width of the bar in the luminance bar.

SetOriginalColor

Initial color value.

SetPalette

Set a custom current control palette.

SetSaturation

Change the saturation of the current color.

SetType

The type of the color control to display.

The possible types are:

LUMINANCE

PICKER

HEX

HEX_GREYSCALE

 

 

CMFCColorPickerCtrl m_wndLum; // on the right

CMFCColorPickerCtrl m_wndColorPalette; // on the left

 

...

 

// Create system palette:

CClientDC dc(this);

 

int nColors = 256; // Use 256 first entries

UINT nSize=sizeof(LOGPALETTE) +(sizeof(PALETTEENTRY)*nColors);

LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

 

pLP->palVersion = 0x300;

pLP->palNumEntries = (USHORT) nColors;

 

::GetSystemPaletteEntries(dc.GetSafeHdc(), 0, nColors,

pLP->palPalEntry);

 

m_palSys.CreatePalette(pLP);

 

delete[] pLP;

 

// Create a picker with a system palette

m_wndColorPalette.SetType(CMFCColorPickerCtrl::PICKER);

m_wndColorPalette.SetPalette(&m_palSys);

m_wndColorPalette.SetColor(RGB(0, 255, 0));

 

//Create a luminance changer with the system palette

m_wndLum.SetType(CMFCColorPickerCtrl::LUMINANCE);

m_wndLum.SetPalette(&m_palSys);

m_wndLum.SetColor(RGB(0, 255, 0));

 

Link the push of the button with a control, and inside it you can call the GetColor method to work with the new color. It is this simple, all of it.  

Image Editor

 

You can use a simple image editor tool to let the user make some basic modifications to an image. This control is called dynamically, just like the color dialog I showed you earlier. Therefore, you do not need to add anything to the dialog other than a button that will trigger the call.

Nevertheless, we may want to also display the current status of our image inside a small rectangle for the user. For this reason, add an image control. Take one of these from the toolbox, add it to your dialog and create the class from the dialog.

We will make it as follows:

CBitmap m_bmpImage;

CMFCButton m_btnImageEdit;

...

//Customize with an image the button

m_btnImageEdit.m_nFlatStyle=CMFCButton::BUTTONSTYLE_SEMIFLAT;

m_btnImageEdit.SetImage(IDB_IMAGE);

m_btnImageEdit.SizeToContent();

m_btnImageEdit.SetTextHotColor(RGB(0, 0, 255));

 

//Load the image whit what we will work

m_bmpImage.LoadBitmap(IDB_TEST_BITMAP);

BITMAP bmp;

m_bmpImage.GetBitmap(&bmp);

 

//Calculate the image area ( so we can redraw later this area)

m_wndImageArea.GetClientRect(m_rectImage);

m_wndImageArea.MapWindowPoints(this, m_rectImage);

m_rectImage.right = m_rectImage.left + bmp.bmWidth;

m_rectImage.bottom = m_rectImage.top + bmp.bmHeight;

 

// Copy a bitmap image from the memory inside a variable

HBITMAP hBmpCopy = (HBITMAP) ::CopyImage(m_bmpImage.GetSafeHandle(),IMAGE_BITMAP, 0, 0, 0);

 

// make sure that it finished with a success

ASSERT(hBmpCopy != NULL);

 

//Create the editor

// Constructor -> First -> Pointer to bitmap image to modify

// Second -> Parent window

// Third -> How many bits use to represent a // single pixel (Color depth). If you use -1 this will be // derived from the image you use. Default value is -1.

 

CMFCImageEditorDialog dlg(CBitmap::FromHandle(hBmpCopy),this);

 

if (dlg.DoModal() == IDOK)

{

// if success delete the current control from memory

m_bmpImage.DeleteObject();

//Attach the new modified version

m_bmpImage.Attach(hBmpCopy);

 

InvalidateRect(m_rectImage);

UpdateWindow();

}

else

{ //dump the result in case of failure

::DeleteObject(hBmpCopy);

}

 

 

 

There are no customizations available for this. However, it works quite well and is surely a welcome addition to the MFC pack.

This will be all for today. I will return next time to present a couple of other controls. I encourage you to post your opinion here on the blog or join the DevHardware forum and do the same there. Until next time make sure you have a good grasp of what I presented today and Live With Passion!

blog comments powered by Disqus
.NET ARTICLES

- .Net 4.5 Brings Changes
- Understanding Events in VB.NET
- Objects, Properties, Events and Methods in V...
- Install Visual Web Developer Express 2010
- Microsoft Gadgeteer an Open Source Alternati...
- Best DotNetNuke Modules
- Facebook Image Viewer in Visual Basic
- Murach`s ADO.NET 4 Database Programming with...
- 5 Must Have Visual Studio 2010 Extensions
- Dynamic Web Applications with ASP.NET Mono u...
- PDFSharp: HTML to PDF in ASP.NET 3.5 using V...
- Using the PDFSharp Library in ASP.NET 3.5 wi...
- Sending Email in ASP.NET 3.5 using VB.NET wi...
- ASP.NET 3.5 Role Based Security and User Aut...
- Creating ASP.NET Login Web Pages and Basic C...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 11 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials