国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

具有自動恢復(fù)功能的通知欄圖標(biāo)控件

2019-11-18 18:40:08
字體:
供稿:網(wǎng)友
 

任務(wù)欄(Taskbar)是微軟公司在Windows 95中引入的一種特殊的桌面工具條,它為用戶快速訪問計算機資源提供了極大的方便,而狀態(tài)欄(以下稱通知欄)無疑是任務(wù)欄上較為特殊的一個窗口。編程人員可以調(diào)用API函數(shù)Shell_NotifyIcon向通知欄發(fā)送消息來添加、刪除或修改圖標(biāo),當(dāng)在圖標(biāo)上發(fā)生鼠標(biāo)或鍵盤事件時,系統(tǒng)會向應(yīng)用程序發(fā)送編程時預(yù)先定義的消息,通知欄處理回調(diào)函數(shù)就會被自動調(diào)用以做出相應(yīng)的處理。實現(xiàn)上述功能的相關(guān)文章俯仰即拾,此處不再贅述。本文將討論兩個較為深入的問題及其在Delphi中的實現(xiàn)方法。
  1、Windows發(fā)生錯誤導(dǎo)致外殼Explorer.exe重啟時通知欄圖標(biāo)的自動恢復(fù)
  2、將自動恢復(fù)功能封裝在控件中以便其它程序中調(diào)用。

關(guān)鍵詞:通知欄、窗口過程


1 外殼Explorer重啟時通知欄圖標(biāo)的自動恢復(fù)
相信很多Windows用戶都碰到過這種情況:運行某個程序時出現(xiàn)意外錯誤,導(dǎo)致外殼程序Explorer.exe崩潰而發(fā)生重啟(即Explorer.exe被關(guān)閉后重新運行),任務(wù)欄也在消失后重新生成,但應(yīng)用程序在通知欄添加的圖標(biāo)消失了,雖然這些程序仍在運行,但再也無法通過通知欄圖標(biāo)與用戶交互。為避免這種情況出現(xiàn),Windows提供了相應(yīng)的機制。
在安裝了Internet Explorer 4.0及以上版本的Windows操作系統(tǒng)中,當(dāng)任務(wù)欄建立后,外殼會向所有頂層的應(yīng)用程序發(fā)出通知消息,該消息是外殼以字符串"TaskbarCreated"為參數(shù)向系統(tǒng)注冊獲得的,應(yīng)用程序窗口接收到該消息后就應(yīng)該重新添加的通知欄圖標(biāo)。
在Delphi中實現(xiàn)過程如下:
1). 定義一個整型變量MsgTaskbarRestart,用以保存任務(wù)欄重建的消息。
2). 在主程序的initialization部分或者是在OnCreate事件中以"TaskbarCreated"為參數(shù)向系統(tǒng)注冊消息(也即是詢問"TaskbarCreated"是哪條消息,因為以相同的參數(shù)注冊會得到相同的消息,而"TaskbarCreated"在Windows啟動的時候就已經(jīng)被外殼注冊)。

initialization
  MsgTaskbarRestart := RegisterWindowMessage('TaskbarCreated');

3). 重載主窗口的消息處理過程,攔截任務(wù)欄重建消息,進(jìn)行重新添加圖標(biāo)的操作。

PRocedure TMainForm.WndProc(var Message: TMessage);
begin
  ……
  if Message.Msg = MsgTaskbarRestart then
  begin
    TrayIcon.Active := False;      //刪除通知欄圖標(biāo)
    TrayIcon.Active := True;       //添加通知欄圖標(biāo)
  end;
  ……
  inherited WndProc(Message);
end; //end of WndProc

