2017-05-08 44 views
0

摘要: 一種形式(貸款申請表,)(當用戶點擊一個特定的按鈕)動態地創建一個名爲DatePickerForm模式窗體。 在DatePickerForm選擇日期後,用戶點擊該窗體的「關閉」按鈕:(一BitBtn) - 這是什麼原因造成的訪問衝突錯誤。德爾福(西雅圖) - 關閉動態創建的模式窗體會導致訪問衝突

詳情:

可重複使用的模式DatePickerForm的目的是爲用戶提供在特殊情況下輸入日期的一致方法。它將用於其他多種情況 - 也就是說,如果我按計劃實現它的工作。

確切錯誤文字是:「項目ABCD.exe引發的異常類$ 0000005與消息‘訪問衝突在0x0060d0b1:讀取0x00000000地址的’。」

代碼編譯,程序正常工作,直到下面的步驟4:

運行時過程:

  1. 上的按鈕的用戶點擊貸款形式(工作
  2. DatePickerForm模式將被創建(owner:Application),然後顯示。 (作品
  3. 用戶選擇從DatePicker控件的日期。 (工作
  4. 上的OK按鈕,用戶點擊(失敗
  5. 的DatePickerForm應該關閉,我們應該回到貸款形式 - 而是發生錯誤。
  6. 下一步將依然對的DatePicker的形式DatePicker控件來讀取日期(形式仍然存在,它只是看不見的在這一點上)

我的問題

A)如果這項工作或我使用動態表單創建不正確?

B)是否有更好的方式來實現這一目標?

任何幫助將不勝感激。

約翰

DatePickerForm代碼(完整):

unit DatePicker_PopupForm; 

interface 

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

type 
    TfmDatePicker_Popup = class(TForm) 
     DTDatePicker: TDateTimePicker; 
     lblDatePrompt: TLabel; 
     btnOK: TBitBtn; 
     procedure btnOKClick(Sender: TObject); 
    private 
     { Private declarations } 
    public 
     { Public declarations } 
    end; 

var 
    fmDatePicker_Popup: TfmDatePicker_Popup; 

implementation 

{$R *.dfm} 

procedure TfmDatePicker_Popup.btnOKClick(Sender: TObject); 
begin 
    fmDatePicker_Popup.CloseModal; 
end; 
end. 

貸款形式 - 部分代碼(完整的代碼大約是9700線長)

unit LoanForm; 

    interface 

    uses 
     Winapi.Windows, ......, DatePicker_PopupForm; 

    ... 

    implementation 

    ... 

    procedure TfmLoan.btnSetDefaultClick(Sender: TObject); 
    begin 
     DatePickerForm := TfmDatePicker_Popup.Create(Application); 
     DatePickerForm.DTDatePicker.Date := GD_ProcessDate; 
     DatePickerForm.ShowModal;   
     dDefaultDate := DatePickerForm.DTDatePicker.Date; 
    end; 
     ... 

    end. 

回答

2

documentation說:

不要在您的應用程序調用CloseModal。當需要關閉模式表單時,VCL使用CloseModal。 CloseModal不會自行關閉表單;它只是調用已註冊的關閉事件並更新ModalResult屬性。

所以,不要因爲它說。通過設置窗體的ModalResult屬性來關閉模式窗體。

做到這一點的最簡單的方法是刪除按鈕OnClick事件處理程序。而是在設計器中設置按鈕的ModalResult屬性。

+0

感謝大衛 - 即做到了!!!!我一定要進一步研究這個(我討厭不理解事情是如何工作的)。謝謝 - 約翰 –

0

這是從您正在訪問nil指針錯誤信息清晰。而其中的原因是因爲你調用CloseModal()上實際上沒有指向一個有效的窗體對象的全局fmDatePicker_Popup對象指針(你不應該直接在第一時間呼叫)開始與:

procedure TfmDatePicker_Popup.btnOKClick(Sender: TObject); 
begin 
    fmDatePicker_Popup.CloseModal; // <-- fmDatePicker_Popup is not assigned! 
end; 

原因fmDatePicker_Popupnil是因爲在btnSetDefaultClick(),當你創建TfmDatePicker_Popup對象,你是它的fmDatePicker_Popup變量分配到不同的DatePickerForm變量,而不是:

procedure TfmLoan.btnSetDefaultClick(Sender: TObject); 
begin 
    DatePickerForm := TfmDatePicker_Popup.Create(Application); // <-- 
    ... 
end; 

TfmDatePicker_Popup根本不應依賴任何外部指針。由於btnOKClick()TfmDatePicker_Popup類的成員,它應該是使用隱含Self指針來代替:

procedure TfmDatePicker_Popup.btnOKClick(Sender: TObject); 
begin 
    Self.CloseModal; 
end; 

或者乾脆:

procedure TfmDatePicker_Popup.btnOKClick(Sender: TObject); 
begin 
    CloseModal; 
end; 

話雖這麼說,CloseModal()是錯誤的事情反正打電話。它實際上並沒有關閉窗體,它只是觸發窗體的OnClose事件。每ShowModal()文檔:

要關閉模式窗體,設置其屬性ModalResult爲非零值

ShowModal()內部調用CloseModal()當它檢測到ModalResult已成爲非零。如果OnClose事件處理程序將其參數Action設置爲caNone,則ModalResult將重置爲0,並且表格未關閉。

所以使用窗體的ModalResult屬性,而不是像文件說要:

procedure TfmDatePicker_Popup.btnOKClick(Sender: TObject); 
begin 
    Self.ModalResult := mrOk; 
end; 

然後可以通過完全移除OnClick處理器,取而代之的是按鈕的ModalResult屬性設置爲非零值(自動化或者在TBitBtn的情況下,設置其Kind財產,其也設置其ModalResult)。點擊模式窗體上的按鈕後,它會在觸發其OnClick事件之前將其自己的ModalResult分配給其父窗體的ModalResult

然後,你也應該改變btnSetDefaultClick()看起來更像這個:

procedure TfmLoan.btnSetDefaultClick(Sender: TObject); 
var 
    DatePickerForm: TfmDatePicker_Popup; 
begin 
    DatePickerForm := TfmDatePicker_Popup.Create(nil); 
    try 
    DatePickerForm.DTDatePicker.Date := GD_ProcessDate; 
    if DatePickerForm.ShowModal = mrOk then 
     dDefaultDate := DatePickerForm.DTDatePicker.Date; 
    finally 
    DatePickerForm.Free; 
    end; 
end; 
+0

雷米 - 感謝您的解釋。這正是我需要理解的(我將不得不花費一些時間考慮它並嘗試在我完全確定使用它之前進行試驗,以便我正確地做到這一點) –