我在主執行緒中有一些作業要做,有時會持續超過幾秒鐘。發生這種情況時,我想將滑鼠游標更改為忙碌狀態(沙漏,在整個主表單上)。但這必須延遲完成(比如 250 毫秒),因為大多數情況下作業時間較短,而且過于頻繁地更改游標很煩人。我不能從主執行緒執行此操作,因為它顯然正忙于做其他事情。所以我想從另一個執行緒來做。但是……驚喜!從執行緒設定Screen.Cursor:= crHourGlass不起作用。我認為該Screen物件只能從主執行緒訪問。我在忙時無法與主執行緒同步任何東西......關于如何使其作業的任何想法?
unit MouseCursor;
interface
uses
System.Classes, Winapi.Windows;
type
TMouseCursor = class(TThread)
private type
TCommand = (cmdSetBusy = $FB45BA57,cmdSetDone = $C75F1D29);
private
hResume: THandle;
Command: TCommand;
TimeOut: Cardinal;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create;
destructor Destroy; override;
procedure Busy;
procedure Done;
end;
implementation
uses
Vcl.Forms, Vcl.Controls;
const
BusyDelay = 250;
{ TMouseCursor }
constructor TMouseCursor.Create;
begin
inherited Create(False);
FreeOnTerminate:= True;
hResume:= CreateEvent(nil, False, False, nil);
end;
destructor TMouseCursor.Destroy;
begin
CloseHandle(hResume);
inherited;
end;
procedure TMouseCursor.TerminatedSet;
begin
Command:= cmdSetDone;
inherited;
SetEvent(hResume);
end;
procedure TMouseCursor.Busy;
begin
Command:= cmdSetBusy;
SetEvent(hResume);
end;
procedure TMouseCursor.Done;
begin
Command:= cmdSetDone;
SetEvent(hResume);
end;
procedure TMouseCursor.Execute;
var WaitRes: Cardinal;
begin
TimeOut:= INFINITE;
repeat
WaitRes:= WaitForSingleObject(hResume, TimeOut);
case WaitRes of
WAIT_TIMEOUT : begin Screen.Cursor:= crHourGlass; TimeOut:= INFINITE; end;
WAIT_OBJECT_0: case Command of
cmdSetBusy: TimeOut:= BusyDelay;
cmdSetDone: begin Screen.Cursor:= crDefault; TimeOut:= INFINITE; end;
end;
end;
until Terminated;
end;
end.
uj5u.com熱心網友回復:
您必須使用創建視窗的執行緒來設定游標。我建議更改您的設計并將主執行緒正在完成的作業放入可由主執行緒監視的作業執行緒(可能使用計時器或由作業執行緒發出Synchronize呼叫)。您的主執行緒不應放棄保持程式運行和回應的訊息回圈。所以一般來說,你的主執行緒應該不斷地監聽和處理發送給它的系統訊息。如果任何作業可能需要一些時間,請將其放入作業執行緒中。
要使該Synchronise方法作業,主執行緒必須處于空閑狀態 -Synchronise在訊息回圈中等待。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/430565.html
