2010-10-16 44 views
5

Tôi có biểu mẫu chính (phụ huynh) MDI và biểu mẫu con MDI. Tôi tạo ra đứa trẻ trong thời gian chạy như thế này:"Không thể tạo biểu mẫu. Không có biểu mẫu MDI hiện đang hoạt động" lỗi

VAR 
    FrmDereplic: TFrmDereplic; 

procedure TMainFrm.Button2Click(Sender: TObject); 
begin 
FrmDereplic:= TFrmDereplic.Create(MainFrm); 
FrmDereplic.Show; 
end; 

bước để sao chép các lỗi:
tôi bắt đầu ứng dụng, tôi nhấn vào nút để tạo ra đứa trẻ, tôi nhấn nút 'x' trên chính (mẹ) để đóng ứng dụng và tôi nhận được lỗi "Không thể tạo biểu mẫu. Hiện không có biểu mẫu MDI nào đang hoạt động".

Dòng mà trên đó các lỗi xuất hiện ở dạng con:

procedure TFrmDereplic.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
Action:= caFree; 
end; 

procedure TFrmDereplic.FormDestroy(Sender: TObject); 
VAR MyIniFile: TCubicIniFile; 
begin 
MyIniFile:= TCubicIniFile.Create(AppINIFile); 
TRY 
    with MyIniFile DO 
    begin 
    if WindowState<> wsMaximized then 
    begin 
    // save form's screen pos 
    ... 
    end; 
    WriteInteger ('Dereplicator', 'fltExtensions', fltExtensions.ItemIndex); <----- HERE 
FINALLY 
    FreeAndNil(MyIniFile); 
END; 
end; 

tôi tiết kiệm rất nhiều tính hình thức (và đặc tính điều khiển khác) đến tập tin INI. Nhưng nó chỉ thất bại khi tôi cố gắng tiết kiệm fltExtensions.ItemIndex (là một TFilterComboBox). Nếu tôi bình luận rằng dòng nó hoạt động hoàn hảo.

Bất kỳ ý tưởng nào tại sao nó cố gắng tạo biểu mẫu khi tôi thực sự đóng ứng dụng ?????????

Trả lời

6

Tôi xem một số trang web và chỉ tìm thấy sự cố. Có vẻ như tốt hơn nếu Chủ sở hữu là Ứng dụng, không phải là biểu mẫu chính. Remy Lebeau gợi ý rằng vấn đề thực sự là trong OnDestroy của mẫu trẻ em. Không có xử lý hợp lệ cho cửa sổ chứa bộ lọc thì OnDestroy được gọi. Vì vậy, việc thay đổi thứ tự hủy diệt tạo cơ hội cho TFrmDereplic.OnDestroy thực thi đúng cách.

Vì vậy, đây là giải pháp:

SOLUTION (S)

FrmDereplic:= TFrmDereplic.Create(Application);

hoặc

Do not save form's properties in OnDestroy

thứ hai đòi hỏi vài dòng thêm mã như OnClose thậm chí là không phải lúc nào cũng được gọi. này được chiết xuất từ ​​Delphi TRỢ GIÚP:

Note: When the application shuts down, the main form receives an OnClose event, but any child forms do not receive the OnClose event.

Nếu bạn sử dụng Application.Terminate, sau đó onCloseQuery và onClose sẽ không được gọi. Tương tự cho Halt (nhưng ... đây là cách quá cực đoan, phải không?).

2

Nếu mã mà bạn cung cấp trong câu hỏi của bạn là một thực tế sau đó tôi đoán có sai số trong dòng này:

FrmDereplic:= TFrmDereplic.Create(TMainFrm); 

