#pragma once
#ifndef __HWINCONTROL_H__
#define __HWINCONTROL_H__
#include "hwindef.h"
#include "hwinmessage.h"
#include "hwinclass.h"
#include "hwinexception.h"
#include "hwincomponent.h"
#include "hwinkeys.h"
#include "hwinobj.h"
#include "hwinhandle.h"
namespace harlinn
{
namespace windows
{
enum class MouseButton : int
{
Left = 0,
Right = 1,
Middle = 2
};
DEFINE_ENUM_FLAG_OPERATORS(MouseButton)
enum class AnchorStyles : int
{
None = 0,
Top = 1,
Bottom = 2,
Left = 4,
Right = 8
};
DEFINE_ENUM_FLAG_OPERATORS(AnchorStyles)
enum class HorizontalAlignment : int
{
Left = 0,
Right = 1,
Center = 2
};
enum class ContentAlignment
{
TopLeft = 1,
TopCenter = 2,
TopRight = 4,
MiddleLeft = 16,
MiddleCenter = 32,
MiddleRight = 64,
BottomLeft = 256,
BottomCenter = 512,
BottomRight = 1024
};
enum class DockStyle
{
// The control is not docked.
None = 0,
// The control's top edge is docked to the top of its containing control.
Top = 1,
// The control's bottom edge is docked to the bottom of its containing control.
Bottom = 2,
// The control's left edge is docked to the left edge of its containing control.
Left = 3,
// The control's right edge is docked to the right edge of its containing control.
Right = 4,
// All the control's edges are docked to the all edges of its containing control
// and sized appropriately.
Fill = 5,
};
class Control;
// --------------------------------------------------------------------
// Controls
// --------------------------------------------------------------------
class Controls
{
friend class Control;
public:
typedef std::vector< std::weak_ptr< Control > > vector;
private:
vector items;
Control* control;
HWIN_EXPORT void DoOnHandleCreated( );
HWIN_EXPORT void DoBeforeHandleDestroy( );
HWIN_EXPORT void Remove(const std::shared_ptr< Control >& theControl);
HWIN_EXPORT void Add(const std::shared_ptr< Control >& theControl);
HWIN_EXPORT void DisconnectParentControl();
public:
HWIN_EXPORT Controls(Control* theControl);
HWIN_EXPORT bool Contains(const std::shared_ptr< const Control >& theChildControl) const;
};
// --------------------------------------------------------------------
// Control
// --------------------------------------------------------------------
class ComControl;
class Control : public virtual Component
{
friend class MessageDispatcherBase;
friend class Controls;
friend class ComControl;
HWND handle;
std::weak_ptr<Control> parentControl;
Point position;
harlinn::windows::Size size;
LONG id;
std::shared_ptr<Controls> controls;
String text;
bool automaticallyAddParentlessOwnedControls;
AnchorStyles anchorStyles;
bool enabled:1;
bool visible:1;
bool tabStop:1;
bool recreatingHandle:1;
DockStyle dock;
WNDPROC originalWindowsProcedure;
protected:
HWIN_EXPORT static UINT REFLECTED_WM_COMMAND;
HWIN_EXPORT static UINT REFLECTED_WM_NOTIFY;
HWIN_EXPORT static UINT REFLECTED_WM_DRAWITEM;
HWIN_EXPORT static UINT WM_GET_CONTROL; //
public:
typedef Component Base;
HWIN_EXPORT Control( );
HWIN_EXPORT virtual ~Control();
protected:
HWIN_EXPORT virtual ComObject* CreateComObject() const;
HWIN_EXPORT virtual void DoOnInitialize( );
HWIN_EXPORT virtual std::shared_ptr<WindowClass> GetWindowClass() const;
HWIN_EXPORT virtual DWORD GetStyle() const;
HWIN_EXPORT virtual DWORD GetStyleEx() const;
HWIN_EXPORT Control& SetWindowStyle(DWORD theStyle);
HWIN_EXPORT Control& SetWindowStyleEx(DWORD theExStyle);
bool IsRecreatingHandle() const { return recreatingHandle; };
HWIN_EXPORT void RecreateHandle();
HWIN_EXPORT virtual void DoOnBeforeRecreatingHandle();
HWIN_EXPORT virtual void DoOnAfterRecreatingHandle();
public:
HWIN_EXPORT bool IsChild() const;
HWIN_EXPORT bool IsToplevel() const;
HWIN_EXPORT bool IsPopup() const;
HWIN_EXPORT bool Enabled() const;
HWIN_EXPORT Control& SetEnabled(bool theValue);
HWIN_EXPORT bool Visible() const;
HWIN_EXPORT Control& SetVisible(bool theValue);
HWIN_EXPORT bool TabStop() const;
HWIN_EXPORT Control& SetTabStop(bool theValue);
protected:
HWIN_EXPORT virtual void DoOnSetEnabled(bool theValue);
public:
HWIN_EXPORT long Id() const;
HWIN_EXPORT Control& SetId(long theValue);
protected:
HWIN_EXPORT virtual HWND CreateHandle( );
HWIN_EXPORT virtual void DoOnHandleCreated( );
HWIN_EXPORT virtual void DestroyHandle( );
HWIN_EXPORT virtual void DoBeforeHandleDestroy( );
private:
HWIN_EXPORT void DisconnectParentControl();
HWIN_EXPORT Control& RestoreSubClassedWindowsProcedure();
static LRESULT CALLBACK SubClassWndProc(HWND hWnd, UINT messageId, WPARAM wParam, LPARAM lParam);
public:
HWIN_EXPORT Control& SubClass(HWND hWnd);
HWIN_EXPORT bool IsSubClassed() const;
protected:
HWIN_EXPORT virtual void DoOnWindowSubClassed( );
public:
HWIN_EXPORT HWND GetSafeHandle() const;
HWIN_EXPORT bool IsHandleCreated() const;
protected:
HWIN_EXPORT virtual void HandleMessage(Message& message);
HWIN_EXPORT static void RegisterControl(HWND hWnd,Control* constrol);
HWIN_EXPORT static void UnregisterControl(HWND hWnd);
HWIN_EXPORT static Control* GetControlFromHWND(HWND hWnd);
public:
HWIN_EXPORT const Control& GetClientRect(RECT* rectangle) const;
HWIN_EXPORT const Control& GetClientRect(RECT& rectangle) const;
HWIN_EXPORT RECT GetClientRect( ) const;
HWIN_EXPORT D2D1_SIZE_F ClientSize() const;
HWIN_EXPORT Control& SetParent(std::shared_ptr<Control> theParentControl);
HWIN_EXPORT std::shared_ptr<Controls> Controls() const;
HWIN_EXPORT std::shared_ptr<Control> Parent() const;
HWIN_EXPORT bool HasParent() const;
HWIN_EXPORT const Control& UpdateRect(RECT& updateRectangle) const;
HWIN_EXPORT Control& UpdateRect(RECT& updateRectangle, bool erase);
HWIN_EXPORT RECT UpdateRect( ) const;
HWIN_EXPORT RECT UpdateRect( bool erase );
//HWIN_EXPORT std::vector< Control* > GetChildren() const;
HWIN_EXPORT bool IsChildOf(std::shared_ptr<const Control> theParentControl) const;
HWIN_EXPORT bool IsChildOf(HWND theParentControl) const;
HWIN_EXPORT bool IsParentOf(std::shared_ptr<const Control> theChildControl) const;
HWIN_EXPORT bool IsParentOf(HWND theChildControl) const;
HWIN_EXPORT bool IsValid() const;
HWIN_EXPORT bool IsVisible() const;
HWIN_EXPORT Control& InvalidateRect(bool erase = false);
HWIN_EXPORT Control& InvalidateRect(const RECT& rectangle,bool erase = false);
HWIN_EXPORT Control& MoveWindow(int x, int y, int width, int height, bool repaint = false);
HWIN_EXPORT LONG SetWindowLong(int index, LONG theNewValue);
HWIN_EXPORT LONG GetWindowLong(int index) const;
HWIN_EXPORT LRESULT SendMessage(UINT Msg, WPARAM wParam = 0, LPARAM lParam = 0) const;
HWIN_EXPORT const Control& PostMessage(UINT Msg, WPARAM wParam = 0, LPARAM lParam = 0) const;
HWIN_EXPORT int TextLength() const;
HWIN_EXPORT String Text() const;
HWIN_EXPORT bool SetText(const String& text);
HWIN_EXPORT bool SetText(const wchar_t* text);
HWIN_EXPORT bool Show();
HWIN_EXPORT bool ValidateRect(const RECT& rectangle);
HWIN_EXPORT bool ValidateRect();
HWIN_EXPORT harlinn::windows::Size Size() const;
HWIN_EXPORT Control& SetSize(int width, int height);
HWIN_EXPORT Control& SetSize(const harlinn::windows::Size& theSize);
HWIN_EXPORT Point Position() const;
HWIN_EXPORT Control& SetPosition(int x, int y);
HWIN_EXPORT Control& SetPosition(const Point& thePosition);
boost::signals2::signal<void (Control* sender, Message& message)> OnCancelMode;
boost::signals2::signal<void (Control* sender, Message& message)> OnChar;
boost::signals2::signal<void (Control* sender, Message& message)> OnCharToItem;
boost::signals2::signal<void (Control* sender, Message& message)> OnClose;
boost::signals2::signal<void (Control* sender, Message& message)> OnCompareItem;
boost::signals2::signal<void (Control* sender, Message& message)> OnCommand;
boost::signals2::signal<void (Control* sender, Message& message)> OnCopyData;
boost::signals2::signal<void (Control* sender, Message& message)> OnDeadChar;
boost::signals2::signal<void (Control* sender, Message& message)> OnDeleteItem;
boost::signals2::signal<void (Control* sender, Message& message)> OnDestroy;
boost::signals2::signal<void (Control* sender, Message& message)> OnDisplayChange;
boost::signals2::signal<void (Control* sender, Message& message)> OnDrawItem;
boost::signals2::signal<void (Control* sender, Message& message)> OnEnable;
boost::signals2::signal<void (Control* sender, Message& message)> OnEnterSizeMove;
boost::signals2::signal<void (Control* sender, Message& message)> OnEraseBackground;
boost::signals2::signal<void (Control* sender, Message& message)> OnExitSizeMove;
boost::signals2::signal<void (Control* sender, Message& message)> OnGetHotKey;
boost::signals2::signal<void (Control* sender, Message& message)> OnGetText;
boost::signals2::signal<void (Control* sender, Message& message)> OnGetTextLength;
boost::signals2::signal<void (Control* sender, Message& message)> OnInitMenu;
boost::signals2::signal<void (Control* sender, Message& message)> OnInitMenuPopup;
boost::signals2::signal<void (Control* sender, Message& message)> OnKeyDown;
boost::signals2::signal<void (Control* sender, Message& message)> OnKeyUp;
boost::signals2::signal<void (Control* sender, Message& message)> OnKillFocus;
boost::signals2::signal<void (Control* sender, Message& message)> OnMeasureItem;
boost::signals2::signal<void (Control* sender, Message& message)> OnMenuCommand;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseMove;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseLeftButtonDown;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseLeftButtonUp;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseLeftButtonDoubleClick;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseMiddleButtonDown;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseMiddleButtonUp;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseMiddleButtonDoubleClick;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseRightButtonDown;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseRightButtonUp;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseRightButtonDoubleClick;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseXButtonDown;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseXButtonUp;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseXButtonDoubleClick;
boost::signals2::signal<void (Control* sender, Message& message)> OnMouseWheel;
boost::signals2::signal<void (Control* sender, Message& message)> OnMove;
boost::signals2::signal<void (Control* sender, Message& message)> OnMoving;
boost::signals2::signal<void (Control* sender, Message& message)> OnNcActivate;
boost::signals2::signal<void (Control* sender, Message& message)> OnNcCalcSize;
boost::signals2::signal<void (Control* sender, Message& message)> OnNcDestroy;
boost::signals2::signal<void (Control* sender, Message& message)> OnNotify;
boost::signals2::signal<void (Control* sender, Message& message)> OnPaint;
boost::signals2::signal<void (Control* sender, Message& message)> OnSetCursor;
boost::signals2::signal<void (Control* sender, Message& message)> OnSetFocus;
boost::signals2::signal<void (Control* sender, Message& message)> OnSetHotKey;
boost::signals2::signal<void (Control* sender, Message& message)> OnSetRedraw;
boost::signals2::signal<void (Control* sender, Message& message)> OnSetText;
boost::signals2::signal<void (Control* sender, Message& message)> OnShowWindow;
boost::signals2::signal<void (Control* sender, Message& message)> OnSize;
boost::signals2::signal<void (Control* sender, Message& message)> OnSizing;
boost::signals2::signal<void (Control* sender, Message& message)> OnSysChar;
boost::signals2::signal<void (Control* sender, Message& message)> OnSysCommand;
boost::signals2::signal<void (Control* sender, Message& message)> OnSysDeadChar;
boost::signals2::signal<void (Control* sender, Message& message)> OnSysKeyDown;
boost::signals2::signal<void (Control* sender, Message& message)> OnSysKeyUp;
boost::signals2::signal<void (Control* sender, Message& message)> OnUniChar;
boost::signals2::signal<void (Control* sender, Message& message)> OnVKeyToItem;
boost::signals2::signal<void (Control* sender, Message& message)> OnWindowPosChanging;
boost::signals2::signal<void (Control* sender, Message& message)> OnWindowPosChanged;
protected:
HWIN_EXPORT virtual bool IsInputChar(wchar_t charCode);
HWIN_EXPORT virtual bool IsInputKey(Keys keyData);
HWIN_EXPORT virtual bool ProcessMnemonic(wchar_t charCode);
HWIN_EXPORT virtual void DoOnCancelMode(Message& message);
HWIN_EXPORT virtual void DoOnChar(Message& message);
HWIN_EXPORT virtual void DoOnCharToItem(Message& message);
HWIN_EXPORT virtual void DoOnClose(Message& message);
HWIN_EXPORT virtual void DoOnCompareItem(Message& message);
HWIN_EXPORT virtual void DoOnCommand(Message& message);
HWIN_EXPORT virtual void DoOnCopyData(Message& message);
HWIN_EXPORT virtual void DoOnDeadChar(Message& message);
HWIN_EXPORT virtual void DoOnDeleteItem(Message& message);
HWIN_EXPORT virtual void DoOnDestroy(Message& message);
HWIN_EXPORT virtual void DoOnDisplayChange(Message& message);
HWIN_EXPORT virtual void DoOnDrawItem(Message& message);
HWIN_EXPORT virtual void DoOnEnable(Message& message);
HWIN_EXPORT virtual void DoOnEnterSizeMove(Message& message);
HWIN_EXPORT virtual void DoOnEraseBackground(Message& message);
HWIN_EXPORT virtual void DoOnExitSizeMove(Message& message);
HWIN_EXPORT virtual void DoOnGetHotKey(Message& message);
HWIN_EXPORT virtual void DoOnGetText(Message& message);
HWIN_EXPORT virtual void DoOnGetTextLength(Message& message);
HWIN_EXPORT virtual void DoOnInitMenu(Message& message);
HWIN_EXPORT virtual void DoOnInitMenuPopup(Message& message);
HWIN_EXPORT virtual void DoOnKeyDown(Message& message);
HWIN_EXPORT virtual void DoOnKeyUp(Message& message);
HWIN_EXPORT virtual void DoOnKillFocus(Message& message);
HWIN_EXPORT virtual void DoOnMeasureItem(Message& message);
HWIN_EXPORT virtual void DoOnMenuCommand(Message& message);
HWIN_EXPORT virtual void DoOnMouseMove(Message& message);
HWIN_EXPORT virtual void DoOnMouseLeftButtonDown(Message& message);
HWIN_EXPORT virtual void DoOnMouseLeftButtonUp(Message& message);
HWIN_EXPORT virtual void DoOnMouseLeftButtonDoubleClick(Message& message);
HWIN_EXPORT virtual void DoOnMouseMiddleButtonDown(Message& message);
HWIN_EXPORT virtual void DoOnMouseMiddleButtonUp(Message& message);
HWIN_EXPORT virtual void DoOnMouseMiddleButtonDoubleClick(Message& message);
HWIN_EXPORT virtual void DoOnMouseRightButtonDown(Message& message);
HWIN_EXPORT virtual void DoOnMouseRightButtonUp(Message& message);
HWIN_EXPORT virtual void DoOnMouseRightButtonDoubleClick(Message& message);
HWIN_EXPORT virtual void DoOnMouseXButtonDown(Message& message);
HWIN_EXPORT virtual void DoOnMouseXButtonUp(Message& message);
HWIN_EXPORT virtual void DoOnMouseXButtonDoubleClick(Message& message);
HWIN_EXPORT virtual void DoOnMouseWheel(Message& message);
HWIN_EXPORT virtual void DoOnMove(Message& message);
HWIN_EXPORT virtual void DoOnMoving(Message& message);
HWIN_EXPORT virtual void DoOnNcActivate(Message& message);
HWIN_EXPORT virtual void DoOnNcCalcSize(Message& message);
HWIN_EXPORT virtual void DoOnNcDestroy(Message& message);
HWIN_EXPORT virtual void DoOnNotify(Message& message);
HWIN_EXPORT virtual void DoOnPaint(Message& message);
HWIN_EXPORT virtual void DoOnSetCursor(Message& message);
HWIN_EXPORT virtual void DoOnSetFocus(Message& message);
HWIN_EXPORT virtual void DoOnSetHotKey(Message& message);
HWIN_EXPORT virtual void DoOnSetRedraw(Message& message);
HWIN_EXPORT virtual void DoOnSetText(Message& message);
HWIN_EXPORT virtual void DoOnShowWindow(Message& message);
HWIN_EXPORT virtual void DoOnSize(Message& message);
HWIN_EXPORT virtual void DoOnSizing(Message& message);
HWIN_EXPORT virtual void DoOnSysChar(Message& message);
HWIN_EXPORT virtual void DoOnSysCommand(Message& message);
HWIN_EXPORT virtual void DoOnSysDeadChar(Message& message);
HWIN_EXPORT virtual void DoOnSysKeyDown(Message& message);
HWIN_EXPORT virtual void DoOnSysKeyUp(Message& message);
HWIN_EXPORT virtual void DoOnUniChar(Message& message);
HWIN_EXPORT virtual void DoOnVKeyToItem(Message& message);
HWIN_EXPORT virtual void DoOnWindowPosChanging(Message& message);
HWIN_EXPORT virtual void DoOnWindowPosChanged(Message& message);
};
template< typename T >
std::shared_ptr<T> make_control( )
{
HWIN_TRACE();
auto result = std::make_shared<T>();
result->Initialize( );
return result;
}
template< typename T >
std::shared_ptr<T> make_control(std::shared_ptr<Control> theParent)
{
HWIN_TRACE();
auto result = std::make_shared<T>();
result->SetParent( theParent );
result->Initialize( theParent );
return result;
}
template< typename T, typename A >
std::shared_ptr<T> make_control(std::shared_ptr<Control> theParent, const A& argument)
{
HWIN_TRACE();
auto result = std::make_shared<T>(argument);
result->SetParent( theParent );
result->Initialize( theParent );
return result;
}
template< typename T, typename A1, typename A2 >
std::shared_ptr<T> make_control(std::shared_ptr<Control> theParent, const A1& argument1, const A2& argument2)
{
HWIN_TRACE();
auto result = std::make_shared<T>(argument1,argument2);
result->SetParent( theParent );
result->Initialize( theParent );
return result;
}
// --------------------------------------------------------------------
// MessageDispatcherBase
// --------------------------------------------------------------------
class MessageDispatcherBase
{
protected:
static void HandleMessage(Control* theControl, Message& message)
{
theControl->HandleMessage(message);
}
static void RegisterControl(HWND hWnd, Control* theControl)
{
Control::RegisterControl(hWnd,theControl);
}
static void UnregisterControl(HWND hWnd)
{
Control::UnregisterControl(hWnd);
}
};
// --------------------------------------------------------------------
// ControlMessageDispatcher
// --------------------------------------------------------------------
template< typename ControlClass_ >
class ControlMessageDispatcher : public MessageDispatcherBase
{
public:
static LRESULT CALLBACK WndProc(HWND hWnd, UINT messageId, WPARAM wParam, LPARAM lParam)
{
HWIN_TRACE();
Message message;
message.hwnd = hWnd;
message.message = messageId;
message.wParam = wParam;
message.lParam = lParam;
message.time = GetMessageTime();
DWORD pos = GetMessagePos();
message.pt.x = GET_X_LPARAM(pos);
message.pt.y = GET_Y_LPARAM(pos);
LONG_PTR userData = (LONG_PTR)0;
if(messageId == WM_NCCREATE)
{
CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam;
if(createStruct != nullptr)
{
userData = (LONG_PTR)createStruct->lpCreateParams;
if(userData)
{
SetWindowLongPtr(hWnd,GWLP_USERDATA,userData);
Control* control = (Control*)userData;
RegisterControl(hWnd,control);
}
}
}
else
{
userData = GetWindowLongPtr(hWnd,GWLP_USERDATA);
}
if(userData)
{
Control* control = (Control*)userData;
HandleMessage(control,message);
if(message.handled)
{
return message.result;
}
}
if(!message.handled)
{
message.result = DefWindowProc(hWnd, message.message, message.wParam, message.lParam);
}
if(messageId == WM_NCDESTROY)
{
UnregisterControl(hWnd);
}
return message.result;
}
};
template< typename ControlClass_ >
class SuperClassMessageDispatcher : public MessageDispatcherBase
{
public:
static WNDPROC ControlProcedure;
static LRESULT CALLBACK WndProc(HWND hWnd, UINT messageId, WPARAM wParam, LPARAM lParam)
{
HWIN_TRACE();
Message message;
message.hwnd = hWnd;
message.message = messageId;
message.wParam = wParam;
message.lParam = lParam;
message.time = GetMessageTime();
DWORD pos = GetMessagePos();
message.pt.x = GET_X_LPARAM(pos);
message.pt.y = GET_Y_LPARAM(pos);
LONG_PTR userData = (LONG_PTR)0;
if(messageId == WM_NCCREATE)
{
CREATESTRUCT* createStruct = (CREATESTRUCT*)lParam;
if(createStruct != nullptr)
{
userData = (LONG_PTR)createStruct->lpCreateParams;
if(userData)
{
SetWindowLongPtr(hWnd,GWLP_USERDATA,userData);
Control* control = (Control*)userData;
RegisterControl(hWnd,control);
}
}
}
else
{
userData = GetWindowLongPtr(hWnd,GWLP_USERDATA);
}
if(userData)
{
Control* control = (Control*)userData;
HandleMessage(control,message);
if(message.handled)
{
return message.result;
}
}
if(!message.handled)
{
message.result = ControlProcedure(hWnd, message.message, message.wParam, message.lParam);
}
if(messageId == WM_NCDESTROY)
{
UnregisterControl(hWnd);
}
return message.result;
}
};
};
};
#endif //__HWINCONTROL_H__