Reputation: 579
In my app I have
Screen.Cursor := crHourGlass;
Application.ProcessMessages;
try
...
finally
Screen.Cursor := crDefault;
Application.ProcessMessages;
end;
But this simply isn't working as expected. It seems to immediately change back to crDefault when it is processing.
After some Googling I decided to try Windows.SetCursor() - but I've searched the MSDN and I can't find the list of cursor types.
Update I thought I found the solution (using SetSystemCursor(Screen.Cursors[crHourGlass], OCR_NORMAL);) but I can't seem to then change the cursor back to normal :(.
Upvotes: 5
Views: 14330
Reputation: 1
Try this:
Screen.Cursor := crHourGlass;
try
...
finally
TThread.Synchronize(nil,
procedure
begin
Screen.Cursor := crDefault;
end
);
end;
for me it's working properly.
Upvotes: 0
Reputation: 958
I had the same problem on my application and the solution that worked for me was to call the
Application.ProcessMessages
in the form constructor
here is my test application:
// MainFormUnit
type
TMainForm = class(TForm)
btnClickMe: TButton;
procedure btnClickMeClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses
LazyFormUnit;
{$R *.dfm}
procedure TMainForm.btnClickMeClick(Sender: TObject);
var
oLazyForm: TLazyForm
begin
oLazyForm := TLazyForm.Create(Self, 0);
oLazyForm.ShowModal;
oLazyForm.Free;
end;
and the second form
// LazyFormUnit
type
TLazyForm = class(TForm)
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
constructor Create(p_oComponent: TComponent; p_nValue: Integer); reintroduce;
end;
implementation
{$R *.dfm}
constructor TLazyForm.Create(p_oComponent: TComponent; p_nValue: Integer);
begin
inherited Create(p_oComponent);
Application.ProcessMessages;
end;
procedure TLazyForm.FormShow(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
Application.ProcessMessages;
try
Sleep(1000 * 5);
finally
Screen.Cursor := crDefault;
end;
end;
This solution will keep the system cursor unchanged.
Upvotes: 3
Reputation: 579
I think I have the solution:
Here is how to change the cursor for 'the whole desktop' - not just for your application:
SetSystemCursor(Screen.Cursors[crDefault], OCR_NORMAL);
But be warned: any other applications/windows that want to change cursors will do so - so this is only effective if your user doesn't mess around with other applications while YOUR application is busy. As an over-ride, you could temporarily change all your systems default cursors to the cursor you want - and change them all back after the process.
I am still disappointed at the MSDN for not providing its cursor types for SetCursor - but fortunately I didn't end up having to use it.
Update: This seems to be the right track, but I can't seem to change the cursor back after SetSystemCursor(Screen.Cursors[crHourGlass], OCR_NORMAL); If anybody's reading this, I would appreciate if you take a moment to provide me with some working code - that 1. Sets the System Cursor to an hourglass, and then back to an arrow.
edit: Sample code for reverting back to default cursor:
procedure TForm1.Button1Click(Sender: TObject);
var
cArrow, cHour: HCURSOR;
begin
cArrow := CopyImage(Screen.Cursors[crArrow], IMAGE_CURSOR, 0, 0, LR_COPYFROMRESOURCE);
cHour := CopyImage(Screen.Cursors[crHourGlass], IMAGE_CURSOR, 0, 0, LR_COPYFROMRESOURCE);
if (cArrow <> 0) and (cHour <> 0) and SetSystemCursor(cHour, OCR_NORMAL) then
try
// do processing
finally
SetSystemCursor(cArrow, OCR_NORMAL);
end;
end;
Upvotes: 6
Reputation: 51000
Depends on what's in your try block. If that doesn't take any time, then the cursor will change back right away. If you put a debug statement right before the finally, you should see it execute before the cursor returns to crDefault.
Also, you should not necessarily assume that the cursor was crDefault when you start your routine. A safe method is:
var
C: TCursor;
begin
C : = Screen.Cursor;
Screen.Cursor := crHourGlass;
try
// long running code here
finally
Screen.Cursor := C;
end;
end;
And, finally (if you'll excuse the expression), you do not need Application.ProcessMessages if the purpose you're using it for is to make sure the changed cursor is shown.
Upvotes: 1