Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / MFC
Article

CCreditsCtrl - An advanced About Box

Rate me:
Please Sign up or sign in to vote.
5.00/5 (14 votes)
7 Jan 2001 202.8K   4.9K   72   34
Yet another fully stacked control for displaying scrolling credits...

Introduction

I just tried Mark Findlay's Scrolling Credits Dialog and Darren S. Gonzales' Scrolling Screen Credits, and I was honestly disappointed. You could do no formatting at all except to choose between 4 different pre-defined text headings (in Darren's version), and it didn't meet the requirements I would make to an "advanced" about-box, where you would usually want to put a hyperlink or two, and maybe Easter-eggs, who knows :)

And as it, IMHO, is lame to say (and think, for that matter) something sux if you can't do it better, I started to code..

Anyway, this control allows you to display formatted scrolling text & images, which would normally be used in an about box for displaying credits. The features include:

  • Extended formatting capabilities;
  • Supports inline resource bitmaps;
  • You can define text and images as hyperlinks which can trigger a ShellExecute command or a user-defined callback function;
  • Text font, size, style and color as well as image border-color can be changed when mouse-pointer is moved over a hyperlink;
  • You can make fancy owner-drawn background effects;
  • Supports text and bitmap transparency;
  • Doesn't scroll if the total size of the content is smaller than the control;
  • Ability to choose whether the user should be able to manually scroll through the content;
  • Sorry, not UNICODE compliant (I have no means of testing this.. my version of VC++ (Introductory edition :( ) hasn't even got the libraries required to compile it in Unicode mode... If anybody wants to do this, they are welcome ;) )

Screenshots:

Styles...

.. demo app with animated, user drawn background ..

...OK, this is just a demonstration of some of the functionalities.. I didn't say your about-box had to look that weird.

Usage

To use the Credits control, follow these four easy steps:

  1. First, you need to add a variable of type CCreditsCtrl to your dialog or window class. Don't forget to #include the required header file.
  2. Next, call either SetDataString or FormatDataString to set the content of the control.
  3. If you want to customize the behavior and look of the control, have a look at the various class members. Normally, you would call/set them before calling Create.
  4. Call the <A href="#create">Create</A> function.

Construction

Use one of these functions to create the CCreditsCtrl control:

BOOL Create(DWORD dwExStyle, DWORD dwStyle, 
    const RECT& rect, CWnd* pParentWnd,
    UINT nID = 0, UINT nDefaultCursorID = 0, 
    UINT nLinkCursorID = 0);

BOOL Create(DWORD dwExStyle, DWORD dwStyle, 
    UINT nPlaceholderID, CWnd* pParentWnd,
    UINT nID = 0, UINT nDefaultCursorID = 0, 
    UINT nLinkCursorID = 0);

These functions create the control using the styles and positions you specify:

  • dwExStyle defines the extended styles.
  • dwStyle defines the control's window styles.
  • pParentWnd is the parent window.
  • nID is the control's child ID.
  • nDefaultCursorID is the ID of a cursor resource or 0 for default.
  • nLinkCursorID is the ID of a cursor resource that will be used when the mouse is over a link.. 0 for default.
  • rect is the rectangle of the control.
  • nPlaceholderID is the ID of a child window whose position will be used to create the window. This one is used in the demo.

Content

You set the content using one of these four functions:

CString SetDataString(LPCTSTR lpszNewString);
CString SetDataString(UINT nStringResourceID);
CString FormatDataString(LPCTSTR lpszFormat, ...);
CString FormatDataString(UINT nFormatID, ...);

All of them return the old content string. SetDataString sets the internal data string to the content of lpszNewString or to the content of the resource string specified by nStringResourceID. FormatDataString does the same to the internal data string that CString::Format does to a CString...

Calling FormatDataString(... , ...) does the same that the following piece of code would do:

CString s;
s.Format(... , ...);
m_wndCreditsCtrl.SetDataString(s);

For information about what the content is supposed to look like, please refer to the language section.

Background

You have two options for drawing the background of the control:

  • If you just want a single-colored background, you can let CCreditsCtrl draw it; you just have to specify the color using the <A href="#setdefaultbkcolor">SetDefaultBkColor</A> function.
  • The other option is to draw the background yourself by specifying a callback function that should do the job.

The function should be defined like this:

static void DrawCreditsBackground(CDC *pDC, 
          RECT rect, BOOL bAnimate, DWORD lParam);
  • pDC is a pointer to the device context to draw to. It's a memory device context, so you don't have to do more BitBlt's than necessary.
  • rect is the client rectangle of the Credits control.
  • bAnimate is a flag that tells if the background is supposed to be animated or not... you don't have to respect that, but you might get unexpected results... but go ahead and try without, first :) ..or look at the demo to see how I used it.
  • lParam can be anything you want; look below.

Assuming that DrawCreditsBackground is a member of a class called CAboutDlg, and that m_wndCredits is a variable of type CCreditsCtrl, you would then use the following lines of code to override the default background drawer:

...
m_wndCredits.m_pBackgroundPaint = CAboutDlg::DrawCreditsBackground;
m_wndCredits.m_dwBackgroundPaintLParam = <code>dwAnything</CODE>;
...
m_wndCredits.Create(...);

..where dwAnything is the value you want CAboutDlg::DrawCreditsBackground to receive as lParam.

"Language"

OK, this is not really a language.. it's a few markup tags that tells the integrated parser, what the formatting should look like. It could be defined as custom HTML with XML rules... the perfect mix for your next headache :)

OK, here we go... first some basic guidelines:

  • Newline characters are not stripped, however it is recommended that you use the <br> and <p> tags (see below)... who knows maybe there will be a next version.
  • Unlike in HMTL, whitespace stays.
  • Again, unlike in HTML, tag parameters must be surrounded by either single- or double quotes: <tag param='value '> or <tag param=" value">. This is important!
  • Never, ever forget closing tags when required! (see reference below)
  • The parser isn't fault tolerant... which means that if you make formatting errors, it could make your program bug.. or what is worse! (However, you are still allowed to make spelin mistaks :)

Now to the tags:

  • font

    This is the most important one. It allows you to specify the font face, size, style, color and background as well as horizontal and vertical alignment for both text and images.

    It is used like this:

    <font face='FontFace' size='n' style='[b|-b] | [i|-i] | [u|-u] | [s|-s]' color='n,n,n' background='red,green,blue' align='left|center|right' valign='top|middle|bottom'></font>

    Looks confusing? Read on.

    Parameters:

    • face

      Specifies the font-name

    • size

      The font-size in device units

    • style

      b means bold, i means italic, u means underline, s means strikeout. You can combine any of those. If you precede one or more of the characters with a minus (-), it removes the corresponding style or styles (when using nested tags).

    • color

      The color of the font. The values can be from 0 to 255.

    • background

      Text background color. Same format as color.

    • align

      Horizontal alignment of the current line. Only the alignment in the last open font tag (with the align parameter specified) before a line break, will be considered: (all of this text will we centered :) ) <font align='left'>this <font align='center'>is a <font align='right'>test</font><br></font></font>

    • valign

      Defines how the current block is aligned on the line. E.g., if you have a line with a 50 pixel high bitmap and some 12 unit high text beside it, valign would tell the parser if the text should be aligned at the top, at the middle or at the bottom of the bitmap. Hope you got it, otherwise take a look at the demo.

    Notes & Tips:

    • This tag must always be combined with a closing </font> tag. Just like in HTML, except that, here things could get worse if you forgot it.
    • This tag can be nested, which means that you can put multiple font tags inside each other. A nested font tag keeps the attributes of the parent tag and changes only the specified parameters.
    • You would also use the font tag to change the alignment of images.
     

    Example:

    <font face='arial' size="14" color='255,0,0' style='buis'> <font style='-i-s'>some text</font></font>

    In this example, "some text" would be rendered with an Arial font, of size 14 in red, and would be bolded and underlined. Note that the second tag removes the italic and strikeout styles defined in the first.

  • img

    This tag allows you to insert an inline image:

    <img href='#n' border='n' color='n,n,n'>

    Parameters

    • src

      This parameter must be a hash character (#) followed by the numerical resource ID of the bitmap (in text-form, see the notes).

    • border

      Specifies the border-width. Can be zero.

    • color

      The border-color. Can be none for transparent.

     

    Notes & Tips:

    An easy way to specify the src parameter would be to do something similar to this:

    m_wndMyCreditsCtrl.FormatDataString("<img src='#%d'>",nBitmapID);

    If you use none for the color parameter, the value of border defines the space between the image and the element surrounding it.

    If whatever is behind the pound sign in the src parameter isn't a valid bitmap-resource-ID, you'll get an assertion! Be careful here.

  • a

    This tag is for defining text blocks and images as hyperlinks...

    <a href='TextToExecute | #[UserArgument#]CallbackFunction' face='FontFace' size='n' style='[b|-b] | [i|-i] | [u|-u] | [s|-s]' color='n,n,n' background='red,green,blue' align='left|center|right' valign='top|middle|bottom'></a>

    Parameters

    • href

      What the link does. You have two options here: Either you can specify anything that will be passed as the command parameter to ShellExecute or you can specify your own callback function by setting the first character to a hash sign.

      Let's have an example:

      class CAboutDlg : public CDialog
      {
        ...
        CCreditsCtrl m_wndCreditsCtrl;
        ...
        static void Test(LPCTSTR lpszArg)
          { AfxMessageBox(lpszArg); }
        ...
        afx_msg void OnInitDialog()
        {
          ...
          m_wndCreditsCtrl.FormatDataString(
              "<a href='#Hello World!#%d'>Click Me!</a>",
              (long)CAboutDlg::Test);
          m_wndCreditsCtrl.Create(...);
          ...
        }
      }

      This would display a CCreditsCtrl containing a link with the text "Click Me!". If you clicked that text, it would pop up a message box saying "Hello World!". Note that if you don't specify an argument (e.g. <a href='#%d'>), lpszArg is NULL.

      Important Note: Don't even try to specify an invalid address here! The rest of the parameters are the same as in <font> except that they only take effect when the cursor is over the link. If there is an image inside the <a> tag, the color attribute defines the border color when the cursor is over the image.

    Notes & Tips:

    You can achieve a cool effect for images if you use a border-width of 1 or 2 in the image tag with a border-color set to none and some other color in the <a> tag. This will make the border appear only when the mouse is over the image.

    You can open a browser window and make it navigate to a specific URL by setting href to e.g. "http://www.yourwebpage.com".

    You can start the user's mail application by setting href to mailto:foo@foo.org or mailto:foo@foo.org?SUBJECT=Hello World!", if you want a predefined subject. <a> tags can not be nested. Don't forget the closing of </a> tag!

  • br

    Inserts a line-break. Usage: <br>

    No Comments.

    Oh, yeah.. just one comment: If the line before the br tag is empty (no text or images), the line break gets the height of the current font. This is also true for <p> (see below).

  • p

    Inserts two line-breaks. Usage: <p>

    The height of the space equals the height of the current font.

  • hspace

    Inserts a horizontal space.

    <hspace size='n'>

    Parameters

    • size

      The size in pixels of the space.

    Notes & Tips:

    A space can not be a hyperlink.

  • vspace

    Wraps the current line if it isn't empty and inserts a vertical space.

    <vspace size='n'>

    Parameters

    • size

      The size in pixels of the space

    Notes & Tips:

    A space can (still) not be a hyperlink

That's it!! -- No more tags :-D

If you experience problems with this "language", have a look at the demo or at the source of the CCreditsCtrl::Initialize() function (not recommended). And if you still can't solve a problem or think it's a bug, post it below.

...ENJOY!!

Misc. Class Members

Here I will briefly comment some useful public class members, in case you'll ever need them...

BOOL Create(...);For a detailed description, see construction
CString SetDataString(...);

Sets the content of the control.

Return value: old content.

For more information, see content.

CString FormatDataString(...);

Sets the content of the control.

Return value: old content

For more information, see content.

CString GetDataString();Returns the value of m_sData which contains the content of the control.
int HitTest(CPoint pt);Returns the index of the link under the cursor. Can be used with m_HotRects and m_HotRectActions. If the cursor isn't over a link, -1 is returned
void SetDefaultBkColor(COLORREF crColor);Sets the background color that the default background drawer will use. If you use your own background drawer, don't call this function!
void Initialize();Parses the content of m_sData and fills m_HotRects and m_HotRectActions. If you modify m_sData manually (e.g. without calling SetDataString or FormatDataString), call this function to update your changes.
void SetDefaultLinkCursor();Sets the link cursor to a hand-cursor. I got this one from Chris Maunder's Hyperlink Control - thanks!

-- variables --

BOOL m_bCanScrollTRUE if the user should be allowed to manually scroll through the content of the control.
int m_nCurBitmapOffsetCurrent scroll-offset... normally you wouldn't want to modify this one.
int m_nTimerSpeedSpeed used in SetTimer(). Change this to get a slower/faster scroll speed. Default: 40
HCURSOR m_hDefaultCursorHandle to the default cursor. If you don't want to specify it with a resource ID in the <A href="#construction">Create</A> function, you can change this variable.. after having called Create.
HCURSOR m_hLinkCursorSame as m_hDefaultCursor but only used when the cursor is over a link.
CString m_sDataString containing the content of the control. Should be set with SetDataString or FormatDataString.
CArray<CRect,CRect&> m_HotRectsAn array containing the rectangles of all the links relative to the top of the content-bitmap (not the client rectangle). You should not modify its content.
CArray<CString,CString&> m_HotRectActionsArray containing all the link actions. Index matches the ones from m_HotRects. Should not be modified.
COLORREF m_crInternalTransparentColor

Color used internally as transparent color. Everything drawn with this color will be transparent (including bitmaps and text). You can use this to add transparency effects to your images.

Also this is the color fonts are initialized to (unless you specify a text background), so choose a color as close to the actual background color as possible (e.g., if you have a dark background, you would choose black as transparent color, or RGB(1,1,1) if you don't want the black parts of your bitmaps to be transparent.)

void(*m_pBackgroundPaint)(CDC*,RECT,BOOL,DWORD)

This variable holds the pointer of the callback function used for background drawing.

Please refer to the background section for more information.

DWORD m_dwBackgroundPaintLParamValue that the function stored in m_pBackgroundPaint will receive as its fourth parameter (lParam)

Tips and Tricks

  1. Download the Demo!
  2. RTFM!
  3. Customize <A href="#m_crInternalTransparentColor">m_crInternalTransparentColor</A> to fit your needs.
  4. Most color parameters (if not all) can take a value of none or transparent which will make them... transparent!
  5. The control begins scrolling (m_nTimerSpeed*10) milliseconds after it has been created. If you want to change this delay, modify m_nTimerSpeed just before calling Create and modify it back just after. For example, if you want to completely remove the delay, you would do like this:
    ...
    int nOldSpeed = m_wndCreditsCtrl.m_nTimerSpeed;
    m_wndCreditsCtrl.m_nTimerSpeed = 0;
    m_wndCreditsCtrl.Create(...);
    m_wndCreditsCtrl.m_nTimerSpeed = nOldSpeed;
    ...
  6. Add a good amount of <A href="#vspace"><vspace></A> at the end of the content... otherwise the beginning of the content will be displayed immediately after the end, and this is usually not what you want.
  7. A computer program does what you tell it to do, not what you want it to do... these are wise words :)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Engineer Nokia
Denmark Denmark
My programming experience started a long time ago in
QBasic (on a 25MHz 486).
I'm now mainly using Java, C++, C, MFC, Perl and PHP, but have used quite a number of other languages as well for various projects.

Comments and Discussions

 
Praisestill working well Pin
Southmountain5-Jan-21 7:37
Southmountain5-Jan-21 7:37 
GeneralMy vote of 5 Pin
maplewang31-Jul-12 0:59
maplewang31-Jul-12 0:59 
QuestionCould i get it in C# Pin
dooldots12-Nov-09 10:23
dooldots12-Nov-09 10:23 
GeneralNice Pin
ohdebug12-Sep-09 0:09
ohdebug12-Sep-09 0:09 
General.Net Version Pin
dustinmudryk9-Aug-06 14:09
dustinmudryk9-Aug-06 14:09 
GeneralIts a great work but i havea problem Pin
rajan_dd17-May-06 5:37
rajan_dd17-May-06 5:37 
GeneralHelp Please Pin
RahulOP23-Jan-06 0:50
RahulOP23-Jan-06 0:50 
GeneralStop Scrolling improvement... Pin
FreewareFire30-Mar-05 0:37
FreewareFire30-Mar-05 0:37 
GeneralScroll bar would be perfect Pin
BlastOff1-Nov-04 18:33
BlastOff1-Nov-04 18:33 
QuestionHow to change it from vertical scrolling to horizontal Pin
Atif Mushtaq1-Jul-04 23:12
Atif Mushtaq1-Jul-04 23:12 
GeneralDebug error in .NET Pin
speedpacer7-Nov-03 7:34
speedpacer7-Nov-03 7:34 
GeneralRe: Debug error in .NET Pin
Vero Nika23-May-04 5:19
Vero Nika23-May-04 5:19 
GeneralRe: Debug error in .NET Pin
ovanes12-Jun-04 8:27
ovanes12-Jun-04 8:27 
GeneralReally Good,But.... Pin
kingxu10-Feb-03 22:50
kingxu10-Feb-03 22:50 
GeneralRe: Really Good,But.... Pin
Atif Mushtaq1-Jul-04 23:50
Atif Mushtaq1-Jul-04 23:50 
GeneralHandy background image capability Pin
20-Dec-01 14:11
suss20-Dec-01 14:11 
GeneralSpeed Enhancement Pin
Benjamin Tucker30-May-01 21:23
Benjamin Tucker30-May-01 21:23 
GeneralTransparent cursor error Pin
Benjamin Tucker27-May-01 11:22
Benjamin Tucker27-May-01 11:22 
GeneralHere's a change for word wrap Pin
Kim Kemp25-May-01 15:46
Kim Kemp25-May-01 15:46 
GeneralRe: Here's a change for word wrap Pin
Marc Richarme28-May-01 10:17
Marc Richarme28-May-01 10:17 
GeneralGreat! Pin
22-Apr-01 20:55
suss22-Apr-01 20:55 
GeneralCool Pin
18-Apr-01 2:01
suss18-Apr-01 2:01 
Generalporting to ATL... Pin
Matt Philmon23-Feb-01 17:06
Matt Philmon23-Feb-01 17:06 
GeneralNice Class Pin
Darren S. Gonzales30-Jan-01 5:01
Darren S. Gonzales30-Jan-01 5:01 
GeneralReally Good!!! Pin
JohnJ13-Jan-01 4:13
JohnJ13-Jan-01 4:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.