2012-09-15 28 views
10

使用VBScript或任何其他編程語言以下幾點可能:更改Windows 7任務欄的位置自動根據屏幕的形狀或有關對接狀態

  • 檢測屏幕形狀 - 或計算機是否對接
  • 變化Windows任務欄的位置

我想實現:

我的筆記本電腦有14英寸寬屏:非常寬,但不是很高。我發現讓Windows任務欄位於屏幕左側是最方便的,因爲我可以節省寬度而不是垂直空間。

但是,當我在辦公室裏,我的電腦坐在擴展塢,並連接到一個很大的方形屏幕上。在這裏,我更喜歡將任務欄放置在其默認位置,即在底部。

我知道如何在任務欄屬性中手動切換兩個任務欄位置,當然。但我每天都會這樣做幾次,這很煩人。我的問題是:我可以自動更改任務欄位置嗎?

例如,在啓動時(或從休眠喚醒)的腳本將運行,用於檢測:

  • 絲網形狀比4高:3? (或其他號碼)
  • 計算機是否連接在塢站上?

如果是,則將任務欄放在底部,否則放在左側。

任何人都知道如何做到這一點,或可以把我放在正確的軌道上?或者是否已經有可以做到這一點的實用工具?爲什麼這是不是別人的機器上的一個好主意

+0

一個肯定的一點是,VBScript的將不能更改任務欄的位置沒有任何第三方工具。我建議使用* AutoIt *腳本(通過鼠標功能)根據當前屏幕大小和方向自動更改任務欄位置以及查詢停靠狀態(通過WMI對象)。 – Jay

+1

傑伊,我證明它可以做到,看到我的答案,不要低估vbscript – peter

回答

7

//普通擴充省略

腳本語言可能不會在這裏一個不錯的選擇,你需要的東西that pumps the message to listen to WM_DISPLAYCHANGE

當您收到消息時,您需要根據顯示器的分辨率計算任務欄的所需方向。然後您使用RmShutdown關閉Windows資源管理器。

// 無證行爲開始時,可​​能會破壞隨時

任務欄對接邊緣被存儲在字節13(如從APPBARDATA在ABE值中的一個),並且位置被存儲在字節25-40作爲win32 RECT。您可以在重新啓動資源管理器之前修改設置。

//無證行爲結束

示例代碼(完整源在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, ftKernel, ftUser; 
        if (GetProcessTimes(hProcess, &ftCreate, &ftExit,&ftKernel, &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); 
2

您可以在一個簡單的批處理或腳本做到這一點。 設置註冊表值以根據屏幕的當前分辨率定位任務欄(如果在對接中它將更高),然後重新啓動explorer.exe。 所以如批量設置在屏幕的左側任務欄會(假設你已經在d的bottom.reg文件:\ scripts文件夾)

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 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 
相關問題