C# Windows 窗体 DateTimePicker,如何获取 SelectedText、SelectionStart 和 SelectionLength?

Posted

技术标签:

【中文标题】C# Windows 窗体 DateTimePicker,如何获取 SelectedText、SelectionStart 和 SelectionLength?【英文标题】:C# Windows Forms DateTimePicker, how to get the SelectedText, SelectionStart, and SelectionLength? 【发布时间】:2020-08-12 23:31:22 【问题描述】:

.NET DateTimePicker 有文本,但我不知道如何获取和设置 DateTimePicker 的 SelectionStart、SelectionLength 和 SelectionText 属性。

例如,我如何以编程方式选择日期“2001 年 11 月 17 日”中的 2 天数字? 以及如何以编程方式确定当前选择的起始位置?

基本上,我想做的是类似于以下代码:

// Select the day's text
((TextBox)myDateTimePicker).SelectionStart = 3;
((TextBox)myDateTimePicker).SelectionLength = 2;

// Get the text start position
return ((TextBox)myDateTimePicker).SelectionStart;

【问题讨论】:

DTP.Enter 事件中调用SendKeys.Send("Right") 以选择下一部分。 @JQSOFT 读懂了我的想法。实际上,这是我的最终目标。当按下空格键时,我会执行您描述的部分步进。我希望 Tab 也可以用于步进。不幸的是,Tab 然后在文本框中卡住。我想知道 SelectionStart 何时位于最后或第一部分(因此我可以在 year 中为 Tab 设置 PreviewKeyDown 的 e.IsInputKey = false; 并在 month 中设置 Shift-Tab 所以用户可以 Tab 浏览 DTP 部分并继续前进。 我还希望在从 DTP 左侧从外部控件输入 DTP 时能够选择 DTP 的月份;或从 DTP 右侧的外部控件输入 DTP 时选择 DTP 的 年份 绝招here。 @JQSOFT 的妙招对我有用。 【参考方案1】:

以下代码是我的问题的答案。它源自DateTimePicker get focused field 问题的answer。

public event System.EventHandler<EventArgs> Parent_ValueChanged;

public enum DatePart

  YEAR,
  MONTH,
  DAY


[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DatePart SelectedPart  get; set; 

private DateTime m_PreviousValue = TimeTools.UnixBaseTime;
private bool m_CheckSelectedPart = false;

public void DateTimeField_GotFocus(object sender, EventArgs e)

  m_PreviousValue = this.Value;
  m_CheckSelectedPart = true;
  SendKeys.SendWait("UP");
  SendKeys.SendWait("DOWN");
  m_CheckSelectedPart = false;



public void DateTimeField_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)

  switch (e.KeyCode)
  
    case Keys.Space: 
      e.IsInputKey = true;
      break;
    case Keys.Tab:
      m_PreviousValue = this.Value;
      m_CheckSelectedPart = true;
      SendKeys.SendWait("UP");
      SendKeys.SendWait("DOWN");
      m_CheckSelectedPart = false;

      // Set e.IsInputKey to false to let Windows use the Tab 
      // to go to the previous or next component with TabStop = true
      if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
      
        // false = exit to the left or up
        e.IsInputKey = !(SelectedPart == DatePart.MONTH);
      
      else
       
        // false = exit to the right or down
        e.IsInputKey = !(SelectedPart == DatePart.YEAR);
      
      break;
    default: break;
  



public void DateTimeField_KeyDown(object sender, KeyEventArgs e)

  // Mimic Delphi's DateTimePicker behavior by advancing to the next part in the format
  // using Space or Tab
  if (e.KeyCode.Equals(Keys.Space) || e.KeyCode.Equals(Keys.Tab))
  
    if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
    
      SendKeys.Send("left");
    
    else
    
      SendKeys.Send("right");
    
  



private void DateTimeField_ValueChanged(object sender, EventArgs e)

  if ((m_CheckSelectedPart) && (sender is DateTimePicker dtp))
  
    TimeSpan change = (dtp.Value - m_PreviousValue);
    var dayChange = Math.Abs(change.Days);
    if (dayChange == 1)
    
      SelectedPart = DatePart.DAY;
    
    else if (dayChange >= 365)
    
      SelectedPart = DatePart.YEAR;
    
    else
    
      SelectedPart = DatePart.MONTH;
    
    m_PreviousValue = dtp.Value;
  

  // parent's ValueChanged event handler
  Parent_ValueChanged?.Invoke(sender, e);


【讨论】:

【参考方案2】:

我知道这个问题被问了很长时间,但它对于下一个仍在寻找暂时未解决的解决方案的人很有用,再次询问应该是一个满足的解决方案,编写的代码更少,并且管理。

在焦点离开DateTimerPicker 控件并稍后返回到它之后,控件会记住哪个部分(日、月或年)具有焦点。焦点回到那部分。

如何强制焦点回到控件的第一个per?

要强制控件忘记哪个部分具有焦点,您可以更改格式,然后再次将其更改回来。因此,如果将其设置为 Short,请将其设置为 Long,然后再设置为 Short。

诀窍是在通过 Enter 事件返回焦点后执行此操作

所以最好的地方是在 Enter 事件中:

Private Sub DateTimePicker_Enter(sender As Object, e As System.EventArgs) Handles DateTimePicker.Enter

        DateTimePicker.Format = DateTimePickerFormat.Long
        DateTimePicker.Format = DateTimePickerFormat.Short
End Sub

【讨论】:

以上是关于C# Windows 窗体 DateTimePicker,如何获取 SelectedText、SelectionStart 和 SelectionLength?的主要内容,如果未能解决你的问题,请参考以下文章

c#中让Windows窗体只运行一次,并在第二次启动窗体时激活该窗体

c# windows 窗体 如何 设置菜单的权限

C# - 从 Windows 服务启动 Windows 窗体 [重复]

显示后的 Windows 窗体不透明度 - C#

C# 使用VS创建Windows窗体应用程序

恢复 C# Windows 窗体背景色