Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendesktop.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 = ▭ 00400 params.pvid = params.pvid;//@@ 00401 00402 hr = pShellView2->CreateViewWindow2(¶ms); 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
1.7.6.1
|