2010-09-23 9 views
5

Tôi có các chức năng tôi muốn thực hiện sau khi ứng dụng của tôi đã hoàn thành việc khởi tạo và biểu mẫu chính đã được tạo. Tôi đã có mã (gọi nó là ProcedureX) trong các sự kiện OnShow hình thức, nhưng tôi đã chỉ nhận thấy rằng nó đang được gọi hai lần, bởi vì OnShow là bắn hai lần. Nó kích hoạt khi chương trình chính DPR gọi:Tôi nên đặt mã để thực hiện một lần sau khi ứng dụng Delphi của tôi đã hoàn thành việc khởi tạo?

Application.CreateForm(TMainForm, MainForm) ; 

như tôi mong đợi. Nhưng sau đó, khi tôi đọc nội dung từ tệp INI bao gồm các biểu mẫu trên màn hình, tôi có cuộc gọi:

MainForm.position := poScreenCenter ; 

Điều này sẽ xuất hiện sự kiện OnShow lần nữa.

Tôi có thể thực hiện cuộc gọi đến ProcedureX ở đâu, chỉ được gọi một lần và cần phải tạo biểu mẫu chính nào trước khi có thể thực thi?

Trả lời

3

Bạn có thể kiểm tra và đặt cờ khi bạn gọi thủ tục lần đầu tiên. Cũng giống như vậy:

type 
    TForm1 = class(TForm) 
    procedure FormShow(Sender: TObject); 
    private 
    FRunOnce: Boolean; 
    public 
    [...] 

[...] 

procedure TForm1.FormShow(Sender: TObject); 
begin 
    if not FRunOnce then begin 
    FRunOnce := True; 
    ProcedureX; 
    end; 
end; 
+0

tôi làm theo quy ước "lĩnh vực tiền tố với một F", do đó FRunOnce âm thanh chuẩn hơn đối với tôi. Không phải là một quy tắc, chỉ là một quy ước, như tên lớp tiền tố với T. Chỉ cần làm cho mã của người khác dễ đọc hơn. – jachguate

+0

@jachguate - Khi có chữ 'F', tôi cảm thấy như nó cần phải có bộ thu thập thông tin. Nhưng đó là vấn đề của tôi, tôi đoán ... Đã chỉnh sửa câu trả lời, cảm ơn vì đã chỉ ra. –

+0

OK, tôi đã nghĩ đến việc đó, nhưng nó có vẻ như điều trị triệu chứng, chứ không phải nguyên nhân. Tôi đoán tôi đang tìm kiếm một số sự kiện khác (như "OnEverythingFinished") mà chỉ bị sa thải một lần. Những gì tôi nghe là không có gì! Cảm ơn bạn đã giúp đỡ. FRunOnce nó được. – rossmcm

4

Trình tự bình thường thực hiện cho một Form là:

  • AfterConstruction: khi biểu mẫu và nó thành phần được tạo ra hoàn toàn với tất cả các tài sản của họ.
  • OnShow: bất cứ khi nào mẫu đã sẵn sàng để hiển thị (và, vâng, bất kỳ sự thay đổi gây ra một CM_SHOWINGCHANGED có thể kích hoạt một OnShow)
  • Activate: bất cứ khi nào Form mất Focus

Vì vậy, tùy thuộc vào những gì bạn cần trong ProcedureX, AfterConstruction có thể là đủ và chỉ được thực hiện một lần; chỉ cần ghi đè lên nó và thêm ProcedureX sau inherited. Nó sẽ sau OnCreate.

Nếu không, bạn có thể đăng thông báo tùy chỉnh lên Biểu mẫu từ AfterConstruction, nó sẽ được xếp hàng đợi và sẽ xử lý tùy chỉnh của bạn sau khi các thư khác đã được xử lý.

Trong cả hai trường hợp, bạn sẽ không cần thêm Trường boolean.

+0

Còn về việc sử dụng OnCreate thì sao? – rossmcm

+0

Nó có thể là OK. Nhưng AfterConstruction cho phép luôn luôn thực hiện ProcedureX sau bất cứ điều gì có thể trong OnCreate ... –

8

Nếu mã của bạn chỉ cần chạy một lần cho mỗi lần tạo biểu mẫu (hoặc mỗi ứng dụng và biểu mẫu chỉ được tạo một lần cho mỗi lần chạy ứng dụng), hãy đặt mã trong trình xử lý OnCreate của biểu mẫu. Đó là nơi tự nhiên để nó đi.

