2016-07-29 5 views
0

Windowsシステムで古いソフトウェアを識別し、ユーザーと対話して更新するプログラムを作成しました。Windows APIを使用して複数のバルーンを条件付きで表示する - Delphiのシステムトレイアイコン

システムトレイアイコンを表示し、システムにインストールされているアップデート/ソフトウェアの使用可能/ダウンロードに関するバルーンヒントを表示するソフトウェアアップデータプログラムがあります。

問題は、各タスクが処理しているときに複数のバルーンヒントを表示できないことです。このようなアップデートは、ソフトウェアのために利用可能であるとき、それはAn update for Software Name is available.のようなバルーンを示すユーザーを忘れてはならないと、ユーザが再びシステムトレイにそれをダウンロードし、最小限にすることを選択したとき、バルーンヒントが再びしかしUpdates are downloading...Click to view the Progress of Downloads.

のようなものを示さなければならない、など私はシステムトレーアイコンを1つだけ使用してこれをどうやって行うことができるのかを知りたいですか?

フラグNIM_MODIFYフラグをもう一度使用して、プログラムの現在の状態に応じてバルーンチップを変更できますか?

これについて検索したところ、いくつかの例が見つかりましたが、Visual StudioとC++では見つかりました。プログラムが実行されているとき、私は複数のヒントを表示しようとした方法です

unit MainForm-1; 

... 

const 
    NIF_INFO = $10; 
    NIF_MESSAGE = 1; 
    NIF_ICON = 2; 
    NOTIFYICON_VERSION = 3; 
    NIF_TIP = 4; 
    NIM_SETVERSION = $00000004; 
    NIM_SETFOCUS = $00000003; 
    NIIF_INFO = $00000001; 
    NIIF_WARNING = $00000002; 
    NIIF_ERROR = $00000003; 

    NIN_BALLOONSHOW = WM_USER + 2; 
    NIN_BALLOONHIDE = WM_USER + 3; 
    NIN_BALLOONTIMEOUT = WM_USER + 4; 
    NIN_BALLOONUSERCLICK = WM_USER + 5; 
    NIN_SELECT = WM_USER + 0; 
    NINF_KEY = $1; 
    NIN_KEYSELECT = NIN_SELECT or NINF_KEY; 

    TRAY_CALLBACK = WM_USER + $7258; 

    PNewNotifyIconData = ^TNewNotifyIconData; 
    TDUMMYUNIONNAME = record 
    case Integer of 
     0: (uTimeout: UINT); 
     1: (uVersion: UINT); 
    end; 

    TNewNotifyIconData = record 
    cbSize: DWORD; 
    Wnd: HWND; 
    uID: UINT; 
    uFlags: UINT; 
    uCallbackMessage: UINT; 
    hIcon: HICON; 
    szTip: array [0..127] of Char; 
    dwState: DWORD;/
    dwStateMask: DWORD; 
    szInfo: array [0..255] of Char; 
    DUMMYUNIONNAME: TDUMMYUNIONNAME; 
    szInfoTitle: array [0..63] of Char; 
    dwInfoFlags: DWORD; 
end; 

type 
    MainForm-1 = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
private 
    IconData: TNewNotifyIconData; 
    procedure SysTrayIconMessageHandler(var Msg: TMessage); message TRAY_CALLBACK; 
    procedure AddSysTrayIcon; 
    procedure ShowBalloonTips; 
    procedure DeleteSysTrayIcon; 
public 
end; 

var 
    MainForm-1: TForm; 

implementation 

uses 
ShellAPI...,.....,; 

procedure MainForm-1.SysTrayIconMessageHandler(var Msg: TMessage); 
begin 
    case Msg.lParam of 
    WM_MOUSEMOVE:; 
    WM_LBUTTONDOWN:; 
    WM_LBUTTONUP:; 
    WM_LBUTTONDBLCLK:; 
    WM_RBUTTONDOWN:; 
    WM_RBUTTONUP:; 
    WM_RBUTTONDBLCLK:; 
    NIN_BALLOONSHOW:; 
    NIN_BALLOONHIDE:; 
    NIN_BALLOONTIMEOUT: 
    NIN_BALLOONUSERCLICK:; 
