Providing a Format toolbar


A rich edit control without UI to change the character and paragraph formatting is not really very useful as a rich text editor. In this section we will develop code for a Format toolbar that can be used with a CRichEditView derivative. There is no hard link between the toolbar itself and the CRichEditView, so we can even use this toolbar with a sub-class of CRichEditCtrl. The only extra work would be to make sure that some of the notifications sent by the toolbar gets forwarded to the control.

There is a huge scope for improvement in the code given here, but intergrating this in your application should be fairly easy. When you feel that you need more functionality out of the Format toolbar, take a look at the WordPad sample that comes with your Visual C++ CD. This sample is the actual source code for the WordPad applet that ships with Windows. Be warned though, it takes a little time to understand the code.

Step 1: Create a toolbar control resource

The first thing we need to do is create a toolbar control resource. Actually you can create a toolbar from a bitmap but it is lot easier to work with a toolbar control. The resource editor has quite a good support for it.

This is what the toolbar control looks like in the resource editor. Give the toolbar control resource the ID - IDR_FORMATBAR. Actually choose any name but you should be willing to replace all occurance of IDR_FORMATBAR in the code below with the new ID.

The first two buttons are place holders for the Font Name combobox and the Font Size combobox. The other buttons are pretty obvious. Once we have the images, we should go ahead and set the properties. Besides specifying an ID for each button, we should also provide the prompt string. The prompt string is used for the help text that appears in the status bar and the tooltip text.

The 'Toolbar Button Properties' dialog is shown above for the Font Name button. The table below lists suggested IDs and prompt strings - in the same sequence they appear in the toolbar.

IDPrompt
IDC_FONTNAMEChanges the font of the selection\nFont
IDC_FONTSIZEChanges the font size of the selection\nFont Size
ID_CHAR_BOLDMakes the selection bold (toggle)\nBold
ID_CHAR_ITALICMakes the selection italics (toggle)\nItalic
ID_CHAR_UNDERLINEFormats the selection with a continuous underline (toggle)\nUnderline
ID_CHAR_COLORFormats the selection with a color\nColor
ID_PARA_LEFTLeft-justifies paragraphs\nLeft Justify
ID_PARA_CENTERCenter-justifies paragraphs\nCenter Justify
ID_PARA_RIGHTRight-justifies paragraph\nRight Justify
ID_INSERT_BULLETInserts a bullet on this line\nBullet

Step 2: Create a CFormatBar class

I used the Class Wizard to create this class. The class wizard did not have the option of specifying the CToolBar class as the base class, so I chose the CToolBarCtrl class as the base class and then in the source files, changed it to CToolBar. The advantage of using a CToolBar is that it is already hooked into the Doc-View architecture of MFC. This helps in updating the toolbar and the status bar.

The code for the CFormatBar class header file is given below. You will notice that besides declaring the CFormatBar class, it also declares CHARNMHDR struct. This is used to send custom notification messages whenever the font name or the font size changes. The FN_SETFORMAT and FN_GETFORMAT defines are the custom notification message values.

The CFormatBar constructor takes a default value which is set to IDR_FORMATBAR. This is useful only if you already have a resource with the ID IDR_FORMATBAR that you are using for some other purpose.

#if !defined(AFX_FORMATBAR_H__76705223_1E1F_11D1_830C_5CB0BB000000__INCLUDED_)
#define AFX_FORMATBAR_H__76705223_1E1F_11D1_830C_5CB0BB000000__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// FormatBar.h : header file
//



/////////////////////////////////////////////////////////////////////////////
// CFormatBar window

struct CHARNMHDR : public NMHDR
{
	CHARFORMAT cf;
	CHARNMHDR() {cf.cbSize = sizeof(CHARFORMAT);}
};

// Define format notifications constant
#define FN_SETFORMAT	0x1000
#define FN_GETFORMAT	0x1001


