/*
 ============================================================================
 xoblite -> an alternative shell based on Blackbox for Windows
 Copyright © 2002-2005 Karl-Henrik Henriksson [qwilk]
 Copyright © 2001-2004 The Blackbox for Windows Development Team
 http://xoblite.net/ - #bb4win on irc.freenode.net
 ============================================================================

  Blackbox for Windows is free software, released under the
  GNU General Public License (GPL version 2 or later), with an extension
  that allows linking of proprietary modules under a controlled interface.
  What this means is that plugins etc. are allowed to be released
  under any license the author wishes. Please note, however, that the
  original Blackbox gradient math code used in Blackbox for Windows
  is available under the BSD license.

  http://www.fsf.org/licenses/gpl.html
  http://www.fsf.org/licenses/gpl-faq.html#LinkingOverControlledInterface
  http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  For additional license information, please read the included license.html

 ============================================================================
*/

#include "Desk.h" 

const char szDesktopName[] = "DesktopBackgroundClass";

int HeightList[MAX_LINE_LENGTH] = {NULL};
ATOM WindowTypeList[MAX_LINE_LENGTH] = {NULL};

extern Settings *pSettings;
extern MenuMaker *pMenuMaker;
extern Desk *pDesk;
extern Toolbar *pToolbar;
extern Systembar *pSystembar;
extern PluginManager *pPluginManager;

HINSTANCE deskInstance = NULL;
ATOM deskrc;
int ScreenWidth, ScreenHeight;
int ScreenTop, ScreenLeft;

//===========================================================================

#ifndef SPI_SETACTIVEWINDOWTRACKING 
#define SPI_SETACTIVEWINDOWTRACKING             0x1001 
#endif 
#ifndef SPI_SETACTIVEWNDTRKZORDER 
#define SPI_SETACTIVEWNDTRKZORDER               0x100D 
#endif 
#ifndef SPI_SETACTIVEWNDTRKTIMEOUT 
#define SPI_SETACTIVEWNDTRKTIMEOUT              0x2003 
#endif 

//BOOL activeWindowTracking;
//BOOL activeWndTrkZOrder;
//DWORD activeWndTrkTimeout;

//===========================================================================

Desk::Desk(HINSTANCE hMainInstance)
{
        // Store old settings... (i.e. Explorer defaults)
//      SystemParametersInfo(SPI_GETACTIVEWNDTRKTIMEOUT, 0, (PVOID)activeWndTrkTimeout, 0);
//      SystemParametersInfo(SPI_GETACTIVEWINDOWTRACKING, 0, (PVOID)activeWindowTracking, 0);
//      SystemParametersInfo(SPI_GETACTIVEWNDTRKZORDER, 0, (PVOID)activeWndTrkZOrder, 0);

        // Apply xoblite settings defined in blackbox.rc...
        SystemParametersInfo(SPI_SETACTIVEWNDTRKTIMEOUT, 0, (PVOID)pSettings->autoRaiseDelay, SPIF_SENDCHANGE);
        if (!stricmp(pSettings->focusModel, "ClickToFocus"))
        {
                SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)false, SPIF_SENDCHANGE);
                SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)false, SPIF_SENDCHANGE);
        }
        else if (!stricmp(pSettings->focusModel, "AutoRaiseSloppyFocus"))
        {
                SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)true, SPIF_SENDCHANGE);
                SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)true, SPIF_SENDCHANGE);
        }
        else if (!stricmp(pSettings->focusModel, "SloppyFocus"))
        {
                SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)true, SPIF_SENDCHANGE);
                SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)false, SPIF_SENDCHANGE);
        }

        createDesktop(hMainInstance);
}

//===========================================================================

Desk::~Desk()
{
        // Restore old settings... (i.e. Explorer defaults)
//      SystemParametersInfo(SPI_SETACTIVEWNDTRKTIMEOUT, 0, (PVOID)activeWndTrkTimeout, SPIF_SENDCHANGE);
//      SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)activeWindowTracking, SPIF_SENDCHANGE);
//      SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)activeWndTrkZOrder, SPIF_SENDCHANGE);
        destroyDesktop();
}