Tôi không bao giờ cố gắng này và tôi không chắc chắn nếu trình biên dịch thực sự mua nó (có thể 't kiểm tra nó ngay bây giờ), nhưng bạn đang cố gắng thiết lập một lớp làm chủ sở hữu của biểu mẫu con MDI. Thay vì đó, bạn nên làm một trong hai

FrmDereplic:= TFrmDereplic.Create(Application); 

hoặc

FrmDereplic:= TFrmDereplic.Create(self); 

Tùy chọn đầu tiên đặt ứng dụng là chủ sở hữu của form con MDI, trong khi cái thứ hai đặt ra thể hiện của hình thức chính MDI là chủ sở hữu .

Hy vọng điều đó sẽ hữu ích.:-)

+2

OP đến kết luận này ba giờ trước khi bạn đăng bài. –

+0

@Andreas - Tôi muốn đánh dấu bài đăng của mình là đã được giải quyết nhưng StackOverflow khiến tôi đợi 2 ngày. Dù sao, tốt đẹp của nó mà người khác xác nhận giải pháp của tôi. Nó có nghĩa là nó là tốt. – Ampere

+2

@ Vicens - Xin lỗi. Nó thực sự là MainForm thay vì TMainForm. Tôi đã nhập lỗi khi tôi nhập mã. Trong mã của tôi, biểu mẫu có một tên khác. Tôi đã đổi tên thành MainForm để làm cho mã dễ hiểu hơn (biểu mẫu chính = biểu mẫu gốc của biểu mẫu con). Xin lỗi lần nữa. Xin lưu ý rằng Self sẽ không hoạt động !! Nó thực sự tương đương với mã ban đầu (lỗi) của tôi. Tại sao? Bởi vì Self = MainForm. – Ampere

3

Lỗi xảy ra khi đọc thuộc tính fltExtensions.ItemIndex vì yêu cầu fltExtensions để có HWND, yêu cầu biểu mẫu TFrmDereplic cha mẹ để có HWND, yêu cầu MainForm của dự án phải có HWND. Nhưng ứng dụng đang ở trạng thái tắt máy, và MainForm không thể cấp phát HWND của nó nữa, vì vậy TFrmDereplic tăng một ngoại lệ khi nó không thể có được HWND cho chính nó.

Lưu dữ liệu INI của bạn trong sự kiện OnDestroy của biểu mẫu quá muộn. Bạn cần thay đổi sự kiện OnClose.

+0

Nhưng OnClosed bị bỏ qua trong một số trường hợp. Điều đó có nghĩa là dữ liệu sẽ không được lưu vào đĩa! Công việc triển khai hiện tại của tôi hoạt động. Cái này sai rồi hả? Tôi có thể sử dụng nó như nó được? Tôi đoán rằng việc sử dụng Ứng dụng làm chủ sở hữu của biểu mẫu đó sẽ thay đổi trình tự hủy. Điều này tạo cơ hội cho TFrmDereplic thực thi OnDestroy đúng cách. – Ampere

+1

OnClose được gọi khi đóng ứng dụng bằng hầu hết các phương tiện - nút X trên cửa sổ, TForm.Close(), Application.Terminate(), v.v. Nhưng có, có một số tình huống mà OnClose không phải lúc nào cũng được gọi, nhưng những điều kiện đó có thể được xử lý riêng. Bạn có thể cấu trúc lại mã tiết kiệm của mình thành hàm riêng của nó mà bạn có thể gọi từ nhiều nơi khi cần. Đối với lý do tại sao các mã chính nó là sai, tôi đã giải thích rằng - OnDestroy thường là quá muộn để truy cập vào các giá trị tài sản dựa trên HWND, như ItemIndex. Đặt Applicaton làm Chủ sở hữu chỉ đơn giản là cho phép con MDI bị phá hủy trước MainForm. –

+0

"Đối với lý do tại sao các mã chính nó là sai, tôi đã giải thích rằng" - Xin lỗi, tôi đã đề cập đến mã mới, nơi tôi đã cố định nó bằng cách thiết lập các ứng dụng (thay vì MainForm) là chủ sở hữu. Nếu nhiệm vụ này là hợp lệ, tôi muốn sử dụng nó thay vì từ bỏ OnClose. – Ampere

Các vấn đề liên quan