根据屏幕形状或停靠状态自动更改Windows 7任务栏位置

使用VBScript或任何其他编程语言可能会出现以下情况:

  • 检测屏幕形状 – 或者计算机是否停靠
  • 更改Windows任务栏的位置

我正在努力实现的是:

我的笔记本电脑有一个14英寸的宽屏幕,宽度很大,但不是很高,我觉得把Windows任务栏放在屏幕左边是最方便的,因为我可以放宽宽度而不是垂直空间。

但是,在办公室里,我的电脑坐在一个基座上,挂在一个很大的方形屏幕上。 在这里,我更喜欢将任务栏放在默认位置,即在底部。

当然,我知道如何在任务栏属性中手动切换两个任务栏位置。 但我每天都这样做几次,这很烦人。 我的问题是:我可以自动更改任务栏位置吗?

例如,在启动时(或从hibernate状态唤醒)脚本将运行,检测以下任一情况:

  • 屏幕形状高于4:3? (或者其他数字)
  • 计算机是否停靠在坞站?

如果是的话,把任务栏放在底部,否则在左边。

任何人都知道如何做到这一点,或可以把我放在正确的轨道上? 还是有一个实用工具可以做到这一点?

//正常增加为什么这不是在别人的机器省略好主意

一个脚本语言在这里可能不是一个好的选择,你需要一些信息来聆听WM_DISPLAYCHANGE 。

当您收到消息时,您需要根据显示器的分辨率计算任务栏的所需方向。 然后,您使用RmShutdown关闭Windows资源管理器。

// 无证行为开始,随时可能中断

任务栏对接边缘存储在字节13(作为来自APPBARDATA的ABE值之一 ),并且位置作为win32 RECT存储在字节25-40中。 您可以在重新启动资源管理器之前修改设置。

//无证行为结束

示例代码(完整源代码https://github.com/jiangsheng/Samples/tree/master/AppBarTest ):

//returns the process id and create time for the oldest explorer.exe RM_UNIQUE_PROCESS GetExplorerApplication() { RM_UNIQUE_PROCESS result={0}; DWORD bytesReturned=0; DWORD processIdSize=4096; std::vector<DWORD> processIds; processIds.resize(1024); EnumProcesses(processIds.data(),processIdSize,&bytesReturned); while(bytesReturned==processIdSize) { processIdSize+=processIdSize; processIds.resize(processIdSize/4); EnumProcesses(processIds.data(),processIdSize,&bytesReturned); } std::for_each(processIds.begin(), processIds.end(), [&result] (DWORD processId) { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, processId); if (hProcess) { std::wstring imageName; imageName.resize(4096); if(GetProcessImageFileName (hProcess,(LPWSTR)imageName.data(),4096)>0) { if(wcscmp(L"explorer.exe",PathFindFileName(imageName.data()))==0) { //this is assmuing the user is not running elevated and won't see explorer processes in other sessions FILETIME ftCreate, ftExit, ftcoreel, ftUser; if (GetProcessTimes(hProcess, &ftCreate, &ftExit,&ftcoreel, &ftUser)) { if(result.dwProcessId==0) { result.dwProcessId=processId; result.ProcessStartTime=ftCreate; } else if(CompareFileTime(&result.ProcessStartTime,&ftCreate)>0) { result.dwProcessId=processId; result.ProcessStartTime=ftCreate; } } } } CloseHandle(hProcess); } }); return result; } //taskbar position calculating code omitted DWORD dwSession=0; WCHAR szSessionKey[CCH_RM_SESSION_KEY+1] = { 0 }; DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey); if (dwError == ERROR_SUCCESS) { RM_UNIQUE_PROCESS rgApplications[1]={GetExplorerApplication()}; dwError=RmRegisterResources( dwSession,0,NULL,1,rgApplications,0,NULL); DWORD dwReason; UINT nProcInfoNeeded; UINT nProcInfo = 10; RM_PROCESS_INFO rgpi[10]; dwError = RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, rgpi, &dwReason); if(dwReason==RmRebootReasonNone)//now free to restart explorer { RmShutdown(dwSession,RmForceShutdown,NULL);//important, if we change the registry before shutting down explorer will override our change //using undocumented setting structure, could break any time //edge setting is stored at HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2!Settings HKEY hKey={0}; DWORD result=0; result=::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StuckRects2"), 0, KEY_READ|KEY_WRITE, &hKey) ; if (result== ERROR_SUCCESS) { std::vector<BYTE> data; data.resize(256); TCHAR settingValue[]= _T("Settings"); DWORD dwKeyDataType=0; DWORD dwDataBufSize=data.size(); result=::RegQueryValueEx(hKey,settingValue, NULL, &dwKeyDataType, (LPBYTE) data.data(), &dwDataBufSize); while(ERROR_MORE_DATA==result) { data.resize(256+data.size()); dwDataBufSize=data.size(); result=::RegQueryValueEx(hKey,settingValue, NULL, &dwKeyDataType, (LPBYTE) data.data(), &dwDataBufSize); } data.resize(dwDataBufSize); if(result==ERROR_SUCCESS) { switch ( dwKeyDataType ) { case REG_BINARY: if(data.size()==40) { BYTE taskbarPosition=data[12]; taskbarPosition=edge; data[12]=taskbarPosition; RECT* taskbarRect=(RECT*)&data[24]; CopyRect (taskbarRect,&abd.rc); result=::RegSetValueEx(hKey,settingValue,0,REG_BINARY,(LPBYTE) data.data(), dwDataBufSize); } break; } } ::RegCloseKey( hKey ); } RmRestart (dwSession,0,NULL); } } RmEndSession(dwSession); 

你可以通过一个简单的批处理或脚本来完成。 设置注册表值以根据屏幕的当前分辨率定位任务栏(如果在对接中将会更高),然后重新启动explorer.exe。 因此,例如批量设置屏幕左侧的任务栏(假设您在d:\ scripts文件夹中有bottom.reg文件)

 reg add d:\scripts\Bottom.reg @echo off taskkill /f /IM explorer.exe explorer.exe 

bottom.reg的内容是

 Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2] "Settings"=hex:28,00,00,00,ff,ff,ff,ff,02,00,00,00,03,00,00,00,3e,00,00,00,2e,\ 00,00,00,00,00,00,00,82,04,00,00,80,07,00,00,b0,04,00,00 