end; 
end; 

procedure MainForm-1.AddSysTrayIcon; 
begin 
    IconData.cbSize := SizeOf(IconData); 
    IconData.Wnd := AllocateHWnd(SysTrayIconMessageHandler); 
    IconData.uID := 0; 
    IconData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP; 
    IconData.uCallbackMessage := TRAY_CALLBACK; 
    IconData.hIcon := Application.Icon.Handle; 
    IconData.szTip := 'Software Updater is running'; 
    if not Shell_NotifyIcon(NIM_ADD, @IconData) then 
    ShowMessage('System Tray Icon cannot be created.'); 
end; 

procedure MainForm-1.DisplayBalloonTips; 
var 
    TipInfo, TipTitle: string; 
begin 
    IconData.cbSize := SizeOf(IconData); 
    IconData.uFlags := NIF_INFO; 
    if ssHelperState = UpdatesAvailable then TipInfo := 'Updates are available to the programs installed on your Computer' + ' Click to see details.'; 
    if ssHelperState = UpdatesDownloading then TipInfo := 'Updates are downloading in the background. Click to view the details.'; 
    strPLCopy(IconData.szInfo, TipInfo, SizeOf(IconData.szInfo) - 1); 
    IconData.DUMMYUNIONNAME.uTimeout := 2500; 
    if ssHelperState = UpdatesAvailable then TipTitle := 'Updates are Available...'; 
    if ssHelperState = UpdatesDownloading then TipTitle := 'Downloading the Updates...'; 
    strPLCopy(IconData.szInfoTitle, TipTitle, SizeOf(IconData.szInfoTitle) - 1); 
    IconData.dwInfoFlags := NIIF_INFO; 
    Shell_NotifyIcon(NIM_MODIFY, @IconData); 
    {Following code is for testing purpose.} 
    IconData.DUMMYUNIONNAME.uVersion := NOTIFYICON_VERSION; 
    if not Shell_NotifyIcon(NIM_SETVERSION, @IconData) then 
    ShowMessage('Setting the Version is Failed.'); 
end; 

procedure MainForm-1.DeleteSysTrayIcon; 
begin 
    DeallocateHWnd(IconData.Wnd); 
    if not Shell_NotifyIcon(NIM_DELETE, @IconData) then 
    ShowMessage('Unable to delete System Tray Icon.'); 
end; 

procedure MainForm-1.FormCreate(Sender: TObject); 
begin 
    AddSysTrayIcon; 
    ShowBalloonTips; 
end; 

procedure MainForm-1.FormDestroy(Sender: TObject); 
begin 
    DeleteSysTrayIcon; 
end; 
... 
end. 

しかし、これは失敗しているとプログラムがあるとき、私は何度も何度も同じバルーンヒント(第一)を得続けます実行中.......

NIN_BALLOONSHOWNIN_BALLOONHIDEフラグを正しく使用する方法がわかりません。だから、あなたの重要な助けを進んでいただきありがとうございます。

答えて

1

なぜすべてを手動で宣言していますか? Delphi 2009には既にShell_NotifyIcon() APIの宣言があります。それらはShellAPIユニットにあります。 uVersionフィールド(Delphi 2010で追加されたフィールド)を除いて、使用しようとしているものすべてを宣言します。 guidItemフィールドとhBalloonIconフィールドを使用していないので、ここではそれらについては心配しないでください。 uTimeoutフィールドは存在し、uVersionのユニオンでラップされているため、データサイズは変更されません。したがって、uVersionを使用する場合は、uTimeoutを使用してください(または、独自のユニオンを定義してフィールドを型キャストしたり、しかしそれは過剰です)。 API全体を再宣言する必要はありません。

