desktop.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2003, 2004, 2005 Martin Fuchs
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 
00020  //
00021  // Explorer clone
00022  //
00023  // desktop.cpp
00024  //
00025  // Martin Fuchs, 09.08.2003
00026  //
00027 
00028 
00029 #include <precomp.h>
00030 
00031 #include "../resource.h"
00032 
00033 #include "../taskbar/desktopbar.h"
00034 #include "../taskbar/taskbar.h" // for PM_GET_LAST_ACTIVE
00035 
00036 
00037 static BOOL (WINAPI*SetShellWindow)(HWND);
00038 static BOOL (WINAPI*SetShellWindowEx)(HWND, HWND);
00039 
00040 
00041 #ifdef _USE_HDESK
00042 
00043 Desktop::Desktop(HDESK hdesktop/*, HWINSTA hwinsta*/)
00044  :  _hdesktop(hdesktop)
00045 //  _hwinsta(hwinsta)
00046 {
00047 }
00048 
00049 Desktop::~Desktop()
00050 {
00051     if (_hdesktop)
00052         CloseDesktop(_hdesktop);
00053 
00054 //  if (_hwinsta)
00055 //      CloseWindowStation(_hwinsta);
00056 
00057     if (_pThread.get()) {
00058         _pThread->Stop();
00059         _pThread.release();
00060     }
00061 }
00062 
00063 #endif
00064 
00065 
00066 Desktops::Desktops()
00067  :  _current_desktop(0)
00068 {
00069 }
00070 
00071 Desktops::~Desktops()
00072 {
00073      // show all hidden windows
00074     for(iterator it_dsk=begin(); it_dsk!=end(); ++it_dsk)
00075         for(WindowSet::iterator it=it_dsk->_windows.begin(); it!=it_dsk->_windows.end(); ++it)
00076             ShowWindowAsync(*it, SW_SHOW);
00077 }
00078 
00079 void Desktops::init()
00080 {
00081     resize(DESKTOP_COUNT);
00082 
00083 #ifdef _USE_HDESK
00084     DesktopPtr& desktop = (*this)[0];
00085 
00086     desktop = DesktopPtr(new Desktop(OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP)));
00087 #endif
00088 }
00089 
00090 #ifdef _USE_HDESK
00091 
00092 void Desktops::SwitchToDesktop(int idx)
00093 {
00094     if (_current_desktop == idx)
00095         return;
00096 
00097     DesktopPtr& desktop = (*this)[idx];
00098 
00099     DesktopThread* pThread = NULL;
00100 
00101     if (desktop.get()) {
00102         if (desktop->_hdesktop)
00103             if (!SwitchDesktop(desktop->_hdesktop))
00104                 return;
00105     } else {
00106         FmtString desktop_name(TEXT("Desktop %d"), idx);
00107 
00108         SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
00109 /*
00110         HWINSTA hwinsta = CreateWindowStation(TEXT("ExplorerWinStation"), 0, GENERIC_ALL, &saAttr);
00111 
00112         if (!SetProcessWindowStation(hwinsta))
00113             return;
00114 */
00115         HDESK hdesktop = CreateDesktop(desktop_name, NULL, NULL, 0, GENERIC_ALL, &saAttr);
00116         if (!hdesktop)
00117             return;
00118 
00119         desktop = DesktopPtr(new Desktop(hdesktop/*, hwinsta*/));
00120 
00121         pThread = new DesktopThread(*desktop);
00122     }
00123 
00124     _current_desktop = idx;
00125 
00126     if (pThread) {
00127         desktop->_pThread = DesktopThreadPtr(pThread);
00128         pThread->Start();
00129     }
00130 }
00131 
00132 int DesktopThread::Run()
00133 {
00134     if (!SetThreadDesktop(_desktop._hdesktop))
00135         return -1;
00136 
00137     HDESK hDesk_old = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
00138 
00139     if (!SwitchDesktop(_desktop._hdesktop))
00140         return -1;
00141 
00142     if (!_desktop._hwndDesktop)
00143         _desktop._hwndDesktop = DesktopWindow::Create();
00144 
00145     int ret = Window::MessageLoop();
00146 
00147     SwitchDesktop(hDesk_old);
00148 
00149     return ret;
00150 }
00151 
00152 #else // _USE_HDESK
00153 
00154 static BOOL CALLBACK SwitchDesktopEnumFct(HWND hwnd, LPARAM lparam)
00155 {
00156     WindowSet& windows = *(WindowSet*)lparam;
00157 
00158     if (hwnd!=g_Globals._hwndDesktopBar && hwnd!=g_Globals._hwndDesktop)
00159         if (IsWindowVisible(hwnd))
00160             windows.insert(hwnd);
00161 
00162     return TRUE;
00163 }
00164 
00165 void Desktops::SwitchToDesktop(int idx)
00166 {
00167     if (_current_desktop == idx)
00168         return;
00169 
00170     Desktop& old_desktop = (*this)[_current_desktop];
00171     WindowSet& windows = old_desktop._windows;
00172     Desktop& desktop = (*this)[idx];
00173 
00174     windows.clear();
00175 
00176      // collect window handles of all other desktops
00177     WindowSet other_wnds;
00178     for(const_iterator it1=begin(); it1!=end(); ++it1)
00179         for(WindowSet::const_iterator it2=it1->_windows.begin(); it2!=it1->_windows.end(); ++it2)
00180             other_wnds.insert(*it2);
00181 
00182      // save currently visible application windows
00183     EnumWindows(SwitchDesktopEnumFct, (LPARAM)&windows);
00184 
00185     old_desktop._hwndForeground = (HWND)SendMessage(g_Globals._hwndDesktopBar, PM_GET_LAST_ACTIVE, 0, 0);
00186 
00187      // hide all windows of the previous desktop
00188     for(WindowSet::iterator it=windows.begin(); it!=windows.end(); ++it)
00189         ShowWindowAsync(*it, SW_HIDE);
00190 
00191      // show all windows of the new desktop
00192     for(WindowSet::iterator it=desktop._windows.begin(); it!=desktop._windows.end(); ++it)
00193         ShowWindowAsync(*it, SW_SHOW);
00194 
00195     if (desktop._hwndForeground)
00196         SetForegroundWindow(desktop._hwndForeground);
00197 
00198      // remove the window handles of the other desktops from what we found on the previous desktop
00199     for(WindowSet::const_iterator it=other_wnds.begin(); it!=other_wnds.end(); ++it)
00200         windows.erase(*it);
00201 
00202      // We don't need to store the window handles of what's now visible the now current desktop.
00203     desktop._windows.clear();
00204 
00205     _current_desktop = idx;
00206 }
00207 
00208 #endif // _USE_HDESK
00209 
00210 
00211 static BOOL CALLBACK MinimizeDesktopEnumFct(HWND hwnd, LPARAM lparam)
00212 {
00213     list<MinimizeStruct>& minimized = *(list<MinimizeStruct>*)lparam;
00214 
00215     if (hwnd!=g_Globals._hwndDesktopBar && hwnd!=g_Globals._hwndDesktop)
00216         if (IsWindowVisible(hwnd) && !IsIconic(hwnd)) {
00217             RECT rect;
00218 
00219             if (GetWindowRect(hwnd,&rect))
00220                 if (rect.right>0 && rect.bottom>0 &&
00221                     rect.right>rect.left && rect.bottom>rect.top) {
00222                 minimized.push_back(MinimizeStruct(hwnd, GetWindowStyle(hwnd)));
00223                 ShowWindowAsync(hwnd, SW_MINIMIZE);
00224             }
00225         }
00226 
00227     return TRUE;
00228 }
00229 
00230  /// minimize/restore all windows on the desktop
00231 void Desktops::ToggleMinimize()
00232 {
00233     list<MinimizeStruct>& minimized = (*this)[_current_desktop]._minimized;
00234 
00235     if (minimized.empty()) {
00236         EnumWindows(MinimizeDesktopEnumFct, (LPARAM)&minimized);
00237     } else {
00238         for(list<MinimizeStruct>::const_iterator it=minimized.begin(); it!=minimized.end(); ++it)
00239             ShowWindowAsync(it->first, it->second&WS_MAXIMIZE? SW_MAXIMIZE: SW_RESTORE);
00240 
00241         minimized.clear();
00242     }
00243 }
00244 
00245 
00246 BOOL IsAnyDesktopRunning()
00247 {
00248     HINSTANCE hUser32 = GetModuleHandle(TEXT("user32"));
00249 
00250     SetShellWindow = (BOOL(WINAPI*)(HWND)) GetProcAddress(hUser32, "SetShellWindow");
00251     SetShellWindowEx = (BOOL(WINAPI*)(HWND,HWND)) GetProcAddress(hUser32, "SetShellWindowEx");
00252 
00253     return GetShellWindow() != 0;
00254 }
00255 
00256 
00257 BackgroundWindow::BackgroundWindow(HWND hwnd)
00258  :  super(hwnd)
00259 {
00260      // set background brush for the short moment of displaying the
00261      // background color while moving foreground windows
00262     SetClassLong(hwnd, GCL_HBRBACKGROUND, COLOR_BACKGROUND+1);
00263 
00264     _display_version = RegGetDWORDValue(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), TEXT("PaintDesktopVersion"), 1);
00265 }
00266 
00267 LRESULT BackgroundWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00268 {
00269     switch(nmsg) {
00270       case WM_ERASEBKGND:
00271         DrawDesktopBkgnd((HDC)wparam);
00272         return TRUE;
00273 
00274       case WM_MBUTTONDBLCLK:
00275         /* Imagelist icons are missing if MainFrame::Create() is called directly from here!
00276         explorer_show_frame(SW_SHOWNORMAL); */
00277         PostMessage(g_Globals._hwndDesktop, nmsg, wparam, lparam);
00278         break;
00279 
00280       case PM_DISPLAY_VERSION:
00281         if (lparam || wparam) {
00282             DWORD or_mask = wparam;
00283             DWORD reset_mask = LOWORD(lparam);
00284             DWORD xor_mask = HIWORD(lparam);
00285             _display_version = ((_display_version&~reset_mask) | or_mask) ^ xor_mask;
00286             RegSetDWORDValue(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), TEXT("PaintDesktopVersion"), _display_version);
00287             ///@todo Changing the PaintDesktopVersion-Flag needs a restart of the shell -> display a message box
00288             InvalidateRect(_hwnd, NULL, TRUE);
00289         }
00290         return _display_version;
00291 
00292       default:
00293         return super::WndProc(nmsg, wparam, lparam);
00294     }
00295 
00296     return 0;
00297 }
00298 
00299 void BackgroundWindow::DrawDesktopBkgnd(HDC hdc)
00300 {
00301     PaintDesktop(hdc);
00302 
00303 /* special solid background
00304     HBRUSH bkgndBrush = CreateSolidBrush(RGB(0,32,160));    // dark blue
00305     FillRect(hdc, &rect, bkgndBrush);
00306     DeleteBrush(bkgndBrush);
00307 */
00308 }
00309 
00310 
00311 DesktopWindow::DesktopWindow(HWND hwnd)
00312  :  super(hwnd)
00313 {
00314     _pShellView = NULL;
00315 }
00316 
00317 DesktopWindow::~DesktopWindow()
00318 {
00319     if (_pShellView)
00320         _pShellView->Release();
00321 }
00322 
00323 
00324 HWND DesktopWindow::Create()
00325 {
00326     static IconWindowClass wcDesktop(TEXT("Progman"), IDI_REACTOS, CS_DBLCLKS);
00327     /* (disabled because of small ugly temporary artefacts when hiding start menu)
00328     wcDesktop.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1); */
00329 
00330     int width = GetSystemMetrics(SM_CXSCREEN);
00331     int height = GetSystemMetrics(SM_CYSCREEN);
00332 
00333     HWND hwndDesktop = Window::Create(WINDOW_CREATOR(DesktopWindow),
00334                     WS_EX_TOOLWINDOW, wcDesktop, TEXT("Program Manager"), WS_POPUP|WS_VISIBLE,  //|WS_CLIPCHILDREN for SDI frames
00335                     0, 0, width, height, 0);
00336 
00337      // work around to display desktop bar in Wine
00338     ShowWindow(GET_WINDOW(DesktopWindow, hwndDesktop)->_desktopBar, SW_SHOW);
00339 
00340      // work around for Windows NT, Win 98, ...
00341      // Without this the desktop has mysteriously only a size of 800x600 pixels.
00342     MoveWindow(hwndDesktop, 0, 0, width, height, TRUE);
00343 
00344     return hwndDesktop;
00345 }
00346 
00347 
00348 LRESULT DesktopWindow::Init(LPCREATESTRUCT pcs)
00349 {
00350     if (super::Init(pcs))
00351         return 1;
00352 
00353     HRESULT hr = GetDesktopFolder()->CreateViewObject(_hwnd, IID_IShellView, (void**)&_pShellView);
00354 /* also possible:
00355     SFV_CREATE sfv_create;
00356 
00357     sfv_create.cbSize = sizeof(SFV_CREATE);
00358     sfv_create.pshf = GetDesktopFolder();
00359     sfv_create.psvOuter = NULL;
00360     sfv_create.psfvcb = NULL;
00361 
00362     HRESULT hr = SHCreateShellFolderView(&sfv_create, &_pShellView);
00363 */
00364     HWND hWndView = 0;
00365 
00366     if (SUCCEEDED(hr)) {
00367         FOLDERSETTINGS fs;
00368 
00369         fs.ViewMode = FVM_ICON;
00370         fs.fFlags = FWF_DESKTOP|FWF_NOCLIENTEDGE|FWF_NOSCROLL|FWF_BESTFITWINDOW|FWF_SNAPTOGRID; //|FWF_AUTOARRANGE;
00371 
00372         ClientRect rect(_hwnd);
00373 
00374         hr = _pShellView->CreateViewWindow(NULL, &fs, this, &rect, &hWndView);
00375 
00376         ///@todo use IShellBrowser::GetViewStateStream() to restore previous view state -> see SHOpenRegStream()
00377 
00378         if (SUCCEEDED(hr)) {
00379             g_Globals._hwndShellView = hWndView;
00380 
00381              // subclass shellview window
00382             new DesktopShellView(hWndView, _pShellView);
00383 
00384             _pShellView->UIActivate(SVUIA_ACTIVATE_FOCUS);
00385 
00386         /*
00387             IShellView2* pShellView2;
00388 
00389             hr = _pShellView->QueryInterface(IID_IShellView2, (void**)&pShellView2);
00390 
00391             SV2CVW2_PARAMS params;
00392             params.cbSize = sizeof(SV2CVW2_PARAMS);
00393             params.psvPrev = _pShellView;
00394             params.pfs = &fs;
00395             params.psbOwner = this;
00396             params.prcView = &rect;
00397             params.pvid = params.pvid;//@@
00398 
00399             hr = pShellView2->CreateViewWindow2(&params);
00400             params.pvid;
00401         */
00402 
00403         /*
00404             IFolderView* pFolderView;
00405 
00406             hr = _pShellView->QueryInterface(IID_IFolderView, (void**)&pFolderView);
00407 
00408             if (SUCCEEDED(hr)) {
00409                 hr = pFolderView->GetAutoArrange();
00410                 hr = pFolderView->SetCurrentViewMode(FVM_DETAILS);
00411             }
00412         */
00413         }
00414     }
00415 
00416     if (hWndView && SetShellWindowEx)
00417         SetShellWindowEx(_hwnd, hWndView);
00418     else if (SetShellWindow)
00419         SetShellWindow(_hwnd);
00420 
00421      // create the explorer bar
00422     _desktopBar = DesktopBar::Create();
00423     g_Globals._hwndDesktopBar = _desktopBar;
00424 
00425     return 0;
00426 }
00427 
00428 
00429 LRESULT DesktopWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00430 {
00431     switch(nmsg) {
00432       case WM_LBUTTONDBLCLK:
00433       case WM_RBUTTONDBLCLK:
00434       case WM_MBUTTONDBLCLK:
00435         explorer_show_frame(SW_SHOWNORMAL);
00436         break;
00437 
00438       case WM_GETISHELLBROWSER:
00439         return (LRESULT)static_cast<IShellBrowser*>(this);
00440 
00441       case WM_DESTROY:
00442 
00443         ///@todo use IShellBrowser::GetViewStateStream() and _pShellView->SaveViewState() to store view state
00444 
00445         if (SetShellWindow)
00446             SetShellWindow(0);
00447         break;
00448 
00449       case WM_CLOSE:
00450         ShowExitWindowsDialog(_hwnd);
00451         break;
00452 
00453       case WM_SYSCOMMAND:
00454         if (wparam == SC_TASKLIST) {
00455             if (_desktopBar)
00456                 SendMessage(_desktopBar, nmsg, wparam, lparam);
00457         }
00458         goto def;
00459 
00460       case WM_SYSCOLORCHANGE:
00461          // redraw background window
00462         InvalidateRect(g_Globals._hwndShellView, NULL, TRUE);
00463 
00464          // forward message to shell view window to redraw icon backgrounds
00465         SendMessage(g_Globals._hwndShellView, WM_SYSCOLORCHANGE, wparam, lparam);
00466         break;
00467 
00468       default: def:
00469         return super::WndProc(nmsg, wparam, lparam);
00470     }
00471 
00472     return 0;
00473 }
00474 
00475 
00476 HRESULT DesktopWindow::OnDefaultCommand(LPIDA pida)
00477 {
00478 #ifndef ROSSHELL    // in shell-only-mode fall through and let shell32 handle the command
00479     if (MainFrameBase::OpenShellFolders(pida, 0))
00480         return S_OK;
00481 #endif
00482 
00483     return E_NOTIMPL;
00484 }
00485 
00486 
00487 DesktopShellView::DesktopShellView(HWND hwnd, IShellView* pShellView)
00488  :  super(hwnd),
00489     _pShellView(pShellView)
00490 {
00491     _hwndListView = GetNextWindow(hwnd, GW_CHILD);
00492 
00493     SetWindowStyle(_hwndListView, GetWindowStyle(_hwndListView)&~LVS_ALIGNMASK);//|LVS_ALIGNTOP|LVS_AUTOARRANGE);
00494 
00495      // work around for Windows NT, Win 98, ...
00496      // Without this the desktop has mysteriously only a size of 800x600 pixels.
00497     ClientRect rect(hwnd);
00498     MoveWindow(_hwndListView, 0, 0, rect.right, rect.bottom, TRUE);
00499 
00500      // subclass background window
00501     new BackgroundWindow(_hwndListView);
00502 
00503     _icon_algo = 1; // default icon arrangement
00504 
00505     PositionIcons();
00506     InitDragDrop();
00507 }
00508 
00509 bool DesktopShellView::InitDragDrop()
00510 {
00511     CONTEXT("DesktopShellView::InitDragDrop()");
00512 
00513     _pDropTarget = new DesktopDropTarget(_hwnd);
00514 
00515     if (!_pDropTarget)
00516         return false;
00517 
00518     _pDropTarget->AddRef();
00519 
00520     if (FAILED(RegisterDragDrop(_hwnd, _pDropTarget))) {
00521         _pDropTarget->Release();
00522         _pDropTarget = NULL;
00523         return false;
00524     }
00525     else
00526         _pDropTarget->Release();
00527 
00528     FORMATETC ftetc;
00529 
00530     ftetc.dwAspect = DVASPECT_CONTENT;
00531     ftetc.lindex = -1;
00532     ftetc.tymed = TYMED_HGLOBAL;
00533     ftetc.cfFormat = CF_HDROP;
00534 
00535     _pDropTarget->AddSuportedFormat(ftetc);
00536 
00537     return true;
00538 }
00539 
00540 LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00541 {
00542     switch(nmsg) {
00543       case WM_CONTEXTMENU:
00544         if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)))
00545             DoDesktopContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
00546         break;
00547 
00548       case PM_SET_ICON_ALGORITHM:
00549         _icon_algo = wparam;
00550         PositionIcons();
00551         break;
00552 
00553       case PM_GET_ICON_ALGORITHM:
00554         return _icon_algo;
00555 
00556       case PM_DISPLAY_VERSION:
00557         return SendMessage(_hwndListView, nmsg, wparam, lparam);
00558 
00559       default:
00560         return super::WndProc(nmsg, wparam, lparam);
00561     }
00562 
00563     return 0;
00564 }
00565 
00566 int DesktopShellView::Command(int id, int code)
00567 {
00568     return super::Command(id, code);
00569 }
00570 
00571 int DesktopShellView::Notify(int id, NMHDR* pnmh)
00572 {
00573     return super::Notify(id, pnmh);
00574 }
00575 
00576 bool DesktopShellView::DoContextMenu(int x, int y)
00577 {
00578     IDataObject* selection;
00579 
00580     HRESULT hr = _pShellView->GetItemObject(SVGIO_SELECTION, IID_IDataObject, (void**)&selection);
00581     if (FAILED(hr))
00582         return false;
00583 
00584     PIDList pidList;
00585 
00586     hr = pidList.GetData(selection);
00587     if (FAILED(hr)) {
00588         selection->Release();
00589         //CHECKERROR(hr);
00590         return false;
00591     }
00592 
00593     LPIDA pida = pidList;
00594     if (!pida->cidl) {
00595         selection->Release();
00596         return false;
00597     }
00598 
00599     LPCITEMIDLIST parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
00600 
00601     LPCITEMIDLIST* apidl = (LPCITEMIDLIST*) alloca(pida->cidl*sizeof(LPCITEMIDLIST));
00602 
00603     for(int i=pida->cidl; i>0; --i)
00604         apidl[i-1] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i]);
00605 
00606     hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y, _cm_ifs);
00607 
00608     selection->Release();
00609 
00610     if (SUCCEEDED(hr))
00611         refresh();
00612     else
00613         CHECKERROR(hr);
00614 
00615     return true;
00616 }
00617 
00618 HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y)
00619 {
00620     IContextMenu* pcm;
00621 
00622     HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm);
00623 
00624     if (SUCCEEDED(hr)) {
00625         pcm = _cm_ifs.query_interfaces(pcm);
00626 
00627         HMENU hmenu = CreatePopupMenu();
00628 
00629         if (hmenu) {
00630             hr = pcm->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST-1, CMF_NORMAL|CMF_EXPLORE);
00631 
00632             if (SUCCEEDED(hr)) {
00633                 AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
00634                 AppendMenu(hmenu, 0, FCIDM_SHVIEWLAST-1, ResString(IDS_ABOUT_EXPLORER));
00635 
00636                 UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, _hwnd, NULL);
00637 
00638                 _cm_ifs.reset();
00639 
00640                 if (idCmd == FCIDM_SHVIEWLAST-1) {
00641                     explorer_about(_hwnd);
00642                 } else if (idCmd) {
00643                   CMINVOKECOMMANDINFO cmi;
00644 
00645                   cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
00646                   cmi.fMask = 0;
00647                   cmi.hwnd = _hwnd;
00648                   cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - FCIDM_SHVIEWFIRST);
00649                   cmi.lpParameters = NULL;
00650                   cmi.lpDirectory = NULL;
00651                   cmi.nShow = SW_SHOWNORMAL;
00652                   cmi.dwHotKey = 0;
00653                   cmi.hIcon = 0;
00654 
00655                   hr = pcm->InvokeCommand(&cmi);
00656                 }
00657             } else
00658                 _cm_ifs.reset();
00659             DestroyMenu(hmenu);
00660         }
00661 
00662         pcm->Release();
00663     }
00664 
00665     return hr;
00666 }
00667 
00668 
00669 #define ARRANGE_BORDER_DOWN  8
00670 #define ARRANGE_BORDER_HV    9
00671 #define ARRANGE_ROUNDABOUT  10
00672 
00673 static const POINTS s_align_start[] = {
00674     {0, 0}, // left/top
00675     {0, 0},
00676     {1, 0}, // right/top
00677     {1, 0},
00678     {0, 1}, // left/bottom
00679     {0, 1},
00680     {1, 1}, // right/bottom
00681     {1, 1},
00682 
00683     {0, 0}, // left/top
00684     {0, 0},
00685     {0, 0}
00686 };
00687 
00688 static const POINTS s_align_dir1[] = {
00689     { 0, +1},   // down
00690     {+1,  0},   // right
00691     {-1,  0},   // left
00692     { 0, +1},   // down
00693     { 0, -1},   // up
00694     {+1,  0},   // right
00695     {-1,  0},   // left
00696     { 0, -1},   // up
00697 
00698     { 0, +1},   // down
00699     {+1,  0},   // right
00700     {+1,  0}    // right
00701 };
00702 
00703 static const POINTS s_align_dir2[] = {
00704     {+1,  0},   // right
00705     { 0, +1},   // down
00706     { 0, +1},   // down
00707     {-1,  0},   // left
00708     {+1,  0},   // right
00709     { 0, -1},   // up
00710     { 0, -1},   // up
00711     {-1,  0},   // left
00712 
00713     {+1,  0},   // right
00714     { 0, +1},   // down
00715     { 0, +1}    // down
00716 };
00717 
00718 typedef pair<int,int> IconPos;
00719 typedef map<IconPos, int> IconMap;
00720 
00721 void DesktopShellView::PositionIcons(int dir)
00722 {
00723     DWORD spacing = ListView_GetItemSpacing(_hwndListView, FALSE);
00724 
00725     RECT work_area;
00726     SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0);
00727 
00728     const POINTS& dir1 = s_align_dir1[_icon_algo];
00729     const POINTS& dir2 = s_align_dir2[_icon_algo];
00730     const POINTS& start_pos = s_align_start[_icon_algo];
00731 
00732     int dir_x1 = dir1.x;
00733     int dir_y1 = dir1.y;
00734     int dir_x2 = dir2.x;
00735     int dir_y2 = dir2.y;
00736 
00737     int cx = LOWORD(spacing);
00738     int cy = HIWORD(spacing);
00739 
00740     int dx1 = dir_x1 * cx;
00741     int dy1 = dir_y1 * cy;
00742     int dx2 = dir_x2 * cx;
00743     int dy2 = dir_y2 * cy;
00744 
00745     int xoffset = (cx-32)/2;
00746     int yoffset = 4/*(cy-32)/2*/;
00747 
00748     int start_x = start_pos.x * (work_area.right - cx) + xoffset;
00749     int start_y = start_pos.y * (work_area.bottom - cy) + yoffset;
00750 
00751     int x = start_x;
00752     int y = start_y;
00753 
00754     int all = ListView_GetItemCount(_hwndListView);
00755     int i1, i2;
00756 
00757     if (dir > 0) {
00758         i1 = 0;
00759         i2 = all;
00760     } else {
00761         i1 = all-1;
00762         i2 = -1;
00763     }
00764 
00765     IconMap pos_idx;
00766     int cnt = 0;
00767     int xhv = start_x;
00768     int yhv = start_y;
00769 
00770     for(int idx=i1; idx!=i2; idx+=dir) {
00771         pos_idx[IconPos(y, x)] = idx;
00772 
00773         if (_icon_algo == ARRANGE_BORDER_DOWN) {
00774             if (++cnt & 1)
00775                 x = work_area.right - x - cx + 2*xoffset;
00776             else {
00777                 y += dy1;
00778 
00779                 if (y + cy - 2 * yoffset > work_area.bottom) {
00780                     y = start_y;
00781                     start_x += dx2;
00782                     x = start_x;
00783                 }
00784             }
00785 
00786             continue;
00787         }
00788         else if (_icon_algo == ARRANGE_BORDER_HV) {
00789             if (++cnt & 1)
00790                 x = work_area.right - x - cx + 2*xoffset;
00791             else if (cnt & 2) {
00792                 yhv += cy;
00793                 y = yhv;
00794                 x = start_x;
00795 
00796                 if (y + cy - 2 * yoffset > work_area.bottom) {
00797                     start_x += cx;
00798                     xhv = start_x;
00799                     x = xhv;
00800                     start_y += cy;
00801                     yhv = start_y;
00802                     y = yhv;
00803                 }
00804             } else {
00805                 xhv += cx;
00806                 x = xhv;
00807                 y = start_y;
00808 
00809                 if (x + cx - 2 * xoffset > work_area.right) {
00810                     start_x += cx;
00811                     xhv = start_x;
00812                     x = xhv;
00813                     start_y += cy;
00814                     yhv = start_y;
00815                     y = yhv;
00816                 }
00817             }
00818 
00819             continue;
00820         }
00821         else if (_icon_algo == ARRANGE_ROUNDABOUT) {
00822 
00823             ///@todo
00824 
00825         }
00826 
00827         x += dx1;
00828         y += dy1;
00829 
00830         if (x<0 || x+cx-2*xoffset>work_area.right) {
00831             x = start_x;
00832             y += dy2;
00833         } else if (y<0 || y+cy-2*yoffset>work_area.bottom) {
00834             y = start_y;
00835             x += dx2;
00836         }
00837     }
00838 
00839      // use a little trick to get the icons where we want them to be...
00840 
00841     //for(IconMap::const_iterator it=pos_idx.end(); --it!=pos_idx.begin(); ) {
00842     //  const IconPos& pos = it->first;
00843 
00844     //  ListView_SetItemPosition32(_hwndListView, it->second, pos.second, pos.first);
00845     //}
00846 
00847     for(IconMap::const_iterator it=pos_idx.begin(); it!=pos_idx.end(); ++it) {
00848         const IconPos& pos = it->first;
00849 
00850         ListView_SetItemPosition32(_hwndListView, it->second, pos.second, pos.first);
00851     }
00852 }
00853 
00854 
00855 void DesktopShellView::refresh()
00856 {
00857     ///@todo
00858 }

ROS Explorer Source Code Documentation
generated on 02.01.2013 by doxygen

ROS Explorer Homepage