Something like this:
NativeEditField.h:
#ifndef __JUCE_NATIVEEDITFIELD_JUCEHEADER__
#define __JUCE_NATIVEEDITFIELD_JUCEHEADER__
#include "../juce_Component.h"
class NativeEditFieldImpl;
class NativeEditField;
class INativeEditFieldCallback
{
public:
virtual ~INativeEditFieldCallback() {}
virtual void INativeEditFieldCallback_changed(NativeEditField& editField) = 0;
virtual void INativeEditFieldCallback_gotFocus(NativeEditField& editField) = 0;
virtual void INativeEditFieldCallback_lostFocus(NativeEditField& editField) = 0;
};
class JUCE_API NativeEditField : public Component
{
public:
NativeEditField();
virtual ~NativeEditField();
void resized();
void moved();
String getText();
void setText(const String& newText);
void setColours(const Colour& bgColor, const Colour& txtColor);
void addListener(INativeEditFieldCallback * listener);
void removeListener(INativeEditFieldCallback * listener);
void selectText(const int start, const int end);
private:
void internalGotFocus();
void internalLostFocus();
void internalChanged();
NativeEditFieldImpl * m_impl;
NativeEditFieldImpl * getImpl();
Colour m_bgColor;
Colour m_txtColor;
Array<INativeEditFieldCallback*> m_listeners;
friend class NativeEditFieldImpl;
};
#endif // __JUCE_NATIVEEDITFIELD_JUCEHEADER__
NativeEditField.cpp:
class NativeEditFieldImpl
{
public:
NativeEditFieldImpl(NativeEditField& owner) : m_owner(owner), m_bgBrush(0), m_edit(0), m_msgWnd(0)
{
}
~NativeEditFieldImpl()
{
if (m_edit)
{
DestroyWindow(m_edit);
m_edit = 0;
}
if (m_msgWnd)
{
DestroyWindow(m_msgWnd);
m_msgWnd = 0;
}
if (m_bgBrush)
{
DeleteObject(m_bgBrush);
m_bgBrush = 0;
}
}
void setColours(const Colour& bgColor, const Colour& txtColor)
{
if (m_bgBrush)
{
DeleteObject(m_bgBrush);
}
m_bgColor = RGB(bgColor.getRed(), bgColor.getGreen(), bgColor.getBlue());
m_bgBrush = CreateSolidBrush(m_bgColor);
m_textColor = RGB(txtColor.getRed(), txtColor.getGreen(), txtColor.getBlue());
}
Rectangle getMyBounds()
{
Rectangle bounds = m_owner.getBounds();
int x = 0, y = 0;
m_owner.relativePositionToOtherComponent(m_owner.getTopLevelComponent(), x, y);
bounds.setPosition(x, y);
return bounds;
}
void create()
{
if (m_edit == 0 && m_msgWnd == 0 && m_owner.getPeer() != 0)
{
const Rectangle& bounds = getMyBounds();
HWND hwnd = (HWND) m_owner.getPeer()->getNativeHandle();
m_msgWnd = CreateWindow(JUCE_T("STATIC"), NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,
bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), hwnd, NULL, NULL, NULL);
assert(m_msgWnd != 0);
SetWindowLongPtr(m_msgWnd, GWL_WNDPROC, (LONG) NativeEditFieldImpl::wndProc);
m_edit = CreateWindow(JUCE_T("EDIT"), NULL, WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,
0, 0, bounds.getWidth(), bounds.getHeight(), m_msgWnd, NULL, NULL, NULL);
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(m_edit, WM_SETFONT, (WPARAM)hFont, NULL);
setText(m_initial);
// Set this last
SetWindowLongPtr(m_msgWnd, GWL_USERDATA, (LONG) this);
}
}
void resized()
{
if (m_msgWnd)
{
const Rectangle& bounds = getMyBounds();
SetWindowPos(m_msgWnd, NULL, 0, 0, bounds.getWidth(), bounds.getHeight(), SWP_NOZORDER|SWP_NOMOVE);
}
}
void moved()
{
if (m_msgWnd)
{
const Rectangle& bounds = getMyBounds();
SetWindowPos(m_msgWnd, NULL, bounds.getX(), bounds.getY(), 0, 0, SWP_NOZORDER|SWP_NOSIZE);
}
}
String getText() const
{
if (m_edit != 0)
{
WCHAR buffer[512];
GetWindowText(m_edit, buffer, 512);
return buffer;
}
return m_initial;
}
void setText(const String& newText)
{
if (m_edit != 0)
{
SetWindowText(m_edit, newText);
}
else
{
m_initial = newText;
}
}
void selectText(const int start, const int end)
{
if (m_edit)
{
SendMessage(m_edit, EM_SETSEL, start, end);
}
}
static LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CTLCOLOREDIT:
{
NativeEditFieldImpl *ptr = (NativeEditFieldImpl*)GetWindowLongPtr(hwnd, GWL_USERDATA);
if (ptr != 0)
{
HDC hdc = (HDC)wParam;
// Set the text background color.
SetBkColor(hdc, ptr->m_bgColor);
// Set the text foreground color.
SetTextColor(hdc, ptr->m_textColor);
// Return the control background brush.
return (LRESULT)ptr->m_bgBrush;
}
}
break;
case WM_COMMAND:
{
NativeEditFieldImpl* ptr = (NativeEditFieldImpl*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (ptr != 0)
{
unsigned notificationCode = HIWORD(wParam);
switch(notificationCode)
{
case EN_SETFOCUS:
ptr->m_owner.internalGotFocus();
break;
case EN_CHANGE:
ptr->m_owner.internalChanged();
break;
case EN_KILLFOCUS:
ptr->m_owner.internalLostFocus();
break;
}
}
}
break;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
private:
HWND m_edit;
HWND m_msgWnd;
HBRUSH m_bgBrush;
COLORREF m_textColor;
COLORREF m_bgColor;
String m_initial;
NativeEditField& m_owner;
friend NativeEditField;
};
NativeEditField::NativeEditField()
: m_impl(0)
{
}
NativeEditField::~NativeEditField()
{
if (m_impl != 0)
{
delete m_impl;
m_impl = 0;
}
}
void NativeEditField::setColours(const Colour& bgColor, const Colour& txtColor)
{
getImpl()->setColours(bgColor, txtColor);
}
void NativeEditField::resized()
{
getImpl()->resized();
}
void NativeEditField::moved()
{
getImpl()->moved();
}
String NativeEditField::getText()
{
return getImpl()->getText();
}
void NativeEditField::setText(const String& newText)
{
getImpl()->setText(newText);
}
void NativeEditField::selectText(const int start, const int end)
{
getImpl()->selectText(start, end);
}
void NativeEditField::addListener(INativeEditFieldCallback * listener)
{
m_listeners.addIfNotAlreadyThere(listener);
}
void NativeEditField::removeListener(INativeEditFieldCallback * listener)
{
m_listeners.removeValue(listener);
}
void NativeEditField::internalGotFocus()
{
for (unsigned i = 0; i < m_listeners.size(); ++i)
{
INativeEditFieldCallback * cb = m_listeners[i];
cb->INativeEditFieldCallback_gotFocus(*this);
}
}
void NativeEditField::internalLostFocus()
{
for (unsigned i = 0; i < m_listeners.size(); ++i)
{
INativeEditFieldCallback * cb = m_listeners[i];
cb->INativeEditFieldCallback_lostFocus(*this);
}
}
void NativeEditField::internalChanged()
{
for (unsigned i = 0; i < m_listeners.size(); ++i)
{
INativeEditFieldCallback * cb = m_listeners[i];
cb->INativeEditFieldCallback_changed(*this);
}
}
NativeEditFieldImpl * NativeEditField::getImpl()
{
assert(getParentComponent() != 0);
if (m_impl == 0)
{
m_impl = new NativeEditFieldImpl(*this);
m_impl->create();
}
return m_impl;
}