2013-07-06 1 views
5

В моем приложении у меня есть основная форма, с возможностью загрузки некоторых изображений в базу данных. Пока изображения загружаются, я хочу показать форму с индикатором прогресса (с использованием стиля границы bsNone).Delphi отключить форму при загрузке

Но, если я показываю форму с ShowModal, выполнение основной формы останавливается, поэтому я не могу этого сделать.

Если я вызываю Show, у пользователя есть доступ ко всем другим компонентам формы, и это может быть опасно, в то время как фото не загружается полностью.

Мне нужно проложить путь, чтобы отключить все на основной форме, а загрузка не завершена.

Пожалуйста, советую мне, как это возможно.

+1

Если вы бы хотели сохранить модальную форму, вы могли бы назвать рутину из ваших модальных показанной форма. например передав метод для вызова внутри конструктора модальной показанной формы. – bummi

+0

Помимо отключения формы, вы также можете скрыть основную форму. Другие возможности включают вызов Load-процедуры из модального диалога прогресса. – GolezTrol

ответ

12

Установите MainForm в качестве PopupParent для формы выполнения, чтобы MainForm никогда не появлялся поверх формы выполнения. Затем просто установите MainForm.Enabled := False, пока форма выполнения открыта и установите MainForm.Enabled := True, когда форма прогресса закрыта.

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; 

Это моделирует хау ShowModal() ведет себя к пользователю (MainForm не используется интерактивным, а форма прогресса открыта), но без блокировки коды.

3

Прежде всего, прямой ответ на ваш вопрос.

Мне нужно проложить путь, чтобы отключить все на основной форме.

Установить MainForm.Enabled на номер False, чтобы отключить окно, связанное с основной формой. И для повторного включения установите вместо этого значение True.


Ваша фундаментальная проблема заключается в том, что вы выполняете долго выполняемые задачи в потоке графического интерфейса пользователя. Это всегда плохая идея, и выход состоит в том, чтобы выполнять эти длительные задачи в отдельном потоке.

Как только вы перемещаете длинные задачи в отдельный поток, вы обнаружите, что ShowModal - это именно то, что вам нужно, чтобы показать вашу форму прогресса.

1

Как я объяснил в своем другом ответе, идеальным решением для решения задачи, связанной с длительной работой, является нить, отличная от потока графического интерфейса пользователя. Поток GUI должен обрабатывать короткие запущенные задачи, чтобы он всегда мог своевременно обслуживать очередь сообщений.

Однако, если у вас уже есть код, предполагающий, что работающая задача выполняется в потоке графического интерфейса пользователя, вы можете предпочесть более целесообразный подход и отложить повторный факторинг на потоковый код. В этом случае, на мой взгляд, еще лучше использовать ShowModal для отображения вашей формы выполнения.

Но для выполнения этой работы вам нужно найти, чтобы выполняемая работа выполнялась в вызове ShowModal. Вы можете сделать это следующим образом:

  1. Прежде чем позвонить по телефону ShowModal, отправьте задачу на форму. Например, передайте TProc конструктору формы выполнения.
  2. Переопределение формы Activate формы выполнения. Это будет выполнено непосредственно перед запуском функции ShowModal. При реализации Activate отправьте сообщение в форму.
  3. Когда форма обрабатывает это сообщение, вызовите задачу, которая была передана конструктору.

Очевидно, что вам нужно будет позвонить ProcessMessages в свою задачу, чтобы поддерживать основную очередь сообщений очереди графического интерфейса пользователя. Очевидно, вы уже должны это делать.

1

Возможно, вы захотите использовать функции DisableTaskWindows и EnableTaskWindows.

Если вы используете простой ParentForm.Enabled := False для родительской формы, вы можете получить доступ ко всем другим формам, таким как основная форма, если она отличается от ParentForm. Очевидно, это еще опасно.

Вот короткий пример:

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

Установите PopupParent формы детской = 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;