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 = ▭ 00397 params.pvid = params.pvid;//@@ 00398 00399 hr = pShellView2->CreateViewWindow2(¶ms); 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 ![]() |