Click here to Skip to main content
15,884,298 members
Articles / Desktop Programming / Win32

Windows Development in C++, Working with Menus

Rate me:
Please Sign up or sign in to vote.
4.96/5 (60 votes)
3 Jan 2015CPOL19 min read 171.6K   4.1K   163  
Windows API, menus, C++ lambda expressions, std::enable_shared_from_this
#include "stdafx.h"

#include "hwinstdctrls.h"
#include "hwinapplication.h"
#include "hwinenvironment.h"

namespace harlinn
{
    namespace windows
    {
        // --------------------------------------------------------------------
        // ImageList
        // --------------------------------------------------------------------
        HWIN_EXPORT ImageListHandle::ImageListHandle(HIMAGELIST theHandle, bool closeHandle)
            : Base(theHandle, closeHandle)
        {
        }

        HWIN_EXPORT HIMAGELIST ImageListHandle::CreateImageList(int elementWidth, int elementHeight,int count, int growBy,ImageListFlags theFlags,ImageListColor color)
        {
            int flagsValue = int(theFlags) | int(color);
            HIMAGELIST result = ImageList_Create(elementWidth,elementHeight,flagsValue,count,growBy);
            if(!result)
            {
                ThrowLastOSError();
            }
            return result;
        }

        HWIN_EXPORT ImageListHandle::ImageListHandle(int elementWidth, int elementHeight,int count, int growBy,ImageListFlags theFlags,ImageListColor color)
            : Base(CreateImageList(elementWidth, elementHeight,count, growBy,theFlags,color), true)
        {
        }
        HWIN_EXPORT ImageListHandle::~ImageListHandle( )
        {
            if(OwnsHandle())
            {
                ImageList_Destroy(GetHIMAGELIST());
            }
        }

        HWIN_EXPORT ImageListHandle& ImageListHandle::Add(const BitmapHandle& bitmap)
        {
            if(ImageList_Add(GetHIMAGELIST(),bitmap.GetHBITMAP(),nullptr) < 0)
            {
                ThrowLastOSError();
            }
            return *this;
        }

        HWIN_EXPORT ImageListHandle& ImageListHandle::Add(const std::shared_ptr<BitmapHandle>& bitmap)
        {
            CheckPointerNotNull(bitmap);
            if(ImageList_Add(GetHIMAGELIST(),bitmap->GetHBITMAP(),nullptr) < 0)
            {
                ThrowLastOSError();
            }
            return *this;
        }

        HWIN_EXPORT ImageListHandle& ImageListHandle::Add(const BitmapHandle& bitmap, const BitmapHandle& mask)
        {
            if(ImageList_Add(GetHIMAGELIST(),bitmap.GetHBITMAP(),mask.GetHBITMAP()) < 0)
            {
                ThrowLastOSError();
            }
            return *this;
        }

        HWIN_EXPORT ImageListHandle& ImageListHandle::Add(const std::shared_ptr<BitmapHandle>& bitmap, const std::shared_ptr<BitmapHandle>& mask)
        {
            CheckPointerNotNull(bitmap);
            HBITMAP hMask = 0;
            if(mask)
            {
                hMask = mask->GetHBITMAP();
            }
            if(ImageList_Add(GetHIMAGELIST(),bitmap->GetHBITMAP(),hMask) < 0)
            {
                ThrowLastOSError();
            }
            return *this;
        }

        HWIN_EXPORT ImageListHandle& ImageListHandle::Add(const BitmapHandle& bitmap, COLORREF maskColor)
        {
            if(ImageList_AddMasked(GetHIMAGELIST(),bitmap.GetHBITMAP(),maskColor) < 0)
            {
                ThrowLastOSError();
            }
            return *this;
        }

        HWIN_EXPORT ImageListHandle& ImageListHandle::Add(const std::shared_ptr<BitmapHandle>& bitmap, COLORREF maskColor)
        {
            CheckPointerNotNull(bitmap);
            if(ImageList_AddMasked(GetHIMAGELIST(),bitmap->GetHBITMAP(),maskColor) < 0)
            {
                ThrowLastOSError();
            }
            return *this;
        }

        HWIN_EXPORT ImageListHandle& ImageListHandle::Move(int indexOfDestinationImage, int indexOfSourceImage)
        {
            if(indexOfDestinationImage != indexOfSourceImage)
            {
                if(ImageList_Copy(GetHIMAGELIST(),indexOfDestinationImage,GetHIMAGELIST(),indexOfSourceImage,ILCF_MOVE) == 0)
                {
                    ThrowLastOSError();
                }
            }
            return *this;
        }
        HWIN_EXPORT ImageListHandle& ImageListHandle::Swap(int indexOfFirstImage, int indexOfSecondImage)
        {
            if(indexOfFirstImage != indexOfSecondImage)
            {
                if(ImageList_Copy(GetHIMAGELIST(),indexOfFirstImage,GetHIMAGELIST(),indexOfSecondImage,ILCF_SWAP) == 0)
                {
                    ThrowLastOSError();
                }
            }
            return *this;
        }

        HWIN_EXPORT std::shared_ptr<ImageListHandle> ImageListHandle::Clone( )
        {
            HIMAGELIST hImageList = ImageList_Duplicate(GetHIMAGELIST());
            if(!hImageList)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<ImageListHandle>(hImageList,true);
            return result;
        }