あなたは大丈夫です、あなたがShell_NotifyIcon()を呼び出す同じIconData変数ごとに、再利用されているが、あなたのヘルパー状態がUpdatesAvailableUpdatesDownloadingでない場合は、szTipszInfoTitleフィールドをクリアしていないため、トレイアイコンが最後のヒントを表示し続けます/あなたが設定した風船。ヒント/風船がもう必要ないときは、これらのフィールドをクリアする必要があります。

NIN_BALLOONSHOWおよびNIN_BALLOONHIDEはフラグではありません。トレイアイコンの登録済みHWNDに送信される通知です。通知を受け取るには、WnduCallbackMessageフィールドに記入し、NIF_MESSAGEフラグを有効にする必要があります。

また、WM_TASKBARCREATEDメッセージを処理する必要があります。何らかの理由でExplorerが再起動した場合(クラッシュまたはユーザーによって殺された場合)、タスクバーが再作成されるため、トレイアイコンを再度追加する必要があります。

また、メッセージハンドラが未処理のウィンドウメッセージをDefWindowProc()に渡すか、システムをロックアップするか、少なくともアプリケーションをロックすることができます。

最後に、Delphi 2009はUnicode版のDelphiですが、Unicodeを正しく処理していないコードがいくつかあります。具体的には、szTipszInfoTitleStrPLCopy()を入力する場合、SizeOf()の代わりにLength()を使用する必要があります。コピーは、バイト数ではなく文字数で表されます。そうは言って

、より多くのこのような何かしてみてください:私はそれを知っているが、 `DUMMYUNIONNAME`は、Windows 7の` ShellAPI`バージョン(このPC)で宣言され、それされていないので、私はそれらを手動で宣言

unit MainForm1; 

interface 

uses 
    ..., ShellAPI; 

type 
    eHelperState = (Idle, UpdatesAvailable, UpdatesDownloading); 

    MainForm = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    private 
    TaskbarCreatedMsg: UINT; 
    IconData: NOTIFYICONDATA; 
    IconAdded: Boolean; 
    ssHelperState: eHelperState; 
    procedure SysTrayIconMessageHandler(var Message: TMessage); 
    procedure AddSysTrayIcon; 
    procedure ShowBalloonTips; 
    procedure DeleteSysTrayIcon; 
    procedures SetHelperState(NewState: eHelperState); 
    ... 
end; 

var 
    MainForm: TForm; 

implementation 

const 
    TRAY_CALLBACK = WM_USER + $7258; 
    {$IF RTLVersion < 21} 
    NOTIFYICON_VERSION_4 = 4; 
    {$IFEND} 

procedure MainForm.FormCreate(Sender: TObject); 
begin 
    TaskbarCreatedMsg := RegisterWindowMessage('TaskbarCreated'); 
    IconData.cbSize := SizeOf(IconData); 
    IconData.Wnd := AllocateHWnd(SysTrayIconMessageHandler); 
    IconData.uID := 1; 
    AddSysTrayIcon; 
end; 

procedure MainForm.FormDestroy(Sender: TObject); 
begin 
    DeleteSysTrayIcon; 
    DeallocateHWnd(IconData.Wnd); 
end; 

procedure MainForm.AddSysTrayIcon; 
begin 
    IconData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP; 
    IconData.uCallbackMessage := TRAY_CALLBACK; 
    IconData.hIcon := Application.Icon.Handle; 
    StrLCopy(IconData.szTip, 'Software Updater is running', Length(IconData.szTip)); 

    IconAdded := Shell_NotifyIcon(NIM_ADD, @IconData); 
    if not IconAdded then 
    begin 
    ShowMessage('Unable to add System Tray Icon.'); 
    Exit; 
    end; 

    if CheckWin32Version(5, 0) then 
    begin 
    IconData.{$IF RTLVersion >= 21}uVersion{$ELSE}uTimeout{$IFEND} := NOTIFYICON_VERSION_4; 
    if not Shell_NotifyIcon(NIM_SETVERSION, @IconData) then 
     ShowMessage('Unable to set version for System Tray Icon.'); 
    end; 