class CFormatBar : public CToolBar
{
// Construction
public:
	enum { IDD = IDR_FORMATBAR };
	CFormatBar(UINT nID = IDD );

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CFormatBar)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CFormatBar();

protected:
	void FillFontName( CDC *pDC );
	virtual void OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler);


protected:
	CComboBox	m_cmbFontName;
	CComboBox	m_cmbFontSize;

	// Generated message map functions
protected:
	afx_msg void OnSelectFontName();
	afx_msg void OnSelectFontSize();

	//{{AFX_MSG(CFormatBar)
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()

private:
	UINT nToolbarID;
	static int CALLBACK EnumFontFamProc(ENUMLOGFONT *lpelf, 
					NEWTEXTMETRIC *lpntm,
					int nFontType,
					LPARAM lParam);

};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_FORMATBAR_H__76705223_1E1F_11D1_830C_5CB0BB000000__INCLUDED_)

The code in the implementation file for CFormatBar now follows.

/////////////////////////////////////////////////////////////////////////////
// FormatBar.cpp : implementation file
//

#include "stdafx.h"
#include "RichEdit.h"
#include "FormatBar.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFormatBar

// Declare const array of font sizes
const static int nFontSizes[] = 
	{8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72};


CFormatBar::CFormatBar(UINT nID )
{
	nToolbarID = nID;
}

CFormatBar::~CFormatBar()
{
}


BEGIN_MESSAGE_MAP(CFormatBar, CToolBar)
	//{{AFX_MSG_MAP(CFormatBar)
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
	ON_CBN_SELENDOK(IDC_FONTNAME, OnSelectFontName)
	ON_CBN_SELENDOK(IDC_FONTSIZE, OnSelectFontSize)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFormatBar message handlers

int CFormatBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CToolBar::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// Load the toolbar
	if( !LoadToolBar( nToolbarID ) )
		return -1;


	// Get the average char width
	CClientDC dc(this);

	// Determine the size required by the font comboboxes
	// We will use the DEFAULT_GUI_FONT
	HGDIOBJ hFont = GetStockObject( DEFAULT_GUI_FONT );
	CFont font;
	font.Attach( hFont );
	dc.SelectObject( font );

	TEXTMETRIC tm;
	dc.GetTextMetrics( &tm );
	int cxChar = tm.tmAveCharWidth;
	int cyChar = tm.tmHeight + tm.tmExternalLeading;


	// Create the Font Name combo
	CRect rect; 
	GetItemRect( CommandToIndex(IDC_FONTNAME), &rect );
	rect.right = rect.left + (LF_FACESIZE+4)*cxChar;
	rect.bottom = rect.top + 16*cyChar;

	SetButtonInfo( CommandToIndex(IDC_FONTNAME), IDC_FONTNAME, 
				TBBS_SEPARATOR, rect.Width() );

	UINT nCreateStyle = WS_TABSTOP|WS_VISIBLE|WS_VSCROLL;
	if (!m_cmbFontName.Create(nCreateStyle|CBS_DROPDOWNLIST|CBS_SORT, 
		rect, this, IDC_FONTNAME))
	{
		TRACE0("Failed to create Font Name combo-box\n");
		return -1;
	}


	// Create Font Size combo
	GetItemRect( CommandToIndex(IDC_FONTSIZE), &rect );
	rect.right = rect.left + 10*cxChar;
	rect.bottom = rect.top + 16*cyChar;

	SetButtonInfo( CommandToIndex(IDC_FONTSIZE), IDC_FONTSIZE, 
				TBBS_SEPARATOR, rect.Width() );

	if (!m_cmbFontSize.Create(nCreateStyle|CBS_DROPDOWN|WS_HSCROLL, 
		rect, this, IDC_FONTSIZE))
	{
		TRACE0("Failed to create Font Size combo-box\n");
		return -1;
	}
	m_cmbFontSize.LimitText(4);


	// Set the font for the combo boxes to DEFAULT_GUI_FONT
	m_cmbFontName.SetFont(&font);
	m_cmbFontSize.SetFont(&font);

	// Fill the Font names in the Font Name combo
	::EnumFontFamilies( dc.m_hDC, NULL, (FONTENUMPROC)EnumFontFamProc, 
				(LPARAM) this );

	// Fill the Font Size combo
	CString sSize;
	int nSizeCount = sizeof(nFontSizes) / sizeof(nFontSizes[0]);
	for( int i=0; i < nSizeCount; i++ )
	{
		sSize.Format("%d", nFontSizes[i] );
		m_cmbFontSize.AddString( sSize );
	}

	return 0;
}

