最近在  https://mp.weixin.qq.com/s/3dEO0NZQv5YLqK72atG4Wg   官方公众号看到了 用WPF 制作 标尺

在去年项目上也接到了一个需求,用于排版自定义拖拽控件画布对齐的标尺,当时接到的要求是 需要横纵对齐的表次,并且鼠标滑动,刻度的上方需要跟着有影子划过的效果。

具体实现如下:

创建 标尺控件 RulerControl.cs

  1 [TemplatePart(Name = "trackLine", Type = typeof(Line))]
2 internal class RulerControl : Control
3 {
4 public static readonly DependencyProperty DpiProperty = DependencyProperty.Register("Dpi", typeof(Dpi), typeof(RulerControl));
5 public static readonly DependencyProperty DisplayPercentProperty = DependencyProperty.Register("DisplayPercent", typeof(double), typeof(RulerControl));
6 public static readonly DependencyProperty DisplayTypeProperty = DependencyProperty.Register("DisplayType", typeof(RulerDisplayType), typeof(RulerControl));
7 public static readonly DependencyProperty DisplayUnitProperty = DependencyProperty.Register("DisplayUnit", typeof(RulerDisplayUnit), typeof(RulerControl));
8 public static readonly DependencyProperty ZeroPointProperty = DependencyProperty.Register("ZeroPoint", typeof(double), typeof(RulerControl));
9
10 /// <summary>
11 /// 定义静态构造函数
12 /// </summary>
13 static RulerControl()
14 {
15 DefaultStyleKeyProperty.OverrideMetadata(typeof(RulerControl), new FrameworkPropertyMetadata(typeof(RulerControl)));
16 }
17
18 #region 属性
19 /// <summary>
20 /// 屏幕分辨率
21 /// </summary>
22 public Dpi Dpi
23 {
24 get
25 {
26 return ((Dpi)GetValue(DpiProperty));
27 }
28 set
29 {
30 SetValue(DpiProperty, value);
31 }
32 }
33
34 /// <summary>
35 /// 设置0点从哪里开始
36 /// </summary>
37 public double ZeroPoint
38 {
39 get
40 {
41 return ((double)GetValue(ZeroPointProperty));
42 }
43 set
44 {
45 SetValue(ZeroPointProperty, value);
46 InvalidateVisual();
47 }
48 }
49
50 /// <summary>
51 /// 显示的比率(目前支持0-1的选项)
52 /// </summary>
53 public double DisplayPercent
54 {
55 get
56 {
57 return ((double)GetValue(DisplayPercentProperty));
58 }
59 set
60 {
61 if (value > 1)
62 {
63 value = 1;
64 }
65 SetValue(DisplayPercentProperty, value);
66 InvalidateVisual();
67 }
68 }
69
70 /// <summary>
71 /// 显示的类型:枚举类(支持横向或者竖向)
72 /// </summary>
73 public RulerDisplayType DisplayType
74 {
75 get
76 {
77 return ((RulerDisplayType)GetValue(DisplayTypeProperty));
78 }
79 set
80 {
81 SetValue(DisplayTypeProperty, value);
82 }
83 }
84
85 /// <summary>
86 /// 显示的单位:cm和pixel
87 /// </summary>
88 public RulerDisplayUnit DisplayUnit
89 {
90 get
91 {
92 return ((RulerDisplayUnit)GetValue(DisplayUnitProperty));
93 }
94 set
95 {
96 SetValue(DisplayUnitProperty, value);
97 }
98 }
99 #endregion
100
101 #region 常量
102 public const double _inchCm = 2.54; //一英寸为2.54cm
103 private const int _p100StepSpanPixel = 100;
104 private const int _p100StepSpanCm = 2;
105 private const int _p100StepCountPixel = 20;
106 private const int _p100StepCountCm = 20;
107
108 #endregion
109
110 #region 变量
111 private double _minStepLengthCm;
112 private double _maxStepLengthCm;
113 private double _actualLength;
114 private int _stepSpan;
115 private int _stepCount;
116 private double _stepLength;
117 Line mouseVerticalTrackLine;
118 Line mouseHorizontalTrackLine;
119 #endregion
120
121 #region 标尺边框加指针显示
122 public void RaiseHorizontalRulerMoveEvent(MouseEventArgs e)
123 {
124 Point mousePoint = e.GetPosition(this);
125 mouseHorizontalTrackLine.X1 = mouseHorizontalTrackLine.X2 = mousePoint.X;
126 }
127 public void RaiseVerticalRulerMoveEvent(MouseEventArgs e)
128 {
129 Point mousePoint = e.GetPosition(this);
130 mouseVerticalTrackLine.Y1 = mouseVerticalTrackLine.Y2 = mousePoint.Y;
131 }
132
133 public override void OnApplyTemplate()
134 {
135 base.OnApplyTemplate();
136 mouseVerticalTrackLine = GetTemplateChild("verticalTrackLine") as Line;
137 mouseHorizontalTrackLine = GetTemplateChild("horizontalTrackLine") as Line;
138 mouseVerticalTrackLine.Visibility = Visibility.Visible;
139 mouseHorizontalTrackLine.Visibility = Visibility.Visible;
140 }
141 #endregion
142
143 /// <summary>
144 /// 重画标尺数据
145 /// </summary>
146 /// <param name="drawingContext"></param>
147 protected override void OnRender(DrawingContext drawingContext)
148 {
149 try
150 {
151 Pen pen = new Pen(new SolidColorBrush(Colors.Black),0.8d);
152 pen.Freeze();
153 Initialize();
154 GetActualLength();
155 GetStep();
156 base.OnRender(drawingContext);
157
158 this.BorderBrush = new SolidColorBrush(Colors.Black);
159 this.BorderThickness = new Thickness(0.1);
160 this.Background = new SolidColorBrush(Colors.White);
161
162 #region try
163 // double actualPx = this._actualLength / DisplayPercent;
164 Position currentPosition = new Position
165 {
166 CurrentStepIndex = 0,
167 Value = 0
168 };
169
170 switch (DisplayType)
171 {
172 case RulerDisplayType.Horizontal:
173 {
174 /* 绘制前半段 */
175 DrawLine(drawingContext, ZeroPoint, currentPosition, pen, 0);
176 /* 绘制后半段 */
177 DrawLine(drawingContext, ZeroPoint, currentPosition, pen, 1);
178 break;
179 }
180 case RulerDisplayType.Vertical:
181 {
182 /* 绘制前半段 */
183 DrawLine(drawingContext, ZeroPoint, currentPosition, pen, 0);
184 /* 绘制后半段 */
185 DrawLine(drawingContext, ZeroPoint, currentPosition, pen, 1);
186 break;
187 }
188 }
189 #endregion
190 }
191 catch (Exception ex)
192 {
193 Console.WriteLine(ex.Message);
194 }
195 }
196
197 private void DrawLine(DrawingContext drawingContext, double currentPoint, Position currentPosition, Pen pen, int type)
198 {
199 double linePercent = 0d;
200 while (true)
201 {
202 if (currentPosition.CurrentStepIndex == 0)
203 {
204
205 FormattedText formattedText = GetFormattedText((currentPosition.Value / 10).ToString());
206
207
208 switch (DisplayType)
209 {
210 case RulerDisplayType.Horizontal:
211 {
212 var point = new Point(currentPoint + formattedText.Width / 2, formattedText.Height / 3);
213 if (point.X<0)
214 {
215 break;
216 }
217 drawingContext.DrawText(formattedText, point);
218 break;
219 }
220 case RulerDisplayType.Vertical:
221 {
222 Point point = new Point(this.ActualWidth, currentPoint + formattedText.Height / 2);
223 RotateTransform rotateTransform = new RotateTransform(90, point.X, point.Y);
224 if (point.Y<0)
225 {
226 break;
227 }
228 drawingContext.PushTransform(rotateTransform);
229 drawingContext.DrawText(formattedText, point);
230 drawingContext.Pop();
231 break;
232 }
233 }
234
235 linePercent = (int)LinePercent.P100;
236 }
237 else if (IsFinalNum(currentPosition.CurrentStepIndex, 3))
238 {
239 linePercent = (int)LinePercent.P30;
240 }
241 else if (IsFinalNum(currentPosition.CurrentStepIndex, 5))
242 {
243 linePercent = (int)LinePercent.P50;
244 }
245 else if (IsFinalNum(currentPosition.CurrentStepIndex, 7))
246 {
247 linePercent = (int)LinePercent.P30;
248 }
249 else if (IsFinalNum(currentPosition.CurrentStepIndex, 0))
250 {
251 linePercent = (int)LinePercent.P70;
252 }
253 else
254 {
255 linePercent = (int)LinePercent.P20;
256 }
257
258 linePercent = linePercent * 0.01;
259
260 switch (DisplayType)
261 {
262 case RulerDisplayType.Horizontal:
263 {
264 if (currentPoint > 0)
265 {
266 drawingContext.DrawLine(pen, new Point(currentPoint, 0), new Point(currentPoint, this.ActualHeight * linePercent));
267 }
268
269 if (type == 0)
270 {
271 currentPoint = currentPoint - _stepLength;
272 currentPosition.CurrentStepIndex--;
273
274 if (currentPosition.CurrentStepIndex < 0)
275 {
276 currentPosition.CurrentStepIndex = _stepCount - 1;
277 currentPosition.Value = GetNextStepValue(currentPosition.Value, _stepSpan, 0);
278 }
279 else if (currentPosition.CurrentStepIndex == 0)
280 {
281 if (currentPosition.Value % _stepSpan != 0)
282 {
283 currentPosition.Value = GetNextStepValue(currentPosition.Value, _stepSpan, 0);
284 }
285 }
286
287 if (currentPoint <= 0)
288 {
289 return;
290 }
291 }
292 else
293 {
294 currentPoint = currentPoint + _stepLength;
295 currentPosition.CurrentStepIndex++;
296
297 if (currentPosition.CurrentStepIndex >= _stepCount)
298 {
299 currentPosition.CurrentStepIndex = 0;
300 currentPosition.Value = GetNextStepValue(currentPosition.Value, _stepSpan, 1);
301 }
302
303 if (currentPoint >= _actualLength)
304 {
305 return;
306 }
307 }
308 break;
309 }
310 case RulerDisplayType.Vertical:
311 {
312 if (currentPoint > 0)
313 {
314 drawingContext.DrawLine(pen, new Point(0, currentPoint), new Point(this.ActualWidth * linePercent, currentPoint));
315 }
316 if (type == 0)
317 {
318 currentPoint = currentPoint - _stepLength;
319 currentPosition.CurrentStepIndex--;
320
321 if (currentPosition.CurrentStepIndex < 0)
322 {
323 currentPosition.CurrentStepIndex = _stepCount - 1;
324 currentPosition.Value = GetNextStepValue(currentPosition.Value, _stepSpan, 0);
325 }
326 else if (currentPosition.CurrentStepIndex == 0)
327 {
328 if (currentPosition.Value % _stepSpan != 0)
329 {
330 currentPosition.Value = GetNextStepValue(currentPosition.Value, _stepSpan, 0);
331 }
332 }
333
334 if (currentPoint <= 0)
335 {
336 return;
337 }
338 }
339 else
340 {
341 currentPoint = currentPoint + _stepLength;
342 currentPosition.CurrentStepIndex++;
343
344 if (currentPosition.CurrentStepIndex >= _stepCount)
345 {
346 currentPosition.CurrentStepIndex = 0;
347 currentPosition.Value = GetNextStepValue(currentPosition.Value, _stepSpan, 1);
348 }
349
350 if (currentPoint >= _actualLength)
351 {
352 return;
353 }
354 }
355 break;
356 }
357 }
358 }
359 }
360
361 /// <summary>
362 /// 获取下一个步长值
363 /// </summary>
364 /// <param name="value">起始值</param>
365 /// <param name="times">跨度</param>
366 /// <param name="type">半段类型,分为前半段、后半段</param>
367 /// <returns></returns>
368 private int GetNextStepValue(int value, int times, int type)
369 {
370 if (type == 0)
371 {
372 do
373 {
374 value--;
375 }
376 while (value % times != 0);
377 }
378 else
379 {
380 do
381 {
382 value++;
383 }
384 while (value % times != 0);
385 }
386 return (value);
387 }
388
389 [Obsolete]
390 private FormattedText GetFormattedText(string text)
391 {
392 return (new FormattedText(text,
393 //CultureInfo.GetCultureInfo("zh-cn"),
394 CultureInfo.GetCultureInfo("en-us"),
395 FlowDirection.LeftToRight,
396 new Typeface("宋体"),
397 12,
398 Brushes.Black));
399 }
400
401 private bool IsFinalNum(int value, int finalNum)
402 {
403 string valueStr = value.ToString();
404 if (valueStr.Substring(valueStr.Length - 1, 1) == finalNum.ToString())
405 {
406 return (true);
407 }
408 return (false);
409 }
410
411 /// <summary>
412 /// 初始化获取屏幕的DPI
413 /// </summary>
414 private void Initialize()
415 {
416 Dpi dpi = new Dpi();
417 dpi.DpiX = Dpi.DpiX;
418 dpi.DpiY = Dpi.DpiY;
419 if (Dpi.DpiX == 0)
420 {
421 dpi.DpiX = 96;
422 }
423
424 if (Dpi.DpiY == 0)
425 {
426 dpi.DpiY = 96;
427 }
428
429 Dpi = dpi;
430 _minStepLengthCm = 0.1;
431 _maxStepLengthCm = 0.3;
432
433 if (DisplayPercent == 0)
434 DisplayPercent = 1;
435
436 switch (DisplayUnit)
437 {
438 case RulerDisplayUnit.pixel:
439 {
440 _stepSpan = _p100StepSpanPixel;
441 _stepCount = _p100StepCountPixel;
442 break;
443 }
444 case RulerDisplayUnit.cm:
445 {
446 _stepSpan = _p100StepSpanCm;
447 _stepCount = _p100StepCountCm;
448 break;
449 }
450 }
451 int width = 15;
452 switch (DisplayType)
453 {
454 case RulerDisplayType.Horizontal:
455 {
456 if (this.ActualHeight == 0)
457 {
458 Height = width;
459 }
460 break;
461 }
462 case RulerDisplayType.Vertical:
463 {
464 if (this.ActualWidth == 0)
465 {
466 Width = width;
467 }
468 break;
469 }
470 }
471 }
472
473 /// <summary>
474 /// 获取每一个数字间隔的跨度
475 /// </summary>
476 private void GetStep()
477 {
478 switch (DisplayUnit)
479 {
480 case RulerDisplayUnit.pixel:
481 {
482 double stepSpanCm;
483 while (true)
484 {
485 stepSpanCm = _stepSpan / Convert.ToDouble(GetDpi()) * _inchCm * DisplayPercent;
486 double stepLengthCm = stepSpanCm / _stepCount;
487 int type = 0;
488 bool isOut = false;
489 if (stepLengthCm > _maxStepLengthCm)
490 {
491 type = 1;
492 _stepCount = GetNextStepCount(_stepCount, type, ref isOut);
493 }
494
495 if (stepLengthCm < _minStepLengthCm)
496 {
497 type = 0;
498 _stepCount = GetNextStepCount(_stepCount, type, ref isOut);
499 }
500
501 if (stepLengthCm <= _maxStepLengthCm && stepLengthCm >= _minStepLengthCm)
502 {
503 _stepLength = stepSpanCm / _inchCm * Convert.ToDouble(GetDpi()) / _stepCount;
504 break;
505 }
506 /* 已超出或小于最大步进长度 */
507 if (isOut)
508 {
509 _stepSpan = GetNextStepSpan(_stepSpan, type);
510 continue;
511 }
512 }
513 break;
514 }
515 }
516 }
517
518
519 private int GetNextStepCount(int stepCount, int type, ref bool isOut)
520 {
521 int result = stepCount;
522 isOut = false;
523 switch (type)
524 {
525 case 0:
526 {
527 if (stepCount == 20)
528 {
529 result = 10;
530 }
531 else
532 {
533 isOut = true;
534 }
535 break;
536 }
537 case 1:
538 {
539 if (stepCount == 10)
540 {
541 result = 20;
542 }
543 else
544 {
545 isOut = true;
546 }
547
548 break;
549 }
550 }
551 return result;
552 }
553
554
555 private int GetNextStepSpan(int stepSpan, int type)
556 {
557 string stepCountStr = stepSpan.ToString();
558 string resultStr = string.Empty;
559
560 switch (DisplayUnit)
561 {
562 case RulerDisplayUnit.pixel:
563 {
564 switch (type)
565 {
566 case 0:
567 {
568 if (stepCountStr.IndexOf('5') > -1)
569 {
570 resultStr = GetNumberAndZeroNum(1, stepCountStr.Length);
571 }
572 else if (stepCountStr.IndexOf('2') > -1)
573 {
574 resultStr = GetNumberAndZeroNum(5, stepCountStr.Length - 1);
575 }
576 else if (stepCountStr.IndexOf('1') > -1)
577 {
578 resultStr = GetNumberAndZeroNum(2, stepCountStr.Length - 1);
579 }
580 break;
581 }
582 case 1:
583 {
584 if (stepCountStr.IndexOf('5') > -1)
585 {
586 resultStr = GetNumberAndZeroNum(2, stepCountStr.Length - 1);
587 }
588 else if (stepCountStr.IndexOf('2') > -1)
589 {
590 resultStr = GetNumberAndZeroNum(1, stepCountStr.Length - 1);
591 }
592 else if (stepCountStr.IndexOf('1') > -1)
593 {
594 resultStr = GetNumberAndZeroNum(5, stepCountStr.Length - 2);
595 }
596 break;
597 }
598 }
599 break;
600 }
601 }
602
603 int result = 0;
604 if (string.IsNullOrWhiteSpace(resultStr))
605 {
606 return 0;
607 }
608
609 if (int.TryParse(resultStr, out result))
610 {
611 return result;
612 }
613 return result;
614 }
615
616
617 private string GetNumberAndZeroNum(int num, int zeroNum)
618 {
619 string result = string.Empty;
620 result += num;
621 for (int i = 0; i < zeroNum; i++)
622 {
623 result += "0";
624 }
625 return (result);
626 }
627
628
629 private int GetDpi()
630 {
631 switch (DisplayType)
632 {
633 case RulerDisplayType.Horizontal:
634 {
635 return (Dpi.DpiX);
636 }
637 case RulerDisplayType.Vertical:
638 {
639 return (Dpi.DpiY);
640 }
641 default:
642 {
643 return (Dpi.DpiX);
644 }
645 }
646 }
647
648 private void GetActualLength()
649 {
650 switch (DisplayType)
651 {
652 case RulerDisplayType.Horizontal:
653 {
654 _actualLength = this.ActualWidth;
655 break;
656 }
657 case RulerDisplayType.Vertical:
658 {
659 _actualLength = this.ActualHeight;
660 break;
661 }
662 }
663 }
664 }
665
666 public enum RulerDisplayType
667 {
668 Horizontal, Vertical
669 }
670
671 public enum RulerDisplayUnit
672 {
673 pixel, cm
674 }
675
676 public enum LinePercent
677 {
678 P20 = 20, P30 = 30, P50 = 50, P70 = 70, P100 = 100
679 }
680
681 public struct Dpi
682 {
683 public int DpiX
684 {
685 get; set;
686 }
687 public int DpiY
688 {
689 get; set;
690 }
691 }
692
693 public struct Position
694 {
695 public int Value
696 {
697 get; set;
698 }
699 public int CurrentStepIndex
700 {
701 get; set;
702 }
703 }

