Click here to Skip to main content
15,886,689 members
Articles / Desktop Programming / MFC

Dynamically switchable multi-purpose control

Rate me:
Please Sign up or sign in to vote.
4.43/5 (9 votes)
5 Mar 2002CPOL10 min read 149.5K   2.2K   57  
Control which allows run-time switching between a number of control types, eg combo, edit etc
////////////////////////////////////////////////////////////////////////////
// File:	BrowseEdit.cpp
// Version:	1.0.0.1
// Created:	05-Mar-2002
//
// Author:	Paul S. Vickery
// E-mail:	paul@vickeryhome.freeserve.co.uk
//
// Edit control with embedded ... (ellipsis) button
//
// You are free to use or modify this code, with no restrictions, other than
// you continue to acknowledge me as the original author in this source code,
// or any code derived from it.
//
// If you use this code, or use it as a base for your own code, it would be 
// nice to hear from you simply so I know it's not been a waste of time!
//
// Copyright (c) 2001-2002 Paul S. Vickery
//
////////////////////////////////////////////////////////////////////////////
// Version History:
//
// Version 1.0.0.1 - 05-Mar-2002
// =============================
// Fixes problem with a BrowseEdit created with ES_READONLY not having button
// disabled.
//
// Version 1.0.0.0 - 27-Jul-2001
// =============================
// Initial version.
// 
////////////////////////////////////////////////////////////////////////////
// PLEASE LEAVE THIS HEADER INTACT
////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "BrowseEdit.h"

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

#define ID_EDIT		1
#define ID_BUTTON	2

/////////////////////////////////////////////////////////////////////////////
// CBrowseEditButton

BEGIN_MESSAGE_MAP(CBrowseEditButton, CButton)
	//{{AFX_MSG_MAP(CBrowseEditButton)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBrowseEditButton message handlers

void CBrowseEditButton::OnLButtonUp(UINT nFlags, CPoint point) 
{
  CButton::OnLButtonUp(nFlags, point);
  // set the focus back to the parent, and stop it looking like the default button
  ModifyStyle(BS_DEFPUSHBUTTON, 0);
  GetParent()->SetFocus();
}

void CBrowseEditButton::OnLButtonDown(UINT nFlags, CPoint point) 
{
  CButton::OnLButtonDown(nFlags, point);
  // stop it looking like the default button
  ModifyStyle(BS_DEFPUSHBUTTON, 0);
}

/////////////////////////////////////////////////////////////////////////////
// CBrowseEdit

CBrowseEdit::CBrowseEdit()
{
  m_pEdit = new CEdit;
  m_pBtn = new CBrowseEditButton;
}

CBrowseEdit::~CBrowseEdit()
{
  if (m_pEdit != NULL)
    delete m_pEdit;
  if (m_pBtn != NULL)
    delete m_pBtn;
}

BEGIN_MESSAGE_MAP(CBrowseEdit, CWnd)
	//{{AFX_MSG_MAP(CBrowseEdit)
	ON_WM_CREATE()
	ON_WM_ENABLE()
	ON_WM_SETFOCUS()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBrowseEdit message handlers

void CBrowseEdit::PreSubclassWindow() 
{
  CWnd::PreSubclassWindow();

#if 0

  CRect rc(0, 0, 0, 0);

  // Get the edit control styles and create the edit control
  // we want to isolate the edit styles from the style, and
  // visible and disabled if specified
  // then add in WS_CHILD
  DWORD dwStyle = GetStyle();
  DWORD dwStyleEdit = dwStyle & (WS_VISIBLE | WS_DISABLED | 0x3DFFL);
  dwStyleEdit |= WS_CHILD | WS_CLIPSIBLINGS;
  if (!m_pEdit->Create(dwStyleEdit, rc, this, ID_EDIT))
    return;

  // Get the button styles and create the button
  // just allow visible and disabled from the specified style
  // and add WS_CHILD and BS_PUSHBUTTON
  DWORD dwStyleBtn = dwStyle & (WS_VISIBLE | WS_DISABLED);
  dwStyleBtn |= WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON;
  if (!m_pBtn->Create("...", dwStyleBtn, rc, this, ID_BUTTON))
    return;

  GetWindowRect(&rc);
  int cx = rc.Width();
  int cy = rc.Height();
  CRect rcEdit(0, 0, cx - cy, cy);
  CRect rcBtn(cx - cy, 0, cy, cy);
  m_pEdit->MoveWindow(0, 0, cx - cy, cy);
  m_pBtn->MoveWindow(cx - cy, 0, cy, cy);

  // set the font to this control's font
  CFont* pFont = GetFont();
  m_pEdit->SetFont(pFont);
  m_pBtn->SetFont(pFont);
#endif  
}