int CALLBACK CFormatBar::EnumFontFamProc(ENUMLOGFONT *lpelf, NEWTEXTMETRIC *lpntm,
					int nFontType, LPARAM lParam)
{
	CFormatBar* pWnd = (CFormatBar*)lParam;

	// Add the font name to the combo
	pWnd->m_cmbFontName.AddString(lpelf->elfLogFont.lfFaceName);

	return 1;		// 1 to continue enumeration
}

void CFormatBar::OnSelectFontName()
{
	TCHAR szFontName[LF_FACESIZE];
	int nIndex = m_cmbFontName.GetCurSel();
	m_cmbFontName.GetLBText( nIndex, szFontName );

	// If font name is empty - return
	if( szFontName[0] == 0 )
		return;

	CHARNMHDR fh;
	CHARFORMAT& cf = fh.cf;
	fh.hwndFrom = m_hWnd;
	fh.idFrom = GetDlgCtrlID();
	fh.code = FN_SETFORMAT;
	cf.dwMask = CFM_FACE;

	_tcsncpy(cf.szFaceName, szFontName, LF_FACESIZE);	//strncpy

	GetOwner()->SendMessage(WM_NOTIFY, fh.idFrom, (LPARAM)&fh);
}

void CFormatBar::OnSelectFontSize()
{
	TCHAR szSize[5];
	int index = m_cmbFontSize.GetCurSel();
	if( index != CB_ERR )
		m_cmbFontSize.GetLBText(index, szSize );
	else
		m_cmbFontSize.GetWindowText( szSize, 5 );

	// Get size in Twips
	int nSize = _ttoi( szSize ) * 20;			// atoi for tchar

	if( !nSize )
		return;

	CHARNMHDR fh;
	CHARFORMAT& cf = fh.cf;
	fh.hwndFrom = m_hWnd;
	fh.idFrom = GetDlgCtrlID();
	fh.code = FN_SETFORMAT;

	cf.dwMask = CFM_SIZE;
	cf.yHeight = nSize;

	GetOwner()->SendMessage(WM_NOTIFY, fh.idFrom, (LPARAM)&fh);
}

void CFormatBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
	// Take care of the regular toolbar buttons
	CToolBar::OnUpdateCmdUI( pTarget, bDisableIfNoHndler);

	// Don't update the combo boxes if user changing font attribute
	CWnd *pWnd = GetFocus();
	if( pWnd == &m_cmbFontName || m_cmbFontSize.IsChild(pWnd) )
		return;

	// get the current font from the view and update
	CHARNMHDR fh;
	CHARFORMAT& cf = fh.cf;
	fh.hwndFrom = m_hWnd;
	fh.idFrom = GetDlgCtrlID();
	fh.code = FN_GETFORMAT;

	CWnd *pOwnerWnd = GetOwner();
	if( !GetOwner()->SendMessage(WM_NOTIFY, fh.idFrom, (LPARAM)&fh) )
	{
		TRACE0("The Rich Edit View/Control has to handle the FN_GETFORMAT\n"
			"notification for the Format Bar to work properly\n");
		return;
	}

	// Update the font only if the selection font is different
	TCHAR szName[LF_FACESIZE];
	m_cmbFontName.GetWindowText( szName, LF_FACESIZE );

	// the selection must be same font and charset to display correctly
	if ((cf.dwMask & (CFM_FACE|CFM_CHARSET)) != (CFM_FACE|CFM_CHARSET))
		m_cmbFontName.SetCurSel( -1 );
	else if( ::_tcscmp( szName, cf.szFaceName ) != 0 )
	{
		if( m_cmbFontName.SelectString( -1, cf.szFaceName ) == CB_ERR )
			m_cmbFontName.SetCurSel( -1 );
	}


	// Update the font size
	TCHAR szSize[5];
	m_cmbFontSize.GetWindowText( szSize, 5 );
	int nSize = _ttoi( szSize );				// atoi for tchar

	// Update the font size only if selection is different 
	int nSelSize = (cf.dwMask & CFM_SIZE) ? cf.yHeight/20 : 0;
	if( nSize != nSelSize )
	{
		if(cf.dwMask & CFM_SIZE)
		{
			CString strSize;
			strSize.Format("%d", nSelSize );
			m_cmbFontSize.SetWindowText( strSize );
		}
		else
			m_cmbFontSize.SetCurSel(-1);
	}
}

