winform圖片標尺控制項

来源:http://www.cnblogs.com/rocpeng/archive/2017/12/05/7988683.html
-Advertisement-
Play Games

最近要做個winform的東西,要在裡面集成一個類似Windows自帶畫圖的標尺功能,還要能在圖片上畫矩形框。在網上找了好久也沒找到寫好的控制項,無奈自己做了一個。 目前還有些bug,這裡先做個分享。(Ps:很少做winform的東西,做的不好,輕噴。另外歡迎指點。) 由於最後要做的東西的背景是黑的, ...


最近要做個winform的東西,要在裡面集成一個類似Windows自帶畫圖的標尺功能,還要能在圖片上畫矩形框。在網上找了好久也沒找到寫好的控制項,無奈自己做了一個。

目前還有些bug,這裡先做個分享。(Ps:很少做winform的東西,做的不好,輕噴。另外歡迎指點。)

由於最後要做的東西的背景是黑的,標尺就畫成白的了,有需要的自己改吧。。

直接上代碼

 

  1 using Helper;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Drawing;
  5 using System.Windows.Forms;
  6 
  7 namespace UserCtrl
  8 {
  9     public partial class RulerControl : UserControl
 10     {
 11         private double _monitorDPI = 100;
 12         /// <summary>
 13         /// 用於控制放大倍數
 14         /// </summary>
 15         private double _multiple = 1;
 16 
 17         /// <summary>
 18         /// 每多少個像素1格
 19         /// </summary>
 20         public double MonitorDPI
 21         {
 22             get
 23             {
 24                 return _monitorDPI;
 25             }
 26             set
 27             {
 28                 _monitorDPI = value;
 29             }
 30         }    
 31         /// <summary>
 32         /// X軸偏移位置
 33         /// </summary>
 34         private float offSetX=0;
 35 
 36         /// <summary>
 37         /// Y軸偏移位置
 38         /// </summary>
 39         private float offSetY = 0;
 40 
 41         /// <summary>
 42         /// 開始位置X
 43         /// </summary>
 44         public double XStart
 45         {
 46             get;
 47             set;
 48         }
 49 
 50         /// <summary>
 51         /// 開始位置Y
 52         /// </summary>
 53         public double YStart
 54         {
 55             get;
 56             set;
 57         }
 58 
 59         /// <summary>
 60         /// 用戶設置的原始圖
 61         /// </summary>
 62         private Image _initImg = null;
 63 
 64 
 65 
 66         /// <summary>
 67         /// 圖片
 68         /// </summary>
 69         public Image Image
 70         {
 71             get
 72             {
 73                 return Pic.Image;
 74             }
 75             set
 76             {
 77                 Pic.Image = value;
 78                 if (_initImg == null&&value!=null)
 79                 {
 80                     _initImg = PicHelper.GetNewPic(value, value.Width , value.Height );
 81                 }
 82             }
 83         }
 84         private Font font = new Font("宋體", 9); //刻度值顯示字體
 85         public RulerControl()
 86         {
 87             InitializeComponent();
 88         }
 89 
 90         private void Pic_MouseWheel(object sender, MouseEventArgs e)
 91         {
 92             if (MouseButtons == MouseButtons.Left)
 93             {
 94                 return;
 95             }
 96             Image img = Pic.Image;
 97             if (img != null)
 98             {
 99                 if (e.Delta >= 0)
100                 {
101                     if (_multiple * 2 > 4)
102                         return;
103                     _multiple *= 2;
104                 }
105                 else
106                 {
107                     if (Pic.Width < this.Width - 50)
108                         return;
109 
110                     _multiple *= 0.5;
111                     if (Pic.Width <= (this.Width - 50))
112                     {
113                         XStart = 0;
114                         YStart = 0;
115                     }
116                 }
117                 DrawRect();
118                 AdapterDpi();
119                 ReDrawX();
120                 ReDrawY();
121             }
122         }
123 
124         private void RulerControl_Paint(object sender, PaintEventArgs e)
125         {
126             P1.Height = 50;
127             P1.Width = this.Width - 50;
128             P2.Height = this.Height - 50;
129             P2.Width = 50;
130             P1.Location = new Point(50, 0);
131             P2.Location = new Point(0, 50);
132             PContainer.Location = new Point(50, 50);
133         }
134 
135         private void RulerControl_Resize(object sender, EventArgs e)
136         {
137             P1.Height = 50;
138             P1.Width = this.Width - 50;
139             P2.Height = this.Height - 50;
140             P2.Width = 50;
141             P1.Location = new Point(50, 0);
142             P2.Location = new Point(0, 50);
143             PContainer.Location = new Point(50, 50);
144         }
145 
146         /// <summary>
147         /// 重畫Y軸
148         /// </summary>
149         private void ReDrawY()
150         {
151             if (P2.BackgroundImage != null)
152             {
153                 P2.BackgroundImage.Dispose();
154             }
155             Bitmap bmpY = new Bitmap(P2.Width, P2.Height);
156             using (Graphics g = Graphics.FromImage(bmpY))
157             {
158                 int originLocation = bmpY.Width - 1;
159                 int startY = (int)Math.Ceiling(YStart);
160                 offSetY = (float)(MonitorDPI * _multiple * (startY - YStart));
161                 for (int i = startY; i <= Math.Ceiling(P2.Height / (MonitorDPI * _multiple) + YStart); i++)
162                 {
163                     float y = (float)(MonitorDPI * _multiple * (i - YStart)) + offSetY;
164                     if (y >= 0)
165                     {
166                         PointF start = new PointF(originLocation, y);
167                         PointF end = new PointF(originLocation - 3, y);
168                         if (i % 5 == 0)
169                         {
170                             end = new PointF(originLocation - 6, y);
171                         }
172                         if (i % 10 == 0 && i != 0)
173                         {
174                             end = new PointF(originLocation - 12, y);
175                             g.DrawString((i*MonitorDPI).ToString(), font, Brushes.White, new PointF(originLocation - 30, y - 5));
176                         }
177                         g.DrawLine(Pens.White, start, end);
178                     }
179                 }
180                 g.DrawLine(Pens.White, new PointF(originLocation, 0), new PointF(originLocation, bmpY.Height));
181                 P2.BackgroundImage = bmpY;
182             }
183         }
184 
185         /// <summary>
186         /// 重畫X軸
187         /// </summary>
188         private void ReDrawX()
189         {
190             if (P1.BackgroundImage != null)
191             {
192                 P1.BackgroundImage.Dispose();
193             }
194             Bitmap bmpX = new Bitmap(P1.Width, P1.Height);
195             using (Graphics g = Graphics.FromImage(bmpX))
196             {
197                 int originLocation = bmpX.Height - 1;
198                 int startX = (int)Math.Ceiling(XStart);
199                 offSetX = (float)(MonitorDPI * _multiple * (startX - XStart));
200                 for (int i = startX; i <= Math.Ceiling(P1.Width / (MonitorDPI * _multiple) + XStart); i++)
201                 {
202                     float x = (float)(MonitorDPI * _multiple * (i - XStart)) + offSetX;
203                     if (x >= 0)
204                     {
205                         PointF start = new PointF(x, originLocation);
206                         PointF end = new PointF(x, originLocation - 3);
207                         if (i % 5 == 0)
208                         {
209                             end = new PointF(x, originLocation - 6);
210                         }
211                         if (i % 10 == 0 && i != 0)
212                         {
213                             end = new PointF(x, originLocation - 12);
214                             g.DrawString((i*MonitorDPI).ToString(), font, Brushes.White, new PointF(x - 5, originLocation - 30));
215                         }
216                         g.DrawLine(Pens.White, start, end);
217                     }
218                 }
219                 g.DrawLine(Pens.White, new PointF(0, originLocation), new PointF(bmpX.Width, originLocation));
220                 P1.BackgroundImage = bmpX;
221             }
222         }
223 
224         private void RulerControl_Load(object sender, EventArgs e)
225         {
226             P1.Height = 50;
227             P1.Width = this.Width - 50;
228             P2.Height = this.Height - 50;
229             P2.Width = 50;
230             P1.Location = new Point(50, 0);
231             P2.Location = new Point(0, 50);
232             PContainer.Location = new Point(50, 50);
233             ReDrawX();
234             ReDrawY();
235             Pic.MouseWheel += new MouseEventHandler(Pic_MouseWheel);
236         }
237 
238         private void Pic_MouseEnter(object sender, EventArgs e)
239         {
240             Pic.Focus();
241         }
242 
243         private void PContainer_Scroll(object sender, ScrollEventArgs e)
244         {
245             if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
246             {
247                 XStart = e.NewValue / (MonitorDPI * _multiple);
248                 ReDrawX();
249             }
250             else if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
251             {
252                 YStart = e.NewValue / (MonitorDPI * _multiple);
253                 ReDrawY();
254             }
255         }
256 
257 
258         #region 畫圖片選定區域
259         bool MouseIsDown = false;
260         Rectangle MouseRect = Rectangle.Empty;
261 
262         private void Pic_MouseDown(object sender, MouseEventArgs e)
263         {
264             MouseIsDown = true;
265             MouseRect = new Rectangle(e.X, e.Y, 0, 0);
266             Rectangle rec = new Rectangle(0, 0,
267                 Math.Min(PContainer.ClientRectangle.Width, Pic.ClientRectangle.Width),
268                 Math.Min(PContainer.ClientRectangle.Height, Pic.ClientRectangle.Height));
269             Cursor.Clip = PContainer.RectangleToScreen(rec);
270         }
271 
272         private void Pic_MouseMove(object sender, MouseEventArgs e)
273         {
274             if (MouseIsDown)
275             {
276                 MouseRect.Width = e.X - MouseRect.Left;
277                 MouseRect.Height = e.Y - MouseRect.Top;
278                 if (MouseRect.Width > 0 && MouseRect.Height > 0)
279                 {
280                     Rectangle rect = Pic.RectangleToScreen(MouseRect);
281                     ControlPaint.DrawReversibleFrame(rect, Color.White, FrameStyle.Dashed);
282                 }
283                 Pic.Refresh();
284             }
285 
286         }
287 
288         private void Pic_MouseUp(object sender, MouseEventArgs e)
289         {
290             if (MouseIsDown)
291             {
292                 MouseRect.Width = e.X - MouseRect.Left;
293                 MouseRect.Height = e.Y - MouseRect.Top;
294                 using (Graphics g = Graphics.FromImage(Pic.Image))
295                 {
296                     g.DrawRectangle(new Pen(Color.Red), MouseRect);
297                 }
298                 Pic.Refresh();
299                 MouseIsDown = false;
300                 if ((int)(MouseRect.Width * _multiple) > 0 && (int)(MouseRect.Height * _multiple) > 0)
301                 {
302                     list.Add(new Rectangle((int)(MouseRect.X / _multiple),
303                         (int)(MouseRect.Y / _multiple),
304                         (int)(MouseRect.Width / _multiple),
305                         (int)(MouseRect.Height / _multiple)
306                         ));
307                 }
308                 MouseRect = Rectangle.Empty;
309                 Cursor.Clip = Rectangle.Empty;
310             }
311         }
312         #endregion
313         public List<Rectangle> list = new List<Rectangle>();
314 
315         private void Pic_DoubleClick(object sender, EventArgs e)
316         {
317             MouseEventArgs ev = e as MouseEventArgs;
318             List<Rectangle> temp = new List<Rectangle>();
319             foreach (Rectangle item in list)
320             {
321                 if (ev.X > item.X * _multiple && ev.X < item.X * _multiple + item.Width * _multiple &&
322                     ev.Y > item.Y * _multiple && ev.Y < item.Y * _multiple + item.Height * _multiple)
323                 {
324                     temp.Add(item);
325                 }
326             }
327             foreach (Rectangle item in temp)
328             {
329                 list.Remove(item);
330             }
331             
332             DrawRect();
333         }
334 
335         /// <summary>
336         /// 把list中的框畫到圖片中
337         /// </summary>
338         private void DrawRect()
339         {
340             if (Pic.Image != _initImg)
341                 Pic.Image.Dispose();
342             Pic.Image = PicHelper.GetNewPic(_initImg, (int)(_initImg.Width * _multiple), (int)(_initImg.Height * _multiple));
343             using (Graphics g = Graphics.FromImage(Image))
344             {
345                 foreach (Rectangle item in list)
346                 {
347                     g.DrawRectangle(new Pen(Color.Red), new Rectangle((int)(item.X * _multiple),
348                         (int)(item.Y * _multiple),
349                         (int)(item.Width * _multiple),
350                         (int)(item.Height * _multiple)
351                         ));
352                 }
353             }
354             Pic.Refresh();
355         }
356 
357         private void AdapterDpi()
358         {
359             if (MonitorDPI * _multiple < 10)
360             {
361                 MonitorDPI *= 2;
362             }
363             if (MonitorDPI * _multiple > 20)
364             {
365                 MonitorDPI /= 2;
366             }
367         }
368 
369 
370         
371     }
372 }