//===========================================================================

bool Desk::createDesktop(HINSTANCE hInstance)
{
        deskInstance = hInstance;
        WNDCLASS wc;
        ZeroMemory(&wc, sizeof(wc));
        wc.hInstance = deskInstance;
        wc.lpfnWndProc = DesktopWndProc;
        wc.lpszClassName = szDesktopName;
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        deskrc = RegisterClass(&wc);
        if (!deskrc)
        {
                MessageBox(0, "Error registering desktop class", szDesktopName, MB_OK);
                Log("Could not register desktop class", NULL);
                return false;
        }

        //====================

        if (pSettings->usingWin2kXP)
        {
                ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
                ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
                ScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN);
                ScreenTop = GetSystemMetrics(SM_YVIRTUALSCREEN);
        }
        else
        {
                ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
                ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
                ScreenLeft = 0;
                ScreenTop = 0;
        }

        hDesktopWnd = CreateWindowEx(
                WS_EX_TOOLWINDOW,
                szDesktopName,
                NULL,
                WS_POPUP,
//              0,0,
                ScreenLeft,
                ScreenTop,
                ScreenWidth,
                ScreenHeight,
                NULL,
                NULL,
                deskInstance,
                0);

        if (!hDesktopWnd)
        {
                UnregisterClass(szDesktopName, deskInstance); // unregister window class
                MessageBox(0, "Error creating desktop window", szDesktopName, MB_OK);
                Log("Could not create desktop window", NULL);
                return false;
        }

        //====================

        // Make the desktop window sticky...
        MakeSticky(hDesktopWnd);
        // Set window to accept drag'n'drop...
        DragAcceptFiles(hDesktopWnd, true);
//      SetWindowPos(hDesktopWnd, HWND_BOTTOM, 0, 0, ScreenWidth, ScreenHeight, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW/* | SWP_NOSENDCHANGING*/);
        SetWindowPos(hDesktopWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSENDCHANGING);
        int msgs[] = { BB_WINDOWSHADE, BB_WINDOWLOWER, BB_WINDOWRAISE, BB_WINDOWGROWHEIGHT, BB_WINDOWGROWWIDTH, 0 };
        SendMessage(GetBBWnd(), BB_REGISTERMESSAGE, (WPARAM)hDesktopWnd, (LPARAM)msgs);

        //##### Now handled by Toolbar::UpdateDesktopArea() #####
        //if (pSettings->fullMaximization)
        //{
        //      RECT r = {0, 0, ScreenWidth, ScreenHeight};
        //      SystemParametersInfo(SPI_SETWORKAREA, 0, (PVOID)&r, SPIF_SENDCHANGE);
        //}

        return true;
}

//===========================================================================

void Desk::destroyDesktop()
{
        int msgs[] = { BB_WINDOWSHADE, BB_WINDOWLOWER, BB_WINDOWRAISE, BB_WINDOWGROWHEIGHT, BB_WINDOWGROWWIDTH, 0 };
        SendMessage(GetBBWnd(), BB_UNREGISTERMESSAGE, (WPARAM)hDesktopWnd, (LPARAM)msgs);
        DestroyWindow(hDesktopWnd); // delete our window
        UnregisterClass(szDesktopName, deskInstance); // unregister window class
}

//===========================================================================

