10

VBScript またはその他のプログラミング言語を使用して、次のことが可能ですか。

  • 画面の形状を検出する - またはコンピューターがドッキングされているかどうか
  • Windows タスクバーの場所を変更する

私が達成しようとしていること:

私のラップトップには 14 インチのワイドスクリーンがあります。幅はかなり広いですが、高さはあまりありません。Windows タスクバーを画面の左側に配置するのが最も便利だと思います。幅は確保できますが、垂直方向のスペースは確保できないからです。

しかし、オフィスにいるときは、私のコンピューターはドッキング ステーションに置かれ、大きな四角い画面に接続されています。ここでは、タスクバーをデフォルトの場所、つまり下部に配置することを好みます。

もちろん、タスクバーのプロパティで 2 つのタスクバーの場所を手動で切り替える方法は知っています。しかし、私はこれを毎日数回行うので、かなり面倒です。私の質問は、タスクバーの場所を自動的に変更できますか?

たとえば、起動時 (または休止状態からの復帰時) に、次のいずれかを検出するスクリプトが実行されます。

  • 画面の形状は 4:3 よりも高いですか? (または任意の番号)
  • コンピュータはドッキング ステーションにドッキングされていますか?

はいの場合はタスクバーを下に置き、そうでない場合は左に置きます。

誰でもこれを行う方法を知っているか、私を正しい軌道に乗せることができますか? または、これを実行できるユーティリティが既に存在しますか?

4

2 に答える 2

8

//これが他の誰かのマシンでは良い考えではない理由についての通常の拡張は省略されています

ここでは、スクリプト言語は適切な選択ではない可能性があります。メッセージを送信して WM_DISPLAYCHANGE をリッスンする何かが必要です。

メッセージが表示されたら、モニターの解像度に基づいてタスク バーの目的の向きを計算する必要があります。次に、RmShutdown を使用して Windows エクスプローラーを閉じます。

//文書化されていない動作が始まり、いつでも壊れる可能性があります

タスクバーのドッキング エッジはバイト 13 に ( APPBARDATAからの ABE 値の 1 つとして) 格納され、位置はバイト 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);
于 2013-01-16T22:52:39.413 に答える
2

これは、単純なバッチまたはスクリプトから実行できます。画面の現在の解像度に基づいてタスクバーを配置するようにレジストリ値を設定し (ドッキングの場合はより高くなります)、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 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
于 2013-01-17T00:49:02.063 に答える