【问题标题】:Delphi 2007 - set focus of TDateTimePicker to seconds on entryDelphi 2007 - 将 TDateTimePicker 的焦点设置为进入时的秒数
【发布时间】:2018-01-23 03:25:33
【问题描述】:

当控件第一次获得焦点时,有没有办法将 TDateTimePicker(设置为时间选择器)的焦点显式设置为“秒”字段?默认值似乎是“小时”字段。当您在控件之间切换时,控件似乎记得 H、M、S 中的哪一个具有焦点,这没关系,但我希望能够在带有控件的对话框首次显示时将焦点显式设置为秒字段。

This answer 建议切换格式(将焦点初始化到“小时”字段),然后我可以发送两个光标右消息移动到秒字段,但我希望少一些 希斯·罗宾逊

【问题讨论】:

  • 根据MSDN,没有可以发送到控件以选择特定字段的消息,这通常意味着没有直接的方法。

标签: delphi focus datetimepicker delphi-2007


【解决方案1】:

没有直接的方法,但如果包含以下代码,则可以在 TDateTimePicker 控件中操作焦点的位置:

{$IF CompilerVersion >= 17 }
{$DEFINE D2005UP }
{$ELSE }
{$UNDEF D2005UP }
{$ENDIF }

{$IF CompilerVersion >= 20 }
{$DEFINE D2009UP }
{$ELSE }
{$UNDEF D2009UP }
{$ENDIF }

PROCEDURE SendKeys(CONST Keys : ARRAY OF WORD);
  VAR
    {$IFDEF D2009UP }
    InputEvents : TArray<TInput>;
    {$ELSE }
    InputEvents : ARRAY OF TInput;
    {$ENDIF }
    {$IFNDEF D2005UP }
    I           : INTEGER;
    {$ENDIF }
    Key         : WORD;

  PROCEDURE Add(Key : WORD ; Action : WORD = 0);
    VAR
      INP       : TInput;

    BEGIN
      FillChar(INP,SizeOf(TInput),0);
      INP.Itype:=INPUT_KEYBOARD;
      INP.ki.wVk:=Key;
      INP.ki.wScan:=0;
      INP.ki.dwFlags:=Action;
      INP.ki.time:=0;
      INP.ki.dwExtraInfo:=0;
      {$IFDEF D2009UP }
        InputEvents:=InputEvents+[INP]
      {$ELSE }
        SetLength(InputEvents,SUCC(LENGTH(InputEvents)));
        InputEvents[HIGH(InputEvents)]:=INP
      {$ENDIF }
    END;

  PROCEDURE AddKeyDown(Key : WORD);
    BEGIN
      Add(Key)
    END;

  PROCEDURE AddKeyUp(Key : WORD);
    BEGIN
      Add(Key,KEYEVENTF_KEYUP)
    END;

  PROCEDURE AddKeyPress(Key : WORD);
    BEGIN
      AddKeyDown(Key);
      AddKeyUp(Key)
    END;

  BEGIN
    IF LENGTH(Keys)=0 THEN EXIT;
    {$IFDEF D2005UP }
      FOR Key IN Keys DO AddKeyPress(Key);
    {$ELSE }
      FOR I:=LOW(Keys) TO HIGH(Keys) DO BEGIN
        Key:=Keys[I];
        AddKeyPress(Key)
      END;
    {$ENDIF }
    SendInput(LENGTH(InputEvents),InputEvents[LOW(InputEvents)],SizeOf(TInput));
    Application.ProcessMessages
  end;

PROCEDURE SetDateTimePickerFocus(DTP : TDateTimePicker ; FocusTo : CHAR);
  VAR
    S   : STRING;

  BEGIN
    DTP.SetFocus;
    Application.ProcessMessages;
    S:=DTP.Format; DTP.Format:='HH';
    Application.ProcessMessages;
    DTP.Format:=S;
    Application.ProcessMessages;
    CASE UpCase(FocusTo) OF
      'H' : ; // NOTHING //
      'M' : SendKeys([VK_RIGHT]);
      'S' : SendKeys([VK_RIGHT,VK_RIGHT])
    ELSE // OTHERWISE //
      RAISE ERangeError.Create('Unsupported FocusTo value in SetDateTimePickerFocus: "'+FocusTo+'"')
    END
  END;

{$IFDEF D2005UP }
TYPE
  TDateTimePickerHelper = CLASS HELPER FOR TDateTimePicker
                            PROCEDURE   SetFocusTo(C : CHAR);
                          END;

{ TDateTimePickerHelper }

PROCEDURE TDateTimePickerHelper.SetFocusTo(C : CHAR);
  BEGIN
    SetDateTimePickerFocus(Self,C)
  END;
{$ENDIF }

如果您使用 Delphi 2005 及更高版本,TDateTimePicker 控件还有一个类帮助器。

用法(Delphi 2005 之前):

SetDateTimePickerFocus(DateTimePicker1,'S'); // 'H', 'M' or 'S' to select field

用法(Delphi 2005+):

DateTimePicker1.SetFocusTo('S'); // 'H', 'M' or 'S' to select field

【讨论】:

  • 为什么需要Application.ProcessMessages
  • 我的经验告诉我,在大多数情况下,您更改了属性并希望确保它已经生效,您需要允许 Windows 看到您的更改。在这种情况下我没有专门测试它,但在许多其他情况下,我已经看到如果我在某些点省略 ProcessMessages,我的以下代码不会按预期工作,因为它是基于假设前面的操作已完全完成(并且没有 ProcessMessages,它还没有完成)。
  • 我可以向您保证,不需要Application.ProcessMessages。您可以在 DTP 上调用 RecreateWnd 将焦点重置到小时字段,而不是 Format 技巧。
猜你喜欢
  • 2014-06-30
  • 2021-05-18
  • 2016-02-27
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
相关资源
最近更新 更多