LRESULT CALLBACK DesktopWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        switch (uMsg)
        {
                //====================

                case WM_CLOSE:
                        return 0;

                //====================

                case WM_KEYDOWN:
                {
                        if (wParam == SC_CLOSE)
                        {
                                PostMessage(GetBBWnd(), BB_SHUTDOWN, 0, 0);
                                return 0;
                        }
                        else return DefWindowProc(hWnd, uMsg, wParam, lParam);
                }
                break;

                //====================

                case WM_LBUTTONUP:
                {
                        if (pMenuMaker)
                        {
                                // First we set focus to the toolbar to prevent
                                // the focus from going back to the previous task
                                // after the menu is closed...
                                if (pSettings->followActive) SetForegroundWindow(pToolbar->hToolbarWnd);

                                pMenuMaker->Hide();
                        }
                }
                break;

                case WM_LBUTTONDOWN: { } break;

                //====================

                case WM_RBUTTONUP:
                {
                        // Right click key modifier actions for people with a 2 button mouse...
                        if (GetAsyncKeyState(VK_MENU) & 0x8000)
                        {
                                if (GetAsyncKeyState(VK_SHIFT) & 0x8000) // Note: Alt+Shift+RightClick
                                {
                                        if (pSettings->midclickStylesMenu) SendMessage(GetBBWnd(), BB_MENU, 1, 0); // Workspaces menu
                                        else SendMessage(GetBBWnd(), BB_MENU, 6, 0); // Themes menu
                                }
                                else
                                {
                                        if (pSettings->midclickStylesMenu) SendMessage(GetBBWnd(), BB_MENU, 5, 0); // Styles menu
                                        else SendMessage(GetBBWnd(), BB_MENU, 1, 0); // Workspaces menu
                                }
                        }
                        else if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
                        {
                                if (pSettings->midclickStylesMenu) SendMessage(GetBBWnd(), BB_MENU, 6, 0); // Themes menu
                                else SendMessage(GetBBWnd(), BB_MENU, 5, 0); // Styles menu
                        }
                        else if (GetAsyncKeyState(VK_CONTROL) & 0x8000) BBExecute(GetDesktopWindow(), NULL, "control.exe", "desk.cpl,,3", NULL, SW_SHOWNORMAL, false);
                        else SendMessage(GetBBWnd(), BB_MENU, 0, 0);
                }
                break;

                case WM_RBUTTONDOWN: { } break;

                //====================

                case WM_MBUTTONUP:
                {
                        if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
                        {
                                 // Is ctrl+shift held down? If so, toggle the slit shown/hidden...
                                if (GetAsyncKeyState(VK_SHIFT) & 0x8000) PostMessage(GetBBWnd(), BB_TOGGLESLIT, 0, 0);
                                 // ...and if just ctrl is held down, we toggle the plugins shown/hidden...
                                else PostMessage(GetBBWnd(), BB_TOGGLEPLUGINS, 0, 0);
                        }
                        else if (pSettings->midclickStylesMenu)
                        {
                                if (GetAsyncKeyState(VK_SHIFT) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 1, 0); // Workspaces menu
                                else if (GetAsyncKeyState(VK_MENU) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 6, 0); // Themes menu
                                else SendMessage(GetBBWnd(), BB_MENU, 5, 0); // Styles menu
                        }
                        else
                        {
                                if (GetAsyncKeyState(VK_SHIFT) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 6, 0); // Themes menu
                                else if (GetAsyncKeyState(VK_MENU) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 5, 0); // Styles menu
                                else SendMessage(GetBBWnd(), BB_MENU, 1, 0); // Workspaces menu
                        }
                }
                break;

                case WM_MBUTTONDOWN: { } break;

                //====================

                case WM_XBUTTONDOWN:
                {
                        if (HIWORD(wParam) == XBUTTON1)
                        {
                                BBExecute(GetDesktopWindow(), NULL, "control.exe", "desk.cpl,,3", NULL, SW_SHOWNORMAL, false);
                                // if (GetAsyncKeyState(VK_MENU) & 0x8000) SendMessage(GetBBWnd(), BB_BROADCAST, 0, (LPARAM)"@xoblite CheckForUpdates");
                                // else BBExecute(GetDesktopWindow(), NULL, "control.exe", "desk.cpl,,3", NULL, SW_SHOWNORMAL, false);
                        }
                        else if (HIWORD(wParam) == XBUTTON2) BBExecute(GetDesktopWindow(), NULL, "control.exe", "mmsys.cpl", NULL, SW_SHOWNORMAL, false);
                }
                break;

                case WM_XBUTTONUP: { } break;

                //====================
/*
                case WM_MOUSEWHEEL:
                {
                        POINT p;
                        GetCursorPos(&p);
                        HWND pluginWnd = ChildWindowFromPoint(pDesk->hDesktopWnd, p);
                        PostMessage(pluginWnd, WM_MOUSEWHEEL, (WPARAM)wParam, (LPARAM)lParam);
                }
                break;
*/
                //====================

                case WM_SYSCOMMAND:
                {
                        if (wParam == SC_CLOSE)
                        {
                                PostMessage(GetBBWnd(), BB_SHUTDOWN, 0, 0);
                                return 0;
                        }
                }
                break;

                //====================

                case WM_PAINT:
                {
                        PAINTSTRUCT ps;
                        HDC hDC = BeginPaint(hWnd, &ps);
                        PaintDesktop(hDC);
                        EndPaint(hWnd, &ps);
                }
                return 0;

                //====================

                case WM_MOUSEACTIVATE:
                {
                        return MA_NOACTIVATE;
                }

                //====================
        
                case WM_ACTIVATE:
                {
                        if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
                                SetActiveWindow(hWnd);
                        return 0;
                }

                //====================
/*
                case WM_MOUSEMOVE:
                {
                        if (!GetCursor()) SetCursor(LoadCursor(NULL, IDC_ARROW));
                }
                return 0;
*/
                //====================

                case WM_QUERYENDSESSION:
                case WM_ENDSESSION:
                        return SendMessage(hWnd, uMsg, wParam, lParam);

                //====================

                case WM_ERASEBKGND:
                {
                        PaintDesktop((HDC)(wParam));
                        return true;
                }

                //====================

                case WM_DISPLAYCHANGE:
                {
                        // Resize desktop window on screen resolution change...
                        if (pSettings->usingWin2kXP)
                        {
                                ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
                                ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
                                ScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN);
                                ScreenTop = GetSystemMetrics(SM_YVIRTUALSCREEN);
                        }
                        else
                        {
                                ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
                                ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
                                ScreenLeft = 0;
                                ScreenTop = 0;
                        }

                        MoveWindow(hWnd, ScreenLeft, ScreenTop, ScreenWidth, ScreenHeight, true);
                        SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, ScreenWidth, ScreenHeight, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
                }
                break;

                //====================

                case WM_WINDOWPOSCHANGING:
                {
                        SetWindowPos(hWnd, HWND_BOTTOM, ScreenLeft, ScreenTop, ScreenWidth, ScreenHeight, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
                        break;
                }

                //====================

                case WM_NCPAINT: // Another security precausion... :)
                {
                        if (!wParam) SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
                        return 0;
                }

                //====================

                case BB_WINDOWSHADE:
                        pDesk->ShadeWindow();
                break;
                case BB_WINDOWGROWHEIGHT:
                        pDesk->GrowWindowHeight();
                break;
                case BB_WINDOWGROWWIDTH:
                        pDesk->GrowWindowWidth();
                break;
                case BB_WINDOWLOWER:
                        pDesk->LowerWindow();
                break;
                case BB_WINDOWRAISE:
                        pDesk->RaiseWindow();
                break;

                //====================

                case WM_DROPFILES:
                {
                        static TCHAR filename[MAX_LINE_LENGTH];
                        DragQueryFile((HDROP)wParam, 0, filename, sizeof(filename));

                        char path[MAX_LINE_LENGTH];
                        strcpy(path, filename);
                        if (path[0] == '\"') StrRemoveEncap(path);

                        // Relay drag to desktop information to interrested plugins...
                        SendMessage(GetBBWnd(), BB_DRAGTODESKTOP, 0, (LPARAM)path);

                        // We only need to check the last 4 characters to get the extension...
                        int pointer = strlen(path) - 4;

                        if (!stricmp(&path[pointer], ".jpg")
                                || !stricmp(&path[pointer], ".png")
                                || !stricmp(&path[pointer], ".bmp")
                                || !stricmp(&path[pointer], ".gif")
                                || !stricmp(&path[pointer], ".tif")
                                || !stricmp(&path[pointer], "jpeg"))
                        {
                                // If the file is a JPEG, PNG, BMP, TIF or GIF
                                // we use bsetbg to set it as wallpaper...
                                // (please note that we leave the menu open)

                                char arguments[MAX_LINE_LENGTH];

                                if (GetAsyncKeyState(VK_CONTROL) & 0x8000) // Is the control key held down? -> center mode
                                        strcpy(arguments, "-center ");
                                else if (GetAsyncKeyState(VK_SHIFT) & 0x8000) // Is the shift key held down? -> stretch mode
                                        strcpy(arguments, "-full ");
                                else strcpy(arguments, "-tile "); // Default -> tile mode

                                if (strchr(path, ' '))
                                {
                                        // Add quotes if the path contains spaces...
                                        strcat(arguments, "\"");
                                        strcat(arguments, path);
                                        strcat(arguments, "\"");
                                }
                                else strcat(arguments, path);

                                // bsetbg.exe should be located in the same folder as
                                // xoblite.exe, so we use that as the working directory...
                                char bbpath[MAX_LINE_LENGTH];
                                GetBlackboxPath(bbpath, sizeof(bbpath));
                                BBExecute(GetDesktopWindow(), NULL, "bsetbg.exe", arguments, bbpath, SW_SHOWNORMAL, false);
                        }
                        else if (!stricmp(&path[pointer], ".dll"))
                        {
                                // If the file is a DLL we try to load it as a plugin,
                                // passing the desktop HWND to it for docking purposes...

                                char deskPlugPath[MAX_PATH];
                                strcpy(deskPlugPath, ">");
                                strcat(deskPlugPath, path);
                                pPluginManager->loadPlugin(deskPlugPath);
                        }
                }
                break;

                //====================

                case DOCK_ADD:
                {
                        pDesk->vDeskWindows.push_back((HWND) lParam);

                        if(IsWindow((HWND)lParam))
                        {
                                SetWindowLong((HWND)lParam, GWL_STYLE, (GetWindowLong((HWND)lParam, GWL_STYLE) & ~WS_POPUP) | WS_CHILD);
                                SetParent((HWND)lParam, pDesk->hDesktopWnd);
                        }
                }
                break;

                //====================

                case DOCK_REMOVE:
                {
                        vector<HWND>::iterator hwndDeskPlugin;

                        for (hwndDeskPlugin = pDesk->vDeskWindows.begin(); hwndDeskPlugin != pDesk->vDeskWindows.end(); hwndDeskPlugin++)
                        {
                                if (*hwndDeskPlugin == (HWND)lParam)
                                {
                                        pDesk->vDeskWindows.erase(hwndDeskPlugin);
                                        break;
                                }
                        }

                        if (IsWindow((HWND)lParam))
                        {
                                SetWindowLong((HWND)lParam, GWL_STYLE, (GetWindowLong((HWND)lParam, GWL_STYLE) & ~WS_CHILD) | WS_POPUP);
                                SetParent((HWND)lParam, NULL);
                        }
                }
                break;

                //====================

                default:
                        return DefWindowProc(hWnd, uMsg, wParam, lParam);

                //====================
        }
        return 0;
}