end; 

procedure MainForm.DisplayBalloonTips; 
var 
    Tip, InfoText, InfoTitle: string; 
begin 
    if not IconAdded then Exit; 

    case ssHelperState of 
    UpdatesAvailable: begin 
     Tip := 'Updates are Available. Click to see details.'; 
     InfoText := 'Updates are available to the programs installed on your Computer. Click to see details.'; 
     InfoTitle := 'Updates are Available'; 
    end; 
    UpdatesDownloading: begin 
     Tip := 'Downloading Updates. Click to see details.'; 
     InfoText := 'Updates are downloading in the background. Click to see details.'; 
     InfoTitle := 'Downloading Updates'; 
    end; 
    else 
    Tip := 'Software Updater is running'; 
    end; 

    IconData.uFlags := NIF_TIP or NIF_INFO; 
    StrPLCopy(IconData.szTip, Tip, Length(IconData.szTip)); 
    StrPLCopy(IconData.szInfo, InfoText, Length(IconData.szInfo)); 
    StrPLCopy(IconData.szInfoTitle, InfoTitle, Length(IconData.szInfoTitle)); 
    IconData.uTimeout := 2500; 
    IconData.dwInfoFlags := NIIF_INFO; 

    if not Shell_NotifyIcon(NIM_MODIFY, @IconData) then 
    ShowMessage('Unable to update System Tray Icon.') 
end; 

procedure MainForm.DeleteSysTrayIcon; 
begin 
    if IconAdded then 
    begin 
    IconAdded := False; 
    if not Shell_NotifyIcon(NIM_DELETE, @IconData) then 
     ShowMessage('Unable to delete System Tray Icon.'); 
    end; 
end; 

procedures MainForm.SetHelperState(NewState: eHelperState); 
begin 
    if ssHelperState <> NewState then 
    begin 
    ssHelperState := NewState; 
    DisplayBalloonTips; 
    end; 
end; 

procedure MainForm.SysTrayIconMessageHandler(var Message: TMessage); 
begin 
    if Message.Msg = TRAY_CALLBACK then 
    begin 
    case LOWORD(Message.LParam) of 
     WM_MOUSEMOVE: begin 
     //... 
     end; 

     WM_LBUTTONDBLCLK, 
     NIN_BALLOONUSERCLICK: begin 
     // display status window... 
     end; 

     WM_CONTEXTMENU, 
     NIN_KEYSELECT, 
     NIN_SELECT: begin 
     // display popup menu at coordinates specified by Msg.WParam... 
    end; 

     NIN_BALLOONSHOW:; 
     NIN_BALLOONHIDE:; 
     NIN_BALLOONTIMEOUT:; 
    end; 
    end 
    else if (Message.Msg = TaskbarCreatedMsg) and (TaskbarCreatedMsg <> 0) then 
    begin 
    IconAdded := False; 
    AddSysTrayIcon; 
    DisplayBalloonTips; 
    end 
    else begin 
    Message.Result := DefWindowProc(IconData.Wnd, Message.Msg, Message.WParam, Message.LParam); 
    end; 
end; 

... 

end. 
+0

を私が知っている 'NotifyIconData'の新しい構造体です。' szTip'や他のフィールドをクリアする方法を教えてください。私は今も自分のコードの他の部分をすべて追加しました。 – GTAVLover

+0

'DUMMYUNIONNAME'は非常に便利で、システムトレイのアイコンのバルーンの表示時間を決めることができるので追加しました: – GTAVLover

+0

' Shell_NotifyIcon() 'API全体を再宣言する必要はありませんバージョン管理機能を使用します。 'uVersion'フィールド(Delphi 2010で追加されました)が存在しない場合でも、Delphi 2009で使用することは可能です。私はこれを示すために私の答えを更新しました。 –

関連する問題