2013-02-21 21 views
7

使用Delphi XE2,Win64。從模態窗口打開的Helpfile無響應

所以我有很多形式的大型應用程序,如果我打開從主窗體中的幫助文件,打開一個模式窗口,然後點擊F1到斷火模態窗口的幫助文件窗口顯示上下文敏感的幫助正確的信息,但幫助文件無法關閉,直到我關閉模態窗口。如果我回到應用程序,直到模式窗口關閉,我甚至無法再次獲得幫助文件的焦點。

調用此確切相同的幫助從舊版本我們的應用程序(用Delphi 6個內置)的文件坐在同一個文件夾中的新版本(與德爾福XE2建)的幫助文件時會顯示F1鍵擊從模式窗口,並作出響應,可以像我期望的那樣關閉。

幫助文件是.chm類型文件。

總結。

啓動應用程序 打開幫助文件由F1 跳轉到應用程序並打開模式窗口從模態窗口申請 啓動幫助擊中F1 幫助文件窗口無法關閉,直到我跳回到我的應用程序,並關閉模態窗口。

有沒有人有任何想法,爲什麼會這樣?

我已經搜索了互聯網,並沒有發現任何類似的問題。

我們很難過。

乾杯 TJ

---- ---- EDIT

這裏爲樣品2形式的應用程序,也表現出這種行爲的一些代碼。

program Project1; 

uses 
    Vcl.Forms, 
    HTMLHelpViewer, 
    Unit1 in 'Unit1.pas' {Form1}, 
    Unit2 in 'Unit2.pas' {Form2}; 

{$R *.res} 

begin 
    Application.Initialize; 
    Application.HelpFile := 'C:\helpfile.chm'; 
    Application.MainFormOnTaskbar := True; 
    Application.CreateForm(TForm1, Form1); 
    Application.Run; 
end. 

這裏是Form 1代碼:

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

uses Unit2; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Form2 := TForm2.Create(Application); 
    try 
    Form2.ShowModal; 
    finally 
    Form2.Free; 
    end; 
end; 

end. 

我設置HelpContext屬性的兩種形式,以我的幫助文件中的兩個有效的上下文。

運行的應用程序 - F1打開幫助文件 命中按鈕,這樣窗體2創建和顯示 F1調用幫助文件 不能關閉幫助文件,直到我關閉窗體2。

希望這會有所幫助。 - TJ

+0

它啓動了winhlp64還是32位版本? – 2013-02-21 21:38:06

+0

@Tony也沒有。這是一個.chm。它將與chm ocx組件進行中。 – 2013-02-21 21:39:10

+0

@DavidHeffernan - 明確設置popupparent沒有明顯的效果。你需要什麼幫助?這甚至發生在一個簡單的兩種形式的測試應用程序。 – 2013-02-21 21:51:32

回答

9

這是一個嚴重的設計缺陷HtmlHelpViewer。而且很容易重現你描述的行爲。做得很好,可以清楚地說明問題。這個問題同樣影響32位和64位程序。

我個人並不使用HtmlHelpViewer,因爲它不起作用。我實現了一個TApplication.OnHelp的處理程序。它看起來像這樣:

class function THelpWindowManager.ApplicationHelp(Command: Word; 
    Data: THelpEventData; var CallHelp: Boolean): Boolean; 
begin 
    CallHelp := False; 
    Result := True; 
    //argh, WinHelp commands 
    case Command of 
    HELP_CONTEXT,HELP_CONTEXTPOPUP: 
    HtmlHelp(GetDesktopWindow, Application.HelpFile, HH_HELP_CONTEXT, Data); 
    end; 
end; 

提出,在一類,並將其分配給Application.OnHelp在啓動時:

Application.OnHelp := THelpWindowManager.ApplicationHelp; 

我剛剛測試了這一點上做文章兩個表單應用程序,它運行良好。在真實的代碼中,您可能希望對此進行修飾。例如,我的實際代碼更復雜。它在用戶設置中存儲幫助窗口關閉時的位置和窗口狀態。然後再次顯示時,該位置和窗口狀態被恢復。因此,幫助窗口似乎記住了上次在屏幕上的位置。


感謝@Sertac在下面的評論中挖掘出細節。總之這裏的地方HtmlHelpViewer代碼出錯:

  1. 這使得在幫助系統啓動時發送的HH_INITIALIZE命令。
  2. documentation中所述,此將HTML幫助配置爲與調用應用程序相同的線程運行,而不是輔助線程
  3. 當您致電ShowModal調用DisableTaskWindows時,會在調用線程中禁用窗口。
  4. 因爲幫助查看器窗口是由應用程序的主線程創建的(因爲HH_INITIALIZE命令),所以它被禁用。

這就是爲什麼當Delphi模式表單處於活動狀態時,您無法與預先存在的幫助窗口進行交互。

+0

如果您通過主窗體的句柄而不是桌面窗口,它的行爲如何? – 2013-02-21 22:05:59

+1

@塞爾特克嗯,我期望當窗口模式窗口禁用它的所有者時會產生窗口所有權問題。但是不,這也沒關係。 'HtmlHelpViewer'吹大塊。 – 2013-02-21 22:07:03

+0

那就是+1,因爲如果你需要傳遞一個表單的句柄,它不會妨礙你。順便說一句,我認爲這是ShowModal通過DisableTaskWindows禁用線程窗口。 – 2013-02-21 22:20:54