// Draw the System Icon
void cef_dark_window::DoDrawSystemMenuIcon(HDC hdc)
{
    if (mWindowIcon == 0) {
        // We haven't cached the icon yet so figure out 
        //  which one we need.

        // First try to load the small icon 
        mWindowIcon = (HICON)SendMessage(WM_GETICON, ICON_SMALL, 0);

        // Otherwise try to use the big icon
        if (!mWindowIcon) 
            mWindowIcon = (HICON)SendMessage(WM_GETICON, ICON_BIG, 0);

        // If that doesn't work check the window class for an icon

        // Start with the small
        if (!mWindowIcon)
            mWindowIcon = reinterpret_cast<HICON>(GetClassLongPtr(GCLP_HICONSM));
        
        // Then try to load the big icon
        if (!mWindowIcon)
            mWindowIcon = reinterpret_cast<HICON>(GetClassLongPtr(GCLP_HICON));

        // Otherwise we need an icon, so just use the standard Windows default 
        //  application Icon which may very between versions 
        if (!mWindowIcon) 
            mWindowIcon = ::LoadIcon(NULL, IDI_APPLICATION);
    }

    RECT rectIcon;
    ComputeWindowIconRect(rectIcon);
    ::DrawIconEx(hdc, rectIcon.left, rectIcon.top, mWindowIcon, ::RectWidth(rectIcon), ::RectHeight(rectIcon), 0, NULL, DI_NORMAL);
}
// Computes the Rect where the window caption is drawn in window coordinates
void cef_dark_aero_window::ComputeWindowCaptionRect(RECT& rect) const
{
	if (CanUseAeroGlass()) {
		RECT wr;
		GetWindowRect(&wr);

		rect.top = ::kWindowFrameSize;
		rect.bottom = rect.top + mNcMetrics.iCaptionHeight;

		RECT ir;
		ComputeWindowIconRect(ir);

		RECT mr;
		ComputeMinimizeButtonRect(mr);

		rect.left = ir.right + ::kWindowFrameSize;
		rect.right = mr.left - ::kWindowFrameSize;
	} else {
		cef_dark_window::ComputeWindowCaptionRect(rect);
	}
}
// Computes the Rect where the window caption is drawn in window coordinates
void cef_dark_window::ComputeWindowCaptionRect(RECT& rect)
{
    RECT wr;
    GetWindowRect(&wr);

    int top = mNcMetrics.iBorderWidth;

    if (IsZoomed()) {
        top = ::kWindowFrameZoomFactorCY;
    }

    rect.top = top;
    rect.bottom = rect.top + mNcMetrics.iCaptionHeight;

    RECT ir;
    ComputeWindowIconRect(ir);

    RECT mr;
    ComputeMinimizeButtonRect(mr);

    rect.left = ir.right + ::GetSystemMetrics (SM_CXFRAME);
    rect.right = mr.left - ::GetSystemMetrics (SM_CXFRAME);
}
// WindowProc handles dispatching of messages and routing back to the base class or to Windows
LRESULT cef_dark_aero_window::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    bool callDefWindowProc = true;

    switch (message) 
    {
    case WM_MEASUREITEM:
        if (HandleMeasureItem((LPMEASUREITEMSTRUCT)lParam))
            return 0L;
        break;
    case WM_DRAWITEM:
        if (HandleDrawItem((LPDRAWITEMSTRUCT)lParam))
            return 0L;
        break;
    case WM_SETICON:
        mWindowIcon = 0;
        {
            RECT rectIcon;
            ComputeWindowIconRect(rectIcon);
            InvalidateRect(&rectIcon);
        }
        break;
    }

    // First let the DesktopWindowManager handle the message and tell us if 
    //  we should pass the message to the default window proc
    LRESULT lr = DwpCustomFrameProc(message, wParam, lParam, &callDefWindowProc);

    switch(message) {
    case WM_SETTINGCHANGE:
        HandleSettingChange((UINT)wParam, (LPCWSTR)lParam);
        break;

    case WM_NCACTIVATE:
    case WM_ACTIVATE:
        if (mReady) {
            UpdateNonClientArea();
        }
        break;
    case WM_NCMOUSELEAVE:
        // NOTE: We want anyone else interested in this message
        //          to be notified. Otherwise the default implementation 
        //          may be in the wrong state
        HandleNcMouseLeave();
        break;
    case WM_NCMOUSEMOVE:
        {
            POINT pt;
            POINTSTOPOINT(pt, lParam);

            if (HandleNcMouseMove((UINT)wParam, &pt))
                return 0L;
        }
        break;
    case WM_NCLBUTTONDOWN:
        {
            POINT pt;
            POINTSTOPOINT(pt, lParam);
            if (HandleNcLeftButtonDown((UINT)wParam, &pt))
                return 0L;
        }
        break;
    case WM_NCLBUTTONUP:
        {
            POINT pt;
            POINTSTOPOINT(pt, lParam);
            if (HandleNcLeftButtonUp((UINT)wParam, &pt))
                return 0L;
        }
        break;
    }

    // call DefWindowProc?
    if (!callDefWindowProc) {
        return lr;
    }


    lr = cef_window::WindowProc(message, wParam, lParam);

    if (!mReady)
        return lr;

    switch (message)
    {
    case WM_GETMINMAXINFO:
        HandleGetMinMaxInfo((LPMINMAXINFO) lParam);
        break;
    case WM_SETTEXT:
    case WM_WINDOWPOSCHANGING:
    case WM_WINDOWPOSCHANGED:
    case WM_MOVE:
    case WM_SIZE:
    case WM_SIZING:
    case WM_EXITSIZEMOVE:
        UpdateNonClientArea();
        if (message == WM_WINDOWPOSCHANGED) 
        {
            RECT rect;
            ComputeMenuBarRect(rect);
            InvalidateRect(&rect, TRUE);
        }
        break;
    case WM_EXITMENULOOP:
        mMenuActiveIndex = -1;
        break;   
    case WM_ACTIVATEAPP:
        mIsActive = (BOOL)wParam;
        UpdateNonClientArea();
        break;
    }

    return lr;
}
// WM_NCHITTEST handler
int cef_dark_aero_window::HandleNcHitTest(LPPOINT ptHit)
{
    RECT rectWindow;
    GetWindowRect(&rectWindow);

    if (!::PtInRect(&rectWindow, *ptHit)) 
        return HTNOWHERE;
    
    RECT rectCaption;
    ComputeWindowCaptionRect(rectCaption);
    ClientToScreen(&rectCaption);

    if (::PtInRect(&rectCaption, *ptHit)) 
        return HTCAPTION;

    RECT rectCloseButton;
    ComputeCloseButtonRect(rectCloseButton);
    ClientToScreen(&rectCloseButton);

    if (::PtInRect(&rectCloseButton, *ptHit)) 
        return HTCLOSE;

    RECT rectMaximizeButton;
    ComputeMaximizeButtonRect(rectMaximizeButton);
    ClientToScreen(&rectMaximizeButton);

    if (::PtInRect(&rectMaximizeButton, *ptHit)) 
        return HTMAXBUTTON;

    RECT rectMinimizeButton;
    ComputeMinimizeButtonRect(rectMinimizeButton);
    ClientToScreen(&rectMinimizeButton);

    if (::PtInRect(&rectMinimizeButton, *ptHit)) 
        return HTMINBUTTON;

    RECT rectSysIcon;
    ComputeWindowIconRect(rectSysIcon);
    ClientToScreen(&rectSysIcon);

    if (::PtInRect(&rectSysIcon, *ptHit)) 
        return HTSYSMENU;

    if (!IsZoomed()) {

        // Left Border
        if (ptHit->x >= rectWindow.left && ptHit->x <= rectWindow.left + ::kWindowFrameSize)
        {
            // it's important that we know if the mouse is on a corner so that
            //    the right mouse cursor is displayed
            if (ptHit->y <= rectWindow.top + ::kWindowFrameSize)
                 return HTTOPLEFT;
 
            if (ptHit->y >= rectWindow.bottom - ::kWindowFrameSize)
                 return HTBOTTOMLEFT;
 
            return HTLEFT;
        }

        // Right Border
        if (ptHit->x <= rectWindow.right && ptHit->x >= rectWindow.right - ::kWindowFrameSize) 
        {
            // it's important that we know if the mouse is on a corner so that
            //    the right mouse cursor is displayed
            if (ptHit->y <= rectWindow.top + ::kWindowFrameSize)
                return HTTOPRIGHT;
 
            if (ptHit->y >= rectWindow.bottom - ::kWindowFrameSize)
                return HTBOTTOMRIGHT;
 
            return HTRIGHT;
        }

        // Top and Bottom Borders
        if (ptHit->y <= rectWindow.top + ::kWindowFrameSize) 
             return HTTOP;
             
        if (ptHit->y >= rectWindow.bottom - ::kWindowFrameSize)
             return HTBOTTOM;
    }

    RECT rectMenu;
    ComputeRequiredMenuRect(rectMenu);
    ClientToScreen(&rectMenu);

    if (::PtInRect(&rectMenu, *ptHit))
        return HTMENU;

    // If it's in the menu bar but not actually
    //  on a menu item, then return caption so 
    //  the window can be dragged from the dead space 
    ComputeMenuBarRect(rectMenu);
    ClientToScreen(&rectMenu);
    if (::PtInRect(&rectMenu, *ptHit))
        return HTCAPTION;

    // Aero requires that we return HTNOWHERE
    return HTNOWHERE;
}
// WM_NCHITTEST handler
int cef_dark_window::HandleNcHitTest(LPPOINT ptHit)
{
    RECT rectWindow;
    GetWindowRect(&rectWindow);

    if (!::PtInRect(&rectWindow, *ptHit)) 
        return HTNOWHERE;
    
    RECT rectClient;
    GetClientRect(&rectClient);
    ClientToScreen(&rectClient);

    if (::PtInRect(&rectClient, *ptHit)) 
        return HTCLIENT;

    RECT rectCaption;
    ComputeWindowCaptionRect(rectCaption);
    NonClientToScreen(&rectCaption);

    if (::PtInRect(&rectCaption, *ptHit)) 
        return HTCAPTION;

    RECT rectCloseButton;
    ComputeCloseButtonRect(rectCloseButton);
    NonClientToScreen(&rectCloseButton);

    if (::PtInRect(&rectCloseButton, *ptHit)) 
        return HTCLOSE;

    RECT rectMaximizeButton;
    ComputeMaximizeButtonRect(rectMaximizeButton);
    NonClientToScreen(&rectMaximizeButton);

    if (::PtInRect(&rectMaximizeButton, *ptHit)) 
        return HTMAXBUTTON;

    RECT rectMinimizeButton;
    ComputeMinimizeButtonRect(rectMinimizeButton);
    NonClientToScreen(&rectMinimizeButton);

    if (::PtInRect(&rectMinimizeButton, *ptHit)) 
        return HTMINBUTTON;

    RECT rectSysIcon;
    ComputeWindowIconRect(rectSysIcon);
    NonClientToScreen(&rectSysIcon);

    if (::PtInRect(&rectSysIcon, *ptHit)) 
        return HTSYSMENU;

    // Left Border
    if (ptHit->x >= rectWindow.left && ptHit->x <= rectWindow.left + ::GetSystemMetrics (SM_CYFRAME))
    {
        // it's important that we know if the mouse is on a corner so that
        //    the right mouse cursor is displayed
        if (ptHit->y <= rectWindow.top + ::GetSystemMetrics (SM_CYFRAME))
             return HTTOPLEFT;
 
        if (ptHit->y >= rectWindow.bottom - ::GetSystemMetrics (SM_CYFRAME))
             return HTBOTTOMLEFT;
 
        return HTLEFT;
    }

    // Right Border
    if (ptHit->x <= rectWindow.right && ptHit->x >= rectWindow.right - ::GetSystemMetrics (SM_CYFRAME)) 
    {
        // it's important that we know if the mouse is on a corner so that
        //    the right mouse cursor is displayed
        if (ptHit->y <= rectWindow.top + ::GetSystemMetrics (SM_CYFRAME))
            return HTTOPRIGHT;
 
        if (ptHit->y >= rectWindow.bottom - ::GetSystemMetrics (SM_CYFRAME))
            return HTBOTTOMRIGHT;
 
        return HTRIGHT;
    }

    // Top and Bottom Borders
    if (ptHit->y <= rectWindow.top + ::GetSystemMetrics (SM_CYFRAME)) 
         return HTTOP;
             
    if (ptHit->y >= rectWindow.bottom - ::GetSystemMetrics (SM_CYFRAME))
         return HTBOTTOM;

    // If it's not in the menu, it's in the caption
    RECT rectMenu;
    ComputeRequiredMenuRect(rectMenu);
    NonClientToScreen(&rectMenu);

    if (::PtInRect(&rectMenu, *ptHit))
        return HTMENU;

    return HTCAPTION;
}