//===========================================================================

void Desk::ShadeWindow()
{
        int i, TitleBarHeight = GetSystemMetrics(SM_CYMIN);
        RECT r;
        bool IsUnshaded;
        HWND currentwnd = pSystembar->GetCurrentWindow();
        BOOL IsMaximized = IsZoomed(currentwnd);

        GetWindowRect(currentwnd, &r);

        IsUnshaded = (r.bottom - r.top > TitleBarHeight);

        i = IsFlaggedShaded(currentwnd);

        if (IsMaximized)
        {
                if (IsUnshaded)
                        WinShade(currentwnd, -1, IsMaximized);
                else
                        WinUnshade(currentwnd, -1, IsMaximized);
        }
        else
        {
                if (i != -1) // Was the window found in our list?
                {
                        if (IsUnshaded) // Shade the window...
                        {
                                RemoveProp(currentwnd,"BBNormalHeight");
                                WinShade(currentwnd, -1, IsMaximized);
                        }
                        else // Unshade the window...
                        {
                                WinUnshade(currentwnd, i, IsMaximized);
                        }     
                }
                else
                {
                        WinShade(currentwnd, i, IsMaximized);
                }
        }
}

//====================

int Desk::IsFlaggedShaded(HWND hwnd)
{
        // Returns true if a window has our "BBNormalHeight" property.
        return (GetProp(hwnd,"BBNormalHeight") != NULL);
}

