How to make a colored button

22 01 2012

We cannot directly change the default color of push buttons in VC++ applications. WM_CTLCOLOR does  not work for push buttons. 😦  Then how can we set our own color for push buttons.

The only way to change the color for push buttons is to use owner-draw button control. That means we have to change the style of the push button to Owner draw. Then within the WM_DRAWITEM message handler we can decide what drawing action is required for our controls.

afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
The first parameter is the id of the control that sent the WM_DRAWITEM message and the second parameter pointing to DRAWITEMSTRUCT structure that contains information about the item to be drawn and the type of drawing required.

 

 

void CMyDialog::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	if(nIDCtl==IDC_BUTTON_COLOR)
	{
		CDC dc;

		dc.Attach(lpDrawItemStruct ->hDC);
		RECT rect;
		rect= lpDrawItemStruct ->rcItem;

		dc.FillSolidRect(&rect,RGB(0,255,0));
		UINT state=lpDrawItemStruct->itemState;

		if((state & ODS_SELECTED))
		{
			dc.DrawEdge(&rect,EDGE_SUNKEN,BF_RECT);

		}
		else
		{
			dc.DrawEdge(&rect,EDGE_RAISED,BF_RECT);
		}

		dc.SetBkColor(RGB(100,100,255));
		dc.SetTextColor(RGB(255,0,0));
		dc.SetBkMode( TRANSPARENT );

		TCHAR buffer[MAX_PATH];
		ZeroMemory(buffer,MAX_PATH );
		::GetWindowText(lpDrawItemStruct->hwndItem,buffer,MAX_PATH);
		dc.DrawText(buffer,&rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);

		dc.Detach();
	}				

	CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

Don’t forget to set Owner Draw property of the control as true form the IDE property section of the controls.

Advertisements




How to change the default font of a control

22 01 2012

Each windows controls(Static Text, Edit, Button etc) have its own default fonts. Sometimes we may need to change this for a better visibility or some other usability requirements.

Before setting a font to a control, we have to create a CFont object with desired size and other parameters using CreateFont function. Then we can set that font to any controls using CWnd’s SetFont function.

CFont newFont;

void ChangeFont()
{
	/** Create a font*/

    newFont.CreateFont(20,
		20,
		0,
		0,
		FW_BOLD,
		FALSE,
		FALSE,
		0,
		DEFAULT_CHARSET,
		OUT_CHARACTER_PRECIS,
		CLIP_CHARACTER_PRECIS,
		DEFAULT_QUALITY,
		DEFAULT_PITCH,
		NULL);

	/** Get the handle of a control*/
	CWnd* pCtrlWnd = GetDlgItem(IDC_ST_TEST_CONTROL);

	/** Set new font for that control*/
	pCtrlWnd->SetFont(&newFont, TRUE);
}

Font can be created in many ways, but the only important thing is font object should exist as long as the control exist. Otherwise font object should decalre as a member or a global object.





How to create a CEdit to display only float numbers

9 11 2009

Description

 

 

Have you ever face a situation to make an edit box that support only floating point numbers. That means the edit box do not accept more than one . (dot) and characters. How shall we do it? Just a trick! 🙂

HowCanIDoIt1

 

 

First of all we have to a derive a new CEdit class to our project and make a control of that on our window. Then we need to put a handler for WM_CHAR and EN_UPDATE messages for our custom edit class. Within the WM_CAHR message handler we can backup the existing value and within the EN_UPDATE message handler we can check the modified value. If its a valid double value, then only we need to update this with the edit control otherwise we can keep the previous value.

MyCodeSnippet

 

 

MyEdit.h

class CMyEdit : public CEdit
{
   DECLARE_DYNAMIC(CMyEdit)
public:
   CMyEdit();
   virtual ~CMyEdit();
protected:
   DECLARE_MESSAGE_MAP()
   afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
   afx_msg void OnUpdate();
private:
   CString m_strPrevValue;
   int m_nLastSel;
};

MyEdit.cpp

CMyEdit::CMyEdit()
{
   m_nLastSel = 0;
}

CMyEdit::~CMyEdit()
{
}

BEGIN_MESSAGE_MAP(CMyEdit, CEdit)
   ON_WM_CHAR()
   ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
END_MESSAGE_MAP()

void CMyEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
   GetWindowText(m_strPrevValue);
   m_nLastSel = GetSel();
   CEdit::OnChar(nChar, nRepCnt, nFlags);
}
void CMyEdit::OnUpdate()
{
   CString str;
   GetWindowText(str);
   errno = 0;
   LPTSTR endPtr;
   double doubleValue = _tcstod(str, &aEndPtr);
   if (*endPtr)
   {
      SetWindowText(m_strPrevValue);
      SetSel(m_nLastSel);
   }
}

MyNote

 

 

If you want to allows only digits to be entered into the edit control just use the style ES_NUMBER.





How to get all the child controls of a window

16 10 2009

