/************************************************************************* * NTSHChangeNotifyRegister [SHELL32.640] * NOTES * Idlist is an array of structures and Count specifies how many items in the array. * count should always be one when calling SHChangeNotifyRegister, or * SHChangeNotifyDeregister will not work properly. */ EXTERN_C ULONG WINAPI NTSHChangeNotifyRegister( HWND hwnd, int fSources, LONG fEvents, UINT msg, int count, SHChangeNotifyEntry *idlist) { return SHChangeNotifyRegister(hwnd, fSources | SHCNRF_NewDelivery, fEvents, msg, count, idlist); }
BOOL CPage6::OnInitDialog() { CMFCPropertyPage::OnInitDialog(); m_wbdShellTree.Expand(m_wbdShellTree.GetRootItem(), TVE_EXPAND); m_wbdShellTree.SetRelatedList(&m_wndShellList); LPITEMIDLIST ppidl; if (SHGetSpecialFolderLocation(GetSafeHwnd(),CSIDL_BITBUCKET, &ppidl) != NOERROR) { return 0; } SHChangeNotifyEntry scnIDL; scnIDL.pidl = ppidl; scnIDL.fRecursive = TRUE; m_ulChangeIconNotifyID = SHChangeNotifyRegister(m_hWnd, SHCNF_ACCEPT_INTERRUPTS | SHCNF_ACCEPT_NON_INTERRUPTS, SHCNE_ALLEVENTS, UWM_CHANGE_SYSTEM_ICON, 1, &scnIDL); return TRUE; // return TRUE unless you set the focus to a control }
/// <summary> /// /// </summary> void TileGroup::SetFolder(LPWSTR folder) { PIDLIST_ABSOLUTE idList; // Just in case we are switching folders, deregister for old notifications if (mChangeNotifyUID != 0) { SHChangeNotifyDeregister(mChangeNotifyUID); mChangeNotifyUID = 0; } // Get the folder we are interested in if (_wcsicmp(folder, L"desktop") == 0) { SHGetKnownFolderIDList(FOLDERID_Desktop, 0, nullptr, &idList); SHGetDesktopFolder(reinterpret_cast<IShellFolder**>(&mWorkingFolder)); } else { mRootFolder->ParseDisplayName(nullptr, nullptr, folder, nullptr, &idList, nullptr); mRootFolder->BindToObject(idList, nullptr, IID_IShellFolder, reinterpret_cast<LPVOID*>(&mWorkingFolder)); } // Enumerate the contents of this folder LoadFolderRequest request; request.blackList = mHiddenItems; request.folder = mWorkingFolder; request.targetIconWidth = mTileSettings.mIconSize; nCore::LoadFolder(request, this); // Register for change notifications SHChangeNotifyEntry watchEntries[] = { idList, FALSE }; mChangeNotifyUID = SHChangeNotifyRegister( mWindow->GetWindowHandle(), CHANGE_SOURCES, CHANGE_EVENTS, mChangeNotifyMsg, 1, watchEntries); // Let go fo the PIDLists CoTaskMemFree(idList); }
void CRecBinViewer::InstallRBinNotify () { SHChangeNotifyEntry stPIDL; LPITEMIDLIST ppidl; SHGetSpecialFolderLocation(m_hWnd, CSIDL_BITBUCKET, &ppidl); stPIDL.pidl = ppidl; stPIDL.fRecursive = TRUE; m_hNotifyRBin = SHChangeNotifyRegister (m_hWnd, SHCNF_ACCEPT_INTERRUPTS | SHCNF_ACCEPT_NON_INTERRUPTS, SHCNE_ALLEVENTS, WM_SHELLNOTIFY, /* Message that would be sent by the Shell */ 1, &stPIDL); if(NULL == m_hNotifyRBin) { TRACE(_T("Change Register Failed for RecycleBin")); } }
LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { XBMC_Event newEvent; ZeroMemory(&newEvent, sizeof(newEvent)); static HDEVNOTIFY hDeviceNotify; if (uMsg == WM_CREATE) { SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams)); DIB_InitOSKeymap(); g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay")); shcne.pidl = NULL; shcne.fRecursive = TRUE; long fEvents = SHCNE_DRIVEADD | SHCNE_DRIVEREMOVED | SHCNE_MEDIAREMOVED | SHCNE_MEDIAINSERTED; SHChangeNotifyRegister(hWnd, SHCNRF_ShellLevel | SHCNRF_NewDelivery, fEvents, WM_MEDIA_CHANGE, 1, &shcne); RegisterDeviceInterfaceToHwnd(USB_HID_GUID, hWnd, &hDeviceNotify); return 0; } m_pEventFunc = (PHANDLE_EVENT_FUNC)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (!m_pEventFunc) return DefWindowProc(hWnd, uMsg, wParam, lParam); if(g_uQueryCancelAutoPlay != 0 && uMsg == g_uQueryCancelAutoPlay) return S_FALSE; switch (uMsg) { case WM_CLOSE: case WM_QUIT: case WM_DESTROY: newEvent.type = XBMC_QUIT; m_pEventFunc(newEvent); break; case WM_SHOWWINDOW: { bool active = g_application.m_AppActive; g_application.m_AppActive = wParam != 0; if (g_application.m_AppActive != active) g_Windowing.NotifyAppActiveChange(g_application.m_AppActive); CLog::Log(LOGDEBUG, __FUNCTION__"Window is %s", g_application.m_AppActive ? "shown" : "hidden"); } break; case WM_ACTIVATE: { bool active = g_application.m_AppActive; if (HIWORD(wParam)) { g_application.m_AppActive = false; } else { WINDOWPLACEMENT lpwndpl; lpwndpl.length = sizeof(lpwndpl); if (LOWORD(wParam) != WA_INACTIVE) { if (GetWindowPlacement(hWnd, &lpwndpl)) g_application.m_AppActive = lpwndpl.showCmd != SW_HIDE; } else { g_application.m_AppActive = g_Windowing.WindowedMode(); } } if (g_application.m_AppActive != active) g_Windowing.NotifyAppActiveChange(g_application.m_AppActive); CLog::Log(LOGDEBUG, __FUNCTION__"Window is %s", g_application.m_AppActive ? "active" : "inactive"); } break; case WM_SETFOCUS: case WM_KILLFOCUS: g_application.m_AppFocused = uMsg == WM_SETFOCUS; g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); if (uMsg == WM_KILLFOCUS) { CStdString procfile; if (CWIN32Util::GetFocussedProcess(procfile)) CLog::Log(LOGDEBUG, __FUNCTION__": Focus switched to process %s", procfile.c_str()); } break; case WM_SYSKEYDOWN: switch (wParam) { case VK_F4: //alt-f4, default event quit. return(DefWindowProc(hWnd, uMsg, wParam, lParam)); case VK_RETURN: //alt-return if ((lParam & REPEATED_KEYMASK) == 0) g_graphicsContext.ToggleFullScreenRoot(); return 0; } //deliberate fallthrough case WM_KEYDOWN: { switch (wParam) { case VK_CONTROL: if ( lParam & EXTENDED_KEYMASK ) wParam = VK_RCONTROL; else wParam = VK_LCONTROL; break; case VK_SHIFT: /* EXTENDED trick doesn't work here */ if (GetKeyState(VK_LSHIFT) & 0x8000) wParam = VK_LSHIFT; else if (GetKeyState(VK_RSHIFT) & 0x8000) wParam = VK_RSHIFT; break; case VK_MENU: if ( lParam & EXTENDED_KEYMASK ) wParam = VK_RMENU; else wParam = VK_LMENU; break; } XBMC_keysym keysym; TranslateKey(wParam, HIWORD(lParam), &keysym, 1); newEvent.type = XBMC_KEYDOWN; newEvent.key.keysym = keysym; m_pEventFunc(newEvent); } return(0); case WM_SYSKEYUP: case WM_KEYUP: { switch (wParam) { case VK_CONTROL: if ( lParam&EXTENDED_KEYMASK ) wParam = VK_RCONTROL; else wParam = VK_LCONTROL; break; case VK_SHIFT: { uint32_t scanCodeL = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC); uint32_t scanCodeR = MapVirtualKey(VK_RSHIFT, MAPVK_VK_TO_VSC); uint32_t keyCode = (uint32_t)((lParam & 0xFF0000) >> 16); if (keyCode == scanCodeL) wParam = VK_LSHIFT; else if (keyCode == scanCodeR) wParam = VK_RSHIFT; } break; case VK_MENU: if ( lParam&EXTENDED_KEYMASK ) wParam = VK_RMENU; else wParam = VK_LMENU; break; } XBMC_keysym keysym; TranslateKey(wParam, HIWORD(lParam), &keysym, 1); if (wParam == VK_SNAPSHOT) newEvent.type = XBMC_KEYDOWN; else newEvent.type = XBMC_KEYUP; newEvent.key.keysym = keysym; m_pEventFunc(newEvent); } return(0); case WM_APPCOMMAND: // MULTIMEDIA keys are mapped to APPCOMMANDS { CLog::Log(LOGDEBUG, "WinEventsWin32.cpp: APPCOMMAND %d", GET_APPCOMMAND_LPARAM(lParam)); newEvent.appcommand.type = XBMC_APPCOMMAND; newEvent.appcommand.action = GET_APPCOMMAND_LPARAM(lParam); if (m_pEventFunc(newEvent)) return TRUE; else return DefWindowProc(hWnd, uMsg, wParam, lParam); } case WM_GESTURENOTIFY: { OnGestureNotify(hWnd, lParam); return DefWindowProc(hWnd, WM_GESTURENOTIFY, wParam, lParam); } case WM_GESTURE: { OnGesture(hWnd, lParam); return 0; } case WM_SYSCHAR: if (wParam == VK_RETURN) //stop system beep on alt-return return 0; break; case WM_SETCURSOR: if (HTCLIENT != LOWORD(lParam)) g_Windowing.ShowOSMouse(true); break; case WM_MOUSEMOVE: newEvent.type = XBMC_MOUSEMOTION; newEvent.motion.x = GET_X_LPARAM(lParam); newEvent.motion.y = GET_Y_LPARAM(lParam); newEvent.motion.state = 0; m_pEventFunc(newEvent); return(0); case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: newEvent.type = XBMC_MOUSEBUTTONDOWN; newEvent.button.state = XBMC_PRESSED; newEvent.button.x = GET_X_LPARAM(lParam); newEvent.button.y = GET_Y_LPARAM(lParam); newEvent.button.button = 0; if (uMsg == WM_LBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_LEFT; else if (uMsg == WM_MBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_MIDDLE; else if (uMsg == WM_RBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_RIGHT; m_pEventFunc(newEvent); return(0); case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: newEvent.type = XBMC_MOUSEBUTTONUP; newEvent.button.state = XBMC_RELEASED; newEvent.button.x = GET_X_LPARAM(lParam); newEvent.button.y = GET_Y_LPARAM(lParam); newEvent.button.button = 0; if (uMsg == WM_LBUTTONUP) newEvent.button.button = XBMC_BUTTON_LEFT; else if (uMsg == WM_MBUTTONUP) newEvent.button.button = XBMC_BUTTON_MIDDLE; else if (uMsg == WM_RBUTTONUP) newEvent.button.button = XBMC_BUTTON_RIGHT; m_pEventFunc(newEvent); return(0); case WM_MOUSEWHEEL: { // SDL, which our events system is based off, sends a MOUSEBUTTONDOWN message // followed by a MOUSEBUTTONUP message. As this is a momentary event, we just // react on the MOUSEBUTTONUP message, resetting the state after processing. newEvent.type = XBMC_MOUSEBUTTONDOWN; newEvent.button.state = XBMC_PRESSED; // the coordinates in WM_MOUSEWHEEL are screen, not client coordinates POINT point; point.x = GET_X_LPARAM(lParam); point.y = GET_Y_LPARAM(lParam); WindowFromScreenCoords(hWnd, &point); newEvent.button.x = (uint16_t)point.x; newEvent.button.y = (uint16_t)point.y; newEvent.button.button = GET_Y_LPARAM(wParam) > 0 ? XBMC_BUTTON_WHEELUP : XBMC_BUTTON_WHEELDOWN; m_pEventFunc(newEvent); newEvent.type = XBMC_MOUSEBUTTONUP; newEvent.button.state = XBMC_RELEASED; m_pEventFunc(newEvent); } return(0); case WM_SIZE: newEvent.type = XBMC_VIDEORESIZE; newEvent.resize.type = XBMC_VIDEORESIZE; newEvent.resize.w = GET_X_LPARAM(lParam); newEvent.resize.h = GET_Y_LPARAM(lParam); if (newEvent.resize.w * newEvent.resize.h) m_pEventFunc(newEvent); return(0); case WM_MEDIA_CHANGE: { // There may be multiple notifications for one event // There are also a few events we're not interested in, but they cause no harm // For example SD card reader insertion/removal long lEvent; PIDLIST_ABSOLUTE *ppidl; HANDLE hLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent); if (hLock) { char drivePath[MAX_PATH+1]; if (!SHGetPathFromIDList(ppidl[0], drivePath)) break; switch(lEvent) { case SHCNE_DRIVEADD: case SHCNE_MEDIAINSERTED: CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media has arrived.", drivePath); if (GetDriveType(drivePath) == DRIVE_CDROM) g_application.getApplicationMessenger().OpticalMount(drivePath, true); else CWin32StorageProvider::SetEvent(); break; case SHCNE_DRIVEREMOVED: case SHCNE_MEDIAREMOVED: CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media was removed.", drivePath); if (GetDriveType(drivePath) == DRIVE_CDROM) g_application.getApplicationMessenger().OpticalUnMount(drivePath); else CWin32StorageProvider::SetEvent(); break; } SHChangeNotification_Unlock(hLock); } break; } case WM_POWERBROADCAST: if (wParam==PBT_APMSUSPEND) { CLog::Log(LOGDEBUG,"WM_POWERBROADCAST: PBT_APMSUSPEND event was sent"); CWin32PowerSyscall::SetOnSuspend(); } else if(wParam==PBT_APMRESUMEAUTOMATIC) { CLog::Log(LOGDEBUG,"WM_POWERBROADCAST: PBT_APMRESUMEAUTOMATIC event was sent"); CWin32PowerSyscall::SetOnResume(); } break; case WM_DEVICECHANGE: { PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam; CStdString dbcc_name(b->dbcc_name); dbcc_name = CKeymapLoader::ParseWin32HIDName(b->dbcc_name); switch (wParam) { case DBT_DEVICEARRIVAL: CKeymapLoader().DeviceAdded(dbcc_name); break; case DBT_DEVICEREMOVECOMPLETE: CKeymapLoader().DeviceRemoved(dbcc_name); break; case DBT_DEVNODES_CHANGED: //CLog::Log(LOGDEBUG, "HID Device Changed"); //We generally don't care about Change notifications, only need to know if a device is removed or added to rescan the device list break; } break; } case WM_PAINT: //some other app has painted over our window, mark everything as dirty g_windowManager.MarkDirty(); break; } return(DefWindowProc(hWnd, uMsg, wParam, lParam)); }
void CRecBinViewer::InstallShellNotify () { SHChangeNotifyEntry stPIDL; LPITEMIDLIST ppidl; int iPos = 0; TCHAR szPath[MAX_PATH]; WIN32_FIND_DATA findData; HANDLE hFindData = INVALID_HANDLE_VALUE; HRESULT hr = S_OK; CDriveArray ar; GetDrives (ar); for (unsigned int i = 0; i < ar.size (); i++) { if (ar[i].m_nType != DRIVE_FIXED) continue; SHQUERYRBINFO qrbi; ZeroMemory (&qrbi, sizeof (qrbi)); qrbi.cbSize = sizeof (qrbi); hr = SHQueryRecycleBin (ar[i].m_Path, &qrbi); if (SUCCEEDED (hr)) { ZeroMemory (&findData, sizeof (findData)); wsprintf (szPath, _T("%sRecycler"), static_cast<LPCWSTR>(ar[i].m_Path)); hFindData = FindFirstFile (szPath, &findData); if (INVALID_HANDLE_VALUE != hFindData) { ppidl = SHSimpleIDListFromPath (szPath); stPIDL.pidl = ppidl; m_pidlDrives[iPos] = ppidl; m_hNotifyDrives[iPos] = SHChangeNotifyRegister (m_hWnd, SHCNF_ACCEPT_INTERRUPTS | SHCNF_ACCEPT_NON_INTERRUPTS, SHCNE_RMDIR | SHCNE_RENAMEFOLDER | SHCNE_DELETE | SHCNE_RENAMEITEM, WM_SHELLNOTIFYRBINDIR, 1, &stPIDL); iPos ++; FindClose (hFindData); } else { ZeroMemory (&findData, sizeof (findData)); wsprintf (szPath, _T("%sRecycled"), static_cast<LPCWSTR>(ar[i].m_Path)); hFindData = FindFirstFile (szPath, &findData); if (INVALID_HANDLE_VALUE != hFindData) { ppidl = SHSimpleIDListFromPath (szPath); stPIDL.pidl = ppidl; m_pidlDrives[iPos] = ppidl; m_hNotifyDrives[iPos] = SHChangeNotifyRegister (m_hWnd, SHCNF_ACCEPT_INTERRUPTS | SHCNF_ACCEPT_NON_INTERRUPTS, SHCNE_RMDIR | SHCNE_RENAMEFOLDER | SHCNE_DELETE | SHCNE_RENAMEITEM, WM_SHELLNOTIFYRBINDIR, 1, &stPIDL); iPos ++; FindClose (hFindData); } } } } }
/// <summary> /// Handles window messages. /// </summary> LRESULT WINAPI TileGroup::HandleMessage(HWND window, UINT message, WPARAM wParam, LPARAM lParam, LPVOID) { if (message == mChangeNotifyMsg) { return HandleChangeNotify(HANDLE(wParam), DWORD(lParam)); } if (mContextMenu3) { LRESULT result; if (SUCCEEDED(mContextMenu3->HandleMenuMsg2(message, wParam, lParam, &result))) { return result; } } if (mContextMenu2) { if (SUCCEEDED(mContextMenu2->HandleMenuMsg(message, wParam, lParam))) { return 0; } } switch (message) { case WM_KEYDOWN: switch (wParam) { case 'A': if (GetKeyState(VK_CONTROL) < 0) { SelectAll(); } break; case 'C': if (GetKeyState(VK_CONTROL) < 0) { DoCopy(false); } break; case 'V': if (GetKeyState(VK_CONTROL) < 0) { DoPaste(); } break; case 'X': if (GetKeyState(VK_CONTROL) < 0) { DoCopy(true); } break; case 'Z': if (GetKeyState(VK_CONTROL) < 0) { DoUndo(); } break; case VK_DELETE: DeleteSelectedFiles(); break; case VK_RETURN: OpenSelectedFiles(); break; case VK_F2: RenameSelectedFiles(); break; case VK_F5: UpdateAllIcons(); break; case VK_UP: case VK_DOWN: case VK_LEFT: case VK_RIGHT: break; } break; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: if (!mInRectangleSelection) { StartRectangleSelection(D2D1::Point2U(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); } else { EndRectangleSelection(D2D1::Point2U(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); } break; case WM_MOUSEMOVE: if (mInRectangleSelection) { MoveRectangleSelection(D2D1::Point2U(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); } break; case WM_LBUTTONUP: case WM_RBUTTONUP: if (mInRectangleSelection) { EndRectangleSelection(D2D1::Point2U(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); } else if (GetKeyState(VK_CONTROL) >= 0) { DeselectAll(); } break; case Window::WM_TOPPARENTLOST: mChangeNotifyMsg = 0; if (mChangeNotifyUID != 0) { SHChangeNotifyDeregister(mChangeNotifyUID); mChangeNotifyUID = 0; } break; case Window::WM_NEWTOPPARENT: { // TODO(Erik): This is unacceptable. We have to pick up change notifications while we don't // have a top parent. IPersistFolder2 *ipsf2; LPITEMIDLIST curFolder; HRESULT hr; mChangeNotifyMsg = mWindow->RegisterUserMessage(this); if (SUCCEEDED(hr = mWorkingFolder->QueryInterface(IID_IPersistFolder2, (LPVOID*)&ipsf2))) { if (SUCCEEDED(hr = ipsf2->GetCurFolder(&curFolder))) { // (Re)Register for change notifications SHChangeNotifyEntry watchEntries[] = { curFolder, FALSE }; mChangeNotifyUID = SHChangeNotifyRegister( window, CHANGE_SOURCES, CHANGE_EVENTS, mChangeNotifyMsg, 1, watchEntries); // Let go fo the PIDLists CoTaskMemFree(curFolder); } ipsf2->Release(); } } break; } mEventHandler->HandleMessage(window, message, wParam, lParam); return DefWindowProc(window, message, wParam, lParam); }