Delphi:屏幕。光标不工作,可以';t计算Windows.SetCursor(crHourGlass)

Delphi:屏幕。光标不工作,可以';t计算Windows.SetCursor(crHourGlass),delphi,Delphi,在我的应用程序中,我有 Screen.Cursor := crHourGlass; Application.ProcessMessages; try ... finally Screen.Cursor := crDefault; Application.ProcessMessages; end; 但这根本没有达到预期效果。在处理时,它似乎会立即变回crDefault 谷歌搜索之后,我决定试试Windows.SetCursor()——但我搜索了MSDN,找不到光标类型列表 更新 我以为

在我的应用程序中,我有

Screen.Cursor := crHourGlass;
Application.ProcessMessages;
try
...

finally
  Screen.Cursor := crDefault;
  Application.ProcessMessages;
end;
但这根本没有达到预期效果。在处理时,它似乎会立即变回crDefault

谷歌搜索之后,我决定试试Windows.SetCursor()——但我搜索了MSDN,找不到光标类型列表

更新
我以为我找到了解决方案(使用SetSystemCursor(Screen.Cursors[crHourGlass],OCR_NORMAL)),但我似乎无法将光标更改回正常状态:(.

取决于try块中的内容。如果这不需要任何时间,则光标将立即更改回原来的位置。如果将调试语句放在finally之前,则应该看到它在光标返回默认值之前执行

此外,在启动例程时,不必假定光标为默认值。安全的方法是:

var
  C: TCursor;

begin

  C : = Screen.Cursor;
  Screen.Cursor := crHourGlass;

  try
    // long running code here
  finally
    Screen.Cursor := C;
  end;

end;

最后(请原谅该表达式),如果使用Application.ProcessMessages的目的是确保显示更改的光标,则不需要它。

我想我有解决方案:

以下是如何更改“整个桌面”的光标,而不仅仅是您的应用程序:

SetSystemCursor(Screen.Cursors[crDefault], OCR_NORMAL);
// 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;
但请注意:任何其他希望更改光标的应用程序/窗口都会这样做-因此,只有当您的应用程序繁忙时,您的用户不会与其他应用程序混在一起时,这才有效。作为一种过渡,您可以临时将所有系统默认光标更改为您想要的光标-并在过程结束后将其全部更改回来党卫军

我仍然对MSDN没有为SetCursor提供游标类型感到失望,但幸运的是,我最终没有使用它

更新: 这似乎是正确的轨迹,但在设置SystemCursor(Screen.Cursors[crHourGlass],OCR_NORMAL)之后,我似乎无法将光标更改回原来的位置; 如果有人在读这篇文章,如果你能花点时间给我提供一些工作代码,我将不胜感激。1.将系统光标设置为沙漏,然后返回到箭头

编辑:返回默认光标的示例代码:

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;
procedure TForm1.按钮1点击(发送方:TObject);
变量
卡罗,乔尔:哈库索;
开始
cArrow:=CopyImage(Screen.Cursors[crArrow],IMAGE\u CURSOR,0,0,LR\u COPYFROMRESOURCE);
cHour:=CopyImage(Screen.Cursors[crHourGlass],IMAGE\u CURSOR,0,0,LR\u COPYFROMRESOURCE);
如果(cArrow 0)和(cHour 0)并设置系统光标(cHour,OCR_NORMAL),则
尝试
//处理
最后
设置系统光标(cArrow,OCR_NORMAL);
结束;
结束;

我的应用程序也遇到了同样的问题,我的解决方案是调用
Application.ProcessMessages
在表单构造函数中

这是我的测试应用程序:

SetSystemCursor(Screen.Cursors[crDefault], OCR_NORMAL);
// 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;
第二种形式

// 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;
此解决方案将保持系统光标不变。

尝试以下操作:

Screen.Cursor := crHourGlass;
try
  ...
finally
  TThread.Synchronize(nil,
    procedure
    begin
      Screen.Cursor := crDefault;
    end
  );
end;

对我来说,它工作正常。

你的问题中没有更多细节,我能说的是:如果它似乎立即变回crDefault,那么try子句中的代码可能正在将其变回(或者调用一些进行更改的代码)或者它可能使用某种异步进程,例如启动另一个线程,该线程实际上是处理该事物的线程。因此,程序执行finally部分,并几乎立即将光标更改回crDefault。JachGrate>No似乎发生的是,设置光标仅在应用程序具有pr时有效oper focus(操作焦点)-但任何发生在应用程序之外的进程-例如调用DLL进程或要求扫描仪扫描(注意:我扫描时没有显示扫描仪进度的任何弹出表单等)-然后Windows恢复默认光标。因此,我想我需要一种方法在Windows中为所有应用程序设置光标,直到我的进程完成。“因此,我想我需要一种方法在Windows中为所有应用程序设置光标,直到我的进程完成”-这是一个非常奇怪的要求。只有您的应用程序忙。为什么您希望其他应用程序在不忙的时候看起来很忙?“只有您的应用程序忙。为什么您希望其他应用程序在不忙的时候看起来很忙?”那么,我该如何解决这个问题呢?当我按下一个按钮时,我设置了屏幕。光标:=crHourglass;然后我让我的扫描仪获取图像-这会导致应用程序在等待扫描完成时失去焦点10秒(注:如前所述,它在没有任何“新窗口”等的情况下失去焦点)然后它调用一个DLL,再次导致应用程序失去焦点。在所有这些“失去焦点”的时间内,光标解析回crDefault(箭头)@Richard:你可以一步一步地运行你的应用程序,而IDE不会与你的窗口重叠,在你执行每一行代码时检查光标,检查哪一行会将其更改回crDefault。然后跟踪该行并跟踪代码,直到你找到错误的指令。也许它真的是扫描仪dll打电话……因此,您无法采取任何措施使其正确,但您的代码或第三方库中可能有一些内容可以更改或解决。顺便说一句:如果您希望我收到您的回复,请在评论中使用@在我的名字之前。谢谢,但它根本不起作用。是的,在t中会发生很多处理他尝试..最后阻止,事实上尝试中有一些过程..最后调用其他过程等-这些过程中的一些可能会暂时将焦点从应用程序移开,例如让扫描仪扫描(应用程序将等待扫描)很明显,在这段时间内,我的光标不是沙漏。我如何才能强制执行此操作?您跟踪了吗?您的代码将更改光标。可能在try块的早期,您自己的代码或库(扫描仪?)中的代码包含再次更改光标的代码。如果该代码使sam