2013-07-06 37 views
5

Trong ứng dụng của tôi, tôi có một biểu mẫu chính, với khả năng tải một số hình ảnh trong cơ sở dữ liệu. Trong khi hình ảnh đang tải, tôi muốn hiển thị biểu mẫu, với chỉ báo tiến trình (với kiểu đường viền bsNone).Hình thức vô hiệu hóa Delphi khi đang tải

Nhưng, nếu tôi hiển thị bằng biểu mẫu với ShowModal, việc thực hiện biểu mẫu chính bị dừng lại, vì vậy tôi không thể làm điều đó.

Nếu tôi gọi Hiển thị, người dùng có quyền truy cập vào tất cả các thành phần biểu mẫu khác và có thể nguy hiểm, trong khi ảnh không được tải hoàn toàn.

Tôi cần có cách để tắt tất cả mọi thứ trên biểu mẫu chính trong khi quá trình tải chưa hoàn tất.

Xin vui lòng, tư vấn cho tôi, làm thế nào nó có thể.

+1

Nếu bạn' muốn giữ một hình thức phương thức, bạn có thể gọi thói quen từ phương thức bạn được hiển thị hình thức. ví dụ. bằng cách bàn giao phương thức để gọi bên trong construcror của biểu mẫu được hiển thị phương thức. – bummi

+0

Ngoài việc vô hiệu hóa biểu mẫu, bạn cũng có thể ẩn biểu mẫu chính. Các khả năng khác bao gồm gọi thủ tục tải từ hộp thoại tiến trình phương thức. – GolezTrol

Trả lời

12

Đặt MainForm làm biểu mẫu tiến trình sao cho MainForm không bao giờ xuất hiện ở đầu biểu mẫu tiến trình. Sau đó, chỉ cần đặt MainForm.Enabled := False trong khi biểu mẫu tiến trình đang mở và đặt MainForm.Enabled := True khi biểu mẫu tiến trình bị đóng.

procedure TMainForm.ShowProgressForm; 
begin 
    with TProgressForm.Create(nil) do 
    begin 
    PopupParent := Self; 
    OnClose := ProgressFormClose; 
    Show; 
    end; 
    Enabled := False; 
end; 

procedure TMainForm.ProgressFormClose(Sender: TObject; var Action: TCloseAction); 
begin 
    Action := caFree; 
    Enabled := True; 
end; 

này mô phỏng như thế nào ShowModal() cư xử cho người sử dụng (các MainForm không phải là người sử dụng tương tác trong khi hình thức tiến bộ được mở), nhưng không ngăn chặn các mã.

3

Trước hết, câu trả lời trực tiếp cho câu hỏi của bạn.

Tôi cần tìm cách để tắt mọi thứ trên biểu mẫu chính.

Đặt MainForm.Enabled thành False để tắt cửa sổ được liên kết với biểu mẫu chính. Và để bật lại, hãy đặt nó thành True.


Tuy nhiên, vấn đề cơ bản của bạn là bạn đang thực hiện các tác vụ chạy dài trong luồng GUI. Đó luôn luôn là một ý tưởng tồi và cách ra là để thực hiện những nhiệm vụ chạy dài trong một chủ đề riêng biệt.

Khi bạn di chuyển các tác vụ đang chạy dài sang một chuỗi riêng biệt thì bạn sẽ thấy rằng ShowModal chính xác là những gì bạn cần để hiển thị biểu mẫu tiến trình của mình.

1

Như tôi đã giải thích trong câu trả lời khác của tôi, việc đặt nhiệm vụ chạy dài vào một chủ đề khác ngoài luồng GUI là giải pháp lý tưởng. Chủ đề GUI sẽ xử lý các tác vụ chạy ngắn để luôn có thể phục vụ hàng đợi tin nhắn một cách kịp thời.

Tuy nhiên, nếu bạn đã có mã giả định rằng tác vụ chạy dài chạy trên luồng GUI, bạn có thể thích thực hiện một cách tiếp cận phù hợp hơn và trì hoãn việc tính lại mã luồng. Trong trường hợp đó, theo quan điểm của tôi, vẫn tốt hơn khi sử dụng ShowModal để hiển thị biểu mẫu tiến trình của bạn.

Nhưng để thực hiện công việc đó, bạn cần tìm cho phép tác vụ chạy dài chạy trong cuộc gọi ShowModal. Bạn có thể làm điều đó như sau:

  1. Trước khi bạn gọi ShowModal, hãy chuyển công việc vào biểu mẫu. Ví dụ: chuyển một số TProc tới hàm tạo của biểu mẫu tiến trình.
  2. Ghi đè phương thức Activate của biểu mẫu tiến trình. Điều này sẽ được thực thi ngay trước khi hàm ShowModal bắt đầu vòng lặp thông điệp phương thức của nó. Khi triển khai Activate, hãy đăng thông báo lên biểu mẫu.
  3. Khi biểu mẫu xử lý thông báo đó, hãy gọi tác vụ đã được truyền cho hàm tạo.

Rõ ràng bạn sẽ cần gọi ProcessMessages trong tác vụ chạy dài của mình, để giữ cho hàng đợi thông điệp chuỗi chủ đề chính được phục vụ. Rõ ràng bạn đã phải làm điều đó.

1

Bạn có thể muốn sử dụng các chức năng DisableTaskWindowsEnableTaskWindows.

Nếu bạn sử dụng đơn giản ParentForm.Enabled := False cho biểu mẫu gốc, bạn vẫn có thể truy cập tất cả các biểu mẫu khác, như biểu mẫu chính nếu nó khác với ParentForm. Nó rõ ràng vẫn còn nguy hiểm.

Đây là mẫu ngắn:

interface 

uses 
    Vcl.Forms, Winapi.Windows, ...; 

type 
    TPleaseWait = class(TObject) 
    private 
    fWindowList: TTaskWindowList; 
    fActiveWindow: HWND; 
    fDialog: TPleaseWaitForm; 
    public 
    constructor Create; 
    destructor Destroy; override; 
    end; 

implementation 

constructor TPleaseWait.Create; 
begin 
    // Disable all displayed windows 
    fWindowList := DisableTaskWindows(0); 

    // Save the last active window 
    fActiveWindow := GetActiveWindow; 

    fDialog := TPleaseWaitForm.Create(nil); 
    fDialog.Show; 
end; 

destructor TPleaseWait.Destroy; 
const 
    INVALID_HANDLE = 0; 
begin 
    fDialog.Close; 
    fDialog.Free; 

    // All windows are enabled now 
    EnableTaskWindows(fWindowList); 

    // That helps by enabling the last one form 
    if (fActiveWindow <> INVALID_HANDLE) and IsWindow(fActiveWindow) then 
    SetActiveWindow(fActiveWindow); 
    inherited; 
end; 

end. 
1

Đặt PopupParent hình thức con = ParentForm

procedure TParentForm.Button1Click(Sender: TObject); 
begin 
ParentForm.Enabled:=False; 
with Tform1.create(nil) do show; 
end; 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
ParentForm.Enabled := true; 
form1.free; 
end; 
Các vấn đề liên quan