        HWIN_EXPORT const ImageListHandle& ImageListHandle::BeginDrag(int indexOfTrackImage,int dxHotspot,int dyHotspot) const
        {
            if(ImageList_BeginDrag(GetHIMAGELIST(),indexOfTrackImage,dxHotspot,dyHotspot) == FALSE)
            {
                ThrowLastOSError();
            }
            return *this;
        }
        HWIN_EXPORT const ImageListHandle& ImageListHandle::BeginDrag(int indexOfTrackImage,const POINT& hotspot) const
        {
            if(ImageList_BeginDrag(GetHIMAGELIST(),indexOfTrackImage,hotspot.x,hotspot.y) == FALSE)
            {
                ThrowLastOSError();
            }
            return *this;
        }
        HWIN_EXPORT void ImageListHandle::DragEnter(HWND hwndLock,int x,int y)
        {
            if(ImageList_DragEnter(hwndLock,x,y) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::DragEnter(std::shared_ptr<Control> theControl,int x,int y)
        {
            CheckPointerNotNull(theControl);
            if(ImageList_DragEnter(theControl->GetSafeHandle(),x,y) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::DragLeave(HWND hwndLock)
        {
            if(ImageList_DragLeave(hwndLock) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::DragLeave(std::shared_ptr<Control> theControl)
        {
            CheckPointerNotNull(theControl);
            if(ImageList_DragLeave(theControl->GetSafeHandle()) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::DragMove(int x,int y)
        {
            if(ImageList_DragMove(x,y) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::DragShowNolock(bool showImage)
        {
            if(ImageList_DragShowNolock(showImage) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::EndDrag(void)
        {
            ImageList_EndDrag();
        }
        HWIN_EXPORT std::shared_ptr<ImageListHandle> ImageListHandle::GetDragImage(POINT *ppt,POINT *pptHotspot)
        {
            HIMAGELIST hImageList = ImageList_GetDragImage(ppt,pptHotspot);
            if(!hImageList)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<ImageListHandle>(hImageList,false);
            return result;
        }

        HWIN_EXPORT const ImageListHandle& ImageListHandle::Draw(int indexOfImage, HDC hDC, int x, int y, ImageListDrawFlags flags) const
        {
            if(ImageList_Draw(GetHIMAGELIST(),indexOfImage, hDC, x, y, UINT(flags)) == FALSE)
            {
                ThrowLastOSError();
            }
            return *this;
        }
        HWIN_EXPORT const ImageListHandle& ImageListHandle::Draw(int indexOfImage, HDC hDC, int x, int y, int dx, int dy, COLORREF background, COLORREF foreground, ImageListDrawFlags flags) const
        {
            if(ImageList_DrawEx(GetHIMAGELIST(),indexOfImage, hDC, x, y, dx, dy, background, foreground, UINT(flags)) == FALSE)
            {
                ThrowLastOSError();
            }
            return *this;
        }
        HWIN_EXPORT void ImageListHandle::Draw(const IMAGELISTDRAWPARAMS* imagelistDrawOarams)
        {
            if(ImageList_DrawIndirect(const_cast<IMAGELISTDRAWPARAMS*>(imagelistDrawOarams)) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::Draw(const IMAGELISTDRAWPARAMS& imagelistDrawOarams)
        {
            if(ImageList_DrawIndirect(const_cast<IMAGELISTDRAWPARAMS*>(&imagelistDrawOarams)) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT COLORREF ImageListHandle::GetBkColor( ) const
        {
            auto result = ImageList_GetBkColor(GetHIMAGELIST());
            return result;
        }
        HWIN_EXPORT COLORREF ImageListHandle::BackgroundColor( ) const
        {
            auto result = ImageList_GetBkColor(GetHIMAGELIST());
            return result;
        }

        HWIN_EXPORT std::shared_ptr<IconHandle> ImageListHandle::GetIcon(int indexOfImage,ImageListDrawFlags flags) const
        {
            auto hIcon = ImageList_GetIcon(GetHIMAGELIST(),indexOfImage,UINT(flags));
            if(!hIcon)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<IconHandle>(hIcon,true);
            return result;
        }

        HWIN_EXPORT std::shared_ptr<IconHandle> ImageListHandle::GetIcon(int indexOfImage) const
        {
            auto hIcon = ImageList_GetIcon(GetHIMAGELIST(),indexOfImage,0);
            if(!hIcon)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<IconHandle>(hIcon,true);
            return result;
        }

        HWIN_EXPORT void ImageListHandle::GetIconSize(int* x, int* y) const
        {
            if(ImageList_GetIconSize(GetHIMAGELIST(),x, y) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::GetIconSize(SIZE& size) const
        {
            if(ImageList_GetIconSize(GetHIMAGELIST(),(int*)&size.cx, (int*)&size.cy) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT SIZE ImageListHandle::GetIconSize() const
        {
            SIZE result = {0,};
            if(ImageList_GetIconSize(GetHIMAGELIST(),(int*)&result.cx, (int*)&result.cy) == FALSE)
            {
                ThrowLastOSError();
            }
            return result;
        }
        HWIN_EXPORT void ImageListHandle::GetImageSize(int* x, int* y) const
        {
            if(ImageList_GetIconSize(GetHIMAGELIST(),x, y) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT void ImageListHandle::GetImageSize(SIZE& size) const
        {
            if(ImageList_GetIconSize(GetHIMAGELIST(),(int*)&size.cx, (int*)&size.cy) == FALSE)
            {
                ThrowLastOSError();
            }
        }
        HWIN_EXPORT SIZE ImageListHandle::GetImageSize() const
        {
            SIZE result = {0,};
            if(ImageList_GetIconSize(GetHIMAGELIST(),(int*)&result.cx, (int*)&result.cy) == FALSE)
            {
                ThrowLastOSError();
            }
            return result;
        }
        HWIN_EXPORT int ImageListHandle::Count() const
        {
            auto result = ImageList_GetImageCount(GetHIMAGELIST());
            return result;
        }
            
        HWIN_EXPORT const ImageListHandle& ImageListHandle::GetImageInfo(int theImageIndex, IMAGEINFO* imageinfo) const
        {
            CheckPointerNotNull(imageinfo);
            if(ImageList_GetImageInfo(GetHIMAGELIST(),theImageIndex, imageinfo) == FALSE)
            {
                ThrowLastOSError();
            }
            return *this;
        }

        HWIN_EXPORT const ImageListHandle& ImageListHandle::GetImageInfo(int theImageIndex, IMAGEINFO& imageinfo) const
        {
            if(ImageList_GetImageInfo(GetHIMAGELIST(),theImageIndex, &imageinfo) == FALSE)
            {
                ThrowLastOSError();
            }
            return *this;
        }
        HWIN_EXPORT std::shared_ptr<ImageListHandle> ImageListHandle::Load(HINSTANCE hInstance, const wchar_t* name, int imageWidth, int growBy, COLORREF maskColor, ImageListLoadFlags flags)
        {
            HIMAGELIST hImageList = ImageList_LoadImageW(hInstance, name, imageWidth, growBy, maskColor, IMAGE_BITMAP,UINT(flags));
            if(!hImageList)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<ImageListHandle>(hImageList,int(flags & ImageListLoadFlags::Shared) != 0?false:true);
            return result;
        }
        HWIN_EXPORT std::shared_ptr<ImageListHandle> ImageListHandle::LoadFromFile(const wchar_t* name, int imageWidth, int growBy, COLORREF maskColor, ImageListLoadFlags flags)
        {
            flags |= ImageListLoadFlags::LoadFromFile;
            HIMAGELIST hImageList = ImageList_LoadImageW(nullptr, name, imageWidth, growBy, maskColor, IMAGE_BITMAP,UINT(flags));
            if(!hImageList)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<ImageListHandle>(hImageList,int(flags & ImageListLoadFlags::Shared) != 0?false:true);
            return result;
        }
        HWIN_EXPORT std::shared_ptr<ImageListHandle> ImageListHandle::LoadFromFile(const wchar_t* name, int imageWidth )
        {
            ImageListLoadFlags flags = ImageListLoadFlags::LoadFromFile;
            HIMAGELIST hImageList = ImageList_LoadImageW(nullptr, name, imageWidth, 1, CLR_DEFAULT, IMAGE_BITMAP,UINT(flags));
            if(!hImageList)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<ImageListHandle>(hImageList,true);
            return result;
        }
        HWIN_EXPORT std::shared_ptr<ImageListHandle> ImageListHandle::Merge(int i1,HIMAGELIST himl2,int i2,int dx,int dy) const
        {
            return Merge(GetHIMAGELIST(),i1,himl2,i2,dx,dy);
        }
        HWIN_EXPORT std::shared_ptr<ImageListHandle> ImageListHandle::Merge(HIMAGELIST himl1, int i1,HIMAGELIST himl2,int i2,int dx,int dy)
        {
            HIMAGELIST hImageList = ImageList_Merge(himl1, i1,himl2,i2,dx,dy);
            if(!hImageList)
            {
                ThrowLastOSError();
            }
            auto result = std::make_shared<ImageListHandle>(hImageList,true);
            return result;
        }



        // --------------------------------------------------------------------
        // ButtonBase
        // --------------------------------------------------------------------
        class ButtonWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT ButtonWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT ButtonWindowClass::windowClassName = String(L"HarlinnWindowsButtonWindowClassName");

        typedef SuperClassMessageDispatcher<Button> ButtonMessageDispatcher;
        WNDPROC ButtonMessageDispatcher::ControlProcedure;

        HWIN_EXPORT ButtonWindowClass::ButtonWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            ButtonMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = ButtonMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT ButtonBase::ButtonBase( )
            : Base( ), 
              autoEllipsis(false)
              
        {
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> ButtonBase::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(ButtonWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::button_class_name);
                auto newWindowClass = std::make_shared<ButtonWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD ButtonBase::GetStyle() const
        {
            auto result = Base::GetStyle();
            result |= WS_TABSTOP | WS_CHILD | WS_VISIBLE;
            return result;
        }

        HWIN_EXPORT bool ButtonBase::AutoEllipsis() const
        {
            return autoEllipsis;
        }
        HWIN_EXPORT ButtonBase& ButtonBase::SetAutoEllipsis(bool theValue)
        {
            autoEllipsis = theValue;
            return *this;
        }



        HWIN_EXPORT void ButtonBase::DoOnSetEnabled(bool theValue)
        {
            Button_Enable(this->GetSafeHandle(),theValue);
        }

        HWIN_EXPORT ButtonBase& ButtonBase::Click()
        {
            if(IsValid())
            {
                SendMessage(BM_CLICK);
            }
            else
            {
                this->DoOnClick();
            }
            return *this;
        }

        HWIN_EXPORT const ButtonBase& ButtonBase::GetTextMargin(RECT& margin) const
        {
            Button_GetTextMargin(GetSafeHandle(),&margin);
            return *this;
        }

        HWIN_EXPORT RECT ButtonBase::GetTextMargin( ) const
        {
            RECT margin = {0,};
            Button_GetTextMargin(GetSafeHandle(),&margin);
            return margin;
        }


        HWIN_EXPORT ButtonBase& ButtonBase::SetTextMargin(const RECT& margin)
        {
            Button_SetTextMargin(GetSafeHandle(),&margin);
            return *this;
        }

        HWIN_EXPORT const ButtonBase& ButtonBase::GetIdealSize(SIZE& preferredSize) const
        {
            Button_GetIdealSize(GetSafeHandle(),&preferredSize);
            return *this;
        }

        HWIN_EXPORT SIZE ButtonBase::GetIdealSize( ) const
        {
            SIZE result = {0,};
            Button_GetIdealSize(GetSafeHandle(),&result);
            return result;
        }


        HWIN_EXPORT void ButtonBase::DoOnClick()
        {
            OnClick(this);
        }

        HWIN_EXPORT void ButtonBase::DoOnCommand(Message& message)
        {
            WORD notificationCode = HIWORD(message.wParam);
            if((notificationCode == BN_CLICKED)&&(message.message == REFLECTED_WM_COMMAND))
            {
                this->DoOnClick();
            }
            Base::DoOnCommand(message);
        }

        // --------------------------------------------------------------------
        // PushButtonBase
        // --------------------------------------------------------------------
        HWIN_EXPORT PushButtonBase::PushButtonBase( )
            : isDefault(false)
        {
        }

        HWIN_EXPORT bool PushButtonBase::IsDefault() const
        {
            return isDefault;
        }
        HWIN_EXPORT PushButtonBase& PushButtonBase::SetDefault(bool theValue)
        {
            if(isDefault != theValue)
            {
                isDefault = theValue;
                if(IsValid())
                {
                    this->DoOnSetDefault(theValue);
                }
                this->DoOnDefaultChanged(theValue);
            }
            return *this;
        }

        HWIN_EXPORT void PushButtonBase::DoOnSetDefault(bool theValue)
        {
        }
        HWIN_EXPORT void PushButtonBase::DoOnDefaultChanged(bool theValue)
        {
            OnDefaultChanged(this,theValue);
        }



        // --------------------------------------------------------------------
        // Button
        // --------------------------------------------------------------------
        HWIN_EXPORT Button::Button( )
            : Base( )
        {
            
        }

        HWIN_EXPORT DWORD Button::GetStyle() const
        {
            DWORD result = Base::GetStyle();
            result |= BS_PUSHBUTTON | WS_TABSTOP;
            if(IsDefault())
            {
                result |= BS_DEFPUSHBUTTON;
            }
            else
            {
                result &= ~BS_DEFPUSHBUTTON;
            }

            return result;
        }

        HWIN_EXPORT void Button::DoOnSetDefault(bool theValue)
        {
            Base::DoOnSetDefault(theValue);
            if(IsValid())
            {
                DWORD style = Base::GetStyle();
                if(IsDefault())
                {
                    style |= BS_DEFPUSHBUTTON;
                }
                else
                {
                    style &= ~BS_DEFPUSHBUTTON;
                }
                Base::SetWindowStyle(style);
            }

        }


        // --------------------------------------------------------------------
        // DropDownButton
        // --------------------------------------------------------------------
        HWIN_EXPORT DropDownButton::DropDownButton( )
            : Base( )
        {
        }

        HWIN_EXPORT void DropDownButton::DoOnInitialize( )
        {
            popupMenu = std::make_shared<PopupMenu>( );
            popupMenu->Initialize(As<Component>());
        }


        HWIN_EXPORT DWORD DropDownButton::GetStyle() const
        {
            DWORD result = Base::GetStyle();
            
            if(IsDefault())
            {
                result |= BS_DEFSPLITBUTTON;
                result &= ~BS_SPLITBUTTON;
            }
            else
            {
                result &= ~BS_DEFSPLITBUTTON;
                result |= BS_SPLITBUTTON;
            }
            
            return result;
        }

        HWIN_EXPORT std::shared_ptr<PopupMenu> DropDownButton::Menu() const
        {
            return popupMenu;
        }

        HWIN_EXPORT void DropDownButton::DoOnSetDefault(bool theValue)
        {
            Base::DoOnSetDefault(theValue);
            if(IsValid())
            {
                DWORD style = Base::GetStyle();
                if(IsDefault())
                {
                    style |= BS_DEFPUSHBUTTON;
                    style &= ~BS_SPLITBUTTON;
                }
                else
                {
                    style &= ~BS_DEFPUSHBUTTON;
                    style |= BS_SPLITBUTTON;
                }
                Base::SetWindowStyle(style);
            }
        }

        HWIN_EXPORT void DropDownButton::DoOnNotify(Message& message)
        {
            Base::DoOnNotify(message);
            if(!message.handled)
            {
                if(message.message == REFLECTED_WM_NOTIFY)
                {
                    NMHDR* nmhdr = (NMHDR*)message.lParam;
                    if(nmhdr->code == BCN_DROPDOWN)
                    {
                        NMBCDROPDOWN* nmbcdropdown = (NMBCDROPDOWN*)message.lParam;
                        POINT pt;
                        pt.x = nmbcdropdown->rcButton.left;
                        pt.y = nmbcdropdown->rcButton.bottom;
                        ::ClientToScreen(nmbcdropdown->hdr.hwndFrom, &pt);

                        popupMenu->Show(As<Control>(),pt,nmbcdropdown->rcButton);
                        message.handled = true;
                        message.result = true;
                    }
                }
            }
        }


        // --------------------------------------------------------------------
        // CommandButton
        // --------------------------------------------------------------------
        HWIN_EXPORT CommandButton::CommandButton( )
            : Base( )
        {
            
        }

        HWIN_EXPORT DWORD CommandButton::GetStyle() const
        {
            DWORD result = Base::GetStyle();
            
            if(IsDefault())
            {
                result |= BS_DEFCOMMANDLINK;
                result &= ~BS_COMMANDLINK;
            }
            else
            {
                result &= ~BS_DEFCOMMANDLINK;
                result |= BS_COMMANDLINK;
            }

            return result;
        }

        HWIN_EXPORT void CommandButton::DoOnSetDefault(bool theValue)
        {
            Base::DoOnSetDefault(theValue);
            if(IsValid())
            {
                DWORD style = Base::GetStyle();
                if(IsDefault())
                {
                    style |= BS_DEFCOMMANDLINK;
                    style &= ~BS_COMMANDLINK;
                }
                else
                {
                    style &= ~BS_DEFCOMMANDLINK;
                    style |= BS_COMMANDLINK;
                }
                Base::SetWindowStyle(style);
            }
        }



        // --------------------------------------------------------------------
        // StateButton
        // --------------------------------------------------------------------
        HWIN_EXPORT StateButton::StateButton( )
            : Base( ), 
              checkState(CheckState::Unchecked),
              allowGrayed(false)
        {

        }

        HWIN_EXPORT void StateButton::DoOnHandleCreated( )
        {
            Base::DoOnHandleCreated( );
            int check = int(checkState);
            Button_SetCheck(GetSafeHandle(),check);
        }

        HWIN_EXPORT void StateButton::HandleMessage(Message& message)
        {
            Base::HandleMessage(message);
            if(!message.handled)
            {
                switch(message.message) 
                {
                case BM_SETCHECK:
                    {
                        harlinn::windows::CheckState theCheckState = harlinn::windows::CheckState(message.wParam);
                        if(checkState != theCheckState)
                        {
                            checkState = theCheckState;
                            this->DoOnCheckStateChanged(checkState);
                        }
                    }
                    break;
                }
            }
        }


        HWIN_EXPORT StateButton& StateButton::SetCheckState(harlinn::windows::CheckState theCheckState)
        {
            if(IsValid())
            {
                int check = int(theCheckState);
                Button_SetCheck(GetSafeHandle(),check);
            }
            else
            {
                if(checkState != theCheckState)
                {
                    checkState = theCheckState;
                    this->DoOnCheckStateChanged(checkState);
                }
            }
            return *this;
        }
        HWIN_EXPORT harlinn::windows::CheckState StateButton::CheckState() const
        {
            return checkState;
        }

        HWIN_EXPORT bool StateButton::AllowGrayed() const
        {
            return allowGrayed;
        }
        HWIN_EXPORT StateButton& StateButton::SetAllowGrayed(bool theValue)
        {
            if(allowGrayed != theValue)
            {
                allowGrayed = theValue;
            }
            return *this;
        }

        HWIN_EXPORT bool StateButton::Checked() const
        {
            return checkState == harlinn::windows::CheckState::Checked;
        }
        HWIN_EXPORT StateButton& StateButton::SetChecked(bool theValue)
        {
            SetCheckState(theValue?harlinn::windows::CheckState::Checked:harlinn::windows::CheckState::Unchecked);
            return *this;
        }

        HWIN_EXPORT StateButton& StateButton::Toggle()
        {
            if(checkState == CheckState::Unchecked)
            {
                SetCheckState(CheckState::Checked);
            }
            else if(checkState == CheckState::Checked)
            {
                if(allowGrayed)
                {
                    SetCheckState(CheckState::Indeterminate);
                }
                else
                {
                    SetCheckState(CheckState::Unchecked);;
                }
            }
            else
            {
                SetCheckState(CheckState::Unchecked);
            }
            return *this;
        }


        HWIN_EXPORT void StateButton::DoOnCheckStateChanged( harlinn::windows::CheckState theCheckState )
        {
            OnCheckStateChanged(this,theCheckState);
        }

        HWIN_EXPORT void StateButton::DoOnClick()
        {
            Toggle();
            Base::DoOnClick();
        }



        // --------------------------------------------------------------------
        // CheckBox
        // --------------------------------------------------------------------
        HWIN_EXPORT CheckBox::CheckBox( )
            : Base( )
        {
        }

        HWIN_EXPORT DWORD CheckBox::GetStyle() const
        {
            DWORD result = Base::GetStyle() | BS_CHECKBOX;
            return result;
        }

        // --------------------------------------------------------------------
        // RadioButton
        // --------------------------------------------------------------------
        HWIN_EXPORT RadioButton::RadioButton( )
            : Base( )
        {
            
        }


        HWIN_EXPORT DWORD RadioButton::GetStyle() const
        {
            DWORD result = Base::GetStyle() | BS_RADIOBUTTON;
            return result;
        }

        // --------------------------------------------------------------------
        // DateTimePicker
        // --------------------------------------------------------------------
        class DateTimePickerWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT DateTimePickerWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT DateTimePickerWindowClass::windowClassName = String(L"HarlinnWindowsDateTimePickerWindowClassName");

        typedef SuperClassMessageDispatcher<DateTimePicker> DateTimePickerMessageDispatcher;
        WNDPROC DateTimePickerMessageDispatcher::ControlProcedure;

        HWIN_EXPORT DateTimePickerWindowClass::DateTimePickerWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            DateTimePickerMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = DateTimePickerMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT DateTimePicker::DateTimePicker( )
            : Base( )
        {
            
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> DateTimePicker::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(DateTimePickerWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::datetimepick_class_name);
                auto newWindowClass = std::make_shared<DateTimePickerWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }


        HWIN_EXPORT DWORD DateTimePicker::GetStyle() const
        {
            return Base::GetStyle();
        }


        // --------------------------------------------------------------------
        // GroupBox
        // --------------------------------------------------------------------
        class GroupBoxWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT GroupBoxWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT GroupBoxWindowClass::windowClassName = String(L"HarlinnWindowsGroupBoxWindowClassName");

        typedef SuperClassMessageDispatcher<GroupBox> GroupBoxMessageDispatcher;
        WNDPROC GroupBoxMessageDispatcher::ControlProcedure;

        HWIN_EXPORT GroupBoxWindowClass::GroupBoxWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            GroupBoxMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = GroupBoxMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT GroupBox::GroupBox( )
            : Base( )
        {
            
            
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> GroupBox::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(GroupBoxWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::button_class_name);
                auto newWindowClass = std::make_shared<GroupBoxWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }


        HWIN_EXPORT DWORD GroupBox::GetStyle() const
        {
            return Base::GetStyle()| BS_GROUPBOX;
        }


        // --------------------------------------------------------------------
        // Label
        // --------------------------------------------------------------------
        class LabelWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT LabelWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT LabelWindowClass::windowClassName = String(L"HarlinnWindowsLabelWindowClassName");

        typedef SuperClassMessageDispatcher<Label> LabelMessageDispatcher;
        WNDPROC LabelMessageDispatcher::ControlProcedure;

        HWIN_EXPORT LabelWindowClass::LabelWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            LabelMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = LabelMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT Label::Label( )
            : Base( )
        {
            
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> Label::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(LabelWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::static_class_name);
                auto newWindowClass = std::make_shared<LabelWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD Label::GetStyle() const
        {
            return Base::GetStyle();
        }


        // --------------------------------------------------------------------
        // LinkLabel
        // --------------------------------------------------------------------
        class LinkLabelWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT LinkLabelWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT LinkLabelWindowClass::windowClassName = String(L"HarlinnWindowsLinkLabelWindowClassName");

        typedef SuperClassMessageDispatcher<LinkLabel> LinkLabelMessageDispatcher;
        WNDPROC LinkLabelMessageDispatcher::ControlProcedure;

        HWIN_EXPORT LinkLabelWindowClass::LinkLabelWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(*existingClass)
        {
            LinkLabelMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = LinkLabelMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT LinkLabel::LinkLabel( )
            : Base( )
        {
             
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> LinkLabel::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(LinkLabelWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::link_class_name);
                auto newWindowClass = std::make_shared<LinkLabelWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD LinkLabel::GetStyle() const
        {
            return Base::GetStyle();
        }


        HWIN_EXPORT void LinkLabel::DoOnClick(NMLINK* pNMLINK)
        {
            OnClick(this,pNMLINK);
        }

        HWIN_EXPORT void LinkLabel::DoOnNotify(Message& message)
        {
            Base::DoOnNotify(message);
            if(message.handled == false)
            {
                if((((LPNMHDR)message.lParam)->code == NM_CLICK)||(((LPNMHDR)message.lParam)->code == NM_RETURN))
                {
                    PNMLINK pNMLink = (PNMLINK)message.lParam;
                    this->DoOnClick(pNMLink);
                }
            }
        }



        // --------------------------------------------------------------------
        // ListControl
        // --------------------------------------------------------------------
        HWIN_EXPORT ListControl::ListControl( )
            : Base( )
        {
            
        }




        // --------------------------------------------------------------------
        // ComboBox
        // --------------------------------------------------------------------
        class ComboBoxWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT ComboBoxWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT ComboBoxWindowClass::windowClassName = String(L"HarlinnWindowsComboBoxWindowClassName");

        typedef SuperClassMessageDispatcher<ComboBox> ComboBoxMessageDispatcher;
        WNDPROC ComboBoxMessageDispatcher::ControlProcedure;

        HWIN_EXPORT ComboBoxWindowClass::ComboBoxWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            ComboBoxMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = ComboBoxMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT ComboBox::ComboBox( )
            : Base( )
        {

        }

        HWIN_EXPORT std::shared_ptr<WindowClass> ComboBox::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(ComboBoxWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::combobox_class_name);
                auto newWindowClass = std::make_shared<ComboBoxWindowClass> (windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD ComboBox::GetStyle() const
        {
            return Base::GetStyle();
        }


        // --------------------------------------------------------------------
        // ListBox
        // --------------------------------------------------------------------
        class ListBoxWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT ListBoxWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT ListBoxWindowClass::windowClassName = String(L"HarlinnWindowsListBoxWindowClassName");

        typedef SuperClassMessageDispatcher<ListBox> ListBoxMessageDispatcher;
        WNDPROC ListBoxMessageDispatcher::ControlProcedure;

        HWIN_EXPORT ListBoxWindowClass::ListBoxWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            ListBoxMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = ListBoxMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT ListBox::ListBox( )
            : Base( )
        {

        }

        HWIN_EXPORT std::shared_ptr<WindowClass> ListBox::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(ListBoxWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::listbox_class_name);
                auto newWindowClass = std::make_shared<ListBoxWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD ListBox::GetStyle() const
        {
            return Base::GetStyle();
        }

        // --------------------------------------------------------------------
        // CheckedListBox
        // --------------------------------------------------------------------
        HWIN_EXPORT CheckedListBox::CheckedListBox( )
            : Base( )
        {
        }


        HWIN_EXPORT DWORD CheckedListBox::GetStyle() const
        {
            return Base::GetStyle();
        }

        // --------------------------------------------------------------------
        // HeaderControlItem
        // --------------------------------------------------------------------
        HWIN_EXPORT HeaderControlItem::HeaderControlItem(HeaderControlItems* theHeaderControlItems)
            : Base(), 
              items(theHeaderControlItems),
              mask(HeaderControlItemMask::None),
              dimension(0),
              format(HeaderControlItemFormat::Default),
              imageIndex(I_IMAGENONE),
              order(-1),
              filterType(HeaderControlItemFilterType::None)
        {}


        HWIN_EXPORT HeaderControlItem::HeaderControlItem(HeaderControlItems* theHeaderControlItems, const String& theText)
        : Base(), 
              items(theHeaderControlItems),
              mask(HeaderControlItemMask::None),
              dimension(50),
              format(HeaderControlItemFormat::Default),
              imageIndex(I_IMAGENONE),
              order(-1),
              filterType(HeaderControlItemFilterType::None),
              text(theText)
        {}

        bool HeaderControlItem::IsHandleCreated() const
        {
            return items->headerControl->IsHandleCreated();
        }

        HWND HeaderControlItem::GetControlHandle() const
        {
            return items->headerControl->GetSafeHandle();
        }

        HeaderControl* HeaderControlItem::GetControl() const
        {
            return items->headerControl;
        }

        



        HWIN_EXPORT String HeaderControlItem::Text() const
        {
            return text;
        }
        HWIN_EXPORT HeaderControlItem& HeaderControlItem::SetText(const String& theText)
        {
            if(text != theText)
            {
                text = theText;
            }
            return *this;
        }


        
        HWIN_EXPORT HeaderControlItem& HeaderControlItem::Assign(const HDITEM& item)
        {
            if(item.mask & HDI_BITMAP)
            {
                if(item.hbm)
                {
                    bitmap = BitmapHandle::FromHandle(item.hbm,false);
                }
                else
                {
                    bitmap.reset();
                }
            }
            if(item.mask & HDI_FORMAT)
            {
                format = HeaderControlItemFormat(item.fmt);
            }
            if(item.mask & HDI_FILTER)
            {

            }
            if(item.mask & HDI_HEIGHT)
            {
                dimension = item.cxy;
            }
            if(item.mask & HDI_IMAGE)
            {
                imageIndex = item.iImage;
            }
            if(item.mask & HDI_LPARAM)
            {

            }
            if(item.mask & HDI_ORDER)
            {
                order = item.iOrder;    
            }

            if(item.mask & HDI_STATE)
            {
                if(item.state & HDIS_FOCUSED)
                {
                    auto index = IndexOf();
                    items->focusedIndex = index;
                }    
            }
            if(item.mask & HDI_TEXT)
            {
                String s(item.pszText,item.cchTextMax);
                if(text != s)
                {
                    text = s;
                }
            }
            
            
            return *this;
        }


        HWIN_EXPORT const HeaderControlItem& HeaderControlItem::AssignTo(HDITEM& item) const
        {
            if(bitmap)
            {
                item.hbm = bitmap->GetHBITMAP();
                item.mask |= HDI_BITMAP;
            }
            else
            {
                item.mask &= ~HDI_BITMAP;
            }
            item.mask |= HDI_FORMAT;
            item.fmt = int(format);
            if(items->headerControl->imageList)
            {
                item.iImage = imageIndex;
                item.mask |= HDI_IMAGE;
            }
            else
            {
                item.mask &= ~HDI_IMAGE;
            }
            if(dimension > 0)
            {
                item.mask |= HDI_HEIGHT;
                item.cxy = dimension;
            }
            else
            {
                item.mask &= ~HDI_HEIGHT;
            }
            if(order >= 0)
            {
                item.mask |= HDI_ORDER;
                item.iOrder = order;
            }
            else
            {
                item.mask &= ~HDI_ORDER;
            }
            if(!text.IsEmpty())
            {
                item.mask |= HDI_TEXT;
                item.pszText = (LPWSTR)text.c_str();
                item.cchTextMax = int(text.length());
            }
            else
            {
                item.mask &= ~HDI_TEXT;
            }
            return *this;
        }

        HWIN_EXPORT size_t HeaderControlItem::IndexOf() const
        {
            return items->IndexOf(this);
        }

        HWIN_EXPORT void HeaderControlItem::DoOnBeginDrag( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnBeginFilterEdit( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnBeginTrack( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnDividerDoubleClick( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnDropDown( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnEndDrag( NMHEADER* pNMHEADER )
        {
        }

        HWIN_EXPORT void HeaderControlItem::DoOnEndFilterEdit( NMHEADER* pNMHEADER )
        {
        }

        HWIN_EXPORT void HeaderControlItem::DoOnEndTrack( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnFilterButtonClicked( NMHDFILTERBTNCLICK* pNMHDFILTERBTNCLICK )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnFilterChange( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnGetDispInfo( NMHDDISPINFO* pNMHDDISPINFO)
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnItemChanged( NMHEADER* pNMHEADER)
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnItemChanging( NMHEADER* pNMHEADER)
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnItemClicked( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnItemDoubleClicked( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnItemKeyDown( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnItemStateIconClicked( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnItemOverflowButtonClicked( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnTrack( NMHEADER* pNMHEADER )
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnCustomDraw( NMCUSTOMDRAW* pNMCUSTOMDRAW) 
        {
        }
        HWIN_EXPORT void HeaderControlItem::DoOnRightClicked( const Point& mousePosition )
        {
        }


        HWIN_EXPORT void HeaderControlItem::InsertHDITEM()
        {
            if(IsHandleCreated())
            {
                HWND hWnd = GetControlHandle();
                int index = int(IndexOf());
                HDITEM hditem = {0,};
                this->AssignTo(hditem);
                if(Header_InsertItem(hWnd,index,&hditem) == -1)
                {
                    ThrowLastOSError();
                }
            }
        }
        HWIN_EXPORT void HeaderControlItem::UpdateHDITEM()
        {
            if(IsHandleCreated())
            {
                HWND hWnd = GetControlHandle();
                int index = int(IndexOf());
                HDITEM hditem = {0,};
                this->AssignTo(hditem);
                if(Header_SetItem(hWnd,index,&hditem) == FALSE)
                {
                    ThrowLastOSError();
                }
            }
        }
        HWIN_EXPORT void HeaderControlItem::DeleteHDITEM()
        {
            auto index = IndexOf();
            items->RemoveAt(index);
        }

        // --------------------------------------------------------------------
        // HeaderControlItems
        // --------------------------------------------------------------------
        HWIN_EXPORT HeaderControlItems::HeaderControlItems(HeaderControl* theHeaderControl)
            : headerControl(theHeaderControl),focusedIndex(npos)
        {

        }

        void HeaderControlItems::DoOnHandleCreated( )
        {
            for(size_type i = 0; i < items.size(); i++)
            {
                auto& item = items.at(i);
                item->InsertHDITEM();
            }
        }


        HWIN_EXPORT HeaderControlItems::size_type HeaderControlItems::Count() const
        {
            return items.size();
        }

        HWIN_EXPORT HeaderControlItems::size_type HeaderControlItems::IndexOf(const HeaderControlItem* theItem) const
        {
            if(theItem)
            {
                for(size_type i = 0; i < items.size(); i++)
                {
                    auto item = items.at(i);
                    if(item)
                    {
                        if(item.get() == theItem)
                        {
                            return i;
                        }
                    }
                }
            }
            return npos;
        }

        HWIN_EXPORT HeaderControlItems::size_type HeaderControlItems::IndexOf(std::shared_ptr<const HeaderControlItem> theItem) const
        {
            if(theItem)
            {
                return IndexOf(theItem.get());
            }
            return npos;
        }

        HWIN_EXPORT std::shared_ptr<const HeaderControlItem> HeaderControlItems::FocusedItem() const
        {
            if(focusedIndex < items.size())
            {
                return items.at(focusedIndex);
            }
            return std::shared_ptr<const HeaderControlItem>();
        }

        HWIN_EXPORT std::shared_ptr<HeaderControlItem> HeaderControlItems::FocusedItem()
        {
            if(focusedIndex < items.size())
            {
                return items.at(focusedIndex);
            }
            return std::shared_ptr<HeaderControlItem>();
        }

        HWIN_EXPORT HeaderControlItems::size_type HeaderControlItems::FocusedIndex() const
        {
            return focusedIndex;
        }


        HWIN_EXPORT std::shared_ptr<const HeaderControlItem> HeaderControlItems::Add(const String& headerText)
        {
            auto result = make_object<HeaderControlItem>(this,headerText);
            items.push_back(result);
            result->InsertHDITEM();
            return result;
        }
        HWIN_EXPORT std::shared_ptr<const HeaderControlItem> HeaderControlItems::Add(const String& headerText, HorizontalAlignment alignment)
        {
            auto result = make_object<HeaderControlItem>(this,headerText);
            result->format |= HeaderControlItemFormat(int(alignment));
            items.push_back(result);
            result->InsertHDITEM();
            return result;
        }

        HWIN_EXPORT HeaderControlItems& HeaderControlItems::RemoveAt( size_type index )
        {
            if(index < items.size() )
            {
                items.erase(items.begin() + index);
                if(headerControl->IsHandleCreated())
                {
                    HWND hWnd = headerControl->GetSafeHandle();
                    if(Header_DeleteItem(hWnd,int(index)) == FALSE)
                    {
                        ThrowLastOSError();
                    }
                }
            }
            return *this;
        }
        


        // --------------------------------------------------------------------
        // HeaderControl
        // --------------------------------------------------------------------
        class HeaderControlWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT HeaderControlWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT HeaderControlWindowClass::windowClassName = String(L"HarlinnWindowsHeaderControlWindowClassName");

        typedef SuperClassMessageDispatcher<HeaderControl> HeaderControlMessageDispatcher;
        WNDPROC HeaderControlMessageDispatcher::ControlProcedure;

        HWIN_EXPORT HeaderControlWindowClass::HeaderControlWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            HeaderControlMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = HeaderControlMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }


        HWIN_EXPORT HeaderControl::HeaderControl( )
            : Base( ),
              items(new HeaderControlItems(this)),
              bitmapMargin(DefaultBitmapMargin())
        {
            
        }

        HWIN_EXPORT HeaderControl::~HeaderControl()
        {
            delete items;
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> HeaderControl::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(HeaderControlWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::header_class_name);
                auto newWindowClass = std::make_shared<HeaderControlWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD HeaderControl::GetStyle() const
        {
            return Base::GetStyle();
        }


        HWIN_EXPORT std::shared_ptr<ImageListHandle> HeaderControl::ImageList() const
        {
            return imageList;
        }

        HWIN_EXPORT HeaderControl& HeaderControl::SetImageList(const std::shared_ptr<ImageListHandle>& theImageList )
        {
            imageList = theImageList;
            if(IsHandleCreated())
            {
                if(imageList)
                {
                    Header_SetImageList(GetSafeHandle(),imageList->GetHIMAGELIST());
                }
                else
                {
                    Header_SetImageList(GetSafeHandle(),nullptr);
                }
            }
            return *this;
        }

        HWIN_EXPORT std::shared_ptr<ImageListHandle> HeaderControl::StateImageList() const
        {
            return stateImageList;
        }
        HWIN_EXPORT HeaderControl& HeaderControl::SetStateImageList(const std::shared_ptr<ImageListHandle>& theImageList )
        {
            stateImageList = theImageList;
            if(IsHandleCreated())
            {
                if(stateImageList)
                {
                    Header_SetStateImageList (GetSafeHandle(),stateImageList->GetHIMAGELIST());
                }
                else
                {
                    Header_SetStateImageList (GetSafeHandle(),nullptr);
                }
            }
            return *this;
        }


        

        HWIN_EXPORT Rectangle HeaderControl::GetItemRectangle(size_t theIndex) const
        {
            Rectangle result;
            if( SendMessage(HDM_GETITEMRECT,WPARAM(theIndex),LPARAM(&result)) == 0)
            {
                ThrowLastOSError();
            }
            return result;
        }
        HWIN_EXPORT Rectangle HeaderControl::GetItemRectangle(const HeaderControlItem* theItem) const
        {
            if(theItem == nullptr)
            {
                throw ArgumentNullException("theItem");
            }
            auto index = items->IndexOf(theItem);
            if(index == HeaderControlItems::npos)
            {
                throw ArgumentNullException("theItem is not an HeaderControlItem belonging to this HeaderControl");
            }
            return GetItemRectangle(index);
        }
        HWIN_EXPORT Rectangle HeaderControl::GetItemRectangle(std::shared_ptr<const HeaderControlItem> theItem) const
        {
            if(!theItem)
            {
                throw ArgumentNullException("theItem");
            }
            auto index = items->IndexOf(theItem);
            if(index == HeaderControlItems::npos)
            {
                throw ArgumentNullException("theItem is not an HeaderControlItem belonging to this HeaderControl");
            }
            return GetItemRectangle(index);
        }

        HWIN_EXPORT int HeaderControl::DefaultBitmapMargin()
        {
            return Environment::SystemMetrics::EdgeBorderWidth() * 3;
        }


        HWIN_EXPORT HeaderControl& HeaderControl::SetBitmapMargin(int theMargin)
        {
            bitmapMargin = theMargin;
            if(IsHandleCreated())
            {
                SendMessage(HDM_SETBITMAPMARGIN,theMargin);
            }
            return *this;
        }


        HWIN_EXPORT void HeaderControl::DoOnHandleCreated( )
        {
            items->DoOnHandleCreated();
        }
        HWIN_EXPORT void HeaderControl::DoOnWindowSubClassed( )
        {
        }

        HWIN_EXPORT void HeaderControl::DoOnBeginDrag( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnBeginDrag(pNMHEADER);
            OnBeginDrag(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnBeginFilterEdit( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnBeginFilterEdit(pNMHEADER);
            OnBeginFilterEdit(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnBeginTrack( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnBeginTrack(pNMHEADER);
            OnBeginTrack(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnDividerDoubleClick( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnDividerDoubleClick(pNMHEADER);
            OnDividerDoubleClick(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnDropDown( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnDropDown(pNMHEADER);
            OnDropDown(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnEndDrag( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnEndDrag(pNMHEADER);
            OnEndDrag(this,pNMHEADER,theItem);
        }

        HWIN_EXPORT void HeaderControl::DoOnEndFilterEdit( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnEndFilterEdit(pNMHEADER);
            OnEndFilterEdit(this,pNMHEADER,theItem);
        }

        HWIN_EXPORT void HeaderControl::DoOnEndTrack( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnEndTrack(pNMHEADER);
            OnEndTrack(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnFilterButtonClicked( NMHDFILTERBTNCLICK* pNMHDFILTERBTNCLICK, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnFilterButtonClicked(pNMHDFILTERBTNCLICK);
            OnFilterButtonClicked(this,pNMHDFILTERBTNCLICK,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnFilterChange( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnFilterChange(pNMHEADER);
            OnFilterChange(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnGetDispInfo( NMHDDISPINFO* pNMHDDISPINFO, const std::shared_ptr<HeaderControlItem>& theItem)
        {
            theItem->DoOnGetDispInfo(pNMHDDISPINFO);
            OnGetDispInfo(this,pNMHDDISPINFO,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnItemChanged( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem)
        {
            theItem->DoOnItemChanged(pNMHEADER);
            OnItemChanged(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnItemChanging( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem)
        {
            theItem->DoOnItemChanging(pNMHEADER);
            OnItemChanging(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnItemClicked( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnItemClicked(pNMHEADER);
            OnItemClicked(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnItemDoubleClicked( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnItemDoubleClicked(pNMHEADER);
            OnItemDoubleClicked(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnItemKeyDown( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnItemKeyDown(pNMHEADER);
            OnItemKeyDown(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnItemStateIconClicked( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnItemStateIconClicked(pNMHEADER);
            OnItemStateIconClicked(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnItemOverflowButtonClicked( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnItemOverflowButtonClicked(pNMHEADER);
            OnItemOverflowButtonClicked(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnTrack( NMHEADER* pNMHEADER, const std::shared_ptr<HeaderControlItem>& theItem )
        {
            theItem->DoOnTrack(pNMHEADER);
            OnTrack(this,pNMHEADER,theItem);
        }
        HWIN_EXPORT void HeaderControl::DoOnCustomDraw( NMCUSTOMDRAW* pNMCUSTOMDRAW) 
        {
            OnCustomDraw(this,pNMCUSTOMDRAW);
        }
        HWIN_EXPORT void HeaderControl::DoOnRightClicked( const Point& mousePosition )
        {
            OnRightClicked(this,mousePosition);
        }
        HWIN_EXPORT void HeaderControl::DoOnCaptureReleased( const Point& mousePosition )
        {
            OnCaptureReleased(this,mousePosition);
        }


        HWIN_EXPORT void HeaderControl::DoOnNotify(Message& message)
        {
            Base::DoOnNotify(message);
            if(message.handled == false)
            {
                NMHDR* pNMHDR = (NMHDR*) message.lParam;
                if(pNMHDR)
                {
                    switch(pNMHDR->code)
                    {
                    case HDN_BEGINDRAG:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnBeginDrag(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_BEGINFILTEREDIT:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnBeginFilterEdit(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_BEGINTRACK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnBeginTrack(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_DIVIDERDBLCLICK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnDividerDoubleClick(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_DROPDOWN:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnDropDown(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ENDDRAG:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnEndDrag(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ENDFILTEREDIT:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnEndFilterEdit(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ENDTRACK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnEndTrack(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_FILTERBTNCLICK:
                        {
                            NMHDFILTERBTNCLICK* pNMHDFILTERBTNCLICK = (NMHDFILTERBTNCLICK*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHDFILTERBTNCLICK->iItem);
                            this->DoOnFilterButtonClicked(pNMHDFILTERBTNCLICK,theItem);
                        }
                        break;
                    case HDN_FILTERCHANGE:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnFilterChange(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_GETDISPINFO:
                        {
                            NMHDDISPINFO* pNMHDDISPINFO = (NMHDDISPINFO*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHDDISPINFO->iItem);
                            this->DoOnGetDispInfo(pNMHDDISPINFO,theItem);
                        }
                        break;
                    case HDN_ITEMCHANGED:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnItemChanged(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ITEMCHANGING:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnItemChanging(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ITEMCLICK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnItemClicked(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ITEMDBLCLICK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnItemDoubleClicked(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ITEMKEYDOWN:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnItemKeyDown(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_ITEMSTATEICONCLICK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnItemStateIconClicked(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_OVERFLOWCLICK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnItemOverflowButtonClicked(pNMHEADER,theItem);
                        }
                        break;
                    case HDN_TRACK:
                        {
                            NMHEADER* pNMHEADER = (NMHEADER*)pNMHDR;
                            std::shared_ptr<HeaderControlItem>& theItem = items->items.at(pNMHEADER->iItem);
                            this->DoOnTrack(pNMHEADER,theItem);
                        }
                        break;
                    case NM_CUSTOMDRAW:
                        {
                            NMCUSTOMDRAW* pNMCUSTOMDRAW = (NMCUSTOMDRAW *)pNMHDR;
                            this->DoOnCustomDraw(pNMCUSTOMDRAW);
                        }
                        break;
                    case NM_RCLICK:
                        {
                            Point pt(message.pt);
                            this->DoOnRightClicked(pt);
                        }
                        break;
                    case NM_RELEASEDCAPTURE:
                        {
                            Point pt(message.pt);
                            this->DoOnCaptureReleased(pt);
                        }
                        break;
                    };
                }
            }
        }



        // --------------------------------------------------------------------
        // ListView
        // --------------------------------------------------------------------
        class ListViewWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT ListViewWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT ListViewWindowClass::windowClassName = String(L"HarlinnWindowsListViewWindowClassName");

        typedef SuperClassMessageDispatcher<ListView> ListViewMessageDispatcher;
        WNDPROC ListViewMessageDispatcher::ControlProcedure;

        HWIN_EXPORT ListViewWindowClass::ListViewWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            ListViewMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = ListViewMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT ListView::ListView( )
            : Base( )
        {
            
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> ListView::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(ListViewWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::listview_class_name);
                auto newWindowClass = std::make_shared<ListViewWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD ListView::GetStyle() const
        {
            return Base::GetStyle();
        }


        // --------------------------------------------------------------------
        // MonthCalendar
        // --------------------------------------------------------------------
        class MonthCalendarWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT MonthCalendarWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT MonthCalendarWindowClass::windowClassName = String(L"HarlinnWindowsMonthCalendarWindowClassName");

        typedef SuperClassMessageDispatcher<MonthCalendar> MonthCalendarMessageDispatcher;
        WNDPROC MonthCalendarMessageDispatcher::ControlProcedure;

        HWIN_EXPORT MonthCalendarWindowClass::MonthCalendarWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(*existingClass)
        {
            MonthCalendarMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = MonthCalendarMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT MonthCalendar::MonthCalendar( )
            : Base( )
        {
            
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> MonthCalendar::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(MonthCalendarWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::monthcal_class_name);
                auto newWindowClass = std::make_shared<MonthCalendarWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD MonthCalendar::GetStyle() const
        {
            return Base::GetStyle();
        }



        // --------------------------------------------------------------------
        // TreeEditBase
        // --------------------------------------------------------------------
        HWIN_EXPORT TreeEditBase::TreeEditBase( )
            : Base( )
        {
            
        }


        // --------------------------------------------------------------------
        // EditBase
        // --------------------------------------------------------------------
        HWIN_EXPORT EditBase::EditBase(  )
            : Base( )
        {
            
        }



        // --------------------------------------------------------------------
        // TextEditBase
        // --------------------------------------------------------------------
        HWIN_EXPORT TextEditBase::TextEditBase(  )
            : Base( )
        {
        }

        // --------------------------------------------------------------------
        // TextEdit
        // --------------------------------------------------------------------
        class TextEditWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT TextEditWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT TextEditWindowClass::windowClassName = String(L"HarlinnWindowsTextEditWindowClassName");

        typedef SuperClassMessageDispatcher<TextEdit> TextEditMessageDispatcher;
        WNDPROC TextEditMessageDispatcher::ControlProcedure;

        HWIN_EXPORT TextEditWindowClass::TextEditWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            TextEditMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = TextEditMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT TextEdit::TextEdit( )
            : Base( )
        {

        }

        HWIN_EXPORT std::shared_ptr<WindowClass> TextEdit::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(TextEditWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::edit_class_name);
                auto newWindowClass = std::make_shared<TextEditWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD TextEdit::GetStyle() const
        {
            return Base::GetStyle();
        }


        HWIN_EXPORT bool TextEdit::CanUndo() const
        {
            LRESULT messageResult = SendMessage(UINT(EM_CANUNDO));
            return messageResult != 0;

        }

        HWIN_EXPORT TextEdit& TextEdit::Undo()
        {
            SendMessage(EM_UNDO);
            return *this;
        }

        HWIN_EXPORT TextEdit& TextEdit::EmptyUndoBuffer()
        {
            SendMessage(EM_EMPTYUNDOBUFFER);
            return *this;
        }
        HWIN_EXPORT TextEdit& TextEdit::FmtLines(bool addSoftLinebreaks)
        {
            SendMessage(EM_FMTLINES,addSoftLinebreaks?TRUE:FALSE);
            return *this;
        }
        HWIN_EXPORT String TextEdit::CueBannerText( ) const
        {
            wchar_t buffer[1024] = {0,};
            if(SendMessage(EM_GETCUEBANNER,WPARAM(buffer),1024) != FALSE)
            {
                return String(buffer);
            }
            return String();
        }

        HWIN_EXPORT TextEdit& TextEdit::SetCueBannerText(const String& theText, bool displayWhileFocused  )
        {
            SetCueBannerText(theText.c_str(),displayWhileFocused);
            return *this;
        }
        HWIN_EXPORT TextEdit& TextEdit::SetCueBannerText(const wchar_t* theText, bool displayWhileFocused )
        {
            if(theText && theText[0])
            {
                SendMessage(EM_SETCUEBANNER,WPARAM(displayWhileFocused?TRUE:FALSE),LPARAM(theText));
            }
            else
            {
                SendMessage(EM_SETCUEBANNER,WPARAM(displayWhileFocused?TRUE:FALSE),LPARAM(L""));
            }
            return *this;
        }

        HWIN_EXPORT int TextEdit::GetFirstVisibleLine() const
        {
            LRESULT messageResult = SendMessage(UINT(EM_GETFIRSTVISIBLELINE));
            return int(messageResult);
        }
        HWIN_EXPORT UINT TextEdit::TextLimit() const
        {
            LRESULT messageResult = SendMessage(UINT(EM_GETLIMITTEXT));
            return UINT(messageResult);
        }
        HWIN_EXPORT TextEdit& TextEdit::SetTextLimit(UINT theValue)
        {
            SendMessage(UINT(EM_SETLIMITTEXT),theValue);
            return *this;
        }


        HWIN_EXPORT int TextEdit::LineIndex(int theIndex) const
        {
            LRESULT messageResult = SendMessage(UINT(EM_LINEINDEX),WPARAM(theIndex));
            return int (messageResult);
        }

        HWIN_EXPORT int TextEdit::LineLength(int theIndex) const
        {
            int lineIndex = LineIndex(theIndex);
            if(lineIndex >= 0)
            {
                LRESULT messageResult = SendMessage(UINT(EM_LINELENGTH),WPARAM(lineIndex));
                return int(messageResult);
            }
            return -1;
        }
        HWIN_EXPORT String TextEdit::Line(int theIndex) const
        {
            int lineLength = LineLength(theIndex);
            if(lineLength > 0 )
            {
                String result(nullptr,String::size_type(lineLength));
                *(WORD*)result.c_str() = WORD(lineLength);
                LRESULT messageResult = SendMessage(UINT(EM_GETLINE),WPARAM(theIndex),LPARAM(result.c_str()));
                result.Remove(messageResult);
                return result;
            }
            return String();
        }
        HWIN_EXPORT int TextEdit::LineCount() const
        {
            LRESULT messageResult = SendMessage(UINT(EM_GETLINECOUNT));
            return int (messageResult);
        }
        HWIN_EXPORT bool TextEdit::IsModified() const
        {
            LRESULT messageResult = SendMessage(UINT(EM_GETMODIFY));
            return messageResult != 0;
        }

        HWIN_EXPORT wchar_t TextEdit::PasswordChar() const
        {
            LRESULT messageResult = SendMessage(UINT(EM_GETPASSWORDCHAR));
            return wchar_t(messageResult);
        }
        HWIN_EXPORT TextEdit& TextEdit::SetPasswordChar(wchar_t theValue )
        {
            SendMessage(UINT(EM_SETPASSWORDCHAR),theValue);
            return *this;
        }

        HWIN_EXPORT Range TextEdit::Selection() const
        {
            DWORD start; 
            DWORD end;
            SendMessage(UINT(EM_GETSEL),WPARAM(&start),LPARAM(&end));
            return Range(start,end);
        }
        HWIN_EXPORT TextEdit& TextEdit::SetSelection(const Range& selectionRange )
        {
            SendMessage(UINT(EM_SETSEL),WPARAM(selectionRange.Start()),LPARAM(selectionRange.End()));
            return *this;
        }

        HWIN_EXPORT void TextEdit::DoOnSetEnabled(bool theValue)
        {
            Edit_Enable(this->GetSafeHandle(),theValue);
        }

        HWIN_EXPORT TextEdit& TextEdit::ReplaceSelection(const String& theText)
        {
            ReplaceSelection(theText.c_str());
            return *this;
        }
        HWIN_EXPORT TextEdit& TextEdit::ReplaceSelection(const wchar_t* theText)
        {
            if(theText && theText[0])
            {
                SendMessage(UINT(EM_REPLACESEL),FALSE,LPARAM(theText));
            }
            else
            {
                SendMessage(UINT(EM_REPLACESEL),FALSE,LPARAM(L""));
            }
            return *this;
        }
        HWIN_EXPORT TextEdit& TextEdit::Append(const String& theText)
        {
            Range currentSelection = Selection();
            int endOfText = TextLength();
            Range endSelection(endOfText,endOfText);
            SetSelection(endSelection);
            ReplaceSelection(theText);
            SetSelection(currentSelection);
            return *this;
        }


        HWIN_EXPORT TextEdit& TextEdit::Append(const wchar_t* theText)
        {
            if(theText && theText[0])
            {
                String s(theText);
                Append(s);
            }
            return *this;
        }



        // --------------------------------------------------------------------
        // MemoEdit
        // --------------------------------------------------------------------
        HWIN_EXPORT MemoEdit::MemoEdit( )
            : Base( )
        {
            
        }


        HWIN_EXPORT DWORD MemoEdit::GetStyle() const
        {
            return Base::GetStyle() | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL;
        }

        HWIN_EXPORT int MemoEdit::FirstVisibleLine() const
        {
            LRESULT messageResult = SendMessage(EM_GETFIRSTVISIBLELINE);
            return int(messageResult);
        }

        HWIN_EXPORT MemoEdit& MemoEdit::AppendLine(const String& theText)
        {
            auto length = theText.length();
            if(length)
            {
                String text(L"\r\n",2,theText.c_str(),length);
                Append(text);
            }
            return *this;
        }

        HWIN_EXPORT MemoEdit& MemoEdit::AppendLine(const wchar_t* theText)
        {
            if(theText && theText[0])
            {
                auto len = wcslen(theText);
                String s(L"\r\n",2,theText,len);
                Append(s);
            }
            return *this;
        }


        // --------------------------------------------------------------------
        // HotKey
        // --------------------------------------------------------------------
        class HotKeyWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT HotKeyWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT HotKeyWindowClass::windowClassName = String(L"HarlinnWindowsHotKeyWindowClassName");

        typedef SuperClassMessageDispatcher<HotKey> HotKeyMessageDispatcher;
        WNDPROC HotKeyMessageDispatcher::ControlProcedure;

        HWIN_EXPORT HotKeyWindowClass::HotKeyWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(existingClass)
        {
            HotKeyMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = HotKeyMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }


        HWIN_EXPORT HotKey::HotKey( )
            : Base()
        {}
        HWIN_EXPORT std::shared_ptr<WindowClass> HotKey::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(HotKeyWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::hotkey_class_name);
                auto newWindowClass = std::make_shared<HotKeyWindowClass>(windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }
        HWIN_EXPORT DWORD HotKey::GetStyle() const
        {
            DWORD result = Base::GetStyle();
            return result;
        }



        // --------------------------------------------------------------------
        // ScrollBar
        // --------------------------------------------------------------------
        class ScrollBarWindowClass : public WindowClass
        {
        public:
            typedef WindowClass Base;
            static String HWIN_EXPORT windowClassName;
            HWIN_EXPORT ScrollBarWindowClass(std::shared_ptr<WindowClass> existingClass);
        };

        String HWIN_EXPORT ScrollBarWindowClass::windowClassName = String(L"HarlinnWindowsScrollBarWindowClassName");

        typedef SuperClassMessageDispatcher<ScrollBar> ScrollBarMessageDispatcher;
        WNDPROC ScrollBarMessageDispatcher::ControlProcedure;

        HWIN_EXPORT ScrollBarWindowClass::ScrollBarWindowClass(std::shared_ptr<WindowClass> existingClass)
            : Base(*existingClass)
        {
            ScrollBarMessageDispatcher::ControlProcedure = existingClass->GetProcedure();
            SetName(windowClassName);
            WNDPROC procedure = ScrollBarMessageDispatcher::WndProc;
            SetProcedure(procedure);
        }

        HWIN_EXPORT ScrollBar::ScrollBar( )
            : Base( )
        {
            
        }

        HWIN_EXPORT std::shared_ptr<WindowClass> ScrollBar::GetWindowClass() const
        {
            auto windowClass = Application::GetWindowClass(ScrollBarWindowClass::windowClassName);
            if(!windowClass)
            {
                auto windowsWindowClass = Application::GetWindowClass(WindowClass::scrollbar_class_name);
                auto newWindowClass = std::make_shared<ScrollBarWindowClass> (windowsWindowClass);
                newWindowClass->Register();
                return newWindowClass;
            }
            return windowClass;
        }

        HWIN_EXPORT DWORD ScrollBar::GetStyle() const
        {
            return Base::GetStyle();
        }


        // --------------------------------------------------------------------
        // HScrollBar
        // --------------------------------------------------------------------
        HWIN_EXPORT HScrollBar::HScrollBar( )
            : Base( )
        {

        }

        HWIN_EXPORT DWORD HScrollBar::GetStyle() const
        {
            return Base::GetStyle();
        }

        // --------------------------------------------------------------------
        // VScrollBar
        // --------------------------------------------------------------------
        HWIN_EXPORT VScrollBar::VScrollBar( )
            : Base( )
        {

        }

        HWIN_EXPORT DWORD VScrollBar::GetStyle() const
        {
            return Base::GetStyle();
        }

        // --------------------------------------------------------------------
        // Timer::TimerControl
        // --------------------------------------------------------------------
        UINT_PTR Timer::TimerControl::TimerID = 1;
        HWIN_EXPORT Timer::TimerControl::TimerControl(const std::shared_ptr<Timer> theTimer)
            : Base(),timer(theTimer),timerId(0)
        {
            SetVisible(false);
            SetEnabled(false);
            SetTabStop(false);
        }


        HWIN_EXPORT void Timer::TimerControl::HandleMessage(Message& message)
        {
            Base::HandleMessage(message);
            if(message.handled == false)
            {
                if((message.message == WM_TIMER) && (message.wParam == timerId))
                {
                    std::shared_ptr<Timer> t = timer.lock();
                    if(t)
                    {
                        t->DoOnTick();
                    }
                }
                else if(message.message == WM_CLOSE)
                {
                    StopTimer();
                }
            }
        }

        HWIN_EXPORT HWND Timer::TimerControl::CreateHandle( )
        {
            auto windowClass = this->GetWindowClass();
            HWND result = NULL;
            if(windowClass)
            {
                const String& className = windowClass->GetName();
                if(className.length())
                {
                    HWND hWndParent = HWND_MESSAGE;
                    result = ::CreateWindowExW(this->GetStyleEx(),
                        className.c_str(),
                        nullptr,this->GetStyle(),
                        0, 0, 0, 0, 
                        hWndParent,0,0,(LPVOID)this);
                    if(!result)
                    {
                        ThrowLastOSError();
                    }
                }
            }
            return result;
        }

        HWIN_EXPORT DWORD Timer::TimerControl::GetStyle() const
        {
            return Base::GetStyle();
        }

        HWIN_EXPORT void Timer::TimerControl::StopTimer()
        {
            if(IsHandleCreated())
            {
                if(KillTimer(GetSafeHandle(),timerId) == FALSE)
                {
                    ThrowLastOSError();
                }
            }
        }

        HWIN_EXPORT void Timer::TimerControl::StartTimer()
        {
            std::shared_ptr<Timer> t = timer.lock();
            if(t)
            {
                UINT period = UINT(t->interval.TotalMilliseconds());
                timerId = SetTimer(GetSafeHandle(),TimerID++,period,nullptr);
            }
        }



        HWIN_EXPORT void Timer::TimerControl::DoBeforeHandleDestroy( )
        {
            StopTimer();
            Base::DoBeforeHandleDestroy( );
            
        }


        // --------------------------------------------------------------------
        // Timer
        // --------------------------------------------------------------------
        HWIN_EXPORT Timer::Timer()
            : Base(),
              interval(TimeSpan::FromMilliseconds(100)),
              enabled(false)
        {}


        HWIN_EXPORT TimeSpan Timer::Interval() const
        {
            return interval;
        }
        HWIN_EXPORT Timer& Timer::SetInterval(TimeSpan& theInterval)
        {
            if(interval != theInterval)
            {
                interval = theInterval;
                if(timerControl)
                {
                    timerControl->StopTimer();
                    timerControl->StartTimer();
                }
            }
            return *this;
        }


        HWIN_EXPORT bool Timer::Enabled() const
        {
            return enabled;
        }
        HWIN_EXPORT Timer& Timer::SetEnabled(bool theValue)
        {
            if(enabled != theValue)
            {
                enabled = theValue;
                if(enabled)
                {
                    auto self = As<Timer>();
                    timerControl = std::make_shared<TimerControl>(self);
                    timerControl->StartTimer();
                }
                else if(timerControl)
                {
                    timerControl = std::shared_ptr<TimerControl>();
                }
            }
            return *this;
        }


        HWIN_EXPORT void Timer::DoOnTick()
        {
            OnTick(this);
        }



    }
}

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
Architect Sea Surveillance AS
Norway Norway
Chief Architect - Sea Surveillance AS.

Specializing in integrated operations and high performance computing solutions.

I’ve been fooling around with computers since the early eighties, I’ve even done work on CP/M and MP/M.

Wrote my first “real” program on a BBC micro model B based on a series in a magazine at that time. It was fun and I got hooked on this thing called programming ...

A few Highlights:

  • High performance application server development
  • Model Driven Architecture and Code generators
  • Real-Time Distributed Solutions
  • C, C++, C#, Java, TSQL, PL/SQL, Delphi, ActionScript, Perl, Rexx
  • Microsoft SQL Server, Oracle RDBMS, IBM DB2, PostGreSQL
  • AMQP, Apache qpid, RabbitMQ, Microsoft Message Queuing, IBM WebSphereMQ, Oracle TuxidoMQ
  • Oracle WebLogic, IBM WebSphere
  • Corba, COM, DCE, WCF
  • AspenTech InfoPlus.21(IP21), OsiSoft PI


More information about what I do for a living can be found at: harlinn.com or LinkedIn

You can contact me at espen@harlinn.no

Comments and Discussions