New native control helpers. Built but not run by anyone just yet. See design doc

http://dev.chromium.org/developers/design-documents/native-controls

Review URL: http://codereview.chromium.org/48094

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12008 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/views/controls/button/native_button_win.cc b/chrome/views/controls/button/native_button_win.cc
new file mode 100644
index 0000000..35472cd0
--- /dev/null
+++ b/chrome/views/controls/button/native_button_win.cc
@@ -0,0 +1,264 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#include "chrome/views/controls/button/native_button_win.h"
+
+#include "chrome/common/l10n_util.h"
+#include "chrome/views/widget/widget.h"
+
+namespace views {
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeButtonWin, public:
+
+NativeButtonWin::NativeButtonWin(NativeButtonWrapperListener* listener)
+    : NativeControlWin(),
+      listener_(listener),
+      is_default_(false),
+      ignore_minimum_size_(false),
+      min_dlu_size_(50, 14) {
+  // The min size in DLUs comes from
+  // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwue/html/ch14e.asp
+}
+
+NativeButtonWin::~NativeButtonWin() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeButtonWin, NativeButtonWrapper implementation:
+
+void NativeButtonWin::SetLabel(const std::wstring& label) {
+  label_ = label;
+
+  // Even though we create a flipped HWND for a native button when the locale
+  // is right-to-left, Windows does not render text for the button using a
+  // right-to-left context (perhaps because the parent HWND is not flipped).
+  // The result is that RTL strings containing punctuation marks are not
+  // displayed properly. For example, the string "...ABC" (where A, B and C are
+  // Hebrew characters) is displayed as "ABC..." which is incorrect.
+  //
+  // In order to overcome this problem, we mark the localized Hebrew strings as
+  // RTL strings explicitly (using the appropriate Unicode formatting) so that
+  // Windows displays the text correctly regardless of the HWND hierarchy.
+  std::wstring localized_label;
+  if (l10n_util::AdjustStringForLocaleDirection(label_, &localized_label))
+    label_ = localized_label;
+
+  // SetLabel can be called before the view is attached to a view hierarchy, so
+  // we check the HWND before attempting to do anything with it.
+  if (IsWindow(GetHWND()))
+    SetWindowText(GetHWND(), label_.c_str());
+}
+
+std::wstring NativeButtonWin::GetLabel() const {
+  return label_;
+}
+
+void NativeButtonWin::SetFont(const ChromeFont& font) {
+  font_ = font;
+}
+
+void NativeButtonWin::SetDefaultButton(bool is_default) {
+  if (is_default == is_default_)
+    return;
+  is_default_ = is_default;
+
+  // SetDefaultButton can be called before the view is attached to a view
+  // hierarchy, so we check the HWND before attempting to modify its style.
+  if (IsWindow(GetHWND())) {
+    SendMessage(GetHWND(), BM_SETSTYLE,
+                is_default_ ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON, true);
+  }
+}
+
+bool NativeButtonWin::IsDefaultButton() const {
+  return is_default_;
+}
+
+void NativeButtonWin::SetMinimumSizeInPlatformUnits(
+    const gfx::Size& minimum_size) {
+  min_dlu_size_ = minimum_size;
+}
+
+void NativeButtonWin::SetIgnoreMinimumSize(bool ignore_minimum_size) {
+  ignore_minimum_size_ = ignore_minimum_size;
+}
+
+View* NativeButtonWin::GetView() {
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeButtonWin, View overrides:
+
+gfx::Size NativeButtonWin::GetPreferredSize() {
+  if (!GetHWND())
+    return gfx::Size();
+
+  SIZE sz = {0};
+  SendMessage(GetHWND(), BCM_GETIDEALSIZE, 0, reinterpret_cast<LPARAM>(&sz));
+
+  if (!ignore_minimum_size_) {
+    if (min_dlu_size_.width()) {
+      sz.cx = std::max(static_cast<int>(sz.cx),
+                       font_.horizontal_dlus_to_pixels(min_dlu_size_.width()));
+    }
+    if (min_dlu_size_.height()) {
+      sz.cy = std::max(static_cast<int>(sz.cy),
+                       font_.vertical_dlus_to_pixels(min_dlu_size_.height()));
+    }
+  }
+  return gfx::Size(sz.cx, sz.cy);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeButtonWin, NativeControlWin overrides:
+
+LRESULT NativeButtonWin::ProcessMessage(UINT message,
+                                        WPARAM w_param,
+                                        LPARAM l_param) {
+  if (message == WM_COMMAND && HIWORD(w_param) == BN_CLICKED) {
+    listener_->ButtonPressed();
+    return 0;
+  }
+  return NativeControlWin::ProcessMessage(message, w_param, l_param);
+}
+
+bool NativeButtonWin::OnKeyDown(int vkey) {
+  bool enter_pressed = vkey == VK_RETURN;
+  if (enter_pressed)
+    listener_->ButtonPressed();
+  return enter_pressed;
+}
+
+bool NativeButtonWin::NotifyOnKeyDown() const {
+  return true;
+}
+
+void NativeButtonWin::CreateNativeControl() {
+  DWORD flags = WS_CHILD | BS_PUSHBUTTON;
+  if (is_default_)
+    flags |= BS_DEFPUSHBUTTON;
+  HWND control_hwnd = CreateWindowEx(GetAdditionalExStyle(), L"BUTTON", L"",
+                                     flags, 0, 0, width(), height(),
+                                     GetWidget()->GetNativeView(), NULL, NULL,
+                                     NULL);
+  NativeControlCreated(control_hwnd);
+}
+
+void NativeButtonWin::NativeControlCreated(HWND control_hwnd) {
+  NativeControlWin::NativeControlCreated(control_hwnd);
+
+  SendMessage(control_hwnd, WM_SETFONT, reinterpret_cast<WPARAM>(font_.hfont()),
+              FALSE);
+  SetLabel(GetLabel());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeCheckboxWin, public:
+
+NativeCheckboxWin::NativeCheckboxWin(NativeButtonWrapperListener* listener)
+    : NativeButtonWin(listener),
+      selected_(false) {
+}
+
+NativeCheckboxWin::~NativeCheckboxWin() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeCheckboxWin, NativeButtonWrapper implementation:
+
+void NativeCheckboxWin::SetSelected(bool selected) {
+  if (selected == selected_)
+    return;
+
+  selected_ = selected;
+  if (GetHWND()) {
+    SendMessage(GetHWND(), BM_SETCHECK, selected ? BST_CHECKED : BST_UNCHECKED,
+                0);
+  }
+}
+
+bool NativeCheckboxWin::IsSelected() const {
+  return selected_;
+}
+
+void NativeCheckboxWin::SetHighlight(bool highlight) {
+  SendMessage(GetHWND(), BM_SETSTATE, highlight, 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeCheckboxWin, NativeButtonWin overrides:
+
+LRESULT NativeCheckboxWin::ProcessMessage(UINT message,
+                                          WPARAM w_param,
+                                          LPARAM l_param) {
+  if (message == WM_COMMAND && HIWORD(w_param) == BN_CLICKED) {
+    SetSelected(!IsSelected());
+    // Fall through to the NativeButtonWin's handler, which will send the
+    // clicked notification to the listener...
+  }
+  return NativeButtonWin::ProcessMessage(message, w_param, l_param);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeCheckboxWin, protected:
+
+void NativeCheckboxWin::CreateNativeControl() {
+  HWND control_hwnd = CreateWindowEx(WS_EX_TRANSPARENT | GetAdditionalExStyle(),
+                                     L"BUTTON", L"",
+                                     WS_CHILD | BS_CHECKBOX | WS_VISIBLE,
+                                     0, 0, width(), height(),
+                                     GetWidget()->GetNativeView(), NULL, NULL,
+                                     NULL);
+  NativeControlCreated(control_hwnd);
+}
+
+void NativeCheckboxWin::NativeControlCreated(HWND control_hwnd) {
+  NativeButtonWin::NativeControlCreated(control_hwnd);
+  SetSelected(IsSelected());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeRadioButtonWin, public:
+
+NativeRadioButtonWin::NativeRadioButtonWin(
+    NativeButtonWrapperListener* listener)
+    : NativeCheckboxWin(listener) {
+}
+
+NativeRadioButtonWin::~NativeRadioButtonWin() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeRaidoButotnWin, NativeCheckboxWin overrides:
+
+void NativeRadioButtonWin::CreateNativeControl() {
+  HWND control_hwnd = CreateWindowEx(GetAdditionalExStyle(), L"BUTTON",
+                                     L"", WS_CHILD | BS_RADIOBUTTON,
+                                     0, 0, width(), height(),
+                                     GetWidget()->GetNativeView(), NULL, NULL,
+                                     NULL);
+  NativeControlCreated(control_hwnd);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeButtonWrapper, public:
+
+// static
+NativeButtonWrapper* NativeButtonWrapper::CreateNativeButtonWrapper(
+    NativeButtonWrapperListener* listener, Type type) {
+  switch (type) {
+    case TYPE_BUTTON:
+      return new NativeButtonWin(listener);
+    case TYPE_CHECKBOX:
+      return new NativeCheckboxWin(listener);
+    case TYPE_RADIOBUTTON:
+      return new NativeRadioButtonWin(listener);
+  }
+  NOTREACHED() << "Invalid button type!";
+  return NULL;
+}
+
+}  // namespace views
diff --git a/chrome/views/controls/button/native_button_win.h b/chrome/views/controls/button/native_button_win.h
new file mode 100644
index 0000000..b7115373
--- /dev/null
+++ b/chrome/views/controls/button/native_button_win.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#ifndef CHROME_VIEWS_CONTROLS_BUTTON_NATIVE_BUTTON_WIN_H_
+#define CHROME_VIEWS_CONTROLS_BUTTON_NATIVE_BUTTON_WIN_H_
+
+#include "chrome/common/gfx/chrome_font.h"
+#include "chrome/views/controls/native_control_win.h"
+#include "chrome/views/controls/button/native_button_wrapper.h"
+
+namespace views {
+
+// A View that hosts a native Windows button.
+class NativeButtonWin : public NativeControlWin,
+                        public NativeButtonWrapper {
+ public:
+  explicit NativeButtonWin(NativeButtonWrapperListener* listener);
+  virtual ~NativeButtonWin();
+
+  // Overridden from NativeButtonWrapper:
+  virtual void SetLabel(const std::wstring& label);
+  virtual std::wstring GetLabel() const;
+  virtual void SetFont(const ChromeFont& font);
+  virtual void SetDefaultButton(bool is_default);
+  virtual bool IsDefaultButton() const;
+  virtual void SetMinimumSizeInPlatformUnits(const gfx::Size& minimum_size);
+  virtual void SetIgnoreMinimumSize(bool ignore_minimum_size);
+  virtual View* GetView();
+
+  // Overridden from View:
+  virtual gfx::Size GetPreferredSize();
+
+  // Overridden from NativeControlWin:
+  virtual LRESULT ProcessMessage(UINT message,
+                                 WPARAM w_param,
+                                 LPARAM l_param);
+  virtual bool OnKeyDown(int vkey);
+
+ protected:
+  virtual bool NotifyOnKeyDown() const;
+  virtual void CreateNativeControl();
+  virtual void NativeControlCreated(HWND control_hwnd);
+
+ private:
+  // Our listener.
+  NativeButtonWrapperListener* listener_;
+
+  // The button label.
+  std::wstring label_;
+
+  // True if the button is the default button in its context.
+  bool is_default_;
+
+  // The font used to render the button label.
+  ChromeFont font_;
+
+  // True if the button should ignore the minimum size for the platform. Default
+  // is false.
+  bool ignore_minimum_size_;
+
+  // Minimum size, in dlus (see SetMinimumSizeInPlatformUnits).
+  gfx::Size min_dlu_size_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeButtonWin);
+};
+
+// A View that hosts a native Windows checkbox.
+class NativeCheckboxWin : public NativeButtonWin {
+ public:
+  explicit NativeCheckboxWin(NativeButtonWrapperListener* listener);
+  virtual ~NativeCheckboxWin();
+
+  // Overridden from NativeButtonWrapper:
+  virtual void SetSelected(bool selected);
+  virtual bool IsSelected() const;
+  virtual void SetHighlight(bool highlight);
+
+  // Overridden from NativeControlWin:
+  virtual LRESULT ProcessMessage(UINT message,
+                                 WPARAM w_param,
+                                 LPARAM l_param);
+
+ protected:
+  virtual void CreateNativeControl();
+  virtual void NativeControlCreated(HWND control_hwnd);
+
+ private:
+  // True if this checkbox is checked.
+  bool selected_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeCheckboxWin);
+};
+
+// A View that hosts a native Windows radio button.
+class NativeRadioButtonWin : public NativeCheckboxWin {
+ public:
+  explicit NativeRadioButtonWin(NativeButtonWrapperListener* listener);
+  virtual ~NativeRadioButtonWin();
+
+ protected:
+  // Overridden from NativeCheckboxWin:
+  virtual void CreateNativeControl();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NativeRadioButtonWin);
+};
+  
+}  // namespace views
+
+#endif  // #ifndef CHROME_VIEWS_CONTROLS_BUTTON_NATIVE_BUTTON_WIN_H_
diff --git a/chrome/views/controls/button/native_button_wrapper.h b/chrome/views/controls/button/native_button_wrapper.h
new file mode 100644
index 0000000..f530b83
--- /dev/null
+++ b/chrome/views/controls/button/native_button_wrapper.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#ifndef CHROME_VIEWS_CONTROLS_BUTTON_NATIVE_BUTTON_WRAPPER_H_
+#define CHROME_VIEWS_CONTROLS_BUTTON_NATIVE_BUTTON_WRAPPER_H_
+
+class ChromeFont;
+
+namespace views {
+
+// An interface implemented by the view that owns the NativeButtonWrapper that
+// allows it to be notified when the button is pressed.
+class NativeButtonWrapperListener {
+ public:
+  virtual void ButtonPressed() = 0;
+};
+
+// A specialization of NativeControlWrapper that hosts a platform-native button.
+class NativeButtonWrapper {
+ public:
+  // Sets/Gets the button's label.
+  virtual void SetLabel(const std::wstring& label) = 0;
+  virtual std::wstring GetLabel() const = 0;
+
+  // Sets the font used by this button.
+  virtual void SetFont(const ChromeFont& font) = 0;
+
+  // Sets whether or not the button should have the default appearance and
+  // action in its setting.
+  virtual void SetDefaultButton(bool is_default) = 0;
+  virtual bool IsDefaultButton() const = 0;
+
+  // Sets the minimum size of the button from the specified size in native
+  // dialog units. The definition of this unit may vary from platform to
+  // platform. If the width/height is non-zero, the preferred size of the button
+  // will not be less than this value when the dialog units are converted to
+  // pixels.
+  virtual void SetMinimumSizeInPlatformUnits(const gfx::Size& minimum_size) = 0;
+
+  // Call to have the button ignore its minimum size. Use this if you want
+  // buttons narrower than the defined minimum size.
+  virtual void SetIgnoreMinimumSize(bool ignore_minimum_size) = 0;
+
+  // Sets/Gets the selected state of button. Valid only for checkboxes and radio
+  // buttons.
+  virtual void SetSelected(bool is_selected) {}
+  virtual bool IsSelected(bool is_selected) { return false; }
+
+  // Shows the hover state for the button if |highlight| is true.
+  virtual void SetHighlight(bool highlight) {};
+
+  // Retrieves the views::View that hosts the native control. 
+  virtual View* GetView() = 0;
+
+  enum Type {
+    TYPE_BUTTON,
+    TYPE_CHECKBOX,
+    TYPE_RADIOBUTTON
+  };
+
+  // Creates an appropriate NativeButtonWrapper for the platform.
+  static NativeButtonWrapper* CreateNativeButtonWrapper(
+      NativeButtonWrapperListener* listener, Type type);
+};
+
+}  // namespace views
+
+#endif  // #ifndef CHROME_VIEWS_CONTROLS_BUTTON_NATIVE_BUTTON_WRAPPER_H_
diff --git a/chrome/views/controls/native_control_win.cc b/chrome/views/controls/native_control_win.cc
new file mode 100644
index 0000000..f60b93ccb
--- /dev/null
+++ b/chrome/views/controls/native_control_win.cc
@@ -0,0 +1,175 @@
+// #ifndef CHROME_VIEWS_NATIVE_CONTROL_WIN_H_// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#include "chrome/views/controls/native_control_win.h"
+
+#include "base/logging.h"
+#include "base/win_util.h"
+#include "chrome/common/l10n_util_win.h"
+
+namespace views {
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeControlWin, public:
+
+// static
+const wchar_t* NativeControlWin::kNativeControlWinKey =
+    L"__NATIVE_CONTROL_WIN__";
+
+NativeControlWin::NativeControlWin() : HWNDView() {
+}
+
+NativeControlWin::~NativeControlWin() {
+}
+
+LRESULT NativeControlWin::ProcessMessage(UINT message, WPARAM w_param,
+                                         LPARAM l_param) {
+  switch (message) {
+    case WM_CONTEXTMENU:
+      ShowContextMenu(gfx::Point(LOWORD(l_param), HIWORD(l_param)));
+      break;
+    case WM_CTLCOLORBTN:
+    case WM_CTLCOLORSTATIC:
+      return GetControlColor(message, reinterpret_cast<HDC>(w_param),
+                             GetHWND());
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeControlWin, View overrides:
+
+void NativeControlWin::SetEnabled(bool enabled) {
+  if (IsEnabled() != enabled) {
+    View::SetEnabled(enabled);
+    if (GetHWND())
+      EnableWindow(GetHWND(), IsEnabled());
+  }
+}
+
+void NativeControlWin::ViewHierarchyChanged(bool is_add, View* parent,
+                                            View* child) {
+  // Create the HWND when we're added to a valid Widget. Many controls need a
+  // parent HWND to function properly.
+  if (is_add && GetWidget() && !GetHWND())
+    CreateNativeControl();
+}
+
+void NativeControlWin::VisibilityChanged(View* starting_from, bool is_visible) {
+  if (!is_visible) {
+    // We destroy the child control HWND when we become invisible because of the
+    // performance cost of maintaining many HWNDs.
+    HWND hwnd = GetHWND();
+    Detach();
+    DestroyWindow(hwnd);
+  } else if (!GetHWND()) {
+    CreateNativeControl();
+  }
+}
+
+void NativeControlWin::Focus() {
+  DCHECK(GetHWND());
+  SetFocus(GetHWND());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeControlWin, protected:
+
+void NativeControlWin::ShowContextMenu(const gfx::Point& location) {
+  if (!GetContextMenuController())
+    return;
+
+  int x = location.x();
+  int y = location.y();
+  bool is_mouse = true;
+  if (x == -1 && y == -1) {
+    gfx::Point point = GetKeyboardContextMenuLocation();
+    x = point.x();
+    y = point.y();
+    is_mouse = false;
+  }
+  View::ShowContextMenu(x, y, is_mouse);
+}
+
+void NativeControlWin::NativeControlCreated(HWND native_control) {
+  // Associate this object with the control's HWND so that WidgetWin can find
+  // this object when it receives messages from it.
+  SetProp(native_control, kNativeControlWinKey, this);
+
+  Attach(native_control);
+  // GetHWND() is now valid.
+
+  // Subclass the window so we can monitor for key presses.
+  win_util::Subclass(GetHWND(), &NativeControlWin::NativeControlWndProc);
+
+  // Update the newly created HWND with any resident enabled state.
+  EnableWindow(GetHWND(), IsEnabled());
+
+  // This message ensures that the focus border is shown.
+  SendMessage(GetHWND(), WM_CHANGEUISTATE,
+              MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
+}
+
+DWORD NativeControlWin::GetAdditionalExStyle() const {
+  // If the UI for the view is mirrored, we should make sure we add the
+  // extended window style for a right-to-left layout so the subclass creates
+  // a mirrored HWND for the underlying control.
+  DWORD ex_style = 0;
+  if (UILayoutIsRightToLeft())
+    ex_style |= l10n_util::GetExtendedStyles();
+
+  return ex_style;
+}
+
+DWORD NativeControlWin::GetAdditionalRTLStyle() const {
+  // If the UI for the view is mirrored, we should make sure we add the
+  // extended window style for a right-to-left layout so the subclass creates
+  // a mirrored HWND for the underlying control.
+  DWORD ex_style = 0;
+  if (UILayoutIsRightToLeft())
+    ex_style |= l10n_util::GetExtendedTooltipStyles();
+
+  return ex_style;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeControlWin, private:
+
+LRESULT NativeControlWin::GetControlColor(UINT message, HDC dc, HWND sender) {
+  View *ancestor = this;
+  while (ancestor) {
+    const Background* background = ancestor->background();
+    if (background) {
+      HBRUSH brush = background->GetNativeControlBrush();
+      if (brush)
+        return reinterpret_cast<LRESULT>(brush);
+    }
+    ancestor = ancestor->GetParent();
+  }
+
+  // COLOR_BTNFACE is the default for dialog box backgrounds.
+  return reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_BTNFACE));
+}
+
+// static
+LRESULT NativeControlWin::NativeControlWndProc(HWND window,
+                                               UINT message,
+                                               WPARAM w_param,
+                                               LPARAM l_param) {
+  NativeControlWin* native_control =
+      static_cast<NativeControlWin*>(GetProp(window, kNativeControlWinKey));
+  DCHECK(native_control);
+
+  if (message == WM_KEYDOWN && native_control->NotifyOnKeyDown()) {
+    if (native_control->OnKeyDown(static_cast<int>(w_param)))
+      return 0;
+  } else if (message == WM_DESTROY) {
+    win_util::Unsubclass(window, &NativeControlWin::NativeControlWndProc);
+    TRACK_HWND_DESTRUCTION(window);
+  }
+
+  return DefWindowProc(window, message, w_param, l_param);
+}
+
+}  // namespace views
diff --git a/chrome/views/controls/native_control_win.h b/chrome/views/controls/native_control_win.h
new file mode 100644
index 0000000..c2ecb41
--- /dev/null
+++ b/chrome/views/controls/native_control_win.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#ifndef CHROME_VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_
+#define CHROME_VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_
+
+#include "chrome/views/controls/hwnd_view.h"
+
+namespace views {
+
+// A View that hosts a native Windows control.
+class NativeControlWin : public HWNDView {
+ public:
+  static const wchar_t* kNativeControlWinKey;
+
+  NativeControlWin();
+  virtual ~NativeControlWin();
+
+  // Called by the containing WidgetWin when a message is received from the HWND
+  // created by an object derived from NativeControlWin. Derived classes MUST
+  // call _this_ version of the function if they override it and do not handle
+  // all of the messages listed in widget_win.cc ProcessNativeControlWinMessage.
+  virtual LRESULT ProcessMessage(UINT message,
+                                 WPARAM w_param,
+                                 LPARAM l_param);
+
+  // Called by our subclassed window procedure when a WM_KEYDOWN message is
+  // received by the HWND created by an object derived from NativeControlWin.
+  // Returns true if the key was processed, false otherwise.
+  virtual bool OnKeyDown(int vkey) { return false; }
+
+  // Overridden from View:
+  virtual void SetEnabled(bool enabled);
+
+ protected:
+  virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
+  virtual void VisibilityChanged(View* starting_from, bool is_visible);
+  virtual void Focus();
+
+  // Called by the containing WidgetWin when a WM_CONTEXTMENU message is
+  // received from the HWND created by an object derived from NativeControlWin.
+  virtual void ShowContextMenu(const gfx::Point& location);
+
+  // Derived classes interested in receiving key down notification should
+  // override this method and return true.  In which case OnKeyDown is called
+  // when a key down message is sent to the control.
+  // Note that this method is called at the time of the control creation: the
+  // behavior will not change if the returned value changes after the control
+  // has been created.
+  virtual bool NotifyOnKeyDown() const { return false; }
+
+  // Called when the NativeControlWin is attached to a View hierarchy with a
+  // valid Widget. The NativeControlWin should use this opportunity to create
+  // its associated HWND.
+  virtual void CreateNativeControl() = 0;
+
+  // MUST be called by the subclass implementation of |CreateNativeControl|
+  // immediately after creating the control HWND, otherwise it won't be attached
+  // to the HWNDView and will be effectively orphaned.
+  virtual void NativeControlCreated(HWND native_control);
+
+  // Returns additional extended style flags. When subclasses call
+  // CreateWindowEx in order to create the underlying control, they must OR the
+  // ExStyle parameter with the value returned by this function.
+  //
+  // We currently use this method in order to add flags such as WS_EX_LAYOUTRTL
+  // to the HWND for views with right-to-left UI layout.
+  DWORD GetAdditionalExStyle() const;
+
+  // TODO(xji): we use the following temporary function as we transition the
+  // various native controls to use the right set of RTL flags. This function
+  // will go away (and be replaced by GetAdditionalExStyle()) once all the
+  // controls are properly transitioned.
+  DWORD GetAdditionalRTLStyle() const;
+
+ private:
+  // Called by the containing WidgetWin when a message of type WM_CTLCOLORBTN or
+  // WM_CTLCOLORSTATIC is sent from the HWND created by an object dreived from
+  // NativeControlWin.
+  LRESULT GetControlColor(UINT message, HDC dc, HWND sender);
+
+  // Our subclass window procedure for the attached control.
+  static LRESULT CALLBACK NativeControlWndProc(HWND window,
+                                               UINT message,
+                                               WPARAM w_param,
+                                               LPARAM l_param);
+
+  DISALLOW_COPY_AND_ASSIGN(NativeControlWin);
+};
+  
+}  // namespace views
+
+#endif  // #ifndef CHROME_VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_