Windows 탐색기에 신호를 보내 시스템 트레이 아이콘을 새로 고칠 수 있습니까?

StackOverflow https://stackoverflow.com/questions/74723

문제

이 문제는 꽤 오랫동안 저를 괴롭혀왔고 정말 짜증났습니다.

재부팅/전원 껐다 켜기 후에 로그인할 때마다 탐색기가 표시되는 데 약간의 시간이 걸립니다.모든 서비스가 부팅될 때까지 기다린 다음 로그인하는 단계를 수행했지만 아무런 차이가 없습니다.결과는 항상 동일합니다.응용 프로그램을 시작해도 일부 아이콘이 표시되지 않습니다.

하나의 응용 프로그램이 아이콘을 "고정"하게 만드는 코드를 조금 파헤쳤지만 탐색기가 해당 아이콘 정보를 모두 다시 읽을 수 있도록 수행할 수 있는 API 호출이 있습니까?무효화하거나 다시 그리는 것과 같은 것인가요?


분명히 Jon이 옳았던 것처럼 보이며 그렇게 하는 것은 불가능합니다.

저는 Bob Dizzle과 Mark Ransom 코드를 따라 이 코드를 작성했습니다(Delphi 코드).

procedure Refresh;
var
  hSysTray: THandle;
begin
  hSysTray := GetSystrayHandle;
  SendMessage(hSysTray, WM_PAINT, 0, 0);
end;

function GetSystrayHandle: THandle;
var
  hTray, hNotify, hSysPager: THandle;
begin
  hTray := FindWindow('Shell_TrayWnd', '');
  if hTray = 0 then
  begin
    Result := hTray;
    exit;
  end;

  hNotify := FindWindowEx(hTray, 0, 'TrayNotifyWnd', '');
  if hNotify = 0 then
  begin
    Result := hNotify;
    exit;
  end;

  hSyspager := FindWindowEx(hNotify, 0, 'SysPager', '');
  if hSyspager = 0 then
  begin
    Result := hSyspager;
    exit;
  end;

  Result := FindWindowEx(hSysPager, 0, 'ToolbarWindow32', 'Notification Area');
end;

그러나 아무 소용이 없습니다.

나는 심지어 시도했다

InvalidateRect()
그리고 아직도 쇼가 없습니다.

다른 제안이 있나요?

도움이 되었습니까?

해결책

이 블로그 항목을 살펴보십시오. 작업 표시줄 알림 영역 새로 고침.고아 아이콘을 제거하기 위해 시스템 트레이를 새로 고치려면 이 코드를 사용하고 있으며 완벽하게 작동합니다.블로그 항목은 매우 유익하며 작성자가 솔루션을 발견하기 위해 수행한 단계에 대한 훌륭한 설명을 제공합니다.

#define FW(x,y) FindWindowEx(x, NULL, y, L"")

void RefreshTaskbarNotificationArea()
{
    HWND hNotificationArea;
    RECT r;

    GetClientRect(
        hNotificationArea = FindWindowEx(
            FW(FW(FW(NULL, L"Shell_TrayWnd"), L"TrayNotifyWnd"), L"SysPager"),
            NULL,
            L"ToolbarWindow32",
            // L"Notification Area"), // Windows XP
            L"User Promoted Notification Area"), // Windows 7 and up
        &r);

    for (LONG x = 0; x < r.right; x += 5)
        for (LONG y = 0; y < r.bottom; y += 5)
            SendMessage(
                hNotificationArea,
                WM_MOUSEMOVE,
                0,
                (y << 16) + x);
}

다른 팁

Louis의 답변을 사용하는 사람을 위한 두 가지 중요한 세부 사항(출처: 작업 표시줄 알림 영역 새로 고침) Windows 7 또는 Windows 8의 경우:

먼저 답변이 반영되어 표시되는 것처럼 XP의 "알림 영역"이라는 제목이 Windows 7(실제로는 Vista일 가능성이 높음) 이상에서는 이제 "사용자 승격 알림 영역"이라는 제목으로 표시됩니다.

둘째, 이 코드는 현재 숨겨진 아이콘을 지우지 않습니다.이들은 별도의 창에 포함되어 있습니다.보이는 아이콘을 새로 고치려면 원본 코드를 사용하고, 숨겨진 아이콘을 새로 고치려면 다음 코드를 사용하세요.

//Hidden icons
GetClientRect(
    hNotificationArea = FindWindowEx(
        FW(NULL, L"NotifyIconOverflowWindow"),
        NULL,
        L"ToolbarWindow32",
        L"Overflow Notification Area"),
    &r);

for (LONG x = 0; x < r.right; x += 5)
    for (LONG y = 0; y < r.bottom; y += 5)
        SendMessage(
            hNotificationArea,
            WM_MOUSEMOVE,
            0,
            (y << 16) + x);

이를 수행하기 위해 코드 대신 실행할 유틸리티가 필요한 사람을 위해 이 업데이트를 사용하여 간단한 exe를 빌드했습니다. 새로 고침 알림 영역

시스템 트레이를 새로 고치려면 다음 코드를 포함하세요.

public const int WM_PAINT = 0xF;
[DllImport("USER32.DLL")]
public static extern int SendMessage(IntPtr hwnd, int msg, int character,
                                     IntPtr lpsText);