BOOL CFormatBar::PreTranslateMessage(MSG* pMsg) 
{
	if (pMsg->message == WM_KEYDOWN)
	{
		NMHDR nm;
		nm.hwndFrom = m_hWnd;
		nm.idFrom = GetDlgCtrlID();
		nm.code = NM_RETURN;
		switch (pMsg->wParam)
		{
		case VK_RETURN:
			// Send change notification
			if( m_cmbFontName.IsChild(GetFocus()) )
				OnSelectFontName();
			else if( m_cmbFontSize.IsChild(GetFocus()) )
				OnSelectFontSize();
			//Fall through
		case VK_ESCAPE:
			GetOwner()->SendMessage(WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
			return TRUE;
		}
	}
	
	return CToolBar::PreTranslateMessage(pMsg);
}

At the top of the file, the nFontSizes array is declared. This array is initialized to the commonly used font sizes and is used to initialize the font size combobox. To make the design simple, the CFormatBar class has beed designed so that the user is always provided with this list of sizes even though the font may not support all of these sizes. The user can also type in an arbitrary value for the font size.

The OnCreate() function calls the base class version of the function so that the toolbar gets created. It then loads the toolbar from the resource and creates the two comboboxes - for font name and font size. To make place for the comboboxes, the place holder buttons are resized using the SetButtonInfo() function. We use the font that will be used in the combobox to determine a reasonable width for the control. Since a font name can have at most LF_FACESIZE characters, we use this number and the average width of a character to determine the width of the font name combobox. LF_FACESIZE by the way is a constant defined as 32. Similarly we make the font size combobox wide enough to accommodate 4 characters.

The font name combobox is created with the CBS_DROPDOWNLIST style. This style forces the user to select one of the listed styles. You may want to change this style to CBS_DROPDOWN so that the user may specify a font that may not be available on the machine. The font size combobox uses the CBS_DROPDOWN style to allow the user to type in any point size or select from the list.

At the end, the OnCreate() function populates the font size combobox by calling the EnumFontFamilies() function, which in turn calls the EnumFontFamProc() for each font on the system (the screen device context). It is EnumFontFamProc() that actually adds the font names to the combobox. OnCreate() also populates the font size combobox from the array of common font sizes.

The OnSelectFontName() is called when the user selects a list item in the font name combobox. Notice the entry ON_CBN_SELENDOK(IDC_FONTNAME, OnSelectFontName) in the message map hooking up this function. This function is also called when the user hits the enter key. The purpose of this function is to send out a notification so that the rich edit control can be updated. It uses an extended notification header so that it can also pass on the character format information. Note that it uses a custom notification code. It is the responsibility of the rich edit control class to handle this notification and change the format accordingly. Similarly, the OnSelectFontSize() handles the font size combobox.

The OnUpdateCmdUI() function is called by the framework to update the status of the toolbar. We override this function because the Format Bar has the two comboboxes. The toolbar buttons get updated by the regular ON_UPDATE_COMMAND_UI() message map macros but the combobox needs special handling. This function basically gets the font information about the current selection from the rich edit control and updates the font comboboxes. This of course doesn't make sense if the user is trying to change the font. The function, therefore returns immediately if either of the comboboxes have the input focus. Here again a custom notification is sent out. The FN_GETFORMAT should be handled by the rich edit control and the control should return the format information through the notification header structure.

Overriding the PreTranslateMessage() is how we tackle the situation when the user presses the enter or the escape key. When the user presses the enter key, it calls the OnSelectFontName() or the OnSelectFontSize() function, whichever is appropriate. The function then sends the NM_RETURN notification. This is another notification that the rich edit control has to look out for. On receiving this message, the rich edit control should take back the input focus.

Step 3: Create the Format toolbar

To create the format toolbar, first add a CFormatBar member variable in the CMainFrame class. Actually any frame class that will contain the CRichEditView or CRichEditCtrl will do.
protected:  // control bar embedded members
	CFormatBar	m_wndFormatBar;

Create the format toolbar in the OnCreate() function. Here's sample code that does that.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (!m_wndFormatBar.Create(this, WS_CHILD | WS_VISIBLE |
			CBRS_TOP |CBRS_TOOLTIPS|CBRS_FLYBY,
			IDR_FORMATBAR) )
	{
		TRACE0("Failed to create FormatBar\n");
		return -1;      // fail to create
	}
	m_wndFormatBar.SetWindowText( _T("Format") );
	m_wndFormatBar.EnableDocking(CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM);
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar( &m_wndFormatBar );

	:
	:
	:	

	return 0;
}