下載鏈接:http://download.csdn.net/download/p690075426/10142184


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定義: 將一個類的介面轉換成客戶希望的另外一個介面。適配器模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。 角色: 目標(Target)角色:這就是所期待得到的介面,也就是這類的介面是符合我們要求的。 源(Adapee)角色:我們要使用的介面,但是這個介面不符合我們的要求,也就是現在需 ...
  • 參考Spring Cloud官方文檔第13、14、15章 13. Circuit Breaker: Hystrix Clients Netflix提供了一個叫Hystrix的類庫,它實現了斷路器模式。在微服務架構中,通常一個微服務會調用多個其他的微服務。一個相對低層級的服務失敗可能造成上層應用的級聯 ...
  • 2017年11月底開始python的學習。選擇python 3.6。 賬號登陸的粗糙實現。 ...
  • 功能 1.天氣預報 2.區域網對戰 展示 java學習群669823128 部分源碼 package game.weather; import java.util.HashMap; public class Weather { /** * @Fields 今天的天氣數據,整體 */ private ...
  • 在大多數大公司,像應用伺服器軟體的安裝、部署都是運維的事情,其實自己去嘗試部署一下,也是有收穫的。 周末在家無聊,正好嘗試了Linux下的rabbitMq安裝過程,做了記錄,希望有用到的人可以做下參考。 安裝環境: Linux: centOS 7.0 mini版 rabbitMq: 3.6.2 查詢 ...
  • 上一篇《Git命令彙總基礎篇》總結了使用Git的基本命令,這一篇作為補充主要給大家講一些平時使用中的技巧和總結 。 學會了這些命令,已經基本解決了使用Git中大部分問題。 1.gitignore 全局配置忽略文件 git config --global core.excludesfile ~/.gi ...
  • 題目描述 永無鄉包含 n 座島,編號從 1 到 n,每座島都有自己的獨一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋連接,通過橋可以從一個島 到達另一個島。如果從島 a 出發經過若幹座(含 0 座)橋可以到達島 b,則稱島 a 和島 b 是連 通 ...
  • S#語言的最全能類型——字元串(對應C#的String),可用於表示文本內容,如"S#公式是很有特色"等。S#的字元串輸入格式有三種:"xxxxx",@"xxxxx"和'xxxxx'。在S#語言設計時字元串的地位是很高的,系統把它也看成是“程式即數據、數據即程式”的全能表達方式之一。 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...