控件的引用:

 1 <UserControl x:Class="Hjmos.DataPainter.Controls.CanvaseCoreEditor"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6 xmlns:local="clr-namespace:Hjmos.DataPainter.Controls"
7 mc:Ignorable="d"
8 x:Name="CanvaseEditor"
9 d:DesignHeight="450" d:DesignWidth="800">
10 <Grid>
11
12 <Grid.ColumnDefinitions>
13 <ColumnDefinition Width="20"/>
14 <ColumnDefinition/>
15 </Grid.ColumnDefinitions>
16 <Grid.RowDefinitions>
17 <RowDefinition Height="20"/>
18 <RowDefinition/>
19 </Grid.RowDefinitions>
20 <!--横向标尺-->
21 <local:RulerControl DisplayUnit="pixel" DisplayType="Horizontal" Grid.Row="0" Grid.Column="1" x:Name="ucPanleHor"/>
22 <!--纵向标尺-->
23 <local:RulerControl DisplayUnit="pixel" DisplayType="Vertical" Grid.Row="1" Grid.Column="0" x:Name="ucPanleVer"/>
24
25
26 </Grid>
27 </UserControl>

鼠标在画布移动的时候触发标尺上的刻度阴影移动

        /// <summary>
/// 鼠标在画布移动的时候触发标尺上的刻度阴影移动
/// </summary>
/// <param name="obj"></param>
private void _diagramView_MouseMove(MouseEventArgs e)
{
ucPanleHor.RaiseHorizontalRulerMoveEvent(e);
ucPanleVer.RaiseVerticalRulerMoveEvent(e);
}