Step 4: Add handlers for format toolbar notifications

As we have already covered, the CFormatBar sends a couple of custom notification as well as the NM_RETURN notification. These notifications inform the rich edit control about activities on the toolbar. The Class Wizard won't be able to help you add these handlers, so you would have to add the entries to the message map yourself.
BEGIN_MESSAGE_MAP(CMyRichEditView, CRichEditView)
	//{{AFX_MSG_MAP(CMyRichEditView)
	:
	:
	//}}AFX_MSG_MAP
	ON_NOTIFY(FN_GETFORMAT, IDR_FORMATBAR, OnGetCharFormat)
	ON_NOTIFY(FN_SETFORMAT, IDR_FORMATBAR, OnSetCharFormat)
	ON_NOTIFY(NM_RETURN, IDR_FORMATBAR, OnBarReturn)
END_MESSAGE_MAP()

The implementation of the handler functions are quite simple. The OnGetCharFormat() function simply gets the format of the current selection and returns this through the notification header. The OnSetCharFormat() receives the format information through the notification header and applies it to the current selection. The OnBarReturn() simply sets focus to the rich edit control.

void CMyRichEditView::OnGetCharFormat(NMHDR* pNMHDR, LRESULT* pRes)
{
	((CHARNMHDR*)pNMHDR)->cf = GetCharFormatSelection();
	*pRes = 1;
}

void CMyRichEditView::OnSetCharFormat(NMHDR* pNMHDR, LRESULT* pRes)
{
	SetCharFormat(((CHARNMHDR*)pNMHDR)->cf);
	*pRes = 1;
}

void CMyRichEditView::OnBarReturn(NMHDR*, LRESULT* )
{
	SetFocus();
}

Step 5: Add UPDATE_COMMAND_UI & COMMAND handlers

