1. automatically restores the notification bar icon when shell explorer restarts
I believe many Windows users have encountered this situation:ProgramWhen an unexpected error occurs, the external shell program assumer.execollapsed and restarted (that is, the cmder.exe is closed and re-run). the taskbar also disappears and is re-generated, but the icons added by the application in the notification bar disappear. Although these programs are still running, however, you can no longer use the notification bar icon to interact with users. To avoid this situation, Windows provides a mechanism.
In a Windows operating system installed with Internet Explorer 4.0 or later, when the taskbar is set up, the shell will send a notification message to all top-level applications, the message is obtained by registering with the system with the string "taskbarcreated" as the parameter. After receiving the message in the application window, the notification bar icon should be added again.
The implementation process in Delphi is as follows:
1) define an integer variable msgtaskbarrestart to save the message rebuilt on the taskbar.
2 ). in the initialization part of the main program or in the oncreate event, register a message with the system with the "taskbarcreated" parameter (that is, to ask which message "taskbarcreated" is, because registration with the same parameters will get the same message, and "taskbarcreated" has been registered by the shell when Windows is started ).
Initialization
Msgtaskbarrestart: = registerwindowmessage ('taskbarcreated ');
3) Reload the message processing process in the main window, intercept the message in the taskbar, and re-Add the icon.
Procedure tmainform. wndproc (VAR message: tmessage );
Begin
......
If message. MSG = msgtaskbarrestart then
Begin
Trayicon. Active: = false; // Delete the notification bar icon
Trayicon. Active: = true; // Add a notification bar icon
End;
......
Inherited wndproc (Message );
End; // end of wndproc
2. encapsulation of the automatic recovery function
Since the shell only sends notifications to all top-layer applications, it makes it difficult to encapsulate the Automatic Recovery feature. Because the callback function of the notification bar icon can only receive limited messages, such as wm_xbuttondown and wm_xbuttonup, and cannot receive all window messages. This section describes how to enable the control to receive window messages and encapsulate the automatic recovery function.
The key to solving the problem is the setwindowlong function, which passes in the gwl_wndproc parameter to change the Window Process of a window. You only need to save the Window Process pointer of the application window when creating the control and point to a new window processing process in the control, in the control, you can respond to all window messages (including the re-created message in the taskbar). When the control is destroyed, the pointer of the saved original window process can be restored. ImplementationCodeSee the following (where "...... "To easily add or delete the notification bar icons and other functions and procedures ):
Teocsystray = Class (tcomponent)
Private
......
Factive: Boolean;
Fparentwindow: twincontrol; // parent window
Fnewwndproc: pointer; // process pointer of the new parent window
Fprevwndproc: pointer; // process pointer of the original parent window
Ftaskbarcreated: tpolicyevent; // Task Bar reconstruction event
......
Procedure setactive (value: Boolean); // you can specify whether the control works.
Procedure hookparentform; // process of replacing the window of the parent window
Procedure unhookparentform; // restore the Window Process of the parent window
Procedure hookwndproc (VAR amsg: tmessage); // new parent Window Process
Protected
Procedure dotaskbarcreated; dynamic; // triggers the task bar reconstruction event.
Public
Constructor create (aowner: tcomponent); override;
Destructor destroy; override;
Property active: Boolean read factive write setactive;
Property ontaskbarcreated: tpolicyevent read ftaskbarcreated
Write ftaskbarcreated;
Implementation
Type
Thack = Class (twincontrol); // used to access the default window processing process in the parent window protection domain
VaR
Msgtaskbarcreated: integer; // The message is recreated on the taskbar registered by the system.
Constructor teocw.ray. Create (aowner: tcomponent );
Begin
Inherited create (aowner );
......
Factive: = false;
Fnewwndproc: = makeobjectinstance (hookwndproc); // create a new window process pointer
Fprevwndproc: = nil;
If (aowner <> nil) and (aowner is tform) Then // obtain the parent window
Fparentwindow: = twincontrol (aowner)
Else
Fparentwindow: = application. mainform;
......
End; // end of contructor
Destructor teocw.ray. Destroy;
Begin
......
Fdestroying: = true;
Fparentwindow: = nil;
Freeobjectinstance (fnewwndproc );
Fnewwndproc: = nil;
......
Inherited destroy;
End; // end of destructor
Procedure teocsystray. setactive (value: Boolean );
Begin
If value <> factive then
Begin
Factive: = value;
If not (csdesigning in componentstate) Then // The control is not in the design status
Case value
True:
Begin
......
Hookparentform; // replaces the Window Process of the parent window
......
End;
False:
Begin
......
Unhookparentform; // restore the Window Process of the parent window
......
End;
End;
End;
End; // end of procedure setactive
Procedure teocsystray. hookparentform; // process of replacing the window of the parent window
VaR
P: pointer;
Begin
If assigned (fparentwindow) and
Not (csdesigning in fparentwindow. componentstate) or
(Csdestroying in fparentwindow. componentstate) or fdestroying) then
Begin
Fparentwindow. handleneeded;
P: = pointer (getwindowlong (fparentwindow. Handle, gwl_wndproc ));
If (P <> fnewwndproc) then
Begin
Fprevwndproc: = P;
Setwindowlong (fparentwindow. handle,
Gwl_wndproc, longint (fnewwndproc); // replaces the Window Process of the parent window
End;
End;
End; // end of procedure hookparentform
Procedure teocsystray. unhookparentform; // restore the window of the parent window
Begin
If assigned (fparentwindow) then
Begin
If assigned (fprevwndproc) and fparentwindow. handleallocated and
(Pointer (getwindowlong (fparentwindow. Handle, gwl_wndproc) = fnewwndproc) then
Setwindowlong (fparentwindow. handle,
Gwl_wndproc, longint (fprevwndproc); // restore the Window Process of the parent window
End;
Fprevwndproc: = nil;
End; // end of procedure unhookparentform
Procedure teocsystray. hookwndproc (VAR amsg: tmessage );
Begin
If assigned (fparentwindow) then
Begin
With amsg do
Begin
If MSG = msgtaskbarcreated then // receives the task bar reconstruction message
Dotaskbarcreated; // triggers the task bar reconstruction event.
If assigned (fprevwndproc) Then // call the Window Process of the original window
Result: = callwindowproc (fprevwndproc, fparentwindow. handle,
MSG, wparam, lparam)
Else
Result: = callwindowproc (Thack (fparentwindow). defwndproc,
Fparentwindow. Handle, MSG, wparam, lparam );
If MSG = wm_destroy then // The window is being destroyed.
Unhookparentform; // restore the Window Process of the parent window
End;
End;
End; // end of procedure hookwndproc
Procedure teocsystray. dotaskbarcreated;
Begin
...... // Add a new notification bar icon here
If assigned (ftaskbarcreated) then
Ftaskbarcreated (Self );
End; // end of procedure dotaskbarcreated
Initialization
// Register the message asking for Task Bar Reconstruction
Msgtaskbarcreated: = registerwindowmessage ('taskbarcreated ');
End.