2 自動恢復(fù)功能的封裝
由于外殼只向所有頂層的應(yīng)用程序發(fā)送通知,這為封裝自動恢復(fù)功能帶來了一定的困難。因為通知欄圖標(biāo)的回調(diào)函數(shù)只能接收WM_XBUTTONDOWN、WM_XBUTTONUP等有限的幾個消息,并不能接收所有的窗口消息。本節(jié)介紹的方法將使得在控件中能夠接收窗口消息,從而實現(xiàn)自動恢復(fù)功能的封裝。
解決問題的關(guān)鍵是SetWindowLong函數(shù),向它傳入GWL_WNDPROC參數(shù),可以改變一個窗口的窗口過程。只需在創(chuàng)建控件時將應(yīng)用程序窗口的窗口過程指針保存起來,并指向為控件中的某個新的窗口處理過程,在控件中就能夠響應(yīng)所有的窗口消息了(包括任務(wù)欄重建的消息);當(dāng)控件銷毀的時候再將保存的原始窗口過程指針恢復(fù)即可。實現(xiàn)代碼如下(其中"……"的地方略去容易實現(xiàn)的添加、刪除通知欄圖標(biāo)等函數(shù)及過程):

  TEoCSysTray = class(TComponent)
  Private
    ……
    FActive: boolean;
    FParentWindow: TWinControl;     //父窗口
    FNewWndProc: Pointer;     //新的父窗口過程指針
    FPrevWndProc: Pointer;     //原先的父窗口過程指針
    FTaskBarCreated: TNotifyEvent;     //任務(wù)欄重建事件
    ……
    procedure SetActive(Value: boolean);   //設(shè)置控件是否起作用
    procedure HookParentForm;     //替換父窗口的窗口過程
    procedure UnHookParentForm;     //還原父窗口的窗口過程
    procedure HookWndProc(var AMsg: TMessage);  //新的父窗口過程
  protected
    procedure DoTaskBarCreated; dynamic;   //觸發(fā)任務(wù)欄重建事件
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Active: boolean read FActive write SetActive;
    property OnTaskBarCreated: TNotifyEvent read FTaskBarCreated
      write FTaskBarCreated;

implementation

type
  THack = class(TWinControl);   //用以訪問位于父窗口保護域的默認(rèn)窗口處理過程

var
  MsgTaskbarCreated  : Integer;   //由系統(tǒng)注冊的任務(wù)欄重建消息

constructor TEoCSysTray.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ……
  FActive := false;
  FNewWndProc := MakeObjectInstance(HookWndProc);//建立新的窗口過程指針
  FPrevWndProc := nil;
  if (AOwner <> nil) and (AOwner is TForm) then  //獲得父窗口
    FParentWindow := TWinControl(AOwner)
  else
    FParentWindow := application.MainForm;
  ……
end;//end of Contructor

destructor TEoCSysTray.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 //控件未處于設(shè)計狀態(tài)
      case Value of
        True:
          begin
            ……
            HookParentForm;     //替換父窗口的窗口過程
            ……
          end;
        False:
          begin
            ……
            UnHookParentForm;     //還原父窗口的窗口過程
            ……
          end;
      end;
  end;
end; //end of procedure SetActive

procedure TEoCSysTray.HookParentForm;    //替換父窗口的窗口過程
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));  //替換父窗口的窗口過程
    end;
  end;
end; //end of procedure HookParentForm

procedure TEoCSysTray.UnHookParentForm;   //還原父窗口的窗口過程
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));  //還原父窗口的窗口過程
  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    //接收到任務(wù)欄重建消息
        DoTaskBarCreated;     //觸發(fā)任務(wù)欄重建事件
      if Assigned(FPrevWndProc) then     //調(diào)用原窗口的窗口過程
        Result := CallWindowProc(FPrevWndProc, FParentWindow.Handle,
          Msg, WParam, LParam)
      else
        Result := CallWindowProc(THack(FParentWindow).DefWndProc,
          FParentWindow.Handle, Msg, WParam, LParam);
      if Msg = WM_DESTROY then     //窗口正被銷毀
        UnHookParentForm;     //還原父窗口的窗口過程
    end;
  end;
end; //end of procedure HookWndProc

procedure TEoCSysTray.DoTaskBarCreated;
begin
  ……    //在這里重新添加通知欄圖標(biāo)
  if Assigned(FTaskBarCreated) then
    FTaskBarCreated(Self);
end; //end of procedure DoTaskBarCreated

initialization
  //注冊詢問任務(wù)欄重建的消息
  MsgTaskbarCreated := RegisterWindowMessage('TaskbarCreated');

end.



上一篇:動態(tài)隱藏/顯示窗口的標(biāo)題欄(同時保持窗口的Sizeable性能)

下一篇:Windows通知欄圖標(biāo)高級編程概述

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 大新县| 胶南市| 扶风县| 斗六市| 泸西县| 托克逊县| 喀喇沁旗| 杭锦后旗| 芦山县| 平定县| 丹江口市| 白山市| 塔城市| 菏泽市| 胶南市| 彰化县| 略阳县| 巴塘县| 赤壁市| 呼伦贝尔市| 江油市| 吉安市| 和政县| 安龙县| 松江区| 廉江市| 伊吾县| 临汾市| 周宁县| 鹤山市| 海盐县| 略阳县| 云梦县| 海安县| 龙川县| 亳州市| 五指山市| 沁水县| 建湖县| 安达市| 洛宁县|