The CRichEditView class already provides support for all but one of the remaining format toolbar buttons. So all we need to do is hook up the message map entries so that the proper functions get called. The only function that we have to write is for the color button. The message map entries and the OnColorPick() function is shown below. We do not have to write the other functions since they are already defined in CRichEditView.
BEGIN_MESSAGE_MAP(CMyRichEditView, CRichEditView)
	//{{AFX_MSG_MAP(CMyRichEditView)
	:
	:
	ON_COMMAND(ID_CHAR_COLOR, OnColorPick)
	ON_COMMAND(ID_CHAR_BOLD, OnCharBold)
	ON_UPDATE_COMMAND_UI(ID_CHAR_BOLD, OnUpdateCharBold)
	ON_COMMAND(ID_CHAR_ITALIC, OnCharItalic)
	ON_UPDATE_COMMAND_UI(ID_CHAR_ITALIC, OnUpdateCharItalic)
	ON_COMMAND(ID_CHAR_UNDERLINE, OnCharUnderline)
	ON_UPDATE_COMMAND_UI(ID_CHAR_UNDERLINE, OnUpdateCharUnderline)
	ON_COMMAND(ID_PARA_CENTER, OnParaCenter)
	ON_UPDATE_COMMAND_UI(ID_PARA_CENTER, OnUpdateParaCenter)
	ON_COMMAND(ID_PARA_LEFT, OnParaLeft)
	ON_UPDATE_COMMAND_UI(ID_PARA_LEFT, OnUpdateParaLeft)
	ON_COMMAND(ID_PARA_RIGHT, OnParaRight)
	ON_UPDATE_COMMAND_UI(ID_PARA_RIGHT, OnUpdateParaRight)
	ON_COMMAND(ID_INSERT_BULLET, OnBullet)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


void CMyRichEditView::OnColorPick() 
{
	CColorDialog dlg;

	if( dlg.DoModal() == IDOK ){
		CRichEditView::OnColorPick(dlg.GetColor());
	}
}