总结:技术点主要是用到了WPF 内部的渲染机制,调用 OnRender的方法,实现对线条绘制;通过计算总长度从而得出步长,绘制不同的长度线的标尺刻度。

仿Word的支持横轴竖轴的WPF 标尺的更多相关文章

  1. WPF仿Word头部格式,涉及DEV RibbonControl,NarvbarControl,ContentPresenter,Navigation

    时隔1个月,2015/06/17走进新的环境. 最近一个星期在学习仿Word菜单栏的WPF实现方式,废话不多说,先看一下效果. 打开界面后,默认选中[市场A],A对应的菜单栏,如上图, 选择[市场B] ...

  2. 开源自己用python封装的一个Windows GUI(UI Automation)自动化工具,支持MFC,Windows Forms,WPF,Metro,Qt

    首先,大家可以看下这个链接 Windows GUI自动化测试技术的比较和展望 . 这篇文章介绍了Windows中GUI自动化的三种技术:Windows API, MSAA - Microsoft Ac ...

  3. HTML页面仿WORD样式

    公司要求不再浏览器中添加office插件的前提下.展示WORD文档中的内容要求一一对应.经过查询资料以及调整,得出如下相关资料: 1  标题样式: 目录 -- 宋体 小二 加粗 一级标题 -- 微软雅 ...

  4. js将HTML中table导出到EXCEL word (只支持IE) 另用php 配合AJAX可以支持所有浏览器

    转载请注明来源:https://www.cnblogs.com/hookjc/ <HTML>     <HEAD>       <title>WEB页面导出为EXC ...

  5. 仿word导航窗口的展开与折叠

    // 标识是否是展开状态 bool isExtend = true; // 定义可以扩展的宽度 const int PanelWidth = 444; private void expandableS ...

  6. wpf控件设计时支持(1)

    原文:wpf控件设计时支持(1) 这部分内容几乎是大家忽略的内容,我想还是来介绍一下. 本篇源码下载 1.属性元数据 在vs IDE中,在asp.net,winfrom等开发环境下,右侧的Proper ...

  7. WPF/.net core WPF 系统托盘支持

    WPF 原生不支持系统托盘图标,需要依靠其它方式处理. 1 使用 WinForm 的支持 WPF最小到系统托盘 - Arvin.Mei - 博客园 2 使用 wpf-notifyicon 库 hard ...

  8. 【.NET6+WPF+Avalonia】开发支持跨平台的WPF应用程序以及基于ubuntu系统的演示

    前言:随着跨平台越来越流行,.net core支持跨平台至今也有好几年的光景了.但是目前基于.net的跨平台,大多数还是在使用B/S架构的跨平台上:至于C/S架构,大部分人可能会选择QT进行开发,或者 ...

  9. 关于WPF你应该知道的2000件事

    原文 关于WPF你应该知道的2000件事 以下列出了迄今为止为WPF博客所知的2,000件事所创建的所有帖子. 帖子总数= 1,201 动画 #7 - 基于属性的动画 #686 - 使用动画制作图像脉 ...