//===========================================================================

// Restore window to original height
void Desk::WinUnshade(HWND MoveHwnd, int ListIndex, BOOL Maximized)
{
        int i = ListIndex;
        RECT r;
        int height;

        SetForegroundWindow(MoveHwnd);

        if (i == -1 && !Maximized) return;

        if (Maximized)
        {
                // This is a maximized window...
                RECT WorkArea;
                SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&WorkArea, SPIF_SENDCHANGE);
                height = WorkArea.bottom - WorkArea.top;
        }
        else
        {
                height = (long)GetProp(MoveHwnd,"BBNormalHeight");
                RemoveProp(MoveHwnd,"BBNormalHeight");
        }

        if (height == 0) return;

        GetWindowRect(MoveHwnd, &r);    
        MoveWindow(MoveHwnd, r.left, r.top, r.right-r.left, height, TRUE);
        InvalidateRect(MoveHwnd, NULL, false);
}

//===========================================================================

// Shrink window to titlebar, remembering original height
void Desk::WinShade(HWND MoveHwnd, int ListIndex, BOOL Maximized)
{
        int i = ListIndex;
        RECT r;

        SetForegroundWindow(MoveHwnd);

        if (i != -1) return;

        GetWindowRect(MoveHwnd, &r);    
        if (!Maximized)
                SetProp(MoveHwnd,"BBNormalHeight",(HANDLE)(r.bottom - r.top));

        SetWindowPos(MoveHwnd, HWND_TOP, 
                r.left, r.top, 
                r.right - r.left, 
                GetSystemMetrics(SM_CYMIN),     SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);

        return;
}