Comments

  • About the Font Families Combo box

    Posted by Legacy on 08/19/2003 12:00am

    Originally posted by: KALAITZOGLOU PANAYOTIS

    Thank you very much for this article. I learned many different things (especially msg passing mechanisms) by studying this code.
    
    

    I want to ask (or correct smthng). I use parts of this code in my application and when selecting text that has a variety of font family names and then trying to set the font family there is an access violation... The same thing does not happen with font sizes. So I modified the

    OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)

    lines:

    // Don't update the combo boxes if user changing font attribute
    CWnd *pWnd = GetFocus();
    if( pWnd == &m_cmbFontName || m_cmbFontSize.IsChild(pWnd) )
    return;

    To:

    // Don't update the combo boxes if user changing font attribute
    CWnd *pWnd = GetFocus();
    if( m_cmbFontName.IsChild(pWnd) || m_cmbFontSize.IsChild(pWnd) )
    return;


    and now it seems to work ok. But why did you do a different check for m_cmbFontName and m_cmbFontSize? Am I missing smthng?

    Thanx again for the valuable code you share,

    Panayotis

    Reply
  • Expanded combobox buttons hide other buttons beneath it

    Posted by Legacy on 07/07/2003 12:00am

    Originally posted by: m m

    Everything works fine. But here is a general question:

    How do insert a separator into my toolbar resource IDR_FORMATBAR. I created a blank button but class wizard says that ID of the button cannot be blank. Does anybody know how to create a separator? I tried to assign ID_SEPARATOR to the button but the wizard won't let me do that.

    Any help is appreciated. Thanks a lot!

    m m

    Reply
  • A solution for VC++.NET

    Posted by Legacy on 02/23/2003 12:00am

    Originally posted by: BN37

    When compiling the code for the .NET version of VC++, I got the error:

    error C2664: 'CRichEditView::SetCharFormat' : cannot convert parameter 1 from 'CHARFORMATA' to 'CHARFORMAT2A'

    I fixed it by modifying the structure CHARNMHDR in the formatbar.h file:

    ...
    00: // CFormatBar window
    01:
    02: struct CHARNMHDR : public NMHDR
    03: {
    04: CHARFORMAT cf;
    05: CHARNMHDR() {cf.cbSize = sizeof(CHARFORMAT);}
    06: };
    07:
    08: // Define format notifications constant
    09: #define FN_SETFORMAT 0x1000
    ...

    to:
    ...
    00: // CFormatBar window
    01:
    02: struct CHARNMHDR : public NMHDR
    03: {
    04: CHARFORMAT2A cf;
    05: CHARNMHDR() {cf.cbSize = sizeof(CHARFORMAT);}
    06: };
    07:
    08: // Define format notifications constant
    09: #define FN_SETFORMAT 0x1000
    ...

    After making the single modification on line 4, the code compiled smoothly. In case any of you out there have had the same problem and did not know how to resolve this issue, this should help you.

    Happy programming,

    BN37

    Reply
  • How to change text direction

    Posted by Legacy on 03/04/2002 12:00am

    Originally posted by: Nazir Ahmed

    How to change to type direction as default direction for English is from left to write I wana a develop a control which uses text direction from right to left

    Reply
  • How to insert an OLE object into a CRichEditCtrl

    Posted by Legacy on 11/13/2001 12:00am

    Originally posted by: hxbings

    I want to insert an OLE object into a CRichEditCtrl placed on the dialog and edit it by double_click ,i tried many times,but i can't.
    Would you like solute this problem?
    And how to make a dialog-based application be an ActiveX container?
    Thanks a lot.

    Reply
  • on dialog

    Posted by Legacy on 06/08/2001 12:00am

    Originally posted by: Ehsan samani

    I am trying put this thing on a static control in a dialog on top of list view. It fails to create the toolbar. do you know why.

    if(m_pCFormatBar->Create(&m_staticText,
    WS_CHILD | WS_VISIBLE |CBRS_TOP |CBRS_TOOLTIPS|CBRS_FLYBY,IDRS_FORMATBAR_TOOLBAR))

    {
    TRACE0("Failed to create FormatBar\n");
    }

    thanks

    Reply
  • Changing Font for CRichEditCtrl

    Posted by Legacy on 05/25/2000 12:00am

    Originally posted by: cyril

    Hi,

    I actually have a problem. I use a CRichEditView, and I'd like to change the font, for each caracter to have the same size (actually, a "space" is less large than other caracters like "A" for example)

    Do you have a solution ?

    I have an other problem.
    I use a CMDIChildWindow, with a split. In the first pane is a dialo, with a CEditCtrl. When I change the value and press "Enter", the childWindow becomes white, and when I close it, it comes back.
    Do you know how to resolve this problem ??

    Thanks a lot !

    Reply
  • Missing ToolTips

    Posted by Legacy on 04/22/2000 12:00am

    Originally posted by: Brad Younie

    I'm developing a product that uses the CFormatBar and it works great, except for this one pesky little problem: I can't get the tool tips to display, nor will it display the prompt on the StatusBar.

    I do include the CBRS_TOOLTIPS flag in my call to CFormatBar::Create, but the tooltips don't appear. The tooltips in my other toolbars work, just not in the CFormatBar.

    Is there any special trick to make them work?

    Reply
  • FunctionX - Visual C++ Tutorial

    Posted by Legacy on 01/19/2000 12:00am

    Originally posted by: Jacques E. ZOO

    I have a working project that uses this formatbar. You can check it at http://www.functionx.com/samples/index.htm.
    Thanks.

    Reply
  • Errors!

    Posted by Legacy on 01/05/2000 12:00am

    Originally posted by: Charles Sanglimsuwan

    HEY YO I ALSO GOT THE SAME ERRORS!!!

    FIX UP YOUR CODE ZAFIR!!

    YES

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Learn How A Global Entertainment Company Saw a 448% ROI Every business today uses software to manage systems, deliver products, and empower employees to do their jobs. But software inevitably breaks, and when it does, businesses lose money -- in the form of dissatisfied customers, missed SLAs or lost productivity. PagerDuty, an operations performance platform, solves this problem by helping operations engineers and developers more effectively manage and resolve incidents across a company's global operations. …

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

Most Popular Programming Stories

More for Developers

RSS Feeds