和为left.reg

 Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2] "Settings"=hex:28,00,00,00,ff,ff,ff,ff,02,00,00,00,00,00,00,00,3e,00,00,00,2e,\ 00,00,00,00,00,00,00,00,00,00,00,3e,00,00,00,b0,04,00,00 

你会有一些闪烁,但因为你会做到这一点,当你启动Windows,这不会是一个问题,我想。 我在Windows 7上测试了这个。

编辑:做了一个基于屏幕分辨率做同样的事情的VBScript

 HKEY_CURRENT_USER = &H80000001 Set WshShell = CreateObject("WScript.Shell") strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set ObjRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv") 'Get curr. user name Set colItems = objWMIService.ExecQuery("Select * From Win32_ComputerSystem") For Each objItem in colItems strCurrentUserName = objItem.UserName Next Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor where DeviceID = 'DesktopMonitor1'",,0) For Each objItem in colItems intHorizontal = objItem.ScreenWidth intVertical = objItem.ScreenHeight Next bottom = Array(&H28,&H00,&H00,&H00,&Hff,&Hff,&Hff,&Hff,&H02,&H00,&H00,&H00,&H03,&H00,&H00,&H00,&H3e,&H00,&H00,&H00,&H2e,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H82,&H04,&H00,&H00,&H80,&H07,&H00,&H00,&Hb0,&H04,&H00,&H00) left_ = Array(&H28,&H00,&H00,&H00,&Hff,&Hff,&Hff,&Hff,&H02,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H3e,&H00,&H00,&H00,&H2e,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H3e,&H00,&H00,&H00,&Hb0,&H04,&H00,&H00) if intHorizontal >= 1920 then regdata = bottom else regdata = left_ end if ObjRegistry.SetBinaryValue HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2\", "Settings", regdata 'Restart user shell Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = 'Explorer.exe'") For Each objProcess in colProcessList colProperties = objProcess.GetOwner(strNameOfUser,strUserDomain) wscript.echo colProperties If strUserDomain & "\" & strNameOfUser = strCurrentUserName then wscript.echo "restarting" objProcess.Terminate() end if Next