Description

 

 

There are two types windows or controls we will deal with in our application. A parent window contains many number of child controls. How shall we enumerate all the child controls of a window. That means control ID, text etc etc…

HowCanIDoIt1

 

 

The EnumChildWindows function enumerates all the child windows/controls belongs to a specified window. This function invokes a application defined CALLBACK function until the last child control is enumerated or the function returns false.

MyCodeSnippet

 

 

void OnEnumerateChildCtrls()
{
   EnumChildWindows(this->m_hWnd,EnumWindowsProc, 0);
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
   TCHAR buff[256];
   ::GetWindowText(hwnd,(LPSTR)buff, 255);
   int nCtrlID = ::GetDlgCtrlID(hwnd);
   return TRUE;
}
void OnEnumerateChildCtrls()
{
   EnumChildWindows(this->m_hWnd,EnumWindowsProc, 0);
}
 
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
   TCHAR buff[256];
   ::GetWindowText(hwnd,(LPSTR)buff, 255);
   int nCtrlID = ::GetDlgCtrlID(hwnd);

   return TRUE;
}

mynote9

 

 

If a child window creates its own child controls, EnumChildWindows enumerates that also.





How to insert colored text into CRichEditCtrl

23 03 2009

description4

 

 

Sometimes we need to insert text with different colors into our CRichEditCtrl. Not only just changes the color of the text but also need to format the characters in the control.

richeditcoloredtxt

 

howcanidoit4

 

 

CRichEditCtrl provides a function SetSelectionCharFormat for that. Actually this function passing a pointer to a CHARFORMAT structure containing the new character formatting attributes. Please see the different members of this structure in the MSDN.

mycodesnippet4

 

 

void InsertColoredTextIntoRichEditCtrl()
{
   CHARFORMAT cf;
  
   cf.cbSize      = sizeof(cf);
   cf.dwMask      = CFM_BOLD|CFM_COLOR  ;
   cf.dwEffects   = CFE_BOLD|~CFE_AUTOCOLOR  ;
  
   myRichEditCtrl.SetWindowText("I want colored text");
  
   cf.crTextColor = RGB(0,255,0); 
  
   myRichEditCtrl.SetSel(0,1);
   myRichEditCtrl.SetSelectionCharFormat(cf);
  
   cf.crTextColor = RGB(255,0,0);
   myRichEditCtrl.SetSel(2,6);
   myRichEditCtrl.SetSelectionCharFormat(cf);
  
   cf.crTextColor = RGB(0,0, 255);
   myRichEditCtrl.SetSel(7,15);
   myRichEditCtrl.SetSelectionCharFormat(cf);
  
   cf.crTextColor = RGB(220,69, 133);
   myRichEditCtrl.SetSel(15,19);
   myRichEditCtrl.SetSelectionCharFormat(cf);
}

mynote6

 

 

If you are using a rich edit control in a dialog box, dont forget to call AfxInitRichEdit once before the dialogbox is displayed.





How to set color for static text controls

17 03 2009

 description3

 

 

Sometimes we need to change the color of the static text on our window. Actually the default colour of the static text is black.

howcanidoit3

 

 

MFC provides a CWnd::OnCtlColor function for that. Actually this function handles the WM_CTLCOLOR messages of the window. The framework calls this member function when a child control is about to be drawn.

mycodesnippet3

 

 

HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{   
   HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);      
  
   if(pWnd->GetDlgCtrlID() == IDC_ST_MY_STATIC_CTRL)   
   {      
      //set the static text color to red      
      pDC->SetTextColor(RGB(255, 0, 0));   
   }      
  
   // TODO: Return a different brush if the default is not desired   
   return hbr;
}

mynote4

 

 

If you want to do it in the Win32 application just handle the message WM_CTLCOLORSTATIC .





How to make a read only Edit box

6 01 2009

description4

 

 

We are familiar with Edit box control, a rectangular child window in which the user can enter text. But some times we need to make a read only Edit box that means non-writable.

readonlyeditbox3

 

 

 

  

 

 

This could achieve by overriding the PreTranslateMessage function on our CDialog derived class  and thus we can easily process on messages sent to our window before they are hand over to child windows. In our particular case we need to prevent the WM_KEYDOWN message write anything to our particular Edit box.

Return value of the PreTranslate function determines whether the particular message need to be dispatched or not. Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched.

mycodesnippet3

 

 

BOOL CMyDialog:: PreTranslateMessage(MSG* pMsg)
{
   //m_MyEditBox - read only edit box
   if(m_MyEditBox.m_hWnd == pMsg->hwnd)
   {
      if(pMsg->message == WM_KEYDOWN)
      {
         //Nullifying the WM_KEYDOWN message
         pMsg->wParam=NULL ;
      }
   }
  
   return CDialog:: PreTranslateMessage(pMsg);
}

mynote3

 

 

All windows message could be nullified within the PreTranslateMessage function.