Send WM_PAINT Message to paint System Tray which will refresh it.
SendMessage(traynotifywnd, WM_PAINT, 0, IntPtr.Zero);

내가 아는 한 Gustavo는 불가능합니다. 알림 아이콘을 시스템 트레이에 넣고 올바른 상태로 유지하는 것은 각 애플리케이션에 달려 있습니다.

explorer.exe가 충돌할 때 특정 아이콘이 다시 나타나지 않는 경우가 종종 있습니다. 이는 프로세스가 충돌했기 때문이 아니라 단순히 explorer.exe의 새 인스턴스가 시작될 때 응용 프로그램이 시스템 트레이에 알림 아이콘을 넣지 않았기 때문입니다. 위로.다시 한 번 말씀드리지만, 책임은 애플리케이션에 있습니다.

더 좋은 소식을 전해드리지 못해 죄송합니다!

나는 작년에 이 문제를 다루었습니다. 코드홀릭 제목의 기사에 있는 웹로그 [델파이] SysTray 업데이트 중.

내 솔루션은 Delphi ActiveX/COM DLL입니다.다운로드 링크는 여전히 작동합니다(얼마나 오랫동안 작동하는지 알 수 없음). 플러그 회원 자격이 상실되었습니다.)

다음 C++ 코드를 사용하여 트레이 창에 대한 창 핸들을 가져옵니다. 메모: 이는 Windows XP에서만 테스트되었습니다.

HWND FindSystemTrayIcons(void)
{
    // the system tray icons are contained in a specific window hierarchy;
    // use the Spy++ utility to see the chain
    HWND hwndTray = ::FindWindow("Shell_TrayWnd", "");
    if (hwndTray == NULL)
        return NULL;
    HWND hwndNotifyWnd = ::FindWindowEx(hwndTray, NULL, "TrayNotifyWnd", "");
    if (hwndNotifyWnd == NULL)
        return NULL;
    HWND hwndSysPager = ::FindWindowEx(hwndNotifyWnd, NULL, "SysPager", "");
    if (hwndSysPager == NULL)
        return NULL;
    return ::FindWindowEx(hwndSysPager, NULL, "ToolbarWindow32", "Notification Area");
}

@Skip R 및 C에서 이 작업을 수행하려는 다른 사람은 이 코드가 Windows 10 64비트(그러나 mingw 32비트 패키지가 설치된)의 최근(가장 최근) mingw에서 컴파일된 것으로 확인되었으며 Windows XP에서 작동하는 것으로 보입니다. / 2003 오래된 알림 영역 아이콘을 제거합니다.

다음과 같이 Chocolatey를 통해 mingw를 설치했습니다.

choco install mingw --x86 --force --params "/exception:sjlj"

(마일리지는 달라질 수 있습니다. 내 시스템에서는 컴파일러가 여기에 설치되었습니다.

C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw32\bin\gcc.exe

그리고 나서 간단한

gcc refresh_notification_area.c

Windows 2003(32비트)에서 발생한 오래된 알림 영역 아이콘 문제를 해결한 a.exe를 생성했습니다.

위의 @Stephen Klancher에서 수정한 코드는 다음과 같습니다(이것은 내 목적을 충족한 Windows XP/2003에서만 작동할 수 있습니다).

#include <windows.h>

#define FW(x,y) FindWindowEx(x, NULL, y, "")

int main ()
{

    HWND hNotificationArea;
    RECT r;

    //WinXP
    // technique found at:
    // https://stackoverflow.com/questions/74723/can-you-send-a-signal-to-windows-explorer-to-make-it-refresh-the-systray-icons#18038441
    GetClientRect(
        hNotificationArea = FindWindowEx(
            FW(FW(FW(NULL, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
            NULL,
            "ToolbarWindow32",
            "Notification Area"),
        &r);

    for (LONG x = 0; x < r.right; x += 5)
        for (LONG y = 0; y < r.bottom; y += 5)
            SendMessage(
                hNotificationArea,
                WM_MOUSEMOVE,
                0,
                (y << 16) + x);

  return 0;

}

여러 번 시도한 끝에 알아야 할 세 가지 문제가 있음을 발견했습니다.

  • 숨겨진 트레이 창의 부모는 다음과 같습니다. NotifyIconOverflowWindow, 이것 말고도 Shell_TrayWnd.
  • 사용하면 안 된다 caption 매개변수 FindWindowEx 창을 찾으려면 Windows OS의 언어 버전이 많기 때문에 항상 동일한 제목은 아닙니다.
  • 사용 spy++ 원하는 것을 찾거나 확인하려면 Visual Studio를 사용하세요.

그래서 @Stephen Klancher와 @Louis Davis의 코드를 변경했습니다. 감사합니다.

다음 코드는 저에게 효과적이었습니다.

#define FW(x,y) FindWindowEx(x, NULL, y, L"")
void RefreshTaskbarNotificationArea()
{
    HWND hNotificationArea;
    RECT r;
    GetClientRect(hNotificationArea = FindWindowEx(FW(NULL, L"NotifyIconOverflowWindow"), NULL, L"ToolbarWindow32", NULL), &r);
    for (LONG x = 0; x < r.right; x += 5)
    {
        for (LONG y = 0; y < r.bottom; y += 5)
        {
            SendMessage(hNotificationArea, WM_MOUSEMOVE, 0, (y << 16) + x);
        }
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top