BOOL CBrowseEdit::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID)
{
  if (!CWnd::Create(NULL, NULL, dwStyle, rect, pParentWnd, nID))
    return FALSE;

  return TRUE;
}

int CBrowseEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
  if (CWnd::OnCreate(lpCreateStruct) == -1)
	  return -1;

  CRect rc(0, 0, 0, 0);

  // Get the edit control styles and create the edit control
  // we want to isolate the edit styles from the style, and
  // visible and disabled if specified
  // then add in WS_CHILD
  DWORD dwStyleEdit = lpCreateStruct->style & (WS_VISIBLE | WS_DISABLED | 0x3DFFL);
  dwStyleEdit |= WS_CHILD | WS_CLIPSIBLINGS;
  if (!m_pEdit->Create(dwStyleEdit, rc, this, ID_EDIT))
    return -1;

  // Get the button styles and create the button
  // just allow visible and disabled from the specified style
  // and add WS_CHILD and BS_PUSHBUTTON
  DWORD dwStyleBtn = lpCreateStruct->style & (WS_VISIBLE | WS_DISABLED);
  dwStyleBtn |= WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON;
  if (!m_pBtn->Create("...", dwStyleBtn, rc, this, ID_BUTTON))
    return -1;
  
  // if the edit control is readonly, disable the button
  if (dwStyleEdit & ES_READONLY)
    m_pBtn->EnableWindow(FALSE);

  return 0;
}

void CBrowseEdit::OnEnable(BOOL bEnable) 
{
  CWnd::OnEnable(bEnable);

  m_pEdit->EnableWindow(bEnable);
  m_pBtn->EnableWindow(bEnable);
}

void CBrowseEdit::OnSetFocus(CWnd* pOldWnd) 
{
  CWnd::OnSetFocus(pOldWnd);

  // set the focus to the edit control
  m_pEdit->SetFocus();
  m_pEdit->SetSel(0, -1);
}

void CBrowseEdit::OnSize(UINT nType, int cx, int cy) 
{
  CWnd::OnSize(nType, cx, cy);

  // size the child controls
  m_pEdit->MoveWindow(0, 0, cx - cy, cy);
  m_pBtn->MoveWindow(cx - cy, 0, cy, cy);
}

BOOL CBrowseEdit::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
  // pass the notifications from the controls to the parent
  CWnd* pParent = GetParent();
  if (pParent != NULL)
  {
    NMHDR* pnmhdr = (NMHDR*)lParam;
    pnmhdr->idFrom = GetDlgCtrlID();
    pnmhdr->hwndFrom = GetSafeHwnd();
    *pResult = pParent->SendMessage(WM_NOTIFY, (WPARAM)GetDlgCtrlID(), lParam);
    return TRUE;
  }
  return CWnd::OnNotify(wParam, lParam, pResult);
}

BOOL CBrowseEdit::OnCommand(WPARAM wParam, LPARAM lParam) 
{
  // pass the commands from the controls to the parent
  CWnd* pParent = GetParent();
  if (pParent != NULL)
  {
    if (!pParent->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), HIWORD(wParam)), (LPARAM)GetSafeHwnd()))
      return TRUE;
  }
  return CWnd::OnCommand(wParam, lParam);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
Originally from an electronics background, I moved into software in 1996, partly as a result of being made redundant, and partly because I was very much enjoying the small amount of coding (in-at-the-deep-end-C) that I had been doing!

I swiftly moved from C to C++, and learned MFC, and then went on to real-time C on Unix. After this I moved to the company for which I currently work, which specialises in Configuration Management software, and currently program mainly in C/C++, for Windows. I have been gradually moving their legacy C code over to use C++ (with STL, MFC, ATL, and WTL). I have pulled in other technologies (Java, C#, VB, COM, SOAP) where appropriate, especially when integrating with third-party products.

In addition to that, I have overseen the technical side of the company website (ASP, VBScript, JavaScript, HTML, CSS), and have also worked closely with colleagues working on other products (Web-based, C#, ASP.NET, SQL, etc).

For developing, I mainly use Visual Studio 2010, along with an in-house-designed editor based on Andrei Stcherbatchenko's syntax parsing classes, and various (mostly freeware) tools. For website design, I use Dreaweaver CS3.

When not developing software, I enjoy listening to and playing music, playing electric and acoustic guitars and mandolin.

Comments and Discussions