随机推荐

  1. 使用gitlab runner进行CI(三):使用sonarqube做c++的静态检查

    目录 1. gitlab-ci.yml的配置 1.1 几个基本概念 1.2 使用CI进行代码检查demo 2. Sonarqube安装和配置 2.1 Sonarqube安装 2.2 数据库配置 2.3 ...

  2. 透过 Chrome 深入理解浏览器导航过程

    网络的导航,是从输入 url 到最终获取到文件的过程.其中牵扯到浏览器架构.操作系统.网络等一系列知识.本文将从各个角度详细论述这一过程,涉及广度与深度.如果您是已经有一定基础的同学,那么本文可以快速 ...

  3. java 文档自动生成的神器 idoc

    写文档 作为一名开发者,每个人都要写代码. 工作中,几乎每一位开发者都要写文档. 因为工作是人和人的协作,产品要写需求文档,开发要写详细设计文档,接口文档. 可是,作为一个懒人,平时最讨厌的一件事情就 ...

  4. CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)

    QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...

  5. 2020.10.16--vj个人赛补题

    D - Drinks Choosing Old timers of Summer Informatics School can remember previous camps in which eac ...

  6. 1.2 Simple Code!(翻译)

    Simple Code! 简洁编码 Playing football is very simple, but playing simple football is the hardest thing ...

  7. from athletelist import AthleteList出现红色下滑波浪线警告

    问题:from athletelist import AthleteList出现红色下滑波浪线警告 经过个人网上搜索了解,这个问题是因为python找不到相关的.py文件,无法导入athletelis ...

  8. ffmpeg剪视频

    ffmpeg裁剪合并视频   ffmpeg提供简单的命令参数: ffmpeg -ss START -t DURATION -i INPUT -vcodec copy -acodec copy OUTP ...

  9. 正则表达式: NFA引擎匹配原理

    NFA引擎匹配原理 1       为什么要了解引擎匹配原理 一个个音符杂乱无章的组合在一起,弹奏出的或许就是噪音,同样的音符经过作曲家的手,就可以谱出非常动听的乐曲,一个演奏者同样可以照着乐谱奏出动 ...

  10. sip信令跟踪工具sngrep

    概述 在VOIP的使用过程中,最常见的问题就是信令不通和语音质量问题. 通常的问题跟踪手段包括日志分析.抓包分析. 抓包的工具有wireshark.tcpdump等等,如果是只针对sip信令的抓包,则 ...