Ngày nay (kể từ khi D3 tôi nghĩ) OnCreate kích hoạt vào cuối quá trình xây dựng trong phương pháp AfterConstruction. Chỉ khi bạn đã đặt OldCreateOrder thành True (và nó là False theo mặc định), bạn có thể gặp rắc rối vì điều đó làm cho OnCreate cháy ở cuối constructor Create.

5

@Sertac,

Thực sự không cần đến trường FRUNOnce; chỉ cần thực hiện OnShow = NIL làm dòng đầu tiên trong phương thức FormShow của bạn.

FYI, Thành ngữ "chạy một lần" - thiết lập trường xử lý sự kiện thành NIL trong dòng đầu tiên của trình xử lý sự kiện - cũng hữu ích cho việc tạo mã và chạy một khi biểu mẫu đã hoàn toàn được khởi tạo.Đặt mã của bạn theo phương thức FormActivate và, như dòng đầu tiên của phương thức, đặt OnActivate = NIL.

+4

mà sẽ chỉ có thể nếu bạn không có gì khác để làm trong xử lý sự kiện. Tuy nhiên, nếu bạn đã có mã trong trình xử lý mà bạn muốn nó chạy bất cứ khi nào bạn f.i. bỏ ẩn form của bạn, bạn không thể nil handler. –

0

@Sertec,

Mã của bạn sẽ không làm việc, hoặc nếu bạn muốn nó chạy cho mỗi sự kiện Bỏ ẩn (bạn đã không đưa vào bất kỳ mã để thiết lập lại các lĩnh vực frunonce).

Vì vậy, phương pháp của bạn sẽ cần phải đặt lại trường đơn sắc và tôi sẽ cần đặt OnShow = FormShow. Cùng một sự khác biệt, ngoại trừ việc bạn cần một trường bổ sung.

+0

Nếu tôi muốn đặt lại cờ, tại sao tôi lại có nó? Ví dụ: Tôi phải chạy thủ tục 'ShowJustOnce' sau khi biểu mẫu hiển thị lần đầu tiên, trên' OnShow'. Và tôi đã chạy 'UpdateInfo' mỗi lần người dùng gây ra để hiển thị lại biểu mẫu, trên' OnShow'. Tôi không thể nil xử lý vì 'UpdateInfo' sẽ không chạy. Tôi phải sử dụng cờ vì nếu không 'ShowJustOnce' sẽ chạy mỗi khi biểu mẫu được hiển thị lại. –

+0

Nếu bạn cần một số mã trong FormSHow chạy một lần và một số chạy nhiều lần, thì có, bạn cần một lá cờ. Điều đó không thực sự liên quan đến câu hỏi mà cả hai chúng tôi đều trả lời, đó chỉ là "làm sao tôi có thứ gì đó chỉ thực hiện một lần khi biểu mẫu của tôi ban đầu được hiển thị". Vì vậy, một lần nữa ... đặt nó trong phương thức FormActivate, và, như là dòng đầu tiên của phương pháp, đặt "OnActivate: = NIL;". Nếu bạn muốn nội dung chạy mỗi lần biểu mẫu được hiển thị và chỉ một lần cho mỗi thay đổi hiển thị thực tế, đó là một câu hỏi khác. –

+1

Nó có liên quan và nó không phải là một câu hỏi khác. Tôi sẽ không đề nghị bất cứ ai để nil xử lý sự kiện của mình vì tôi sẽ không biết nếu có mã đã có hay không, và sẽ không được trong tương lai quá ...Giống như trong 'OnShow', người ta cũng có thể viết mã 'OnActivate'. Ví dụ: ** có ** mã hiển thị lại các biểu mẫu đã bị ẩn trước đó trên 'OnDeactivate'. Nếu tôi không được 'OnActivate', bạn sẽ đề nghị tôi cho họ xem lại ở đâu? –

4

Bạn có thể thêm thủ tục vào tệp DPR của mình, sau tệp Application.CreateForm. Đặt tất cả mã bạn cần để khởi tạo trong quy trình đó. Hoạt động tốt nhất khi bạn có nhiều biểu mẫu trong ứng dụng của mình.

Ngoài ra nếu khởi tạo mất rất nhiều, chương trình sẽ hiển thị các biểu mẫu trên màn hình để người dùng biết rằng ứng dụng đang tải.

Ví dụ:

PROGRAM MyProgram; 
begin 
    Application.Initialize; 
    Application.CreateForm(TMyForm, MyForm); 
    MyForm.Show; 

    LateInitialize;  <----------- here 

    Application.Run; 
end.