ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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 
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_reverse_iterator it=minimized.rbegin(); 
00239                                                             it!=minimized.rend(); ++it) {
00240             ShowWindowAsync(it->first, it->second&WS_MAXIMIZE? SW_MAXIMIZE: SW_RESTORE);
00241             Sleep(20);
00242         }
00243 
00244         minimized.clear();
00245     }
00246 }
00247 
00248 
00249 BOOL IsAnyDesktopRunning()
00250 {
00251     HINSTANCE hUser32 = GetModuleHandle(TEXT("user32"));
00252 
00253     SetShellWindow = (BOOL(WINAPI*)(HWND)) GetProcAddress(hUser32, "SetShellWindow");
00254     SetShellWindowEx = (BOOL(WINAPI*)(HWND,HWND)) GetProcAddress(hUser32, "SetShellWindowEx");
00255 
00256     return GetShellWindow() != 0;
00257 }
00258 
00259 
00260 BackgroundWindow::BackgroundWindow(HWND hwnd)
00261  :  super(hwnd)
00262 {
00263      // set background brush for the short moment of displaying the
00264      // background color while moving foreground windows
00265     SetClassLongPtr(hwnd, GCL_HBRBACKGROUND, COLOR_BACKGROUND+1);
00266 
00267     _display_version = RegGetDWORDValue(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), TEXT("PaintDesktopVersion"), 1);
00268 }
00269 
00270 LRESULT BackgroundWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00271 {
00272     switch(nmsg) {
00273       case WM_ERASEBKGND:
00274         DrawDesktopBkgnd((HDC)wparam);
00275         return TRUE;
00276 
00277       case WM_MBUTTONDBLCLK:
00278         /* Imagelist icons are missing if MainFrame::Create() is called directly from here!
00279         explorer_show_frame(SW_SHOWNORMAL); */
00280         PostMessage(g_Globals._hwndDesktop, nmsg, wparam, lparam);
00281         break;
00282 
00283       case PM_DISPLAY_VERSION:
00284         if (lparam || wparam) {
00285             DWORD or_mask = wparam;
00286             DWORD reset_mask = LOWORD(lparam);
00287             DWORD xor_mask = HIWORD(lparam);
00288             _display_version = ((_display_version&~reset_mask) | or_mask) ^ xor_mask;
00289             RegSetDWORDValue(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), TEXT("PaintDesktopVersion"), _display_version);
00291             InvalidateRect(_hwnd, NULL, TRUE);
00292         }
00293         return _display_version;
00294 
00295       default:
00296         return super::WndProc(nmsg, wparam, lparam);
00297     }
00298 
00299     return 0;
00300 }
00301 
00302 void BackgroundWindow::DrawDesktopBkgnd(HDC hdc)
00303 {
00304     PaintDesktop(hdc);
00305 
00306 /* special solid background
00307     HBRUSH bkgndBrush = CreateSolidBrush(RGB(0,32,160));    // dark blue
00308     FillRect(hdc, &rect, bkgndBrush);
00309     DeleteBrush(bkgndBrush);
00310 */
00311 }
00312 
00313 
00314 DesktopWindow::DesktopWindow(HWND hwnd)
00315  :  super(hwnd)
00316 {
00317     _pShellView = NULL;
00318 }
00319 
00320 DesktopWindow::~DesktopWindow()
00321 {
00322     if (_pShellView)
00323         _pShellView->Release();
00324 }
00325 
00326 
00327 HWND DesktopWindow::Create()
00328 {
00329     static IconWindowClass wcDesktop(TEXT("Progman"), IDI_REACTOS, CS_DBLCLKS);
00330     /* (disabled because of small ugly temporary artefacts when hiding start menu)
00331     wcDesktop.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1); */
00332 
00333     int width = GetSystemMetrics(SM_CXSCREEN);
00334     int height = GetSystemMetrics(SM_CYSCREEN);
00335 
00336     HWND hwndDesktop = Window::Create(WINDOW_CREATOR(DesktopWindow),
00337                     WS_EX_TOOLWINDOW, wcDesktop, TEXT("Program Manager"), WS_POPUP|WS_VISIBLE,  //|WS_CLIPCHILDREN for SDI frames
00338                     0, 0, width, height, 0);
00339 
00340      // work around to display desktop bar in Wine
00341     ShowWindow(GET_WINDOW(DesktopWindow, hwndDesktop)->_desktopBar, SW_SHOW);
00342 
00343      // work around for Windows NT, Win 98, ...
00344      // Without this the desktop has mysteriously only a size of 800x600 pixels.
00345     MoveWindow(hwndDesktop, 0, 0, width, height, TRUE);
00346 
00347     return hwndDesktop;
00348 }
00349 
00350 
00351 LRESULT DesktopWindow::Init(LPCREATESTRUCT pcs)
00352 {
00353     if (super::Init(pcs))
00354         return 1;
00355 
00356     HRESULT hr = GetDesktopFolder()->CreateViewObject(_hwnd, IID_IShellView, (void**)&_pShellView);
00357 /* also possible:
00358     SFV_CREATE sfv_create;
00359 
00360     sfv_create.cbSize = sizeof(SFV_CREATE);
00361     sfv_create.pshf = GetDesktopFolder();
00362     sfv_create.psvOuter = NULL;
00363     sfv_create.psfvcb = NULL;
00364 
00365     HRESULT hr = SHCreateShellFolderView(&sfv_create, &_pShellView);
00366 */
00367     HWND hWndView = 0;
00368 
00369     if (SUCCEEDED(hr)) {
00370         FOLDERSETTINGS fs;
00371 
00372         fs.ViewMode = FVM_ICON;
00373         fs.fFlags = FWF_DESKTOP|FWF_NOCLIENTEDGE|FWF_NOSCROLL|FWF_BESTFITWINDOW|FWF_SNAPTOGRID; //|FWF_AUTOARRANGE;
00374 
00375         ClientRect rect(_hwnd);
00376 
00377         hr = _pShellView->CreateViewWindow(NULL, &fs, this, &rect, &hWndView);
00378 
00380 
00381         if (SUCCEEDED(hr)) {
00382             g_Globals._hwndShellView = hWndView;
00383 
00384              // subclass shellview window
00385             new DesktopShellView(hWndView, _pShellView);
00386 
00387             _pShellView->UIActivate(SVUIA_ACTIVATE_FOCUS);
00388 
00389         /*
00390             IShellView2* pShellView2;
00391 
00392             hr = _pShellView->QueryInterface(IID_IShellView2, (void**)&pShellView2);
00393 
00394             SV2CVW2_PARAMS params;
00395             params.cbSize = sizeof(SV2CVW2_PARAMS);
00396             params.psvPrev = _pShellView;
00397             params.pfs = &fs;
00398             params.psbOwner = this;
00399             params.prcView = &rect;
00400             params.pvid = params.pvid;//@@
00401 
00402             hr = pShellView2->CreateViewWindow2(&params);
00403             params.pvid;
00404         */
00405 
00406         /*
00407             IFolderView* pFolderView;
00408 
00409             hr = _pShellView->QueryInterface(IID_IFolderView, (void**)&pFolderView);
00410 
00411             if (SUCCEEDED(hr)) {
00412                 hr = pFolderView->GetAutoArrange();
00413                 hr = pFolderView->SetCurrentViewMode(FVM_DETAILS);
00414             }
00415         */
00416         }
00417     }
00418 
00419     if (hWndView && SetShellWindowEx)
00420         SetShellWindowEx(_hwnd, hWndView);
00421     else if (SetShellWindow)
00422         SetShellWindow(_hwnd);
00423 
00424      // create the explorer bar
00425     _desktopBar = DesktopBar::Create();
00426     g_Globals._hwndDesktopBar = _desktopBar;
00427 
00428     return 0;
00429 }
00430 
00431 
00432 LRESULT DesktopWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00433 {
00434     switch(nmsg) {
00435       case WM_LBUTTONDBLCLK:
00436       case WM_RBUTTONDBLCLK:
00437       case WM_MBUTTONDBLCLK:
00438         explorer_show_frame(SW_SHOWNORMAL);
00439         break;
00440 
00441       case WM_DISPLAYCHANGE:
00442         MoveWindow(_hwnd, 0, 0, LOWORD(lparam), HIWORD(lparam), TRUE);
00443         MoveWindow(g_Globals._hwndShellView, 0, 0, LOWORD(lparam), HIWORD(lparam), TRUE);
00444         MoveWindow(_desktopBar, 0, HIWORD(lparam) - DESKTOPBARBAR_HEIGHT, LOWORD(lparam), DESKTOPBARBAR_HEIGHT, TRUE);
00445         break;
00446 
00447       case WM_GETISHELLBROWSER:
00448         return (LRESULT)static_cast<IShellBrowser*>(this);
00449 
00450       case WM_DESTROY:
00451 
00453 
00454         if (SetShellWindow)
00455             SetShellWindow(0);
00456         break;
00457 
00458       case WM_CLOSE:
00459         ShowExitWindowsDialog(_hwnd);
00460         break;
00461 
00462       case WM_SYSCOMMAND:
00463         if (wparam == SC_TASKLIST) {
00464             if (_desktopBar)
00465                 SendMessage(_desktopBar, nmsg, wparam, lparam);
00466         }
00467         goto def;
00468 
00469       case WM_SYSCOLORCHANGE:
00470         // redraw background window - it's done by system
00471         //InvalidateRect(g_Globals._hwndShellView, NULL, TRUE);
00472 
00473         // forward message to common controls
00474         SendMessage(g_Globals._hwndShellView, WM_SYSCOLORCHANGE, 0, 0);
00475         SendMessage(_desktopBar, WM_SYSCOLORCHANGE, 0, 0);
00476         break;
00477 
00478       case WM_SETTINGCHANGE:
00479         SendMessage(g_Globals._hwndShellView, nmsg, wparam, lparam);
00480         break;
00481 
00482       default: def:
00483         return super::WndProc(nmsg, wparam, lparam);
00484     }
00485 
00486     return 0;
00487 }
00488 
00489 
00490 HRESULT DesktopWindow::OnDefaultCommand(LPIDA pida)
00491 {
00492 #ifndef ROSSHELL    // in shell-only-mode fall through and let shell32 handle the command
00493     if (MainFrameBase::OpenShellFolders(pida, 0))
00494         return S_OK;
00495 #endif
00496 
00497     return E_NOTIMPL;
00498 }
00499 
00500 
00501 DesktopShellView::DesktopShellView(HWND hwnd, IShellView* pShellView)
00502  :  super(hwnd),
00503     _pShellView(pShellView)
00504 {
00505     _hwndListView = GetNextWindow(hwnd, GW_CHILD);
00506 
00507      // work around for Windows NT, Win 98, ...
00508      // Without this the desktop has mysteriously only a size of 800x600 pixels.
00509     ClientRect rect(hwnd);
00510     MoveWindow(_hwndListView, 0, 0, rect.right, rect.bottom, TRUE);
00511 
00512      // subclass background window
00513     new BackgroundWindow(_hwndListView);
00514 
00515     _icon_algo = 0; // default icon arrangement
00516 
00517     InitDragDrop();
00518 }
00519 
00520 
00521 DesktopShellView::~DesktopShellView()
00522 {
00523     if (FAILED(RevokeDragDrop(_hwnd)))
00524         assert(0);
00525 }
00526 
00527 
00528 bool DesktopShellView::InitDragDrop()
00529 {
00530     CONTEXT("DesktopShellView::InitDragDrop()");
00531 
00532     DesktopDropTarget * pDropTarget = new DesktopDropTarget(_hwnd);
00533 
00534     if (!pDropTarget)
00535         return false;
00536 
00537     pDropTarget->AddRef();
00538 
00539     if (FAILED(RegisterDragDrop(_hwnd, pDropTarget))) {
00540         pDropTarget->Release();
00541         return false;
00542     }
00543 
00544     FORMATETC ftetc;
00545 
00546     ftetc.dwAspect = DVASPECT_CONTENT;
00547     ftetc.lindex = -1;
00548     ftetc.tymed = TYMED_HGLOBAL;
00549     ftetc.cfFormat = CF_HDROP;
00550 
00551     pDropTarget->AddSuportedFormat(ftetc);
00552     pDropTarget->Release();
00553 
00554     return true;
00555 }
00556 
00557 LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
00558 {
00559     switch(nmsg) {
00560       case WM_CONTEXTMENU:
00561         if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)))
00562             DoDesktopContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
00563         break;
00564 
00565       case PM_SET_ICON_ALGORITHM:
00566         _icon_algo = wparam;
00567         PositionIcons();
00568         break;
00569 
00570       case PM_GET_ICON_ALGORITHM:
00571         return _icon_algo;
00572 
00573       case PM_DISPLAY_VERSION:
00574         return SendMessage(_hwndListView, nmsg, wparam, lparam);
00575 
00576       default:
00577         return super::WndProc(nmsg, wparam, lparam);
00578     }
00579 
00580     return 0;
00581 }
00582 
00583 int DesktopShellView::Command(int id, int code)
00584 {
00585     return super::Command(id, code);
00586 }
00587 
00588 int DesktopShellView::Notify(int id, NMHDR* pnmh)
00589 {
00590     return super::Notify(id, pnmh);
00591 }
00592 
00593 bool DesktopShellView::DoContextMenu(int x, int y)
00594 {
00595     IDataObject* selection;
00596 
00597     HRESULT hr = _pShellView->GetItemObject(SVGIO_SELECTION, IID_IDataObject, (void**)&selection);
00598     if (FAILED(hr))
00599         return false;
00600 
00601     PIDList pidList;
00602 
00603     hr = pidList.GetData(selection);
00604     if (FAILED(hr)) {
00605         selection->Release();
00606         //CHECKERROR(hr);
00607         return false;
00608     }
00609 
00610     LPIDA pida = pidList;
00611     if (!pida->cidl) {
00612         selection->Release();
00613         return false;
00614     }
00615 
00616     LPCITEMIDLIST parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
00617 
00618     LPCITEMIDLIST* apidl = (LPCITEMIDLIST*) alloca(pida->cidl*sizeof(LPCITEMIDLIST));
00619 
00620     for(int i=pida->cidl; i>0; --i)
00621         apidl[i-1] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i]);
00622 
00623     hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y, _cm_ifs);
00624 
00625     selection->Release();
00626 
00627     if (SUCCEEDED(hr))
00628         refresh();
00629     else
00630         CHECKERROR(hr);
00631 
00632     return true;
00633 }
00634 
00635 HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y)
00636 {
00637     IContextMenu* pcm;
00638 
00639     HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm);
00640 
00641     if (SUCCEEDED(hr)) {
00642         pcm = _cm_ifs.query_interfaces(pcm);
00643 
00644         HMENU hmenu = CreatePopupMenu();
00645 
00646         if (hmenu) {
00647             hr = pcm->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST-1, CMF_NORMAL|CMF_EXPLORE);
00648 
00649             if (SUCCEEDED(hr)) {
00650                 AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
00651                 AppendMenu(hmenu, 0, FCIDM_SHVIEWLAST-1, ResString(IDS_ABOUT_EXPLORER));
00652 
00653                 UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, _hwnd, NULL);
00654 
00655                 _cm_ifs.reset();
00656 
00657                 if (idCmd == FCIDM_SHVIEWLAST-1) {
00658                     explorer_about(_hwnd);
00659                 } else if (idCmd) {
00660                   CMINVOKECOMMANDINFO cmi;
00661 
00662                   cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
00663                   cmi.fMask = 0;
00664                   cmi.hwnd = _hwnd;
00665                   cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - FCIDM_SHVIEWFIRST);
00666                   cmi.lpParameters = NULL;
00667                   cmi.lpDirectory = NULL;
00668                   cmi.nShow = SW_SHOWNORMAL;
00669                   cmi.dwHotKey = 0;
00670                   cmi.hIcon = 0;
00671 
00672                   hr = pcm->InvokeCommand(&cmi);
00673                 }
00674             } else
00675                 _cm_ifs.reset();
00676             DestroyMenu(hmenu);
00677         }
00678 
00679         pcm->Release();
00680     }
00681 
00682     return hr;
00683 }
00684 
00685 
00686 #define ARRANGE_BORDER_DOWN  8
00687 #define ARRANGE_BORDER_HV    9
00688 #define ARRANGE_ROUNDABOUT  10
00689 
00690 static const POINTS s_align_start[] = {
00691     {0, 0}, // left/top
00692     {0, 0},
00693     {1, 0}, // right/top
00694     {1, 0},
00695     {0, 1}, // left/bottom
00696     {0, 1},
00697     {1, 1}, // right/bottom
00698     {1, 1},
00699 
00700     {0, 0}, // left/top
00701     {0, 0},
00702     {0, 0}
00703 };
00704 
00705 static const POINTS s_align_dir1[] = {
00706     { 0, +1},   // down
00707     {+1,  0},   // right
00708     {-1,  0},   // left
00709     { 0, +1},   // down
00710     { 0, -1},   // up
00711     {+1,  0},   // right
00712     {-1,  0},   // left
00713     { 0, -1},   // up
00714 
00715     { 0, +1},   // down
00716     {+1,  0},   // right
00717     {+1,  0}    // right
00718 };
00719 
00720 static const POINTS s_align_dir2[] = {
00721     {+1,  0},   // right
00722     { 0, +1},   // down
00723     { 0, +1},   // down
00724     {-1,  0},   // left
00725     {+1,  0},   // right
00726     { 0, -1},   // up
00727     { 0, -1},   // up
00728     {-1,  0},   // left
00729 
00730     {+1,  0},   // right
00731     { 0, +1},   // down
00732     { 0, +1}    // down
00733 };
00734 
00735 typedef pair<int,int> IconPos;
00736 typedef map<IconPos, int> IconMap;
00737 
00738 void DesktopShellView::PositionIcons(int dir)
00739 {
00740     DWORD spacing = ListView_GetItemSpacing(_hwndListView, FALSE);
00741 
00742     RECT work_area;
00743     SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0);
00744 
00745     /* disable default allignment */
00746     SetWindowStyle(_hwndListView, GetWindowStyle(_hwndListView)&~LVS_ALIGNMASK);//|LVS_ALIGNTOP|LVS_AUTOARRANGE);
00747 
00748     const POINTS& dir1 = s_align_dir1[_icon_algo];
00749     const POINTS& dir2 = s_align_dir2[_icon_algo];
00750     const POINTS& start_pos = s_align_start[_icon_algo];
00751 
00752     int dir_x1 = dir1.x;
00753     int dir_y1 = dir1.y;
00754     int dir_x2 = dir2.x;
00755     int dir_y2 = dir2.y;
00756 
00757     int cx = LOWORD(spacing);
00758     int cy = HIWORD(spacing);
00759 
00760     int dx1 = dir_x1 * cx;
00761     int dy1 = dir_y1 * cy;
00762     int dx2 = dir_x2 * cx;
00763     int dy2 = dir_y2 * cy;
00764 
00765     int xoffset = (cx-32)/2;
00766     int yoffset = 4/*(cy-32)/2*/;
00767 
00768     int start_x = start_pos.x * (work_area.right - cx) + xoffset;
00769     int start_y = start_pos.y * (work_area.bottom - cy) + yoffset;
00770 
00771     int x = start_x;
00772     int y = start_y;
00773 
00774     int all = ListView_GetItemCount(_hwndListView);
00775     int i1, i2;
00776 
00777     if (dir > 0) {
00778         i1 = 0;
00779         i2 = all;
00780     } else {
00781         i1 = all-1;
00782         i2 = -1;
00783     }
00784 
00785     IconMap pos_idx;
00786     int cnt = 0;
00787     int xhv = start_x;
00788     int yhv = start_y;
00789 
00790     for(int idx=i1; idx!=i2; idx+=dir) {
00791         pos_idx[IconPos(y, x)] = idx;
00792 
00793         if (_icon_algo == ARRANGE_BORDER_DOWN) {
00794             if (++cnt & 1)
00795                 x = work_area.right - x - cx + 2*xoffset;
00796             else {
00797                 y += dy1;
00798 
00799                 if (y + cy - 2 * yoffset > work_area.bottom) {
00800                     y = start_y;
00801                     start_x += dx2;
00802                     x = start_x;
00803                 }
00804             }
00805 
00806             continue;
00807         }
00808         else if (_icon_algo == ARRANGE_BORDER_HV) {
00809             if (++cnt & 1)
00810                 x = work_area.right - x - cx + 2*xoffset;
00811             else if (cnt & 2) {
00812                 yhv += cy;
00813                 y = yhv;
00814                 x = start_x;
00815 
00816                 if (y + cy - 2 * yoffset > work_area.bottom) {
00817                     start_x += cx;
00818                     xhv = start_x;
00819                     x = xhv;
00820                     start_y += cy;
00821                     yhv = start_y;
00822                     y = yhv;
00823                 }
00824             } else {
00825                 xhv += cx;
00826                 x = xhv;
00827                 y = start_y;
00828 
00829                 if (x + cx - 2 * xoffset > work_area.right) {
00830                     start_x += cx;
00831                     xhv = start_x;
00832                     x = xhv;
00833                     start_y += cy;
00834                     yhv = start_y;
00835                     y = yhv;
00836                 }
00837             }
00838 
00839             continue;
00840         }
00841         else if (_icon_algo == ARRANGE_ROUNDABOUT) {
00842 
00844 
00845         }
00846 
00847         x += dx1;
00848         y += dy1;
00849 
00850         if (x<0 || x+cx-2*xoffset>work_area.right) {
00851             x = start_x;
00852             y += dy2;
00853         } else if (y<0 || y+cy-2*yoffset>work_area.bottom) {
00854             y = start_y;
00855             x += dx2;
00856         }
00857     }
00858 
00859      // use a little trick to get the icons where we want them to be...
00860 
00861     //for(IconMap::const_iterator it=pos_idx.end(); --it!=pos_idx.begin(); ) {
00862     //  const IconPos& pos = it->first;
00863 
00864     //  ListView_SetItemPosition32(_hwndListView, it->second, pos.second, pos.first);
00865     //}
00866 
00867     for(IconMap::const_iterator it=pos_idx.begin(); it!=pos_idx.end(); ++it) {
00868         const IconPos& pos = it->first;
00869 
00870         ListView_SetItemPosition32(_hwndListView, it->second, pos.second, pos.first);
00871     }
00872 }
00873 
00874 
00875 void DesktopShellView::refresh()
00876 {
00878 }

Generated on Sat May 26 2012 04:17:25 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.