//===========================================================================

// Grow window to maximum height or just downwards
void Desk::GrowWindowHeight()
{
        HWND currentwnd = pSystembar->GetCurrentWindow();
        RECT r, WorkArea;
        GetWindowRect(currentwnd, &r);  
        SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&WorkArea, SPIF_SENDCHANGE);
        MoveWindow(currentwnd, r.left, 0, r.right-r.left, WorkArea.bottom-WorkArea.top, TRUE);
        InvalidateRect(currentwnd, NULL, false);
        SetForegroundWindow(currentwnd);
}

//====================

void Desk::GrowWindowWidth()
{
        HWND currentwnd = pSystembar->GetCurrentWindow();
        RECT r, WorkArea;
        GetWindowRect(currentwnd, &r);  
        SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&WorkArea, SPIF_SENDCHANGE);
        MoveWindow(currentwnd, 0, r.top, WorkArea.right-WorkArea.left, r.bottom-r.top, TRUE);
        GetWindowRect(currentwnd, &r);
        SetForegroundWindow(currentwnd);
}

//====================

void Desk::LowerWindow()
{
        HWND currentwnd = pSystembar->GetCurrentWindow();
        HWND bbwnd = GetBBWnd();

        // First we fetch the bottom window...
        HWND bottomwnd = GetWindow(bbwnd, GW_HWNDLAST);
        HWND hProgManWnd = FindWindow("Progman", "Program Manager");
        if (bottomwnd == hProgManWnd) bottomwnd = GetWindow(bottomwnd, GW_HWNDPREV);
        while (!(IsWindowVisible(bottomwnd)) | IsIconic(bottomwnd) | !(GetWindowTextLength(bottomwnd)))
        {
                bottomwnd = GetWindow(bottomwnd, GW_HWNDPREV);
                if (bottomwnd == hProgManWnd) bottomwnd = GetWindow(bottomwnd, GW_HWNDPREV);
        }
        // ...the we put the current window behind that...
        if (IsWindow(currentwnd) && IsWindow(bottomwnd))
                SetWindowPos(currentwnd, bottomwnd, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
}

//====================

void Desk::RaiseWindow()
{
        HWND currentwnd = pSystembar->GetCurrentWindow();
        // Raise the current window to the top...
        SetWindowPos(currentwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
}


//===========================================================================





syntax highlighting by

w e b c p p
web c plus plus