/* Edit With Button This class acts mostly like a normal Edit Box except that it provides a button to the right side of the control. Clicking the button invokes the virutal OnLeftClick method. If that has not been overridden in a derived classes then it sends the EDIT_BUTTON_LEFTCLICKED message to the parent window. CEditWithButton_Base contains most of the code to make this work but cannot be instantiated itself. A derived class must override DrawButtonContent and CalculateButtonWidth to determine what is actually drawn for the button. CEditWithButton is a derived class that handles the simplest form of a button where a plain text string is displayed on the button. Other classes could be derived to draw other kinds of buttons. */ #pragma once #include #include "UxTheme.h" // May be sent to the parent window when the edit control's button is clicked. // wParam will be set to the ID of the control that sent the message. #define EDIT_BUTTON_LEFTCLICKED (WM_APP + 842) // arbitrary number, change if necessary // CEditWithButton_Base --------------------------------------------------------------------------- // This is the base class from which others derive to implement specific kinds of buttons. class CEditWithButton_Base : public CEdit { public: CEditWithButton_Base(); // Called when a left click is detected. The default implementation will send a // EDIT_BUTTON_LEFTCLICKED message to the parent window. Derived classes // could override this to handle the event themselves, and so are not required // to call this base implementation. virtual void OnLeftClick(); protected: afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp); afx_msg void OnNcPaint(); afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point); afx_msg void OnNcMouseLeave(); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg LRESULT OnNcHitTest(CPoint point); virtual void PreSubclassWindow(); afx_msg LRESULT OnRecalcNcSize(WPARAM wParam, LPARAM lParam); afx_msg void OnEnable(BOOL bEnable); afx_msg LRESULT OnSetReadOnly(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() // Given the rectangle of the control window, this returns the rect that the button will occupy. CRect GetButtonRect(const CRect& rectWindow) const; // Translates the current button state in a value that could be used by DrawThemeBackground. int GetButtonThemeState() const; // Called when the button needs to be drawn. // The default implementation draws the button frame, adjusts the rect if // the button is pressed, and then calls DrawButtonContent to render the // contents of the button. virtual void DrawButton(CRect rectButton); // Called when the button contents (anything inside the button's border) needs to // be drawn. The rect will have already been adjusted if the button is pressed. // The content must be drawn using the given device context within the given rect. virtual void DrawButtonContent(CDC& dc, CRect rectButton, HTHEME hButtonTheme) = 0; // Called when the button's width needs to be (re)calculated. // This must return the width in pixels. virtual int CalculateButtonWidth() = 0; private: int m_TopBorder; int m_BottomBorder; int m_LeftBorder; int m_RightBorder; int m_ButtonWidth; // stores the button's width in pixels (so that we don't have to re-calculate it) bool m_IsButtonPressed; bool m_IsMouseActive; bool m_IsButtonHot; }; // CEditWithButton -------------------------------------------------------------------------------- // This implements a button containing plain text. class CEditWithButton : public CEditWithButton_Base { public: // The given text will be displayed in the button. explicit CEditWithButton(LPCTSTR pszButtonText = _T("...")); // Gets/Sets the button text. CString GetButtonText() const; void SetButtonText(LPCTSTR buttonText); private: virtual void DrawButtonContent(CDC& dc, CRect rectButton, HTHEME hButtonTheme); virtual int CalculateButtonWidth(); CString m_ButtonText; };